From 74cf3589c07e4bd70246beca3c88fa9b6f8d9253 Mon Sep 17 00:00:00 2001 From: Teriuihi Date: Sat, 8 Feb 2025 23:00:04 +0100 Subject: [PATCH] Refactor configuration handling and add world border support Moved FLAG settings from Config to GameConfig for better modularity. Introduced world border configuration with types and sizes for different game phases. Updated related classes to utilize new configuration structure and added error handling to prevent runtime failures. --- src/main/java/com/alttd/ctf/Main.java | 4 +- .../java/com/alttd/ctf/config/Config.java | 17 ------ .../java/com/alttd/ctf/config/GameConfig.java | 53 ++++++++++++++++++- .../java/com/alttd/ctf/config/Messages.java | 2 +- .../alttd/ctf/config/WorldBorderSettings.java | 4 ++ .../com/alttd/ctf/config/WorldBorderType.java | 6 +++ .../com/alttd/ctf/events/OnPlayerDeath.java | 3 +- src/main/java/com/alttd/ctf/flag/Flag.java | 19 +++---- .../java/com/alttd/ctf/game/RunningGame.java | 29 +++++----- .../com/alttd/ctf/game/phases/EndedPhase.java | 4 +- version.properties | 4 +- 11 files changed, 95 insertions(+), 50 deletions(-) create mode 100644 src/main/java/com/alttd/ctf/config/WorldBorderSettings.java create mode 100644 src/main/java/com/alttd/ctf/config/WorldBorderType.java diff --git a/src/main/java/com/alttd/ctf/Main.java b/src/main/java/com/alttd/ctf/Main.java index 1221b21..b192452 100644 --- a/src/main/java/com/alttd/ctf/Main.java +++ b/src/main/java/com/alttd/ctf/Main.java @@ -52,8 +52,8 @@ public class Main extends JavaPlugin { flag = new Flag(this, gameManager); new CommandManager(this, gameManager, flag, worldBorderApi); //Ensuring immediate respawn is on in all worlds - log.info("Enabling immediate respawn for {}.", Config.FLAG.world); - World world = Bukkit.getWorld(Config.FLAG.world); + log.info("Enabling immediate respawn for {}.", GameConfig.FLAG.world); + World world = Bukkit.getWorld(GameConfig.FLAG.world); if (world != null) { world.setGameRule(GameRule.DO_IMMEDIATE_RESPAWN, true); } else { diff --git a/src/main/java/com/alttd/ctf/config/Config.java b/src/main/java/com/alttd/ctf/config/Config.java index 9f6220a..7958991 100644 --- a/src/main/java/com/alttd/ctf/config/Config.java +++ b/src/main/java/com/alttd/ctf/config/Config.java @@ -41,21 +41,4 @@ public class Config extends AbstractConfig{ } } - public static class FLAG { - private static final String prefix = "flag."; - - public static String world = "world"; - public static double x = 0; - public static double y = 0; - public static double z = 0; - - @SuppressWarnings("unused") - private static void load() { - world = config.getString(prefix, "world", world); - x = config.getDouble(prefix, "x", x); - y = config.getDouble(prefix, "y", y); - z = config.getDouble(prefix, "z", z); - } - } - } diff --git a/src/main/java/com/alttd/ctf/config/GameConfig.java b/src/main/java/com/alttd/ctf/config/GameConfig.java index 25134be..33929c2 100644 --- a/src/main/java/com/alttd/ctf/config/GameConfig.java +++ b/src/main/java/com/alttd/ctf/config/GameConfig.java @@ -8,7 +8,7 @@ import java.time.Duration; import java.util.HashMap; @Slf4j -public class GameConfig extends AbstractConfig{ +public class GameConfig extends AbstractConfig { static GameConfig config; @@ -45,4 +45,55 @@ public class GameConfig extends AbstractConfig{ } } + @SuppressWarnings("unused") + public static class WORLD_BORDER { + private static final String prefix = "world-border."; + + private static final HashMap GAME_PHASE_WORLD_BORDER = new HashMap<>(); + + public static HashMap getGAME_PHASE_WORLD_BORDER() { + return new HashMap<>(GAME_PHASE_WORLD_BORDER); + } + + @SuppressWarnings("unused") + private static void load() { + GAME_PHASE_WORLD_BORDER.clear(); + for (GamePhase phase : GamePhase.values()) { + String stringType = config.getString(prefix, phase.name().toLowerCase() + ".type", WorldBorderType.PLAYER.name()); + double size = config.getDouble(prefix, phase.name().toLowerCase() + ".size", 10); + + WorldBorderType worldBorderType; + try { + worldBorderType = WorldBorderType.valueOf(stringType); + } catch (IllegalArgumentException e) { + log.error("Invalid world border type [{}] in game phase world border config", stringType); + continue; + } + GAME_PHASE_WORLD_BORDER.put(phase, new WorldBorderSettings(worldBorderType, size)); + log.debug("Set {} phase world border type to {} blocks", phase.name(), size); + } + } + } + + public static class FLAG { + private static final String prefix = "flag."; + + public static String world = "world"; + public static double x = 0; + public static double y = 0; + public static double z = 0; + public static double CAPTURE_RADIUS = 7; + public static int WINNING_SCORE = 50; + + @SuppressWarnings("unused") + private static void load() { + world = config.getString(prefix, "world", world); + x = config.getDouble(prefix, "x", x); + y = config.getDouble(prefix, "y", y); + z = config.getDouble(prefix, "z", z); + CAPTURE_RADIUS = config.getDouble(prefix, "capture-radius", CAPTURE_RADIUS); + WINNING_SCORE = config.getInt(prefix, "winning-score", WINNING_SCORE); + } + } + } diff --git a/src/main/java/com/alttd/ctf/config/Messages.java b/src/main/java/com/alttd/ctf/config/Messages.java index d596590..0e77159 100644 --- a/src/main/java/com/alttd/ctf/config/Messages.java +++ b/src/main/java/com/alttd/ctf/config/Messages.java @@ -8,7 +8,7 @@ public class Messages extends AbstractConfig { static Messages config; Messages(Main main) { - super(main, "config.yml"); + super(main, "messages.yml"); } public static void reload(Main main) { diff --git a/src/main/java/com/alttd/ctf/config/WorldBorderSettings.java b/src/main/java/com/alttd/ctf/config/WorldBorderSettings.java new file mode 100644 index 0000000..78c12e7 --- /dev/null +++ b/src/main/java/com/alttd/ctf/config/WorldBorderSettings.java @@ -0,0 +1,4 @@ +package com.alttd.ctf.config; + +public record WorldBorderSettings(WorldBorderType type, double size) { +} diff --git a/src/main/java/com/alttd/ctf/config/WorldBorderType.java b/src/main/java/com/alttd/ctf/config/WorldBorderType.java new file mode 100644 index 0000000..ac6b922 --- /dev/null +++ b/src/main/java/com/alttd/ctf/config/WorldBorderType.java @@ -0,0 +1,6 @@ +package com.alttd.ctf.config; + +public enum WorldBorderType { + FLAG, + PLAYER +} diff --git a/src/main/java/com/alttd/ctf/events/OnPlayerDeath.java b/src/main/java/com/alttd/ctf/events/OnPlayerDeath.java index 340e797..beac107 100644 --- a/src/main/java/com/alttd/ctf/events/OnPlayerDeath.java +++ b/src/main/java/com/alttd/ctf/events/OnPlayerDeath.java @@ -1,6 +1,7 @@ package com.alttd.ctf.events; import com.alttd.ctf.Main; +import com.alttd.ctf.config.Config; import com.alttd.ctf.game.GameManager; import com.alttd.ctf.game.GamePhase; import com.alttd.ctf.team.TeamPlayer; @@ -54,7 +55,7 @@ public class OnPlayerDeath implements Listener { } TeamPlayer teamPlayer = optionalTeamPlayer.get(); event.setRespawnLocation(player.getWorld().getSpawnLocation()); - Bukkit.getScheduler().runTaskLater(main, () -> teamPlayer.getGameClass().apply(teamPlayer, worldBorderApi, gamePhase.get(), true), 10 * 20);//10 x 20 ticks aka 10 seconds + Bukkit.getScheduler().runTaskLater(main, () -> teamPlayer.getGameClass().apply(teamPlayer, worldBorderApi, gamePhase.get(), true), Config.SETTINGS * 20);//10 x 20 ticks aka 10 seconds } } diff --git a/src/main/java/com/alttd/ctf/flag/Flag.java b/src/main/java/com/alttd/ctf/flag/Flag.java index 4e16640..ca783b6 100644 --- a/src/main/java/com/alttd/ctf/flag/Flag.java +++ b/src/main/java/com/alttd/ctf/flag/Flag.java @@ -1,13 +1,12 @@ package com.alttd.ctf.flag; import com.alttd.ctf.Main; -import com.alttd.ctf.config.Config; +import com.alttd.ctf.config.GameConfig; import com.alttd.ctf.game.GameManager; import com.alttd.ctf.team.Team; import com.alttd.ctf.team.TeamColor; import com.alttd.ctf.team.TeamPlayer; import lombok.Getter; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; @@ -21,13 +20,9 @@ import org.bukkit.boss.KeyedBossBar; import org.bukkit.entity.Player; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; -import org.bukkit.scheduler.BukkitRunnable; -import org.bukkit.scheduler.BukkitScheduler; import java.util.*; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.Future; import java.util.stream.Collectors; @Slf4j @@ -49,11 +44,11 @@ public class Flag implements Runnable { public Flag(Main main, GameManager gameManager) { this.main = main; this.gameManager = gameManager; - World world = Bukkit.getWorld(Config.FLAG.world); + World world = Bukkit.getWorld(GameConfig.FLAG.world); if (world == null) { - throw new IllegalStateException(String.format("Tried to spawn flag in world [%s] that doesn't exist", Config.FLAG.world)); + throw new IllegalStateException(String.format("Tried to spawn flag in world [%s] that doesn't exist", GameConfig.FLAG.world)); } - this.flagLocation = new Location(world, Config.FLAG.x, Config.FLAG.y, Config.FLAG.z); + this.flagLocation = new Location(world, GameConfig.FLAG.x, GameConfig.FLAG.y, GameConfig.FLAG.z); } private BossBar createBossBar() { @@ -194,7 +189,7 @@ public class Flag implements Runnable { if (max.isEmpty()) { return Optional.empty(); } - if (max.get().getValue() < 100) { + if (max.get().getValue() < GameConfig.FLAG.WINNING_SCORE) { return Optional.empty(); } return gameManager.getTeam(max.get().getKey()); @@ -209,7 +204,7 @@ public class Flag implements Runnable { private CompletableFuture updateScoreBasedOnNearbyPlayers() { CompletableFuture future = new CompletableFuture<>(); Bukkit.getScheduler().runTask(main, () -> { - Collection nearbyPlayers = flagLocation.getNearbyPlayers(10); + Collection nearbyPlayers = flagLocation.getNearbyPlayers(GameConfig.FLAG.CAPTURE_RADIUS); Bukkit.getScheduler().runTaskAsynchronously(main, () -> { boolean result = updateScoreBasedOnNearbyPlayers(nearbyPlayers); future.complete(result); @@ -288,7 +283,7 @@ public class Flag implements Runnable { bossBar.setTitle(String.format("Team %s is capturing the flag", PlainTextComponentSerializer.plainText().serialize(team.get().getName()))); lastWinningTeamId = highestKey; } - bossBar.setProgress(Math.min(100, teamFlagPointCount.get(highestKey)) / 100.0); + bossBar.setProgress(Math.min(GameConfig.FLAG.WINNING_SCORE, teamFlagPointCount.get(highestKey)) / (double) GameConfig.FLAG.WINNING_SCORE); bossBar.setVisible(teamFlagPointCount.get(highestKey) > 0); } diff --git a/src/main/java/com/alttd/ctf/game/RunningGame.java b/src/main/java/com/alttd/ctf/game/RunningGame.java index 3e39970..3cd2f3d 100644 --- a/src/main/java/com/alttd/ctf/game/RunningGame.java +++ b/src/main/java/com/alttd/ctf/game/RunningGame.java @@ -33,19 +33,24 @@ public class RunningGame implements Runnable { @Override public void run() { - GamePhase nextPhase = GamePhase.values().length < currentPhase.ordinal() ? null : GamePhase.values()[currentPhase.ordinal() + 1]; - if (phaseStartTime == null) { - phaseStartTime = Instant.now(); - nextPhaseActions(null, currentPhase, nextPhase); - } + try { + GamePhase nextPhase = GamePhase.values().length < currentPhase.ordinal() ? null : GamePhase.values()[currentPhase.ordinal() + 1]; + if (phaseStartTime == null) { + phaseStartTime = Instant.now(); + nextPhaseActions(null, currentPhase, nextPhase); + } - if (Duration.between(phaseStartTime, Instant.now()).compareTo(phaseDurations.get(currentPhase)) >= 0) { - GamePhase previousPhase = currentPhase; - currentPhase = GamePhase.values()[currentPhase.ordinal() + 1]; - nextPhaseActions(previousPhase, currentPhase, nextPhase); - phaseStartTime = Instant.now(); - } else if (nextPhase != null) { - broadcastNextPhaseStartTime(currentPhase, nextPhase); + if (Duration.between(phaseStartTime, Instant.now()).compareTo(phaseDurations.get(currentPhase)) >= 0) { + GamePhase previousPhase = currentPhase; + currentPhase = GamePhase.values()[currentPhase.ordinal() + 1]; + nextPhaseActions(previousPhase, currentPhase, nextPhase); + phaseStartTime = Instant.now(); + } else if (nextPhase != null) { + broadcastNextPhaseStartTime(currentPhase, nextPhase); + } + } catch (Exception e) { + log.error("Unexpected error in running game", e); + throw new RuntimeException(e); } } diff --git a/src/main/java/com/alttd/ctf/game/phases/EndedPhase.java b/src/main/java/com/alttd/ctf/game/phases/EndedPhase.java index 1dd8b79..639acda 100644 --- a/src/main/java/com/alttd/ctf/game/phases/EndedPhase.java +++ b/src/main/java/com/alttd/ctf/game/phases/EndedPhase.java @@ -1,6 +1,6 @@ package com.alttd.ctf.game.phases; -import com.alttd.ctf.config.Config; +import com.alttd.ctf.config.GameConfig; import com.alttd.ctf.flag.Flag; import com.alttd.ctf.game.GamePhase; import com.alttd.ctf.game.GamePhaseExecutor; @@ -32,7 +32,7 @@ public class EndedPhase implements GamePhaseExecutor { HashMap wins = flag.getWins(); Bukkit.broadcast(Component.join(JoinConfiguration.separator(Component.newline()), getWinnerMessages(wins))); new Thread(() -> { - World world = Bukkit.getWorld(Config.FLAG.world); + World world = Bukkit.getWorld(GameConfig.FLAG.world); if (world == null) { log.error("Invalid flag world defined"); return; diff --git a/version.properties b/version.properties index f9b3742..f632b66 100644 --- a/version.properties +++ b/version.properties @@ -1,3 +1,3 @@ -#Sat Feb 08 21:33:29 CET 2025 -buildNumber=29 +#Sat Feb 08 21:57:04 CET 2025 +buildNumber=30 version=0.1