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 listeners = new ArrayList<>(); private ROUND_STATE roundState = ROUND_STATE.PLAYER_REGISTRATION; private ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); private Round() { } public static Round createSingletonInstance() throws IllegalStateException { if (instance != null) { throw new IllegalStateException("Round is already initialized."); } instance = new Round(); return instance; } public ROUND_STATE register(RoundListener listener) { listeners.add(listener); return roundState; } public void unregister(RoundListener listener) { listeners.remove(listener); } public void stop() { roundState = ROUND_STATE.PLAYER_REGISTRATION; listeners.forEach(roundListener -> roundListener.stateChange(roundState)); } private void nextStage() { Optional optionalNextRoundState = roundState.next(); if (optionalNextRoundState.isEmpty()) { 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 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); } }