Content generated with AI — it may contain mistakes.

Interfaces

HUD

Text on a player's screen that never takes their controls: widgets, notices and big moments, designed widgets, anchors and the minimap.

Text on a player's screen that never takes their controls: widgets that stay (money, health, a quest tracker, a combat timer), notices that pop in and out ("+120 coins", a kill), and big moments over the crosshair ("DOUBLE KILL"). Since 1.566.0, in net.exylia.lib.hud (Huds, HudWidget, HudNotice, HudAnchor). It shares the text-display machinery of Screens.

Huds huds = Huds.of(this);
 
HudHandle money = huds.show(player, HudWidget.of("money", HudAnchor.TOP_LEFT,
        p -> Text.of("{success}♦ {letters}" + Formats.money(balance(p))).build()));
money.refresh();   // read the text again now, instead of on its next period
money.remove();
 
huds.notify(player, HudNotice.of(Text.of("{success}+120 {letters}coins").build()).group("coins"));
huds.notify(player, HudNotice.moment(Text.of("{error}&lDOUBLE KILL").build()));

Every method is safe from any thread. Without PacketEvents nothing is drawn and the handles still work, so a caller never branches on support.

Widgets

HudWidget.of(id, anchor, text) stays until it is removed. Showing another with the same id replaces it in place.

FieldCopyDefault
text (Function<Player, Component>)read every every ticks
when (Predicate<Player>)when(condition)always
order (place in the anchor's stack, lowest at the edge)order(n)0
every (ticks between reads, at least 2)every(ticks)10; a fixed Component 1200
background (ARGB, 0 none)background(argb)0; HudWidget.PANEL is the palette's panel
scalescale(size)1
  • text and when run on the player's own thread: read memory, never a database. A text equal to the one on screen sends nothing.
  • A null or blank text, or a false condition, shrinks the widget away and it pops back when it has something to say: "in combat", "low health", "inside a region".
  • Lines break only where the text has \n. A corner is about a fifth of the screen wide before it reaches the middle.

Designed widgets

Since 1.582.0 a widget can be designed like a screen: boxes with backgrounds, gradients and outlines, rows and columns, progress bars and img pictures, laid out by the screens' flexbox (markup).

ScreenMarkup vitals = ScreenMarkup.load(folder.resolve("vitals.html"), folder.resolve("vitals.css"));
huds.show(player, HudWidget.markup("vitals", HudAnchor.TOP_LEFT, vitals).every(4));
 
// or a tree built in Java, null to hide it
huds.show(player, HudWidget.layout("boss", HudAnchor.TOP, p -> Node.column(...)));
<column class="hud-card">
  <row class="line"><text>{error}❤ {letters}Health</text><text>{error}${round(health())}</text></row>
  <progress value="${health()}" max="20"/>
</column>
  • The tree is read again every every ticks on the player's thread. A layout equal to the one on screen sends nothing.
  • hud-card is in the base theme: the dark see-through panel and thin outline that read over any sky. The HUD kit (1.585.0) adds hud-row, hud-stack, hud-chip, hud-banner, hud-objective, hud-alert, hud-level with hud-bar, hud-profile, hud-panel with hud-panel-title and hud-map.
  • border-radius: 2px cuts each corner as pixel steps without a seam. Only a HUD draws it.
  • Minimap: <img map="40" zoom="1" round ring="{primary}"/> is the ground around the player, turned so their facing is up, with an arrow in the middle: the map colour of each column's top block, shaded by height. Four displays whatever its size (8 to 64); it reads only loaded chunks the player's region owns. Give it every: 10 or more.
  • Clicks, hovers, transition, animation and enter do nothing on a HUD; item, item3d, window and turning bodies are left out, and text shadows are never drawn.
  • Cost: one display per rect, per text and four per picture; an outline is four. An element draws at most 64, so keep designs small. Layers are spawned back to front because a client draws see-through displays in spawn order.

Notices

HudNotice.of(text) pops in at the top right, stays three seconds and shrinks away. Newer ones stand nearest the edge; past five at one anchor the oldest leaves early.

FieldCopyDefault
anchoranchor(where)TOP_RIGHT
secondsseconds(time)3
groupgroup(key)none
scalescale(size)1

A notice whose group matches one still up replaces it, counts (×3), pops and restarts its time: three kills in a row are one line. HudNotice.moment(text) is twice the size, no panel, just above the crosshair for two seconds; a new moment replaces the one on screen.

Anchors

AnchorWhereStacks
TOP_LEFTthe top left corner, free in vanilladown
TOPthe top centre, under one boss bardown
TOP_RIGHTthe top right, under the potion icons; noticesdown
LEFTthe left edge, above the chatdown
CENTERjust above the crosshair; momentsdown
RIGHTthe right edge, where the sidebar goesdown
ABOVE_HOTBARover the hotbar, hearts and experience barup
BOTTOM_RIGHTthe bottom right cornerup

HudAnchor.parse("top-left") reads the names a file writes. The held item covers BOTTOM_RIGHT (the client draws the hand last), so keep it for things that can wait. Positions are measured on a 16:9 window at FOV 70.

How it stays put

Each element is one text display seated on the player for their client alone, with a camera-facing billboard sixteen blocks ahead, so walking, jumping and turning cost no packet. Only a changed text, a condition flipping, a reflowed stack or a pitch step (3°) sends anything.

  • Fitted to the window (1.584.0): corners are placed for the player's own FOV and window shape, the ones they fit on their first screen or HUD, and elements are drawn larger by the same share (Screens).
  • Sprinting narrows the HUD a little towards the middle with the world; it is not compensated.
  • One stack per anchor across plugins: two plugins at one anchor stack one after the other.
  • Steps aside while a screen is open, a camera shot plays, the player is dead or in spectator mode, and when the player turned Show HUD off in /settings (Huds.hidden(player, hide) from code).
  • Only translation and scale animate: elements grow from their middle, glide when their stack reflows and shrink back (1.588.0).
  • Who sees it (1.591.0): Huds.supports(player) is a Java client of 1.20.2 or newer with PacketEvents on the server; Huds.visible(player) adds "and did not turn it off". A widget shown to someone not visible is simply not drawn; branch only to show something else instead (a sidebar, a boss bar). %player_hud% gives the same answer to other plugins' files.

Try it with /exylialib hudtest show|notice [group]|moment|hide.

From a file

Any interaction list (menu clicks, screen actions, open items) can write [HUD] {success}+120 {letters}coins;group:coins;seconds:4 and [MOMENT] {error}&lDOUBLE KILL. Options are the trailing ;key:value parts (anchor, seconds, group); the rest is the text, with the player's placeholders.

Something missing on this page? Tell us on Discord