Skip to main content
This guide demonstrates how to create, customize, and manage HUD elements using the BetterHud API.

Understanding HUD Components

HUD elements in BetterHud are persistent displays that appear on the player’s screen. They can show:
  • Player statistics (health, mana, experience)
  • Custom metrics and counters
  • Dynamic text and images
  • Conditional content based on game state

Getting HUD Manager

import kr.toxicity.hud.api.BetterHudAPI;
import kr.toxicity.hud.api.manager.HudManager;
import kr.toxicity.hud.api.hud.Hud;

public class HudHelper {
    
    public static HudManager getManager() {
        return BetterHudAPI.inst().getHudManager();
    }
    
    public static Hud getHud(String name) {
        return getManager().getHud(name);
    }
    
    public static Set<String> getAllHudNames() {
        return getManager().getAllNames();
    }
    
    public static Set<Hud> getAllHuds() {
        return getManager().getAllHuds();
    }
}

Player HUD Management

Getting Player’s Active HUDs

import kr.toxicity.hud.api.BetterHudAPI;
import kr.toxicity.hud.api.player.HudPlayer;
import kr.toxicity.hud.api.hud.Hud;
import org.bukkit.entity.Player;

import java.util.Set;

public class PlayerHudManager {
    
    public static Set<Hud> getPlayerHuds(Player player) {
        var playerManager = BetterHudAPI.inst().getPlayerManager();
        HudPlayer hudPlayer = playerManager.getHudPlayer(player.getUniqueId());
        
        if (hudPlayer != null) {
            return hudPlayer.getHuds();
        }
        
        return Set.of();
    }
    
    public static boolean hasHud(Player player, String hudName) {
        Set<Hud> huds = getPlayerHuds(player);
        return huds.stream()
            .anyMatch(hud -> hud.getName().equals(hudName));
    }
    
    public static void listPlayerHuds(Player player) {
        Set<Hud> huds = getPlayerHuds(player);
        
        if (huds.isEmpty()) {
            player.sendMessage("You have no active HUDs");
        } else {
            player.sendMessage("Active HUDs:");
            huds.forEach(hud -> 
                player.sendMessage("- " + hud.getName())
            );
        }
    }
}

Enabling/Disabling HUDs

Toggle HUD Display

import kr.toxicity.hud.api.BetterHudAPI;
import kr.toxicity.hud.api.player.HudPlayer;
import org.bukkit.entity.Player;

public class HudToggle {
    
    public static void enableHud(Player player) {
        var playerManager = BetterHudAPI.inst().getPlayerManager();
        HudPlayer hudPlayer = playerManager.getHudPlayer(player.getUniqueId());
        
        if (hudPlayer != null) {
            hudPlayer.setHudEnabled(true);
            player.sendMessage("HUD enabled");
        }
    }
    
    public static void disableHud(Player player) {
        var playerManager = BetterHudAPI.inst().getPlayerManager();
        HudPlayer hudPlayer = playerManager.getHudPlayer(player.getUniqueId());
        
        if (hudPlayer != null) {
            hudPlayer.setHudEnabled(false);
            player.sendMessage("HUD disabled");
        }
    }
    
    public static void toggleHud(Player player) {
        var playerManager = BetterHudAPI.inst().getPlayerManager();
        HudPlayer hudPlayer = playerManager.getHudPlayer(player.getUniqueId());
        
        if (hudPlayer != null) {
            boolean currentState = hudPlayer.isHudEnabled();
            hudPlayer.setHudEnabled(!currentState);
            player.sendMessage("HUD " + (!currentState ? "enabled" : "disabled"));
        }
    }
    
    public static boolean isHudEnabled(Player player) {
        var playerManager = BetterHudAPI.inst().getPlayerManager();
        HudPlayer hudPlayer = playerManager.getHudPlayer(player.getUniqueId());
        
        return hudPlayer != null && hudPlayer.isHudEnabled();
    }
}

Custom HUD Component

Creating Additional Components

import kr.toxicity.hud.api.BetterHudAPI;
import kr.toxicity.hud.api.component.PixelComponent;
import kr.toxicity.hud.api.component.WidthComponent;
import kr.toxicity.hud.api.player.HudPlayer;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.entity.Player;

import java.util.List;

public class CustomHudComponent {
    
    public static void addCustomComponent(Player player, String text) {
        var playerManager = BetterHudAPI.inst().getPlayerManager();
        HudPlayer hudPlayer = playerManager.getHudPlayer(player.getUniqueId());
        
        if (hudPlayer == null) return;
        
        // Create a custom width component
        WidthComponent component = new WidthComponent() {
            @Override
            public int getWidth() {
                return text.length() * 6; // Approximate width
            }
            
            @Override
            public Component getComponent() {
                return Component.text(text).color(NamedTextColor.GOLD);
            }
        };
        
        // Set as additional component
        hudPlayer.setAdditionalComponent(component);
    }
    
    public static void removeCustomComponent(Player player) {
        var playerManager = BetterHudAPI.inst().getPlayerManager();
        HudPlayer hudPlayer = playerManager.getHudPlayer(player.getUniqueId());
        
        if (hudPlayer != null) {
            hudPlayer.setAdditionalComponent(null);
        }
    }
    
    public static WidthComponent createPixelComponent(String imageName, int width, int height) {
        return new WidthComponent() {
            @Override
            public int getWidth() {
                return width;
            }
            
            @Override
            public Component getComponent() {
                // Create component from pixel/image data
                return Component.text("[" + imageName + "]");
            }
        };
    }
}

HUD Color Customization

Boss Bar Color

import kr.toxicity.hud.api.BetterHudAPI;
import kr.toxicity.hud.api.player.HudPlayer;
import net.kyori.adventure.bossbar.BossBar;
import org.bukkit.entity.Player;

public class HudColorManager {
    
    public static void setBarColor(Player player, BossBar.Color color) {
        var playerManager = BetterHudAPI.inst().getPlayerManager();
        HudPlayer hudPlayer = playerManager.getHudPlayer(player.getUniqueId());
        
        if (hudPlayer != null) {
            hudPlayer.setBarColor(color);
        }
    }
    
    public static BossBar.Color getBarColor(Player player) {
        var playerManager = BetterHudAPI.inst().getPlayerManager();
        HudPlayer hudPlayer = playerManager.getHudPlayer(player.getUniqueId());
        
        if (hudPlayer != null) {
            return hudPlayer.getBarColor();
        }
        
        return null;
    }
    
    public static void setHealthBasedColor(Player player) {
        var playerManager = BetterHudAPI.inst().getPlayerManager();
        HudPlayer hudPlayer = playerManager.getHudPlayer(player.getUniqueId());
        
        if (hudPlayer != null) {
            double healthPercent = player.getHealth() / player.getMaxHealth();
            
            BossBar.Color color;
            if (healthPercent > 0.7) {
                color = BossBar.Color.GREEN;
            } else if (healthPercent > 0.3) {
                color = BossBar.Color.YELLOW;
            } else {
                color = BossBar.Color.RED;
            }
            
            hudPlayer.setBarColor(color);
        }
    }
}

HUD Update Management

Manual Updates

import kr.toxicity.hud.api.BetterHudAPI;
import kr.toxicity.hud.api.player.HudPlayer;
import org.bukkit.entity.Player;

public class HudUpdater {
    
    public static void forceUpdate(Player player) {
        var playerManager = BetterHudAPI.inst().getPlayerManager();
        HudPlayer hudPlayer = playerManager.getHudPlayer(player.getUniqueId());
        
        if (hudPlayer != null) {
            hudPlayer.update();
        }
    }
    
    public static void reloadPlayer(Player player) {
        var playerManager = BetterHudAPI.inst().getPlayerManager();
        HudPlayer hudPlayer = playerManager.getHudPlayer(player.getUniqueId());
        
        if (hudPlayer != null) {
            hudPlayer.reload();
        }
    }
    
    public static long getPlayerTick(Player player) {
        var playerManager = BetterHudAPI.inst().getPlayerManager();
        HudPlayer hudPlayer = playerManager.getHudPlayer(player.getUniqueId());
        
        if (hudPlayer != null) {
            return hudPlayer.getTick();
        }
        
        return 0;
    }
}

HUD Task Management

Start/Stop Update Tasks

import kr.toxicity.hud.api.BetterHudAPI;
import kr.toxicity.hud.api.player.HudPlayer;
import org.bukkit.entity.Player;

public class HudTaskManager {
    
    public static void startHudTick(Player player) {
        var playerManager = BetterHudAPI.inst().getPlayerManager();
        HudPlayer hudPlayer = playerManager.getHudPlayer(player.getUniqueId());
        
        if (hudPlayer != null) {
            hudPlayer.startTick();
        }
    }
    
    public static void stopHudTick(Player player) {
        var playerManager = BetterHudAPI.inst().getPlayerManager();
        HudPlayer hudPlayer = playerManager.getHudPlayer(player.getUniqueId());
        
        if (hudPlayer != null) {
            hudPlayer.cancelTick();
        }
    }
    
    public static void restartHudTick(Player player) {
        var playerManager = BetterHudAPI.inst().getPlayerManager();
        HudPlayer hudPlayer = playerManager.getHudPlayer(player.getUniqueId());
        
        if (hudPlayer != null) {
            hudPlayer.cancelTick();
            hudPlayer.startTick();
        }
    }
}

Complete Example: Dynamic Health HUD

import kr.toxicity.hud.api.BetterHudAPI;
import kr.toxicity.hud.api.player.HudPlayer;
import kr.toxicity.hud.api.placeholder.HudPlaceholder;
import net.kyori.adventure.bossbar.BossBar;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityRegainHealthEvent;

public class DynamicHealthHud implements Listener {
    
    public static void initialize() {
        // Register health-related placeholders
        var manager = BetterHudAPI.inst().getPlaceholderManager();
        
        HudPlaceholder.<Number>builder()
            .function((args, event) -> player -> {
                Player p = (Player) player.handle();
                return p.getHealth();
            })
            .build()
            .add("current_health", manager.getNumberContainer());
        
        HudPlaceholder.<Number>builder()
            .function((args, event) -> player -> {
                Player p = (Player) player.handle();
                return p.getMaxHealth();
            })
            .build()
            .add("max_health", manager.getNumberContainer());
        
        HudPlaceholder.<Number>builder()
            .function((args, event) -> player -> {
                Player p = (Player) player.handle();
                return (p.getHealth() / p.getMaxHealth()) * 100;
            })
            .build()
            .add("health_percent", manager.getNumberContainer());
    }
    
    @EventHandler
    public void onDamage(EntityDamageEvent event) {
        if (event.getEntity() instanceof Player player) {
            updateHealthColor(player);
        }
    }
    
    @EventHandler
    public void onHeal(EntityRegainHealthEvent event) {
        if (event.getEntity() instanceof Player player) {
            updateHealthColor(player);
        }
    }
    
    private void updateHealthColor(Player player) {
        var playerManager = BetterHudAPI.inst().getPlayerManager();
        HudPlayer hudPlayer = playerManager.getHudPlayer(player.getUniqueId());
        
        if (hudPlayer == null) return;
        
        double healthPercent = player.getHealth() / player.getMaxHealth();
        
        BossBar.Color color;
        if (healthPercent > 0.7) {
            color = BossBar.Color.GREEN;
        } else if (healthPercent > 0.4) {
            color = BossBar.Color.YELLOW;
        } else if (healthPercent > 0.2) {
            color = BossBar.Color.RED;
        } else {
            color = BossBar.Color.PURPLE; // Critical health
        }
        
        hudPlayer.setBarColor(color);
        hudPlayer.update();
    }
}

Conditional HUD Display

import kr.toxicity.hud.api.BetterHudAPI;
import kr.toxicity.hud.api.placeholder.HudPlaceholder;
import org.bukkit.GameMode;
import org.bukkit.entity.Player;

public class ConditionalHud {
    
    public static void registerConditionalPlaceholders() {
        var manager = BetterHudAPI.inst().getPlaceholderManager();
        
        // Show different values based on game mode
        HudPlaceholder.<Boolean>builder()
            .function((args, event) -> player -> {
                Player p = (Player) player.handle();
                return p.getGameMode() == GameMode.SURVIVAL;
            })
            .build()
            .add("is_survival", manager.getBooleanContainer());
        
        // Show based on world
        HudPlaceholder.<Boolean>builder()
            .function((args, event) -> player -> {
                Player p = (Player) player.handle();
                return p.getWorld().getName().equals("world_nether");
            })
            .build()
            .add("in_nether", manager.getBooleanContainer());
        
        // Show based on permission
        HudPlaceholder.<Boolean>builder()
            .requiredArgsLength(1)
            .function((args, event) -> {
                String permission = args.get(0);
                return player -> {
                    Player p = (Player) player.handle();
                    return p.hasPermission(permission);
                };
            })
            .build()
            .add("has_permission", manager.getBooleanContainer());
    }
}

Best Practices

  • Cache HudPlayer instances when possible
  • Avoid frequent updates in tight loops
  • Use conditional rendering with boolean placeholders
  • Batch multiple changes before calling update()
  • Always check if HudPlayer is null before operations
  • Validate HUD names exist before accessing
  • Handle exceptions when updating components
  • Log warnings for debugging
  • Remove custom components when no longer needed
  • Clear player data on disconnect
  • Don’t store unnecessary references to HudPlayer
  • Use weak references for long-term storage

Next Steps

Custom Popup

Create dynamic popup notifications

Placeholders

Advanced placeholder patterns

HUD Manager

Complete HUD Manager API

Player API

Full HudPlayer reference

Build docs developers (and LLMs) love