Support multiple named billboards per arena
Build / build (push) Successful in 1m16s

This commit is contained in:
Michael Burgess
2026-08-07 11:13:50 -04:00
parent 412c9411b8
commit 796f8bd1de
6 changed files with 189 additions and 78 deletions
+25 -15
View File
@@ -25,7 +25,8 @@ slightly faster round. Last player standing wins.
All admin/config commands live under `/blockparty` (alias `/bp`) and work from console All admin/config commands live under `/blockparty` (alias `/bp`) and work from console
where it makes sense (`create`, `delete`, `enable`, `disable`, `info`, `list`, `reload`). where it makes sense (`create`, `delete`, `enable`, `disable`, `info`, `list`, `reload`).
Commands that require a physical location (`setlobby`, `setspawn`, `setspectator`, Commands that require a physical location (`setlobby`, `setspawn`, `setspectator`,
`setbillboard`, `pos1`, `pos2`) require a player sender. `setbillboard`, `pos1`, `pos2`) require a player sender. `delbillboard`, `billboards`, `info`
work fine from console.
### Admin ### Admin
| Command | Description | | Command | Description |
@@ -38,8 +39,9 @@ Commands that require a physical location (`setlobby`, `setspawn`, `setspectator
| `/blockparty setlobby <arena>` | Set the waiting-room location | | `/blockparty setlobby <arena>` | Set the waiting-room location |
| `/blockparty setspawn <arena>` | Set the in-game spawn location | | `/blockparty setspawn <arena>` | Set the in-game spawn location |
| `/blockparty setspectator <arena>` | Set the spectator/eliminated location | | `/blockparty setspectator <arena>` | Set the spectator/eliminated location |
| `/blockparty setbillboard <arena>` | (Optional) place a display block here that mirrors the current target color | | `/blockparty setbillboard <arena> [name]` | (Optional) place a named display block here that mirrors the current target color; `name` defaults to `default`, so you can have any number by giving each a unique name |
| `/blockparty delbillboard <arena>` | Remove the billboard, if one is set | | `/blockparty delbillboard <arena> [name]` | Remove a named billboard (defaults to `default`) |
| `/blockparty billboards <arena>` | List an arena's billboards and whether each is enabled |
| `/blockparty pos1 <arena>` | Set floor region corner 1 | | `/blockparty pos1 <arena>` | Set floor region corner 1 |
| `/blockparty pos2 <arena>` | Set floor region corner 2 | | `/blockparty pos2 <arena>` | Set floor region corner 2 |
| `/blockparty setfloor <arena> <mat1,mat2,...>` | Set the allowed floor materials | | `/blockparty setfloor <arena> <mat1,mat2,...>` | Set the allowed floor materials |
@@ -86,8 +88,9 @@ Commands that require a physical location (`setlobby`, `setspawn`, `setspectator
each round (BlockParty does not scan the world every round — it restores from the saved each round (BlockParty does not scan the world every round — it restores from the saved
layout for performance and determinism). layout for performance and determinism).
8. Optionally, stand somewhere visible near/above the floor and run `/bp setbillboard lobby1` 8. Optionally, stand somewhere visible near/above the floor and run `/bp setbillboard lobby1`
(or `/bp setbillboard lobby1 <name>` to add more than one, e.g. one per side of the arena)
to place a big display block that mirrors the round's target color — purely cosmetic and to place a big display block that mirrors the round's target color — purely cosmetic and
entirely optional (see "Billboard" below). entirely optional (see "Billboards" below).
9. `/bp info lobby1` to confirm there are no validation errors. 9. `/bp info lobby1` to confirm there are no validation errors.
10. `/bp enable lobby1`. 10. `/bp enable lobby1`.
11. Players run `/bp join lobby1`. Once `min-players` is reached the countdown starts 11. Players run `/bp join lobby1`. Once `min-players` is reached the countdown starts
@@ -112,22 +115,29 @@ Commands that require a physical location (`setlobby`, `setspawn`, `setspectator
(`generated-layout`) so it can be restored exactly, every round, without re-scanning or (`generated-layout`) so it can be restored exactly, every round, without re-scanning or
re-randomizing the world. re-randomizing the world.
### Billboard ### Billboards
An arena billboard is a `BlockDisplay` entity that visually shows the currently selected An arena billboard is a `BlockDisplay` entity that visually shows the currently selected
target color/block each round, in addition to the title/actionbar/hotbar-item cues. It is target color/block each round, in addition to the title/actionbar/hotbar-item cues. An arena
entirely optional: may have any number of them (e.g. one visible from each side of the floor), each independently
named, positioned and toggled. Entirely optional:
- Per-arena: only spawned if `/bp setbillboard <arena>` has been run (stored as `billboard` - Per-billboard: `/bp setbillboard <arena> [name]` places/updates one at your current location;
in the arena's yml). `/bp delbillboard <arena>` removes it. `name` defaults to `default` if omitted, so the simple single-billboard flow needs no name at
- Per-arena toggle: `billboard-enabled` in the arena's yml (default `true`) lets you keep the all. Give each a distinct `name` to have several at once (e.g. `/bp setbillboard lobby1 north`,
location set but temporarily turn it off without deleting it. `/bp setbillboard lobby1 south`). `/bp delbillboard <arena> [name]` removes one. `/bp billboards
- Global toggle: `ui.billboard` in `config.yml` (default `true`) disables billboards across <arena>` lists an arena's billboards and whether each is enabled.
- Per-billboard toggle: stored per name in the arena's yml (`billboards.<name>.enabled`, default
`true`) — set to `false` to keep the location saved but temporarily stop displaying it, without
running `delbillboard`.
- Global toggle: `ui.billboard` in `config.yml` (default `true`) disables every billboard on
every arena at once, e.g. for performance-constrained servers. every arena at once, e.g. for performance-constrained servers.
The entity is non-persistent (not saved to the world, so it never survives a server restart on Every billboard shows the same current target color in sync — they're just multiple vantage
its own — BlockParty re-creates it on demand) and is despawned automatically when the arena is points on the same information. Entities are non-persistent (not saved to the world, so they
disabled, deleted, or the plugin shuts down, so it never leaks entities. never survive a server restart on their own — BlockParty re-creates them on demand) and are all
despawned automatically when the arena is disabled, deleted, or the plugin shuts down, so
nothing leaks.
## Player usage ## Player usage
@@ -10,14 +10,16 @@ import org.joml.Vector3f;
import us.tss3.blockparty.BlockPartyPlugin; import us.tss3.blockparty.BlockPartyPlugin;
import us.tss3.blockparty.config.ArenaConfig; import us.tss3.blockparty.config.ArenaConfig;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.logging.Level; import java.util.logging.Level;
/** /**
* Owns an optional {@link BlockDisplay} entity that visually mirrors an arena's currently * Owns any number of named, optional {@link BlockDisplay} entities that visually mirror an
* selected target color. Purely cosmetic: fully optional (global toggle + per-arena * arena's currently selected target color. Purely cosmetic: fully optional (global toggle +
* toggle/location), and every method safely no-ops when disabled, unset, or the arena's * per-billboard toggle/location), and every method safely no-ops when disabled, unset, or the
* world isn't loaded. * arena's world isn't loaded.
*/ */
public class BillboardManager { public class BillboardManager {
@@ -25,75 +27,96 @@ public class BillboardManager {
private final BlockPartyPlugin plugin; private final BlockPartyPlugin plugin;
private final ArenaConfig config; private final ArenaConfig config;
private UUID entityId; /** billboard name -> live display entity id, only present while spawned. */
private final Map<String, UUID> entityIds = new HashMap<>();
public BillboardManager(BlockPartyPlugin plugin, ArenaConfig config) { public BillboardManager(BlockPartyPlugin plugin, ArenaConfig config) {
this.plugin = plugin; this.plugin = plugin;
this.config = config; this.config = config;
} }
private boolean isActive() { private boolean globallyActive() {
return plugin.getConfigManager().isBillboardEnabled() && config.hasBillboard() return plugin.getConfigManager().isBillboardEnabled() && config.hasAnyBillboards();
&& config.getBillboard().getWorld() != null;
} }
/** Shows (spawning the display entity if needed) the given material as the current target. */ /** Shows the given material as the current target on every enabled, valid billboard. */
public void show(Material material) { public void show(Material material) {
if (!isActive()) { if (!globallyActive()) {
return;
}
for (String name : config.getBillboards().keySet()) {
showOne(name, material);
}
}
private void showOne(String name, Material material) {
Location loc = config.getBillboard(name);
if (loc == null || loc.getWorld() == null || !config.isBillboardEnabled(name)) {
return; return;
} }
try { try {
BlockDisplay display = resolve(); BlockDisplay display = resolve(name);
if (display == null) { if (display == null) {
display = spawn(); display = spawn(name, loc);
} }
if (display != null) { if (display != null) {
display.setBlock(material.createBlockData()); display.setBlock(material.createBlockData());
} }
} catch (Exception ex) { } catch (Exception ex) {
plugin.getLogger().log(Level.WARNING, "Failed to update billboard for arena '" + config.getName() + "'", ex); plugin.getLogger().log(Level.WARNING, "Failed to update billboard '" + name
+ "' for arena '" + config.getName() + "'", ex);
} }
} }
/** Blanks the display (e.g. between matches) without destroying the entity. */ /** Blanks every spawned display (e.g. between matches) without destroying the entities. */
public void clear() { public void clear() {
BlockDisplay display = resolve(); for (String name : entityIds.keySet().toArray(new String[0])) {
if (display != null) { BlockDisplay display = resolve(name);
display.setBlock(Material.AIR.createBlockData()); if (display != null) {
display.setBlock(Material.AIR.createBlockData());
}
} }
} }
/** Fully removes the display entity. Safe to call even if nothing was ever spawned. */ /** Fully removes every display entity. Safe to call even if nothing was ever spawned. */
public void despawn() { public void despawn() {
BlockDisplay display = resolve(); for (String name : entityIds.keySet().toArray(new String[0])) {
BlockDisplay display = resolve(name);
if (display != null) {
display.remove();
}
entityIds.remove(name);
}
}
/** Removes a single named billboard's live entity (e.g. after deletion or relocation). */
public void despawnOne(String name) {
BlockDisplay display = resolve(name);
if (display != null) { if (display != null) {
display.remove(); display.remove();
} }
entityId = null; entityIds.remove(name);
} }
/** Forces the entity to be re-created at its (possibly updated) configured location next time it's shown. */ /** Forces a specific billboard to be re-created at its (possibly updated) location next show(). */
public void invalidate() { public void invalidate(String name) {
despawn(); despawnOne(name);
} }
private BlockDisplay resolve() { private BlockDisplay resolve(String name) {
if (entityId == null) { UUID id = entityIds.get(name);
if (id == null) {
return null; return null;
} }
Entity entity = plugin.getServer().getEntity(entityId); Entity entity = plugin.getServer().getEntity(id);
if (entity instanceof BlockDisplay display && !display.isDead()) { if (entity instanceof BlockDisplay display && !display.isDead()) {
return display; return display;
} }
entityId = null; entityIds.remove(name);
return null; return null;
} }
private BlockDisplay spawn() { private BlockDisplay spawn(String name, Location loc) {
Location loc = config.getBillboard();
if (loc == null || loc.getWorld() == null) {
return null;
}
BlockDisplay display = loc.getWorld().spawn(loc, BlockDisplay.class, bd -> { BlockDisplay display = loc.getWorld().spawn(loc, BlockDisplay.class, bd -> {
bd.setPersistent(false); bd.setPersistent(false);
bd.setGlowing(true); bd.setGlowing(true);
@@ -103,7 +126,7 @@ public class BillboardManager {
new Vector3f(1.5f, 1.5f, 1.5f), new Vector3f(1.5f, 1.5f, 1.5f),
NO_ROTATION)); NO_ROTATION));
}); });
entityId = display.getUniqueId(); entityIds.put(name, display.getUniqueId());
return display; return display;
} }
} }
@@ -48,6 +48,7 @@ public class BlockPartyCommand implements CommandExecutor, TabCompleter {
case "setspectator" -> setSpectator(sender, args); case "setspectator" -> setSpectator(sender, args);
case "setbillboard" -> setBillboard(sender, args); case "setbillboard" -> setBillboard(sender, args);
case "delbillboard" -> delBillboard(sender, args); case "delbillboard" -> delBillboard(sender, args);
case "billboards" -> listBillboards(sender, args);
case "pos1" -> pos1(sender, args); case "pos1" -> pos1(sender, args);
case "pos2" -> pos2(sender, args); case "pos2" -> pos2(sender, args);
case "setfloor" -> setFloor(sender, args); case "setfloor" -> setFloor(sender, args);
@@ -78,8 +79,9 @@ public class BlockPartyCommand implements CommandExecutor, TabCompleter {
"/blockparty setlobby <arena>", "/blockparty setlobby <arena>",
"/blockparty setspawn <arena>", "/blockparty setspawn <arena>",
"/blockparty setspectator <arena>", "/blockparty setspectator <arena>",
"/blockparty setbillboard <arena>", "/blockparty setbillboard <arena> [name]",
"/blockparty delbillboard <arena>", "/blockparty delbillboard <arena> [name]",
"/blockparty billboards <arena>",
"/blockparty pos1 <arena>", "/blockparty pos1 <arena>",
"/blockparty pos2 <arena>", "/blockparty pos2 <arena>",
"/blockparty setfloor <arena>", "/blockparty setfloor <arena>",
@@ -198,25 +200,56 @@ public class BlockPartyCommand implements CommandExecutor, TabCompleter {
private void setBillboard(CommandSender sender, String[] args) { private void setBillboard(CommandSender sender, String[] args) {
if (!requireAdmin(sender, "blockparty.admin.setup") || !requirePlayer(sender)) return; if (!requireAdmin(sender, "blockparty.admin.setup") || !requirePlayer(sender)) return;
String billboardName = args.length > 2 ? args[2] : "default";
withArena(sender, args, arena -> { withArena(sender, args, arena -> {
arena.getConfig().setBillboard(((Player) sender).getLocation()); arena.getConfig().setBillboard(billboardName, ((Player) sender).getLocation());
arena.getConfig().setBillboardEnabled(true); arena.getConfig().setBillboardEnabled(billboardName, true);
arena.getBillboardManager().invalidate(); arena.getBillboardManager().invalidate(billboardName);
plugin.getArenaManager().save(arena); plugin.getArenaManager().save(arena);
sender.sendMessage(plugin.getMessages().get("admin.billboard-set", Map.of("arena", arena.getConfig().getName()))); sender.sendMessage(plugin.getMessages().get("admin.billboard-set",
Map.of("arena", arena.getConfig().getName(), "name", billboardName)));
}); });
} }
private void delBillboard(CommandSender sender, String[] args) { private void delBillboard(CommandSender sender, String[] args) {
if (!requireAdmin(sender, "blockparty.admin.setup")) return; if (!requireAdmin(sender, "blockparty.admin.setup")) return;
String billboardName = args.length > 2 ? args[2] : "default";
withArena(sender, args, arena -> { withArena(sender, args, arena -> {
arena.getBillboardManager().despawn(); if (!arena.getConfig().hasBillboard(billboardName)) {
arena.getConfig().setBillboard(null); sender.sendMessage(plugin.getMessages().get("admin.billboard-unknown",
Map.of("arena", arena.getConfig().getName(), "name", billboardName)));
return;
}
arena.getBillboardManager().despawnOne(billboardName);
arena.getConfig().removeBillboard(billboardName);
plugin.getArenaManager().save(arena); plugin.getArenaManager().save(arena);
sender.sendMessage(plugin.getMessages().get("admin.billboard-removed", Map.of("arena", arena.getConfig().getName()))); sender.sendMessage(plugin.getMessages().get("admin.billboard-removed",
Map.of("arena", arena.getConfig().getName(), "name", billboardName)));
}); });
} }
private void listBillboards(CommandSender sender, String[] args) {
String name = argOrCurrentArenaless(args);
if (name == null) {
sender.sendMessage("Usage: /blockparty billboards <arena>");
return;
}
var opt = plugin.getArenaManager().get(name);
if (opt.isEmpty()) {
sender.sendMessage(plugin.getMessages().get("errors.unknown-arena", Map.of("arena", name)));
return;
}
ArenaConfig cfg = opt.get().getConfig();
sender.sendMessage("§6=== Billboards: " + cfg.getName() + " ===");
if (cfg.getBillboards().isEmpty()) {
sender.sendMessage("§7(none set)");
return;
}
for (String bbName : cfg.getBillboards().keySet()) {
sender.sendMessage("§7- §f" + bbName + " §7(enabled: " + cfg.isBillboardEnabled(bbName) + ")");
}
}
private void pos1(CommandSender sender, String[] args) { private void pos1(CommandSender sender, String[] args) {
if (!requireAdmin(sender, "blockparty.admin.setup") || !requirePlayer(sender)) return; if (!requireAdmin(sender, "blockparty.admin.setup") || !requirePlayer(sender)) return;
withArena(sender, args, arena -> { withArena(sender, args, arena -> {
@@ -335,7 +368,7 @@ public class BlockPartyCommand implements CommandExecutor, TabCompleter {
sender.sendMessage("§7Lobby set: §f" + (cfg.getLobby() != null)); sender.sendMessage("§7Lobby set: §f" + (cfg.getLobby() != null));
sender.sendMessage("§7Spawn set: §f" + (cfg.getSpawn() != null)); sender.sendMessage("§7Spawn set: §f" + (cfg.getSpawn() != null));
sender.sendMessage("§7Spectator set: §f" + (cfg.getSpectator() != null)); sender.sendMessage("§7Spectator set: §f" + (cfg.getSpectator() != null));
sender.sendMessage("§7Billboard set: §f" + (cfg.getBillboard() != null) + (cfg.getBillboard() != null ? " (enabled: " + cfg.isBillboardEnabled() + ")" : "")); sender.sendMessage("§7Billboards: §f" + cfg.getBillboards().size() + " (see /bp billboards " + cfg.getName() + ")");
sender.sendMessage("§7Floor region set: §f" + cfg.hasFloorRegion()); sender.sendMessage("§7Floor region set: §f" + cfg.hasFloorRegion());
sender.sendMessage("§7Floor generated: §f" + cfg.hasGeneratedLayout()); sender.sendMessage("§7Floor generated: §f" + cfg.hasGeneratedLayout());
sender.sendMessage("§7Floor materials: §f" + cfg.getFloorMaterials().size()); sender.sendMessage("§7Floor materials: §f" + cfg.getFloorMaterials().size());
@@ -453,7 +486,7 @@ public class BlockPartyCommand implements CommandExecutor, TabCompleter {
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) { public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
if (args.length == 1) { if (args.length == 1) {
return List.of("help", "join", "leave", "arenas", "stats", "create", "delete", "enable", "disable", return List.of("help", "join", "leave", "arenas", "stats", "create", "delete", "enable", "disable",
"setlobby", "setspawn", "setspectator", "setbillboard", "delbillboard", "pos1", "pos2", "setfloor", "generate", "info", "list", "reload") "setlobby", "setspawn", "setspectator", "setbillboard", "delbillboard", "billboards", "pos1", "pos2", "setfloor", "generate", "info", "list", "reload")
.stream().filter(s -> s.startsWith(args[0].toLowerCase())).collect(Collectors.toList()); .stream().filter(s -> s.startsWith(args[0].toLowerCase())).collect(Collectors.toList());
} }
if (args.length == 2) { if (args.length == 2) {
@@ -5,7 +5,12 @@ import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.World;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
/** Mutable POJO describing a single arena's configuration, mirrors arenas/<name>.yml. */ /** Mutable POJO describing a single arena's configuration, mirrors arenas/<name>.yml. */
public class ArenaConfig { public class ArenaConfig {
@@ -15,8 +20,10 @@ public class ArenaConfig {
private Location lobby; private Location lobby;
private Location spawn; private Location spawn;
private Location spectator; private Location spectator;
private Location billboard; /** Named billboards: displays that mirror the current round's target color. Any number
private boolean billboardEnabled = true; * may be set (e.g. one per side of the arena), each independently enabled/disabled. */
private final Map<String, Location> billboards = new LinkedHashMap<>();
private final Set<String> disabledBillboards = new HashSet<>();
private int[] pos1; // x,y,z block coords private int[] pos1; // x,y,z block coords
private int[] pos2; private int[] pos2;
@@ -86,24 +93,42 @@ public class ArenaConfig {
this.spectator = spectator; this.spectator = spectator;
} }
public Location getBillboard() { /** All configured billboards by name, in insertion order. */
return billboard; public Map<String, Location> getBillboards() {
return Collections.unmodifiableMap(billboards);
} }
public void setBillboard(Location billboard) { public Location getBillboard(String name) {
this.billboard = billboard; return billboards.get(name);
} }
public boolean isBillboardEnabled() { public void setBillboard(String name, Location location) {
return billboardEnabled; billboards.put(name, location);
} }
public void setBillboardEnabled(boolean billboardEnabled) { public void removeBillboard(String name) {
this.billboardEnabled = billboardEnabled; billboards.remove(name);
disabledBillboards.remove(name);
} }
public boolean hasBillboard() { public boolean hasBillboard(String name) {
return billboard != null && billboardEnabled; return billboards.containsKey(name);
}
public boolean hasAnyBillboards() {
return !billboards.isEmpty();
}
public boolean isBillboardEnabled(String name) {
return !disabledBillboards.contains(name);
}
public void setBillboardEnabled(String name, boolean enabled) {
if (enabled) {
disabledBillboards.remove(name);
} else {
disabledBillboards.add(name);
}
} }
public int[] getPos1() { public int[] getPos1() {
@@ -1,7 +1,9 @@
package us.tss3.blockparty.config; package us.tss3.blockparty.config;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import us.tss3.blockparty.logic.ArenaConfigValidator; import us.tss3.blockparty.logic.ArenaConfigValidator;
@@ -57,8 +59,21 @@ public class ArenaConfigLoader {
cfg.setLobby(LocationUtil.fromSection(yml.getConfigurationSection("lobby"))); cfg.setLobby(LocationUtil.fromSection(yml.getConfigurationSection("lobby")));
cfg.setSpawn(LocationUtil.fromSection(yml.getConfigurationSection("spawn"))); cfg.setSpawn(LocationUtil.fromSection(yml.getConfigurationSection("spawn")));
cfg.setSpectator(LocationUtil.fromSection(yml.getConfigurationSection("spectator"))); cfg.setSpectator(LocationUtil.fromSection(yml.getConfigurationSection("spectator")));
cfg.setBillboard(LocationUtil.fromSection(yml.getConfigurationSection("billboard"))); ConfigurationSection billboardsSection = yml.getConfigurationSection("billboards");
cfg.setBillboardEnabled(yml.getBoolean("billboard-enabled", true)); if (billboardsSection != null) {
for (String bbName : billboardsSection.getKeys(false)) {
ConfigurationSection bbSection = billboardsSection.getConfigurationSection(bbName);
if (bbSection == null) {
continue;
}
Location loc = LocationUtil.fromSection(bbSection.getConfigurationSection("location"));
if (loc == null) {
continue;
}
cfg.setBillboard(bbName, loc);
cfg.setBillboardEnabled(bbName, bbSection.getBoolean("enabled", true));
}
}
if (yml.contains("pos1")) { if (yml.contains("pos1")) {
cfg.setPos1(new int[]{yml.getInt("pos1.x"), yml.getInt("pos1.y"), yml.getInt("pos1.z")}); cfg.setPos1(new int[]{yml.getInt("pos1.x"), yml.getInt("pos1.y"), yml.getInt("pos1.z")});
} }
@@ -108,10 +123,14 @@ public class ArenaConfigLoader {
if (cfg.getSpectator() != null) { if (cfg.getSpectator() != null) {
LocationUtil.toSection(yml.createSection("spectator"), cfg.getSpectator()); LocationUtil.toSection(yml.createSection("spectator"), cfg.getSpectator());
} }
if (cfg.getBillboard() != null) { if (!cfg.getBillboards().isEmpty()) {
LocationUtil.toSection(yml.createSection("billboard"), cfg.getBillboard()); ConfigurationSection billboardsSection = yml.createSection("billboards");
for (var entry : cfg.getBillboards().entrySet()) {
ConfigurationSection bbSection = billboardsSection.createSection(entry.getKey());
LocationUtil.toSection(bbSection.createSection("location"), entry.getValue());
bbSection.set("enabled", cfg.isBillboardEnabled(entry.getKey()));
}
} }
yml.set("billboard-enabled", cfg.isBillboardEnabled());
if (cfg.getPos1() != null) { if (cfg.getPos1() != null) {
yml.set("pos1.x", cfg.getPos1()[0]); yml.set("pos1.x", cfg.getPos1()[0]);
yml.set("pos1.y", cfg.getPos1()[1]); yml.set("pos1.y", cfg.getPos1()[1]);
+3 -2
View File
@@ -20,8 +20,9 @@ admin:
lobby-set: "<green>Lobby set for '%arena%'.</green>" lobby-set: "<green>Lobby set for '%arena%'.</green>"
spawn-set: "<green>Spawn set for '%arena%'.</green>" spawn-set: "<green>Spawn set for '%arena%'.</green>"
spectator-set: "<green>Spectator location set for '%arena%'.</green>" spectator-set: "<green>Spectator location set for '%arena%'.</green>"
billboard-set: "<green>Billboard set for '%arena%'. It will display the target color each round.</green>" billboard-set: "<green>Billboard '%name%' set for '%arena%'. It will display the target color each round.</green>"
billboard-removed: "<green>Billboard removed for '%arena%'.</green>" billboard-removed: "<green>Billboard '%name%' removed for '%arena%'.</green>"
billboard-unknown: "<red>No billboard named '%name%' exists for '%arena%'.</red>"
pos1-set: "<green>Position 1 set for '%arena%'.</green>" pos1-set: "<green>Position 1 set for '%arena%'.</green>"
pos2-set: "<green>Position 2 set for '%arena%'.</green>" pos2-set: "<green>Position 2 set for '%arena%'.</green>"
pos1-set-we: "<green>Position 1 set for '%arena%' from your WorldEdit selection.</green>" pos1-set-we: "<green>Position 1 set for '%arena%' from your WorldEdit selection.</green>"