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);
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
Install PlaceholderAPI on your Bukkit server
BetterHud will automatically detect and integrate with it
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>"
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
Avoid expensive operations in the player function
Pre-calculate values in the args/event function when possible
Use appropriate update intervals (see Triggers )
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:
Verify the placeholder is registered correctly
Check the placeholder name spelling
Ensure the placeholder type matches usage (number/string/boolean)
Reload the plugin: /betterhud reload
Placeholder Returns Wrong Value
If a placeholder shows incorrect values:
Add debug logging to your placeholder function
Check the update event context
Verify the player object is correct
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