diff --git a/core/src/main/java/tc/oc/pgm/PGMConfig.java b/core/src/main/java/tc/oc/pgm/PGMConfig.java index 0d50fa1df5..b528c90e22 100644 --- a/core/src/main/java/tc/oc/pgm/PGMConfig.java +++ b/core/src/main/java/tc/oc/pgm/PGMConfig.java @@ -77,6 +77,7 @@ public final class PGMConfig implements Config { // restart.* private final Duration uptimeLimit; private final long matchLimit; + private final boolean pollMapOnRestart; // gameplay.* private final boolean woolRefill; @@ -179,6 +180,7 @@ public final class PGMConfig implements Config { this.uptimeLimit = parseDuration(config.getString("restart.uptime", "1d")); this.matchLimit = parseInteger(config.getString("restart.match-limit", "30")); + this.pollMapOnRestart = parseBoolean(config.getString("restart.poll-map-on-restart", "false")); this.woolRefill = parseBoolean(config.getString("gameplay.refill-wool", "true")); this.griefScore = @@ -533,6 +535,10 @@ public long getMatchLimit() { return matchLimit; } + public boolean shouldPollMapOnRestart() { + return pollMapOnRestart; + } + @Override public long getMinimumPlayers() { return minPlayers; diff --git a/core/src/main/java/tc/oc/pgm/api/Config.java b/core/src/main/java/tc/oc/pgm/api/Config.java index cb7c8280c9..2fe77530fc 100644 --- a/core/src/main/java/tc/oc/pgm/api/Config.java +++ b/core/src/main/java/tc/oc/pgm/api/Config.java @@ -117,6 +117,13 @@ public interface Config { */ long getMatchLimit(); + /** + * If a map pool vote should be started even when the server restarts. + * + * @return If a vote should be started. + */ + boolean shouldPollMapOnRestart(); + /** * Gets the minimum number of players for a match to start. * diff --git a/core/src/main/java/tc/oc/pgm/api/Modules.java b/core/src/main/java/tc/oc/pgm/api/Modules.java index 2d02de53ca..9ad1f34d38 100644 --- a/core/src/main/java/tc/oc/pgm/api/Modules.java +++ b/core/src/main/java/tc/oc/pgm/api/Modules.java @@ -31,6 +31,7 @@ import tc.oc.pgm.crafting.CraftingMatchModule; import tc.oc.pgm.crafting.CraftingModule; import tc.oc.pgm.cycle.CycleMatchModule; +import tc.oc.pgm.cycle.SmoothRestartModule; import tc.oc.pgm.damage.DamageMatchModule; import tc.oc.pgm.damage.DamageModule; import tc.oc.pgm.damage.DisableDamageMatchModule; @@ -225,6 +226,7 @@ void registerAll() { register(PlayerTimeMatchModule.class, PlayerTimeMatchModule::new); register(SpectateMatchModule.class, SpectateMatchModule::new); register(DamageHistoryMatchModule.class, DamageHistoryMatchModule::new); + register(SmoothRestartModule.class, SmoothRestartModule::new); register(ProjectileTrailMatchModule.class, ProjectileTrailMatchModule::new); diff --git a/core/src/main/java/tc/oc/pgm/command/CancelCommand.java b/core/src/main/java/tc/oc/pgm/command/CancelCommand.java index 3a7b244ece..fc44034d58 100644 --- a/core/src/main/java/tc/oc/pgm/command/CancelCommand.java +++ b/core/src/main/java/tc/oc/pgm/command/CancelCommand.java @@ -25,7 +25,7 @@ public final class CancelCommand { @CommandDescription("Cancels all countdowns") @Permission(Permissions.STOP) public void cancel(CommandSender sender, Audience audience, Match match) { - if (RestartManager.isQueued()) { + if (RestartManager.getInstance().isQueued()) { match.callEvent(new CancelRestartEvent()); audience.sendMessage(translatable("admin.cancelRestart.restartUnqueued", NamedTextColor.RED)); return; diff --git a/core/src/main/java/tc/oc/pgm/command/MapOrderCommand.java b/core/src/main/java/tc/oc/pgm/command/MapOrderCommand.java index 8c8c089cc9..8214137b4e 100644 --- a/core/src/main/java/tc/oc/pgm/command/MapOrderCommand.java +++ b/core/src/main/java/tc/oc/pgm/command/MapOrderCommand.java @@ -53,7 +53,7 @@ public void setNext( @Flag(value = "force", aliases = "f") boolean force, @Flag(value = "reset", aliases = "r") boolean reset, @Argument("map") @Default(CURRENT) @FlagYielding MapInfo map) { - if (RestartManager.isQueued() && !force) { + if (RestartManager.getInstance().isQueued() && !force) { throw exception("map.setNext.confirm"); } @@ -77,8 +77,8 @@ public void setNext( mapOrder.setNextMap(map); - if (RestartManager.isQueued()) { - RestartManager.cancelRestart(); + if (RestartManager.getInstance().isQueued()) { + RestartManager.getInstance().cancelRestart(); viewer.sendWarning(translatable("admin.cancelRestart.restartUnqueued", NamedTextColor.GREEN)); } diff --git a/core/src/main/java/tc/oc/pgm/command/RestartCommand.java b/core/src/main/java/tc/oc/pgm/command/RestartCommand.java index 007d451df1..c18cdcd2a1 100644 --- a/core/src/main/java/tc/oc/pgm/command/RestartCommand.java +++ b/core/src/main/java/tc/oc/pgm/command/RestartCommand.java @@ -11,7 +11,6 @@ import org.incendo.cloud.annotations.Permission; import tc.oc.pgm.api.Permissions; import tc.oc.pgm.api.match.Match; -import tc.oc.pgm.restart.RequestRestartEvent; import tc.oc.pgm.restart.RestartManager; import tc.oc.pgm.util.Audience; @@ -25,8 +24,6 @@ public void restart( Match match, @Argument("duration") Duration duration, @Flag(value = "force", aliases = "f") boolean force) { - RestartManager.queueRestart("Restart requested via /queuerestart command", duration); - if (force && match.isRunning()) { match.finish(); } @@ -37,6 +34,7 @@ public void restart( audience.sendMessage(translatable("admin.queueRestart.restartingNow", NamedTextColor.GREEN)); } - match.callEvent(new RequestRestartEvent()); + RestartManager.getInstance() + .queueRestart("Restart requested via /queuerestart command", duration); } } diff --git a/core/src/main/java/tc/oc/pgm/cycle/CycleCountdown.java b/core/src/main/java/tc/oc/pgm/cycle/CycleCountdown.java index 5548849bd0..e2c760d74a 100644 --- a/core/src/main/java/tc/oc/pgm/cycle/CycleCountdown.java +++ b/core/src/main/java/tc/oc/pgm/cycle/CycleCountdown.java @@ -22,23 +22,22 @@ public class CycleCountdown extends MatchCountdown { // Number of seconds before a cycle occurs to start loading the next match. // This eases stress on the main thread when handling lots of players. - private int preloadSecs; + protected int preloadSecs; - private MapInfo nextMap; + protected MapInfo nextMap; private MatchFactory nextMatch; public CycleCountdown(Match match) { super(match, BossBar.Color.BLUE); try { - this.preloadSecs = - TextParser.parseInteger( - PGM.get() - .getConfiguration() - .getExperiments() - .getOrDefault("match-preload-seconds", "") - .toString(), - Range.atLeast(0)); + this.preloadSecs = TextParser.parseInteger( + PGM.get() + .getConfiguration() + .getExperiments() + .getOrDefault("match-preload-seconds", "") + .toString(), + Range.atLeast(0)); } catch (TextException t) { // No-op, since this is experimental } @@ -54,16 +53,15 @@ protected Component formatText() { mapName != null ? translatable("map.cycledMap", mapName) : translatable("map.cycled"); } else { Component secs = secondsRemaining(NamedTextColor.DARK_RED); - cycleComponent = - mapName != null - ? translatable("map.cycleMap", mapName, secs) - : translatable("map.cycle", secs); + cycleComponent = mapName != null + ? translatable("map.cycleMap", mapName, secs) + : translatable("map.cycle", secs); } return cycleComponent.color(NamedTextColor.DARK_AQUA); } - private void checkSetNext() { + protected void checkSetNext() { final MapOrder mapOrder = PGM.get().getMapOrder(); if (remaining.getSeconds() <= preloadSecs) { if (nextMatch != null) return; diff --git a/core/src/main/java/tc/oc/pgm/cycle/CycleMatchModule.java b/core/src/main/java/tc/oc/pgm/cycle/CycleMatchModule.java index 876f701ec2..a8b0a68bde 100644 --- a/core/src/main/java/tc/oc/pgm/cycle/CycleMatchModule.java +++ b/core/src/main/java/tc/oc/pgm/cycle/CycleMatchModule.java @@ -59,7 +59,7 @@ public void onMatchEnd(MatchFinishEvent event) { final Match match = event.getMatch(); mapOrder.matchEnded(match); - if (!RestartManager.isQueued()) { + if (!RestartManager.getInstance().isQueued()) { Duration duration = mapOrder.getCycleTime(); if (!duration.isNegative()) { diff --git a/core/src/main/java/tc/oc/pgm/cycle/FakeCycleCountdown.java b/core/src/main/java/tc/oc/pgm/cycle/FakeCycleCountdown.java new file mode 100644 index 0000000000..469367fe27 --- /dev/null +++ b/core/src/main/java/tc/oc/pgm/cycle/FakeCycleCountdown.java @@ -0,0 +1,56 @@ +package tc.oc.pgm.cycle; + +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.Component.translatable; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TranslatableComponent; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import tc.oc.pgm.api.PGM; +import tc.oc.pgm.api.map.MapOrder; +import tc.oc.pgm.api.match.Match; + +public class FakeCycleCountdown extends CycleCountdown { + + private final SmoothRestartModule smoothRestartModule; + + public FakeCycleCountdown(Match match, SmoothRestartModule smoothRestartModule) { + super(match); + this.smoothRestartModule = smoothRestartModule; + } + + @Override + protected Component formatText() { + Component mapName = nextMap == null ? null : text(nextMap.getName(), NamedTextColor.AQUA); + + TranslatableComponent cycleComponent; + if (remaining.isZero()) { + cycleComponent = + mapName != null ? translatable("map.cycledMap", mapName) : translatable("map.cycled"); + } else { + Component secs = secondsRemaining(NamedTextColor.DARK_RED); + cycleComponent = mapName != null + ? translatable("map.cycleMap", mapName, secs) + : translatable("map.cycle", secs); + } + + return cycleComponent.color(NamedTextColor.GOLD); + } + + @Override + protected void checkSetNext() { + final MapOrder mapOrder = PGM.get().getMapOrder(); + if (remaining.getSeconds() <= preloadSecs) { + if (nextMap != null) return; + nextMap = mapOrder.popNextMap(); + smoothRestartModule.updateSelectedMap(nextMap); + Bukkit.broadcastMessage(nextMap.toString()); + } else { + nextMap = mapOrder.getNextMap(); + if (nextMap != null) { + smoothRestartModule.updateSelectedMap(nextMap); + } + } + } +} diff --git a/core/src/main/java/tc/oc/pgm/cycle/SmoothRestartModule.java b/core/src/main/java/tc/oc/pgm/cycle/SmoothRestartModule.java new file mode 100644 index 0000000000..4da90bf834 --- /dev/null +++ b/core/src/main/java/tc/oc/pgm/cycle/SmoothRestartModule.java @@ -0,0 +1,107 @@ +package tc.oc.pgm.cycle; + +import static net.kyori.adventure.text.Component.text; + +import java.util.concurrent.TimeUnit; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import tc.oc.pgm.api.PGM; +import tc.oc.pgm.api.map.MapInfo; +import tc.oc.pgm.api.map.MapOrder; +import tc.oc.pgm.api.match.Match; +import tc.oc.pgm.api.match.MatchModule; +import tc.oc.pgm.api.match.MatchScope; +import tc.oc.pgm.events.CountdownEndEvent; +import tc.oc.pgm.events.CountdownStartEvent; +import tc.oc.pgm.events.ListenerScope; +import tc.oc.pgm.restart.CancelRestartEvent; +import tc.oc.pgm.restart.RequestRestartEvent; +import tc.oc.pgm.rotation.MapPoolManager; +import tc.oc.pgm.rotation.pools.MapPool; +import tc.oc.pgm.rotation.pools.VotingPool; +import tc.oc.pgm.rotation.vote.MapPoll; + +@ListenerScope(MatchScope.LOADED) +public class SmoothRestartModule implements MatchModule, Listener { + + private final Match match; + private FakeCycleCountdown countdown; + private MapPoll currentPoll; + + public SmoothRestartModule(Match match) { + this.match = match; + } + + public void updateSelectedMap(MapInfo nextMap) { + if (nextMap == null) return; + Bukkit.broadcastMessage(nextMap.toString()); + } + + @EventHandler(priority = EventPriority.LOW) + public void onRequestRestart(RequestRestartEvent event) { + // Randomly allow for regular restarts + if (match.getRandom().nextBoolean()) { + match.sendMessage(text("real restart")); + return; + } + + match.sendMessage(text("fake cycle")); + + countdown = new FakeCycleCountdown(match, this); + event.setRestartCountdown(countdown); + } + + public void tryStartCycleCountdown() { + countdown = new FakeCycleCountdown(match, this); + match.getCountdown().start(countdown, PGM.get().getConfiguration().getCycleTime()); + } + + @EventHandler + public void onRestartCancel(CancelRestartEvent event) { + if (match.getCountdown().isRunning(countdown)) { + match.getCountdown().cancel(countdown); + } + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onCountdownStart(CountdownStartEvent event) { + if (!(event.getCountdown() instanceof FakeCycleCountdown)) return; + + // // TODO: check that we are on a voted pool + MapOrder mapOrder = PGM.get().getMapOrder(); + + MapInfo nextMap = mapOrder.getNextMap(); + if (nextMap != null) Bukkit.broadcastMessage("next map: " + nextMap.getName()); + + if (mapOrder instanceof MapPoolManager) { + + MapPool pool = ((MapPoolManager) mapOrder).getActiveMapPool(); + + if (pool instanceof VotingPool votingPool) { + + match + .getExecutor(MatchScope.LOADED) + .schedule( + () -> { + votingPool.startMapPoll(match); + }, + 5, + TimeUnit.SECONDS); + } + } + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onCountdownEnd(CountdownEndEvent event) { + if (!(event.getCountdown() instanceof FakeCycleCountdown)) return; + + Bukkit.getServer().broadcastMessage("next map: " + countdown.nextMap); + + event.getMatch().sendMessage(text("get the map")); + + // TODO: how to actual restart? + // RestartListener.getInstance().startRestartCountdown(event.getMatch()); + } +} diff --git a/core/src/main/java/tc/oc/pgm/restart/RequestRestartEvent.java b/core/src/main/java/tc/oc/pgm/restart/RequestRestartEvent.java index 7fec531f0e..c69997c002 100644 --- a/core/src/main/java/tc/oc/pgm/restart/RequestRestartEvent.java +++ b/core/src/main/java/tc/oc/pgm/restart/RequestRestartEvent.java @@ -3,9 +3,20 @@ import org.bukkit.event.Event; import org.bukkit.event.HandlerList; import org.bukkit.plugin.Plugin; +import tc.oc.pgm.countdowns.Countdown; public class RequestRestartEvent extends Event { + private Countdown restartCountdown; + + public Countdown getRestartCountdown() { + return restartCountdown; + } + + public void setRestartCountdown(Countdown restartCountdown) { + this.restartCountdown = restartCountdown; + } + public class Deferral { private final Plugin plugin; @@ -22,22 +33,22 @@ public Plugin getPlugin() { * and can be discarded. */ public void remove() { - RestartManager.removeDeferral(this); + RestartManager.getInstance().removeDeferral(this); } public boolean isDeferring() { - return RestartManager.isDeferredBy(this); + return RestartManager.getInstance().isDeferredBy(this); } } - private static final HandlerList handlers = new HandlerList(); - public Deferral defer(Plugin plugin) { Deferral deferral = new Deferral(plugin); - RestartManager.addDeferral(deferral); + RestartManager.getInstance().addDeferral(deferral); return deferral; } + private static final HandlerList handlers = new HandlerList(); + @Override public HandlerList getHandlers() { return handlers; diff --git a/core/src/main/java/tc/oc/pgm/restart/RestartListener.java b/core/src/main/java/tc/oc/pgm/restart/RestartListener.java index 35d1209783..28149fdaa5 100644 --- a/core/src/main/java/tc/oc/pgm/restart/RestartListener.java +++ b/core/src/main/java/tc/oc/pgm/restart/RestartListener.java @@ -1,9 +1,7 @@ package tc.oc.pgm.restart; -import java.time.Duration; import java.util.Iterator; import java.util.logging.Logger; -import org.bukkit.Bukkit; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; @@ -24,16 +22,39 @@ public class RestartListener implements Listener { private final Logger logger; private long matchCount; - private @Nullable RequestRestartEvent.Deferral deferral; + + private @Nullable RequestRestartEvent.Deferral playingDeferral; + + static RestartListener instance; public RestartListener(PGM plugin, MatchManager matchManager) { this.plugin = plugin; this.matchManager = matchManager; this.logger = ClassLogger.get(plugin.getLogger(), getClass()); + instance = this; + } + + public static RestartListener getInstance() { + return instance; + } + + @EventHandler(ignoreCancelled = true) + public void onRequestRestart(RequestRestartEvent event) { + // Don't do a countdown if there's nobody online + if (this.plugin.getServer().getOnlinePlayers().isEmpty()) return; + + Iterator iterator = matchManager.getMatches(); + Match match = iterator.hasNext() ? iterator.next() : null; + if (match == null) return; + + if (match.isRunning()) { + this.playingDeferral = event.defer(this.plugin); + attemptMatchEnd(match); + } } private void attemptMatchEnd(Match match) { - if (this.deferral == null) return; + if (playingDeferral == null) return; if (match.isRunning()) { if (match.getParticipants().isEmpty()) { @@ -43,32 +64,6 @@ private void attemptMatchEnd(Match match) { } } - @EventHandler - public void onRequestRestart(RequestRestartEvent event) { - if (this.plugin.getServer().getOnlinePlayers().isEmpty()) { - Bukkit.getServer().shutdown(); - } else { - Iterator iterator = matchManager.getMatches(); - Match match = iterator.hasNext() ? iterator.next() : null; - if (match != null) { - this.deferral = event.defer(this.plugin); - if (match.isRunning()) { - attemptMatchEnd(match); - } else { - SingleCountdownContext ctx = (SingleCountdownContext) match.getCountdown(); - ctx.cancelAll(); - - Duration countdownTime = - RestartManager.getCountdown() != null - ? RestartManager.getCountdown() - : PGM.get().getConfiguration().getRestartTime(); - this.logger.info("Starting restart countdown from " + countdownTime); - ctx.start(new RestartCountdown(match), countdownTime); - } - } - } - } - @EventHandler public void onCancelRestart(CancelRestartEvent event) { Iterator iterator = matchManager.getMatches(); @@ -79,15 +74,15 @@ public void onCancelRestart(CancelRestartEvent event) { this.logger.info("Cancelling restart countdown"); ctx.cancelAll(); } - this.deferral = null; } - RestartManager.cancelRestart(); + RestartManager.getInstance().cancelRestart(); } @EventHandler(priority = EventPriority.LOW) public void onMatchEnd(MatchFinishEvent event) { - if (RestartManager.isQueued()) { - this.plugin.getServer().getPluginManager().callEvent(new RequestRestartEvent()); + if (this.playingDeferral != null) { + this.playingDeferral.remove(); + this.playingDeferral = null; } } @@ -100,7 +95,7 @@ public void onPartyChange(PlayerPartyChangeEvent event) { public void onMatchLoad(MatchLoadEvent event) { long matchLimit = plugin.getConfiguration().getMatchLimit(); if (++matchCount >= matchLimit && matchLimit > 0) { - RestartManager.queueRestart("Reached match limit of " + matchLimit); + RestartManager.getInstance().queueRestart("Reached match limit of " + matchLimit); } } } diff --git a/core/src/main/java/tc/oc/pgm/restart/RestartManager.java b/core/src/main/java/tc/oc/pgm/restart/RestartManager.java index 17a7ef5359..75869a26c4 100644 --- a/core/src/main/java/tc/oc/pgm/restart/RestartManager.java +++ b/core/src/main/java/tc/oc/pgm/restart/RestartManager.java @@ -3,74 +3,135 @@ import java.time.Duration; import java.time.Instant; import java.util.HashSet; +import java.util.Iterator; import java.util.Set; +import org.bukkit.Bukkit; import org.jetbrains.annotations.Nullable; import tc.oc.pgm.api.PGM; +import tc.oc.pgm.api.match.Match; +import tc.oc.pgm.api.match.MatchManager; +import tc.oc.pgm.countdowns.Countdown; +import tc.oc.pgm.countdowns.SingleCountdownContext; +import tc.oc.pgm.util.ClassLogger; public class RestartManager { - private static final Set deferrals = new HashSet<>(); + private static final RestartManager INSTANCE = new RestartManager(); - private static Instant queuedAt; - private static String reason; - private static Duration countdown; + private final PGM plugin; + private final MatchManager matchManager; + private final ClassLogger logger; + + private final Set deferrals = new HashSet<>(); + + private Instant queuedAt; + private String reason; + private Duration countdown; + + public RestartManager() { + this.plugin = PGM.get(); + this.matchManager = this.plugin.getMatchManager(); + this.logger = ClassLogger.get(plugin.getLogger(), getClass()); + } + + public static RestartManager getInstance() { + return INSTANCE; + } + + public void checkRestart() { + // Check if queued and check for existing deferrals + if (!isQueued() || isDeferred()) return; + + // Launch the RequestRestartEvent + RequestRestartEvent event = new RequestRestartEvent(); + Bukkit.getPluginManager().callEvent(event); + + if (isDeferred()) return; + + if (plugin.getServer().getOnlinePlayers().isEmpty()) { + Bukkit.getServer().shutdown(); + return; + } + + Iterator iterator = matchManager.getMatches(); + Match match = iterator.hasNext() ? iterator.next() : null; + if (match == null) return; // TODO: what now? + + SingleCountdownContext ctx = (SingleCountdownContext) match.getCountdown(); + ctx.cancelAll(); + + // Start the countdown from the event or create one + Duration countdownTime = + getCountdown() != null ? getCountdown() : plugin.getConfiguration().getRestartTime(); + + this.logger.info("Starting restart countdown from " + countdownTime); + Countdown restartCountdown = event.getRestartCountdown() != null + ? event.getRestartCountdown() + : new RestartCountdown(match); + + ctx.start(restartCountdown, countdownTime); + } /** Queues a restart to be initiated at next available opportunity. */ - public static boolean queueRestart(String reason) { + public boolean queueRestart(String reason) { return queueRestart(reason, null); } - public static boolean queueRestart(String reason, @Nullable Duration countdown) { + public boolean queueRestart(String reason, @Nullable Duration countdown) { if (!isQueued()) { - RestartManager.queuedAt = Instant.now(); - RestartManager.reason = reason; - RestartManager.countdown = - (countdown != null) ? countdown : PGM.get().getConfiguration().getRestartTime(); + this.queuedAt = Instant.now(); + this.reason = reason; + this.countdown = + (countdown != null) ? countdown : plugin.getConfiguration().getRestartTime(); + + checkRestart(); + return true; } return false; } /** Cancels the restart if there is one already queued */ - public static void cancelRestart() { - if (isQueued()) { - RestartManager.queuedAt = null; - RestartManager.reason = null; - RestartManager.countdown = null; + public void cancelRestart() { + if (isQueued()) { // TODO: why this? + this.queuedAt = null; + this.reason = null; + this.countdown = null; } } - public static @Nullable Instant getQueuedAt() { + public @Nullable Instant getQueuedAt() { return queuedAt; } - public static @Nullable String getReason() { + public @Nullable String getReason() { return reason; } - public static @Nullable Duration getCountdown() { + public @Nullable Duration getCountdown() { return countdown; } - public static boolean isQueued() { + public boolean isQueued() { return getQueuedAt() != null; } - public static boolean isDeferred() { + public boolean isDeferred() { return !deferrals.isEmpty(); } - public static boolean isDeferredBy(RequestRestartEvent.Deferral deferral) { + public boolean isDeferredBy(RequestRestartEvent.Deferral deferral) { return deferrals.contains(deferral); } - public static void addDeferral(RequestRestartEvent.Deferral deferral) { + public void addDeferral(RequestRestartEvent.Deferral deferral) { if (isQueued()) { deferrals.add(deferral); } } - public static void removeDeferral(RequestRestartEvent.Deferral deferral) { + public void removeDeferral(RequestRestartEvent.Deferral deferral) { deferrals.remove(deferral); + checkRestart(); } } diff --git a/core/src/main/java/tc/oc/pgm/restart/ShouldRestartTask.java b/core/src/main/java/tc/oc/pgm/restart/ShouldRestartTask.java index 6c7a69be26..e3c619ce5f 100644 --- a/core/src/main/java/tc/oc/pgm/restart/ShouldRestartTask.java +++ b/core/src/main/java/tc/oc/pgm/restart/ShouldRestartTask.java @@ -19,8 +19,8 @@ public ShouldRestartTask() { @Override public void run() { - if (!RestartManager.isQueued() && hasReachedLimit()) { - RestartManager.queueRestart("Exceeded uptime limit of " + getLimit()); + if (!RestartManager.getInstance().isQueued() && hasReachedLimit()) { + RestartManager.getInstance().queueRestart("Exceeded uptime limit of " + getLimit()); } } diff --git a/core/src/main/java/tc/oc/pgm/rotation/pools/VotingPool.java b/core/src/main/java/tc/oc/pgm/rotation/pools/VotingPool.java index 915745dab0..4f8588196a 100644 --- a/core/src/main/java/tc/oc/pgm/rotation/pools/VotingPool.java +++ b/core/src/main/java/tc/oc/pgm/rotation/pools/VotingPool.java @@ -140,6 +140,10 @@ public void unloadPool(Match match) { tickScores(match); } + public void startMapPoll(Match match) { + currentPoll = new MapPoll(match, mapPicker.getMaps(manager.getVoteOptions(), mapScores)); + } + @Override public void matchEnded(Match match) { tickScores(match); @@ -149,11 +153,13 @@ public void matchEnded(Match match) { () -> { // Start poll here, to avoid starting it if you set next another map. if (manager.getOverriderMap() != null) return; - // If there is a restart queued, don't start a vote - if (RestartManager.isQueued()) return; - currentPoll = - new MapPoll(match, mapPicker.getMaps(manager.getVoteOptions(), mapScores)); + // If there is a restart queued, don't start a vote unless stated in config + if (RestartManager.getInstance().isQueued() + && !RestartManager.getInstance().isDeferred() + && !PGM.get().getConfiguration().shouldPollMapOnRestart()) return; + + startMapPoll(match); }, 5, TimeUnit.SECONDS); diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index b9d2524fd1..22d441eb97 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -62,6 +62,7 @@ countdown: restart: uptime: "1d" # Queues a restart after this amount of time has elapsed. match-limit: 60 # Queues a restart after this amount of matches. + poll-map-on-restart: false # If a map poll should be triggered during restarts # Changes behaviour when players try to /join a match. join: