From 02228f570d4e80f98df6be7b065498863c5afe01 Mon Sep 17 00:00:00 2001 From: akastijn Date: Sun, 31 May 2026 16:40:16 +0200 Subject: [PATCH] Add initial border size configuration, round warmup messages, and start-round validation logic --- .gitignore | 5 +- .../hunger_games/commands/BaseCommand.java | 17 +++---- .../commands/subcommands/StartRound.java | 12 ++++- .../hunger_games/config/AbstractConfig.java | 3 +- .../com/alttd/hunger_games/config/Config.java | 2 + .../alttd/hunger_games/config/Messages.java | 25 ++++++++++ .../hunger_games/game/GameStageHandler.java | 47 +++++++++++++++++-- .../alttd/hunger_games/services/Round.java | 2 +- 8 files changed, 98 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 1fac4d5..4e26ea0 100644 --- a/.gitignore +++ b/.gitignore @@ -40,4 +40,7 @@ bin/ .vscode/ ### Mac OS ### -.DS_Store \ No newline at end of file +.DS_Store + +### Ignore bat files ### +*bat diff --git a/src/main/java/com/alttd/hunger_games/commands/BaseCommand.java b/src/main/java/com/alttd/hunger_games/commands/BaseCommand.java index ae47e52..aff77dc 100644 --- a/src/main/java/com/alttd/hunger_games/commands/BaseCommand.java +++ b/src/main/java/com/alttd/hunger_games/commands/BaseCommand.java @@ -20,7 +20,8 @@ import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; -@Slf4j @Getter +@Slf4j +@Getter public class BaseCommand implements CommandExecutor, TabExecutor { private final List subCommands; @@ -39,8 +40,8 @@ public class BaseCommand implements CommandExecutor, TabExecutor { new Reload(main), new RoundState(roundService), new Register(playerService), - new StartRound(round) - )); + new StartRound(round, roundService) + )); } @Override @@ -76,11 +77,11 @@ public class BaseCommand implements CommandExecutor, TabExecutor { if (args.length <= 1) { res.addAll(subCommands.stream() - .filter(subCommand -> commandSender.hasPermission(subCommand.getPermission())) - .map(SubCommand::getName) - .filter(name -> args.length == 0 || name.startsWith(args[0])) - .toList() - ); + .filter(subCommand -> commandSender.hasPermission(subCommand.getPermission())) + .map(SubCommand::getName) + .filter(name -> args.length == 0 || name.startsWith(args[0])) + .toList() + ); } else { SubCommand subCommand = getSubCommand(args[0]); if (subCommand != null && commandSender.hasPermission(subCommand.getPermission())) { diff --git a/src/main/java/com/alttd/hunger_games/commands/subcommands/StartRound.java b/src/main/java/com/alttd/hunger_games/commands/subcommands/StartRound.java index 17fdb69..549f79c 100644 --- a/src/main/java/com/alttd/hunger_games/commands/subcommands/StartRound.java +++ b/src/main/java/com/alttd/hunger_games/commands/subcommands/StartRound.java @@ -2,8 +2,11 @@ package com.alttd.hunger_games.commands.subcommands; import com.alttd.hunger_games.commands.SubCommand; import com.alttd.hunger_games.config.Messages; +import com.alttd.hunger_games.data_objects.ROUND_STATE; import com.alttd.hunger_games.services.Round; +import com.alttd.hunger_games.services.RoundService; import lombok.RequiredArgsConstructor; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import org.bukkit.command.CommandSender; import java.util.List; @@ -12,10 +15,17 @@ import java.util.List; public class StartRound extends SubCommand { private final Round round; + private final RoundService roundService; @Override public boolean onCommand(CommandSender commandSender, String[] args) { - round.startRound(); + ROUND_STATE roundState = roundService.getRoundState(); + if (roundState == ROUND_STATE.PLAYER_REGISTRATION) { + round.startRound(); + } else { + commandSender.sendRichMessage(Messages.START_ROUND.CAN_NOT_START_ROUND, + Placeholder.parsed("round_state", roundState.getHumandReadableName())); + } return true; } diff --git a/src/main/java/com/alttd/hunger_games/config/AbstractConfig.java b/src/main/java/com/alttd/hunger_games/config/AbstractConfig.java index b67201e..f123358 100644 --- a/src/main/java/com/alttd/hunger_games/config/AbstractConfig.java +++ b/src/main/java/com/alttd/hunger_games/config/AbstractConfig.java @@ -123,7 +123,8 @@ abstract class AbstractConfig { String rootPath = prefix + path + "."; if (contains(rootPath, "world") || contains(rootPath, path + "x") || contains(rootPath, path + "y") || contains(rootPath, path + "z")) { - log.error("Invalid location configuration for {}", path); + ConfigurationSection configurationSection = getConfigurationSection(prefix + path); + log.error("Invalid location configuration for:\n\t{}", configurationSection.getKeys(false).stream().map(key -> rootPath + key).collect(Collectors.joining("\n\t"))); return Optional.empty(); } diff --git a/src/main/java/com/alttd/hunger_games/config/Config.java b/src/main/java/com/alttd/hunger_games/config/Config.java index d19e28b..2a9f086 100644 --- a/src/main/java/com/alttd/hunger_games/config/Config.java +++ b/src/main/java/com/alttd/hunger_games/config/Config.java @@ -45,6 +45,7 @@ public class Config extends AbstractConfig { private static final String prefix = "round."; public static Duration COUNTDOWN = Duration.ofSeconds(10); + public static int INITIAL_BORDER_SIZE = 5000; public static List STAGES = List.of( GameStage.builder().duration(Duration.ofMinutes(5)).worldBorderSize(1000).build(), GameStage.builder().duration(Duration.ofMinutes(5)).worldBorderSize(750).build(), @@ -55,6 +56,7 @@ public class Config extends AbstractConfig { private static void load() { int countdownSeconds = config.getInt(prefix, "countdown-seconds", Math.toIntExact(COUNTDOWN.toSeconds())); COUNTDOWN = Duration.ofSeconds(countdownSeconds); + INITIAL_BORDER_SIZE = config.getInt(prefix, "initial-border-size", INITIAL_BORDER_SIZE); ConfigurationSection configurationSection = config.getConfigurationSection(prefix + "stages"); if (configurationSection == null) { diff --git a/src/main/java/com/alttd/hunger_games/config/Messages.java b/src/main/java/com/alttd/hunger_games/config/Messages.java index fc93ce2..40f28c6 100644 --- a/src/main/java/com/alttd/hunger_games/config/Messages.java +++ b/src/main/java/com/alttd/hunger_games/config/Messages.java @@ -70,6 +70,21 @@ public class Messages extends AbstractConfig { } } + public static class GAME { + private static final String prefix = "game."; + + public static String WARMUP = "The Hunger Game is starting soon! Get ready!"; + public static String STARTED = "The Hunger Game has begun! Good luck!"; + public static String BORDER_SHRINK = "The border is shrinking to blocks!"; + + @SuppressWarnings("unused") + private static void load() { + WARMUP = config.getString(prefix, "warmup", WARMUP); + STARTED = config.getString(prefix, "started", STARTED); + BORDER_SHRINK = config.getString(prefix, "border-shrink", BORDER_SHRINK); + } + } + public static class RECONNECT { private static final String prefix = "reconnect."; @@ -101,4 +116,14 @@ public class Messages extends AbstractConfig { GAME_RUNNING = config.getString(prefix, "game-running", GAME_RUNNING); } } + + public static class START_ROUND { + private static final String prefix = "start-round."; + public static String CAN_NOT_START_ROUND = "The round can not be started because the current state is ."; + + @SuppressWarnings("unused") + private static void load() { + CAN_NOT_START_ROUND = config.getString(prefix, "can-not-start", CAN_NOT_START_ROUND); + } + } } diff --git a/src/main/java/com/alttd/hunger_games/game/GameStageHandler.java b/src/main/java/com/alttd/hunger_games/game/GameStageHandler.java index 80b1d31..34e7a76 100644 --- a/src/main/java/com/alttd/hunger_games/game/GameStageHandler.java +++ b/src/main/java/com/alttd/hunger_games/game/GameStageHandler.java @@ -1,19 +1,60 @@ package com.alttd.hunger_games.game; +import com.alttd.hunger_games.config.Config; +import com.alttd.hunger_games.config.Messages; import lombok.experimental.UtilityClass; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.WorldBorder; + +import java.util.Optional; @UtilityClass public class GameStageHandler { + private static final int BORDER_TRANSITION_SECONDS = 10; + public static void handleStageChange(int worldBorderSize) { - //TODO change world border size and handle stage change + World world = getWorld().orElseThrow(() -> new IllegalStateException("No worlds available during state change,")); + + WorldBorder border = world.getWorldBorder(); + border.setSize(worldBorderSize, BORDER_TRANSITION_SECONDS); + + String message = Messages.GAME.BORDER_SHRINK + .replace("", String.valueOf(worldBorderSize)); + broadcast(message); } public static void handleCountdownEnd() { - //TODO free players and handle stage change + broadcast(Messages.GAME.STARTED); } public static void handleWarmup() { - //TODO tp players to start area etc (might be handled by state change already, so maybe just messages) + Location center = Config.DESTINATION.START_CENTER; + if (center == null || center.getWorld() == null) { + throw new IllegalStateException("Start center is not set during warmup."); + } + + WorldBorder border = center.getWorld().getWorldBorder(); + border.setCenter(center.getX(), center.getZ()); + border.setSize(Config.ROUND.INITIAL_BORDER_SIZE); + + broadcast(Messages.GAME.WARMUP); + } + + private static Optional getWorld() { + Location center = Config.DESTINATION.START_CENTER; + if (center != null && center.getWorld() != null) { + return Optional.ofNullable(center.getWorld()); + } + return Bukkit.getWorlds().isEmpty() ? Optional.empty() : Optional.of(Bukkit.getWorlds().getFirst()); + } + + private static void broadcast(String message) { + Component component = MiniMessage.miniMessage().deserialize(message); + Bukkit.broadcast(component); } } diff --git a/src/main/java/com/alttd/hunger_games/services/Round.java b/src/main/java/com/alttd/hunger_games/services/Round.java index 9040c29..c41bc94 100644 --- a/src/main/java/com/alttd/hunger_games/services/Round.java +++ b/src/main/java/com/alttd/hunger_games/services/Round.java @@ -58,7 +58,7 @@ public class Round { } public void startRound() { - if (roundState.equals(ROUND_STATE.PLAYER_REGISTRATION)) { + if (!roundState.equals(ROUND_STATE.PLAYER_REGISTRATION)) { throw new IllegalStateException("Round can not be started before player registration."); } roundState = ROUND_STATE.COUNTDOWN;