-
Notifications
You must be signed in to change notification settings - Fork 4
Initialization
Important
The Minecraft Cursor Wiki has moved to:
https://fishstiz.github.io/minecraft-cursor-wiki/.
This page will no longer be updated.
Register cursor types and elements using the MinecraftCursorInitializer interface.
Note: Minecraft Cursor does not have to be a required dependency for
MinecraftCursorInitializer. The class will only be loaded when it needs to.
Create your initializer class and implement MinecraftCursorInitializer. This is the entrypoint for Minecraft Cursor.
public class MyMinecraftCursorInitializer implements MinecraftCursorInitializer {
@Override
public void init(CursorTypeRegistrar cursorRegistrar, ElementRegistrar elementRegistrar) {
// The CursorTypeRegistrar and ElementRegistrar instances are injected here for registration.
// This method is invoked on client initialization of Minecraft Cursor.
}
}Fabric:
Add the initializer in fabric.mod.json with the minecraft-cursor key.
"entrypoints": {
"minecraft-cursor": ["com.example.modid.MyMinecraftCursorInitializer"]
}Neoforge & Forge: Create a services directory under META-INF, then create a file named with the fully qualified class name of the initializer:
resources/
└── META-INF/
└── services/
└── io.github.fishstiz.minecraftcursor.api.MinecraftCursorInitializer
Place the fully qualified class name of your MinecraftCursorInitializer implementation inside the file.
io.github.fishstiz.minecraftcursor.api.MinecraftCursorInitializer:
com.example.modid.MyMinecraftCursorInitializer
After creating your cursor types, you must register them here using CursorTypeRegistrar#register(CursorType...) so the assets can be retrieved on resource reloads.
Note: You should only register your custom cursor type within
MinecraftCursorInitializer#init(CursorTypeRegistrar, ElementRegistrar)to ensure that your custom cursor type's assets will be loaded on the initial resource load of Minecraft.
public class MyMinecraftCursorInitializer implements MinecraftCursorInitializer {
static final CursorType STATIC_CURSOR_TYPE = CursorType.of("static-cursor-type");
@Override
public void init(CursorTypeRegistrar cursorRegistrar, ElementRegistrar elementRegistrar) {
// Register STATIC_CURSOR_TYPE
cursorRegistrar.register(STATIC_CURSOR_TYPE)
// Creating a CursorType inline
CursorType customCursor = CursorType.of("custom-cursor");
// Register customCursor
cursorRegistrar.register(customCursor);
// Create and register a cursor type inline at the same time
CursorType myCursor = cursorRegistrar.register("my-cursor");
// Registering multiple cursor types
cursorRegistrar.register(STATIC_CURSOR_TYPE, customCursor, myCursor);
// Registering cursor types from a CursorType enum
cursorRegistrar.register(CustomCursorEnum.values());
}
// Example implementation of CursorType on an enum
enum CustomCursorEnum implements CursorType {
CROSSHAIR,
NOT_ALLOWED;
@Override
public String getKey() {
return this.name().toLowerCase();
}
}
}Using ElementRegistrar#register(Element, CursorTypeFunction), register elements with a function that determines the cursor type to be applied when the the mouse is on it, meaning Element#isMouseOver(mouseX, mouseY) returns true.
Note: The element must be an instance of
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
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 Mojang Mappings:
Element=GuiEventListener, andParentElement=ContainerEventListener
public class MyMinecraftCursorInitializer implements MinecraftCursorInitializer {
@Override
public void init(CursorTypeRegistrar cursorRegistrar, ElementRegistrar elementRegistrar) {
// Register MyButton with the built-in pointer cursor type
elementRegistrar.register(MyButton.class, (myButton, mouseX, mouseY) -> CursorType.POINTER);
// You can use the built-in static methods of ElementRegistrar when no additional logic is needed
elementRegistrar.register(MyOtherButton.class, ElementRegistrar::elementToPointer);
// Register MyCustomElement with a custom cursor type
CursorType customCursor = cursorRegistrar.register("custom-cursor");
elementRegistrar.register(MyCustomElement.class, (myCustomElement, mouseX, mouseY) -> customCursor);
}
}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
Elementin Fabric.
public class MyMinecraftCursorInitializer implements MinecraftCursorInitializer {
@Override
public void init(CursorTypeRegistrar cursorRegistrar, ElementRegistrar elementRegistrar) {
// Register PressableWidget using its fully qualified class name in Fabric with the built-in pointer cursor type
elementRegistrar.register("net.minecraft.class_4264", (pressableWidget, mouseX, mouseY) -> CursorType.POINTER);
}
}CursorHandler is an interface used 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 MyMinecraftCursorInitializer implements MinecraftCursorInitializer {
@Override
public void init(CursorTypeRegistrar cursorRegistrar, ElementRegistrar elementRegistrar) {
// inline CursorHandler
elementRegistrar.register(new CursorHandler<MyButton>() {
@Override
public CursorType getCursorType(MyButton myButton, double mouseX, double mouseY) {
return CursorType.POINTER;
}
});
}
}Implement CursorHandler to a class for more complex computations, better readability, and clearer separation of concerns.
// The type passed will be the element to be registered. In this case, it is MyElement.
public class MyElementCursorHandler implements CursorHandler<MyElement> {
@Override
public CursorType getCursorType(MyElement myElement, double mouseX, double mouseY) {
// This is the cursor type function to be associated with MyElement, invoked when MyElement.isMouseOver returns true
return CursorType.POINTER;
}
}// Register the CursorHandler
public class MyMinecraftCursorInitializer implements MinecraftCursorInitializer {
@Override
public void init(CursorTypeRegistrar cursorRegistrar, ElementRegistrar elementRegistrar) {
elementRegistrar.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
Elementin Fabric.
// Pass the Element superclass as placeholder
public class MerchantScreenButtonCursorHandler implements CursorHandler<Element> {
@Override
public @NotNull TargetElement<Element> getTargetElement() { // Override this method to change the target element
// return a TargetElement with the fully qualified class name
// Use intermediary mappings for Minecraft elements when using Fabric
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;
}
}// Register the CursorHandler as usual
public class MyMinecraftCursorInitializer implements MinecraftCursorInitializer {
@Override
public void init(CursorTypeRegistrar cursorRegistrar, ElementRegistrar elementRegistrar) {
cursorTypeRegistrar.register(new MerchantScreenButtonCursorHandler());
}
}HandledScreen elements must be handled differently so that the HandledScreen built-in cursor handler does not get overriden.
The HandledScreen cursor handler is responsible for:
- Changing the cursor type to shift when holding shift above items in the inventory.
- Changing the cursor type to pointer when hovering over items in the inventory.
- Changing the cursor type to grabbing when an item is held in the inventory.
You can either replicate this behavior in your HandledScreen subclass, or extend the AbstractHandledScreenCursorHandler, or better yet, implement CursorProvider directly in your element so you do not need to do register it or provide additional logic for the HandleScreen superclass.
// AbstractHandledScreenCursorHandler accepts two parameters:
// The first parameter is the ScreenHandler of the HandledScreen subclass you wish to be registered.
// The second parameter is the HandledScreen subclass itself.
public class MyHandledScreenCursorHandler extends AbstractHandledScreenCursorHandler<MyScreenHandler, MyHandledScreen> {
@Override
public CursorType getCursorType(MyHandledScreen handledScreen, double mouseX, double mouseY) {
// There are two approaches:
// 1. Get the cursor type of the HandledScreen first.
CursorType cursorType = super.getCursorType(handledScreen, mouseX, mouseY);
// If the cursor type of the handled screen is not default then return the cursor type
if (cursorType != CursorType.DEFAULT) return cursorType;
// You can also return later if you need the state of the cursor type from the HandledScreen.
// 2. Return the cursor type of the HandledScreen last after computing the cursor type
// of your HandledScreen and none of your conditions were met.
return super.getCursorType(handledScreen, mouseX, mouseY);
}
}For more examples, you can take a look at the source code of Minecraft Cursor: https://github.com/fishstiz/minecraft-cursor/blob/release/1.21.4/common/src/main/java/io/github/fishstiz/minecraftcursor/impl/MinecraftCursorInitializerImpl.java#L18
|
Previous: Create Cursor Types
|
Next: CursorProvider Interface
|