Modopedia allows you to register your own Page Components for books. I'll be using the Text Box as an example of how to implement one.
Step 1.) Create a PageComponent class
First, create a new class extending net.favouriteless.modopedia.api.book.page_components.PageComponent
, the JavaDocs in the class will explain how to use each method. I recommend storing the ID of the page component in a constant in this class to make it easier to find.
public class TextPageComponent extends PageComponent {public static final ResourceLocation ID = Modopedia.id("text");}
Step 2.) Grab your variables from the lookup
Next, override init
and use it to grab any values you need from the Lookup
provided to you. You need to cache every value you need here as the lookup is discarded after initialisation. Make sure to call super.init
if you want the position and page number to load correctly.
Mandatory fields should use Lookup#get
while optional fields should use Lookup#getOrDefault
and/or Lookup#has
. The keys used here are will be the names of the fields in your component's JSON objects. If any exceptions are thrown, the component will get replaced with an error component on the page, so the user can see what happened. It is recommended to throw a descriptive exception to make this clearer for the user.
Heads up!
Trying to use Lookup#get
to grab a value which doesn't exist will throw a NullPointerException. This is intended!
private List<TextChunk> textChunks;private int width;private int lineHeight;@Overridepublic void init(Book book, Lookup lookup, Level level) {super.init(book, lookup, level);Justify justify = lookup.getOrDefault("justify", Justify.LEFT).as(Justify.class);Style baseStyle = Style.EMPTY.withFont(book.getFont()).withColor(book.getTextColour());width = lookup.getOrDefault("width", book.getLineWidth()).asInt();lineHeight = lookup.getOrDefault("line_height", Minecraft.getInstance().font.lineHeight).asInt();textChunks = TextParser.parse(lookup.get("text").asString(), baseStyle, width, lineHeight, language, justify);}
Step 3.) Rendering and click handling
The final step of creating your PageComponent class is to (if your component needs it) implement render
and/or input handling. The PoseStack
in render is already transformed to the position of the PageComponent and any mouse positions provided are relative to the page.
@Overridepublic void render(GuiGraphics graphics, BookRenderContext context, int mouseX, int mouseY, float partialTicks) {for(TextChunk word : textChunks) {word.render(graphics, x, y, mouseX - x, mouseY - y);}}@Overridepublic boolean mouseClicked(BookRenderContext context, double mouseX, double mouseY, int button) {for(TextChunk chunk : textChunks) {if(chunk.mouseClicked(context, mouseX - x, mouseY - y, button))return true;}return false;}
Step 4.) Registering your PageComponent
The last thing you need to do for Modopedia to load your new PageComponent is add it to PageComponentRegistry
. You can do this by calling PageComponentRegistry#register
in your mod's Client Entrypoint. The ID you use to register your processor will be what pages use to reference it in their field.
PageComponentRegistry.get().register(TextPageComponent.ID, TextPageComponent::new);