-
Notifications
You must be signed in to change notification settings - Fork 0
API
The API differs between versions. Differences are marked below.
The public API lives in com.skd.vellumli.api. It is designed to be dependency-free: if Vellumli is not installed, VellumliAPI.get() still returns a no-op stub, so code that calls it will not crash. Many methods only make sense on the physical client; those assert that they are called client-side.
Between 1.21.1 and 26.2, Minecraft renamed some types: ResourceLocation became Identifier, and GuiGraphics became GuiGraphicsExtractor. Where a signature is affected, both versions are shown.
Identical in both versions.
import com.skd.vellumli.api.VellumliAPI;
VellumliAPI.IVellumliAPI api = VellumliAPI.get();
api.isStub(); // true when Vellumli is absentVellumliAPI.MOD_ID is "vellumli" and VellumliAPI.LOGGER is the mod logger.
| 1.21.1 | 26.2 | Side | Description |
|---|---|---|---|
openBookGUI(ServerPlayer player, ResourceLocation book) |
openBookGUI(ServerPlayer player, Identifier book) |
both | Ask a player's client to open a book on its last page. |
openBookEntry(ServerPlayer player, ResourceLocation book, ResourceLocation entry, int page) |
openBookEntry(ServerPlayer player, Identifier book, Identifier entry, int page) |
both | Ask a player's client to open a specific entry at a zero-indexed page. |
openBookGUI(ResourceLocation book) |
openBookGUI(Identifier book) |
client | Open a book locally. |
openBookEntry(ResourceLocation book, ResourceLocation entry, int page) |
openBookEntry(Identifier book, Identifier entry, int page) |
client | Open an entry locally. |
ResourceLocation getOpenBookGui() |
Identifier getOpenBookGui() |
client | The book id of the currently open book, or null. |
Component getSubtitle(ResourceLocation bookId) |
Component getSubtitle(Identifier bookId) |
both | The edition string shown under the book title. |
ItemStack getBookStack(ResourceLocation book) |
ItemStack getBookStack(Identifier book) |
both | An ItemStack of the guide book pointing at the given book. |
| — | Holder<Item> getBookItem() |
both | The guide book item as a registry holder. 26.2 only. |
| — | TypedDataComponent<Identifier> makeBookDataComponent(Identifier book) |
both | A data component pointing at the given book. 26.2 only. |
| — | @Nullable ItemStackTemplate getBookStackTemplate(Identifier book) |
both | A book item stack template with its data component set to the given book. 26.2 only. |
getBookItem, makeBookDataComponent and getBookStackTemplate do not exist on 1.21.1.
Identical in both versions.
Config flags are boolean values used by the flag field on categories, entries, pages and components.
api.setConfigFlag("mymod:hardmode", true);
boolean hardmode = api.getConfigFlag("mymod:hardmode");Set flags once during mod setup. See Configuration for the flags Vellumli sets itself.
registerCommand and registerFunction are identical in both versions:
// $(mymod:version) -> a fixed string
api.registerCommand("mymod:version", styleStack -> "1.2.3");
// $(mymod:config:key) -> looks up a config value
api.registerFunction("mymod:config", (arg, styleStack) -> myConfig.get(arg));registerTemplateAsBuiltin takes a ResourceLocation on 1.21.1 and an Identifier on 26.2:
1.21.1
// Register a template as an "addon" template available to all books.
api.registerTemplateAsBuiltin(
ResourceLocation.fromNamespaceAndPath("mymod", "card"),
() -> MyMod.class.getResourceAsStream("/assets/mymod/card.json"));26.2
// Register a template as an "addon" template available to all books.
api.registerTemplateAsBuiltin(
Identifier.fromNamespaceAndPath("mymod", "card"),
() -> MyMod.class.getResourceAsStream("/assets/mymod/card.json"));-
registerCommand(String name, Function<IStyleStack, String>)replaces$(name). -
registerFunction(String name, BiFunction<String, IStyleStack, String>)replaces$(name:argument). -
registerTemplateAsBuiltin(ResourceLocation res, Supplier<InputStream>)(1.21.1) /registerTemplateAsBuiltin(Identifier res, Supplier<InputStream>)(26.2) makes a template available to every book underres.
Both command registration methods are client-side and thread safe. The returned string replaces the command; return "" for commands that only modify style.
Identical in both versions.
Implement this on a plain class with a no-arg constructor and name it in a template's processor field. One instance is created per usage of the template.
package com.example.mymod;
import com.skd.vellumli.api.IComponentProcessor;
import com.skd.vellumli.api.IVariable;
import com.skd.vellumli.api.IVariableProvider;
import net.minecraft.world.level.Level;
public class MyProcessor implements IComponentProcessor {
private IVariableProvider variables;
@Override
public void setup(Level level, IVariableProvider variables) {
this.variables = variables;
}
@Override
public IVariable process(Level level, String key) {
if (key.equals("greeting")) {
return IVariable.wrap("Hello from Java!", level.registryAccess());
}
return null; // let the default lookup handle it
}
// Hide an entire group when it should not be shown.
@Override
public boolean allowRender(String group) {
return !group.equals("debug");
}
}setup receives the template's variables (including using bindings). process is called for #keys used in components. allowRender(group) is called for components with a non-empty group. refresh(parent, left, top) is called when the page is shown.
Implement this for a fully custom component and reference it with a vellumli:custom component's class field. Fields are normally deserialized from the component JSON, so mark non-JSON fields transient.
The render method differs: 1.21.1 has render(GuiGraphics, ...), 26.2 has extractRenderState(GuiGraphicsExtractor, ...).
1.21.1
package com.example.mymod;
import com.skd.vellumli.api.ICustomComponent;
import com.skd.vellumli.api.IComponentRenderContext;
import com.skd.vellumli.api.IVariable;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.core.HolderLookup;
import java.util.function.UnaryOperator;
public class MyWidget implements ICustomComponent {
public IVariable label;
@Override
public void onVariablesAvailable(UnaryOperator<IVariable> lookup, HolderLookup.Provider registries) {
label = lookup.apply(label);
}
@Override
public void build(int componentX, int componentY, int pageNum) {
// Called after variables are resolved.
}
@Override
public void render(GuiGraphics graphics, IComponentRenderContext context, float pticks, int mouseX, int mouseY) {
// Draw in book-page coordinates.
}
}26.2
package com.example.mymod;
import com.skd.vellumli.api.ICustomComponent;
import com.skd.vellumli.api.IComponentRenderContext;
import com.skd.vellumli.api.IVariable;
import net.minecraft.client.gui.GuiGraphicsExtractor;
import net.minecraft.core.HolderLookup;
import java.util.function.UnaryOperator;
public class MyWidget implements ICustomComponent {
public IVariable label;
@Override
public void onVariablesAvailable(UnaryOperator<IVariable> lookup, HolderLookup.Provider registries) {
label = lookup.apply(label);
}
@Override
public void build(int componentX, int componentY, int pageNum) {
// Called after variables are resolved.
}
@Override
public void extractRenderState(GuiGraphicsExtractor graphics, IComponentRenderContext context, float pticks, int mouseX, int mouseY) {
// Draw in book-page coordinates.
}
}| 1.21.1 | 26.2 | Description |
|---|---|---|
void render(GuiGraphics graphics, IComponentRenderContext context, float pticks, int mouseX, int mouseY) |
void extractRenderState(GuiGraphicsExtractor graphics, IComponentRenderContext context, float pticks, int mouseX, int mouseY) |
Called every render tick. |
default boolean mouseClicked(IComponentRenderContext context, double mouseX, double mouseY, int mouseButton) |
default boolean mouseClicked(IComponentRenderContext context, MouseButtonEvent event, boolean doubleClick) |
Called on mouse click. |
void build(int componentX, int componentY, int pageNum) |
identical | Called after variables are resolved. |
default void onDisplayed(IComponentRenderContext context) |
identical | Called when the component enters the screen. |
onDisplayed(context) is called when the component enters the screen. The click handler signature changes in 26.2 to receive a MouseButtonEvent and a double-click flag.
A context for a custom component's methods. Members whose signature differs:
| 1.21.1 | 26.2 | Description |
|---|---|---|
Style getFont() |
Style getFontStyle() |
The book font style. |
void renderItemStack(GuiGraphics graphics, int x, int y, int mouseX, int mouseY, ItemStack stack) |
void renderItemStack(GuiGraphicsExtractor graphics, int x, int y, int mouseX, int mouseY, ItemStack stack) |
Draw an item stack. |
void renderIngredient(GuiGraphics graphics, int x, int y, int mouseX, int mouseY, Ingredient ingredient) |
void renderIngredient(GuiGraphicsExtractor graphics, int x, int y, int mouseX, int mouseY, Ingredient ingredient) |
Draw an ingredient. |
boolean navigateToEntry(ResourceLocation entry, int page, boolean push) |
boolean navigateToEntry(Identifier entry, int page, boolean push) |
Navigate to another entry. |
ResourceLocation getBookTexture() |
Identifier getBookTexture() |
The book background texture. |
ResourceLocation getCraftingTexture() |
Identifier getCraftingTexture() |
The crafting texture. |
getGui(), isAreaHovered(...), setHoverTooltip(...), setHoverTooltipComponents(...), registerButton(...), addWidget(...), getTextColor(), getHeaderColor() and getTicksInBook() are identical in both versions.
Identical in both versions.
IVariable is a JSON-backed value with converters:
IVariable v = IVariable.wrap("hello", level.registryAccess());
String s = v.asString();
ItemStack stack = v.as(ItemStack.class);Register custom serializers with VariableHelper:
VariableHelper.instance().registerSerializer(new MySerializer(), MyType.class);An IVariableSerializer<T> converts between T and JsonElement. Implement IVariablesAvailableCallback to receive a lookup function that resolves variable strings (inline #vars, ->derivations and plain values) before your component is built.
Both events extend NeoForge's Event and are posted on NeoForge.EVENT_BUS.
| 1.21.1 | 26.2 |
|---|---|
BookContentsReloadEvent.getBook() returns ResourceLocation
|
BookContentsReloadEvent.getBook() returns Identifier
|
BookDrawScreenEvent.getBook() returns ResourceLocation
|
BookDrawScreenEvent.getBook() returns Identifier
|
BookDrawScreenEvent.getGraphics() returns GuiGraphics
|
BookDrawScreenEvent.getGraphics() returns GuiGraphicsExtractor
|
BookDrawScreenEvent.getScreen(), getMouseX(), getMouseY(), getPartialTicks()
|
identical |
import net.neoforged.neoforge.common.NeoForge;
import com.skd.vellumli.api.BookContentsReloadEvent;
import com.skd.vellumli.api.BookDrawScreenEvent;
NeoForge.EVENT_BUS.addListener((BookContentsReloadEvent e) -> {
// a book's contents were (re)built; e.getBook() is the book id
});
NeoForge.EVENT_BUS.addListener((BookDrawScreenEvent e) -> {
// a book GUI finished drawing, with the book GUI transform applied:
// e.getBook(), e.getScreen(), e.getMouseX(), e.getMouseY(),
// e.getPartialTicks(), e.getGraphics()
});The multiblock API methods are present for source compatibility but are stubs in this build: getMultiblock, registerMultiblock, getCurrentMultiblock, showMultiblock, clearMultiblock, makeMultiblock, makeSparseMultiblock and the various matcher factories currently return null or do nothing. The in-world multiblock preview system and the vellumli:multiblock page type are not ported.
Only the id type differs:
| 1.21.1 | 26.2 |
|---|---|
IMultiblock getMultiblock(ResourceLocation id) |
IMultiblock getMultiblock(Identifier id) |
IMultiblock registerMultiblock(ResourceLocation id, IMultiblock mb) |
IMultiblock registerMultiblock(Identifier id, IMultiblock mb) |
IMultiblock setId(ResourceLocation res) |
IMultiblock setId(Identifier res) |
ResourceLocation IMultiblock.getID() |
Identifier IMultiblock.getID() |
The matcher factory methods (predicateMatcher, stateMatcher, propertyMatcher, looseBlockMatcher, strictBlockMatcher, displayOnlyMatcher, tagMatcher, airMatcher, anyMatcher) have identical signatures in both versions.
Vellumli is a fork of Patchouli by Vazkii and williewillus. This documentation is licensed under CC BY-NC-SA 3.0. Not affiliated with or endorsed by the Patchouli authors.