-
Notifications
You must be signed in to change notification settings - Fork 3
Board
The Board API provides a system to wrap the Bukkit's Scoreboard. It has different layers going from a simple wrapper to the concept of a BoardModel, with placeholders, and that can be also loaded from config.
If you just need to wrap Bukkit's scoreboard you may just want to use the Board class. Here's how:
public void setBoard(Player player) {
Board board = new Board();
board.setTitle(YELLOW + "An awful board");
board.setLines(new ArrayList<String>() {{
add(RED + "line 1"); // Colored line.
add("line 2");
add("line 3");
add(""); // Empty line.
add("line 4");
add("...");
}});
board.open(player); // Open the board to the player.
}Given a player, this function will create a board and open it to him. Quite easy, isn't it?
Now let's dive into a more difficult concept: the board models.
Let's say we have to create a scoreboard that shows a countdown but also contains the name of the player that is visualizing it. If we had only the countdown and nothing related to the player, we could just create one Board instance and set it to all players. But having the owner's name as a line leads us to create one Board for every player.
To handle the problem we introduced the concept of BoardModel:
public class AwfulBoardModel implements BoardModel {
// public int getCountdown() {}
@Override
public void apply(Board board, Player player, PlaceholderRegistry<?> placeholders) {
board.setTitle(YELLOW + "An awful board");
board.setLines(new ArrayList<String>() {{
add("Countdown: " + getCountdown()); // Gets the countdown value someway.
add("Owner: " + player.getName());
}});
}
}Now we have to open the board to a given player and eventually update the board every time the countdown changes.
// We need to remember the board hook associated with every player.
private final Map<Player, BoardModel.Hook> hooks = new HashMap<>();
public void createBoard(Player player) {
// The model is hooked to a newly created board and then opened to the player.
BoardModel.Hook hook = new AwfulBoardModel().hook(new Board());
hook.open(player, PlaceholderRegistry.def()); // We're not using any placeholder, uses the default registry.
}
// This function should be called when the countdown changes.
public void updateBoard(Player player) {
BoardModel.Hook hook = hooks.get(player);
if (hook != null) // Was the board opened for this player?
hook.render(player, PlaceholderRegistry.def());
}This is also the way we handle boards among different phases in our minigames.
Uppercore provides the SimpleBoardModel which is a built-in implementation of the BoardModel. It is really useful specifically if you have scoreboards that don't vary the number of lines dynamically and that relies on placeholders.
The SimpleBoardModel is used the same as the BoardModel, seen above.
To load it from a configuration issue:
SimpleBoardModel awfulBoard = config.getRequired("awful-board", SimpleBoardModel.class);How the scoreboard should look like in the YML file:
awful-board:
title: '&eAn awful board'
lines:
- 'Countdown: %countdown%'
- 'Owner: %player_name%'When opening/updating the board if you use PlaceholderRegistry.def() you'll see the %countdown% placeholder left unresolved. Thus, you need to create your own PlaceholderRegistry that defines it.