Skip to content

Commit

Permalink
Fix #14 and improve internal logistics of Game
Browse files Browse the repository at this point in the history
Signed-off-by: Darcy Chen <darcy.chen@outlook.com>
  • Loading branch information
Darcy Chen committed Mar 8, 2018
1 parent ba4015d commit a22e208
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public CommandResult execute(CommandSource src, CommandContext args) throws Comm
try {
gamer.quit();
} catch (NullPointerException e) {
player.sendMessage(Text.of("You're not in any game."));
player.sendMessage(Text.of("Unexpected error occurs when quitting you from the game."));
return CommandResult.empty();
}
player.sendMessage(Text.of("You left the game."));
Expand Down
70 changes: 36 additions & 34 deletions src/main/java/net/huskycraft/blockyarena/games/Game.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.spongepowered.api.data.key.Keys;
import org.spongepowered.api.effect.sound.SoundTypes;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.entity.living.player.gamemode.GameMode;
import org.spongepowered.api.entity.living.player.gamemode.GameModes;
import org.spongepowered.api.scheduler.Task;
import org.spongepowered.api.text.Text;
Expand All @@ -34,13 +35,13 @@ public class Game {
* The GameState is set to RECRUITING by default.
* @param arena an enabled arena
*/
public Game(BlockyArena plugin, TeamMode teamMode, Arena arena) {
public Game(BlockyArena plugin, TeamMode teamMode, Arena arena, int numTeams) {
this.plugin = plugin;
this.teamMode = teamMode;
this.arena = arena;
arena.setState(ArenaState.OCCUPIED);
gamers = new ArrayList<>();
gameState = GameState.RECRUITING;
arena.setState(ArenaState.OCCUPIED);
}

/**
Expand All @@ -50,16 +51,14 @@ public Game(BlockyArena plugin, TeamMode teamMode, Arena arena) {
* @param gamer the Gamer to be added to this Game
*/
public void add(Gamer gamer) {
// reject if the game reaches maximum capacity or is currently not recruiting
if (gamers.size() == teamMode.getCapacity() * 2 || gameState != GameState.RECRUITING) {
gamer.getPlayer().sendMessage(Text.of("Unable to join the game at this time."));
return;
}
gamers.add(gamer);
gamer.getPlayer().offer(Keys.GAME_MODE, GameModes.SURVIVAL);
gamer.getPlayer().offer(Keys.HEALTH, gamer.getPlayer().get(Keys.MAX_HEALTH).get());
gamer.getPlayer().offer(Keys.FOOD_LEVEL, 20);
gamer.getPlayer().sendMessage(Text.of("Sending you to " + arena.getID()));
gamer.spawnAt(arena.getLobbySpawn());
broadcast(Text.of(gamer.getName() + " joined the game."));
if (gameState == GameState.RECRUITING) {
checkStartingCondition();
}
inspect();
}

/**
Expand All @@ -72,11 +71,10 @@ public void remove(Gamer gamer) {
if (gameState == GameState.RECRUITING || gameState == GameState.STARTING) {
gamers.remove(gamer);
broadcast(Text.of(gamer.getName() + " left the game."));
checkStartingCondition();
inspect();
} else if (gameState == GameState.STARTED) {
eliminate(gamer, Text.of(gamer.getPlayer().getName() + " disconnected."));
}
gamer.getPlayer().offer(Keys.GAME_MODE, GameModes.SURVIVAL);
}

/**
Expand All @@ -87,21 +85,23 @@ public void remove(Gamer gamer) {
*/
public void eliminate(Gamer gamer, Text cause) {
broadcast(cause);
gamer.spawnAt(arena.getSpectatorSpawn());
gamer.getPlayer().offer(Keys.HEALTH, gamer.getPlayer().get(Keys.MAX_HEALTH).get());
gamer.getPlayer().offer(Keys.GAME_MODE, GameModes.SPECTATOR);
gamer.setStatus(GamerStatus.SPECTATING);
gamer.spectate(this);
checkStoppingCondition();
}

/**
* Checks to see if this Game should start based on the current condition.
*
* Starts the starting timer if the precondition is met, otherwise cancels the timer.
* Inspects the current condition of the Game. The starting countdown of this game is triggered if the number of
* players matches the starting condition of the associated game mode, otherwise the countdown will be canceled.
* This Game is terminated if there is no player active in the session.
*/
private void checkStartingCondition() {
boolean canSolo = teamMode == TeamMode.SOLO && gamers.size() == 2;
boolean canDoubles = teamMode == TeamMode.DOUBLES && gamers.size() == 4;
private void inspect() {
// terminate if there is no active gamer
if (gamers.isEmpty()) {
terminate();
return;
}
boolean canSolo = teamMode.getCapacity() * 2 == gamers.size();
boolean canDoubles = teamMode.getCapacity() * 2 == gamers.size();
if (canSolo || canDoubles) {
teamA = new Team(arena.getTeamSpawnA(), this);
teamB = new Team(arena.getTeamSpawnB(), this);
Expand All @@ -115,7 +115,7 @@ private void checkStartingCondition() {
} else if (timer != null) {
timer.cancel();
gameState = GameState.RECRUITING;
broadcast(Text.of("Waiting for more players to join."));
broadcast(Text.of("Waiting for more players to join ..."));
}
}

Expand Down Expand Up @@ -157,17 +157,7 @@ public void onGameStopping() {
gamer.quit();
}
}
onGameStopped();
}

/**
* Executed as soon as the Game has stopped.
*/
public void onGameStopped() {
gameState = GameState.STOPPED;
arena.setState(ArenaState.AVAILABLE);
plugin.getGameManager().remove(this);
// TODO: logging
terminate();
}

private void startingCountdown(int second) {
Expand Down Expand Up @@ -214,4 +204,16 @@ public void broadcast(Text msg) {
}
}
}

/**
* Terminates this Game permanently.
*/
public void terminate() {
arena.setState(ArenaState.AVAILABLE);
plugin.getGameManager().remove(this);
}

public Arena getArena() {
return arena;
}
}
12 changes: 11 additions & 1 deletion src/main/java/net/huskycraft/blockyarena/games/TeamMode.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,15 @@
* A TeamMode represents the mode of a Team based on the number of gamers on a Team.
*/
public enum TeamMode {
SOLO, DOUBLES, TEAMS
SOLO(1), DOUBLES(2);

private int capacity; // the capacity of each team in this mode

TeamMode(int capacity) {
this.capacity = capacity;
}

public int getCapacity() {
return capacity;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import net.huskycraft.blockyarena.games.GameState;
import net.huskycraft.blockyarena.utils.Gamer;
import net.huskycraft.blockyarena.utils.GamerStatus;
import org.spongepowered.api.data.key.Keys;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.entity.DamageEntityEvent;
Expand All @@ -30,6 +31,7 @@ public void onDamageEntity(DamageEntityEvent event) {
if (event.willCauseDeath()) {
event.setCancelled(true);
gamer.getGame().eliminate(gamer, Text.of(gamer.getName() + " was beaten to death."));
gamer.getPlayer().offer(Keys.HEALTH, gamer.getPlayer().get(Keys.MAX_HEALTH).get());
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public Game getGame(TeamMode teamMode) {
Arena arena = plugin.getArenaManager().getArena();
// if there is no available Arena, no Game can be instantiated and null is returned
if (arena == null) return null;
Game game = new Game(plugin, teamMode, arena);
Game game = new Game(plugin, teamMode, arena, 2); // TODO: customize number of teams
games.add(game);
return game;
}
Expand Down
26 changes: 23 additions & 3 deletions src/main/java/net/huskycraft/blockyarena/utils/Gamer.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

import net.huskycraft.blockyarena.arenas.Spawn;
import net.huskycraft.blockyarena.games.Game;
import org.spongepowered.api.data.key.Keys;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.entity.living.player.gamemode.GameModes;
import org.spongepowered.api.text.Text;
import org.spongepowered.api.world.Location;

import java.util.UUID;
Expand Down Expand Up @@ -132,12 +135,18 @@ public String getName() {
* @param game the Game in which the Gamer is about to join
*/
public void join(Game game) {
this.game = game;
saveLocation();
saveInventory();
game.add(this);
this.game = game;
setStatus(GamerStatus.PLAYING);
player.getInventory().clear(); // TODO: allow bringing personal kit
player.sendMessage(Text.of("Sending you to " + game.getArena().getID() + " ..."));
spawnAt(game.getArena().getLobbySpawn());
// TODO: refer to game logistics for the following parameters
player.offer(Keys.GAME_MODE, GameModes.SURVIVAL);
player.offer(Keys.HEALTH, player.get(Keys.MAX_HEALTH).get());
player.offer(Keys.FOOD_LEVEL, 20);
setStatus(GamerStatus.PLAYING);
game.add(this);
}

/**
Expand All @@ -146,11 +155,22 @@ public void join(Game game) {
public void quit() {
game.remove(this);
this.game = null;
player.offer(Keys.GAME_MODE, GameModes.SURVIVAL);
setStatus(GamerStatus.AVAILABLE);
retrieveInventory();
setLocation(getSavedLocation());
}

/**
* Spectates the given game. Sets the gamemode to be SPECTATOR and teleports to the spectator spawn of the Game.
* @param game the game the gamer about to spectate
*/
public void spectate(Game game) {
player.offer(Keys.GAME_MODE, GameModes.SPECTATOR);
spawnAt(game.getArena().getSpectatorSpawn());
setStatus(GamerStatus.SPECTATING);
}

/**
* Sets the given Player as the new Player instance associated with this Gamer
* @param player the Player instance to be associated with this Gamer
Expand Down

0 comments on commit a22e208

Please sign in to comment.