From a4b110773e5597fc13206b942f41178262c2c996 Mon Sep 17 00:00:00 2001 From: Torrie Fischer Date: Tue, 10 May 2022 21:35:25 +0200 Subject: [PATCH] Implement first pass at config loading, /join, /leave commands, tab completion (broken) --- TODO.md | 39 +++-- .../java/gg/malloc/defense/MemoryArena.java | 26 +-- src/main/java/gg/malloc/defense/Plugin.java | 163 ++++++++++++++---- .../defense/commands/AddPlayerCommand.java | 8 +- .../defense/commands/JoinGameCommand.java | 56 ++++++ .../defense/commands/LeaveGameCommand.java | 35 ++++ .../defense/commands/ListGamesCommand.java | 35 ++++ .../defense/commands/PlayerReadyCommand.java | 9 +- .../defense/commands/SetStageCommand.java | 39 ++++- .../gg/malloc/defense/engine/GameRunner.java | 45 +++-- .../gg/malloc/defense/engine/GameSpawner.java | 14 +- .../java/gg/malloc/defense/model/Arena.java | 6 +- .../java/gg/malloc/defense/model/Game.java | 2 - .../gg/malloc/defense/model/Spawnpoint.java | 9 - .../gg/malloc/defense/model/Waypoint.java | 8 + src/main/resources/config.yml | 16 ++ src/main/resources/plugin.yml | 10 +- 17 files changed, 410 insertions(+), 110 deletions(-) create mode 100644 src/main/java/gg/malloc/defense/commands/JoinGameCommand.java create mode 100644 src/main/java/gg/malloc/defense/commands/LeaveGameCommand.java create mode 100644 src/main/java/gg/malloc/defense/commands/ListGamesCommand.java delete mode 100644 src/main/java/gg/malloc/defense/model/Spawnpoint.java create mode 100644 src/main/java/gg/malloc/defense/model/Waypoint.java create mode 100644 src/main/resources/config.yml diff --git a/TODO.md b/TODO.md index 53ee6a0..fd712ab 100644 --- a/TODO.md +++ b/TODO.md @@ -8,12 +8,18 @@ # Malloc Beta -[ ] Join games -[ ] Leave games -[ ] One arena config +[X] One arena config +[ ] Config reload +[X] Leave games +[X] Join games +[ ] Lobby with instructions +[ ] Drop back to lobby on game over +[ ] Grist drops +[ ] Item shoppes # Scaled waves +[ ] Limit ranged mobs and Ravagers to non-bomb-carrier state [ ] Weaker mobs, more of them [ ] Mob categories [ ] Spawnpoint categories @@ -24,9 +30,16 @@ [X] Mob count boss bar [X] Stage titles [X] EXPLOSIONS -[ ] Target catches on fire more it is lit +[X] Bomb model +[ ] Pretty bomb model +[ ] "Player $X is ready" message in chat [ ] Colored titles +[ ] Clickable join links in /list +[ ] Clickable /leave action [ ] Clickable /ready in chat +[ ] Countdown while in warmup +[ ] Countdown shrinks w/ every /ready player +[ ] Target catches on fire more it is lit [ ] Sidebar [ ] List of mobs in next wave @@ -37,13 +50,16 @@ [ ] Plan stats [ ] /invite friends to games [ ] /voterestart +[ ] Medals/awards/scoreboards # Mechanics -[ ] Coin drops [X] Mob tracking should prioritize bomb [X] Mobs recover dropped bombs [X] Bomb carriers are slower +[ ] Coin drops +[ ] Mob categories +[ ] Mobs split between bomb and player priorities [ ] Bonus coins for complete coin pickup [ ] Infinite weapons + armor [ ] Ammo/health spawns @@ -56,26 +72,29 @@ [X] Batch overlap [ ] Scripted batch overlap/timings [ ] Scripted spawn locations +[ ] Scripted waypoint paths [ ] Bosses # Mapping -[ ] Load arenas from config file +[X] Load arenas from config file [ ] Live map editing # Game lifecycle -[ ] /list arenas and games -[ ] /start a game on an arena -[ ] /join games +[X] /list arenas and games +[X] /join games [X] /ready -[ ] /leave games +[X] /leave games [ ] /restart games [X] Spectator mode on death [X] Player readiness starts countdown [ ] Game is automatically closed some time after game over [ ] Return to lobby on leave/close [ ] Instancing +[ ] Restore health+hunger on respawn/game start +[ ] Respawn during games +[ ] Player revival items # Powerups diff --git a/src/main/java/gg/malloc/defense/MemoryArena.java b/src/main/java/gg/malloc/defense/MemoryArena.java index 18e407e..1269ebc 100644 --- a/src/main/java/gg/malloc/defense/MemoryArena.java +++ b/src/main/java/gg/malloc/defense/MemoryArena.java @@ -1,41 +1,27 @@ package gg.malloc.defense; import gg.malloc.defense.model.Arena; -import gg.malloc.defense.model.Spawnpoint; +import gg.malloc.defense.model.Waypoint; import org.bukkit.World; public class MemoryArena implements Arena { - Spawnpoint[] m_spawnpoints; - Spawnpoint m_bombTarget; - World m_world; - String m_name; + Waypoint[] m_spawnpoints; + Waypoint m_bombTarget; - public MemoryArena(String name, World world, Spawnpoint[] spawnpoints, Spawnpoint bombTarget) { - m_world = world; + public MemoryArena(Waypoint[] spawnpoints, Waypoint bombTarget) { m_spawnpoints = spawnpoints; - m_name = name; m_bombTarget = bombTarget; } @Override - public String name() { - return m_name; - } - - @Override - public Spawnpoint[] spawnpoints() { + public Waypoint[] spawnpoints() { return m_spawnpoints; } @Override - public World getWorld() { - return m_world; - } - - @Override - public Spawnpoint bombTarget() { + public Waypoint bombTarget() { return m_bombTarget; } } diff --git a/src/main/java/gg/malloc/defense/Plugin.java b/src/main/java/gg/malloc/defense/Plugin.java index 5891526..6ba9102 100644 --- a/src/main/java/gg/malloc/defense/Plugin.java +++ b/src/main/java/gg/malloc/defense/Plugin.java @@ -5,17 +5,27 @@ import org.bukkit.plugin.RegisteredServiceProvider; import org.bukkit.Location; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.configuration.ConfigurationSection; import org.bukkit.World; import org.bukkit.WorldCreator; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.EventHandler; + import java.util.logging.Logger; import java.util.logging.Level; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Collection; import gg.malloc.defense.model.Arena; -import gg.malloc.defense.model.Spawnpoint; +import gg.malloc.defense.model.Waypoint; import gg.malloc.defense.model.Game; import gg.malloc.defense.games.LinearGame; @@ -26,32 +36,40 @@ import gg.malloc.defense.engine.GameRunner; import gg.malloc.defense.commands.AddPlayerCommand; import gg.malloc.defense.commands.SetStageCommand; import gg.malloc.defense.commands.PlayerReadyCommand; +import gg.malloc.defense.commands.ListGamesCommand; +import gg.malloc.defense.commands.JoinGameCommand; +import gg.malloc.defense.commands.LeaveGameCommand; public class Plugin extends JavaPlugin { - ArrayList m_arenas = new ArrayList<>(); + HashMap m_arenas = new HashMap<>(); ArrayList m_games = new ArrayList<>(); - HashMap m_runningGames = new HashMap<>(); + HashMap m_runningGames = new HashMap<>(); + HashMap m_playerGames = new HashMap<>(); - private class TestSpawn implements Spawnpoint { - Location m_location; + public Collection arenaNames() { + return m_arenas.keySet(); + } - public TestSpawn(Location location) { - m_location = location; + private class TestSpawn implements Waypoint { + double m_x; + double m_y; + double m_z; + String m_name; + + public TestSpawn(double x, double y, double z) { + m_x = x; + m_y = y; + m_z = z; + m_name = "(" + x + "," + y + "," + z + ")"; } - @Override - public Location getLocation() { - return m_location; - } + public double getX() { return m_x; } + public double getY() { return m_y; } + public double getZ() { return m_z; } @Override public String getName() { - return "Mob Spawner"; - } - - @Override - public String getID() { - return "mob-spawner"; + return m_name; } } @@ -63,23 +81,107 @@ public class Plugin extends JavaPlugin { public void onEnable() { getLogger().info("Malloc Defense registered"); getLogger().setLevel(Level.FINEST); - setupDemoGame(); - getCommand("setstage").setExecutor(new SetStageCommand(this)); - getCommand("addplayer").setExecutor(new AddPlayerCommand(this)); - getCommand("debuginfo").setExecutor(new DebuginfoCommand(this)); + //setupDemoGame(); + m_games.add(new ScaledWaves()); + loadArenas(); + getCommand("join").setExecutor(new JoinGameCommand(this)); + getCommand("leave").setExecutor(new LeaveGameCommand(this)); getCommand("ready").setExecutor(new PlayerReadyCommand(this)); + getCommand("list").setExecutor(new ListGamesCommand(this)); + + getCommand("addplayer").setExecutor(new AddPlayerCommand(this)); + getCommand("setstage").setExecutor(new SetStageCommand(this)); + getCommand("debuginfo").setExecutor(new DebuginfoCommand(this)); + + getServer().getPluginManager().registerEvents(new PlayerQuitHandler(), this); } - public GameRunner getRunnerForWorld(World world) { + void loadArenas() { + getLogger().info("Loading arenas..."); + saveDefaultConfig(); + ConfigurationSection pluginConfig = getConfig(); + ConfigurationSection mapList = pluginConfig.getConfigurationSection("maps"); + + for(String mapName : mapList.getKeys(false)) { + getLogger().info("Loading arena: " + mapName); + ConfigurationSection mapConfig = mapList.getConfigurationSection(mapName); + List> spawnpointList = mapConfig.getMapList("spawnpoints"); + ArrayList spawnpoints = new ArrayList<>(); + + for(Map spawnerObj : spawnpointList) { + Map thisSpawner = (Map)spawnerObj; + double x = thisSpawner.get("x"); + double y = thisSpawner.get("y"); + double z = thisSpawner.get("z"); + spawnpoints.add(new TestSpawn(x, y, z)); + } + + ConfigurationSection targetConfig = mapConfig.getConfigurationSection("target"); + double x = targetConfig.getDouble("x"); + double y = targetConfig.getDouble("y"); + double z = targetConfig.getDouble("z"); + Waypoint bombTarget = new TestSpawn(x, y, z); + Waypoint[] spawnArray = new Waypoint[spawnpoints.size()]; + spawnpoints.toArray(spawnArray); + Arena arena = new MemoryArena(spawnArray, bombTarget); + m_arenas.put(mapName, arena); + } + } + + /*GameRunner getRunnerForWorld(World world) { GameRunner ret; if (m_runningGames.containsKey(world)) { ret = m_runningGames.get(world); - } else { - ret = new GameRunner(this, m_games.get(0), m_arenas.get(0)); + } else if (m_arenas.containsKey(world)) { + ret = new GameRunner(this, m_games.get(0), m_arenas.get(world.getName()), world); m_runningGames.put(world, ret); getServer().getPluginManager().registerEvents(new GameEventHandler(ret), this); } return ret; + }*/ + + public boolean hasRunnerForArenaName(String arenaName) { + return m_runningGames.containsKey(arenaName); + } + + public void addPlayerToArena(String arenaName, Player player) { + GameRunner runner = getRunnerForArenaName(arenaName); + runner.addPlayer(player); + m_playerGames.put(player, runner); + } + + class PlayerQuitHandler implements Listener { + @EventHandler + public void onPlayerQuit(PlayerQuitEvent evt) { + m_playerGames.remove(evt.getPlayer()); + } + } + + public GameRunner getRunnerForArenaName(String arenaName) { + GameRunner ret = null; + if (m_runningGames.containsKey(arenaName)) { + ret = m_runningGames.get(arenaName); + } else if (m_arenas.containsKey(arenaName)) { + getLogger().info("Loading game world " + arenaName); + World gameWorld = getServer().getWorld(arenaName); + if (gameWorld == null) { + getLogger().info("Creating game world " + arenaName); + gameWorld = new WorldCreator(arenaName).generateStructures(false).createWorld(); + } + ret = new GameRunner(this, m_games.get(0), m_arenas.get(arenaName), gameWorld); + getServer().getPluginManager().registerEvents(new GameEventHandler(ret), this); + m_runningGames.put(arenaName, ret); + getLogger().info("Game ready for " + arenaName); + } + return ret; + } + + public GameRunner getRunnerForPlayer(Player p) { + GameRunner ret = null; + if (m_playerGames.containsKey(p)) { + ret = m_playerGames.get(p); + } + return ret; } void setupDemoGame() { @@ -88,12 +190,11 @@ public class Plugin extends JavaPlugin { if (testWorld == null) { testWorld = new WorldCreator("quarry").generateStructures(false).createWorld(); } - Spawnpoint[] spawnpoints = new Spawnpoint[3]; - spawnpoints[0] = new TestSpawn(new Location(testWorld, -15, 80, -46)); - spawnpoints[1] = new TestSpawn(new Location(testWorld, -1, 80, -45)); - spawnpoints[2] = new TestSpawn(new Location(testWorld, 12, 81, -42)); - Spawnpoint bombTarget = new TestSpawn(new Location(testWorld, -20, 80, 31)); - m_arenas.add(new MemoryArena("Test Arena", testWorld, spawnpoints, bombTarget)); - m_games.add(new ScaledWaves()); + Waypoint[] spawnpoints = new Waypoint[3]; + spawnpoints[0] = new TestSpawn(-15, 80, -46); + spawnpoints[1] = new TestSpawn(-1, 80, -45); + spawnpoints[2] = new TestSpawn(12, 81, -42); + Waypoint bombTarget = new TestSpawn(-20, 80, 31); + m_arenas.put("quarry", new MemoryArena(spawnpoints, bombTarget)); } } diff --git a/src/main/java/gg/malloc/defense/commands/AddPlayerCommand.java b/src/main/java/gg/malloc/defense/commands/AddPlayerCommand.java index 7c97669..37e5be1 100644 --- a/src/main/java/gg/malloc/defense/commands/AddPlayerCommand.java +++ b/src/main/java/gg/malloc/defense/commands/AddPlayerCommand.java @@ -18,8 +18,12 @@ public class AddPlayerCommand implements CommandExecutor { @Override public boolean onCommand(CommandSender sender, Command command, String s, String[] args) { - String worldName = args[0]; - GameRunner runner = m_plugin.getRunnerForWorld(m_plugin.getServer().getWorld(worldName)); + String arenaName = args[0]; + GameRunner runner = m_plugin.getRunnerForArenaName(arenaName); + if (runner == null) { + sender.sendMessage("No such arena '" + arenaName + "'"); + return true; + } Player player = m_plugin.getServer().getPlayer(args[1]); runner.addPlayer(player); return true; diff --git a/src/main/java/gg/malloc/defense/commands/JoinGameCommand.java b/src/main/java/gg/malloc/defense/commands/JoinGameCommand.java new file mode 100644 index 0000000..588b1c9 --- /dev/null +++ b/src/main/java/gg/malloc/defense/commands/JoinGameCommand.java @@ -0,0 +1,56 @@ +package gg.malloc.defense.commands; + +import org.bukkit.command.Command; +import org.bukkit.command.TabExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import gg.malloc.defense.engine.GameRunner; + +import gg.malloc.defense.Plugin; + +import java.util.ArrayList; +import java.util.List; + +public class JoinGameCommand implements TabExecutor { + Plugin m_plugin; + + public JoinGameCommand(Plugin plugin) { + m_plugin = plugin; + } + + public List onTabComplete(CommandSender sender, Command command, String label, String[] args) { + ArrayList ret = new ArrayList<>(); + if (args.length == 1) { + String proposal = args[0].toLowerCase(); + for(String arena : m_plugin.arenaNames()) { + if (proposal.startsWith(arena.toLowerCase())) { + ret.add(arena); + } + } + } + return ret; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String s, String[] args) { + if (args.length != 1) { + sender.sendMessage("Usage: join "); + return true; + } + if (sender instanceof Player) { + Player player = (Player)sender; + String arenaName = args[0]; + sender.sendMessage("Joining arena '" + arenaName + "'..."); + GameRunner runner = m_plugin.getRunnerForArenaName(arenaName); + if (runner == null) { + sender.sendMessage("No such arena '" + arenaName + "'"); + return true; + } + m_plugin.addPlayerToArena(arenaName, player); + } else { + sender.sendMessage("Only players may use htis command."); + } + return true; + } +} diff --git a/src/main/java/gg/malloc/defense/commands/LeaveGameCommand.java b/src/main/java/gg/malloc/defense/commands/LeaveGameCommand.java new file mode 100644 index 0000000..139757e --- /dev/null +++ b/src/main/java/gg/malloc/defense/commands/LeaveGameCommand.java @@ -0,0 +1,35 @@ +package gg.malloc.defense.commands; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import gg.malloc.defense.engine.GameRunner; + +import gg.malloc.defense.Plugin; + +public class LeaveGameCommand implements CommandExecutor { + Plugin m_plugin; + + public LeaveGameCommand(Plugin plugin) { + m_plugin = plugin; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String s, String[] args) { + if (sender instanceof Player) { + Player player = (Player)sender; + GameRunner runner = m_plugin.getRunnerForPlayer(player); + if (runner == null) { + sender.sendMessage("You ae not currently in a game."); + return true; + } + runner.removePlayer(player); + } else { + sender.sendMessage("Only players may use htis command."); + } + return true; + } +} + diff --git a/src/main/java/gg/malloc/defense/commands/ListGamesCommand.java b/src/main/java/gg/malloc/defense/commands/ListGamesCommand.java new file mode 100644 index 0000000..617b5bb --- /dev/null +++ b/src/main/java/gg/malloc/defense/commands/ListGamesCommand.java @@ -0,0 +1,35 @@ +package gg.malloc.defense.commands; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import gg.malloc.defense.engine.GameRunner; + +import gg.malloc.defense.Plugin; + +public class ListGamesCommand implements CommandExecutor { + Plugin m_plugin; + + public ListGamesCommand(Plugin plugin) { + m_plugin = plugin; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String s, String[] args) { + sender.sendMessage("Available games:"); + for(String arenaName : m_plugin.arenaNames()) { + String arenaDescription = arenaName + ": "; + if (m_plugin.hasRunnerForArenaName(arenaName)) { + GameRunner runner = m_plugin.getRunnerForArenaName(arenaName); + arenaDescription += runner.getStage().toString(); + } else { + arenaDescription += "Loadable"; + } + sender.sendMessage(arenaDescription); + } + return true; + } +} + diff --git a/src/main/java/gg/malloc/defense/commands/PlayerReadyCommand.java b/src/main/java/gg/malloc/defense/commands/PlayerReadyCommand.java index d6fa338..6e54fbf 100644 --- a/src/main/java/gg/malloc/defense/commands/PlayerReadyCommand.java +++ b/src/main/java/gg/malloc/defense/commands/PlayerReadyCommand.java @@ -20,9 +20,12 @@ public class PlayerReadyCommand implements CommandExecutor { public boolean onCommand(CommandSender sender, Command command, String s, String[] args) { if (sender instanceof Player) { Player player = (Player)sender; - GameRunner runner = m_plugin.getRunnerForWorld(player.getLocation().getWorld()); - runner.addPlayer(player); - runner.togglePlayerReady(player); + GameRunner runner = m_plugin.getRunnerForPlayer(player); + if (runner != null) { + runner.togglePlayerReady(player); + } else { + sender.sendMessage("You are not part of any game."); + } return true; } else { sender.sendMessage("You must be a player to use this command."); diff --git a/src/main/java/gg/malloc/defense/commands/SetStageCommand.java b/src/main/java/gg/malloc/defense/commands/SetStageCommand.java index 5517d84..8c87fac 100644 --- a/src/main/java/gg/malloc/defense/commands/SetStageCommand.java +++ b/src/main/java/gg/malloc/defense/commands/SetStageCommand.java @@ -1,25 +1,56 @@ package gg.malloc.defense.commands; import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; +import org.bukkit.command.TabExecutor; import org.bukkit.World; import gg.malloc.defense.engine.GameRunner; import gg.malloc.defense.Plugin; -public class SetStageCommand implements CommandExecutor { +import java.util.ArrayList; +import java.util.List; + +public class SetStageCommand implements TabExecutor { Plugin m_plugin; public SetStageCommand(Plugin plugin) { m_plugin = plugin; } + public List onTabComplete(CommandSender sender, Command command, String label, String[] args) { + ArrayList ret = new ArrayList<>(); + if (args.length == 1) { + String proposal = args[0]; + for(String arena : m_plugin.arenaNames()) { + if (proposal.startsWith(arena)) { + ret.add(arena); + } + } + } else if (args.length == 2) { + String proposal = args[1].toLowerCase(); + GameRunner.Stage stages[] = GameRunner.Stage.Idle.getDeclaringClass().getEnumConstants(); + for(GameRunner.Stage stage : stages) { + if (proposal.startsWith(stage.toString().toLowerCase())) { + ret.add(stage.toString()); + } + } + } + return ret; + } + @Override public boolean onCommand(CommandSender sender, Command command, String s, String[] args) { - World world = m_plugin.getServer().getWorld(args[1]); - GameRunner runner = m_plugin.getRunnerForWorld(world); + if (args.length != 2) { + sender.sendMessage("Usage: setstage "); + return true; + } + GameRunner runner = m_plugin.getRunnerForArenaName(args[1]); + if (runner == null) { + sender.sendMessage("Unknown arena " + args[1]); + return true; + } String stateName = args[0].toLowerCase(); boolean ret = false; GameRunner.Stage decodedStage = null; diff --git a/src/main/java/gg/malloc/defense/engine/GameRunner.java b/src/main/java/gg/malloc/defense/engine/GameRunner.java index ab209de..4d8fd74 100644 --- a/src/main/java/gg/malloc/defense/engine/GameRunner.java +++ b/src/main/java/gg/malloc/defense/engine/GameRunner.java @@ -3,6 +3,7 @@ package gg.malloc.defense.engine; import gg.malloc.defense.model.Arena; import gg.malloc.defense.model.Game; import gg.malloc.defense.model.Spawner; +import gg.malloc.defense.model.Waypoint; import gg.malloc.defense.ui.BombCarrier; import gg.malloc.defense.ui.BossBars; @@ -60,9 +61,16 @@ public class GameRunner { BossBars m_bars; - public GameRunner(Plugin plugin, Game game, Arena arena) { + World m_world; + + Location getLocation(Waypoint waypoint) { + return new Location(m_world, waypoint.getX(), waypoint.getY(), waypoint.getZ()); + } + + public GameRunner(Plugin plugin, Game game, Arena arena, World world) { m_plugin = plugin; m_game = game; + m_world = world; m_arena = arena; m_stage = Stage.Idle; m_mobs = new MobManager(); @@ -92,13 +100,13 @@ public class GameRunner { }, 20); m_bombSmokeTask = new TickTask(m_plugin, () -> { - Location targetLoc = m_arena.bombTarget().getLocation(); - m_arena.getWorld().spawnParticle(Particle.SMOKE_LARGE, targetLoc, 35, 4, 2, 4); - m_arena.getWorld().spawnParticle(Particle.SMALL_FLAME, targetLoc, 30, 3, 2, 3); + Location targetLoc = getLocation(m_arena.bombTarget()); + m_world.spawnParticle(Particle.SMOKE_LARGE, targetLoc, 35, 4, 2, 4); + m_world.spawnParticle(Particle.SMALL_FLAME, targetLoc, 30, 3, 2, 3); }, 5); m_bombCrackleTask = new TickTask(m_plugin, () -> { - Location targetLoc = m_arena.bombTarget().getLocation(); - m_arena.getWorld().playSound(targetLoc, Sound.BLOCK_CAMPFIRE_CRACKLE, SoundCategory.NEUTRAL, 1.0f, 1.0f); + Location targetLoc = getLocation(m_arena.bombTarget()); + m_world.playSound(targetLoc, Sound.BLOCK_CAMPFIRE_CRACKLE, SoundCategory.NEUTRAL, 1.0f, 1.0f); }, 35); } @@ -115,12 +123,12 @@ public class GameRunner { m_log.info("Target attacked!"); entityEvt.getDamager().setGlowing(true); m_bombFuse.tickLit(); - m_arena.getWorld().playSound(m_arena.bombTarget().getLocation(), Sound.ENTITY_ZOMBIE_ATTACK_IRON_DOOR, 1.5f, 0.9f); + m_world.playSound(getLocation(m_arena.bombTarget()), Sound.ENTITY_ZOMBIE_ATTACK_IRON_DOOR, 1.5f, 0.9f); m_bars.update(); if (m_bombFuse.isExploded()) { - m_arena.getWorld().strikeLightningEffect(m_arena.bombTarget().getLocation()); - m_arena.getWorld().playSound(m_arena.bombTarget().getLocation(), Sound.ENTITY_GENERIC_EXPLODE, SoundCategory.NEUTRAL, 1.3f, 1.0f); - m_arena.getWorld().spawnParticle(Particle.EXPLOSION_HUGE, m_arena.bombTarget().getLocation(), 8, 5, 2, 5); + m_world.strikeLightningEffect(getLocation(m_arena.bombTarget())); + m_world.playSound(getLocation(m_arena.bombTarget()), Sound.ENTITY_GENERIC_EXPLODE, SoundCategory.NEUTRAL, 1.3f, 1.0f); + m_world.spawnParticle(Particle.EXPLOSION_HUGE, getLocation(m_arena.bombTarget()), 8, 5, 2, 5); requestTransition(Stage.GameOver); m_bombSmokeTask.start(); m_bombCrackleTask.start(); @@ -150,7 +158,7 @@ public class GameRunner { m_waves.next(); for(Player p : m_players.getPlayers()) { if (m_players.requestTransition(p, PlayerManager.State.Playing)) { - p.teleport(m_arena.getWorld().getSpawnLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN); + p.teleport(m_world.getSpawnLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN); } m_players.setReady(p, false); } @@ -179,11 +187,11 @@ public class GameRunner { private boolean enterPlaying() { m_log.info("Starting wave " + m_waves.currentWaveNum()); - m_mobs.spawnTarget(m_arena.bombTarget().getLocation()); + m_mobs.spawnTarget(getLocation(m_arena.bombTarget())); // TODO: Set helmet with custom model data for(Player p : m_players.getPlayers()) { if (m_players.requestTransition(p, PlayerManager.State.Playing)) { - p.teleport(m_arena.getWorld().getSpawnLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN); + p.teleport(m_world.getSpawnLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN); } } m_countdownTask.stop(); @@ -211,14 +219,14 @@ public class GameRunner { private void spawnNextBatch() { broadcastMessage("Spawning batch " + m_waves.currentBatchNum()); - Spawner spawner = new GameSpawner(m_arena, m_mobs, m_players); + Spawner spawner = new GameSpawner(m_world, m_arena, m_mobs, m_players); m_waves.currentWave().spawnBatch(spawner, m_waves.currentBatchNum()); m_bars.update(); } private void handlePlayerDeath(Player player) { if (m_players.requestTransition(player, PlayerManager.State.Dead)) { - m_arena.getWorld().strikeLightningEffect(player.getLocation()); + m_world.strikeLightningEffect(player.getLocation()); if (!m_players.isAnyoneAlive()) { broadcastMessage("Everyone is dead :("); requestTransition(Stage.GameOver); @@ -273,7 +281,7 @@ public class GameRunner { private boolean validateTransition(Stage from, Stage to) { switch(from) { case Idle: - return to == Stage.Warmup; + return !m_players.isEmpty() && to == Stage.Warmup; case Warmup: return to == Stage.Playing || to == Stage.Idle || to == Stage.Countdown ; case Countdown: @@ -309,7 +317,7 @@ public class GameRunner { m_bars.addPlayer(p); if (m_stage == Stage.Idle || m_stage == Stage.Warmup) { if (m_players.requestTransition(p, PlayerManager.State.Playing)) { - p.teleport(m_arena.getWorld().getSpawnLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN); + p.teleport(m_world.getSpawnLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN); } broadcastMessage(p.getName() + " has joined the game"); if (m_stage == Stage.Idle) { @@ -337,8 +345,7 @@ public class GameRunner { } void broadcastMessage(String string) { - World world = m_arena.getWorld(); - for(Player p : world.getPlayers()) { + for(Player p : m_world.getPlayers()) { p.sendMessage(string); } } diff --git a/src/main/java/gg/malloc/defense/engine/GameSpawner.java b/src/main/java/gg/malloc/defense/engine/GameSpawner.java index 0a01293..d531ba0 100644 --- a/src/main/java/gg/malloc/defense/engine/GameSpawner.java +++ b/src/main/java/gg/malloc/defense/engine/GameSpawner.java @@ -1,13 +1,15 @@ package gg.malloc.defense.engine; import gg.malloc.defense.model.Spawner; -import gg.malloc.defense.model.Spawnpoint; +import gg.malloc.defense.model.Waypoint; import gg.malloc.defense.model.Arena; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.EntityType; import org.bukkit.entity.Mob; +import org.bukkit.World; +import org.bukkit.Location; import org.bukkit.inventory.EntityEquipment; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; @@ -20,8 +22,10 @@ public class GameSpawner implements Spawner { MobManager m_manager; PlayerManager m_players; int m_spawnIdx = 0; + World m_world; - public GameSpawner(Arena arena, MobManager manager, PlayerManager players) { + public GameSpawner(World world, Arena arena, MobManager manager, PlayerManager players) { + m_world = world; m_arena = arena; m_manager = manager; m_players = players; @@ -38,10 +42,12 @@ public class GameSpawner implements Spawner { @Override public LivingEntity spawnMob(EntityType type) { - Spawnpoint[] spawnpoints = m_arena.spawnpoints(); + Waypoint[] spawnpoints = m_arena.spawnpoints(); m_spawnIdx %= spawnpoints.length; //m_log.fine("Spawning " + type + " at " + spawnpoints[m_spawnIdx]); - Entity newMob = m_arena.getWorld().spawnEntity(spawnpoints[m_spawnIdx].getLocation(), type); + Waypoint thisSpawner = spawnpoints[m_spawnIdx]; + Location loc = new Location(m_world, thisSpawner.getX(), thisSpawner.getY(), thisSpawner.getZ()); + Entity newMob = m_world.spawnEntity(loc, type); LivingEntity livingMob = (LivingEntity)newMob; livingMob.setRemoveWhenFarAway(false); m_manager.addEntity(livingMob); diff --git a/src/main/java/gg/malloc/defense/model/Arena.java b/src/main/java/gg/malloc/defense/model/Arena.java index 11e5265..333de4c 100644 --- a/src/main/java/gg/malloc/defense/model/Arena.java +++ b/src/main/java/gg/malloc/defense/model/Arena.java @@ -3,8 +3,6 @@ package gg.malloc.defense.model; import org.bukkit.World; public interface Arena { - World getWorld(); - String name(); - Spawnpoint[] spawnpoints(); - Spawnpoint bombTarget(); + Waypoint[] spawnpoints(); + Waypoint bombTarget(); } diff --git a/src/main/java/gg/malloc/defense/model/Game.java b/src/main/java/gg/malloc/defense/model/Game.java index cdbb2d5..d264502 100644 --- a/src/main/java/gg/malloc/defense/model/Game.java +++ b/src/main/java/gg/malloc/defense/model/Game.java @@ -1,8 +1,6 @@ package gg.malloc.defense.model; -import org.bukkit.entity.Entity; public interface Game { int getWaveCount(); Wave getWave(int waveNumber); - default void onMobDamaged(Entity entity) {} } diff --git a/src/main/java/gg/malloc/defense/model/Spawnpoint.java b/src/main/java/gg/malloc/defense/model/Spawnpoint.java deleted file mode 100644 index 11f0e49..0000000 --- a/src/main/java/gg/malloc/defense/model/Spawnpoint.java +++ /dev/null @@ -1,9 +0,0 @@ -package gg.malloc.defense.model; - -import org.bukkit.Location; - -public interface Spawnpoint { - Location getLocation(); - String getName(); - String getID(); -} diff --git a/src/main/java/gg/malloc/defense/model/Waypoint.java b/src/main/java/gg/malloc/defense/model/Waypoint.java new file mode 100644 index 0000000..eda052f --- /dev/null +++ b/src/main/java/gg/malloc/defense/model/Waypoint.java @@ -0,0 +1,8 @@ +package gg.malloc.defense.model; + +public interface Waypoint { + double getX(); + double getY(); + double getZ(); + String getName(); +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml new file mode 100644 index 0000000..5acdce0 --- /dev/null +++ b/src/main/resources/config.yml @@ -0,0 +1,16 @@ +maps: + quarry: + target: + x: -20.0 + y: 80.0 + z: 31.0 + spawnpoints: + - x: -15.0 + y: 80.0 + z: -46.0 + - x: -1.0 + y: 80.0 + z: -45.0 + - x: 12.0 + y: 81.0 + z: -42.0 diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 0737546..a89a5bf 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -4,11 +4,17 @@ api-version: 1.18 main: gg.malloc.defense.Plugin depend: [] commands: + ready: + description: Mark yourself as ready for the next wave + list: + description: List games + join: + description: Join a game + leave: + description: Leave a game setstage: description: Sets a game stage addplayer: description: Adds a player to a game debuginfo: description: Unknowable powers - ready: - description: Mark yourself as ready for the next wave