Skip to main content
Huds are persistent display elements that remain visible to players continuously. They’re perfect for health bars, hunger displays, status indicators, and other information that should always be visible.

What is a Hud?

A Hud is a HudObject that:
  • Displays continuously once added to a player
  • Updates based on placeholders and listeners
  • Can be toggled on/off per player
  • Supports animations and conditional visibility
Unlike Popups, Huds don’t automatically disappear. They remain visible until explicitly removed or the player disconnects.

Basic Structure

Huds are defined in YAML files in the huds/ directory:
my_hud_name:
  layouts:           # One or more layouts to display
    1:
      name: health_layout
      gui:
        x: 35       # Screen position (percentage)
        y: 100
      pixel:
        x: 0        # Pixel offset
        y: -80
    2:
      name: hunger_layout
      gui:
        x: 65
        y: 100
      pixel:
        x: 0
        y: -80
The layout names (e.g., health_layout) must match layout definitions in the layouts/ directory.

Real Example: Default Health & Hunger HUD

Here’s the actual default HUD from BetterHud’s source:
test_hud:
  layouts:
    1:
      name: health
      gui:
        x: 35        # 35% from left of screen
        y: 100       # 100% from top (bottom of screen)
      pixel:
        x: 0
        y: -80       # 80 pixels up from bottom
    2:
      name: hunger
      gui:
        x: 65        # 65% from left of screen
        y: 100
      pixel:
        x: 0
        y: -80
This HUD displays two layouts side-by-side at the bottom of the screen:

Health Layout

Shows health bar and armor bar on the left side

Hunger Layout

Shows hunger bar and air bar on the right side

Layout Configuration

The referenced layouts are defined in layouts/default-layout.yml:
health:
  images:
    1:
      name: health_empty    # Background image
      x: 0
      y: 0
    2:
      name: health_bar      # Dynamic health bar
      x: 15
      y: 4
    3:
      name: armor_empty     # Armor background
      x: 0
      y: 15
    4:
      name: armor_bar       # Dynamic armor bar
      x: 15
      y: 19
  animations:
    duration: 60
    x-equation: 0
    y-equation: 3cos(t/30 * pi)  # Gentle bobbing animation
The y-equation: 3cos(t/30 * pi) creates a smooth up-and-down bobbing effect. The t variable represents the current tick.

Positioning System

Huds use a two-part positioning system:

GUI Coordinates

Percentage-based positioning relative to screen size:
gui:
  x: 50    # 50% from left (center)
  y: 50    # 50% from top (middle)
ValuePosition
x: 0Left edge
x: 50Center horizontally
x: 100Right edge
y: 0Top edge
y: 100Bottom edge

Pixel Coordinates

Fixed pixel offset from GUI position:
pixel:
  x: 10    # 10 pixels right
  y: -20   # 20 pixels up (negative = up)
Combine both for responsive positioning that adapts to screen size while maintaining precise alignment.

Dynamic Content with Listeners

Hud images can respond to game state using listeners:
health_bar:
  type: listener
  file: health_bar.png
  split: 25           # Divide into 25 frames
  split-type: left    # Fill from left to right
  setting:
    listener:
      class: health   # Use health listener
When the player’s health changes, the appropriate frame is displayed:
1

Player takes damage

Health listener detects the change
2

Calculate frame

Current health / max health determines which frame to show
3

Update display

The corresponding portion of health_bar.png is displayed

Available Listeners

ListenerMonitorsExample Use
healthPlayer healthHealth bars
foodHunger levelHunger bars
armorArmor pointsArmor indicators
airOxygen levelAir bubbles
expExperienceXP bars
Create custom listeners with the Listener API to track any numeric value.

Animations

Add life to your HUDs with mathematical animations:
my_layout:
  images:
    # ... image configuration
  animations:
    duration: 60              # Animation loop length (ticks)
    x-equation: 5sin(t/20)   # Horizontal movement
    y-equation: 3cos(t/30 * pi)  # Vertical movement

Animation Variables

  • t - Current tick in animation cycle (0 to duration)
  • Mathematical functions - sin, cos, tan, sqrt, abs, etc.
  • Constants - pi, e
Use sin and cos for smooth, repeating motions. Use t for linear progression.

Conditional Visibility

Show/hide HUDs based on conditions:
my_hud:
  conditions:
    - "<player_health> > 0"      # Only show if alive
    - "<player_world> = 'world'"  # Only in specific world
  layouts:
    # ...

Working with Huds via API

Add and remove HUDs programmatically:
import kr.toxicity.hud.api.BetterHud;
import kr.toxicity.hud.api.hud.Hud;
import kr.toxicity.hud.api.player.HudPlayer;

// Get a HUD by name
Hud myHud = BetterHud.getInstance()
    .getHudManager()
    .getHud("test_hud");

// Add to player
if (myHud != null) {
    myHud.add(hudPlayer);
}

// Remove from player
myHud.remove(hudPlayer);

// Check what HUDs a player has
Set<Hud> activeHuds = hudPlayer.getHuds();
Get a HudPlayer instance from the PlayerManager:
HudPlayer hudPlayer = BetterHud.getInstance()
    .getPlayerManager()
    .getHudPlayer(player.getUniqueId());

Default HUDs

Mark a HUD as default to show it automatically to all players:
my_default_hud:
  default: true  # Show to all players automatically
  layouts:
    # ...
Default HUDs are added to players when they join and after reloads.

Update Frequency

Control how often a HUD updates:
my_hud:
  update:
    tick: 20  # Update every 20 ticks (1 second)
  layouts:
    # ...
Lower values = more frequent updates = higher server load.
For static or rarely-changing HUDs, set a higher tick value to reduce performance impact.

Complete Example

Here’s a complete HUD configuration with all features:
advanced_hud:
  default: false
  conditions:
    - "<player_health> > 0"
  update:
    tick: 10
  layouts:
    1:
      name: status_layout
      gui:
        x: 50
        y: 10
      pixel:
        x: -64
        y: 0
With a corresponding layout in layouts/status_layout.yml:
status_layout:
  images:
    1:
      name: status_background
      x: 0
      y: 0
    2:
      name: health_indicator
      x: 10
      y: 5
  texts:
    1:
      name: main_font
      pattern: "HP: <player_health>/<player_max_health>"
      x: 30
      y: 8
      scale: 0.8
  animations:
    duration: 40
    y-equation: 2sin(t/10)

Best Practices

  • Use reasonable update frequencies (don’t update every tick unless necessary)
  • Minimize the number of active HUDs per player
  • Optimize image sizes (smaller = better performance)
  • Keep HUD elements small and unobtrusive
  • Use consistent positioning across HUDs
  • Test on different screen sizes and resolutions
  • Group related layouts together
  • Use descriptive names for HUDs and layouts
  • Document complex equations with comments (using #)

Next Steps

Popups

Learn about temporary notification displays

Layouts

Deep dive into layout configuration

Images

Configure dynamic and animated images

Listeners

Create custom data listeners

Build docs developers (and LLMs) love