Refactor Round phase transitions and countdown logic; consolidate messages, adjust state handling, and add configurable durations for safe and kill phases.

This commit is contained in:
akastijn 2026-07-05 23:42:20 +02:00
parent 5ce26782f2
commit c7161f707c
6 changed files with 43 additions and 31 deletions

View File

@ -16,7 +16,7 @@ public class NextPhase extends SubCommand {
@Override @Override
public boolean onCommand(CommandSender commandSender, String[] args) { public boolean onCommand(CommandSender commandSender, String[] args) {
round.forceNextPhase(); round.forceNextPhase();
commandSender.sendRichMessage("<green>Skipping to the next phase/stage.</green>"); commandSender.sendRichMessage(Messages.COMMANDS.NEXT_PHASE_SUCCESS);
return true; return true;
} }

View File

@ -42,6 +42,8 @@ public class Config extends AbstractConfig {
private static final String prefix = "round."; private static final String prefix = "round.";
public static Duration COUNTDOWN = Duration.ofSeconds(10); public static Duration COUNTDOWN = Duration.ofSeconds(10);
public static Duration SAFE_PHASE = Duration.ofSeconds(30);
public static Duration KILL_PHASE = Duration.ofMinutes(5);
public static int INITIAL_BORDER_SIZE = 5000; public static int INITIAL_BORDER_SIZE = 5000;
public static List<GameStage> STAGES = List.of( public static List<GameStage> STAGES = List.of(
GameStage.builder().duration(Duration.ofMinutes(5)).worldBorderSize(1000).build(), GameStage.builder().duration(Duration.ofMinutes(5)).worldBorderSize(1000).build(),
@ -53,6 +55,10 @@ public class Config extends AbstractConfig {
private static void load() { private static void load() {
int countdownSeconds = config.getInt(prefix, "countdown-seconds", Math.toIntExact(COUNTDOWN.toSeconds())); int countdownSeconds = config.getInt(prefix, "countdown-seconds", Math.toIntExact(COUNTDOWN.toSeconds()));
COUNTDOWN = Duration.ofSeconds(countdownSeconds); COUNTDOWN = Duration.ofSeconds(countdownSeconds);
int safePhaseSeconds = config.getInt(prefix, "safe-phase-seconds", Math.toIntExact(SAFE_PHASE.toSeconds()));
SAFE_PHASE = Duration.ofSeconds(safePhaseSeconds);
int killPhaseSeconds = config.getInt(prefix, "kill-phase-seconds", Math.toIntExact(KILL_PHASE.toSeconds()));
KILL_PHASE = Duration.ofSeconds(killPhaseSeconds);
INITIAL_BORDER_SIZE = config.getInt(prefix, "initial-border-size", INITIAL_BORDER_SIZE); INITIAL_BORDER_SIZE = config.getInt(prefix, "initial-border-size", INITIAL_BORDER_SIZE);
ConfigurationSection configurationSection = config.getConfigurationSection(prefix + "stages"); ConfigurationSection configurationSection = config.getConfigurationSection(prefix + "stages");

View File

@ -91,6 +91,7 @@ public class Messages extends AbstractConfig {
public static String PLAYER_DEATH = "<red><player> has died! <gold><remaining></gold> players remaining.</red>"; public static String PLAYER_DEATH = "<red><player> has died! <gold><remaining></gold> players remaining.</red>";
public static String BOSSBAR_COUNTDOWN = "<gold>Loot phase in <time></gold>"; public static String BOSSBAR_COUNTDOWN = "<gold>Loot phase in <time></gold>";
public static String BOSSBAR_PVP_COUNTDOWN = "<green>PVP starts in <time></green>";
public static String BOSSBAR_SAFE_PHASE = "<green>Border shrinking in <time></green>"; public static String BOSSBAR_SAFE_PHASE = "<green>Border shrinking in <time></green>";
public static String BOSSBAR_KILL_PHASE = "<red>Border shrinking... <time></red>"; public static String BOSSBAR_KILL_PHASE = "<red>Border shrinking... <time></red>";
public static String BOSSBAR_FINALE = "<gold>Remaining Players: <remaining></gold>"; public static String BOSSBAR_FINALE = "<gold>Remaining Players: <remaining></gold>";
@ -107,6 +108,7 @@ public class Messages extends AbstractConfig {
PLAYER_DEATH = config.getString(prefix, "player-death", PLAYER_DEATH); PLAYER_DEATH = config.getString(prefix, "player-death", PLAYER_DEATH);
BOSSBAR_COUNTDOWN = config.getString(prefix, "bossbar-countdown", BOSSBAR_COUNTDOWN); BOSSBAR_COUNTDOWN = config.getString(prefix, "bossbar-countdown", BOSSBAR_COUNTDOWN);
BOSSBAR_PVP_COUNTDOWN = config.getString(prefix, "bossbar-pvp-countdown", BOSSBAR_PVP_COUNTDOWN);
BOSSBAR_SAFE_PHASE = config.getString(prefix, "bossbar-border-shrinking-in", BOSSBAR_SAFE_PHASE); BOSSBAR_SAFE_PHASE = config.getString(prefix, "bossbar-border-shrinking-in", BOSSBAR_SAFE_PHASE);
BOSSBAR_KILL_PHASE = config.getString(prefix, "bossbar-border-shrinking", BOSSBAR_KILL_PHASE); BOSSBAR_KILL_PHASE = config.getString(prefix, "bossbar-border-shrinking", BOSSBAR_KILL_PHASE);
BOSSBAR_FINALE = config.getString(prefix, "bossbar-finale", BOSSBAR_FINALE); BOSSBAR_FINALE = config.getString(prefix, "bossbar-finale", BOSSBAR_FINALE);
@ -201,4 +203,15 @@ public class Messages extends AbstractConfig {
STATS_FORMAT = config.getString(prefix, "format", STATS_FORMAT); STATS_FORMAT = config.getString(prefix, "format", STATS_FORMAT);
} }
} }
public static class COMMANDS {
private static final String prefix = "commands.";
public static String NEXT_PHASE_SUCCESS = "<green>Skipping to the next phase/stage.</green>";
@SuppressWarnings("unused")
private static void load() {
NEXT_PHASE_SUCCESS = config.getString(prefix + "next-phase", "success", NEXT_PHASE_SUCCESS);
}
}
} }

View File

@ -18,6 +18,10 @@ public class GameStageHandler {
broadcast(message); broadcast(message);
} }
public static void broadcastMessage(String message) {
broadcast(message);
}
public static void handleCountdownEnd() { public static void handleCountdownEnd() {
broadcast(Messages.GAME.STARTED); broadcast(Messages.GAME.STARTED);
} }

View File

@ -42,9 +42,14 @@ public class BossBarService implements RoundListener {
public void updateCountdown(Duration timeLeft, Duration totalTime, ROUND_STATE state) { public void updateCountdown(Duration timeLeft, Duration totalTime, ROUND_STATE state) {
String message = switch (state) { String message = switch (state) {
case COUNTDOWN -> Messages.GAME.BOSSBAR_COUNTDOWN; case COUNTDOWN -> Messages.GAME.BOSSBAR_COUNTDOWN;
case SAFE_PHASE -> Messages.GAME.BOSSBAR_SAFE_PHASE; case SAFE_PHASE -> Messages.GAME.BOSSBAR_PVP_COUNTDOWN;
case KILL_PHASE -> Messages.GAME.BOSSBAR_KILL_PHASE; case KILL_PHASE -> Messages.GAME.BOSSBAR_SAFE_PHASE;
default -> throw new IllegalArgumentException("Invalid round state: " + state); default -> {
if (state.ordinal() > ROUND_STATE.KILL_PHASE.ordinal()) {
yield Messages.GAME.BOSSBAR_KILL_PHASE;
}
throw new IllegalArgumentException("Invalid round state: " + state);
}
}; };
if (message.isEmpty()) { if (message.isEmpty()) {

View File

@ -1,8 +1,8 @@
package com.alttd.hunger_games.services; package com.alttd.hunger_games.services;
import com.alttd.hunger_games.config.Config; import com.alttd.hunger_games.config.Config;
import com.alttd.hunger_games.config.Messages;
import com.alttd.hunger_games.data_objects.GameStage; import com.alttd.hunger_games.data_objects.GameStage;
import com.alttd.hunger_games.data_objects.PLAYER_STATE;
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 lombok.Setter;
@ -87,8 +87,12 @@ public class Round {
startCountdown(warmupDuration, () -> { startCountdown(warmupDuration, () -> {
GameStageHandler.handleCountdownEnd(); GameStageHandler.handleCountdownEnd();
nextStage(); nextStage(); // COUNTDOWN -> SAFE_PHASE
scheduleNextStage(0); startCountdown(Config.ROUND.SAFE_PHASE, () -> {
nextStage(); // SAFE_PHASE -> KILL_PHASE
GameStageHandler.broadcastMessage(Messages.GAME.NEXT_STATE.replace("<round>", roundState.getHumanReadableName()));
startCountdown(Config.ROUND.KILL_PHASE, () -> scheduleNextStage(0));
});
}); });
} }
@ -120,13 +124,11 @@ public class Round {
private void scheduleNextStage(int index) { private void scheduleNextStage(int index) {
List<GameStage> gameStageList = Config.ROUND.STAGES; List<GameStage> gameStageList = Config.ROUND.STAGES;
if (gameStageList.isEmpty()) { if (gameStageList.isEmpty()) {
nextStage(); // Transition to SAFE_PHASE
nextStage(); // Transition to KILL_PHASE
return; return;
} }
if (gameStageList.size() <= index) { if (gameStageList.size() <= index) {
nextStage(); nextStage(); // Transition to FINALE
return; return;
} }
@ -134,17 +136,8 @@ public class Round {
Duration duration = gameStage.getDuration(); Duration duration = gameStage.getDuration();
startCountdown(duration, () -> { startCountdown(duration, () -> {
if (gameStageList.size() <= index + 1) { GameStageHandler.handleStageChange(gameStage.getWorldBorderSize());
nextStage(); scheduleNextStage(index + 1);
GameStageHandler.handleStageChange(gameStage.getWorldBorderSize());
startCountdown(Duration.ofMinutes(5), this::nextStage);
} else {
if (index == 0 && roundState.equals(ROUND_STATE.SAFE_PHASE)) {
nextStage();
}
GameStageHandler.handleStageChange(gameStage.getWorldBorderSize());
scheduleNextStage(index + 1);
}
}); });
} }
@ -153,16 +146,7 @@ public class Round {
return; return;
} }
countdownFuture.cancel(true); countdownFuture.cancel(true);
if (roundState.equals(ROUND_STATE.KILL_PHASE)) { onEnd.run();
onEnd.run();
} else {
nextStage();
if (roundState.equals(ROUND_STATE.SAFE_PHASE)) {
scheduleNextStage(0);
} else if (roundState.equals(ROUND_STATE.KILL_PHASE)) {
scheduleNextStage(0);
}
}
} }
} }