diff --git a/build.gradle.kts b/build.gradle.kts index e3f3e77..d8b8103 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -31,6 +31,8 @@ dependencies { implementation("com.fasterxml.jackson.core:jackson-databind:2.15.2") implementation("com.fasterxml.jackson.core:jackson-annotations:2.15.2") // End JSON config dependencies + // WorldBorderAPI + compileOnly("com.github.yannicklamprecht:worldborderapi:1.210.0:dev") } tasks.test { diff --git a/settings.gradle.kts b/settings.gradle.kts index 3b7e557..e8538cc 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -5,6 +5,10 @@ dependencyResolutionManagement { mavenLocal() mavenCentral() maven("https://repo.destro.xyz/snapshots") // Altitude - Galaxy + maven { // WorldBorderAPI + name = "eldonexus" + url = uri("https://eldonexus.de/repository/maven-releases/") + } } repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) } diff --git a/src/main/java/com/alttd/ctf/Main.java b/src/main/java/com/alttd/ctf/Main.java index a1b3ff9..f188758 100644 --- a/src/main/java/com/alttd/ctf/Main.java +++ b/src/main/java/com/alttd/ctf/Main.java @@ -15,11 +15,13 @@ import com.alttd.ctf.gui.GUIListener; import com.alttd.ctf.json_config.JacksonConfig; import com.alttd.ctf.json_config.JsonConfigManager; import com.alttd.ctf.team.Team; +import com.github.yannicklamprecht.worldborder.api.WorldBorderApi; import lombok.extern.slf4j.Slf4j; import org.bukkit.Bukkit; import org.bukkit.GameRule; import org.bukkit.World; import org.bukkit.plugin.PluginManager; +import org.bukkit.plugin.RegisteredServiceProvider; import org.bukkit.plugin.java.JavaPlugin; import java.io.File; @@ -40,10 +42,11 @@ public class Main extends JavaPlugin { log.info("Plugin enabled, version {}", version); reloadConfigs(); - this.gameManager = new GameManager(); + WorldBorderApi worldBorderApi = worldBorder(); + this.gameManager = new GameManager(worldBorderApi); registerTeams(); //Skipped in reloadConfig if gameManager is not created yet flag = new Flag(this, gameManager); - CommandManager commandManager = new CommandManager(this, gameManager, flag); + 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); @@ -52,7 +55,7 @@ public class Main extends JavaPlugin { } else { log.error("No valid flag world defined, unable to modify game rules"); } - registerEvents(flag); + registerEvents(flag, worldBorderApi); } public void reloadConfigs() { @@ -64,12 +67,23 @@ public class Main extends JavaPlugin { } } - private void registerEvents(Flag flag) { + private WorldBorderApi worldBorder() { + RegisteredServiceProvider worldBorderApiRegisteredServiceProvider = getServer().getServicesManager().getRegistration(WorldBorderApi.class); + + if (worldBorderApiRegisteredServiceProvider == null) { + log.error("WorldBorder API not found, disabling plugin"); + getServer().getPluginManager().disablePlugin(this); + return null; + } + + return worldBorderApiRegisteredServiceProvider.getProvider(); + } + + private void registerEvents(Flag flag, WorldBorderApi worldBorderApi) { PluginManager pluginManager = getServer().getPluginManager(); - //TODO add event for player joining and clear their inv pluginManager.registerEvents(new SnowballEvent(gameManager), this); pluginManager.registerEvents(new FlagTryCaptureEvent(flag), this); - pluginManager.registerEvents(new OnPlayerDeath(gameManager), this); + pluginManager.registerEvents(new OnPlayerDeath(gameManager, worldBorderApi), this); pluginManager.registerEvents(new InventoryItemInteractionEvent(), this); pluginManager.registerEvents(new OnPlayerJoin(gameManager, flag), this); pluginManager.registerEvents(new GUIListener(), this); diff --git a/src/main/java/com/alttd/ctf/commands/CommandManager.java b/src/main/java/com/alttd/ctf/commands/CommandManager.java index 3bdc1e1..87bbb23 100644 --- a/src/main/java/com/alttd/ctf/commands/CommandManager.java +++ b/src/main/java/com/alttd/ctf/commands/CommandManager.java @@ -5,6 +5,7 @@ import com.alttd.ctf.commands.subcommands.*; import com.alttd.ctf.config.Messages; import com.alttd.ctf.flag.Flag; import com.alttd.ctf.game.GameManager; +import com.github.yannicklamprecht.worldborder.api.WorldBorderApi; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; @@ -22,7 +23,7 @@ import java.util.stream.Collectors; public class CommandManager implements CommandExecutor, TabExecutor { private final List subCommands; - public CommandManager(Main main, GameManager gameManager, Flag flag) { + public CommandManager(Main main, GameManager gameManager, Flag flag, WorldBorderApi worldBorderApi) { PluginCommand command = main.getCommand("ctf"); if (command == null) { subCommands = null; @@ -36,7 +37,7 @@ public class CommandManager implements CommandExecutor, TabExecutor { new ChangeTeam(gameManager), new Start(gameManager, flag), new CreateTeam(main, gameManager), - new SelectClass(gameManager), + new SelectClass(gameManager, worldBorderApi), new Reload(main) ); } diff --git a/src/main/java/com/alttd/ctf/commands/subcommands/SelectClass.java b/src/main/java/com/alttd/ctf/commands/subcommands/SelectClass.java index 49ee4e6..5ab25e7 100644 --- a/src/main/java/com/alttd/ctf/commands/subcommands/SelectClass.java +++ b/src/main/java/com/alttd/ctf/commands/subcommands/SelectClass.java @@ -10,6 +10,7 @@ import com.alttd.ctf.game_class.creation.FighterCreator; import com.alttd.ctf.game_class.creation.TankCreator; import com.alttd.ctf.gui.ClassSelectionGUI; import com.alttd.ctf.team.TeamPlayer; +import com.github.yannicklamprecht.worldborder.api.WorldBorderApi; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -22,9 +23,11 @@ public class SelectClass extends SubCommand { private final GameManager gameManager; private final HashMap> gameClasses; + private final WorldBorderApi worldBorderApi; - public SelectClass(GameManager gameManager) { + public SelectClass(GameManager gameManager, WorldBorderApi worldBorderApi) { this.gameManager = gameManager; + this.worldBorderApi = worldBorderApi; this.gameClasses = new HashMap<>(); gameManager.getTeams().forEach(team -> { gameClasses.computeIfAbsent(team.getId(), teamId -> new ArrayList<>()).add(FighterCreator.createFighter(team.getColor())); @@ -55,7 +58,7 @@ public class SelectClass extends SubCommand { commandSender.sendRichMessage("You have to be near your spawn to change classes."); return 0; } - new ClassSelectionGUI(gameClasses.get(teamPlayer.getTeam().getId()), teamPlayer) + new ClassSelectionGUI(gameClasses.get(teamPlayer.getTeam().getId()), teamPlayer, worldBorderApi, gamePhase) .open(player); return 0; } diff --git a/src/main/java/com/alttd/ctf/events/OnPlayerDeath.java b/src/main/java/com/alttd/ctf/events/OnPlayerDeath.java index 15f618f..848ccde 100644 --- a/src/main/java/com/alttd/ctf/events/OnPlayerDeath.java +++ b/src/main/java/com/alttd/ctf/events/OnPlayerDeath.java @@ -1,7 +1,10 @@ package com.alttd.ctf.events; import com.alttd.ctf.game.GameManager; +import com.alttd.ctf.game.GamePhase; import com.alttd.ctf.team.TeamPlayer; +import com.github.yannicklamprecht.worldborder.api.WorldBorderApi; +import lombok.extern.slf4j.Slf4j; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -10,12 +13,15 @@ import org.bukkit.event.player.PlayerRespawnEvent; import java.util.Optional; +@Slf4j public class OnPlayerDeath implements Listener { private final GameManager gameManager; + private final WorldBorderApi worldBorderApi; - public OnPlayerDeath(GameManager gameManager) { + public OnPlayerDeath(GameManager gameManager, WorldBorderApi worldBorderApi) { this.gameManager = gameManager; + this.worldBorderApi = worldBorderApi; } @EventHandler @@ -33,13 +39,18 @@ public class OnPlayerDeath implements Listener { @EventHandler public void onPlayerRespawn(PlayerRespawnEvent event) { Player player = event.getPlayer(); + Optional gamePhase = gameManager.getGamePhase(); + if (gamePhase.isEmpty()) { + log.warn("Player {} died while the game wasn't running", player.getName()); + return; + } Optional optionalTeamPlayer = gameManager.getTeamPlayer(player.getUniqueId()); if (optionalTeamPlayer.isEmpty()) { return; } TeamPlayer teamPlayer = optionalTeamPlayer.get(); event.setRespawnLocation(teamPlayer.getTeam().getSpawnLocation()); - teamPlayer.getGameClass().apply(teamPlayer); + teamPlayer.getGameClass().apply(teamPlayer, worldBorderApi, gamePhase.get(), false); } } diff --git a/src/main/java/com/alttd/ctf/flag/Flag.java b/src/main/java/com/alttd/ctf/flag/Flag.java index ca79e46..493fcf5 100644 --- a/src/main/java/com/alttd/ctf/flag/Flag.java +++ b/src/main/java/com/alttd/ctf/flag/Flag.java @@ -6,6 +6,7 @@ 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; @@ -30,7 +31,6 @@ import java.util.concurrent.Future; import java.util.stream.Collectors; @Slf4j -@RequiredArgsConstructor public class Flag implements Runnable { private final HashMap teamFlagPointCount = new HashMap<>(); @@ -38,13 +38,24 @@ public class Flag implements Runnable { private final BossBar bossBar = createBossBar(); private final HashMap wins = new HashMap<>(); private int lastWinningTeamId = -1; - private Location flagLocation; + @Getter + private final Location flagLocation; private Team winningTeam; private Player flagCarrier; private final Main main; private final GameManager gameManager; + public Flag(Main main, GameManager gameManager) { + this.main = main; + this.gameManager = gameManager; + World world = Bukkit.getWorld(Config.FLAG.world); + if (world == null) { + throw new IllegalStateException(String.format("Tried to spawn flag in world [%s] that doesn't exist", Config.FLAG.world)); + } + this.flagLocation = new Location(world, Config.FLAG.x, Config.FLAG.y, Config.FLAG.z); + } + private BossBar createBossBar() { NamespacedKey namespacedKey = NamespacedKey.fromString("ctf_flag", main); if (namespacedKey == null) { @@ -60,10 +71,6 @@ public class Flag implements Runnable { return captureProgress; } - protected Location getFlagLocation() { - return flagLocation; - } - public void addPlayer(Player player) { bossBar.addPlayer(player); } @@ -85,13 +92,6 @@ public class Flag implements Runnable { } public void spawnFlag() { - //TODO disable flag capture for a minute or so, and maybe have it slowly drop down? - World world = Bukkit.getWorld(Config.FLAG.world); - if (world == null) { - throw new IllegalStateException(String.format("Tried to spawn flag in world [%s] that doesn't exist", Config.FLAG.world)); - } - this.flagLocation = new Location(world, Config.FLAG.x, Config.FLAG.y, Config.FLAG.z); - //Place block on main thread Bukkit.getScheduler().runTask(main, () -> flagLocation.getBlock().setType(flagItem.getType())); } @@ -126,18 +126,18 @@ public class Flag implements Runnable { private void spawnParticlesOnSquareBorder(World world, Location center) { double size = 10; double step = 0.2; - center.add(0, 0.5, 0); + Location finalCenter = center.clone().add(0, 0.5, 0); Bukkit.getScheduler().runTask(main, () -> { // Top and Bottom (Z varies, X constant) for (double z = -size; z <= size; z += step) { - world.spawnParticle(Particle.FLAME, center.getX() + size, center.getY(), center.getZ() + z, 1, 0, 0, 0, 0); - world.spawnParticle(Particle.FLAME, center.getX() - size, center.getY(), center.getZ() + z, 1, 0, 0, 0, 0); + world.spawnParticle(Particle.FLAME, finalCenter.getX() + size, finalCenter.getY(), finalCenter.getZ() + z, 1, 0, 0, 0, 0); + world.spawnParticle(Particle.FLAME, finalCenter.getX() - size, finalCenter.getY(), finalCenter.getZ() + z, 1, 0, 0, 0, 0); } // Left and Right (X varies, Z constant) for (double x = -size; x <= size; x += step) { - world.spawnParticle(Particle.FLAME, center.getX() + x, center.getY(), center.getZ() + size, 1, 0, 0, 0, 0); - world.spawnParticle(Particle.FLAME, center.getX() + x, center.getY(), center.getZ() - size, 1, 0, 0, 0, 0); + world.spawnParticle(Particle.FLAME, finalCenter.getX() + x, finalCenter.getY(), finalCenter.getZ() + size, 1, 0, 0, 0, 0); + world.spawnParticle(Particle.FLAME, finalCenter.getX() + x, finalCenter.getY(), finalCenter.getZ() - size, 1, 0, 0, 0, 0); } }); } diff --git a/src/main/java/com/alttd/ctf/game/GameManager.java b/src/main/java/com/alttd/ctf/game/GameManager.java index 1616b8b..ba1c4c9 100644 --- a/src/main/java/com/alttd/ctf/game/GameManager.java +++ b/src/main/java/com/alttd/ctf/game/GameManager.java @@ -8,6 +8,7 @@ import com.alttd.ctf.game.phases.GatheringPhase; import com.alttd.ctf.game_class.creation.FighterCreator; import com.alttd.ctf.team.Team; import com.alttd.ctf.team.TeamPlayer; +import com.github.yannicklamprecht.worldborder.api.WorldBorderApi; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; @@ -24,10 +25,10 @@ public class GameManager { private RunningGame runningGame; private final HashMap teams = new HashMap<>(); - public GameManager() { + public GameManager(WorldBorderApi worldBorderApi) { phases = new HashMap<>(); - phases.put(GamePhase.CLASS_SELECTION, new ClassSelectionPhase(this, (FighterCreator::createFighter))); - phases.put(GamePhase.GATHERING, new GatheringPhase()); + phases.put(GamePhase.CLASS_SELECTION, new ClassSelectionPhase(this, FighterCreator::createFighter, worldBorderApi)); + phases.put(GamePhase.GATHERING, new GatheringPhase(this, worldBorderApi)); phases.put(GamePhase.COMBAT, new CombatPhase()); phases.put(GamePhase.ENDED, new EndedPhase()); } diff --git a/src/main/java/com/alttd/ctf/game/GamePhase.java b/src/main/java/com/alttd/ctf/game/GamePhase.java index dae37d1..53da727 100644 --- a/src/main/java/com/alttd/ctf/game/GamePhase.java +++ b/src/main/java/com/alttd/ctf/game/GamePhase.java @@ -6,14 +6,16 @@ import net.kyori.adventure.text.minimessage.MiniMessage; @Getter public enum GamePhase { - CLASS_SELECTION(MiniMessage.miniMessage().deserialize("Class selection phase")), - GATHERING(MiniMessage.miniMessage().deserialize("Gathering phase")), - COMBAT(MiniMessage.miniMessage().deserialize("Combat phase")), - ENDED(MiniMessage.miniMessage().deserialize("Game end phase")); + CLASS_SELECTION(MiniMessage.miniMessage().deserialize("Class selection phase"), 25), + GATHERING(MiniMessage.miniMessage().deserialize("Gathering phase"), 50), + COMBAT(MiniMessage.miniMessage().deserialize("Combat phase"), 0), + ENDED(MiniMessage.miniMessage().deserialize("Game end phase"), 0); private final Component displayName; + private final double worldBorderSize; - GamePhase(Component displayName) { + GamePhase(Component displayName, double worldBorderSize) { this.displayName = displayName; + this.worldBorderSize = worldBorderSize; } } diff --git a/src/main/java/com/alttd/ctf/game/GamePhaseExecutor.java b/src/main/java/com/alttd/ctf/game/GamePhaseExecutor.java index 50a66b1..5133e46 100644 --- a/src/main/java/com/alttd/ctf/game/GamePhaseExecutor.java +++ b/src/main/java/com/alttd/ctf/game/GamePhaseExecutor.java @@ -6,5 +6,5 @@ public interface GamePhaseExecutor { void start(Flag flag); - void end(); + void end(GamePhase nextGamePhase); } diff --git a/src/main/java/com/alttd/ctf/game/RunningGame.java b/src/main/java/com/alttd/ctf/game/RunningGame.java index 9f62613..3e39970 100644 --- a/src/main/java/com/alttd/ctf/game/RunningGame.java +++ b/src/main/java/com/alttd/ctf/game/RunningGame.java @@ -52,7 +52,7 @@ public class RunningGame implements Runnable { private void nextPhaseActions(@Nullable GamePhase previousPhase, @NotNull GamePhase phase, @Nullable GamePhase nextPhase) { //TODO command to go to next phase if (previousPhase != null) { - gameManager.getPhaseExecutor(previousPhase).end(); + gameManager.getPhaseExecutor(previousPhase).end(phase); } gameManager.getPhaseExecutor(phase).start(flag); if (nextPhase != null) { diff --git a/src/main/java/com/alttd/ctf/game/phases/ClassSelectionPhase.java b/src/main/java/com/alttd/ctf/game/phases/ClassSelectionPhase.java index 2477be5..9259e44 100644 --- a/src/main/java/com/alttd/ctf/game/phases/ClassSelectionPhase.java +++ b/src/main/java/com/alttd/ctf/game/phases/ClassSelectionPhase.java @@ -2,16 +2,18 @@ package com.alttd.ctf.game.phases; import com.alttd.ctf.flag.Flag; import com.alttd.ctf.game.GameManager; +import com.alttd.ctf.game.GamePhase; import com.alttd.ctf.game.GamePhaseExecutor; import com.alttd.ctf.game_class.GameClass; import com.alttd.ctf.team.Team; import com.alttd.ctf.team.TeamColor; +import com.alttd.ctf.team.TeamPlayer; import com.alttd.ctf.util.CircularIterator; +import com.github.yannicklamprecht.worldborder.api.WorldBorderApi; import lombok.extern.slf4j.Slf4j; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import org.bukkit.Bukkit; -import org.bukkit.Location; import org.jetbrains.annotations.NotNull; import java.util.Optional; @@ -21,20 +23,22 @@ public class ClassSelectionPhase implements GamePhaseExecutor { private final GameManager gameManager; private final DefaultClassCreator defaultClassCreator; + private final WorldBorderApi worldBorderApi; @FunctionalInterface public interface DefaultClassCreator { @NotNull GameClass apply(TeamColor teamColor); } - public ClassSelectionPhase(@NotNull GameManager gameManager, DefaultClassCreator defaultClassCreator) { + public ClassSelectionPhase(@NotNull GameManager gameManager, DefaultClassCreator defaultClassCreator, + @NotNull WorldBorderApi worldBorderApi) { this.gameManager = gameManager; this.defaultClassCreator = defaultClassCreator; + this.worldBorderApi = worldBorderApi; } @Override public void start(Flag flag) { - teleportPlayersToStartingZone(); Bukkit.broadcast(MiniMessage.miniMessage().deserialize("Select your class")); CircularIterator teamCircularIterator = new CircularIterator<>(gameManager.getTeams()); if (teamCircularIterator.hasNext()) { @@ -48,34 +52,36 @@ public class ClassSelectionPhase implements GamePhaseExecutor { } else { log.warn("No teams to add players to"); } - //TODO let players select classes - // They should always be able to do this when in their starting zone - // They should be locked into their starting zone until the next phase starts - // That phase should handle opening the zone + teleportPlayersToStartingZone(); } private void teleportPlayersToStartingZone() { Bukkit.getOnlinePlayers().forEach(player -> { - Optional team = gameManager.getTeam(player.getUniqueId()); - if (team.isEmpty()) { + Optional teamPlayer = gameManager.getTeamPlayer(player.getUniqueId()); + if (teamPlayer.isEmpty()) { + log.warn("{} is not a team player when teleporting to starting zone", player.getName()); return; } - Location spawnLocation = team.get().getSpawnLocation(); - player.teleportAsync(spawnLocation); + Optional gamePhase = gameManager.getGamePhase(); + if (gamePhase.isEmpty()) { + log.warn("Game phase is empty when teleporting to starting zone"); + return; + } + teamPlayer.get().respawn(player, worldBorderApi, gamePhase.get()); }); } @Override - public void end() { + public void end(GamePhase nextPhase) { gameManager.getTeams().forEach(team -> { GameClass defaultClass = defaultClassCreator.apply(team.getColor()); team.getPlayers().forEach(player -> { + player.resetWorldBorder(Bukkit.getPlayer(player.getUuid()), worldBorderApi, nextPhase, team.getWorldBorderCenter()); if (player.getGameClass() != null) { return; } - defaultClass.apply(player); + defaultClass.apply(player, worldBorderApi, nextPhase, false); }); }); - //TODO expand world border so ppl can gather things but not get near the flag yet } } diff --git a/src/main/java/com/alttd/ctf/game/phases/CombatPhase.java b/src/main/java/com/alttd/ctf/game/phases/CombatPhase.java index 8a40f84..4d90f62 100644 --- a/src/main/java/com/alttd/ctf/game/phases/CombatPhase.java +++ b/src/main/java/com/alttd/ctf/game/phases/CombatPhase.java @@ -1,6 +1,7 @@ package com.alttd.ctf.game.phases; import com.alttd.ctf.flag.Flag; +import com.alttd.ctf.game.GamePhase; import com.alttd.ctf.game.GamePhaseExecutor; import net.kyori.adventure.text.minimessage.MiniMessage; import org.bukkit.Bukkit; @@ -28,7 +29,7 @@ public class CombatPhase implements GamePhaseExecutor { } @Override - public void end() { + public void end(GamePhase ignored) { executorService.shutdown(); } } 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 ee74339..1dd8b79 100644 --- a/src/main/java/com/alttd/ctf/game/phases/EndedPhase.java +++ b/src/main/java/com/alttd/ctf/game/phases/EndedPhase.java @@ -2,6 +2,7 @@ package com.alttd.ctf.game.phases; import com.alttd.ctf.config.Config; import com.alttd.ctf.flag.Flag; +import com.alttd.ctf.game.GamePhase; import com.alttd.ctf.game.GamePhaseExecutor; import com.alttd.ctf.team.Team; import lombok.extern.slf4j.Slf4j; @@ -101,7 +102,7 @@ public class EndedPhase implements GamePhaseExecutor { } @Override - public void end() { + public void end(GamePhase ignored) { } } diff --git a/src/main/java/com/alttd/ctf/game/phases/GatheringPhase.java b/src/main/java/com/alttd/ctf/game/phases/GatheringPhase.java index 24e904a..8d1e51a 100644 --- a/src/main/java/com/alttd/ctf/game/phases/GatheringPhase.java +++ b/src/main/java/com/alttd/ctf/game/phases/GatheringPhase.java @@ -1,20 +1,45 @@ package com.alttd.ctf.game.phases; import com.alttd.ctf.flag.Flag; +import com.alttd.ctf.game.GameManager; +import com.alttd.ctf.game.GamePhase; import com.alttd.ctf.game.GamePhaseExecutor; +import com.alttd.ctf.game_class.GameClass; +import com.github.yannicklamprecht.worldborder.api.WorldBorderApi; +import lombok.extern.slf4j.Slf4j; import net.kyori.adventure.text.minimessage.MiniMessage; import org.bukkit.Bukkit; +@Slf4j public class GatheringPhase implements GamePhaseExecutor { + + private final GameManager gameManager; + private final WorldBorderApi worldBorderApi; + private Flag flag; + + public GatheringPhase(GameManager gameManager, WorldBorderApi worldBorderApi) { + this.gameManager = gameManager; + this.worldBorderApi = worldBorderApi; + } + @Override public void start(Flag flag) { + this.flag = flag; Bukkit.broadcast(MiniMessage.miniMessage().deserialize("Gather materials and prepare for combat!")); //TODO give everyone haste or something so they can mine faster till this game phase ends // Let them store things at base during this phase, after only one class can do this? } @Override - public void end() { - //TODO Remove team area barrier + public void end(GamePhase nextPhase) { + if (flag == null) { + log.error("Unable to update world border due to missing Flag"); + return; + } + gameManager.getTeams().forEach(team -> { + team.getPlayers().forEach(player -> { + player.resetWorldBorder(Bukkit.getPlayer(player.getUuid()), worldBorderApi, nextPhase, flag.getFlagLocation()); + }); + }); } } diff --git a/src/main/java/com/alttd/ctf/game_class/GameClass.java b/src/main/java/com/alttd/ctf/game_class/GameClass.java index 0146c28..18260e7 100644 --- a/src/main/java/com/alttd/ctf/game_class/GameClass.java +++ b/src/main/java/com/alttd/ctf/game_class/GameClass.java @@ -1,7 +1,9 @@ package com.alttd.ctf.game_class; +import com.alttd.ctf.game.GamePhase; import com.alttd.ctf.team.TeamColor; import com.alttd.ctf.team.TeamPlayer; +import com.github.yannicklamprecht.worldborder.api.WorldBorderApi; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import net.kyori.adventure.text.Component; @@ -68,7 +70,7 @@ public abstract class GameClass { displayItem.setItemMeta(itemMeta); } - public void apply(TeamPlayer teamPlayer) { + public void apply(TeamPlayer teamPlayer, WorldBorderApi worldBorderApi, GamePhase gamePhase, boolean teleport) { Player player = Bukkit.getPlayer(teamPlayer.getUuid()); if (player == null || !player.isOnline()) { log.warn("Tried to give class to offline player {}", player == null ? teamPlayer.getUuid() : player.getName()); @@ -91,7 +93,7 @@ public abstract class GameClass { player.updateInventory(); teamPlayer.setGameClass(this); player.sendRichMessage("You selected the class", Placeholder.component("class_name", className)); - player.teleportAsync(teamPlayer.getTeam().getSpawnLocation()); + teamPlayer.respawn(player, worldBorderApi, gamePhase, teleport); } private void setArmor(Player player, int r, int g, int b) { diff --git a/src/main/java/com/alttd/ctf/gui/ClassSelectionGUI.java b/src/main/java/com/alttd/ctf/gui/ClassSelectionGUI.java index 3ad1bd2..b348930 100644 --- a/src/main/java/com/alttd/ctf/gui/ClassSelectionGUI.java +++ b/src/main/java/com/alttd/ctf/gui/ClassSelectionGUI.java @@ -1,7 +1,9 @@ package com.alttd.ctf.gui; +import com.alttd.ctf.game.GamePhase; import com.alttd.ctf.game_class.GameClass; import com.alttd.ctf.team.TeamPlayer; +import com.github.yannicklamprecht.worldborder.api.WorldBorderApi; import net.kyori.adventure.text.minimessage.MiniMessage; import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.inventory.InventoryType; @@ -11,16 +13,17 @@ import java.util.List; public class ClassSelectionGUI extends GUIInventory { - public ClassSelectionGUI(@NotNull List gameClasses, @NotNull TeamPlayer teamPlayer) { + public ClassSelectionGUI(@NotNull List gameClasses, @NotNull TeamPlayer teamPlayer, + @NotNull WorldBorderApi worldBorderApi, @NotNull GamePhase gamePhase) { super(InventoryType.CHEST, teamPlayer.getTeam().getName().append(MiniMessage.miniMessage().deserialize(" - class selection"))); - createClassSelection(gameClasses, teamPlayer); + createClassSelection(gameClasses, teamPlayer, worldBorderApi, gamePhase); } - private void createClassSelection(@NotNull List gameClasses, @NotNull TeamPlayer teamPlayer) { + private void createClassSelection(@NotNull List gameClasses, @NotNull TeamPlayer teamPlayer, @NotNull WorldBorderApi worldBorderApi, @NotNull GamePhase gamePhase) { int pos = (9 + (9 - gameClasses.size()) / 2); for (GameClass gameClass : gameClasses) { setItem(pos++, gameClass.getDisplayItem(), player -> { - gameClass.apply(teamPlayer); + gameClass.apply(teamPlayer, worldBorderApi, gamePhase, true); player.closeInventory(InventoryCloseEvent.Reason.PLUGIN); }); } diff --git a/src/main/java/com/alttd/ctf/team/Team.java b/src/main/java/com/alttd/ctf/team/Team.java index 91ac100..cdf89c3 100644 --- a/src/main/java/com/alttd/ctf/team/Team.java +++ b/src/main/java/com/alttd/ctf/team/Team.java @@ -33,7 +33,7 @@ public class Team { @JsonProperty("worldBorderCenter") @NotNull @Getter - private Location worldBorderCenter; //TODO https://github.com/yannicklamprecht/WorldBorderAPI/blob/main/how-to-use.md + private Location worldBorderCenter; // https://github.com/yannicklamprecht/WorldBorderAPI/blob/main/how-to-use.md @JsonProperty("teamColor") @NotNull @Getter diff --git a/src/main/java/com/alttd/ctf/team/TeamPlayer.java b/src/main/java/com/alttd/ctf/team/TeamPlayer.java index 39c43bb..d935700 100644 --- a/src/main/java/com/alttd/ctf/team/TeamPlayer.java +++ b/src/main/java/com/alttd/ctf/team/TeamPlayer.java @@ -1,12 +1,21 @@ package com.alttd.ctf.team; +import com.alttd.ctf.game.GamePhase; import com.alttd.ctf.game_class.GameClass; +import com.github.yannicklamprecht.worldborder.api.IWorldBorder; +import com.github.yannicklamprecht.worldborder.api.Position; +import com.github.yannicklamprecht.worldborder.api.WorldBorderApi; import lombok.Getter; import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import java.util.Objects; import java.util.UUID; +@Slf4j @Getter public class TeamPlayer { @@ -20,6 +29,35 @@ public class TeamPlayer { this.team = team; } + public void respawn(@NotNull Player player, @NotNull WorldBorderApi worldBorderApi, @NotNull GamePhase gamePhase) { + respawn(player, worldBorderApi, gamePhase, true); + } + + public void respawn(Player player, WorldBorderApi worldBorderApi, GamePhase gamePhase, boolean teleport) { + Location spawnLocation = team.getSpawnLocation(); + Location worldBorderCenter = team.getWorldBorderCenter(); + if (!teleport) { + resetWorldBorder(player, worldBorderApi, gamePhase, worldBorderCenter); + return; + } + player.teleportAsync(spawnLocation).thenAcceptAsync(unused -> + resetWorldBorder(player, worldBorderApi, gamePhase, worldBorderCenter)); + } + + public void resetWorldBorder(Player player, WorldBorderApi worldBorderApi, GamePhase gamePhase, Location worldBorderCenter) { + log.info("Resetting world border for {}", player.getName()); + double worldBorderSize = gamePhase.getWorldBorderSize(); + log.info("Resetting world border to {} for {}", worldBorderSize, player.getName()); + IWorldBorder worldBorder = worldBorderApi.getWorldBorder(player); + if (worldBorderSize <= 0) { + log.info("Resetting world border to global for {}", player.getName()); + worldBorderApi.resetWorldBorderToGlobal(player); + return; + } + log.info("Resetting world border to {} for {}", worldBorderCenter.toString(), player.getName()); + worldBorderApi.setBorder(player, worldBorderSize, worldBorderCenter); + } + @Override public boolean equals(Object obj) { if (this == obj) { diff --git a/version.properties b/version.properties index f71f3b8..99f41e5 100644 --- a/version.properties +++ b/version.properties @@ -1,3 +1,3 @@ -#Sat Feb 08 00:30:51 CET 2025 -buildNumber=11 +#Sat Feb 08 20:41:32 CET 2025 +buildNumber=18 version=0.1