-
Notifications
You must be signed in to change notification settings - Fork 4
Initialization
Create custom cursor types and register your elements using the MinecraftCursorInitializer interface.
Create your API Implementation class and implement MinecraftCursorInitializer which is initialized in the client environment.
public class MinecraftCursorApiImpl implements MinecraftCursorInitializer {
@Override
public void init(CursorTypeFactory cursorTypeFactory, CursorTypeRegistrar cursorTypeRegistrar) {
}
}Add the entrypoint in minecraft-cursor
fabric.mod.json:
"entrypoints": {
"minecraft-cursor": ["com.example.modid.MinecraftCursorApiImpl"]
}MinecraftCursorInitializer#init() will be invoked on Minecraft Cursor client initialization.
Follow the Resource Pack Support section in README.md for more info on the asset creation of your custom cursor.
Once you have prepared the custom cursor's assets, use CursorTypeFactory#of(key) to initialize the custom cursor type.
Note: You should only initialize your custom cursor type within
MinecraftCursorInitializer#init(cursorTypeFactory, cursorTypeRegistrar)to ensure that your custom cursor type will be loaded on the initial resource load of Minecraft.
public class MinecraftCursorApiImpl implements MinecraftCursorInitializer {
@Override
public void init(CursorTypeFactory cursorTypeFactory, CursorTypeRegistrar cursorTypeRegistrar) {
CursorType customCursorType = cursorTypeFactory.of("custom-cursor");
}
}The key serves as the cursor type's identifier.
- This should be the filename of the cursor type.
assets/ └── minecraft-cursor/ └── textures/ └── cursors/ └── <key>.png - This is the key for custom settings in
cursors.json.{ "settings": { "<key>": { "xhot": 3, "yhot": 6 } } } - Add the translation entry for your cursor type:
{ "minecraft-cursor.options.cursor-type.<key>": "Custom" }
Once you have initialized your cursor types, you can register your elements with a cursor type function which determines the cursor type to be applied when the mouse is over the registered element.
Note: The element must be an instance of
net.minecraft.gui.Element. It must either be the current screen itself or be accessible from the current screen or from its parent element using theParentElement#children()method.Any container or nested container must be an instance of
net.minecraft.gui.ParentElementand accessible via theParentElement#children()method. This accessibility must be maintained through the entire element hierarchy, starting from the current screen down to the deepest nested parent element.
For most cases, registering elements directly using their class is the simplest approach.
public class MinecraftCursorApiImpl implements MinecraftCursorInitializer {
@Override
public void init(CursorTypeFactory cursorTypeFactory, CursorTypeRegistrar cursorTypeRegistrar) {
CursorType customCursorType = cursorTypeFactory.of("custom-cursor");
// Register MyButton with the built-in pointer cursor type
cursorTypeRegistrar.register(MyButton.class, (myButton, mouseX, mouseY) -> CursorType.POINTER);
// You can use the built-in static methods of CursorTypeRegistrar when no additional logic is needed
cursorTypeRegistrar.register(MyOtherButton.class, CursorTypeRegistrar::elementToPointer);
// Register MyCustomElement with the custom cursor type
cursorTypeRegistrar.register(MyCustomElement.class, (myCustomElement, mouseX, mouseY) -> customCursorType);
}
}If you cannot access a class directly, you can register it using its fully qualified class name (FQCN)
Note: Use the intermediary mappings when registering a native Minecraft
Element.
public class MinecraftCursorApiImpl implements MinecraftCursorInitializer {
@Override
public void init(CursorTypeFactory cursorTypeFactory, CursorTypeRegistrar cursorTypeRegistrar) {
// ...
// Register PressableWidget with the built-in pointer cursor type using its fully qualified class name
cursorTypeRegistrar.register("net.minecraft.class_4264", (pressableWidget, mouseX, mouseY) -> CursorType.POINTER);
}
}Mostly used for when the cursor type computing logic gets too large or complex, or you simply want to it to be in a separate class file.
public class MinecraftCursorApiImpl implements MinecraftCursorInitializer {
@Override
public void init(CursorTypeFactory cursorTypeFactory, CursorTypeRegistrar cursorTypeRegistrar) {
// ...
cursorTypeRegistrar.register(new CursorHandler<MyButton>() {
@Override
public CursorType getCursorType(MyButton myButton, double mouseX, double mouseY) {
return CursorType.POINTER;
}
});
}
}MyElementCursorHandler:
public class MyElementCursorHandler implements CursorHandler<MyElement> {
@Override
public CursorType getCursorType(MyElement myElement, double mouseX, double mouseY) {
return CursorType.POINTER;
}
}MinecraftCursorApiImpl:
public class MinecraftCursorApiImpl implements MinecraftCursorInitializer {
@Override
public void init(CursorTypeFactory cursorTypeFactory, CursorTypeRegistrar cursorTypeRegistrar) {
// ...
cursorTypeRegistrar.register(new MyElementCursorHandler());
}
}When the target element is inaccessible, you can simply pass the Element generic type and override the CursorHandler#getTargetElement() method to return the FQCN of the target element.
Note: Use the intermediary mappings when registering a native Minecraft
Element.
MerchantScreenButtonCursorHandler:
public class MerchantScreenButtonCursorHandler implements CursorHandler<Element> {
@Override
public @NotNull TargetElement<Element> getTargetElement() {
return TargetElement.fromClassName("net.minecraft.class_492$class_493");
}
@Override
public CursorType getCursorType(Element element, double mouseX, double mouseY) {
return CursorTypeUtil.canShift() ? CursorType.SHIFT : CursorType.POINTER;
}
}MinecraftCursorApiImpl:
public class MinecraftCursorApiImpl implements MinecraftCursorInitializer {
@Override
public void init(CursorTypeFactory cursorTypeFactory, CursorTypeRegistrar cursorTypeRegistrar) {
// ...
cursorTypeRegistrar.register(new MerchantScreenButtonCursorHandler());
}
}