From f0d3a202834dc0ac236eda3b209d585920d4afcd Mon Sep 17 00:00:00 2001 From: akastijn Date: Mon, 22 Jun 2026 02:22:02 +0200 Subject: [PATCH] Add `/hg nextphase` and `/hg end` commands to manage game phases and rounds --- .../hunger_games/commands/BaseCommand.java | 2 + .../commands/subcommands/EndRound.java | 37 +++++++++++++++++++ .../commands/subcommands/NextPhase.java | 37 +++++++++++++++++++ .../alttd/hunger_games/config/Messages.java | 8 ++++ .../alttd/hunger_games/services/Round.java | 22 ++++++++++- .../hunger_games/services/RoundService.java | 1 + 6 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/alttd/hunger_games/commands/subcommands/EndRound.java create mode 100644 src/main/java/com/alttd/hunger_games/commands/subcommands/NextPhase.java 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 a908078..311dc72 100644 --- a/src/main/java/com/alttd/hunger_games/commands/BaseCommand.java +++ b/src/main/java/com/alttd/hunger_games/commands/BaseCommand.java @@ -39,6 +39,8 @@ public class BaseCommand implements CommandExecutor, TabExecutor { new RoundState(roundService), new Register(playerService), new StartRound(round, roundService), + new NextPhase(round), + new EndRound(round), new Stuck(main), new Stats(statService) )); diff --git a/src/main/java/com/alttd/hunger_games/commands/subcommands/EndRound.java b/src/main/java/com/alttd/hunger_games/commands/subcommands/EndRound.java new file mode 100644 index 0000000..7ec934d --- /dev/null +++ b/src/main/java/com/alttd/hunger_games/commands/subcommands/EndRound.java @@ -0,0 +1,37 @@ +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.services.Round; +import lombok.RequiredArgsConstructor; +import org.bukkit.command.CommandSender; + +import java.util.List; + +@RequiredArgsConstructor +public class EndRound extends SubCommand { + + private final Round round; + + @Override + public boolean onCommand(CommandSender commandSender, String[] args) { + round.endRound(); + commandSender.sendRichMessage("Ending the round."); + return true; + } + + @Override + public String getName() { + return "end"; + } + + @Override + public List getTabComplete(CommandSender commandSender, String[] args) { + return List.of(); + } + + @Override + public String getHelpMessage() { + return Messages.HELP.END_ROUND; + } +} diff --git a/src/main/java/com/alttd/hunger_games/commands/subcommands/NextPhase.java b/src/main/java/com/alttd/hunger_games/commands/subcommands/NextPhase.java new file mode 100644 index 0000000..cbb9ac8 --- /dev/null +++ b/src/main/java/com/alttd/hunger_games/commands/subcommands/NextPhase.java @@ -0,0 +1,37 @@ +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.services.Round; +import lombok.RequiredArgsConstructor; +import org.bukkit.command.CommandSender; + +import java.util.List; + +@RequiredArgsConstructor +public class NextPhase extends SubCommand { + + private final Round round; + + @Override + public boolean onCommand(CommandSender commandSender, String[] args) { + round.forceNextPhase(); + commandSender.sendRichMessage("Skipping to the next phase/stage."); + return true; + } + + @Override + public String getName() { + return "nextphase"; + } + + @Override + public List getTabComplete(CommandSender commandSender, String[] args) { + return List.of(); + } + + @Override + public String getHelpMessage() { + return Messages.HELP.NEXT_PHASE; + } +} 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 69fa1f2..798c68c 100644 --- a/src/main/java/com/alttd/hunger_games/config/Messages.java +++ b/src/main/java/com/alttd/hunger_games/config/Messages.java @@ -29,9 +29,11 @@ public class Messages extends AbstractConfig { public static String ROUND_STATE = "Show the current round state: /hg roundstate"; public static String REGISTER = "Register a player for the game: /hg register "; public static String START_ROUND = "Start the game: /hg start"; + public static String NEXT_PHASE = "Skip to the next phase/stage: /hg nextphase"; public static String RELOAD = "Reload config and messages: /hg reload"; public static String STUCK = "Teleport to safety if stuck: /hg stuck"; public static String STATS = "Show player stats: /hg stats [player]"; + public static String END_ROUND = "End the game: /hg end"; @SuppressWarnings("unused") private static void load() { @@ -40,9 +42,11 @@ public class Messages extends AbstractConfig { ROUND_STATE = config.getString(prefix, "round-state", ROUND_STATE); REGISTER = config.getString(prefix, "register", REGISTER); START_ROUND = config.getString(prefix, "start", START_ROUND); + NEXT_PHASE = config.getString(prefix, "next-phase", NEXT_PHASE); RELOAD = config.getString(prefix, "reload", RELOAD); STUCK = config.getString(prefix, "stuck", STUCK); STATS = config.getString(prefix, "stats", STATS); + END_ROUND = config.getString(prefix, "end-round", END_ROUND); } } @@ -89,6 +93,8 @@ public class Messages extends AbstractConfig { public static String BOSSBAR_KILL_PHASE = "Border shrink in "; public static String BOSSBAR_FINALE = "Remaining Players: "; + public static String NEXT_STATE = "Starting !"; + @SuppressWarnings("unused") private static void load() { WARMUP = config.getString(prefix, "warmup", WARMUP); @@ -102,6 +108,8 @@ public class Messages extends AbstractConfig { BOSSBAR_SAFE_PHASE = config.getString(prefix, "bossbar-safe-phase", BOSSBAR_SAFE_PHASE); BOSSBAR_KILL_PHASE = config.getString(prefix, "bossbar-kill-phase", BOSSBAR_KILL_PHASE); BOSSBAR_FINALE = config.getString(prefix, "bossbar-finale", BOSSBAR_FINALE); + + NEXT_STATE = config.getString(prefix, "next-state", NEXT_STATE); } } 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 547cced..6ef9c48 100644 --- a/src/main/java/com/alttd/hunger_games/services/Round.java +++ b/src/main/java/com/alttd/hunger_games/services/Round.java @@ -4,6 +4,7 @@ import com.alttd.hunger_games.config.Config; import com.alttd.hunger_games.data_objects.GameStage; import com.alttd.hunger_games.data_objects.ROUND_STATE; import com.alttd.hunger_games.game.GameStageHandler; +import lombok.Setter; import java.time.Duration; import java.time.Instant; @@ -22,6 +23,8 @@ public class Round { private ROUND_STATE roundState = ROUND_STATE.PLAYER_REGISTRATION; private ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); private ScheduledFuture countdownFuture = null; + private Runnable onEnd = null; + @Setter private BossBarService bossBarService; private Round() { @@ -92,6 +95,7 @@ public class Round { if (countdownFuture != null) { countdownFuture.cancel(true); } + this.onEnd = onEnd; final Instant endTime = Instant.now().plus(duration); countdownFuture = scheduledExecutorService.scheduleAtFixedRate(() -> { @@ -121,7 +125,21 @@ public class Round { }); } - public void setBossBarService(BossBarService bossBarService) { - this.bossBarService = bossBarService; + public void forceNextPhase() { + if (countdownFuture == null || onEnd == null) { + return; + } + countdownFuture.cancel(true); + if (roundState.equals(ROUND_STATE.KILL_PHASE)) { + onEnd.run(); + } else { + nextStage(); + if (roundState.equals(ROUND_STATE.SAFE_PHASE)) { + scheduleNextStage(0); + } else if (roundState.equals(ROUND_STATE.KILL_PHASE)) { + scheduleNextStage(0); + } + } } + } diff --git a/src/main/java/com/alttd/hunger_games/services/RoundService.java b/src/main/java/com/alttd/hunger_games/services/RoundService.java index c98d7aa..2de720b 100644 --- a/src/main/java/com/alttd/hunger_games/services/RoundService.java +++ b/src/main/java/com/alttd/hunger_games/services/RoundService.java @@ -109,6 +109,7 @@ public class RoundService implements RoundListener { if (roundState.equals(ROUND_STATE.COUNTDOWN)) { startFreeze(); } + Bukkit.broadcast(MiniMessage.miniMessage().deserialize(Messages.GAME.NEXT_STATE, Placeholder.parsed("state", roundState.getHumandReadableName()))); } private void stopFreeze() {