From 859ce6e395aab249489690392b7ca604a0057e4f Mon Sep 17 00:00:00 2001 From: TehSteel <50503589+TehSteel@users.noreply.github.com> Date: Sun, 17 Dec 2023 16:31:54 +0200 Subject: [PATCH 1/4] Update .gitignore --- .gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index e7f9c79..5a0acdf 100644 --- a/.gitignore +++ b/.gitignore @@ -21,5 +21,4 @@ manifest.mf *~ # Java -*.jar - +*.jar \ No newline at end of file From e44bc1e0e488e5f21a58b7ae801cda3d5ba30aa1 Mon Sep 17 00:00:00 2001 From: TehSteel <50503589+TehSteel@users.noreply.github.com> Date: Sun, 17 Dec 2023 16:37:47 +0200 Subject: [PATCH 2/4] refactor(arena) **Arena** - New SimpleArenaBuilder for easier arena creation usage - New Arena events **Util** - Modified CustomLocation to utilize record feature for better immutability and readability. - CustomLocation now serialize with json --- README.md | 14 +- pom.xml | 16 +- .../tehsteel/minigameapi/Constants.java | 9 - .../tehsteel/minigameapi/MiniGameLib.java | 42 ----- .../api/game/GameCountdownEvent.java | 36 ---- .../minigameapi/api/game/GameEndEvent.java | 29 --- .../minigameapi/api/game/GameStartEvent.java | 28 --- .../api/game/player/GamePlayerJoinEvent.java | 29 --- .../api/game/player/GamePlayerLoseEvent.java | 18 -- .../api/game/player/GamePlayerQuitEvent.java | 29 --- .../api/game/player/GamePlayerWinEvent.java | 18 -- .../minigameapi/arena/ArenaException.java | 8 - .../minigameapi/arena/ArenaState.java | 7 - .../tehsteel/minigameapi/game/GameState.java | 8 - .../tehsteel/minigameapi/game/model/Game.java | 170 ------------------ .../minigameapi/game/model/GameRound.java | 58 ------ .../minigameapi/util/CustomLocation.java | 77 -------- .../dev/tehsteel/minigameapi/MiniGameLib.java | 29 +++ .../api/arena/ArenaCreateEvent.java | 11 ++ .../api/arena/ArenaDeleteEvent.java | 10 ++ .../api/arena/model/ArenaEvent.java | 27 +++ .../minigameapi/api/game}/GameEvent.java | 8 +- .../minigameapi/arena/ArenaException.java | 16 ++ .../minigameapi/arena/ArenaState.java | 16 ++ .../minigameapi/arena/SimpleArenaBuilder.java | 127 +++++++++++++ .../minigameapi/arena/model/Arena.java | 77 +++++--- .../tehsteel/minigameapi/game/GameState.java | 4 + .../tehsteel/minigameapi/game/model/Game.java | 4 + .../minigameapi/game/model/SimpleGame.java | 4 + .../typeadapter/CustomLocationAdapter.java | 59 ++++++ .../minigameapi/util/CustomLocation.java | 24 +++ 31 files changed, 396 insertions(+), 616 deletions(-) delete mode 100644 src/main/java/com/github/tehsteel/minigameapi/Constants.java delete mode 100644 src/main/java/com/github/tehsteel/minigameapi/MiniGameLib.java delete mode 100644 src/main/java/com/github/tehsteel/minigameapi/api/game/GameCountdownEvent.java delete mode 100644 src/main/java/com/github/tehsteel/minigameapi/api/game/GameEndEvent.java delete mode 100644 src/main/java/com/github/tehsteel/minigameapi/api/game/GameStartEvent.java delete mode 100644 src/main/java/com/github/tehsteel/minigameapi/api/game/player/GamePlayerJoinEvent.java delete mode 100644 src/main/java/com/github/tehsteel/minigameapi/api/game/player/GamePlayerLoseEvent.java delete mode 100644 src/main/java/com/github/tehsteel/minigameapi/api/game/player/GamePlayerQuitEvent.java delete mode 100644 src/main/java/com/github/tehsteel/minigameapi/api/game/player/GamePlayerWinEvent.java delete mode 100644 src/main/java/com/github/tehsteel/minigameapi/arena/ArenaException.java delete mode 100644 src/main/java/com/github/tehsteel/minigameapi/arena/ArenaState.java delete mode 100644 src/main/java/com/github/tehsteel/minigameapi/game/GameState.java delete mode 100644 src/main/java/com/github/tehsteel/minigameapi/game/model/Game.java delete mode 100644 src/main/java/com/github/tehsteel/minigameapi/game/model/GameRound.java delete mode 100644 src/main/java/com/github/tehsteel/minigameapi/util/CustomLocation.java create mode 100644 src/main/java/dev/tehsteel/minigameapi/MiniGameLib.java create mode 100644 src/main/java/dev/tehsteel/minigameapi/api/arena/ArenaCreateEvent.java create mode 100644 src/main/java/dev/tehsteel/minigameapi/api/arena/ArenaDeleteEvent.java create mode 100644 src/main/java/dev/tehsteel/minigameapi/api/arena/model/ArenaEvent.java rename src/main/java/{com/github/tehsteel/minigameapi/api/game/model => dev/tehsteel/minigameapi/api/game}/GameEvent.java (82%) create mode 100644 src/main/java/dev/tehsteel/minigameapi/arena/ArenaException.java create mode 100644 src/main/java/dev/tehsteel/minigameapi/arena/ArenaState.java create mode 100644 src/main/java/dev/tehsteel/minigameapi/arena/SimpleArenaBuilder.java rename src/main/java/{com/github => dev}/tehsteel/minigameapi/arena/model/Arena.java (69%) create mode 100644 src/main/java/dev/tehsteel/minigameapi/game/GameState.java create mode 100644 src/main/java/dev/tehsteel/minigameapi/game/model/Game.java create mode 100644 src/main/java/dev/tehsteel/minigameapi/game/model/SimpleGame.java create mode 100644 src/main/java/dev/tehsteel/minigameapi/typeadapter/CustomLocationAdapter.java create mode 100644 src/main/java/dev/tehsteel/minigameapi/util/CustomLocation.java diff --git a/README.md b/README.md index a089a2b..48a11be 100644 --- a/README.md +++ b/README.md @@ -24,13 +24,13 @@ You may need to compile it from the source before using it. - - com.github.tehsteel - minigameapi - - VERSION - compile - + + dev.tehsteel + minigameapi + + VERSION + compile + ``` ### Initialize the Library diff --git a/pom.xml b/pom.xml index fcad198..5f03e97 100644 --- a/pom.xml +++ b/pom.xml @@ -4,9 +4,9 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.github.tehsteel + dev.tehsteel minigameapi - 1.0.0 + 1.0.1 17 @@ -15,20 +15,19 @@ - + spigot-repo https://hub.spigotmc.org/nexus/content/repositories/snapshots/ - org.spigotmc spigot-api - 1.20.1-R0.1-SNAPSHOT + 1.20.2-R0.1-SNAPSHOT provided @@ -36,7 +35,7 @@ org.projectlombok lombok - 1.18.28 + 1.18.30 provided @@ -55,7 +54,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.0 + 3.5.1 package @@ -78,5 +77,4 @@ - - + \ No newline at end of file diff --git a/src/main/java/com/github/tehsteel/minigameapi/Constants.java b/src/main/java/com/github/tehsteel/minigameapi/Constants.java deleted file mode 100644 index c8a8c71..0000000 --- a/src/main/java/com/github/tehsteel/minigameapi/Constants.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.github.tehsteel.minigameapi; - -public final class Constants { - - public static boolean DEBUG_MODE = false; - - private Constants() { - } -} diff --git a/src/main/java/com/github/tehsteel/minigameapi/MiniGameLib.java b/src/main/java/com/github/tehsteel/minigameapi/MiniGameLib.java deleted file mode 100644 index 9c49bc8..0000000 --- a/src/main/java/com/github/tehsteel/minigameapi/MiniGameLib.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.github.tehsteel.minigameapi; - -import lombok.Getter; -import org.bukkit.plugin.java.JavaPlugin; - -public final class MiniGameLib { - - @Getter - private static JavaPlugin plugin; - - /** - * Sets the main JavaPlugin instance for MiniGameLib. - * - * @param plugin The JavaPlugin instance to be set as the main plugin for MiniGameLib. - */ - public static void setPlugin(final JavaPlugin plugin) { - MiniGameLib.plugin = plugin; - } - - /** - * Sets the main JavaPlugin instance for MiniGameLib and configures debug mode. - * - * @param plugin The JavaPlugin instance to be set as the main plugin for MiniGameLib. - * @param debugMode Whether debug mode should be enabled or not. - */ - public static void setPlugin(final JavaPlugin plugin, final boolean debugMode) { - MiniGameLib.plugin = plugin; - Constants.DEBUG_MODE = debugMode; - } - - /** - * Sets the debug mode for MiniGameLib. - * - * @param debugMode Whether debug mode should be enabled or not. - */ - public static void setDebugMode(final boolean debugMode) { - Constants.DEBUG_MODE = debugMode; - } - - private MiniGameLib() { - } -} diff --git a/src/main/java/com/github/tehsteel/minigameapi/api/game/GameCountdownEvent.java b/src/main/java/com/github/tehsteel/minigameapi/api/game/GameCountdownEvent.java deleted file mode 100644 index 3959516..0000000 --- a/src/main/java/com/github/tehsteel/minigameapi/api/game/GameCountdownEvent.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.github.tehsteel.minigameapi.api.game; - -import com.github.tehsteel.minigameapi.api.game.model.GameEvent; -import com.github.tehsteel.minigameapi.game.model.Game; -import lombok.Getter; - -/** - * Represents an event for counting down in a game. - * This event is triggered when the startCountdown method is called. - */ -@Getter -public class GameCountdownEvent extends GameEvent { - - /** - * The number of seconds in the countdown. - */ - private final int seconds; - - /** - * Indicates if the countdown was forcefully started. - */ - private final boolean forceStart; - - /** - * Constructs a GameCountdownEvent. - * - * @param game The game associated with this event. - * @param seconds The number of seconds in the countdown. - * @param forceStart Indicates whether the countdown was forcefully started. - */ - public GameCountdownEvent(final Game game, final int seconds, final boolean forceStart) { - super(game); - this.seconds = seconds; - this.forceStart = forceStart; - } -} diff --git a/src/main/java/com/github/tehsteel/minigameapi/api/game/GameEndEvent.java b/src/main/java/com/github/tehsteel/minigameapi/api/game/GameEndEvent.java deleted file mode 100644 index 67493ce..0000000 --- a/src/main/java/com/github/tehsteel/minigameapi/api/game/GameEndEvent.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.github.tehsteel.minigameapi.api.game; - -import com.github.tehsteel.minigameapi.api.game.model.GameEvent; -import com.github.tehsteel.minigameapi.game.model.Game; -import lombok.Getter; - -/** - * Represents an event indicating the end of a game. - * Extends the base GameEvent class. - */ -@Getter -public class GameEndEvent extends GameEvent { - - /** - * Indicates whether the game was forcefully stopped. - */ - private final boolean forceStopped; - - /** - * Constructs a GameEndEvent. - * - * @param game The game associated with this event. - * @param forceStopped Indicates whether the game was forcefully stopped. - */ - public GameEndEvent(final Game game, final boolean forceStopped) { - super(game); - this.forceStopped = forceStopped; - } -} diff --git a/src/main/java/com/github/tehsteel/minigameapi/api/game/GameStartEvent.java b/src/main/java/com/github/tehsteel/minigameapi/api/game/GameStartEvent.java deleted file mode 100644 index a7434b8..0000000 --- a/src/main/java/com/github/tehsteel/minigameapi/api/game/GameStartEvent.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.github.tehsteel.minigameapi.api.game; - -import com.github.tehsteel.minigameapi.api.game.model.GameEvent; -import com.github.tehsteel.minigameapi.game.model.Game; -import lombok.Getter; - -/** - * Represents an event when a game starts. - */ -@Getter -public final class GameStartEvent extends GameEvent { - - /** - * Indicates if the game was forcefully started. - */ - private final boolean forceStart; - - /** - * Constructs a GameStartEvent. - * - * @param game The game associated with this event. - * @param forceStart Indicates whether the game was forcefully started. - */ - public GameStartEvent(final Game game, final boolean forceStart) { - super(game); - this.forceStart = forceStart; - } -} diff --git a/src/main/java/com/github/tehsteel/minigameapi/api/game/player/GamePlayerJoinEvent.java b/src/main/java/com/github/tehsteel/minigameapi/api/game/player/GamePlayerJoinEvent.java deleted file mode 100644 index 22d7130..0000000 --- a/src/main/java/com/github/tehsteel/minigameapi/api/game/player/GamePlayerJoinEvent.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.github.tehsteel.minigameapi.api.game.player; - -import com.github.tehsteel.minigameapi.api.game.model.GameEvent; -import com.github.tehsteel.minigameapi.game.model.Game; -import lombok.Getter; -import org.bukkit.entity.Player; - -/** - * Represents an event when a player joins a game. - */ -@Getter -public class GamePlayerJoinEvent extends GameEvent { - - /** - * The player who joined the game. - */ - private final Player player; - - /** - * Constructs a GamePlayerJoinEvent. - * - * @param game The game associated with this event. - * @param player The player who joined the game. - */ - public GamePlayerJoinEvent(final Game game, final Player player) { - super(game); - this.player = player; - } -} diff --git a/src/main/java/com/github/tehsteel/minigameapi/api/game/player/GamePlayerLoseEvent.java b/src/main/java/com/github/tehsteel/minigameapi/api/game/player/GamePlayerLoseEvent.java deleted file mode 100644 index 5447e2b..0000000 --- a/src/main/java/com/github/tehsteel/minigameapi/api/game/player/GamePlayerLoseEvent.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.github.tehsteel.minigameapi.api.game.player; - -import com.github.tehsteel.minigameapi.api.game.model.GameEvent; -import com.github.tehsteel.minigameapi.game.model.Game; -import lombok.Getter; -import org.bukkit.entity.Player; - - -@Getter -public final class GamePlayerLoseEvent extends GameEvent { - - private final Player player; - - public GamePlayerLoseEvent(final Game game, final Player player) { - super(game); - this.player = player; - } -} diff --git a/src/main/java/com/github/tehsteel/minigameapi/api/game/player/GamePlayerQuitEvent.java b/src/main/java/com/github/tehsteel/minigameapi/api/game/player/GamePlayerQuitEvent.java deleted file mode 100644 index 5b367ce..0000000 --- a/src/main/java/com/github/tehsteel/minigameapi/api/game/player/GamePlayerQuitEvent.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.github.tehsteel.minigameapi.api.game.player; - -import com.github.tehsteel.minigameapi.api.game.model.GameEvent; -import com.github.tehsteel.minigameapi.game.model.Game; -import lombok.Getter; -import org.bukkit.entity.Player; - -/** - * Represents an event when a player quits or leaves a game. - */ -@Getter -public class GamePlayerQuitEvent extends GameEvent { - - /** - * The player who quit or left the game. - */ - private final Player player; - - /** - * Constructs a GamePlayerQuitEvent. - * - * @param game The game associated with this event. - * @param player The player who quit or left the game. - */ - public GamePlayerQuitEvent(final Game game, final Player player) { - super(game); - this.player = player; - } -} diff --git a/src/main/java/com/github/tehsteel/minigameapi/api/game/player/GamePlayerWinEvent.java b/src/main/java/com/github/tehsteel/minigameapi/api/game/player/GamePlayerWinEvent.java deleted file mode 100644 index 33a1092..0000000 --- a/src/main/java/com/github/tehsteel/minigameapi/api/game/player/GamePlayerWinEvent.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.github.tehsteel.minigameapi.api.game.player; - -import com.github.tehsteel.minigameapi.api.game.model.GameEvent; -import com.github.tehsteel.minigameapi.game.model.Game; -import lombok.Getter; -import org.bukkit.entity.Player; - - -@Getter -public final class GamePlayerWinEvent extends GameEvent { - - private final Player player; - - public GamePlayerWinEvent(final Game game, final Player player) { - super(game); - this.player = player; - } -} diff --git a/src/main/java/com/github/tehsteel/minigameapi/arena/ArenaException.java b/src/main/java/com/github/tehsteel/minigameapi/arena/ArenaException.java deleted file mode 100644 index 5492401..0000000 --- a/src/main/java/com/github/tehsteel/minigameapi/arena/ArenaException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.github.tehsteel.minigameapi.arena; - -public class ArenaException extends Exception { - - public ArenaException(String message) { - super(message); - } -} diff --git a/src/main/java/com/github/tehsteel/minigameapi/arena/ArenaState.java b/src/main/java/com/github/tehsteel/minigameapi/arena/ArenaState.java deleted file mode 100644 index 07ce318..0000000 --- a/src/main/java/com/github/tehsteel/minigameapi/arena/ArenaState.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.github.tehsteel.minigameapi.arena; - -public enum ArenaState { - - READY, - INGAME, -} diff --git a/src/main/java/com/github/tehsteel/minigameapi/game/GameState.java b/src/main/java/com/github/tehsteel/minigameapi/game/GameState.java deleted file mode 100644 index 0f9d06f..0000000 --- a/src/main/java/com/github/tehsteel/minigameapi/game/GameState.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.github.tehsteel.minigameapi.game; - -public enum GameState { - WAITING, - COUNTDOWN, - INGAME, - ENDGAME, -} diff --git a/src/main/java/com/github/tehsteel/minigameapi/game/model/Game.java b/src/main/java/com/github/tehsteel/minigameapi/game/model/Game.java deleted file mode 100644 index 5914aac..0000000 --- a/src/main/java/com/github/tehsteel/minigameapi/game/model/Game.java +++ /dev/null @@ -1,170 +0,0 @@ -package com.github.tehsteel.minigameapi.game.model; - -import com.github.tehsteel.minigameapi.api.game.GameCountdownEvent; -import com.github.tehsteel.minigameapi.api.game.GameEndEvent; -import com.github.tehsteel.minigameapi.api.game.GameStartEvent; -import com.github.tehsteel.minigameapi.api.game.model.GameEvent; -import com.github.tehsteel.minigameapi.api.game.player.GamePlayerJoinEvent; -import com.github.tehsteel.minigameapi.api.game.player.GamePlayerLoseEvent; -import com.github.tehsteel.minigameapi.api.game.player.GamePlayerQuitEvent; -import com.github.tehsteel.minigameapi.api.game.player.GamePlayerWinEvent; -import com.github.tehsteel.minigameapi.arena.ArenaState; -import com.github.tehsteel.minigameapi.arena.model.Arena; -import com.github.tehsteel.minigameapi.game.GameState; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import lombok.Setter; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; - -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; - -@RequiredArgsConstructor -public abstract class Game { - - @Getter private final Arena arena; - @Getter private final Set players = new HashSet<>(); - @Getter @Setter private GameState state = GameState.WAITING; - @Getter @Setter private int countdown = 10; - - - /** - * Starts the game if there are enough players or if forceStart is set to true. - * Triggers a GameStartEvent with the specified forceStart parameter. - * The game will not start if the number of players is less than the required minimum and forceStart is false. - * - * @param forceStart If true, the game will start regardless of the number of players. If false, - * the game will only start if the minimum required players are present. - * @see GameStartEvent - */ - public final void startGame(final boolean forceStart) { - if (players.size() < arena.getMinPlayers() && !forceStart) return; - fireGameEvent(new GameStartEvent(this, forceStart)); - getArena().setState(ArenaState.INGAME); - setState(GameState.INGAME); - } - - /** - * Initiates a countdown before starting the game if there are enough players or if forceStart is set to true. - * Triggers a GameCountdownEvent with the specified countdown duration and forceStart parameter. - * The countdown will not initiate if the number of players is less than the required minimum and forceStart is false. - * - * @param forceStart If true, the countdown and game start will proceed regardless of the number of players. If false, - * the countdown will only initiate if the minimum required players are present. - * @see GameCountdownEvent - */ - public final void startCountdown(final boolean forceStart) { - if (players.size() < arena.getMinPlayers() && !forceStart) return; - fireGameEvent(new GameCountdownEvent(this, countdown, forceStart)); - setState(GameState.COUNTDOWN); - getArena().setState(ArenaState.INGAME); - } - - /** - * Ends the game, triggering a GameEndEvent. - * If forceStop is true, the game will end regardless of its current state. - * If forceStop is false, the game will only end if the conditions for ending are met. - * - * @param forceStop If true, the game will end immediately. If false, the game will end only if the - * conditions for ending are met. - * @see GameEndEvent - */ - public final void endGame(final boolean forceStop) { - if (!forceStop && !shouldGameEnd()) return; - fireGameEvent(new GameEndEvent(this, forceStop)); - setState(GameState.ENDGAME); - } - - /** - * Forces the immediate start of the game by triggering a GameStartEvent with forceStart set to true. - * This bypasses any player count requirements. - * - * @see GameStartEvent - */ - public final void forceStartGame() { - fireGameEvent(new GameStartEvent(this, true)); - getArena().setState(ArenaState.INGAME); - } - - /** - * Checks if the game is in a state where players can join freely. - * The game is considered free if it's in the WAITING state or in the COUNTDOWN state - * with the number of players less than the maximum allowed. - * - * @return True if the game is in a free state, otherwise false. - */ - public final boolean isGameFree() { - return state == GameState.WAITING || state == GameState.COUNTDOWN && players.size() < arena.getMaxPlayers(); - } - - /** - * Adds a player to the game and triggers a GamePlayerJoinEvent. - * Ensure not to trigger twice to prevent an endless loop. - * - * @param player The player to be added to the game. This will also be included in the GamePlayerJoinEvent. - */ - public final void addPlayer(final Player player) { - players.add(player); - fireGameEvent(new GamePlayerJoinEvent(this, player)); - startCountdown(false); - } - - /** - * Removes a player from the game and triggers a GamePlayerQuitEvent. - * - * @param player The player to be removed from the game. This will also be included in the GamePlayerQuitEvent. - */ - public final void removePlayer(final Player player) { - players.remove(player); - fireGameEvent(new GamePlayerQuitEvent(this, player)); - } - - /** - * @param player - */ - public final void onPlayerWin(final Player player) { - fireGameEvent(new GamePlayerWinEvent(this, player)); - } - - /** - * @param player - */ - public final void onPlayerLose(final Player player) { - fireGameEvent(new GamePlayerLoseEvent(this, player)); - } - - /** - * Resets the game to its initial state, allowing for a fresh start. - * This method should clear any in-progress game data and reinitialize - * all relevant game parameters and variables. - */ - public abstract void resetGame(); - - /** - * Determines whether the game should end based on specific conditions. - * - * @return True if the game should end, otherwise false. - */ - public abstract boolean shouldGameEnd(); - - /** - * Fires a custom GameEvent by calling the Bukkit event system. - * - * @param event The GameEvent to be fired. - * @param The type of GameEvent to be fired. - */ - private void fireGameEvent(final T event) { - if (event.isCancelled()) return; - Bukkit.getServer().getPluginManager().callEvent(event); - } - - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - final Game game = (Game) o; - return countdown == game.countdown && Objects.equals(arena, game.arena) && Objects.equals(players, game.players) && state == game.state; - } -} diff --git a/src/main/java/com/github/tehsteel/minigameapi/game/model/GameRound.java b/src/main/java/com/github/tehsteel/minigameapi/game/model/GameRound.java deleted file mode 100644 index 7e2a395..0000000 --- a/src/main/java/com/github/tehsteel/minigameapi/game/model/GameRound.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.github.tehsteel.minigameapi.game.model; - -import com.github.tehsteel.minigameapi.MiniGameLib; -import com.github.tehsteel.minigameapi.api.game.GameStartEvent; -import com.github.tehsteel.minigameapi.arena.model.Arena; -import com.google.common.annotations.Beta; -import lombok.Getter; -import lombok.Setter; -import org.bukkit.Bukkit; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.scheduler.BukkitTask; - -@Beta -public abstract class GameRound extends Game implements Runnable, Listener { - - @Getter @Setter private int roundSeconds; - @Getter @Setter private int rounds; - @Getter @Setter private long runEveryTick; - @Getter private int runnableTaskId; - - public GameRound(final Arena arena) { - super(arena); - - - } - - public abstract boolean shouldNextRoundStart(); - - public abstract void startNextRound(); - - public abstract void onTick(); - - public abstract void onEnd(); - - protected void onError() { - } - - - private void runTask() { - final BukkitTask task = Bukkit.getScheduler().runTaskTimer(MiniGameLib.getPlugin(), this, runEveryTick, runEveryTick); - - runnableTaskId = task.getTaskId(); - } - - @EventHandler - public void onGameStart(final GameStartEvent event) { - if (event.getGame() == this) { - runTask(); - } - } - - - @Override - public void run() { - - } -} diff --git a/src/main/java/com/github/tehsteel/minigameapi/util/CustomLocation.java b/src/main/java/com/github/tehsteel/minigameapi/util/CustomLocation.java deleted file mode 100644 index a18c596..0000000 --- a/src/main/java/com/github/tehsteel/minigameapi/util/CustomLocation.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.github.tehsteel.minigameapi.util; - -import lombok.AllArgsConstructor; -import lombok.NonNull; -import org.bukkit.Bukkit; -import org.bukkit.Location; - -@AllArgsConstructor -public final class CustomLocation { - - private final String world; - - private final double x; - private final double y; - private final double z; - - private final float yaw; - private final float pitch; - - /** - * Creates a CustomLocation object from a Bukkit Location. - * - * @param location The Bukkit Location to be converted. - * @return A CustomLocation object equivalent to the given Bukkit Location. - */ - public static CustomLocation fromBukkitLocation(final Location location) { - return new CustomLocation(location.getWorld().getName(), - location.getX(), - location.getY(), - location.getZ(), - location.getYaw(), - location.getPitch() - ); - } - - /** - * Deserializes a string into a CustomLocation object. - * - * @param location A string representation of the CustomLocation. - * @return The deserialized CustomLocation object. - * @throws NullPointerException if the input string is null. - * @throws NumberFormatException if the input string is not in the expected format. - */ - public static CustomLocation deserialize(@NonNull final String location) { - final String[] strings = location.split(" "); - - final String worldName = strings[0]; - - final double x = Double.parseDouble(strings[1]); - final double y = Double.parseDouble(strings[2]); - final double z = Double.parseDouble(strings[3]); - - final float yaw = Float.parseFloat(strings[4]); - final float pitch = Float.parseFloat(strings[5]); - - return new CustomLocation(worldName, x, y, z, yaw, pitch); - } - - /** - * Converts a CustomLocation object to a Bukkit Location. - * - * @return The Bukkit Location. - */ - public Location toBukkitLocation() { - return new Location(Bukkit.getWorld(world), x, y, z, yaw, pitch); - } - - /** - * Serializes a CustomLocation object into a string format. - * - * @return The serialized string. - */ - public String serialize() { - return world + " " + x + " " + y + " " + z + " " + yaw + " " + pitch; - } - -} \ No newline at end of file diff --git a/src/main/java/dev/tehsteel/minigameapi/MiniGameLib.java b/src/main/java/dev/tehsteel/minigameapi/MiniGameLib.java new file mode 100644 index 0000000..bf98730 --- /dev/null +++ b/src/main/java/dev/tehsteel/minigameapi/MiniGameLib.java @@ -0,0 +1,29 @@ +package dev.tehsteel.minigameapi; + + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import dev.tehsteel.minigameapi.typeadapter.CustomLocationAdapter; +import dev.tehsteel.minigameapi.util.CustomLocation; +import lombok.Getter; +import org.bukkit.plugin.java.JavaPlugin; + +public final class MiniGameLib { + + @Getter private static JavaPlugin plugin; + @Getter private static Gson gson = new GsonBuilder() + .registerTypeAdapter(CustomLocation.class, new CustomLocationAdapter()) + .create(); + + /** + * Sets the main JavaPlugin instance for MiniGameLib. + * + * @param plugin The JavaPlugin instance to be set as the main plugin for MiniGameLib. + */ + public static void setPlugin(final JavaPlugin plugin) { + MiniGameLib.plugin = plugin; + } + + private MiniGameLib() { + } +} diff --git a/src/main/java/dev/tehsteel/minigameapi/api/arena/ArenaCreateEvent.java b/src/main/java/dev/tehsteel/minigameapi/api/arena/ArenaCreateEvent.java new file mode 100644 index 0000000..a5f71b9 --- /dev/null +++ b/src/main/java/dev/tehsteel/minigameapi/api/arena/ArenaCreateEvent.java @@ -0,0 +1,11 @@ +package dev.tehsteel.minigameapi.api.arena; + +import dev.tehsteel.minigameapi.api.arena.model.ArenaEvent; +import dev.tehsteel.minigameapi.arena.model.Arena; + +public final class ArenaCreateEvent extends ArenaEvent { + + public ArenaCreateEvent(final Arena arena) { + super(arena); + } +} diff --git a/src/main/java/dev/tehsteel/minigameapi/api/arena/ArenaDeleteEvent.java b/src/main/java/dev/tehsteel/minigameapi/api/arena/ArenaDeleteEvent.java new file mode 100644 index 0000000..799d46a --- /dev/null +++ b/src/main/java/dev/tehsteel/minigameapi/api/arena/ArenaDeleteEvent.java @@ -0,0 +1,10 @@ +package dev.tehsteel.minigameapi.api.arena; + +import dev.tehsteel.minigameapi.api.arena.model.ArenaEvent; +import dev.tehsteel.minigameapi.arena.model.Arena; + +public class ArenaDeleteEvent extends ArenaEvent { + public ArenaDeleteEvent(final Arena arena) { + super(arena); + } +} diff --git a/src/main/java/dev/tehsteel/minigameapi/api/arena/model/ArenaEvent.java b/src/main/java/dev/tehsteel/minigameapi/api/arena/model/ArenaEvent.java new file mode 100644 index 0000000..8112fb1 --- /dev/null +++ b/src/main/java/dev/tehsteel/minigameapi/api/arena/model/ArenaEvent.java @@ -0,0 +1,27 @@ +package dev.tehsteel.minigameapi.api.arena.model; + +import dev.tehsteel.minigameapi.arena.model.Arena; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +@Getter +@RequiredArgsConstructor +public class ArenaEvent extends Event implements Cancellable { + private static final HandlerList HANDLERS = new HandlerList(); + + private final Arena arena; + @Setter private boolean cancelled; + + public static HandlerList getHandlerList() { + return HANDLERS; + } + + @Override + public HandlerList getHandlers() { + return HANDLERS; + } +} \ No newline at end of file diff --git a/src/main/java/com/github/tehsteel/minigameapi/api/game/model/GameEvent.java b/src/main/java/dev/tehsteel/minigameapi/api/game/GameEvent.java similarity index 82% rename from src/main/java/com/github/tehsteel/minigameapi/api/game/model/GameEvent.java rename to src/main/java/dev/tehsteel/minigameapi/api/game/GameEvent.java index cdc7b16..9098d9c 100644 --- a/src/main/java/com/github/tehsteel/minigameapi/api/game/model/GameEvent.java +++ b/src/main/java/dev/tehsteel/minigameapi/api/game/GameEvent.java @@ -1,6 +1,6 @@ -package com.github.tehsteel.minigameapi.api.game.model; +package dev.tehsteel.minigameapi.api.game; -import com.github.tehsteel.minigameapi.game.model.Game; +import dev.tehsteel.minigameapi.game.model.Game; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Setter; @@ -24,6 +24,4 @@ public static HandlerList getHandlerList() { public HandlerList getHandlers() { return HANDLERS; } - - -} +} \ No newline at end of file diff --git a/src/main/java/dev/tehsteel/minigameapi/arena/ArenaException.java b/src/main/java/dev/tehsteel/minigameapi/arena/ArenaException.java new file mode 100644 index 0000000..5827ea9 --- /dev/null +++ b/src/main/java/dev/tehsteel/minigameapi/arena/ArenaException.java @@ -0,0 +1,16 @@ +package dev.tehsteel.minigameapi.arena; + +/** + * The ArenaException is an exception specific to Arena operations. + */ +public class ArenaException extends Exception { + + /** + * Constructs a new ArenaException with the specified detail message. + * + * @param message the detail message (which is saved for later retrieval by the getMessage() method) + */ + public ArenaException(final String message) { + super(message); + } +} diff --git a/src/main/java/dev/tehsteel/minigameapi/arena/ArenaState.java b/src/main/java/dev/tehsteel/minigameapi/arena/ArenaState.java new file mode 100644 index 0000000..a07ebdc --- /dev/null +++ b/src/main/java/dev/tehsteel/minigameapi/arena/ArenaState.java @@ -0,0 +1,16 @@ +package dev.tehsteel.minigameapi.arena; + +/** + * The ArenaState enum represents different states of an arena. + */ +public enum ArenaState { + /** + * Represents the state when the arena is ready for use. + */ + READY, + + /** + * Represents the state when the arena is currently in-game. + */ + INGAME, +} diff --git a/src/main/java/dev/tehsteel/minigameapi/arena/SimpleArenaBuilder.java b/src/main/java/dev/tehsteel/minigameapi/arena/SimpleArenaBuilder.java new file mode 100644 index 0000000..8774258 --- /dev/null +++ b/src/main/java/dev/tehsteel/minigameapi/arena/SimpleArenaBuilder.java @@ -0,0 +1,127 @@ +package dev.tehsteel.minigameapi.arena; + +import dev.tehsteel.minigameapi.arena.model.Arena; +import org.bukkit.Location; + +import java.util.HashSet; +import java.util.Set; + +/** + * A builder class for constructing Arena easily with various properties. + */ +public final class SimpleArenaBuilder { + private final String name; + private Location waitingLocation; + private int maxPlayers; + private int minPlayers; + private ArenaState state = ArenaState.READY; + private Set spawnLocations = new HashSet<>(); + + /** + * Private constructor for SimpleArenaBuilder. + * + * @param name The name of the arena. + */ + private SimpleArenaBuilder(final String name) { + this.name = name; + } + + /** + * Static factory method to create an instance of SimpleArenaBuilder. + * + * @param name The name of the arena. + * @return A new instance of SimpleArenaBuilder. + */ + public static SimpleArenaBuilder of(final String name) { + return new SimpleArenaBuilder(name); + } + + /** + * Sets the waiting location for the arena. + * + * @param waitingLocation The location where players wait before starting the game. + * @return This SimpleArenaBuilder instance. + */ + public SimpleArenaBuilder withWaitingLocation(final Location waitingLocation) { + this.waitingLocation = waitingLocation; + + return this; + } + + /** + * Sets the maximum number of players allowed in the arena. + * + * @param maxPlayers The maximum number of players allowed. + * @return This SimpleArenaBuilder instance. + */ + public SimpleArenaBuilder withMaxPlayers(final int maxPlayers) { + this.maxPlayers = maxPlayers; + + return this; + } + + /** + * Sets the minimum number of players required to start the game in the arena. + * + * @param minPlayers The minimum number of players required. + * @return This SimpleArenaBuilder instance. + */ + public SimpleArenaBuilder withMinPlayers(final int minPlayers) { + this.minPlayers = minPlayers; + + return this; + } + + /** + * Sets the state of the arena. + * + * @param state The state of the arena. + * @return This SimpleArenaBuilder instance. + */ + public SimpleArenaBuilder withState(final ArenaState state) { + this.state = state; + + return this; + } + + /** + * Sets the spawn locations for the arena. + * + * @param spawnLocations The set of spawn locations for players in the arena. + * @return This SimpleArenaBuilder instance. + */ + public SimpleArenaBuilder withSpawnLocations(final Set spawnLocations) { + this.spawnLocations = spawnLocations; + + return this; + } + + /** + * Adds a spawn location for players in the arena. + * + * @param spawnLocation The spawn location to be added. + * @return This SimpleArenaBuilder instance. + */ + public SimpleArenaBuilder withSpawnLocation(final Location spawnLocation) { + this.spawnLocations.add(spawnLocation); + + return this; + } + + /** + * Builds and returns the configured Arena object. + * + * @return The constructed Arena object. + */ + public Arena build() { + final Arena arena = new Arena(name); + + arena.setWaitingLocation(waitingLocation); + arena.setMaxPlayers(maxPlayers); + arena.setMinPlayers(minPlayers); + arena.setState(state); + arena.setSpawnLocations(spawnLocations); + + return arena; + } +} diff --git a/src/main/java/com/github/tehsteel/minigameapi/arena/model/Arena.java b/src/main/java/dev/tehsteel/minigameapi/arena/model/Arena.java similarity index 69% rename from src/main/java/com/github/tehsteel/minigameapi/arena/model/Arena.java rename to src/main/java/dev/tehsteel/minigameapi/arena/model/Arena.java index e37a8ff..60b33b9 100644 --- a/src/main/java/com/github/tehsteel/minigameapi/arena/model/Arena.java +++ b/src/main/java/dev/tehsteel/minigameapi/arena/model/Arena.java @@ -1,10 +1,13 @@ -package com.github.tehsteel.minigameapi.arena.model; - - -import com.github.tehsteel.minigameapi.MiniGameLib; -import com.github.tehsteel.minigameapi.arena.ArenaException; -import com.github.tehsteel.minigameapi.arena.ArenaState; -import com.github.tehsteel.minigameapi.util.CustomLocation; +package dev.tehsteel.minigameapi.arena.model; + +import com.google.gson.Gson; +import dev.tehsteel.minigameapi.MiniGameLib; +import dev.tehsteel.minigameapi.api.arena.ArenaCreateEvent; +import dev.tehsteel.minigameapi.api.arena.ArenaDeleteEvent; +import dev.tehsteel.minigameapi.api.arena.model.ArenaEvent; +import dev.tehsteel.minigameapi.arena.ArenaException; +import dev.tehsteel.minigameapi.arena.ArenaState; +import dev.tehsteel.minigameapi.util.CustomLocation; import lombok.Getter; import lombok.Setter; import org.bukkit.Location; @@ -16,20 +19,20 @@ import java.io.File; import java.io.IOException; import java.util.HashSet; -import java.util.Objects; import java.util.Set; +@Getter public class Arena { - @Getter private final String name; - @Getter @Setter private Location waitingLocation; - @Getter @Setter private int maxPlayers; - @Getter @Setter private int minPlayers; - @Getter @Setter private ArenaState state = ArenaState.READY; - @Getter @Setter private Set spawnLocations = new HashSet<>(); + private final String name; + @Setter private Location waitingLocation; + @Setter private int maxPlayers; + @Setter private int minPlayers; + @Setter private ArenaState state = ArenaState.READY; + @Setter private Set spawnLocations = new HashSet<>(); - @Getter private File configFile; - @Getter private YamlConfiguration config = new YamlConfiguration(); + private File configFile; + private YamlConfiguration config = new YamlConfiguration(); /** * Creates a new Arena with the specified name. @@ -40,6 +43,8 @@ public class Arena { public Arena(final String name) { this.name = name; + fireArenaEvent(new ArenaCreateEvent(this)); + try { createArenaFile(); } catch (final ArenaException e) { @@ -62,6 +67,8 @@ public Arena(final Arena arena) { this.configFile = arena.configFile; this.config = arena.config; + fireArenaEvent(new ArenaCreateEvent(this)); + try { createArenaFile(); } catch (final ArenaException e) { @@ -84,6 +91,9 @@ public Arena(final String name, final Location waitingLocation, final int maxPla this.maxPlayers = maxPlayers; this.minPlayers = minPlayers; + + fireArenaEvent(new ArenaCreateEvent(this)); + try { createArenaFile(); } catch (final ArenaException e) { @@ -97,12 +107,21 @@ public Arena(final String name, final Location waitingLocation, final int maxPla * @param config The FileConfiguration object containing the serialized Arena data. * @return The deserialized Arena. */ - public static Arena deserialize(final FileConfiguration config) { + public static Arena deserialize(final FileConfiguration config) throws ArenaException { + final Gson gson = MiniGameLib.getGson(); + + if (config == null) { + throw new ArenaException("The config hasn't been initialized yet."); + } + + if (config.getString("ArenaData.name") == null || config.getString("ArenaData.name").isEmpty()) { + throw new ArenaException("The arena data named does not exist."); + } final Arena arena = new Arena(config.getString("ArenaData.name")); if (config.getString("ArenaData.waitingLocation") != null) - arena.setWaitingLocation(CustomLocation.deserialize(Objects.requireNonNull(config.getString("ArenaData.waitingLocation"))).toBukkitLocation()); + arena.setWaitingLocation(gson.fromJson(config.getString("ArenaData.waitingLocation"), CustomLocation.class).toBukkitLocation()); arena.setMaxPlayers(config.getInt("ArenaData.maxPlayers")); arena.setMinPlayers(config.getInt("ArenaData.minPlayers")); @@ -111,7 +130,7 @@ public static Arena deserialize(final FileConfiguration config) { if (section != null) { for (int i = 0; i < section.getKeys(false).size(); i++) { - arena.getSpawnLocations().add(CustomLocation.deserialize(Objects.requireNonNull(section.getString(String.valueOf(i)))).toBukkitLocation()); + arena.getSpawnLocations().add(gson.fromJson(section.getString(String.valueOf(i)), CustomLocation.class).toBukkitLocation()); } } @@ -135,6 +154,7 @@ public void saveConfig() throws ArenaException { * Deletes the arena configuration file from the file system. */ public void deleteArenaConfig() { + fireArenaEvent(new ArenaDeleteEvent(this)); configFile.delete(); } @@ -155,27 +175,20 @@ public boolean isArenaReady() { * @throws ArenaException If an error occurs during the creation or loading process. */ private void createArenaFile() throws ArenaException { - - // Define the file path for the arena configuration file configFile = new File(MiniGameLib.getPlugin().getDataFolder() + "/arenas", name + ".yml"); - // If the configuration file does not exist, create a new one if (!configFile.exists()) { - - // Ensure the parent directory exists; create if necessary if (!configFile.getParentFile().exists() && !configFile.getParentFile().mkdirs()) { - throw new ArenaException("Failed to create 'arenas' directory."); + throw new ArenaException("Failed to create arenas directory."); } try { - // Create a new file and load the configuration configFile.createNewFile(); config.load(configFile); } catch (IOException | InvalidConfigurationException e) { throw new ArenaException("Failed to create arena file: " + e.getMessage()); } } else { - // Load the existing configuration file try { config.load(configFile); } catch (IOException | InvalidConfigurationException e) { @@ -190,10 +203,11 @@ private void createArenaFile() throws ArenaException { * @throws ArenaException If an error occurs during the serialization process. */ public void serialize() throws ArenaException { + final Gson gson = MiniGameLib.getGson(); config.set("ArenaData.name", name); if (waitingLocation != null) { - config.set("ArenaData.waitingLocation", waitingLocation.serialize()); + config.set("ArenaData.waitingLocation", gson.toJson(CustomLocation.fromBukkitLocation(waitingLocation), CustomLocation.class)); } config.set("ArenaData.maxPlayers", maxPlayers); @@ -201,9 +215,14 @@ public void serialize() throws ArenaException { if (spawnLocations != null && !spawnLocations.isEmpty()) { for (int i = 0; i < spawnLocations.size(); i++) { - config.set("ArenaData.spawnLocations." + i, spawnLocations.stream().toList().get(i).serialize()); + config.set("ArenaData.spawnLocations." + i, gson.toJson(CustomLocation.fromBukkitLocation(spawnLocations.stream().toList().get(i)), CustomLocation.class)); } } saveConfig(); } + + private void fireArenaEvent(final T event) { + if (event.isCancelled()) return; + MiniGameLib.getPlugin().getServer().getPluginManager().callEvent(event); + } } \ No newline at end of file diff --git a/src/main/java/dev/tehsteel/minigameapi/game/GameState.java b/src/main/java/dev/tehsteel/minigameapi/game/GameState.java new file mode 100644 index 0000000..ac67e12 --- /dev/null +++ b/src/main/java/dev/tehsteel/minigameapi/game/GameState.java @@ -0,0 +1,4 @@ +package dev.tehsteel.minigameapi.game; + +public enum GameState { +} diff --git a/src/main/java/dev/tehsteel/minigameapi/game/model/Game.java b/src/main/java/dev/tehsteel/minigameapi/game/model/Game.java new file mode 100644 index 0000000..32726a8 --- /dev/null +++ b/src/main/java/dev/tehsteel/minigameapi/game/model/Game.java @@ -0,0 +1,4 @@ +package dev.tehsteel.minigameapi.game.model; + +public class Game { +} diff --git a/src/main/java/dev/tehsteel/minigameapi/game/model/SimpleGame.java b/src/main/java/dev/tehsteel/minigameapi/game/model/SimpleGame.java new file mode 100644 index 0000000..8139cf2 --- /dev/null +++ b/src/main/java/dev/tehsteel/minigameapi/game/model/SimpleGame.java @@ -0,0 +1,4 @@ +package dev.tehsteel.minigameapi.game.model; + +public class SimpleGame { +} diff --git a/src/main/java/dev/tehsteel/minigameapi/typeadapter/CustomLocationAdapter.java b/src/main/java/dev/tehsteel/minigameapi/typeadapter/CustomLocationAdapter.java new file mode 100644 index 0000000..9248bee --- /dev/null +++ b/src/main/java/dev/tehsteel/minigameapi/typeadapter/CustomLocationAdapter.java @@ -0,0 +1,59 @@ +package dev.tehsteel.minigameapi.typeadapter; + +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import dev.tehsteel.minigameapi.util.CustomLocation; + +import java.io.IOException; + +public class CustomLocationAdapter extends TypeAdapter { + @Override + public void write(final JsonWriter out, final CustomLocation customLocation) throws IOException { + out.beginObject(); + out.name("world").value(customLocation.world()); + out.name("x").value(customLocation.x()); + out.name("y").value(customLocation.y()); + out.name("z").value(customLocation.z()); + out.name("yaw").value(customLocation.yaw()); + out.name("pitch").value(customLocation.pitch()); + out.endObject(); + } + + @Override + public CustomLocation read(final JsonReader in) throws IOException { + String world = "world"; + double x = 0, y = 0, z = 0; + float yaw = 0, pitch = 0; + + in.beginObject(); + while (in.hasNext()) { + switch (in.nextName()) { + case "world": + world = in.nextString(); + break; + case "x": + x = in.nextDouble(); + break; + case "y": + y = in.nextDouble(); + break; + case "z": + z = in.nextDouble(); + break; + case "yaw": + yaw = (float) in.nextDouble(); + break; + case "pitch": + pitch = (float) in.nextDouble(); + break; + default: + in.skipValue(); + break; + } + } + + in.endObject(); + return new CustomLocation(world, x, y, z, yaw, pitch); + } +} diff --git a/src/main/java/dev/tehsteel/minigameapi/util/CustomLocation.java b/src/main/java/dev/tehsteel/minigameapi/util/CustomLocation.java new file mode 100644 index 0000000..61d3e8a --- /dev/null +++ b/src/main/java/dev/tehsteel/minigameapi/util/CustomLocation.java @@ -0,0 +1,24 @@ +package dev.tehsteel.minigameapi.util; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; + +public record CustomLocation(String world, double x, double y, double z, float yaw, float pitch) { + public Location toBukkitLocation() { + final World bukkitWorld = Bukkit.getWorld(world); + + if (bukkitWorld == null) { + throw new RuntimeException(""); + } + + return new Location(bukkitWorld, x, y, z, yaw, pitch); + } + + public static CustomLocation fromBukkitLocation(final Location location) { + if (location == null) { + throw new RuntimeException("Location hasn't been initialized."); + } + return new CustomLocation(location.getWorld().getName(), location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); + } +} From 1bcf595547d32bf29b5804804db5e3412e9e7e08 Mon Sep 17 00:00:00 2001 From: TehSteel <50503589+TehSteel@users.noreply.github.com> Date: Sun, 17 Dec 2023 16:39:20 +0200 Subject: [PATCH 3/4] Update SimpleArenaBuilder.java --- .../minigameapi/arena/{ => model}/SimpleArenaBuilder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename src/main/java/dev/tehsteel/minigameapi/arena/{ => model}/SimpleArenaBuilder.java (96%) diff --git a/src/main/java/dev/tehsteel/minigameapi/arena/SimpleArenaBuilder.java b/src/main/java/dev/tehsteel/minigameapi/arena/model/SimpleArenaBuilder.java similarity index 96% rename from src/main/java/dev/tehsteel/minigameapi/arena/SimpleArenaBuilder.java rename to src/main/java/dev/tehsteel/minigameapi/arena/model/SimpleArenaBuilder.java index 8774258..55a1013 100644 --- a/src/main/java/dev/tehsteel/minigameapi/arena/SimpleArenaBuilder.java +++ b/src/main/java/dev/tehsteel/minigameapi/arena/model/SimpleArenaBuilder.java @@ -1,6 +1,6 @@ -package dev.tehsteel.minigameapi.arena; +package dev.tehsteel.minigameapi.arena.model; -import dev.tehsteel.minigameapi.arena.model.Arena; +import dev.tehsteel.minigameapi.arena.ArenaState; import org.bukkit.Location; import java.util.HashSet; From 250415deb875fe88d4aba811e3449d2a420bdc78 Mon Sep 17 00:00:00 2001 From: TehSteel <50503589+TehSteel@users.noreply.github.com> Date: Tue, 26 Dec 2023 13:24:00 +0200 Subject: [PATCH 4/4] feat(game & arena): Finished game and arena classes --- README.md | 22 +-- .../api/arena/ArenaCreateEvent.java | 5 +- .../api/arena/ArenaDeleteEvent.java | 4 + .../api/arena/model/ArenaEvent.java | 4 + .../api/game/GameCountdownEvent.java | 22 +++ .../minigameapi/api/game/GameEndEvent.java | 21 +++ .../minigameapi/api/game/GameStartEvent.java | 21 +++ .../api/game/{ => model}/GameEvent.java | 6 +- .../api/game/player/GamePlayerJoinEvent.java | 21 +++ .../api/game/player/GamePlayerLoseEvent.java | 20 +++ .../api/game/player/GamePlayerQuitEvent.java | 20 +++ .../api/game/player/GamePlayerWinEvent.java | 20 +++ .../minigameapi/arena/ArenaException.java | 6 - .../minigameapi/arena/ArenaState.java | 7 - .../arena/{model => }/SimpleArenaBuilder.java | 16 +- .../minigameapi/arena/model/Arena.java | 34 ++-- .../tehsteel/minigameapi/game/GameState.java | 7 +- .../tehsteel/minigameapi/game/model/Game.java | 166 +++++++++++++++++- .../minigameapi/game/model/SimpleGame.java | 10 +- .../minigameapi/game/model/TimeBasedGame.java | 12 ++ .../typeadapter/CustomLocationAdapter.java | 6 +- .../minigameapi/util/CustomLocation.java | 2 +- 22 files changed, 384 insertions(+), 68 deletions(-) create mode 100644 src/main/java/dev/tehsteel/minigameapi/api/game/GameCountdownEvent.java create mode 100644 src/main/java/dev/tehsteel/minigameapi/api/game/GameEndEvent.java create mode 100644 src/main/java/dev/tehsteel/minigameapi/api/game/GameStartEvent.java rename src/main/java/dev/tehsteel/minigameapi/api/game/{ => model}/GameEvent.java (78%) create mode 100644 src/main/java/dev/tehsteel/minigameapi/api/game/player/GamePlayerJoinEvent.java create mode 100644 src/main/java/dev/tehsteel/minigameapi/api/game/player/GamePlayerLoseEvent.java create mode 100644 src/main/java/dev/tehsteel/minigameapi/api/game/player/GamePlayerQuitEvent.java create mode 100644 src/main/java/dev/tehsteel/minigameapi/api/game/player/GamePlayerWinEvent.java rename src/main/java/dev/tehsteel/minigameapi/arena/{model => }/SimpleArenaBuilder.java (89%) create mode 100644 src/main/java/dev/tehsteel/minigameapi/game/model/TimeBasedGame.java diff --git a/README.md b/README.md index 48a11be..ffba5be 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ # MiniGameAPI - [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) ![Java Version](https://img.shields.io/badge/Java-17%2B-blue.svg) [![Java CI with Maven](https://github.com/TehSteel/MiniGameAPI/actions/workflows/maven.yml/badge.svg?branch=main)](https://github.com/TehSteel/MiniGameAPI/actions/workflows/maven.yml) @@ -8,21 +7,17 @@ ## Table of Contents - - [Getting Started](#getting-started) -- [Project Status](#project-status) +- [Projects & Examples](#projects) - [License](#license) ## Getting Started You may need to compile it from the source before using it. - ```xml - - - jitpack.io - https://jitpack.io - - + + jitpack.io + https://jitpack.io + dev.tehsteel @@ -35,14 +30,13 @@ You may need to compile it from the source before using it. ### Initialize the Library -You must perform an initialization step to start using the Mini Game Library in your Java project. This step involves setting up essential configurations or providing necessary information for the library to function correctly. - +You must initialize the lib before start using the MiniGameLib in your project. ```java MiniGameLib.setPlugin(this); ``` -## Project Status -This project is currently under development and may not be stable. Use at your own risk. +## Projects +- [SpleefGame](https://github.com/TehSteel/SpleefGame) ## License This project is licensed under the [MIT License](LICENSE) - see the [LICENSE](LICENSE) file for details. diff --git a/src/main/java/dev/tehsteel/minigameapi/api/arena/ArenaCreateEvent.java b/src/main/java/dev/tehsteel/minigameapi/api/arena/ArenaCreateEvent.java index a5f71b9..2775da8 100644 --- a/src/main/java/dev/tehsteel/minigameapi/api/arena/ArenaCreateEvent.java +++ b/src/main/java/dev/tehsteel/minigameapi/api/arena/ArenaCreateEvent.java @@ -3,8 +3,11 @@ import dev.tehsteel.minigameapi.api.arena.model.ArenaEvent; import dev.tehsteel.minigameapi.arena.model.Arena; +/** + * Represents an event triggered when an arena is created. + * This event is fired when a new arena is created. + */ public final class ArenaCreateEvent extends ArenaEvent { - public ArenaCreateEvent(final Arena arena) { super(arena); } diff --git a/src/main/java/dev/tehsteel/minigameapi/api/arena/ArenaDeleteEvent.java b/src/main/java/dev/tehsteel/minigameapi/api/arena/ArenaDeleteEvent.java index 799d46a..8674b10 100644 --- a/src/main/java/dev/tehsteel/minigameapi/api/arena/ArenaDeleteEvent.java +++ b/src/main/java/dev/tehsteel/minigameapi/api/arena/ArenaDeleteEvent.java @@ -3,6 +3,10 @@ import dev.tehsteel.minigameapi.api.arena.model.ArenaEvent; import dev.tehsteel.minigameapi.arena.model.Arena; +/** + * Represents an event triggered when an arena is deleted. + * This event is fired when a new arena is deleted. + */ public class ArenaDeleteEvent extends ArenaEvent { public ArenaDeleteEvent(final Arena arena) { super(arena); diff --git a/src/main/java/dev/tehsteel/minigameapi/api/arena/model/ArenaEvent.java b/src/main/java/dev/tehsteel/minigameapi/api/arena/model/ArenaEvent.java index 8112fb1..87f8765 100644 --- a/src/main/java/dev/tehsteel/minigameapi/api/arena/model/ArenaEvent.java +++ b/src/main/java/dev/tehsteel/minigameapi/api/arena/model/ArenaEvent.java @@ -8,6 +8,10 @@ import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +/** + * Represents an event related to an arena. + * This event is used within the context of an arena events execution. + */ @Getter @RequiredArgsConstructor public class ArenaEvent extends Event implements Cancellable { diff --git a/src/main/java/dev/tehsteel/minigameapi/api/game/GameCountdownEvent.java b/src/main/java/dev/tehsteel/minigameapi/api/game/GameCountdownEvent.java new file mode 100644 index 0000000..942faf4 --- /dev/null +++ b/src/main/java/dev/tehsteel/minigameapi/api/game/GameCountdownEvent.java @@ -0,0 +1,22 @@ +package dev.tehsteel.minigameapi.api.game; + +import dev.tehsteel.minigameapi.api.game.model.GameEvent; +import dev.tehsteel.minigameapi.game.model.Game; +import lombok.Getter; + +/** + * Represents an event triggered when a game has started a countdown. + * This event is fired when a game has a countdown. + */ +@Getter +public class GameCountdownEvent extends GameEvent { + + private final int seconds; + private final boolean forceStart; + + public GameCountdownEvent(final Game game, final int seconds, final boolean forceStart) { + super(game); + this.seconds = seconds; + this.forceStart = forceStart; + } +} \ No newline at end of file diff --git a/src/main/java/dev/tehsteel/minigameapi/api/game/GameEndEvent.java b/src/main/java/dev/tehsteel/minigameapi/api/game/GameEndEvent.java new file mode 100644 index 0000000..733e93a --- /dev/null +++ b/src/main/java/dev/tehsteel/minigameapi/api/game/GameEndEvent.java @@ -0,0 +1,21 @@ +package dev.tehsteel.minigameapi.api.game; + + +import dev.tehsteel.minigameapi.api.game.model.GameEvent; +import dev.tehsteel.minigameapi.game.model.Game; +import lombok.Getter; + +/** + * Represents an event triggered when a game has ended. + * This event is fired when a game has ended. + */ +@Getter +public class GameEndEvent extends GameEvent { + + private final boolean forceStopped; + + public GameEndEvent(final Game game, final boolean forceStopped) { + super(game); + this.forceStopped = forceStopped; + } +} \ No newline at end of file diff --git a/src/main/java/dev/tehsteel/minigameapi/api/game/GameStartEvent.java b/src/main/java/dev/tehsteel/minigameapi/api/game/GameStartEvent.java new file mode 100644 index 0000000..38455dd --- /dev/null +++ b/src/main/java/dev/tehsteel/minigameapi/api/game/GameStartEvent.java @@ -0,0 +1,21 @@ +package dev.tehsteel.minigameapi.api.game; + + +import dev.tehsteel.minigameapi.api.game.model.GameEvent; +import dev.tehsteel.minigameapi.game.model.Game; +import lombok.Getter; + +/** + * Represents an event triggered when a game has started. + * This event is fired when a game has started. + */ +@Getter +public class GameStartEvent extends GameEvent { + + private final boolean forceStart; + + public GameStartEvent(final Game game, final boolean forceStart) { + super(game); + this.forceStart = forceStart; + } +} \ No newline at end of file diff --git a/src/main/java/dev/tehsteel/minigameapi/api/game/GameEvent.java b/src/main/java/dev/tehsteel/minigameapi/api/game/model/GameEvent.java similarity index 78% rename from src/main/java/dev/tehsteel/minigameapi/api/game/GameEvent.java rename to src/main/java/dev/tehsteel/minigameapi/api/game/model/GameEvent.java index 9098d9c..225ad91 100644 --- a/src/main/java/dev/tehsteel/minigameapi/api/game/GameEvent.java +++ b/src/main/java/dev/tehsteel/minigameapi/api/game/model/GameEvent.java @@ -1,4 +1,4 @@ -package dev.tehsteel.minigameapi.api.game; +package dev.tehsteel.minigameapi.api.game.model; import dev.tehsteel.minigameapi.game.model.Game; import lombok.Getter; @@ -8,6 +8,10 @@ import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +/** + * Represents an event related to a game. + * This event is used within the context of a game events' execution. + */ @Getter @RequiredArgsConstructor public class GameEvent extends Event implements Cancellable { diff --git a/src/main/java/dev/tehsteel/minigameapi/api/game/player/GamePlayerJoinEvent.java b/src/main/java/dev/tehsteel/minigameapi/api/game/player/GamePlayerJoinEvent.java new file mode 100644 index 0000000..de3155f --- /dev/null +++ b/src/main/java/dev/tehsteel/minigameapi/api/game/player/GamePlayerJoinEvent.java @@ -0,0 +1,21 @@ +package dev.tehsteel.minigameapi.api.game.player; + +import dev.tehsteel.minigameapi.api.game.model.GameEvent; +import dev.tehsteel.minigameapi.game.model.Game; +import lombok.Getter; +import org.bukkit.entity.Player; + + +/** + * Represents an event when a player joins a game. + */ +@Getter +public class GamePlayerJoinEvent extends GameEvent { + + private final Player player; + + public GamePlayerJoinEvent(final Game game, final Player player) { + super(game); + this.player = player; + } +} \ No newline at end of file diff --git a/src/main/java/dev/tehsteel/minigameapi/api/game/player/GamePlayerLoseEvent.java b/src/main/java/dev/tehsteel/minigameapi/api/game/player/GamePlayerLoseEvent.java new file mode 100644 index 0000000..f3027a9 --- /dev/null +++ b/src/main/java/dev/tehsteel/minigameapi/api/game/player/GamePlayerLoseEvent.java @@ -0,0 +1,20 @@ +package dev.tehsteel.minigameapi.api.game.player; + +import dev.tehsteel.minigameapi.api.game.model.GameEvent; +import dev.tehsteel.minigameapi.game.model.Game; +import lombok.Getter; +import org.bukkit.entity.Player; + +/** + * Represents an event when a player loses the game. + */ +@Getter +public class GamePlayerLoseEvent extends GameEvent { + + private final Player player; + + public GamePlayerLoseEvent(final Game game, final Player player) { + super(game); + this.player = player; + } +} \ No newline at end of file diff --git a/src/main/java/dev/tehsteel/minigameapi/api/game/player/GamePlayerQuitEvent.java b/src/main/java/dev/tehsteel/minigameapi/api/game/player/GamePlayerQuitEvent.java new file mode 100644 index 0000000..8829c94 --- /dev/null +++ b/src/main/java/dev/tehsteel/minigameapi/api/game/player/GamePlayerQuitEvent.java @@ -0,0 +1,20 @@ +package dev.tehsteel.minigameapi.api.game.player; + +import dev.tehsteel.minigameapi.api.game.model.GameEvent; +import dev.tehsteel.minigameapi.game.model.Game; +import lombok.Getter; +import org.bukkit.entity.Player; + +/** + * Represents an event when a player quits or leaves a game. + */ +@Getter +public class GamePlayerQuitEvent extends GameEvent { + + private final Player player; + + public GamePlayerQuitEvent(final Game game, final Player player) { + super(game); + this.player = player; + } +} \ No newline at end of file diff --git a/src/main/java/dev/tehsteel/minigameapi/api/game/player/GamePlayerWinEvent.java b/src/main/java/dev/tehsteel/minigameapi/api/game/player/GamePlayerWinEvent.java new file mode 100644 index 0000000..85cc83c --- /dev/null +++ b/src/main/java/dev/tehsteel/minigameapi/api/game/player/GamePlayerWinEvent.java @@ -0,0 +1,20 @@ +package dev.tehsteel.minigameapi.api.game.player; + +import dev.tehsteel.minigameapi.api.game.model.GameEvent; +import dev.tehsteel.minigameapi.game.model.Game; +import lombok.Getter; +import org.bukkit.entity.Player; + +/** + * Represents an event when a player wins the game. + */ +@Getter +public class GamePlayerWinEvent extends GameEvent { + + private final Player player; + + public GamePlayerWinEvent(final Game game, final Player player) { + super(game); + this.player = player; + } +} \ No newline at end of file diff --git a/src/main/java/dev/tehsteel/minigameapi/arena/ArenaException.java b/src/main/java/dev/tehsteel/minigameapi/arena/ArenaException.java index 5827ea9..8bf2978 100644 --- a/src/main/java/dev/tehsteel/minigameapi/arena/ArenaException.java +++ b/src/main/java/dev/tehsteel/minigameapi/arena/ArenaException.java @@ -4,12 +4,6 @@ * The ArenaException is an exception specific to Arena operations. */ public class ArenaException extends Exception { - - /** - * Constructs a new ArenaException with the specified detail message. - * - * @param message the detail message (which is saved for later retrieval by the getMessage() method) - */ public ArenaException(final String message) { super(message); } diff --git a/src/main/java/dev/tehsteel/minigameapi/arena/ArenaState.java b/src/main/java/dev/tehsteel/minigameapi/arena/ArenaState.java index a07ebdc..8959b86 100644 --- a/src/main/java/dev/tehsteel/minigameapi/arena/ArenaState.java +++ b/src/main/java/dev/tehsteel/minigameapi/arena/ArenaState.java @@ -4,13 +4,6 @@ * The ArenaState enum represents different states of an arena. */ public enum ArenaState { - /** - * Represents the state when the arena is ready for use. - */ READY, - - /** - * Represents the state when the arena is currently in-game. - */ INGAME, } diff --git a/src/main/java/dev/tehsteel/minigameapi/arena/model/SimpleArenaBuilder.java b/src/main/java/dev/tehsteel/minigameapi/arena/SimpleArenaBuilder.java similarity index 89% rename from src/main/java/dev/tehsteel/minigameapi/arena/model/SimpleArenaBuilder.java rename to src/main/java/dev/tehsteel/minigameapi/arena/SimpleArenaBuilder.java index 55a1013..7db358d 100644 --- a/src/main/java/dev/tehsteel/minigameapi/arena/model/SimpleArenaBuilder.java +++ b/src/main/java/dev/tehsteel/minigameapi/arena/SimpleArenaBuilder.java @@ -1,13 +1,13 @@ -package dev.tehsteel.minigameapi.arena.model; +package dev.tehsteel.minigameapi.arena; -import dev.tehsteel.minigameapi.arena.ArenaState; +import dev.tehsteel.minigameapi.arena.model.Arena; import org.bukkit.Location; import java.util.HashSet; import java.util.Set; /** - * A builder class for constructing Arena easily with various properties. + * A builder class for constructing Arena easily. */ public final class SimpleArenaBuilder { private final String name; @@ -17,11 +17,6 @@ public final class SimpleArenaBuilder { private ArenaState state = ArenaState.READY; private Set spawnLocations = new HashSet<>(); - /** - * Private constructor for SimpleArenaBuilder. - * - * @param name The name of the arena. - */ private SimpleArenaBuilder(final String name) { this.name = name; } @@ -111,9 +106,10 @@ public SimpleArenaBuilder withSpawnLocation(final Location spawnLocation) { /** * Builds and returns the configured Arena object. * - * @return The constructed Arena object. + * @return {@link Arena} The constructed Arena object. + * @throws ArenaException If an error occurs during the build process. */ - public Arena build() { + public Arena build() throws ArenaException { final Arena arena = new Arena(name); arena.setWaitingLocation(waitingLocation); diff --git a/src/main/java/dev/tehsteel/minigameapi/arena/model/Arena.java b/src/main/java/dev/tehsteel/minigameapi/arena/model/Arena.java index 60b33b9..f9ef0d2 100644 --- a/src/main/java/dev/tehsteel/minigameapi/arena/model/Arena.java +++ b/src/main/java/dev/tehsteel/minigameapi/arena/model/Arena.java @@ -21,6 +21,9 @@ import java.util.HashSet; import java.util.Set; +/** + * The Arena class represents an arena object. + */ @Getter public class Arena { @@ -38,27 +41,23 @@ public class Arena { * Creates a new Arena with the specified name. * * @param name The name of the arena. - * @throws RuntimeException If an ArenaException occurs during arena file creation. + * @throws ArenaException If an ArenaException occurs during arena file creation. */ - public Arena(final String name) { + public Arena(final String name) throws ArenaException { this.name = name; fireArenaEvent(new ArenaCreateEvent(this)); - try { - createArenaFile(); - } catch (final ArenaException e) { - throw new RuntimeException(e); - } + createArenaFile(); } /** * Creates a new Arena by copying attributes from an existing Arena. * * @param arena The existing Arena to copy attributes from. - * @throws RuntimeException If an ArenaException occurs during arena file creation. + * @throws ArenaException If an ArenaException occurs during arena file creation. */ - public Arena(final Arena arena) { + public Arena(final Arena arena) throws ArenaException { this.name = arena.name; this.waitingLocation = arena.waitingLocation; this.maxPlayers = arena.maxPlayers; @@ -69,11 +68,7 @@ public Arena(final Arena arena) { fireArenaEvent(new ArenaCreateEvent(this)); - try { - createArenaFile(); - } catch (final ArenaException e) { - throw new RuntimeException(e); - } + createArenaFile(); } /** @@ -83,22 +78,17 @@ public Arena(final Arena arena) { * @param waitingLocation The waiting location for players. * @param maxPlayers The maximum number of players allowed in the arena. * @param minPlayers The minimum number of players required to start the game. - * @throws RuntimeException If an ArenaException occurs during arena file creation. + * @throws ArenaException If an ArenaException occurs during arena file creation. */ - public Arena(final String name, final Location waitingLocation, final int maxPlayers, final int minPlayers) { + public Arena(final String name, final Location waitingLocation, final int maxPlayers, final int minPlayers) throws ArenaException { this.name = name; this.waitingLocation = waitingLocation; this.maxPlayers = maxPlayers; this.minPlayers = minPlayers; - fireArenaEvent(new ArenaCreateEvent(this)); - try { - createArenaFile(); - } catch (final ArenaException e) { - throw new RuntimeException(e); - } + createArenaFile(); } /** diff --git a/src/main/java/dev/tehsteel/minigameapi/game/GameState.java b/src/main/java/dev/tehsteel/minigameapi/game/GameState.java index ac67e12..5c90091 100644 --- a/src/main/java/dev/tehsteel/minigameapi/game/GameState.java +++ b/src/main/java/dev/tehsteel/minigameapi/game/GameState.java @@ -1,4 +1,9 @@ package dev.tehsteel.minigameapi.game; + public enum GameState { -} + WAITING, + COUNTDOWN, + INGAME, + ENDGAME, +} \ No newline at end of file diff --git a/src/main/java/dev/tehsteel/minigameapi/game/model/Game.java b/src/main/java/dev/tehsteel/minigameapi/game/model/Game.java index 32726a8..f1c4831 100644 --- a/src/main/java/dev/tehsteel/minigameapi/game/model/Game.java +++ b/src/main/java/dev/tehsteel/minigameapi/game/model/Game.java @@ -1,4 +1,168 @@ package dev.tehsteel.minigameapi.game.model; -public class Game { +import dev.tehsteel.minigameapi.api.game.GameCountdownEvent; +import dev.tehsteel.minigameapi.api.game.GameEndEvent; +import dev.tehsteel.minigameapi.api.game.GameStartEvent; +import dev.tehsteel.minigameapi.api.game.model.GameEvent; +import dev.tehsteel.minigameapi.api.game.player.GamePlayerJoinEvent; +import dev.tehsteel.minigameapi.api.game.player.GamePlayerLoseEvent; +import dev.tehsteel.minigameapi.api.game.player.GamePlayerQuitEvent; +import dev.tehsteel.minigameapi.api.game.player.GamePlayerWinEvent; +import dev.tehsteel.minigameapi.arena.ArenaState; +import dev.tehsteel.minigameapi.arena.model.Arena; +import dev.tehsteel.minigameapi.game.GameState; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.util.HashSet; +import java.util.Set; + +@Getter +@RequiredArgsConstructor +public abstract class Game { + + private final Arena arena; + private final Set players = new HashSet<>(); + @Setter private GameState state = GameState.WAITING; + @Setter private int countdown = 10; + + /** + * Starts the game if there are enough players or if forceStart is set to true. + * Triggers a GameStartEvent with the specified forceStart parameter. + * The game will not start if the number of players is less than the required minimum and forceStart is false. + * + * @param forceStart If true, the game will start regardless of the number of players. If false, + * the game will only start if the minimum required players are present. + * @see GameStartEvent + */ + public void startGame(final boolean forceStart) { + if (players.size() < arena.getMinPlayers() && !forceStart) return; + fireGameEvent(new GameStartEvent(this, forceStart)); + getArena().setState(ArenaState.INGAME); + setState(GameState.INGAME); + } + + /** + * Initiates a countdown before starting the game if there are enough players or if forceStart is set to true. + * Triggers a GameCountdownEvent with the specified countdown duration and forceStart parameter. + * The countdown will not initiate if the number of players is less than the required minimum and forceStart is false. + * + * @param forceStart If true, the countdown and game start will proceed regardless of the number of players. If false, + * the countdown will only initiate if the minimum required players are present. + * @see GameCountdownEvent + */ + public void startCountdown(final boolean forceStart) { + if (players.size() < arena.getMinPlayers() && !forceStart) return; + fireGameEvent(new GameCountdownEvent(this, countdown, forceStart)); + setState(GameState.COUNTDOWN); + getArena().setState(ArenaState.INGAME); + } + + /** + * Ends the game, triggering a GameEndEvent. + * If forceStop is true, the game will end regardless of its current state. + * If forceStop is false, the game will only end if the conditions for ending are met. + * + * @param forceStop If true, the game will end immediately. If false, the game will end only if the + * conditions for ending are met. + * @see GameEndEvent + */ + public void endGame(final boolean forceStop) { + if (!forceStop && !shouldGameEnd()) return; + fireGameEvent(new GameEndEvent(this, forceStop)); + setState(GameState.ENDGAME); + } + + /** + * Forces the immediate start of the game by triggering a GameStartEvent with forceStart set to true. + * This bypasses any player count requirements. + * + * @see GameStartEvent + */ + public void forceStartGame() { + fireGameEvent(new GameStartEvent(this, true)); + getArena().setState(ArenaState.INGAME); + } + + + /** + * Checks if the game is in a state where players can join freely. + * The game is considered free if it's in the WAITING state or in the COUNTDOWN state + * with the number of players less than the maximum allowed. + * + * @return True if the game is in a free state, otherwise false. + */ + public boolean isGameFree() { + return state == GameState.WAITING || state == GameState.COUNTDOWN && players.size() < arena.getMaxPlayers(); + } + + /** + * Adds a player to the game and triggers a GamePlayerJoinEvent. + * Ensure not to trigger twice to prevent an endless loop. + * + * @param player The player to be added to the game. This will also be included in the GamePlayerJoinEvent. + */ + public void addPlayer(final Player player) { + players.add(player); + fireGameEvent(new GamePlayerJoinEvent(this, player)); + startCountdown(false); + } + + /** + * Removes a player from the game and triggers a GamePlayerQuitEvent. + * + * @param player The player to be removed from the game. This will also be included in the GamePlayerQuitEvent. + */ + public void removePlayer(final Player player) { + players.remove(player); + fireGameEvent(new GamePlayerQuitEvent(this, player)); + } + + /** + * Triggers a game event indicating that the specified player has won the game. + * + * @param player The player who won the game. + */ + public void onPlayerWin(final Player player) { + fireGameEvent(new GamePlayerWinEvent(this, player)); + } + + /** + * Triggers a game event indicating that the specified player has lost the game. + * + * @param player The player that lost the game. + */ + public void onPlayerLose(final Player player) { + fireGameEvent(new GamePlayerLoseEvent(this, player)); + } + + /** + * Resets the game to its initial state, allowing for a fresh start. + * This method should clear any in-progress game data and reinitialize + * all relevant game parameters and variables. + */ + public void resetGame() { + + } + + /** + * Determines whether the game should end based on specific conditions. + * + * @return True if the game should end, otherwise false. + */ + public abstract boolean shouldGameEnd(); + + /** + * Fires a custom GameEvent by calling the Bukkit event system. + * + * @param event The GameEvent to be fired. + * @param The type of GameEvent to be fired. + */ + protected void fireGameEvent(final T event) { + if (event.isCancelled()) return; + Bukkit.getServer().getPluginManager().callEvent(event); + } } diff --git a/src/main/java/dev/tehsteel/minigameapi/game/model/SimpleGame.java b/src/main/java/dev/tehsteel/minigameapi/game/model/SimpleGame.java index 8139cf2..d74ab1f 100644 --- a/src/main/java/dev/tehsteel/minigameapi/game/model/SimpleGame.java +++ b/src/main/java/dev/tehsteel/minigameapi/game/model/SimpleGame.java @@ -1,4 +1,12 @@ package dev.tehsteel.minigameapi.game.model; -public class SimpleGame { +import dev.tehsteel.minigameapi.arena.model.Arena; + +public abstract class SimpleGame extends Game { + public SimpleGame(final Arena arena) { + super(arena); + } + + @Override + public abstract boolean shouldGameEnd(); } diff --git a/src/main/java/dev/tehsteel/minigameapi/game/model/TimeBasedGame.java b/src/main/java/dev/tehsteel/minigameapi/game/model/TimeBasedGame.java new file mode 100644 index 0000000..db21fba --- /dev/null +++ b/src/main/java/dev/tehsteel/minigameapi/game/model/TimeBasedGame.java @@ -0,0 +1,12 @@ +package dev.tehsteel.minigameapi.game.model; + +import dev.tehsteel.minigameapi.arena.model.Arena; + +public abstract class TimeBasedGame extends Game { + public TimeBasedGame(final Arena arena) { + super(arena); + } + + @Override + public abstract boolean shouldGameEnd(); +} diff --git a/src/main/java/dev/tehsteel/minigameapi/typeadapter/CustomLocationAdapter.java b/src/main/java/dev/tehsteel/minigameapi/typeadapter/CustomLocationAdapter.java index 9248bee..e8310ec 100644 --- a/src/main/java/dev/tehsteel/minigameapi/typeadapter/CustomLocationAdapter.java +++ b/src/main/java/dev/tehsteel/minigameapi/typeadapter/CustomLocationAdapter.java @@ -7,7 +7,7 @@ import java.io.IOException; -public class CustomLocationAdapter extends TypeAdapter { +public final class CustomLocationAdapter extends TypeAdapter { @Override public void write(final JsonWriter out, final CustomLocation customLocation) throws IOException { out.beginObject(); @@ -23,7 +23,7 @@ public void write(final JsonWriter out, final CustomLocation customLocation) thr @Override public CustomLocation read(final JsonReader in) throws IOException { String world = "world"; - double x = 0, y = 0, z = 0; + double x = 0.0, y = 0.0, z = 0.0; float yaw = 0, pitch = 0; in.beginObject(); @@ -52,7 +52,7 @@ public CustomLocation read(final JsonReader in) throws IOException { break; } } - + in.endObject(); return new CustomLocation(world, x, y, z, yaw, pitch); } diff --git a/src/main/java/dev/tehsteel/minigameapi/util/CustomLocation.java b/src/main/java/dev/tehsteel/minigameapi/util/CustomLocation.java index 61d3e8a..5e6307b 100644 --- a/src/main/java/dev/tehsteel/minigameapi/util/CustomLocation.java +++ b/src/main/java/dev/tehsteel/minigameapi/util/CustomLocation.java @@ -16,7 +16,7 @@ public Location toBukkitLocation() { } public static CustomLocation fromBukkitLocation(final Location location) { - if (location == null) { + if (location == null || location.getWorld() == null) { throw new RuntimeException("Location hasn't been initialized."); } return new CustomLocation(location.getWorld().getName(), location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());