Skip to content

HUD Overlay

ssbaxys edited this page Oct 26, 2026 · 1 revision

UI on top of the game and live player data.

On this page: HUD (hud.Hud) · HUD widgets · Game data (game.GameData)

HUD (hud.Hud)

Hud.get() is the shared HUD that the loader draws every frame on top of the game interface (Forge 1.20.1: the luminaui:hud overlay above all vanilla ones, NeoForge 1.21.1: the luminaui:hud layer) and ticks on every client tick. The mouse and keyboard don't reach the HUD. An empty HUD costs nothing: the frame doesn't even start.

Hud hud = Hud.get();
hud.add(new SegmentedBar().bind(GameData.health()).bindMax(GameData.maxHealth()), HudAnchor.BOTTOM_CENTER)
        .offset(0, 52)                       // inward from the anchored edge
        .layer(10)                           // higher layer is on top
        .visibility(HudVisibility.GAMEPLAY); // hide on F1, F3, in chat and under screens
hud.toast("Done", "World saved");
hud.feed().post("minecraft:diamond", "+1 diamond", Toast.SUCCESS);
hud.remove(element);

HudAnchor anchors: TOP_LEFT, TOP_CENTER, TOP_RIGHT, CENTER_LEFT, CENTER, CENTER_RIGHT, BOTTOM_LEFT, BOTTOM_CENTER, BOTTOM_RIGHT. The offset points inward, like right: 4px in CSS: for right anchors a positive dx moves left, for bottom anchors a positive dy moves up. An element that changes size stays pinned to its edge.

HudVisibility rules are checked every frame against the Platform.hudState() mask:

Rule Hidden
ALWAYS never
DEFAULT (the HUD-wide rule) on F1 and on the F3 debug screen
GAMEPLAY on F1, F3, in chat and under any open screen
.hideWithGui/hideInDebug/hideInChat/hideInScreens(bool) your own combination
.when(() -> condition) an extra show condition (keep it cheap: read every frame)

Your own HUD-wide rule: hud.setDefaultVisibility(...); an element's own visibility (setVisible) is left alone, since the rule applies to a wrapper. hud.setTheme(theme), hud.setScale(1.25f), hud.onClientTick(runnable). You can draw your own new Hud() instance yourself: hud.render(canvas, w, h, partialTick).

HUD widgets

Widget What it is
Toast a notification: item icon, title, up to 3 lines of text, a progress bar, a lifetime (a bar at the bottom). Toast.info/success/warning/error(...), .icon(id), .timeout(sec) (0 means until dismiss()), .progress(0..1) / .bindProgress(signal), .onClose(...). Slides in from the nearest edge, leaves and collapses; time stops while hovered
ToastStack a stack of toasts: maxVisible(n) (extra ones wait in a queue), newestOnTop, slideFrom(±1), dismissAll(). The shared one is hud.toasts() (top right)
NotificationFeed a compact feed of lines with a colored tag and an icon, fading after lifetime seconds, at most capacity. The shared one is hud.feed() (middle left)
Countdown + TimerDisplay countdown / stopwatch on the real clock (start/pause/toggle/reset/restart/add, onFinish); the widget shows "M:SS", with tenthsBelow(5) tenths, and turns red and pulses for the last warnBelow seconds
SegmentedBar a bar made of segments like hearts: segments, segmentSize, color, lowBelow (blinks), damage trail
BossBar a wide bar with a title, a colors(from, to) gradient and notches(6/10/12/20)
RadialGauge a 270° (sweep) circular gauge with a number or a percentage (percent(true)) and a label

All bars take any numeric signal (bind(ReadableSignal<? extends Number>)), unsubscribe when they leave the tree, and draw without allocating memory per frame (strings only when the value changes).

Theme classes (in all built-in themes; for a theme built from scratch use HudStyles.install(theme)): toast, hud-bar, hud-feed, hud-timer, hud-panel (a translucent backing for a group). Custom properties: HudStyles.TRACK_COLOR (empty part of bars), LOW_COLOR (low / time running out), ROW_COLOR (feed rows).

Game data (game.GameData)

Signals that the loader updates on every client tick via Platform.pollGameData (they notify only on a real change): inWorld, health, maxHealth, healthFraction, absorption, food, foodFraction, saturation, armor, air, maxAir, airFraction, xpLevel, xpProgress, x/y/z (exact), blockX/Y/Z, position ("12 64 -30"), yaw, pitch, facing, biome, dimension, dayTime (0–23999), clock ("06:00"), fps, selectedSlot, selectedItem, selectedCount, inventory (an Inventory snapshot: itemId(i), count(i), total(id), contains(id); a new object only on change). Without a world the values are those of a new player.

Label.bound(GameData.position());
GameData.inventory().subscribe(inv -> diamonds.set(inv.total("minecraft:diamond")));
GameData.setSource(out -> { out.health = 7; return true; });   // your own source (tests, replay)

Subscriptions to the static GameData signals live until you close them: in widgets, subscribe in onAttach and close in onDetach (all library widgets do this), not via map(...) every time a page is built.

In markup: Bindings.gameData() (or bindings.withGameData()) with short names from GameData.named().

<label>❤ {{health}} / {{maxHealth}} · food {{food}} · {{pos}} · {{time}} · {{biome}}</label>
<progress value="{{healthFraction}}"/>

An example of everything together is the HudPage page and the HudDemo demo HUD in the test mod.


← Mobs, Items and 3D · English home · Maps →

Clone this wiki locally