Appearance
HUD widgets
A HUD widget is a module that draws on the screen while playing. LynxClient handles everything around it: the player drags it in the HUD editor, snaps it to edges and other widgets, scales it, groups it and switches its background. You only say how big it is and what it draws.
Text widgets
Most widgets are "label value", like LynxClient's own FPS or ping. Extend TextHudWidget and return two strings:
java
public final class HelloWidget extends TextHudWidget {
public HelloWidget() {
// id, on by default, anchor, distance from the anchor in GUI pixels
super("my_addon_hello", true, HudWidgetConfig.Anchor.TOP, 0, 4);
}
@Override
protected String label() {
return "Hello";
}
@Override
protected String value(boolean editor) {
return "world";
}
}Text widgets get LynxClient's style settings for free: box or clean style, show label, label and value colour. editor is true in the HUD editor. Return a sample value there when you have nothing to show (no world loaded yet).
Free widgets
For anything else extend HudWidget<C>:
java
public final class Compass extends HudWidget<HudWidgetConfig> {
public Compass() {
super("my_addon_compass", new HudWidgetConfig(true, HudWidgetConfig.Anchor.TOP, 0, 22));
}
@Override
public int width(RenderContext ctx) {
return 80;
}
@Override
public int height(RenderContext ctx) {
return 12;
}
@Override
public void render(RenderContext ctx, boolean editor) {
if (config().background.get()) ctx.roundedRect(0, 0, 80, 12, 3, 0x7012141A);
ctx.text(direction(), 4, 2, 0xFFFFFFFF, !config().background.get());
}
}Draw at (0, 0). Position and scale are applied by LynxClient. Sizes are GUI pixels at scale 1.
Drawing
RenderContext is the same on every Minecraft version. Colours are ARGB (0xFF12141A). Never use OpenGL directly, Minecraft keeps changing its renderer.
| Method | |
|---|---|
fill(x1, y1, x2, y2, argb) | Rectangle |
roundedRect(x1, y1, x2, y2, radius, fill[, border]) | Rounded rectangle, corners drawn at full screen resolution |
outline(x, y, w, h, argb) | 1-pixel frame |
text(text, x, y, argb, shadow), textWidth, lineHeight | Minecraft's font |
item(item, x, y) | 16×16 item icon (from GameInfo) |
push(), pop(), translate, scale | Transform |
enableScissor, disableScissor | Clip to a rectangle |
Keep it cheap: the HUD cache
LynxClient draws the HUD into a buffer and only redraws it when something changed. For that, each widget reports a fingerprint of what it shows right now:
java
@Override
public long stateHash() {
return text().hashCode(); // same value → nothing to redraw
}TextHudWidgetdoes this for you (the hash of label and value).- For your own
HudWidget, return a hash of the values you draw. Position, scale and settings are covered by LynxClient. - If the widget really changes every frame (an animation), return
NOT_CACHEABLE. That is the default, and it costs performance.
Measured with the built-in benchmark, LynxClient's whole HUD costs about 0.01 to 0.02 ms per frame thanks to this cache. Please keep it that way: no allocations and no heavy work in render, compute values in a tick listener instead.
Nothing to show
Return false from hasContent() to skip the widget in game (for example "no potion effects"). It is still shown in the HUD editor so the player can place it.
Position
HudWidgetConfig.Anchor is the corner, edge centre or centre the widget is attached to (TOP_LEFT to BOTTOM_RIGHT). The offset counts from that edge. Anchored positions keep widgets in place at every GUI scale. A new widget whose default spot is already taken moves to a free one the first time it appears, so you do not need to know where the player put their widgets.