Skip to main content

Overview

The Placeholder API allows you to create custom placeholders that can be used in HUDs, popups, and other BetterHud components. Placeholders provide dynamic text replacement based on player data and game state.

HudPlaceholder Interface

The HudPlaceholder<T> interface represents a placeholder that returns values of type T.

Package

kr.toxicity.hud.api.placeholder.HudPlaceholder

Type Parameters

T
Type
The return type of the placeholder (Number, String, or Boolean)

Methods

invoke

Creates a function from the given arguments that will be evaluated for each player.
@NotNull Function<HudPlayer, T> invoke(
    @NotNull @Unmodifiable List<String> args, 
    @NotNull UpdateEvent reason
)
args
List<String>
required
The arguments provided to the placeholder (e.g., from %placeholder_arg1_arg2%)
reason
UpdateEvent
required
The event that triggered this placeholder evaluation
return
Function<HudPlayer, T>
A function that takes a HudPlayer and returns the placeholder value

getRequiredArgsLength

Gets the number of required arguments for this placeholder.
int getRequiredArgsLength()
return
int
The minimum number of arguments required

PlaceholderContainer Interface

Manages a group of related placeholders.

Package

kr.toxicity.hud.api.placeholder.PlaceholderContainer

Type Parameters

T
Type
The return type of placeholders in this container

Methods

addPlaceholder

Adds a placeholder to this container.
void addPlaceholder(@NotNull String name, @NotNull HudPlaceholder<T> placeholder)
name
String
required
The name/identifier for the placeholder
placeholder
HudPlaceholder<T>
required
The placeholder implementation

getAllPlaceholders

Gets all registered placeholders.
@NotNull @Unmodifiable Map<String, HudPlaceholder<?>> getAllPlaceholders()
return
Map<String, HudPlaceholder<?>>
An unmodifiable map of all placeholders in this container

HudPlaceholder.Builder

A builder for creating placeholder implementations.

Methods

requiredArgsLength

Sets the required number of arguments.
@NotNull Builder<T> requiredArgsLength(int requiredArgsLength)
requiredArgsLength
int
required
The number of required arguments

function

Sets the placeholder function.
@NotNull Builder<T> function(@NotNull PlaceholderFunction<T> function)
function
PlaceholderFunction<T>
required
The function that computes the placeholder value

build

Builds the placeholder.
@NotNull HudPlaceholder<T> build()
return
HudPlaceholder<T>
The constructed placeholder

add

Builds and adds the placeholder to a container.
void add(@NotNull String name, @NotNull PlaceholderContainer<T> container)
name
String
required
The name for the placeholder
container
PlaceholderContainer<T>
required
The container to add the placeholder to

PlaceholderFunction

A functional interface for placeholder logic.
@FunctionalInterface
interface PlaceholderFunction<T> extends BiFunction<List<String>, UpdateEvent, Function<HudPlayer, T>>
Signature: (List<String> args, UpdateEvent event) -> (HudPlayer player) -> T

Usage Examples

Creating a Simple Placeholder

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

public class SimplePlaceholderExample {
    
    public void registerHealthPlaceholder() {
        // Get the number placeholder container
        PlaceholderContainer<Number> numberContainer = 
            BetterHud.inst().getPlaceholderManager().getNumberContainer();
        
        // Create a simple placeholder using static method
        HudPlaceholder<Number> healthPlaceholder = HudPlaceholder.of(
            (args, event) -> (HudPlayer player) -> {
                // Return player's health
                if (player.handle() instanceof org.bukkit.entity.Player p) {
                    return p.getHealth();
                }
                return 0;
            }
        );
        
        // Register the placeholder
        numberContainer.addPlaceholder("player_health", healthPlaceholder);
        // Usage in config: %player_health%
    }
}

Using the Builder Pattern

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

public void registerLevelPlaceholder() {
    PlaceholderContainer<Number> numberContainer = 
        BetterHud.inst().getPlaceholderManager().getNumberContainer();
    
    // Build and add placeholder in one go
    HudPlaceholder.<Number>builder()
        .requiredArgsLength(0)
        .function((args, event) -> player -> {
            if (player.handle() instanceof org.bukkit.entity.Player p) {
                return p.getLevel();
            }
            return 0;
        })
        .add("player_level", numberContainer);
    // Usage in config: %player_level%
}

Placeholder with Arguments

public void registerStatPlaceholder() {
    PlaceholderContainer<Number> numberContainer = 
        BetterHud.inst().getPlaceholderManager().getNumberContainer();
    
    HudPlaceholder.<Number>builder()
        .requiredArgsLength(1)  // Requires 1 argument
        .function((args, event) -> player -> {
            String statName = args.get(0);
            
            if (player.handle() instanceof org.bukkit.entity.Player p) {
                return switch (statName.toLowerCase()) {
                    case "health" -> p.getHealth();
                    case "food" -> p.getFoodLevel();
                    case "level" -> p.getLevel();
                    case "exp" -> p.getExp();
                    default -> 0;
                };
            }
            return 0;
        })
        .add("player_stat", numberContainer);
    // Usage in config: %player_stat_health%
    // Usage in config: %player_stat_food%
}

String Placeholder

public void registerNamePlaceholder() {
    PlaceholderContainer<String> stringContainer = 
        BetterHud.inst().getPlaceholderManager().getStringContainer();
    
    HudPlaceholder.<String>builder()
        .requiredArgsLength(0)
        .function((args, event) -> player -> player.name())
        .add("player_name", stringContainer);
    // Usage in config: %player_name%
}

Boolean Placeholder

import org.bukkit.entity.Player;

public void registerFlyingPlaceholder() {
    PlaceholderContainer<Boolean> booleanContainer = 
        BetterHud.inst().getPlaceholderManager().getBooleanContainer();
    
    HudPlaceholder.<Boolean>builder()
        .requiredArgsLength(0)
        .function((args, event) -> player -> {
            if (player.handle() instanceof Player p) {
                return p.isFlying();
            }
            return false;
        })
        .add("is_flying", booleanContainer);
    // Usage in config: %is_flying%
}

Advanced: World-Specific Placeholder

public void registerWorldPlaceholder() {
    PlaceholderContainer<String> stringContainer = 
        BetterHud.inst().getPlaceholderManager().getStringContainer();
    
    HudPlaceholder.<String>builder()
        .requiredArgsLength(1)
        .function((args, event) -> player -> {
            String property = args.get(0);
            
            if (player.handle() instanceof Player p) {
                return switch (property.toLowerCase()) {
                    case "name" -> p.getWorld().getName();
                    case "time" -> String.valueOf(p.getWorld().getTime());
                    case "difficulty" -> p.getWorld().getDifficulty().name();
                    default -> "unknown";
                };
            }
            return "unknown";
        })
        .add("world", stringContainer);
    // Usage: %world_name%, %world_time%, %world_difficulty%
}

Using Update Event Context

import kr.toxicity.hud.api.update.UpdateEvent;

public void registerEventPlaceholder() {
    PlaceholderContainer<String> stringContainer = 
        BetterHud.inst().getPlaceholderManager().getStringContainer();
    
    HudPlaceholder.<String>builder()
        .requiredArgsLength(0)
        .function((args, event) -> player -> {
            // Access the update event context
            return "Event: " + event.getType().name();
        })
        .add("event_type", stringContainer);
}

Math Operations Placeholder

public void registerMathPlaceholder() {
    PlaceholderContainer<Number> numberContainer = 
        BetterHud.inst().getPlaceholderManager().getNumberContainer();
    
    HudPlaceholder.<Number>builder()
        .requiredArgsLength(2)
        .function((args, event) -> player -> {
            String operation = args.get(0);
            double value = Double.parseDouble(args.get(1));
            
            if (player.handle() instanceof Player p) {
                double health = p.getHealth();
                
                return switch (operation.toLowerCase()) {
                    case "add" -> health + value;
                    case "sub" -> health - value;
                    case "mul" -> health * value;
                    case "div" -> health / value;
                    default -> health;
                };
            }
            return 0;
        })
        .add("health_math", numberContainer);
    // Usage: %health_math_add_5%, %health_math_mul_2%
}

Conditional Placeholder

import org.bukkit.GameMode;

public void registerConditionalPlaceholder() {
    PlaceholderContainer<String> stringContainer = 
        BetterHud.inst().getPlaceholderManager().getStringContainer();
    
    HudPlaceholder.<String>builder()
        .requiredArgsLength(0)
        .function((args, event) -> player -> {
            if (player.handle() instanceof Player p) {
                if (p.getGameMode() == GameMode.CREATIVE) {
                    return "Creative Mode";
                } else if (p.getGameMode() == GameMode.SURVIVAL) {
                    return "Survival Mode";
                } else {
                    return p.getGameMode().name();
                }
            }
            return "Unknown";
        })
        .add("gamemode_display", stringContainer);
}

Complete Placeholder Registration System

import kr.toxicity.hud.api.BetterHud;
import kr.toxicity.hud.api.placeholder.PlaceholderContainer;
import org.bukkit.plugin.java.JavaPlugin;

public class PlaceholderRegistry {
    private final JavaPlugin plugin;
    
    public PlaceholderRegistry(JavaPlugin plugin) {
        this.plugin = plugin;
    }
    
    public void registerAll() {
        PlaceholderContainer<Number> numbers = 
            BetterHud.inst().getPlaceholderManager().getNumberContainer();
        PlaceholderContainer<String> strings = 
            BetterHud.inst().getPlaceholderManager().getStringContainer();
        PlaceholderContainer<Boolean> booleans = 
            BetterHud.inst().getPlaceholderManager().getBooleanContainer();
        
        // Register number placeholders
        registerNumberPlaceholders(numbers);
        
        // Register string placeholders
        registerStringPlaceholders(strings);
        
        // Register boolean placeholders
        registerBooleanPlaceholders(booleans);
        
        plugin.getLogger().info("Registered custom placeholders!");
    }
    
    private void registerNumberPlaceholders(PlaceholderContainer<Number> container) {
        HudPlaceholder.<Number>builder()
            .function((args, event) -> player -> {
                if (player.handle() instanceof Player p) {
                    return p.getHealth();
                }
                return 0;
            })
            .add("health", container);
        
        // Add more number placeholders...
    }
    
    private void registerStringPlaceholders(PlaceholderContainer<String> container) {
        HudPlaceholder.<String>builder()
            .function((args, event) -> player -> player.name())
            .add("name", container);
        
        // Add more string placeholders...
    }
    
    private void registerBooleanPlaceholders(PlaceholderContainer<Boolean> container) {
        HudPlaceholder.<Boolean>builder()
            .function((args, event) -> player -> {
                if (player.handle() instanceof Player p) {
                    return p.isFlying();
                }
                return false;
            })
            .add("flying", container);
        
        // Add more boolean placeholders...
    }
}

Accessing Placeholder Containers

Get placeholder containers from the PlaceholderManager:
import kr.toxicity.hud.api.BetterHud;
import kr.toxicity.hud.api.manager.PlaceholderManager;

PlaceholderManager manager = BetterHud.inst().getPlaceholderManager();

// Get typed containers
PlaceholderContainer<Number> numbers = manager.getNumberContainer();
PlaceholderContainer<String> strings = manager.getStringContainer();
PlaceholderContainer<Boolean> booleans = manager.getBooleanContainer();
  • HUD API - Use placeholders in HUDs
  • Popup API - Use placeholders in popups
  • Triggers - Placeholders can use trigger event context

See Also

  • HudPlaceholder interface: kr.toxicity.hud.api.placeholder.HudPlaceholder
  • PlaceholderContainer interface: kr.toxicity.hud.api.placeholder.PlaceholderContainer
  • PlaceholderFunction: kr.toxicity.hud.api.placeholder.HudPlaceholder.PlaceholderFunction
  • PlaceholderManager: kr.toxicity.hud.api.manager.PlaceholderManager

Build docs developers (and LLMs) love