Add /hg nextphase and /hg end commands to manage game phases and rounds

This commit is contained in:
akastijn 2026-06-22 02:22:02 +02:00
parent 233cffd2df
commit f0d3a20283
6 changed files with 105 additions and 2 deletions

View File

@ -39,6 +39,8 @@ public class BaseCommand implements CommandExecutor, TabExecutor {
new RoundState(roundService), new RoundState(roundService),
new Register(playerService), new Register(playerService),
new StartRound(round, roundService), new StartRound(round, roundService),
new NextPhase(round),
new EndRound(round),
new Stuck(main), new Stuck(main),
new Stats(statService) new Stats(statService)
)); ));

View File

@ -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("<green>Ending the round.</green>");
return true;
}
@Override
public String getName() {
return "end";
}
@Override
public List<String> getTabComplete(CommandSender commandSender, String[] args) {
return List.of();
}
@Override
public String getHelpMessage() {
return Messages.HELP.END_ROUND;
}
}

View File

@ -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("<green>Skipping to the next phase/stage.</green>");
return true;
}
@Override
public String getName() {
return "nextphase";
}
@Override
public List<String> getTabComplete(CommandSender commandSender, String[] args) {
return List.of();
}
@Override
public String getHelpMessage() {
return Messages.HELP.NEXT_PHASE;
}
}

View File

@ -29,9 +29,11 @@ public class Messages extends AbstractConfig {
public static String ROUND_STATE = "<green>Show the current round state: <gold>/hg roundstate</gold></green>"; public static String ROUND_STATE = "<green>Show the current round state: <gold>/hg roundstate</gold></green>";
public static String REGISTER = "<green>Register a player for the game: <gold>/hg register <player></gold></green>"; public static String REGISTER = "<green>Register a player for the game: <gold>/hg register <player></gold></green>";
public static String START_ROUND = "<green>Start the game: <gold>/hg start</gold></green>"; public static String START_ROUND = "<green>Start the game: <gold>/hg start</gold></green>";
public static String NEXT_PHASE = "<green>Skip to the next phase/stage: <gold>/hg nextphase</gold></green>";
public static String RELOAD = "<green>Reload config and messages: <gold>/hg reload</gold></green>"; public static String RELOAD = "<green>Reload config and messages: <gold>/hg reload</gold></green>";
public static String STUCK = "<green>Teleport to safety if stuck: <gold>/hg stuck</gold></green>"; public static String STUCK = "<green>Teleport to safety if stuck: <gold>/hg stuck</gold></green>";
public static String STATS = "<green>Show player stats: <gold>/hg stats [player]</gold></green>"; public static String STATS = "<green>Show player stats: <gold>/hg stats [player]</gold></green>";
public static String END_ROUND = "<green>End the game: <gold>/hg end</gold></green>";
@SuppressWarnings("unused") @SuppressWarnings("unused")
private static void load() { private static void load() {
@ -40,9 +42,11 @@ public class Messages extends AbstractConfig {
ROUND_STATE = config.getString(prefix, "round-state", ROUND_STATE); ROUND_STATE = config.getString(prefix, "round-state", ROUND_STATE);
REGISTER = config.getString(prefix, "register", REGISTER); REGISTER = config.getString(prefix, "register", REGISTER);
START_ROUND = config.getString(prefix, "start", START_ROUND); START_ROUND = config.getString(prefix, "start", START_ROUND);
NEXT_PHASE = config.getString(prefix, "next-phase", NEXT_PHASE);
RELOAD = config.getString(prefix, "reload", RELOAD); RELOAD = config.getString(prefix, "reload", RELOAD);
STUCK = config.getString(prefix, "stuck", STUCK); STUCK = config.getString(prefix, "stuck", STUCK);
STATS = config.getString(prefix, "stats", STATS); 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 = "<red>Border shrink in <time></red>"; public static String BOSSBAR_KILL_PHASE = "<red>Border shrink in <time></red>";
public static String BOSSBAR_FINALE = "<gold>Remaining Players: <remaining></gold>"; public static String BOSSBAR_FINALE = "<gold>Remaining Players: <remaining></gold>";
public static String NEXT_STATE = "<gold>Starting <round>!</gold>";
@SuppressWarnings("unused") @SuppressWarnings("unused")
private static void load() { private static void load() {
WARMUP = config.getString(prefix, "warmup", WARMUP); 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_SAFE_PHASE = config.getString(prefix, "bossbar-safe-phase", BOSSBAR_SAFE_PHASE);
BOSSBAR_KILL_PHASE = config.getString(prefix, "bossbar-kill-phase", BOSSBAR_KILL_PHASE); BOSSBAR_KILL_PHASE = config.getString(prefix, "bossbar-kill-phase", BOSSBAR_KILL_PHASE);
BOSSBAR_FINALE = config.getString(prefix, "bossbar-finale", BOSSBAR_FINALE); BOSSBAR_FINALE = config.getString(prefix, "bossbar-finale", BOSSBAR_FINALE);
NEXT_STATE = config.getString(prefix, "next-state", NEXT_STATE);
} }
} }

View File

@ -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.GameStage;
import com.alttd.hunger_games.data_objects.ROUND_STATE; import com.alttd.hunger_games.data_objects.ROUND_STATE;
import com.alttd.hunger_games.game.GameStageHandler; import com.alttd.hunger_games.game.GameStageHandler;
import lombok.Setter;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
@ -22,6 +23,8 @@ public class Round {
private ROUND_STATE roundState = ROUND_STATE.PLAYER_REGISTRATION; private ROUND_STATE roundState = ROUND_STATE.PLAYER_REGISTRATION;
private ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); private ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
private ScheduledFuture<?> countdownFuture = null; private ScheduledFuture<?> countdownFuture = null;
private Runnable onEnd = null;
@Setter
private BossBarService bossBarService; private BossBarService bossBarService;
private Round() { private Round() {
@ -92,6 +95,7 @@ public class Round {
if (countdownFuture != null) { if (countdownFuture != null) {
countdownFuture.cancel(true); countdownFuture.cancel(true);
} }
this.onEnd = onEnd;
final Instant endTime = Instant.now().plus(duration); final Instant endTime = Instant.now().plus(duration);
countdownFuture = scheduledExecutorService.scheduleAtFixedRate(() -> { countdownFuture = scheduledExecutorService.scheduleAtFixedRate(() -> {
@ -121,7 +125,21 @@ public class Round {
}); });
} }
public void setBossBarService(BossBarService bossBarService) { public void forceNextPhase() {
this.bossBarService = bossBarService; 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);
}
}
} }
} }

View File

@ -109,6 +109,7 @@ public class RoundService implements RoundListener {
if (roundState.equals(ROUND_STATE.COUNTDOWN)) { if (roundState.equals(ROUND_STATE.COUNTDOWN)) {
startFreeze(); startFreeze();
} }
Bukkit.broadcast(MiniMessage.miniMessage().deserialize(Messages.GAME.NEXT_STATE, Placeholder.parsed("state", roundState.getHumandReadableName())));
} }
private void stopFreeze() { private void stopFreeze() {