Implement first pass at config loading, /join, /leave commands, tab completion (broken)
This commit is contained in:
parent
75debe1905
commit
a4b110773e
39
TODO.md
39
TODO.md
@ -8,12 +8,18 @@
|
|||||||
|
|
||||||
# Malloc Beta
|
# Malloc Beta
|
||||||
|
|
||||||
[ ] Join games
|
[X] One arena config
|
||||||
[ ] Leave games
|
[ ] Config reload
|
||||||
[ ] One arena config
|
[X] Leave games
|
||||||
|
[X] Join games
|
||||||
|
[ ] Lobby with instructions
|
||||||
|
[ ] Drop back to lobby on game over
|
||||||
|
[ ] Grist drops
|
||||||
|
[ ] Item shoppes
|
||||||
|
|
||||||
# Scaled waves
|
# Scaled waves
|
||||||
|
|
||||||
|
[ ] Limit ranged mobs and Ravagers to non-bomb-carrier state
|
||||||
[ ] Weaker mobs, more of them
|
[ ] Weaker mobs, more of them
|
||||||
[ ] Mob categories
|
[ ] Mob categories
|
||||||
[ ] Spawnpoint categories
|
[ ] Spawnpoint categories
|
||||||
@ -24,9 +30,16 @@
|
|||||||
[X] Mob count boss bar
|
[X] Mob count boss bar
|
||||||
[X] Stage titles
|
[X] Stage titles
|
||||||
[X] EXPLOSIONS
|
[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
|
[ ] Colored titles
|
||||||
|
[ ] Clickable join links in /list
|
||||||
|
[ ] Clickable /leave action
|
||||||
[ ] Clickable /ready in chat
|
[ ] Clickable /ready in chat
|
||||||
|
[ ] Countdown while in warmup
|
||||||
|
[ ] Countdown shrinks w/ every /ready player
|
||||||
|
[ ] Target catches on fire more it is lit
|
||||||
[ ] Sidebar
|
[ ] Sidebar
|
||||||
[ ] List of mobs in next wave
|
[ ] List of mobs in next wave
|
||||||
|
|
||||||
@ -37,13 +50,16 @@
|
|||||||
[ ] Plan stats
|
[ ] Plan stats
|
||||||
[ ] /invite friends to games
|
[ ] /invite friends to games
|
||||||
[ ] /voterestart
|
[ ] /voterestart
|
||||||
|
[ ] Medals/awards/scoreboards
|
||||||
|
|
||||||
# Mechanics
|
# Mechanics
|
||||||
|
|
||||||
[ ] Coin drops
|
|
||||||
[X] Mob tracking should prioritize bomb
|
[X] Mob tracking should prioritize bomb
|
||||||
[X] Mobs recover dropped bombs
|
[X] Mobs recover dropped bombs
|
||||||
[X] Bomb carriers are slower
|
[X] Bomb carriers are slower
|
||||||
|
[ ] Coin drops
|
||||||
|
[ ] Mob categories
|
||||||
|
[ ] Mobs split between bomb and player priorities
|
||||||
[ ] Bonus coins for complete coin pickup
|
[ ] Bonus coins for complete coin pickup
|
||||||
[ ] Infinite weapons + armor
|
[ ] Infinite weapons + armor
|
||||||
[ ] Ammo/health spawns
|
[ ] Ammo/health spawns
|
||||||
@ -56,26 +72,29 @@
|
|||||||
[X] Batch overlap
|
[X] Batch overlap
|
||||||
[ ] Scripted batch overlap/timings
|
[ ] Scripted batch overlap/timings
|
||||||
[ ] Scripted spawn locations
|
[ ] Scripted spawn locations
|
||||||
|
[ ] Scripted waypoint paths
|
||||||
[ ] Bosses
|
[ ] Bosses
|
||||||
|
|
||||||
# Mapping
|
# Mapping
|
||||||
|
|
||||||
[ ] Load arenas from config file
|
[X] Load arenas from config file
|
||||||
[ ] Live map editing
|
[ ] Live map editing
|
||||||
|
|
||||||
# Game lifecycle
|
# Game lifecycle
|
||||||
|
|
||||||
[ ] /list arenas and games
|
[X] /list arenas and games
|
||||||
[ ] /start a game on an arena
|
[X] /join games
|
||||||
[ ] /join games
|
|
||||||
[X] /ready
|
[X] /ready
|
||||||
[ ] /leave games
|
[X] /leave games
|
||||||
[ ] /restart games
|
[ ] /restart games
|
||||||
[X] Spectator mode on death
|
[X] Spectator mode on death
|
||||||
[X] Player readiness starts countdown
|
[X] Player readiness starts countdown
|
||||||
[ ] Game is automatically closed some time after game over
|
[ ] Game is automatically closed some time after game over
|
||||||
[ ] Return to lobby on leave/close
|
[ ] Return to lobby on leave/close
|
||||||
[ ] Instancing
|
[ ] Instancing
|
||||||
|
[ ] Restore health+hunger on respawn/game start
|
||||||
|
[ ] Respawn during games
|
||||||
|
[ ] Player revival items
|
||||||
|
|
||||||
# Powerups
|
# Powerups
|
||||||
|
|
||||||
|
@ -1,41 +1,27 @@
|
|||||||
package gg.malloc.defense;
|
package gg.malloc.defense;
|
||||||
|
|
||||||
import gg.malloc.defense.model.Arena;
|
import gg.malloc.defense.model.Arena;
|
||||||
import gg.malloc.defense.model.Spawnpoint;
|
import gg.malloc.defense.model.Waypoint;
|
||||||
|
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
|
|
||||||
public class MemoryArena implements Arena {
|
public class MemoryArena implements Arena {
|
||||||
|
|
||||||
Spawnpoint[] m_spawnpoints;
|
Waypoint[] m_spawnpoints;
|
||||||
Spawnpoint m_bombTarget;
|
Waypoint m_bombTarget;
|
||||||
World m_world;
|
|
||||||
String m_name;
|
|
||||||
|
|
||||||
public MemoryArena(String name, World world, Spawnpoint[] spawnpoints, Spawnpoint bombTarget) {
|
public MemoryArena(Waypoint[] spawnpoints, Waypoint bombTarget) {
|
||||||
m_world = world;
|
|
||||||
m_spawnpoints = spawnpoints;
|
m_spawnpoints = spawnpoints;
|
||||||
m_name = name;
|
|
||||||
m_bombTarget = bombTarget;
|
m_bombTarget = bombTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String name() {
|
public Waypoint[] spawnpoints() {
|
||||||
return m_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Spawnpoint[] spawnpoints() {
|
|
||||||
return m_spawnpoints;
|
return m_spawnpoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public World getWorld() {
|
public Waypoint bombTarget() {
|
||||||
return m_world;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Spawnpoint bombTarget() {
|
|
||||||
return m_bombTarget;
|
return m_bombTarget;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,17 +5,27 @@ import org.bukkit.plugin.RegisteredServiceProvider;
|
|||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.EntityType;
|
import org.bukkit.entity.EntityType;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.WorldCreator;
|
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.Logger;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
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.Arena;
|
||||||
import gg.malloc.defense.model.Spawnpoint;
|
import gg.malloc.defense.model.Waypoint;
|
||||||
import gg.malloc.defense.model.Game;
|
import gg.malloc.defense.model.Game;
|
||||||
|
|
||||||
import gg.malloc.defense.games.LinearGame;
|
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.AddPlayerCommand;
|
||||||
import gg.malloc.defense.commands.SetStageCommand;
|
import gg.malloc.defense.commands.SetStageCommand;
|
||||||
import gg.malloc.defense.commands.PlayerReadyCommand;
|
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 {
|
public class Plugin extends JavaPlugin {
|
||||||
ArrayList<Arena> m_arenas = new ArrayList<>();
|
HashMap<String, Arena> m_arenas = new HashMap<>();
|
||||||
ArrayList<Game> m_games = new ArrayList<>();
|
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 {
|
public Collection<String> arenaNames() {
|
||||||
Location m_location;
|
return m_arenas.keySet();
|
||||||
|
|
||||||
public TestSpawn(Location location) {
|
|
||||||
m_location = location;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private class TestSpawn implements Waypoint {
|
||||||
public Location getLocation() {
|
double m_x;
|
||||||
return m_location;
|
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 + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public double getX() { return m_x; }
|
||||||
|
public double getY() { return m_y; }
|
||||||
|
public double getZ() { return m_z; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Mob Spawner";
|
return m_name;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getID() {
|
|
||||||
return "mob-spawner";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,23 +81,107 @@ public class Plugin extends JavaPlugin {
|
|||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
getLogger().info("Malloc Defense registered");
|
getLogger().info("Malloc Defense registered");
|
||||||
getLogger().setLevel(Level.FINEST);
|
getLogger().setLevel(Level.FINEST);
|
||||||
setupDemoGame();
|
//setupDemoGame();
|
||||||
getCommand("setstage").setExecutor(new SetStageCommand(this));
|
m_games.add(new ScaledWaves());
|
||||||
getCommand("addplayer").setExecutor(new AddPlayerCommand(this));
|
loadArenas();
|
||||||
getCommand("debuginfo").setExecutor(new DebuginfoCommand(this));
|
getCommand("join").setExecutor(new JoinGameCommand(this));
|
||||||
|
getCommand("leave").setExecutor(new LeaveGameCommand(this));
|
||||||
getCommand("ready").setExecutor(new PlayerReadyCommand(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;
|
GameRunner ret;
|
||||||
if (m_runningGames.containsKey(world)) {
|
if (m_runningGames.containsKey(world)) {
|
||||||
ret = m_runningGames.get(world);
|
ret = m_runningGames.get(world);
|
||||||
} else {
|
} else if (m_arenas.containsKey(world)) {
|
||||||
ret = new GameRunner(this, m_games.get(0), m_arenas.get(0));
|
ret = new GameRunner(this, m_games.get(0), m_arenas.get(world.getName()), world);
|
||||||
m_runningGames.put(world, ret);
|
m_runningGames.put(world, ret);
|
||||||
getServer().getPluginManager().registerEvents(new GameEventHandler(ret), this);
|
getServer().getPluginManager().registerEvents(new GameEventHandler(ret), this);
|
||||||
}
|
}
|
||||||
return ret;
|
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() {
|
void setupDemoGame() {
|
||||||
@ -88,12 +190,11 @@ public class Plugin extends JavaPlugin {
|
|||||||
if (testWorld == null) {
|
if (testWorld == null) {
|
||||||
testWorld = new WorldCreator("quarry").generateStructures(false).createWorld();
|
testWorld = new WorldCreator("quarry").generateStructures(false).createWorld();
|
||||||
}
|
}
|
||||||
Spawnpoint[] spawnpoints = new Spawnpoint[3];
|
Waypoint[] spawnpoints = new Waypoint[3];
|
||||||
spawnpoints[0] = new TestSpawn(new Location(testWorld, -15, 80, -46));
|
spawnpoints[0] = new TestSpawn(-15, 80, -46);
|
||||||
spawnpoints[1] = new TestSpawn(new Location(testWorld, -1, 80, -45));
|
spawnpoints[1] = new TestSpawn(-1, 80, -45);
|
||||||
spawnpoints[2] = new TestSpawn(new Location(testWorld, 12, 81, -42));
|
spawnpoints[2] = new TestSpawn(12, 81, -42);
|
||||||
Spawnpoint bombTarget = new TestSpawn(new Location(testWorld, -20, 80, 31));
|
Waypoint bombTarget = new TestSpawn(-20, 80, 31);
|
||||||
m_arenas.add(new MemoryArena("Test Arena", testWorld, spawnpoints, bombTarget));
|
m_arenas.put("quarry", new MemoryArena(spawnpoints, bombTarget));
|
||||||
m_games.add(new ScaledWaves());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,12 @@ public class AddPlayerCommand implements CommandExecutor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCommand(CommandSender sender, Command command, String s, String[] args) {
|
public boolean onCommand(CommandSender sender, Command command, String s, String[] args) {
|
||||||
String worldName = args[0];
|
String arenaName = args[0];
|
||||||
GameRunner runner = m_plugin.getRunnerForWorld(m_plugin.getServer().getWorld(worldName));
|
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]);
|
Player player = m_plugin.getServer().getPlayer(args[1]);
|
||||||
runner.addPlayer(player);
|
runner.addPlayer(player);
|
||||||
return true;
|
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) {
|
public boolean onCommand(CommandSender sender, Command command, String s, String[] args) {
|
||||||
if (sender instanceof Player) {
|
if (sender instanceof Player) {
|
||||||
Player player = (Player)sender;
|
Player player = (Player)sender;
|
||||||
GameRunner runner = m_plugin.getRunnerForWorld(player.getLocation().getWorld());
|
GameRunner runner = m_plugin.getRunnerForPlayer(player);
|
||||||
runner.addPlayer(player);
|
if (runner != null) {
|
||||||
runner.togglePlayerReady(player);
|
runner.togglePlayerReady(player);
|
||||||
|
} else {
|
||||||
|
sender.sendMessage("You are not part of any game.");
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
sender.sendMessage("You must be a player to use this command.");
|
sender.sendMessage("You must be a player to use this command.");
|
||||||
|
@ -1,25 +1,56 @@
|
|||||||
package gg.malloc.defense.commands;
|
package gg.malloc.defense.commands;
|
||||||
|
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandExecutor;
|
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.command.TabExecutor;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
|
|
||||||
import gg.malloc.defense.engine.GameRunner;
|
import gg.malloc.defense.engine.GameRunner;
|
||||||
|
|
||||||
import gg.malloc.defense.Plugin;
|
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;
|
Plugin m_plugin;
|
||||||
|
|
||||||
public SetStageCommand(Plugin plugin) {
|
public SetStageCommand(Plugin plugin) {
|
||||||
m_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
|
@Override
|
||||||
public boolean onCommand(CommandSender sender, Command command, String s, String[] args) {
|
public boolean onCommand(CommandSender sender, Command command, String s, String[] args) {
|
||||||
World world = m_plugin.getServer().getWorld(args[1]);
|
if (args.length != 2) {
|
||||||
GameRunner runner = m_plugin.getRunnerForWorld(world);
|
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();
|
String stateName = args[0].toLowerCase();
|
||||||
boolean ret = false;
|
boolean ret = false;
|
||||||
GameRunner.Stage decodedStage = null;
|
GameRunner.Stage decodedStage = null;
|
||||||
|
@ -3,6 +3,7 @@ package gg.malloc.defense.engine;
|
|||||||
import gg.malloc.defense.model.Arena;
|
import gg.malloc.defense.model.Arena;
|
||||||
import gg.malloc.defense.model.Game;
|
import gg.malloc.defense.model.Game;
|
||||||
import gg.malloc.defense.model.Spawner;
|
import gg.malloc.defense.model.Spawner;
|
||||||
|
import gg.malloc.defense.model.Waypoint;
|
||||||
|
|
||||||
import gg.malloc.defense.ui.BombCarrier;
|
import gg.malloc.defense.ui.BombCarrier;
|
||||||
import gg.malloc.defense.ui.BossBars;
|
import gg.malloc.defense.ui.BossBars;
|
||||||
@ -60,9 +61,16 @@ public class GameRunner {
|
|||||||
|
|
||||||
BossBars m_bars;
|
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_plugin = plugin;
|
||||||
m_game = game;
|
m_game = game;
|
||||||
|
m_world = world;
|
||||||
m_arena = arena;
|
m_arena = arena;
|
||||||
m_stage = Stage.Idle;
|
m_stage = Stage.Idle;
|
||||||
m_mobs = new MobManager();
|
m_mobs = new MobManager();
|
||||||
@ -92,13 +100,13 @@ public class GameRunner {
|
|||||||
}, 20);
|
}, 20);
|
||||||
|
|
||||||
m_bombSmokeTask = new TickTask(m_plugin, () -> {
|
m_bombSmokeTask = new TickTask(m_plugin, () -> {
|
||||||
Location targetLoc = m_arena.bombTarget().getLocation();
|
Location targetLoc = getLocation(m_arena.bombTarget());
|
||||||
m_arena.getWorld().spawnParticle(Particle.SMOKE_LARGE, targetLoc, 35, 4, 2, 4);
|
m_world.spawnParticle(Particle.SMOKE_LARGE, targetLoc, 35, 4, 2, 4);
|
||||||
m_arena.getWorld().spawnParticle(Particle.SMALL_FLAME, targetLoc, 30, 3, 2, 3);
|
m_world.spawnParticle(Particle.SMALL_FLAME, targetLoc, 30, 3, 2, 3);
|
||||||
}, 5);
|
}, 5);
|
||||||
m_bombCrackleTask = new TickTask(m_plugin, () -> {
|
m_bombCrackleTask = new TickTask(m_plugin, () -> {
|
||||||
Location targetLoc = m_arena.bombTarget().getLocation();
|
Location targetLoc = getLocation(m_arena.bombTarget());
|
||||||
m_arena.getWorld().playSound(targetLoc, Sound.BLOCK_CAMPFIRE_CRACKLE, SoundCategory.NEUTRAL, 1.0f, 1.0f);
|
m_world.playSound(targetLoc, Sound.BLOCK_CAMPFIRE_CRACKLE, SoundCategory.NEUTRAL, 1.0f, 1.0f);
|
||||||
}, 35);
|
}, 35);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,12 +123,12 @@ public class GameRunner {
|
|||||||
m_log.info("Target attacked!");
|
m_log.info("Target attacked!");
|
||||||
entityEvt.getDamager().setGlowing(true);
|
entityEvt.getDamager().setGlowing(true);
|
||||||
m_bombFuse.tickLit();
|
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();
|
m_bars.update();
|
||||||
if (m_bombFuse.isExploded()) {
|
if (m_bombFuse.isExploded()) {
|
||||||
m_arena.getWorld().strikeLightningEffect(m_arena.bombTarget().getLocation());
|
m_world.strikeLightningEffect(getLocation(m_arena.bombTarget()));
|
||||||
m_arena.getWorld().playSound(m_arena.bombTarget().getLocation(), Sound.ENTITY_GENERIC_EXPLODE, SoundCategory.NEUTRAL, 1.3f, 1.0f);
|
m_world.playSound(getLocation(m_arena.bombTarget()), 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.spawnParticle(Particle.EXPLOSION_HUGE, getLocation(m_arena.bombTarget()), 8, 5, 2, 5);
|
||||||
requestTransition(Stage.GameOver);
|
requestTransition(Stage.GameOver);
|
||||||
m_bombSmokeTask.start();
|
m_bombSmokeTask.start();
|
||||||
m_bombCrackleTask.start();
|
m_bombCrackleTask.start();
|
||||||
@ -150,7 +158,7 @@ public class GameRunner {
|
|||||||
m_waves.next();
|
m_waves.next();
|
||||||
for(Player p : m_players.getPlayers()) {
|
for(Player p : m_players.getPlayers()) {
|
||||||
if (m_players.requestTransition(p, PlayerManager.State.Playing)) {
|
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);
|
m_players.setReady(p, false);
|
||||||
}
|
}
|
||||||
@ -179,11 +187,11 @@ public class GameRunner {
|
|||||||
|
|
||||||
private boolean enterPlaying() {
|
private boolean enterPlaying() {
|
||||||
m_log.info("Starting wave " + m_waves.currentWaveNum());
|
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
|
// TODO: Set helmet with custom model data
|
||||||
for(Player p : m_players.getPlayers()) {
|
for(Player p : m_players.getPlayers()) {
|
||||||
if (m_players.requestTransition(p, PlayerManager.State.Playing)) {
|
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();
|
m_countdownTask.stop();
|
||||||
@ -211,14 +219,14 @@ public class GameRunner {
|
|||||||
|
|
||||||
private void spawnNextBatch() {
|
private void spawnNextBatch() {
|
||||||
broadcastMessage("Spawning batch " + m_waves.currentBatchNum());
|
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_waves.currentWave().spawnBatch(spawner, m_waves.currentBatchNum());
|
||||||
m_bars.update();
|
m_bars.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handlePlayerDeath(Player player) {
|
private void handlePlayerDeath(Player player) {
|
||||||
if (m_players.requestTransition(player, PlayerManager.State.Dead)) {
|
if (m_players.requestTransition(player, PlayerManager.State.Dead)) {
|
||||||
m_arena.getWorld().strikeLightningEffect(player.getLocation());
|
m_world.strikeLightningEffect(player.getLocation());
|
||||||
if (!m_players.isAnyoneAlive()) {
|
if (!m_players.isAnyoneAlive()) {
|
||||||
broadcastMessage("Everyone is dead :(");
|
broadcastMessage("Everyone is dead :(");
|
||||||
requestTransition(Stage.GameOver);
|
requestTransition(Stage.GameOver);
|
||||||
@ -273,7 +281,7 @@ public class GameRunner {
|
|||||||
private boolean validateTransition(Stage from, Stage to) {
|
private boolean validateTransition(Stage from, Stage to) {
|
||||||
switch(from) {
|
switch(from) {
|
||||||
case Idle:
|
case Idle:
|
||||||
return to == Stage.Warmup;
|
return !m_players.isEmpty() && to == Stage.Warmup;
|
||||||
case Warmup:
|
case Warmup:
|
||||||
return to == Stage.Playing || to == Stage.Idle || to == Stage.Countdown ;
|
return to == Stage.Playing || to == Stage.Idle || to == Stage.Countdown ;
|
||||||
case Countdown:
|
case Countdown:
|
||||||
@ -309,7 +317,7 @@ public class GameRunner {
|
|||||||
m_bars.addPlayer(p);
|
m_bars.addPlayer(p);
|
||||||
if (m_stage == Stage.Idle || m_stage == Stage.Warmup) {
|
if (m_stage == Stage.Idle || m_stage == Stage.Warmup) {
|
||||||
if (m_players.requestTransition(p, PlayerManager.State.Playing)) {
|
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");
|
broadcastMessage(p.getName() + " has joined the game");
|
||||||
if (m_stage == Stage.Idle) {
|
if (m_stage == Stage.Idle) {
|
||||||
@ -337,8 +345,7 @@ public class GameRunner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void broadcastMessage(String string) {
|
void broadcastMessage(String string) {
|
||||||
World world = m_arena.getWorld();
|
for(Player p : m_world.getPlayers()) {
|
||||||
for(Player p : world.getPlayers()) {
|
|
||||||
p.sendMessage(string);
|
p.sendMessage(string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
package gg.malloc.defense.engine;
|
package gg.malloc.defense.engine;
|
||||||
|
|
||||||
import gg.malloc.defense.model.Spawner;
|
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 gg.malloc.defense.model.Arena;
|
||||||
|
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.LivingEntity;
|
import org.bukkit.entity.LivingEntity;
|
||||||
import org.bukkit.entity.EntityType;
|
import org.bukkit.entity.EntityType;
|
||||||
import org.bukkit.entity.Mob;
|
import org.bukkit.entity.Mob;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.Location;
|
||||||
import org.bukkit.inventory.EntityEquipment;
|
import org.bukkit.inventory.EntityEquipment;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
@ -20,8 +22,10 @@ public class GameSpawner implements Spawner {
|
|||||||
MobManager m_manager;
|
MobManager m_manager;
|
||||||
PlayerManager m_players;
|
PlayerManager m_players;
|
||||||
int m_spawnIdx = 0;
|
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_arena = arena;
|
||||||
m_manager = manager;
|
m_manager = manager;
|
||||||
m_players = players;
|
m_players = players;
|
||||||
@ -38,10 +42,12 @@ public class GameSpawner implements Spawner {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LivingEntity spawnMob(EntityType type) {
|
public LivingEntity spawnMob(EntityType type) {
|
||||||
Spawnpoint[] spawnpoints = m_arena.spawnpoints();
|
Waypoint[] spawnpoints = m_arena.spawnpoints();
|
||||||
m_spawnIdx %= spawnpoints.length;
|
m_spawnIdx %= spawnpoints.length;
|
||||||
//m_log.fine("Spawning " + type + " at " + spawnpoints[m_spawnIdx]);
|
//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;
|
LivingEntity livingMob = (LivingEntity)newMob;
|
||||||
livingMob.setRemoveWhenFarAway(false);
|
livingMob.setRemoveWhenFarAway(false);
|
||||||
m_manager.addEntity(livingMob);
|
m_manager.addEntity(livingMob);
|
||||||
|
@ -3,8 +3,6 @@ package gg.malloc.defense.model;
|
|||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
|
|
||||||
public interface Arena {
|
public interface Arena {
|
||||||
World getWorld();
|
Waypoint[] spawnpoints();
|
||||||
String name();
|
Waypoint bombTarget();
|
||||||
Spawnpoint[] spawnpoints();
|
|
||||||
Spawnpoint bombTarget();
|
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package gg.malloc.defense.model;
|
package gg.malloc.defense.model;
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
|
|
||||||
public interface Game {
|
public interface Game {
|
||||||
int getWaveCount();
|
int getWaveCount();
|
||||||
Wave getWave(int waveNumber);
|
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
|
main: gg.malloc.defense.Plugin
|
||||||
depend: []
|
depend: []
|
||||||
commands:
|
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:
|
setstage:
|
||||||
description: Sets a game stage
|
description: Sets a game stage
|
||||||
addplayer:
|
addplayer:
|
||||||
description: Adds a player to a game
|
description: Adds a player to a game
|
||||||
debuginfo:
|
debuginfo:
|
||||||
description: Unknowable powers
|
description: Unknowable powers
|
||||||
ready:
|
|
||||||
description: Mark yourself as ready for the next wave
|
|
||||||
|
Loading…
Reference in New Issue
Block a user