Introduced a new `/ctf skipphase` command allowing admins to skip the current game phase. Updated relevant classes to handle phase-skipping logic and ensure proper game state transitions. Added corresponding message configuration and subcommand registration.
105 lines
4.4 KiB
Java
105 lines
4.4 KiB
Java
package com.alttd.ctf.game;
|
|
|
|
import com.alttd.ctf.config.GameConfig;
|
|
import com.alttd.ctf.flag.Flag;
|
|
import lombok.Getter;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import net.kyori.adventure.text.minimessage.MiniMessage;
|
|
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
|
import org.bukkit.Bukkit;
|
|
import org.jetbrains.annotations.NotNull;
|
|
|
|
import javax.annotation.Nullable;
|
|
import java.time.Duration;
|
|
import java.time.Instant;
|
|
import java.util.HashMap;
|
|
import java.util.concurrent.ScheduledExecutorService;
|
|
|
|
@Slf4j
|
|
public class RunningGame implements Runnable {
|
|
|
|
private final HashMap<GamePhase, Duration> phaseDurations = GameConfig.PHASES.getGAME_PHASE_DURATION();
|
|
private final GameManager gameManager;
|
|
private final Flag flag;
|
|
private final ScheduledExecutorService executorService;
|
|
@Getter
|
|
private GamePhase currentPhase = GamePhase.values()[0];
|
|
private Instant phaseStartTime = null;
|
|
private int lastMinuteBroadcast = 0;
|
|
|
|
public RunningGame(GameManager gameManager, Duration gameDuration, Flag flag, ScheduledExecutorService executorService) {
|
|
this.gameManager = gameManager;
|
|
this.flag = flag;
|
|
this.executorService = executorService;
|
|
phaseDurations.put(GamePhase.COMBAT, gameDuration);
|
|
}
|
|
|
|
@Override
|
|
public void run() {
|
|
try {
|
|
GamePhase nextPhase = (currentPhase.ordinal() + 1 < GamePhase.values().length) ? GamePhase.values()[currentPhase.ordinal() + 1] : null;
|
|
if (phaseStartTime == null) {
|
|
phaseStartTime = Instant.now();
|
|
nextPhaseActions(null, currentPhase);
|
|
}
|
|
|
|
if (nextPhase != null && Duration.between(phaseStartTime, Instant.now()).compareTo(phaseDurations.get(currentPhase)) >= 0) {
|
|
nextPhaseActions(currentPhase, nextPhase);
|
|
phaseStartTime = Instant.now();
|
|
} else if (nextPhase != null) {
|
|
broadcastNextPhaseStartTime(currentPhase, nextPhase);
|
|
} else {
|
|
executorService.shutdown();
|
|
}
|
|
} catch (Exception e) {
|
|
log.error("Unexpected error in running game", e);
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
|
|
private void nextPhaseActions(@Nullable GamePhase previousPhase, @NotNull GamePhase phase) {
|
|
//TODO command to go to next phase
|
|
this.currentPhase = phase;
|
|
if (previousPhase != null) {
|
|
gameManager.getPhaseExecutor(previousPhase).end(phase);
|
|
}
|
|
gameManager.getPhaseExecutor(phase).start(flag);
|
|
}
|
|
|
|
private void broadcastNextPhaseStartTime(GamePhase currentPhase, GamePhase nextPhase) {//TODO check how this works/what it should do
|
|
//Remaining time for this phase
|
|
Duration duration = phaseDurations.get(currentPhase).minus(Duration.between(phaseStartTime, Instant.now()));
|
|
log.debug(duration.toString());//TODO remove debug
|
|
if ((duration.toMinutes() > 1 && (duration.toMinutes() % 15 == 0 || duration.toMinutes() <= 5)) && duration.toSecondsPart() < 2) {
|
|
if (lastMinuteBroadcast == duration.toMinutes()) {
|
|
return;
|
|
}
|
|
lastMinuteBroadcast = (int) duration.toMinutes();
|
|
Bukkit.broadcast(MiniMessage.miniMessage().deserialize(
|
|
"<green>The <phase> will start in <bold><red>" + duration.toMinutes() + "</red> minutes</bold></green>",
|
|
Placeholder.component("phase", nextPhase.getDisplayName())
|
|
));
|
|
} else if (duration.toMinutes() < 1 && duration.toSeconds() % 15 == 0) {
|
|
Bukkit.broadcast(MiniMessage.miniMessage().deserialize(
|
|
"<green>The <phase> will start in <bold><red>" + duration.toSeconds() + "</red> seconds</bold></green>",
|
|
Placeholder.component("phase", nextPhase.getDisplayName())
|
|
));
|
|
}
|
|
}
|
|
|
|
public boolean skipCurrentPhase() {
|
|
GamePhase nextPhase = (currentPhase.ordinal() + 1 < GamePhase.values().length) ? GamePhase.values()[currentPhase.ordinal() + 1] : null;
|
|
if (nextPhase == null) {
|
|
log.warn("Tried to skip phase {} but there is no next phase", currentPhase);
|
|
return false;
|
|
}
|
|
nextPhaseActions(currentPhase, nextPhase);
|
|
return true;
|
|
}
|
|
|
|
public void end() {
|
|
//TODO say the phase ended early?
|
|
nextPhaseActions(currentPhase, GamePhase.ENDED);
|
|
}
|
|
}
|