Implement first pass at config loading, /join, /leave commands, tab completion (broken)
This commit is contained in:
		
							
								
								
									
										39
									
								
								TODO.md
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								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 | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -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<Arena> m_arenas = new ArrayList<>(); | ||||
|   HashMap<String, Arena> m_arenas = new HashMap<>(); | ||||
|   ArrayList<Game> m_games = new ArrayList<>(); | ||||
|   HashMap<World, GameRunner> m_runningGames = new HashMap<>(); | ||||
|   HashMap<String, GameRunner> m_runningGames = new HashMap<>(); | ||||
|   HashMap<Player, GameRunner> m_playerGames = new HashMap<>(); | ||||
|  | ||||
|   private class TestSpawn implements Spawnpoint { | ||||
|     Location m_location; | ||||
|   public Collection<String> 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<Map<?, ?>> spawnpointList = mapConfig.getMapList("spawnpoints"); | ||||
|       ArrayList<Waypoint> spawnpoints = new ArrayList<>(); | ||||
|  | ||||
|       for(Map<?, ?> spawnerObj : spawnpointList) { | ||||
|         Map<String, Double> thisSpawner = (Map<String, Double>)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)); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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<String> onTabComplete(CommandSender sender, Command command, String label, String[] args) { | ||||
|     ArrayList<String> 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 <game>"); | ||||
|       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; | ||||
|   } | ||||
| } | ||||
| @@ -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; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -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; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -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."); | ||||
|   | ||||
| @@ -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<String> onTabComplete(CommandSender sender, Command command, String label, String[] args) { | ||||
|     ArrayList<String> 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 <stage> <arena>"); | ||||
|       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; | ||||
|   | ||||
| @@ -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); | ||||
|     } | ||||
|   } | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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(); | ||||
| } | ||||
|   | ||||
| @@ -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) {} | ||||
| } | ||||
|   | ||||
| @@ -1,9 +0,0 @@ | ||||
| package gg.malloc.defense.model; | ||||
|  | ||||
| import org.bukkit.Location; | ||||
|  | ||||
| public interface Spawnpoint { | ||||
|   Location getLocation(); | ||||
|   String getName(); | ||||
|   String getID(); | ||||
| } | ||||
							
								
								
									
										8
									
								
								src/main/java/gg/malloc/defense/model/Waypoint.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/main/java/gg/malloc/defense/model/Waypoint.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| package gg.malloc.defense.model; | ||||
|  | ||||
| public interface Waypoint { | ||||
|   double getX(); | ||||
|   double getY(); | ||||
|   double getZ(); | ||||
|   String getName(); | ||||
| } | ||||
							
								
								
									
										16
									
								
								src/main/resources/config.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/main/resources/config.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
| @@ -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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user