reorganize engine bits into engine package, same with commands, reimplement player state as FSM
This commit is contained in:
parent
9e7ab2c0d4
commit
a078f74b4b
@ -1,5 +1,7 @@
|
|||||||
package gg.malloc.defense;
|
package gg.malloc.defense;
|
||||||
|
|
||||||
|
import gg.malloc.defense.engine.GameRunner;
|
||||||
|
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.entity.EntityDeathEvent;
|
import org.bukkit.event.entity.EntityDeathEvent;
|
||||||
|
@ -1,381 +0,0 @@
|
|||||||
package gg.malloc.defense;
|
|
||||||
|
|
||||||
import gg.malloc.defense.model.Game;
|
|
||||||
import gg.malloc.defense.model.Arena;
|
|
||||||
import gg.malloc.defense.model.Spawnpoint;
|
|
||||||
import gg.malloc.defense.model.Spawner;
|
|
||||||
import gg.malloc.defense.model.Wave;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.GameMode;
|
|
||||||
import org.bukkit.attribute.Attribute;
|
|
||||||
import org.bukkit.boss.BarColor;
|
|
||||||
import org.bukkit.boss.BarStyle;
|
|
||||||
import org.bukkit.boss.BossBar;
|
|
||||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
|
||||||
import org.bukkit.event.entity.EntityDamageEvent;
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.entity.EntityType;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.scheduler.BukkitTask;
|
|
||||||
|
|
||||||
public class GameRunner {
|
|
||||||
HashSet<Entity> m_livingMobs = new HashSet<>();
|
|
||||||
int m_createdMobs = 0;
|
|
||||||
int m_killedMobs = 0;
|
|
||||||
Arena m_arena;
|
|
||||||
Game m_game;
|
|
||||||
State m_state;
|
|
||||||
HashSet<Player> m_players = new HashSet<>();
|
|
||||||
HashSet<Player> m_livingPlayers = new HashSet<>();
|
|
||||||
Plugin m_plugin;
|
|
||||||
|
|
||||||
BossBar m_gameBar = Bukkit.createBossBar("Malloc Defense", BarColor.PURPLE, BarStyle.SOLID);
|
|
||||||
BossBar m_waveBar = Bukkit.createBossBar("Malloc Defense", BarColor.PURPLE, BarStyle.SOLID);
|
|
||||||
BukkitTask m_countdownTask;
|
|
||||||
|
|
||||||
int m_currentWaveNum = 0;
|
|
||||||
int m_currentBatch = 0;
|
|
||||||
Wave m_currentWave = null;
|
|
||||||
|
|
||||||
Logger m_log;
|
|
||||||
|
|
||||||
enum State {
|
|
||||||
Idle,
|
|
||||||
Warmup,
|
|
||||||
Playing,
|
|
||||||
GameOver
|
|
||||||
}
|
|
||||||
|
|
||||||
public GameRunner(Plugin plugin, Game game, Arena arena) {
|
|
||||||
m_plugin = plugin;
|
|
||||||
m_game = game;
|
|
||||||
m_arena = arena;
|
|
||||||
m_state = State.Idle;
|
|
||||||
m_gameBar.setVisible(true);
|
|
||||||
m_waveBar.setVisible(false);
|
|
||||||
m_log = m_plugin.getLogger();
|
|
||||||
}
|
|
||||||
|
|
||||||
int m_warmupCountdown = 0;
|
|
||||||
|
|
||||||
public void handleEntityDamage(EntityDamageEvent evt) {
|
|
||||||
Entity entity = evt.getEntity();
|
|
||||||
m_log.info("Damage " + entity);
|
|
||||||
m_log.info("Living Mobs " + m_livingMobs);
|
|
||||||
if (m_livingMobs.contains(entity)) {
|
|
||||||
m_game.onMobDamaged(entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void countdownTick() {
|
|
||||||
if (m_warmupCountdown == 0) {
|
|
||||||
requestTransition(State.Playing);
|
|
||||||
} else {
|
|
||||||
updateMobBars();
|
|
||||||
broadcastMessage("Starting game in " + m_warmupCountdown);
|
|
||||||
m_warmupCountdown--;
|
|
||||||
m_countdownTask = m_plugin.getServer().getScheduler().runTaskLater(m_plugin, () -> {
|
|
||||||
countdownTick();
|
|
||||||
}, 20);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void clearMobs() {
|
|
||||||
for(Entity e : m_livingMobs) {
|
|
||||||
e.remove();
|
|
||||||
}
|
|
||||||
m_livingMobs.clear();
|
|
||||||
m_createdMobs = 0;
|
|
||||||
m_killedMobs = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean enterIdle() {
|
|
||||||
broadcastMessage("Game state: Idle");
|
|
||||||
m_currentWaveNum = 0;
|
|
||||||
m_livingPlayers.clear();
|
|
||||||
for(Player p : m_players) {
|
|
||||||
m_livingPlayers.add(p);
|
|
||||||
}
|
|
||||||
if (m_countdownTask != null) {
|
|
||||||
m_countdownTask.cancel();
|
|
||||||
m_countdownTask = null;
|
|
||||||
}
|
|
||||||
clearMobs();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean enterWarmup() {
|
|
||||||
m_log.info("Game state: Warmup");
|
|
||||||
m_currentWaveNum += 1;
|
|
||||||
m_currentWave = m_game.getWave(m_currentWaveNum);
|
|
||||||
m_warmupCountdown = 10;
|
|
||||||
for(Player p : m_players) {
|
|
||||||
m_livingPlayers.add(p);
|
|
||||||
}
|
|
||||||
broadcastTitle("Warmup", "Prepare yourself for wave " + m_currentWaveNum);
|
|
||||||
clearMobs();
|
|
||||||
countdownTick();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean enterPlaying() {
|
|
||||||
m_log.info("Game state: Playing");
|
|
||||||
m_log.info("Starting wave " + m_currentWaveNum);
|
|
||||||
m_currentBatch = 1;
|
|
||||||
spawnNextBatch();
|
|
||||||
broadcastTitle("Wave " + m_currentWaveNum);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean enterGameOver() {
|
|
||||||
broadcastTitle("Game Over!");
|
|
||||||
if (m_countdownTask != null) {
|
|
||||||
m_countdownTask.cancel();
|
|
||||||
m_countdownTask = null;
|
|
||||||
}
|
|
||||||
clearMobs();
|
|
||||||
for(Player p : m_players) {
|
|
||||||
removePlayer(p);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateMobBars() {
|
|
||||||
m_gameBar.setVisible(true);
|
|
||||||
switch(m_state) {
|
|
||||||
case Idle:
|
|
||||||
m_gameBar.setProgress(1.0);
|
|
||||||
m_gameBar.setTitle("Waiting for playres...");
|
|
||||||
m_gameBar.setColor(BarColor.PURPLE);
|
|
||||||
m_waveBar.setVisible(false);
|
|
||||||
break;
|
|
||||||
case Warmup:
|
|
||||||
m_gameBar.setProgress((double)m_currentWaveNum / (double)m_game.getWaveCount());
|
|
||||||
m_gameBar.setTitle("Wave " + m_currentWaveNum + " / " + m_game.getWaveCount());
|
|
||||||
m_gameBar.setColor(BarColor.PURPLE);
|
|
||||||
m_waveBar.setVisible(true);
|
|
||||||
m_waveBar.setColor(BarColor.YELLOW);
|
|
||||||
m_waveBar.setTitle("Warmup");
|
|
||||||
m_waveBar.setProgress((double)m_warmupCountdown / (double)10);
|
|
||||||
break;
|
|
||||||
case Playing:
|
|
||||||
m_gameBar.setProgress((double)m_currentWaveNum / (double)m_game.getWaveCount());
|
|
||||||
m_gameBar.setTitle("Wave " + m_currentWaveNum + " / " + m_game.getWaveCount());
|
|
||||||
m_gameBar.setColor(BarColor.PURPLE);
|
|
||||||
if (m_createdMobs > 0) {
|
|
||||||
m_waveBar.setVisible(true);
|
|
||||||
m_waveBar.setColor(BarColor.GREEN);
|
|
||||||
m_waveBar.setTitle("Mobs remaining: " + (m_createdMobs - m_killedMobs));
|
|
||||||
m_waveBar.setProgress((double)m_killedMobs / (double)m_createdMobs);
|
|
||||||
} else {
|
|
||||||
m_waveBar.setVisible(false);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case GameOver:
|
|
||||||
m_gameBar.setColor(BarColor.RED);
|
|
||||||
m_gameBar.setProgress(1.0);
|
|
||||||
m_gameBar.setTitle("Game Over!");
|
|
||||||
m_waveBar.setVisible(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void spawnNextBatch() {
|
|
||||||
broadcastMessage("Spawning batch " + m_currentBatch);
|
|
||||||
Spawner spawner = new GameSpawner(m_arena.spawnpoints());
|
|
||||||
m_currentWave.spawnBatch(spawner, m_currentBatch);
|
|
||||||
updateMobBars();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void handlePlayerDeath(Player player) {
|
|
||||||
if (m_livingPlayers.contains(player)) {
|
|
||||||
m_log.info("Player has died in game" + player);
|
|
||||||
m_livingPlayers.remove(player);
|
|
||||||
m_arena.getWorld().strikeLightningEffect(player.getLocation());
|
|
||||||
player.setGameMode(GameMode.SPECTATOR);
|
|
||||||
if (m_livingPlayers.size() == 0) {
|
|
||||||
broadcastMessage("Everyone is dead :(");
|
|
||||||
requestTransition(State.GameOver);
|
|
||||||
} else {
|
|
||||||
m_log.info("Remaining players " + m_livingPlayers.size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void handleEntityDeath(Entity entity) {
|
|
||||||
if (m_livingMobs.contains(entity)) {
|
|
||||||
broadcastMessage("Killed game entity " + entity);
|
|
||||||
m_livingMobs.remove(entity);
|
|
||||||
m_killedMobs += 1;
|
|
||||||
updateMobBars();
|
|
||||||
if (m_livingMobs.size() <= 3) {
|
|
||||||
m_log.info("Starting next batch!");
|
|
||||||
if (m_currentBatch >= m_currentWave.batchCount()) {
|
|
||||||
if (m_currentWaveNum >= m_game.getWaveCount()) {
|
|
||||||
requestTransition(State.GameOver);
|
|
||||||
} else if (m_livingMobs.size() == 0) {
|
|
||||||
requestTransition(State.Warmup);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
m_currentBatch += 1;
|
|
||||||
spawnNextBatch();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
m_log.fine("Living mobs remaining: " + m_livingMobs.size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean syncPlayer(Player player) {
|
|
||||||
m_log.fine("Synchronizing player " + player);
|
|
||||||
World playerWorld = player.getLocation().getWorld();
|
|
||||||
World gameWorld = m_arena.getWorld();
|
|
||||||
m_gameBar.addPlayer(player);
|
|
||||||
m_waveBar.addPlayer(player);
|
|
||||||
if (m_livingPlayers.contains(player)) {
|
|
||||||
m_log.fine("Player is alive, turning into adventure mode " + player);
|
|
||||||
if (player.getGameMode() != Bukkit.getDefaultGameMode()) {
|
|
||||||
player.setGameMode(Bukkit.getDefaultGameMode());
|
|
||||||
player.teleport(gameWorld.getSpawnLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN);
|
|
||||||
}
|
|
||||||
player.setHealth(player.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue());
|
|
||||||
player.setFoodLevel(10);
|
|
||||||
} else {
|
|
||||||
m_log.fine("Player is dead, turning into spectator " + player);
|
|
||||||
player.setGameMode(GameMode.SPECTATOR);
|
|
||||||
}
|
|
||||||
if (playerWorld != gameWorld) {
|
|
||||||
m_log.info("Teleporting player " + player);
|
|
||||||
return player.teleport(gameWorld.getSpawnLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean attemptTransition(State state) {
|
|
||||||
if (m_state == state) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
switch(state) {
|
|
||||||
case Idle:
|
|
||||||
return enterIdle();
|
|
||||||
case Warmup:
|
|
||||||
return enterWarmup();
|
|
||||||
case Playing:
|
|
||||||
return enterPlaying();
|
|
||||||
case GameOver:
|
|
||||||
return enterGameOver();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean validateTransition(State from, State to) {
|
|
||||||
switch(from) {
|
|
||||||
case Idle:
|
|
||||||
return to == State.Warmup;
|
|
||||||
case Warmup:
|
|
||||||
return to == State.Playing || to == State.Idle || to == State.GameOver;
|
|
||||||
case Playing:
|
|
||||||
return to == State.Warmup || to == State.GameOver || to == State.Idle;
|
|
||||||
case GameOver:
|
|
||||||
return to == State.Idle;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean requestTransition(State state) {
|
|
||||||
if (!validateTransition(m_state, state)) {
|
|
||||||
m_log.warning("Attemped illegal transition: " + m_state + " -> " + state);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (attemptTransition(state)) {
|
|
||||||
updateMobBars();
|
|
||||||
m_log.info("Game transition: " + m_state + " -> " + state);
|
|
||||||
m_state = state;
|
|
||||||
for(Player p : m_players) {
|
|
||||||
syncPlayer(p);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
m_log.severe("Failed to complete transition: " + m_state + " -> " + state);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean addPlayer(Player p) {
|
|
||||||
if (m_state == State.Idle || m_state == State.Warmup) {
|
|
||||||
m_log.info("Adding player " + p);
|
|
||||||
m_players.add(p);
|
|
||||||
broadcastMessage(p.getName() + " has joined the game");
|
|
||||||
syncPlayer(p);
|
|
||||||
if (m_state == State.Idle) {
|
|
||||||
requestTransition(State.Warmup);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removePlayer(Player p) {
|
|
||||||
m_log.info("Removing player " + p);
|
|
||||||
m_gameBar.removePlayer(p);
|
|
||||||
m_waveBar.removePlayer(p);
|
|
||||||
m_players.remove(p);
|
|
||||||
m_livingPlayers.remove(p);
|
|
||||||
p.setGameMode(Bukkit.getDefaultGameMode());
|
|
||||||
if (m_players.size() == 0) {
|
|
||||||
requestTransition(State.Idle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void broadcastTitle(String title) {
|
|
||||||
broadcastTitle(title, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
void broadcastTitle(String title, String subtitle) {
|
|
||||||
for(Player p : m_players) {
|
|
||||||
p.sendTitle(title, subtitle, 10, 70, 20);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void broadcastMessage(String string) {
|
|
||||||
World world = m_arena.getWorld();
|
|
||||||
for(Player p : world.getPlayers()) {
|
|
||||||
p.sendMessage(string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void registerSpawnedMob(Entity entity) {
|
|
||||||
m_log.fine("Registered new mob " + entity);
|
|
||||||
m_livingMobs.add(entity);
|
|
||||||
m_createdMobs += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class GameSpawner implements Spawner {
|
|
||||||
Spawnpoint[] m_spawnpoints;
|
|
||||||
int m_spawnIdx = 0;
|
|
||||||
|
|
||||||
public GameSpawner(Spawnpoint[] spawnpoints) {
|
|
||||||
m_spawnpoints = spawnpoints;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Entity spawnMob(EntityType type) {
|
|
||||||
m_log.fine("Spawning " + type + " at " + m_spawnpoints[m_spawnIdx]);
|
|
||||||
Entity newMob = m_arena.getWorld().spawnEntity(m_spawnpoints[m_spawnIdx].getLocation(), type);
|
|
||||||
LivingEntity livingMob = (LivingEntity)newMob;
|
|
||||||
livingMob.setRemoveWhenFarAway(false);
|
|
||||||
registerSpawnedMob(newMob);
|
|
||||||
m_spawnIdx += 1;
|
|
||||||
m_spawnIdx %= m_spawnpoints.length;
|
|
||||||
return newMob;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -20,6 +20,11 @@ import gg.malloc.defense.model.Game;
|
|||||||
import gg.malloc.defense.games.LinearGame;
|
import gg.malloc.defense.games.LinearGame;
|
||||||
import gg.malloc.defense.games.ScaledWaves;
|
import gg.malloc.defense.games.ScaledWaves;
|
||||||
|
|
||||||
|
import gg.malloc.defense.engine.GameRunner;
|
||||||
|
|
||||||
|
import gg.malloc.defense.commands.AddPlayerCommand;
|
||||||
|
import gg.malloc.defense.commands.SetStageCommand;
|
||||||
|
|
||||||
public class Plugin extends JavaPlugin {
|
public class Plugin extends JavaPlugin {
|
||||||
ArrayList<Arena> m_arenas = new ArrayList<>();
|
ArrayList<Arena> m_arenas = new ArrayList<>();
|
||||||
ArrayList<Game> m_games = new ArrayList<>();
|
ArrayList<Game> m_games = new ArrayList<>();
|
||||||
@ -58,7 +63,7 @@ public class Plugin extends JavaPlugin {
|
|||||||
getLogger().setLevel(Level.FINEST);
|
getLogger().setLevel(Level.FINEST);
|
||||||
setupDemoGame();
|
setupDemoGame();
|
||||||
getCommand("setstage").setExecutor(new SetStageCommand(this));
|
getCommand("setstage").setExecutor(new SetStageCommand(this));
|
||||||
getCommand("initgame").setExecutor(new InitGameCommand(this));
|
getCommand("addplayer").setExecutor(new AddPlayerCommand(this));
|
||||||
getCommand("debuginfo").setExecutor(new DebuginfoCommand(this));
|
getCommand("debuginfo").setExecutor(new DebuginfoCommand(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
package gg.malloc.defense;
|
package gg.malloc.defense.commands;
|
||||||
|
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandExecutor;
|
import org.bukkit.command.CommandExecutor;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
public class InitGameCommand implements CommandExecutor {
|
import gg.malloc.defense.engine.GameRunner;
|
||||||
|
|
||||||
|
import gg.malloc.defense.Plugin;
|
||||||
|
|
||||||
|
public class AddPlayerCommand implements CommandExecutor {
|
||||||
Plugin m_plugin;
|
Plugin m_plugin;
|
||||||
|
|
||||||
public InitGameCommand(Plugin plugin) {
|
public AddPlayerCommand(Plugin plugin) {
|
||||||
m_plugin = plugin;
|
m_plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16,7 +20,7 @@ public class InitGameCommand implements CommandExecutor {
|
|||||||
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 worldName = args[0];
|
||||||
GameRunner runner = m_plugin.getRunnerForWorld(m_plugin.getServer().getWorld(worldName));
|
GameRunner runner = m_plugin.getRunnerForWorld(m_plugin.getServer().getWorld(worldName));
|
||||||
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;
|
||||||
}
|
}
|
@ -1,10 +1,14 @@
|
|||||||
package gg.malloc.defense;
|
package gg.malloc.defense.commands;
|
||||||
|
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandExecutor;
|
import org.bukkit.command.CommandExecutor;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
|
|
||||||
|
import gg.malloc.defense.engine.GameRunner;
|
||||||
|
|
||||||
|
import gg.malloc.defense.Plugin;
|
||||||
|
|
||||||
public class SetStageCommand implements CommandExecutor {
|
public class SetStageCommand implements CommandExecutor {
|
||||||
Plugin m_plugin;
|
Plugin m_plugin;
|
||||||
|
|
||||||
@ -19,13 +23,13 @@ public class SetStageCommand implements CommandExecutor {
|
|||||||
String stateName = args[0].toLowerCase();
|
String stateName = args[0].toLowerCase();
|
||||||
boolean ret = false;
|
boolean ret = false;
|
||||||
if (stateName.equals("idle")) {
|
if (stateName.equals("idle")) {
|
||||||
ret = runner.requestTransition(GameRunner.State.Idle);
|
ret = runner.requestTransition(GameRunner.Stage.Idle);
|
||||||
} else if (stateName.equals("warmup")) {
|
} else if (stateName.equals("warmup")) {
|
||||||
ret = runner.requestTransition(GameRunner.State.Warmup);
|
ret = runner.requestTransition(GameRunner.Stage.Warmup);
|
||||||
} else if (stateName.equals("playing")) {
|
} else if (stateName.equals("playing")) {
|
||||||
ret = runner.requestTransition(GameRunner.State.Playing);
|
ret = runner.requestTransition(GameRunner.Stage.Playing);
|
||||||
} else if (stateName.equals("gameover")) {
|
} else if (stateName.equals("gameover")) {
|
||||||
ret = runner.requestTransition(GameRunner.State.GameOver);
|
ret = runner.requestTransition(GameRunner.Stage.GameOver);
|
||||||
} else {
|
} else {
|
||||||
sender.sendMessage("Unknown state " + stateName);
|
sender.sendMessage("Unknown state " + stateName);
|
||||||
return false;
|
return false;
|
350
src/main/java/gg/malloc/defense/engine/GameRunner.java
Normal file
350
src/main/java/gg/malloc/defense/engine/GameRunner.java
Normal file
@ -0,0 +1,350 @@
|
|||||||
|
package gg.malloc.defense.engine;
|
||||||
|
|
||||||
|
import gg.malloc.defense.model.Game;
|
||||||
|
import gg.malloc.defense.model.Arena;
|
||||||
|
import gg.malloc.defense.model.Spawner;
|
||||||
|
import gg.malloc.defense.model.Wave;
|
||||||
|
|
||||||
|
import gg.malloc.defense.Plugin;
|
||||||
|
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.boss.BarColor;
|
||||||
|
import org.bukkit.boss.BarStyle;
|
||||||
|
import org.bukkit.boss.BossBar;
|
||||||
|
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||||
|
import org.bukkit.event.entity.EntityDamageEvent;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.bukkit.entity.EntityType;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.scheduler.BukkitTask;
|
||||||
|
|
||||||
|
public class GameRunner {
|
||||||
|
Arena m_arena;
|
||||||
|
Game m_game;
|
||||||
|
Stage m_stage;
|
||||||
|
Plugin m_plugin;
|
||||||
|
|
||||||
|
BossBar m_gameBar = Bukkit.createBossBar("Malloc Defense", BarColor.PURPLE, BarStyle.SOLID);
|
||||||
|
BossBar m_waveBar = Bukkit.createBossBar("Malloc Defense", BarColor.PURPLE, BarStyle.SOLID);
|
||||||
|
BukkitTask m_countdownTask;
|
||||||
|
|
||||||
|
MobManager m_mobs;
|
||||||
|
WaveManager m_waves;
|
||||||
|
PlayerManager m_players;
|
||||||
|
|
||||||
|
Logger m_log;
|
||||||
|
|
||||||
|
public enum Stage {
|
||||||
|
Idle,
|
||||||
|
Warmup,
|
||||||
|
Playing,
|
||||||
|
GameOver
|
||||||
|
}
|
||||||
|
|
||||||
|
class WaveManager {
|
||||||
|
int m_currentWaveNum = 0;
|
||||||
|
int m_currentBatch = 0;
|
||||||
|
Wave m_currentWave = null;
|
||||||
|
Game m_game;
|
||||||
|
|
||||||
|
WaveManager(Game game) {
|
||||||
|
m_game = game;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
m_currentWaveNum = 0;
|
||||||
|
m_currentBatch = 0;
|
||||||
|
m_currentWave = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Wave currentWave() {
|
||||||
|
return m_currentWave;
|
||||||
|
}
|
||||||
|
|
||||||
|
int currentWaveNum() {
|
||||||
|
return m_currentWaveNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
int currentBatchNum() {
|
||||||
|
return m_currentBatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
double progress() {
|
||||||
|
return (double)m_currentWaveNum / (double)m_game.getWaveCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isLastWave() {
|
||||||
|
return m_currentWaveNum >= m_game.getWaveCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isLastBatch() {
|
||||||
|
return m_currentBatch >= m_currentWave.batchCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
void nextBatch() {
|
||||||
|
m_currentBatch += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void next() {
|
||||||
|
m_currentWaveNum += 1;
|
||||||
|
m_currentBatch = 0;
|
||||||
|
m_currentWave = m_game.getWave(m_currentWaveNum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public GameRunner(Plugin plugin, Game game, Arena arena) {
|
||||||
|
m_plugin = plugin;
|
||||||
|
m_game = game;
|
||||||
|
m_arena = arena;
|
||||||
|
m_stage = Stage.Idle;
|
||||||
|
m_gameBar.setVisible(true);
|
||||||
|
m_waveBar.setVisible(false);
|
||||||
|
m_mobs = new MobManager(m_game);
|
||||||
|
m_waves = new WaveManager(m_game);
|
||||||
|
m_players = new PlayerManager();
|
||||||
|
m_log = m_plugin.getLogger();
|
||||||
|
}
|
||||||
|
|
||||||
|
int m_warmupCountdown = 0;
|
||||||
|
|
||||||
|
public void handleEntityDamage(EntityDamageEvent evt) {
|
||||||
|
m_mobs.handleEntityDamage(evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void countdownTick() {
|
||||||
|
if (m_warmupCountdown == 0) {
|
||||||
|
requestTransition(Stage.Playing);
|
||||||
|
} else {
|
||||||
|
updateMobBars();
|
||||||
|
broadcastMessage("Starting game in " + m_warmupCountdown);
|
||||||
|
m_warmupCountdown--;
|
||||||
|
m_countdownTask = m_plugin.getServer().getScheduler().runTaskLater(m_plugin, () -> {
|
||||||
|
countdownTick();
|
||||||
|
}, 20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean enterIdle() {
|
||||||
|
m_waves.reset();
|
||||||
|
m_mobs.clear();
|
||||||
|
m_players.requestTransitionForAll(PlayerManager.State.Idle);
|
||||||
|
if (m_countdownTask != null) {
|
||||||
|
m_countdownTask.cancel();
|
||||||
|
m_countdownTask = null;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean enterWarmup() {
|
||||||
|
m_waves.next();
|
||||||
|
m_warmupCountdown = 10;
|
||||||
|
for(Player p : m_players.getPlayers()) {
|
||||||
|
if (m_players.requestTransition(p, PlayerManager.State.Playing)) {
|
||||||
|
p.teleport(m_arena.getWorld().getSpawnLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
broadcastTitle("Warmup", "Prepare yourself for wave " + m_waves.currentWaveNum());
|
||||||
|
m_mobs.clear();
|
||||||
|
countdownTick();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean enterPlaying() {
|
||||||
|
m_log.info("Starting wave " + m_waves.currentWaveNum());
|
||||||
|
spawnNextBatch();
|
||||||
|
broadcastTitle("Wave " + m_waves.currentWaveNum());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean enterGameOver() {
|
||||||
|
broadcastTitle("Game Over!");
|
||||||
|
if (m_countdownTask != null) {
|
||||||
|
m_countdownTask.cancel();
|
||||||
|
m_countdownTask = null;
|
||||||
|
}
|
||||||
|
m_mobs.clear();
|
||||||
|
for(Player p : m_players.getPlayers()) {
|
||||||
|
removePlayer(p);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateMobBars() {
|
||||||
|
m_gameBar.setVisible(true);
|
||||||
|
switch(m_stage) {
|
||||||
|
case Idle:
|
||||||
|
m_gameBar.setProgress(1.0);
|
||||||
|
m_gameBar.setTitle("Waiting for playres...");
|
||||||
|
m_gameBar.setColor(BarColor.PURPLE);
|
||||||
|
m_waveBar.setVisible(false);
|
||||||
|
break;
|
||||||
|
case Warmup:
|
||||||
|
m_gameBar.setProgress(m_waves.progress());
|
||||||
|
m_gameBar.setTitle("Wave " + m_waves.currentWaveNum() + " / " + m_game.getWaveCount());
|
||||||
|
m_gameBar.setColor(BarColor.PURPLE);
|
||||||
|
m_waveBar.setVisible(true);
|
||||||
|
m_waveBar.setColor(BarColor.YELLOW);
|
||||||
|
m_waveBar.setTitle("Warmup");
|
||||||
|
m_waveBar.setProgress((double)m_warmupCountdown / (double)10);
|
||||||
|
break;
|
||||||
|
case Playing:
|
||||||
|
m_gameBar.setProgress(m_waves.progress());
|
||||||
|
m_gameBar.setTitle("Wave " + m_waves.currentWaveNum() + " / " + m_game.getWaveCount());
|
||||||
|
m_gameBar.setColor(BarColor.PURPLE);
|
||||||
|
if (m_mobs.createdMobs() > 0) {
|
||||||
|
m_waveBar.setVisible(true);
|
||||||
|
m_waveBar.setColor(BarColor.GREEN);
|
||||||
|
m_waveBar.setTitle("Mobs remaining: " + m_mobs.remainingMobs());
|
||||||
|
m_waveBar.setProgress(m_mobs.progress());
|
||||||
|
} else {
|
||||||
|
m_waveBar.setVisible(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GameOver:
|
||||||
|
m_gameBar.setColor(BarColor.RED);
|
||||||
|
m_gameBar.setProgress(1.0);
|
||||||
|
m_gameBar.setTitle("Game Over!");
|
||||||
|
m_waveBar.setVisible(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void spawnNextBatch() {
|
||||||
|
broadcastMessage("Spawning batch " + m_waves.currentBatchNum());
|
||||||
|
Spawner spawner = new GameSpawner(m_arena, m_mobs);
|
||||||
|
m_waves.currentWave().spawnBatch(spawner, m_waves.currentBatchNum());
|
||||||
|
updateMobBars();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handlePlayerDeath(Player player) {
|
||||||
|
if (m_players.requestTransition(player, PlayerManager.State.Dead)) {
|
||||||
|
m_arena.getWorld().strikeLightningEffect(player.getLocation());
|
||||||
|
if (!m_players.isAnyoneAlive()) {
|
||||||
|
broadcastMessage("Everyone is dead :(");
|
||||||
|
requestTransition(Stage.GameOver);
|
||||||
|
} else {
|
||||||
|
m_log.info("Remaining players " + m_players.remainingPlayers());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleEntityDeath(Entity entity) {
|
||||||
|
if (m_mobs.killMob(entity)) {
|
||||||
|
broadcastMessage("Killed game entity " + entity);
|
||||||
|
updateMobBars();
|
||||||
|
if (m_mobs.remainingMobs() <= 3) {
|
||||||
|
m_log.info("Starting next batch!");
|
||||||
|
if (m_waves.isLastBatch()) {
|
||||||
|
if (m_waves.isLastWave()) {
|
||||||
|
requestTransition(Stage.GameOver);
|
||||||
|
} else if (m_mobs.empty()) {
|
||||||
|
requestTransition(Stage.Warmup);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m_waves.nextBatch();
|
||||||
|
spawnNextBatch();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m_log.fine("Living mobs remaining: " + m_mobs.remainingMobs());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean attemptTransition(Stage stage) {
|
||||||
|
if (m_stage == stage) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_log.info("Game state: " + stage);
|
||||||
|
switch(stage) {
|
||||||
|
case Idle:
|
||||||
|
return enterIdle();
|
||||||
|
case Warmup:
|
||||||
|
return enterWarmup();
|
||||||
|
case Playing:
|
||||||
|
return enterPlaying();
|
||||||
|
case GameOver:
|
||||||
|
return enterGameOver();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean validateTransition(Stage from, Stage to) {
|
||||||
|
switch(from) {
|
||||||
|
case Idle:
|
||||||
|
return to == Stage.Warmup;
|
||||||
|
case Warmup:
|
||||||
|
return to == Stage.Playing || to == Stage.Idle || to == Stage.GameOver;
|
||||||
|
case Playing:
|
||||||
|
return to == Stage.Warmup || to == Stage.GameOver || to == Stage.Idle;
|
||||||
|
case GameOver:
|
||||||
|
return to == Stage.Idle;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean requestTransition(Stage stage) {
|
||||||
|
if (!validateTransition(m_stage, stage)) {
|
||||||
|
m_log.warning("Attemped illegal transition: " + m_stage + " -> " + stage);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (attemptTransition(stage)) {
|
||||||
|
m_log.info("Game transition: " + m_stage + " -> " + stage);
|
||||||
|
m_stage = stage;
|
||||||
|
updateMobBars();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
m_log.severe("Failed to complete transition: " + m_stage + " -> " + stage);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPlayer(Player p) {
|
||||||
|
m_players.addPlayer(p);
|
||||||
|
m_gameBar.addPlayer(p);
|
||||||
|
m_waveBar.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);
|
||||||
|
}
|
||||||
|
broadcastMessage(p.getName() + " has joined the game");
|
||||||
|
if (m_stage == Stage.Idle) {
|
||||||
|
requestTransition(Stage.Warmup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removePlayer(Player p) {
|
||||||
|
m_gameBar.removePlayer(p);
|
||||||
|
m_waveBar.removePlayer(p);
|
||||||
|
m_players.removePlayer(p);
|
||||||
|
if (m_players.isEmpty()) {
|
||||||
|
requestTransition(Stage.Idle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void broadcastTitle(String title) {
|
||||||
|
broadcastTitle(title, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
void broadcastTitle(String title, String subtitle) {
|
||||||
|
for(Player p : m_players.getPlayers()) {
|
||||||
|
p.sendTitle(title, subtitle, 10, 70, 20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void broadcastMessage(String string) {
|
||||||
|
World world = m_arena.getWorld();
|
||||||
|
for(Player p : world.getPlayers()) {
|
||||||
|
p.sendMessage(string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void registerSpawnedMob(Entity entity) {
|
||||||
|
m_mobs.addEntity(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
33
src/main/java/gg/malloc/defense/engine/GameSpawner.java
Normal file
33
src/main/java/gg/malloc/defense/engine/GameSpawner.java
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package gg.malloc.defense.engine;
|
||||||
|
|
||||||
|
import gg.malloc.defense.model.Spawner;
|
||||||
|
import gg.malloc.defense.model.Spawnpoint;
|
||||||
|
import gg.malloc.defense.model.Arena;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.bukkit.entity.EntityType;
|
||||||
|
|
||||||
|
public class GameSpawner implements Spawner {
|
||||||
|
Arena m_arena;
|
||||||
|
MobManager m_manager;
|
||||||
|
int m_spawnIdx = 0;
|
||||||
|
|
||||||
|
public GameSpawner(Arena arena, MobManager manager) {
|
||||||
|
m_arena = arena;
|
||||||
|
m_manager = manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Entity spawnMob(EntityType type) {
|
||||||
|
Spawnpoint[] 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);
|
||||||
|
LivingEntity livingMob = (LivingEntity)newMob;
|
||||||
|
livingMob.setRemoveWhenFarAway(false);
|
||||||
|
m_manager.addEntity(newMob);
|
||||||
|
m_spawnIdx += 1;
|
||||||
|
return newMob;
|
||||||
|
}
|
||||||
|
}
|
7
src/main/java/gg/malloc/defense/engine/GameStage.java
Normal file
7
src/main/java/gg/malloc/defense/engine/GameStage.java
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package gg.malloc.defense.engine;
|
||||||
|
|
||||||
|
public interface GameStage {
|
||||||
|
String name();
|
||||||
|
default void onEnter() {}
|
||||||
|
default void onExit() {}
|
||||||
|
}
|
72
src/main/java/gg/malloc/defense/engine/MobManager.java
Normal file
72
src/main/java/gg/malloc/defense/engine/MobManager.java
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package gg.malloc.defense.engine;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.event.entity.EntityDamageEvent;
|
||||||
|
|
||||||
|
import gg.malloc.defense.model.Game;
|
||||||
|
|
||||||
|
public class MobManager {
|
||||||
|
HashSet<Entity> m_livingMobs = new HashSet<>();
|
||||||
|
int m_createdMobs = 0;
|
||||||
|
int m_killedMobs = 0;
|
||||||
|
|
||||||
|
Game m_game;
|
||||||
|
|
||||||
|
MobManager(Game game) {
|
||||||
|
m_game = game;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleEntityDamage(EntityDamageEvent evt) {
|
||||||
|
Entity entity = evt.getEntity();
|
||||||
|
//m_log.info("Damage " + entity);
|
||||||
|
//m_log.info("Living Mobs " + m_livingMobs);
|
||||||
|
if (m_livingMobs.contains(entity)) {
|
||||||
|
m_game.onMobDamaged(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean killMob(Entity entity) {
|
||||||
|
if (m_livingMobs.contains(entity)) {
|
||||||
|
m_killedMobs += 1;
|
||||||
|
return m_livingMobs.remove(entity);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
for(Entity e : m_livingMobs) {
|
||||||
|
e.remove();
|
||||||
|
}
|
||||||
|
m_livingMobs.clear();
|
||||||
|
m_createdMobs = 0;
|
||||||
|
m_killedMobs = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int createdMobs() {
|
||||||
|
return m_createdMobs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int killedMobs() {
|
||||||
|
return m_killedMobs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int remainingMobs() {
|
||||||
|
return m_createdMobs - m_killedMobs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double progress() {
|
||||||
|
return (double)m_killedMobs / (double)m_createdMobs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addEntity(Entity entity) {
|
||||||
|
//m_log.fine("Registered new mob " + entity);
|
||||||
|
m_livingMobs.add(entity);
|
||||||
|
m_createdMobs += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean empty() {
|
||||||
|
return m_livingMobs.size() == 0;
|
||||||
|
}
|
||||||
|
}
|
113
src/main/java/gg/malloc/defense/engine/PlayerManager.java
Normal file
113
src/main/java/gg/malloc/defense/engine/PlayerManager.java
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
package gg.malloc.defense.engine;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.GameMode;
|
||||||
|
import org.bukkit.attribute.Attribute;
|
||||||
|
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
public class PlayerManager {
|
||||||
|
HashMap<Player, State> m_playerStates = new HashMap<>();
|
||||||
|
|
||||||
|
public enum State {
|
||||||
|
Idle,
|
||||||
|
Playing,
|
||||||
|
Dead
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean requestTransitionForAll(State toState) {
|
||||||
|
boolean allSuccess = true;
|
||||||
|
for (Player p : getPlayers()) {
|
||||||
|
allSuccess = allSuccess && requestTransition(p, toState);
|
||||||
|
}
|
||||||
|
return allSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean requestTransition(Player player, State toState) {
|
||||||
|
State currentState = m_playerStates.get(player);
|
||||||
|
if (currentState == toState) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
boolean ret = false;
|
||||||
|
switch(toState) {
|
||||||
|
case Idle:
|
||||||
|
ret = enterIdle(player);break;
|
||||||
|
case Playing:
|
||||||
|
ret = enterPlaying(player);break;
|
||||||
|
case Dead:
|
||||||
|
ret = enterDead(player);break;
|
||||||
|
}
|
||||||
|
if (ret) {
|
||||||
|
m_playerStates.put(player, toState);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean enterIdle(Player player) {
|
||||||
|
// Reset player to non-game state, return control back to Minecraft
|
||||||
|
player.setGameMode(Bukkit.getDefaultGameMode());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Respawn player
|
||||||
|
public boolean enterPlaying(Player player) {
|
||||||
|
//m_log.fine("Respawning player " + player);
|
||||||
|
player.setGameMode(Bukkit.getDefaultGameMode());
|
||||||
|
player.setHealth(player.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue());
|
||||||
|
player.setFoodLevel(10);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean enterDead(Player player) {
|
||||||
|
//m_log.info("Player has died in game" + player);
|
||||||
|
player.setGameMode(GameMode.SPECTATOR);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPlayer(Player player) {
|
||||||
|
//m_log.info("Adding player " + player);
|
||||||
|
m_playerStates.put(player, State.Idle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean removePlayer(Player player) {
|
||||||
|
//m_log.info("Removing player " + player);
|
||||||
|
requestTransition(player, State.Idle);
|
||||||
|
m_playerStates.remove(player);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return m_playerStates.size() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAlive(Player player) {
|
||||||
|
return m_playerStates.get(player) == State.Playing;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAnyoneAlive() {
|
||||||
|
for(Player p : m_playerStates.keySet()) {
|
||||||
|
if (m_playerStates.get(p) == State.Playing) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int remainingPlayers() {
|
||||||
|
int aliveCount = 0;
|
||||||
|
for(State s : m_playerStates.values()) {
|
||||||
|
if (s == State.Playing) {
|
||||||
|
aliveCount += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return aliveCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
Collection<Player> getPlayers() {
|
||||||
|
return m_playerStates.keySet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,7 +6,7 @@ depend: []
|
|||||||
commands:
|
commands:
|
||||||
setstage:
|
setstage:
|
||||||
description: Sets a game stage
|
description: Sets a game stage
|
||||||
initgame:
|
addplayer:
|
||||||
description: Adds a player to a game
|
description: Adds a player to a game
|
||||||
debuginfo:
|
debuginfo:
|
||||||
description: Unknowable powers
|
description: Unknowable powers
|
||||||
|
Loading…
Reference in New Issue
Block a user