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