diff --git a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/ScrowAPI.java b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/ScrowAPI.java index ebba10c..34eb5a9 100644 --- a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/ScrowAPI.java +++ b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/ScrowAPI.java @@ -1,6 +1,7 @@ package de.kentoj.scrow.bukkit; import de.kentoj.kencommandapi.CommandAPI; +import de.kentoj.scrow.bukkit.minigame.MinigameManager; import de.kentoj.scrowlib.friends.FriendRequestService; import de.kentoj.scrowlib.friends.FriendshipService; import de.kentoj.scrowlib.economy.EconomyService; @@ -15,7 +16,6 @@ import lombok.Getter; import lombok.NoArgsConstructor; import org.bukkit.OfflinePlayer; import org.bukkit.plugin.Plugin; -import org.checkerframework.checker.signature.qual.InternalForm; import org.jdbi.v3.core.Jdbi; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; @@ -48,6 +48,8 @@ public class ScrowAPI { private static CommandAPI commandApi; @Getter private static PlayerPrefixProvider playerPrefixProvider; + @Getter + private static final MinigameManager minigameManager = new MinigameManager(); private static NetworkPlayerFactory playerFactory; public static NetworkPlayer getPlayer(OfflinePlayer player) { diff --git a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/gameserver/GameServer.java b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/gameserver/GameServer.java new file mode 100644 index 0000000..7819b2b --- /dev/null +++ b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/gameserver/GameServer.java @@ -0,0 +1,6 @@ +package de.kentoj.scrow.bukkit.gameserver; + +public interface GameServer { + + void destroy(); +} diff --git a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/gameserver/GameServerPool.java b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/gameserver/GameServerPool.java new file mode 100644 index 0000000..f484621 --- /dev/null +++ b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/gameserver/GameServerPool.java @@ -0,0 +1,8 @@ +package de.kentoj.scrow.bukkit.gameserver; + +public interface GameServerPool { + + GameServer prepareServer(String gameName); + + void returnServer(String name); +} diff --git a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/MinigameManager.java b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/MinigameManager.java new file mode 100644 index 0000000..8d0cb60 --- /dev/null +++ b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/MinigameManager.java @@ -0,0 +1,24 @@ +package de.kentoj.scrow.bukkit.minigame; + +import org.bukkit.OfflinePlayer; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class MinigameManager { + + private final Map playerToMinigameMap = new HashMap<>(); + + public @Nullable Minigame getMinigameByPlayer(OfflinePlayer player) { + return playerToMinigameMap.get(player.getUniqueId()); + } + + public void setMinigame(OfflinePlayer player, @Nullable Minigame minigame) { + if (minigame == null) + playerToMinigameMap.remove(player.getUniqueId()); + else + playerToMinigameMap.put(player.getUniqueId(), minigame); + } +} diff --git a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/PlayerManager.java b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/PlayerManager.java index a52e9b0..ed039f9 100644 --- a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/PlayerManager.java +++ b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/PlayerManager.java @@ -1,5 +1,7 @@ package de.kentoj.scrow.bukkit.minigame; +import de.kentoj.scrow.bukkit.ScrowAPI; +import lombok.RequiredArgsConstructor; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -8,17 +10,20 @@ import java.util.Set; import java.util.UUID; import java.util.stream.Stream; - -public class PlayerManager { +@RequiredArgsConstructor +public final class PlayerManager { private final Set participants = new HashSet<>(); private final Set spectators = new HashSet<>(); - public final Stream getParticipants() { + private final MinigameManager minigameManager = ScrowAPI.getMinigameManager(); + private final Minigame minigame; + + public Stream getParticipants() { return participants.stream().map(Bukkit::getPlayer); } - public final Stream getSpectators() { + public Stream getSpectators() { return spectators.stream().map(Bukkit::getPlayer); } @@ -28,12 +33,14 @@ public class PlayerManager { public void addParticipant(Player player) { participants.add(player.getUniqueId()); + minigameManager.setMinigame(player, minigame); } /** * @return if the player was a participant */ public boolean removeParticipant(Player player) { + minigameManager.setMinigame(player, null); return participants.remove(player.getUniqueId()); } diff --git a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/lobby/LobbyMinigame.java b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/lobby/LobbyMinigame.java new file mode 100644 index 0000000..a08b2b0 --- /dev/null +++ b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/lobby/LobbyMinigame.java @@ -0,0 +1,46 @@ +package de.kentoj.scrow.bukkit.minigame.lobby; + +import de.kentoj.scrow.bukkit.gameserver.GameServer; +import de.kentoj.scrow.bukkit.minigame.Minigame; +import de.kentoj.scrow.bukkit.minigame.PlayerManager; +import de.kentoj.scrowlib.convention.ScrowMessageStyle; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; + +import java.util.concurrent.CompletableFuture; + +@RequiredArgsConstructor +public class LobbyMinigame implements Minigame { + + @Getter + private final String gameName; + @Getter + private final ScrowMessageStyle messageStyle; + @Getter + @Setter + private GameServer gameServer = null; + @Getter + @Setter + private CompletableFuture destroyGameServer; + + @Override + public int getMinParticipants() { + return 0; + } + + @Override + public int getMaxParticipants() { + return 0; + } + + @Override + public PlayerManager getPlayerManager() { + return null; + } + + @Override + public CompletableFuture start() { + return null; + } +} diff --git a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/lobby/LobbyPhase.java b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/lobby/LobbyPhase.java index e548520..3b97728 100644 --- a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/lobby/LobbyPhase.java +++ b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/lobby/LobbyPhase.java @@ -1,9 +1,8 @@ package de.kentoj.scrow.bukkit.minigame.lobby; -import de.kentoj.scrow.bukkit.minigame.LinearPhaseFlow; -import de.kentoj.scrow.bukkit.minigame.Minigame; +import de.kentoj.scrow.bukkit.minigame.phaseflow.LinearPhaseFlow; import de.kentoj.scrow.bukkit.minigame.phase.CompositePhase; -import de.kentoj.scrow.bukkit.minigame.phase.PhaseContext; +import de.kentoj.scrow.bukkit.minigame.phaseflow.PhaseContext; import lombok.Getter; import org.bukkit.event.EventPriority; import org.bukkit.event.block.BlockBreakEvent; @@ -16,16 +15,16 @@ import org.bukkit.event.entity.FoodLevelChangeEvent; import org.bukkit.event.hanging.HangingBreakByEntityEvent; import org.bukkit.event.player.*; -public class LobbyPhase extends CompositePhase { +public class LobbyPhase extends CompositePhase { @Getter private final LinearPhaseFlow subPhaseFlow = new LinearPhaseFlow("lobby"); - public LobbyPhase(PhaseContext ctx) { + public LobbyPhase(PhaseContext ctx) { super(ctx); - var subCtx = new PhaseContext<>(ctx.game(), subPhaseFlow); + PhaseContext subCtx = new PhaseContext<>(ctx.game(), subPhaseFlow); subPhaseFlow.add(new WaitForMinimumPlayersPhase<>(subCtx)); - subPhaseFlow.add(new WaitForMaximumPlayersPhase<>(subCtx)); + subPhaseFlow.add(new WaitForMaximumPlayersPhase(subCtx)); } @Override diff --git a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/lobby/WaitForMaximumPlayersPhase.java b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/lobby/WaitForMaximumPlayersPhase.java index 8132672..d3532f8 100644 --- a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/lobby/WaitForMaximumPlayersPhase.java +++ b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/lobby/WaitForMaximumPlayersPhase.java @@ -1,27 +1,51 @@ package de.kentoj.scrow.bukkit.minigame.lobby; -import de.kentoj.scrow.bukkit.minigame.Minigame; -import de.kentoj.scrow.bukkit.minigame.phase.AbstractPhase; -import de.kentoj.scrow.bukkit.minigame.phase.PhaseContext; +import de.kentoj.scrow.bukkit.gameserver.GameServer; +import de.kentoj.scrow.bukkit.minigame.phase.Phase; +import de.kentoj.scrow.bukkit.minigame.phaseflow.PhaseContext; import org.bukkit.event.player.PlayerQuitEvent; -public class WaitForMaximumPlayersPhase extends AbstractPhase { +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; + +public class WaitForMaximumPlayersPhase extends Phase { private int secsLeft; + private CompletableFuture deployedServer; - public WaitForMaximumPlayersPhase(PhaseContext ctx) { + public WaitForMaximumPlayersPhase(PhaseContext ctx) { super(ctx); + + var delayedExecutor = CompletableFuture.delayedExecutor(3, TimeUnit.MINUTES); + ctx.game().setDestroyGameServer(CompletableFuture.runAsync(() -> { + synchronized (ctx.game().getGameServer()) { + ctx.game().getGameServer().destroy(); + } + }, delayedExecutor)); } @Override public void onStart() { this.secsLeft = 5; ctx.listeners().on(PlayerQuitEvent.class, this::onQuit); + + /* + this.deployedServer=Tasks.supplyAsync(() -> + gameServers.deployServer(ctx.game().getGameName())) + .mapSync(server -> { + ctx.game().setGameServer(server); + return server; + }).toFuture() + ctx.game().setGameServer(); + */ } private void onQuit(PlayerQuitEvent ev) { var isEnough = ctx.players().getParticipantCount() >= ctx.game().getMinParticipants(); - if (!isEnough) ctx.phases().rewindPhase(); + if (!isEnough) { + //deployedServer + ctx.phases().rewindPhase(); + } } @Override @@ -31,7 +55,7 @@ public class WaitForMaximumPlayersPhase extends AbstractPhas player.sendTitle("Game starting in " + secsLeft + " seconds", "have fun", 5, 20, 10) ); secsLeft--; - if (secsLeft == 0) super.advancePhase(); + if (secsLeft == 0) ctx.advancePhase(); } } diff --git a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/lobby/WaitForMinimumPlayersPhase.java b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/lobby/WaitForMinimumPlayersPhase.java index 49c14fe..c076ae0 100644 --- a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/lobby/WaitForMinimumPlayersPhase.java +++ b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/lobby/WaitForMinimumPlayersPhase.java @@ -1,11 +1,11 @@ package de.kentoj.scrow.bukkit.minigame.lobby; import de.kentoj.scrow.bukkit.minigame.Minigame; -import de.kentoj.scrow.bukkit.minigame.phase.AbstractPhase; -import de.kentoj.scrow.bukkit.minigame.phase.PhaseContext; +import de.kentoj.scrow.bukkit.minigame.phase.Phase; +import de.kentoj.scrow.bukkit.minigame.phaseflow.PhaseContext; import org.bukkit.event.player.PlayerJoinEvent; -public class WaitForMinimumPlayersPhase extends AbstractPhase { +public class WaitForMinimumPlayersPhase extends Phase { public WaitForMinimumPlayersPhase(PhaseContext ctx) { super(ctx); diff --git a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/phase/AbstractPhase.java b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/phase/AbstractPhase.java deleted file mode 100644 index 1e450b9..0000000 --- a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/phase/AbstractPhase.java +++ /dev/null @@ -1,78 +0,0 @@ -package de.kentoj.scrow.bukkit.minigame.phase; - -import com.google.errorprone.annotations.ForOverride; -import de.kentoj.scrow.bukkit.ScrowAPI; -import de.kentoj.scrow.bukkit.minigame.Minigame; -import de.kentoj.scrow.bukkit.minigame.PhaseFlow; -import lombok.RequiredArgsConstructor; -import org.bukkit.scheduler.BukkitRunnable; - -@RequiredArgsConstructor -public abstract class AbstractPhase implements Phase { - - protected final PhaseContext ctx; - - private boolean isActive = false; - - /** - * Shall call {@link PhaseFlow#advancePhase()} - */ - protected abstract void onStart(); - - /** - * Called together with {@link AbstractPhase#onEnd()} but only called when the phase was cancelled - * due to an error - */ - protected abstract void onCancel(); - - @ForOverride - protected void onEnd() { - } - - @ForOverride - protected void onTick(int tick) { - } - - @Override - public void cancel() { - onCancel(); - end(); - } - - public final void start() { - if (isActive) return; - isActive = true; - onStart(); - runTicker(); - } - - public final void end() { - if (!isActive) return; - ctx.listeners().unregisterAll(); - onEnd(); - isActive = false; - } - - /** - * end the current phase and advance to the next. - * same as {@link PhaseFlow#advancePhase()}. - */ - public final void advancePhase() { - ctx.phases().advancePhase(); - } - - private void runTicker() { - new BukkitRunnable() { - int tick = 0; - - @Override - public void run() { - if (!isActive) { - this.cancel(); - return; - } - onTick(tick++); - } - }.runTaskTimer(ScrowAPI.plugin, 1, 1); - } -} diff --git a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/phase/CompositePhase.java b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/phase/CompositePhase.java index ff011d0..3c73204 100644 --- a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/phase/CompositePhase.java +++ b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/phase/CompositePhase.java @@ -1,9 +1,9 @@ package de.kentoj.scrow.bukkit.minigame.phase; import de.kentoj.scrow.bukkit.minigame.Minigame; -import de.kentoj.scrow.bukkit.minigame.PhaseFlow; +import de.kentoj.scrow.bukkit.minigame.phaseflow.PhaseContext; -public abstract class CompositePhase extends AbstractPhase { +public abstract class CompositePhase extends Phase { public CompositePhase(PhaseContext ctx) { super(ctx); diff --git a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/phase/IPhase.java b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/phase/IPhase.java new file mode 100644 index 0000000..1161fa1 --- /dev/null +++ b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/phase/IPhase.java @@ -0,0 +1,10 @@ +package de.kentoj.scrow.bukkit.minigame.phase; + +public interface IPhase { + + void start(); + + void end(); + + void cancel(); +} diff --git a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/phase/Phase.java b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/phase/Phase.java index 14ee254..9ad19eb 100644 --- a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/phase/Phase.java +++ b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/phase/Phase.java @@ -1,10 +1,78 @@ package de.kentoj.scrow.bukkit.minigame.phase; -public interface Phase { +import com.google.errorprone.annotations.ForOverride; +import de.kentoj.scrow.bukkit.ScrowAPI; +import de.kentoj.scrow.bukkit.minigame.Minigame; +import de.kentoj.scrow.bukkit.minigame.phaseflow.PhaseContext; +import lombok.RequiredArgsConstructor; +import org.bukkit.scheduler.BukkitRunnable; - void start(); +@RequiredArgsConstructor +public abstract class Phase implements IPhase { - void end(); + protected final PhaseContext ctx; - void cancel(); + private boolean isActive = false; + + /** + * Shall call {@link PhaseFlow#advancePhase()} + */ + protected abstract void onStart(); + + /** + * Called together with {@link Phase#onEnd()} but only called when the phase was cancelled + * due to an error + */ + protected abstract void onCancel(); + + @ForOverride + protected void onEnd() { + } + + @ForOverride + protected void onTick(int tick) { + } + + @Override + public void cancel() { + end(); + onCancel(); + } + + public final void start() { + if (isActive) return; + isActive = true; + onStart(); + runTicker(); + } + + public final void end() { + if (!isActive) return; + ctx.listeners().unregisterAll(); + onEnd(); + isActive = false; + } + + /** + * end the current phase and advance to the next. + * same as {@link PhaseFlow#advancePhase()}. + */ + public final void advancePhase() { + ctx.phases().advancePhase(); + } + + private void runTicker() { + new BukkitRunnable() { + int tick = 0; + + @Override + public void run() { + if (!isActive) { + this.cancel(); + return; + } + onTick(tick++); + } + }.runTaskTimer(ScrowAPI.plugin, 1, 1); + } } diff --git a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/PhaseFlow.java b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/phase/PhaseFlow.java similarity index 90% rename from core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/PhaseFlow.java rename to core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/phase/PhaseFlow.java index 65070a1..15706f1 100644 --- a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/PhaseFlow.java +++ b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/phase/PhaseFlow.java @@ -1,4 +1,4 @@ -package de.kentoj.scrow.bukkit.minigame; +package de.kentoj.scrow.bukkit.minigame.phase; import java.util.concurrent.CompletableFuture; diff --git a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/LinearPhaseFlow.java b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/phaseflow/LinearPhaseFlow.java similarity index 85% rename from core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/LinearPhaseFlow.java rename to core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/phaseflow/LinearPhaseFlow.java index 01064b9..9a6b2ac 100644 --- a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/LinearPhaseFlow.java +++ b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/phaseflow/LinearPhaseFlow.java @@ -1,7 +1,8 @@ -package de.kentoj.scrow.bukkit.minigame; +package de.kentoj.scrow.bukkit.minigame.phaseflow; import com.google.common.base.Preconditions; -import de.kentoj.scrow.bukkit.minigame.phase.Phase; +import de.kentoj.scrow.bukkit.minigame.phase.IPhase; +import de.kentoj.scrow.bukkit.minigame.phase.PhaseFlow; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -18,17 +19,17 @@ public class LinearPhaseFlow implements PhaseFlow { @Getter private final String name; - private final List phases = new ArrayList<>(); + private final List phases = new ArrayList<>(); private CompletableFuture onEnd = null; private int curInd = -1; - public void add(Phase phase) { + public void add(IPhase phase) { this.phases.add(phase); } @Override public void advancePhase() { - Phase cur; + IPhase cur; cur = current(); if (cur != null) { cur.cancel(); @@ -82,11 +83,11 @@ public class LinearPhaseFlow implements PhaseFlow { return onEnd; } - private void startPhase(Phase phase) { + private void startPhase(IPhase phase) { this.startPhase(phase, true); } - private void startPhase(Phase phase, boolean recoverOnError) { + private void startPhase(IPhase phase, boolean recoverOnError) { if (!recoverOnError) { phase.start(); return; @@ -101,7 +102,7 @@ public class LinearPhaseFlow implements PhaseFlow { } } - private @Nullable Phase current() { + private @Nullable IPhase current() { if (curInd < 0 || curInd >= phases.size()) return null; return phases.get(curInd); } diff --git a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/phase/PhaseContext.java b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/phaseflow/PhaseContext.java similarity index 90% rename from core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/phase/PhaseContext.java rename to core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/phaseflow/PhaseContext.java index e4d90d6..31817f1 100644 --- a/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/phase/PhaseContext.java +++ b/core-bukkit-api/src/main/java/de/kentoj/scrow/bukkit/minigame/phaseflow/PhaseContext.java @@ -1,9 +1,9 @@ -package de.kentoj.scrow.bukkit.minigame.phase; +package de.kentoj.scrow.bukkit.minigame.phaseflow; import de.kentoj.kencommandapi.api.platform.MessageStyle; import de.kentoj.scrow.bukkit.minigame.Minigame; -import de.kentoj.scrow.bukkit.minigame.PhaseFlow; import de.kentoj.scrow.bukkit.minigame.PlayerManager; +import de.kentoj.scrow.bukkit.minigame.phase.PhaseFlow; import de.kentoj.scrow.bukkit.minigame.phase.event.PhaseListeners; import de.kentoj.scrow.bukkit.minigame.phase.event.PhaseListenersImpl; import lombok.RequiredArgsConstructor;