Implement round progression system with countdown, stages, and /hg start command

This commit is contained in:
2026-05-24 01:30:11 +02:00
parent ab6112b9da
commit c832a6648b
9 changed files with 179 additions and 22 deletions
@@ -42,11 +42,6 @@ public class PlayerService implements RoundListener {
unregisteredPlayers.forEach(player -> roundService.setPlayerState(player.getUniqueId(), PLAYER_STATE.SPECTATING));
}
@Override
public void roundReset() {
//TODO: teleport everyone to spawn (or spectator?) location (from where they can join the game)
}
public Optional<PLAYER_STATE> registerPlayer(Player player) {
if (roundState == null) {
return Optional.empty();
@@ -1,16 +1,24 @@
package com.alttd.hunger_games.services;
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 java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Round {
private static Round instance = null;
private final List<RoundListener> listeners = new ArrayList<>();
private ROUND_STATE roundState = null;
private ROUND_STATE roundState = ROUND_STATE.PLAYER_REGISTRATION;
private ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
private Round() {
@@ -33,24 +41,49 @@ public class Round {
listeners.remove(listener);
}
public void reset() {
listeners.forEach(RoundListener::roundReset);
}
public void start() {
public void stop() {
roundState = ROUND_STATE.PLAYER_REGISTRATION;
listeners.forEach(roundListener -> roundListener.stateChange(roundState));
}
public void nextStage() {
private void nextStage() {
Optional<ROUND_STATE> optionalNextRoundState = roundState.next();
if (optionalNextRoundState.isEmpty()) {
roundState = null;
reset();
roundState = ROUND_STATE.PLAYER_REGISTRATION;
listeners.forEach(roundListener -> roundListener.stateChange(roundState));
return;
}
roundState = optionalNextRoundState.get();
listeners.forEach(roundListener -> roundListener.stateChange(roundState));
}
public void startRound() {
if (roundState.equals(ROUND_STATE.PLAYER_REGISTRATION)) {
throw new IllegalStateException("Round can not be started before player registration.");
}
roundState = ROUND_STATE.COUNTDOWN;
listeners.forEach(roundListener -> roundListener.stateChange(roundState));
GameStageHandler.handleWarmup();
Duration warmupDuration = Config.ROUND.COUNTDOWN;
scheduledExecutorService.schedule(() -> {
GameStageHandler.handleCountdownEnd();
nextStage();
scheduleNextStage(0);
}, warmupDuration.toSeconds(), TimeUnit.SECONDS);
}
private void scheduleNextStage(int index) {
List<GameStage> gameStageList = Config.ROUND.STAGES;
if (gameStageList.size() <= index) {
nextStage();
return;
}
GameStage gameStage = gameStageList.get(index);
Duration duration = gameStage.getDuration();
scheduledExecutorService.schedule(() -> {
GameStageHandler.handleStageChange(gameStage.getWorldBorderSize());
scheduleNextStage(index + 1);
}, duration.toSeconds(), TimeUnit.SECONDS);
}
}
@@ -6,6 +6,4 @@ public interface RoundListener {
void stateChange(ROUND_STATE roundState);
void roundReset();
}
@@ -40,11 +40,8 @@ public class RoundService implements RoundListener {
@Override
public void stateChange(ROUND_STATE roundState) {
this.roundState = roundState;
}
@Override
public void roundReset() {
clear();
roundState = null;
if (roundState.equals(ROUND_STATE.PLAYER_REGISTRATION)) {
clear();
}
}
}