Skip to main content
Placeholders are dynamic values that can be displayed in your HUDs, popups, and other elements. BetterHud supports three types of placeholders: Number, String, and Boolean.

Placeholder Types

BetterHud organizes placeholders into three containers based on their return type:
  • Number: Numeric values (health, level, coordinates, etc.)
  • String: Text values (player name, world name, etc.)
  • Boolean: True/false values (sneaking, flying, in combat, etc.)

Using Placeholders

Placeholders are used in configuration files with special syntax:
# In a text element
text:
  - "Health: <number:player_health>"
  - "Name: <string:player_name>"
  - "Flying: <boolean:is_flying>"

Built-in Placeholders

BetterHud provides many built-in placeholders:

Number Placeholders

  • player_health - Current health
  • player_max_health - Maximum health
  • player_food - Food level
  • player_level - Experience level
  • player_x - X coordinate
  • player_y - Y coordinate
  • player_z - Z coordinate
  • player_armor - Armor points
  • player_air - Air level

String Placeholders

  • player_name - Player display name
  • world_name - Current world name
  • biome_name - Current biome

Boolean Placeholders

  • is_sneaking - Whether player is sneaking
  • is_flying - Whether player is flying
  • is_sprinting - Whether player is sprinting
  • is_in_water - Whether player is in water

Creating Custom Placeholders

Java API

Create custom placeholders using the Java API:

Number Placeholder

import kr.toxicity.hud.api.BetterHudAPI;
import kr.toxicity.hud.api.placeholder.HudPlaceholder;
import kr.toxicity.hud.api.placeholder.PlaceholderContainer;
import kr.toxicity.hud.api.player.HudPlayer;

public class CustomPlaceholders {
    public void registerPlaceholders() {
        PlaceholderContainer<Number> numberContainer = BetterHudAPI.inst()
            .getPlaceholderManager()
            .getNumberContainer();
        
        // Simple placeholder
        HudPlaceholder.<Number>builder()
            .function((args, event) -> player -> {
                return player.getLevel() * 100; // Custom calculation
            })
            .build()
            .add("custom_score", numberContainer);
    }
}

String Placeholder

import kr.toxicity.hud.api.placeholder.HudPlaceholder;

PlaceholderContainer<String> stringContainer = BetterHudAPI.inst()
    .getPlaceholderManager()
    .getStringContainer();

HudPlaceholder.<String>builder()
    .function((args, event) -> player -> {
        return "Welcome, " + player.getName() + "!";
    })
    .build()
    .add("custom_greeting", stringContainer);

Boolean Placeholder

import kr.toxicity.hud.api.placeholder.HudPlaceholder;

PlaceholderContainer<Boolean> booleanContainer = BetterHudAPI.inst()
    .getPlaceholderManager()
    .getBooleanContainer();

HudPlaceholder.<Boolean>builder()
    .function((args, event) -> player -> {
        return player.getHealth() < 5.0; // Low health check
    })
    .build()
    .add("is_low_health", booleanContainer);

Placeholders with Arguments

Create placeholders that accept arguments:
HudPlaceholder.<Number>builder()
    .requiredArgsLength(1) // Require 1 argument
    .function((args, event) -> player -> {
        // args.get(0) contains the first argument
        int multiplier = Integer.parseInt(args.get(0));
        return player.getLevel() * multiplier;
    })
    .build()
    .add("level_multiplied", numberContainer);
Use in configuration:
text:
  - "Score: <number:level_multiplied:5>" # Multiplies level by 5

Advanced Placeholder Functions

Use the update event for context-aware placeholders:
import kr.toxicity.hud.api.update.UpdateEvent;
import kr.toxicity.hud.api.update.UpdateReason;

HudPlaceholder.<String>builder()
    .function((args, event) -> {
        // Access event information
        UpdateReason reason = event.getType();
        Object key = event.getKey();
        
        return player -> {
            if (reason == UpdateReason.EMPTY) {
                return "No event";
            }
            return "Event: " + reason.name();
        };
    })
    .build()
    .add("event_type", stringContainer);

Platform-Specific Placeholders

Bukkit Placeholders

Access Bukkit-specific data:
import org.bukkit.entity.Player;

HudPlaceholder.<String>builder()
    .function((args, event) -> hudPlayer -> {
        Player player = (Player) hudPlayer.handle();
        return player.getWorld().getName();
    })
    .build()
    .add("bukkit_world", stringContainer);

Fabric Placeholders

Access Fabric-specific data:
import net.minecraft.server.level.ServerPlayer;

HudPlaceholder.<Number>builder()
    .function((args, event) -> hudPlayer -> {
        ServerPlayer player = (ServerPlayer) hudPlayer.handle();
        return player.experienceLevel;
    })
    .build()
    .add("fabric_level", numberContainer);

PlaceholderAPI Integration (Bukkit)

BetterHud can integrate with PlaceholderAPI on Bukkit servers to use any PAPI placeholder.

Setup

  1. Install PlaceholderAPI on your Bukkit server
  2. BetterHud will automatically detect and integrate with it
  3. Use PAPI placeholders with the papi_ prefix

Usage

text:
  - "Balance: <papi_vault_eco_balance>"
  - "Rank: <papi_luckperms_prefix>"

Conditional Placeholders

Combine placeholders with conditions (see Conditions):
text:
  - condition: "<boolean:is_low_health>"
    value: "Health: <number:player_health> (LOW!)"
  - condition: "!<boolean:is_low_health>"
    value: "Health: <number:player_health>"

Placeholder Performance

Caching

Placeholder values are cached per update cycle:
// Values are computed once per update
HudPlaceholder.<Number>builder()
    .function((args, event) -> {
        // This is called once per update event
        ExpensiveCalculation calc = new ExpensiveCalculation();
        
        return player -> {
            // This is called once per player
            return calc.getValue(player);
        };
    })
    .build()

Optimization Tips

  1. Avoid expensive operations in the player function
  2. Pre-calculate values in the args/event function when possible
  3. Use appropriate update intervals (see Triggers)
  4. Cache external data (database queries, API calls)

Examples

Health Bar Placeholder

HudPlaceholder.<Number>builder()
    .function((args, event) -> player -> {
        double health = player.getHealth();
        double maxHealth = player.getMaxHealth();
        return (health / maxHealth) * 100; // Health percentage
    })
    .build()
    .add("health_percentage", numberContainer);

Time-Based Placeholder

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

HudPlaceholder.<String>builder()
    .function((args, event) -> {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
        return player -> LocalDateTime.now().format(formatter);
    })
    .build()
    .add("current_time", stringContainer);

Combat Status Placeholder

import java.util.Map;
import java.util.HashMap;
import java.util.UUID;

public class CombatPlaceholder {
    private final Map<UUID, Long> combatTimers = new HashMap<>();
    
    public void register() {
        HudPlaceholder.<Boolean>builder()
            .function((args, event) -> player -> {
                Long lastCombat = combatTimers.get(player.getUUID());
                if (lastCombat == null) return false;
                return System.currentTimeMillis() - lastCombat < 10000; // 10 seconds
            })
            .build()
            .add("in_combat", BetterHudAPI.inst()
                .getPlaceholderManager()
                .getBooleanContainer());
    }
    
    public void onPlayerAttack(UUID playerId) {
        combatTimers.put(playerId, System.currentTimeMillis());
    }
}

Troubleshooting

Placeholder Not Found

If a placeholder isn’t recognized:
  1. Verify the placeholder is registered correctly
  2. Check the placeholder name spelling
  3. Ensure the placeholder type matches usage (number/string/boolean)
  4. Reload the plugin: /betterhud reload

Placeholder Returns Wrong Value

If a placeholder shows incorrect values:
  1. Add debug logging to your placeholder function
  2. Check the update event context
  3. Verify the player object is correct
  4. Test with built-in placeholders first

Next Steps

Triggers

Learn when placeholders update

Conditions

Use placeholders in conditions

Animations

Animate placeholder values

API Reference

Full placeholder API docs

Build docs developers (and LLMs) love