// FOR DEVELOPERS

API Guide

Eymistaken's HUD was engineered with extensibility at its core. Use the EymistakenHudPlugin API to inject custom modules seamlessly into the HUD rendering and ticking engines — no core modification required.

JUMP TO: Architecture Dependency Creating a Module Sub-Elements HUD Editor Context Menu Registering

Modular Architecture

The entire HUD system is orchestrated by HudModuleManager. On initialization it registers the 7 built-in modules. Via the eymistaken_hud Fabric entrypoint, third-party addons can register additional modules that are loaded and managed alongside the core ones automatically.

Each module extends HudModule, which handles render position injection, rainbow color cycling, and the context menu settings contract. On each client tick, SimpleCPSClient calls HudModuleManager#tickAll(Minecraft); during HUD rendering, it calls renderAll(GuiGraphicsExtractor, float). The render pipeline runs through the client-side HUD registry — modules receive a GuiGraphicsExtractor context and implement extractRenderState(GuiGraphicsExtractor, float) to draw their content. Automatic stacking is handled for TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, and BOTTOM_RIGHT; CENTER modules are centered rather than stacked, so multiple centered modules can overlap unless your addon offsets them.

Adding the Dependency

Use JitPack to compile your addon mod against Eymistaken's HUD 26.2. Add the following to your build.gradle:

repositories {
    maven { url 'https://jitpack.io' }
}

dependencies {
    modImplementation 'com.github.Eymistaken:Eymistaken-s-hud:-SNAPSHOT'
}

After reloading your Gradle project, the current 26.2 API classes — including HudModule, IHudElement, HudModuleSetting, and all six setting types — will be available in your development environment.

Creating a Custom Module

Every HUD element must extend HudModule and implement its abstract methods. Below is the minimum required implementation:

import com.eymistaken.simplecps.api.HudModule;
import com.eymistaken.simplecps.SimpleCPSConfig;
import net.minecraft.client.gui.GuiGraphicsExtractor;

public class MyCustomModule extends HudModule {

    @Override
    public String getName() {
        return "My Custom Tracker";
    }

    @Override
    public SimpleCPSConfig.Position getPositionType() {
        return SimpleCPSConfig.Position.TOP_LEFT; // Default corner alignment
    }

    @Override
    public int getXOffset() { return 0; }

    @Override
    public int getYOffset() { return 0; }

    @Override
    public boolean isEnabled() {
        return true; // Tie to your own config
    }

    @Override
    public int getWidth() {
        return 100; // Required for stacking layout
    }

    @Override
    public int getHeight() {
        return 20;
    }

    @Override
    public void extractRenderState(GuiGraphicsExtractor context, float tickDelta) {
        float currentScale = getScale() / 100f;
        context.pose().pushMatrix();
        context.pose().translate((float) this.x, (float) this.y);
        context.pose().scale(currentScale, currentScale);
        
        // After translating, drawing should be done relative to 0,0 (the local origin)
        context.text(this.client.font, "Hello World", 0, 0, 0xFFFFFFFF, true);
        
        context.pose().popMatrix();
    }

    @Override
    public void tick(net.minecraft.client.Minecraft client) {
        // Optional: runs every client tick (timers, click tracking, etc.)
        super.tick(client);
    }
}

Important: Always return accurate values from getWidth() and getHeight(). Returning 0 removes your module from the stacking layout and makes it invisible.

Unique Name Requirement: The value returned by the getName() method must be strictly unique. The HudModuleManager uses this name as a key to store bounding boxes in a Map. Use specific names, for example: "MyAddon_Tracker".

Inherited Variables Note: When a module extends the HudModule class, the variables this.client (Minecraft.getInstance()), this.x, and this.y are automatically inherited. Developers do not need to define these manually.

Advanced: Sub-Elements (Complex Modules)

If a module consists of multiple independently draggable parts (such as the ArmorModule), developers can override the getSubElements() method inside HudModule. This method should return a list of objects that implement the IHudElement interface. This allows the HUD Editor to treat these sub-parts as independent draggable elements instead of dragging the entire main module.

@Override
public List<IHudElement> getSubElements() {
    // Return a list of independent sub-elements (e.g., Helmet, Chestplate, etc.)
    // If empty, the entire module is treated as a single draggable element.
    return mySubElementsList;
}

HUD Editor Integration (Drag & Drop)

Override the optional setter methods to allow players to move, scale, and reset your module in the HUD Editor. Important: save all values to your own mod's config — never to SimpleCPSConfig.

// Inside your MyCustomModule class:

@Override
public void setPositionType(SimpleCPSConfig.Position pos) {
    MyAddonConfig.anchor = pos; // Save to YOUR config
}

@Override
public void setXOffset(int x) { MyAddonConfig.xOffset = x; }

@Override
public void setYOffset(int y) { MyAddonConfig.yOffset = y; }

@Override
public void setScale(int scale) { MyAddonConfig.scale = scale; }

@Override
public int getScale() { return MyAddonConfig.scale; }

@Override
public void resetToDefaults() {
    // Called by "Reset Position" in the context menu
    MyAddonConfig.anchor  = SimpleCPSConfig.Position.TOP_LEFT;
    MyAddonConfig.xOffset = 0;
    MyAddonConfig.yOffset = 0;
    MyAddonConfig.scale   = 100;
}

If you skip these overrides, your module will still render correctly — but players will not be able to move or scale it via the HUD Editor.

When the user drags and drops a module in the HUD Editor screen, the onPositionUpdated() method inside the module is triggered. Developers can override this method to act as a listener, allowing them to automatically save the module's new position to their own config files.

@Override
public void onPositionUpdated() {
    // Called when the user releases the mouse after dragging the module in HUD Editor
    MyAddonConfig.save();
}

Context Menu Settings

When a player right-clicks your module in the HUD Editor, a context menu appears. By default it contains Reset Position and Reset Settings. Extend it by overriding getContextMenuSettings().

Six setting types are available under com.eymistaken.simplecps.api:

import com.eymistaken.simplecps.api.*;
import java.util.Arrays;
import java.util.List;

// Inside your MyCustomModule class:

@Override
public List<HudModuleSetting> getContextMenuSettings() {
    List<HudModuleSetting> settings = new java.util.ArrayList<>(super.getContextMenuSettings());

    // Toggle — shown as [ON] / [OFF]
    settings.add(new BooleanSetting("Enable My Module",
        () -> MyAddonConfig.enabled,
        val -> { MyAddonConfig.enabled = val; MyAddonConfig.save(); }
    ));

    // Color — opens Color Picker on click
    settings.add(new ColorSetting("Text Color",
        () -> MyAddonConfig.textColor,
        color -> { MyAddonConfig.textColor = color; MyAddonConfig.save(); }
    ));

    // Text — opens inline input on click
    settings.add(new TextSetting("Suffix Text",
        () -> MyAddonConfig.suffix,
        val -> { MyAddonConfig.suffix = val; MyAddonConfig.save(); }
    ));

    // Cycle — click through options
    settings.add(new CycleSetting("Display Mode",
        Arrays.asList("Compact", "Full", "Minimal"),
        () -> MyAddonConfig.displayModeIndex,
        idx -> { MyAddonConfig.displayModeIndex = idx; MyAddonConfig.save(); }
    ));

    // Action — plain button, no value
    settings.add(new ActionSetting("Reset My Settings", () -> {
        MyAddonConfig.resetVisuals();
        MyAddonConfig.save();
    }));

    // Slider — integer range with Reset button
    settings.add(new SliderSetting("Scale %",
        50, 300, 100,
        () -> MyAddonConfig.scale,
        val -> { MyAddonConfig.scale = val; MyAddonConfig.save(); }
    ));

    return settings;
}

Tip: Always call super.getContextMenuSettings() and wrap it in a new ArrayList to preserve the default Reset Settings action at the top of the menu. Skip the super call only if you intentionally want to replace it entirely. Note: Reset Position is always present regardless — it is added directly by the HUD Editor, not by getContextMenuSettings().

Override resetVisualDefaults() to define what Reset Settings does for your module. Reset visual and behavioral fields, but keep the enabled state and anchor offsets under the player's control. If your module treats scale as a visual preference, it is safe to reset it here, just like the built-in modules do:

@Override
public void resetVisualDefaults() {
    MyAddonConfig.textColor        = 0xFFFFFF;
    MyAddonConfig.suffix           = "";
    MyAddonConfig.displayModeIndex = 0;
    MyAddonConfig.scale            = 100;
    MyAddonConfig.save();
}

Rule: Never reset enabled, position, or offsets inside resetVisualDefaults(). Position is handled separately by Reset Position, and whether the module is on or off is always the player's choice.

Registering the Plugin

Declare an entrypoint implementing EymistakenHudPlugin in your fabric.mod.json. Your modules will be passed to HudModuleManager#registerModule() and managed alongside the built-in ones from that point forward — no core modification required.

Implementation class:

import com.eymistaken.simplecps.api.EymistakenHudPlugin;
import com.eymistaken.simplecps.HudModuleManager;

public class MyPluginInit implements EymistakenHudPlugin {
    @Override
    public void registerHudModules(HudModuleManager manager) {
        manager.registerModule(new MyCustomModule());
    }
}

fabric.mod.json:

"entrypoints": {
  "eymistaken_hud": [
    "com.myname.myaddon.MyPluginInit"
  ]
}

The eymistaken_hud entrypoint key is processed by SimpleCPSClient during initialization. Every registered module is automatically included in the tickAll() and renderAll() cycles of HudModuleManager, and becomes fully editable in the in-game HUD Editor.