Creating Placeholder Tokens

Waarschuwing

These docs were written for SpongeAPI 7 and are likely out of date. If you feel like you can help update them, please submit a PR!

At the heart of the Sponge Placeholder API is the ability to create your own tokens and have them accessible to all plugins. To create your own placeholder, you must create an object that implements PlaceholderParser and then registered in the appropriate registry.

Creating PlaceholderParsers

There are two ways you can create a PlaceholderParser:

PlaceholderParser objects take a PlaceholderContext object which contains the context of the request and returns a Component based on that context. Information that the PlaceholderContext may contain includes:

  • An associated object, such as a Player

  • An argument string which generally will be provided by a templating engine

This is the minimum as specified by Sponge.

If your placeholder is unable to provide text because the context does not provide the context or arguments it requires, the placeholder should return an empty Component and not throw an exception.

Tip

If you wish to provide the ability to add multiple arguments to your placeholder, consider specifying a way to split up the argument string.

Remember to tell users of your plugin what you expect your argument string to look like.

Example: Default World Name PlaceholderParser

This PlaceholderParser attempts to get the default world’s name, returning an empty Component if it cannot be found. It uses the builder to create the parser with ID spongedocs:defaultworld, assuming the plugin has an ID of spongedocs.

import net.kyori.adventure.text.Component;

PluginContainer thisPlugin = ...;

PlaceholderParser parser = PlaceholderParser.builder()
    .plugin(this.thisPlugin)
    .id("defaultworld")
    .name("Default World Placeholder")
    .parser(placeholderContext -> {
        return Sponge.getServer()
            .getDefaultWorld()
            .map(x -> x.getWorldName())
            .orElse(Component.empty());
    })
    .build();

Example: Player Location PlaceholderParser

This PlaceholderParser attempts to get the player’s location in the world. If used without a Player as the associated object, it returns an empty Component. This implements the PlaceholderParser interface directly.

import net.kyori.adventure.text.TextComponent;

public class PlayerLocationPlaceholder implements PlaceholderParser {

    @Override
    public String getId() {
        return "spongedocs:location"
    }

    @Override
    public String getName() {
        return "Location Placeholder"
    }

    @Override
    public Component parse(PlaceholderContext placeholderContext) {
        placeholderContext.associatedObject()
            .filter(x -> x instanceof Player)
            .map(player -> ((Player) player).getLocation())
            .map(location -> TextComponent.ofChildren(
                Component.text("World: "),
                Component.text(location.getExtent().getName()),
                Component.text(" - "),
                Component.text(location.getPosition())))
            .orElse(Component.empty());
    }
}

Example: Current Time PlaceholderParser

This PlaceholderParser returns the current time in the server’s local timezone. If the string “UTC” is provided as the argument string, it returns the current time in the UTC time zone. This implements the PlaceholderParser interface directly.

public class CurrentTimePlaceholder implements PlaceholderParser {

    @Override
    public String getId() {
        return "spongedocs:currenttime";
    }

    @Override
    public String getName() {
        return "Current Time parser";
    }

    @Override
    public Component parse(PlaceholderContext placeholderContext) {
        if (placeholderContext.argumentString().filter(x -> x.equalsIgnoreCase("UTC")).isPresent()) {
            return Component.text(OffsetDateTime.now(ZoneOffset.UTC).format(FORMATTER));
        }
        return Component.text(OffsetDateTime.now().format(FORMATTER));
    }

}

Registering Your PlaceholderParser

For your parser to be easily accessible to other plugins, it must be registered in the registry. This should be done by listening to the GameRegistryEvent.Register<PlaceholderParser> event and registering your parsers using the register method.

Example: Registering a PlaceholderParser

PlaceholderParser parser = ...;

@Listener
public void registerTokensEvent(GameRegistryEvent.Register<PlaceholderParser> event) {
    event.register(this.parser);
}