backend game autostart

This commit is contained in:
orcook 2018-05-10 12:10:18 -05:00
parent ef6670d742
commit a42d1fd7c2
2 changed files with 81 additions and 3 deletions

View File

@ -50,6 +50,8 @@ public class GameRound implements Runnable {
public static final int GAME_TICK_SPEED = 50; // ms public static final int GAME_TICK_SPEED = 50; // ms
private static final int DELAY_BETWEEN_ROUNDS = 5; //ticks private static final int DELAY_BETWEEN_ROUNDS = 5; //ticks
private static final int STARTING_COUNTDOWN = 3; // seconds private static final int STARTING_COUNTDOWN = 3; // seconds
private static final int MAX_TIME_BETWEEN_ROUNDS = 30; //seconds
private static final int FULL_GAME_TIME_BETWEEN_ROUNDS = 5; //seconds
private static final Random r = new Random(); private static final Random r = new Random();
private static final AtomicInteger runningGames = new AtomicInteger(); private static final AtomicInteger runningGames = new AtomicInteger();
@ -65,6 +67,8 @@ public class GameRound implements Runnable {
private final Map<Session, Client> clients = new HashMap<>(); private final Map<Session, Client> clients = new HashMap<>();
private final Deque<Player> playerRanks = new ArrayDeque<>(); private final Deque<Player> playerRanks = new ArrayDeque<>();
private final Set<LifecycleCallback> lifecycleCallbacks = new HashSet<>(); private final Set<LifecycleCallback> lifecycleCallbacks = new HashSet<>();
private AutoStartCountdown autoStart;
private boolean autoStarting = false;
private int ticksFromGameEnd = 0; private int ticksFromGameEnd = 0;
@ -83,13 +87,28 @@ public class GameRound implements Runnable {
public GameRound(String id) { public GameRound(String id) {
this.id = id; this.id = id;
nextRoundId = getRandomId(); nextRoundId = getRandomId();
} }
public GameBoard getBoard() { public GameBoard getBoard() {
return board; return board;
} }
public void autoStart(Session s, boolean isPhone) {
if (!autoStarting) {
autoStarting = true;
try {
ManagedScheduledExecutorService exec = InitialContext.doLookup("java:comp/DefaultManagedScheduledExecutorService");
autoStart = new AutoStartCountdown(this);
exec.submit(autoStart);
} catch (NamingException e) {
log("Unable to obtain executor service reference");
e.printStackTrace();
}
}
if (!isPhone)
sendTextToClient(s, jsonb.toJson(new OutboundMessage.GameStartCountdown(autoStart.roundStartCountdown)));
}
public void updatePlayerDirection(Session playerSession, InboundMessage msg) { public void updatePlayerDirection(Session playerSession, InboundMessage msg) {
Client c = clients.get(playerSession); Client c = clients.get(playerSession);
if (c.isPlayer()) if (c.isPlayer())
@ -106,12 +125,14 @@ public class GameRound implements Runnable {
if (getPlayers().size() + 1 >= Player.MAX_PLAYERS) { if (getPlayers().size() + 1 >= Player.MAX_PLAYERS) {
gameState = State.FULL; gameState = State.FULL;
autoStart.gameFull();
} }
Player p = board.addPlayer(playerId, playerName); Player p = board.addPlayer(playerId, playerName);
boolean isPhone = false;
if (p != null) { if (p != null) {
Client c = new Client(s, p); Client c = new Client(s, p);
c.isPhone = hasGameBoard ? false : true; isPhone = c.isPhone = hasGameBoard ? false : true;
clients.put(s, c); clients.put(s, c);
log("Player " + playerId + " has joined."); log("Player " + playerId + " has joined.");
} else { } else {
@ -120,6 +141,7 @@ public class GameRound implements Runnable {
broadcastPlayerList(); broadcastPlayerList();
broadcastGameBoard(); broadcastGameBoard();
beginHeartbeat(); beginHeartbeat();
autoStart(s, isPhone);
} }
public void addAI() { public void addAI() {
@ -142,6 +164,7 @@ public class GameRound implements Runnable {
sendTextToClient(s, jsonb.toJson(new OutboundMessage.PlayerList(getPlayers()))); sendTextToClient(s, jsonb.toJson(new OutboundMessage.PlayerList(getPlayers())));
sendTextToClient(s, jsonb.toJson(board)); sendTextToClient(s, jsonb.toJson(board));
beginHeartbeat(); beginHeartbeat();
autoStart(s, false);
} }
public void addCallback(LifecycleCallback callback) { public void addCallback(LifecycleCallback callback) {
@ -292,6 +315,10 @@ public class GameRound implements Runnable {
.collect(Collectors.toSet()); .collect(Collectors.toSet());
} }
private void broadcastTimeUntilGameStarts(int time) {
sendTextToClients(getNonMobileSessions(), jsonb.toJson(new OutboundMessage.GameStartCountdown(time)));
}
private void broadcastGameBoard() { private void broadcastGameBoard() {
sendTextToClients(getNonMobileSessions(), jsonb.toJson(board)); sendTextToClients(getNonMobileSessions(), jsonb.toJson(board));
} }
@ -392,6 +419,7 @@ public class GameRound implements Runnable {
for (Client c : clients.values()) for (Client c : clients.values())
if (c.autoRequeue) if (c.autoRequeue)
GameRoundWebsocket.requeueClient(gameSvc, this, c.session); GameRoundWebsocket.requeueClient(gameSvc, this, c.session);
} }
private void log(String msg) { private void log(String msg) {
@ -399,8 +427,49 @@ public class GameRound implements Runnable {
} }
public interface LifecycleCallback { public interface LifecycleCallback {
public void gameEnding(); public void gameEnding();
}
private class AutoStartCountdown implements Runnable {
public int roundStartCountdown = MAX_TIME_BETWEEN_ROUNDS;
private final GameRound round;
public AutoStartCountdown(GameRound round) {
this.round = round;
}
public void gameFull() {
roundStartCountdown = roundStartCountdown > 5 ? FULL_GAME_TIME_BETWEEN_ROUNDS : roundStartCountdown;
round.broadcastTimeUntilGameStarts(roundStartCountdown);
}
@Override
public void run() {
while (round.isOpen() || round.gameState == State.FULL) {
delay(1000);
roundStartCountdown--;
//round.broadcastTimeUntilGameStarts(--roundStartCountdown);
if (roundStartCountdown < 1) {
if (round.clients.size() == 0) {
log("No clients remaining. Cancelling autoStart.");
// Ensure that game state is closed off so that no other players can quick join while a round is marked for deletion
gameState = State.FINISHED;
} else {
round.startGame();
}
}
}
}
private void delay(long ms) {
if (ms < 0)
return;
try {
Thread.sleep(ms);
} catch (InterruptedException ie) {
}
}
} }

View File

@ -39,6 +39,15 @@ public class OutboundMessage {
} }
} }
public static class GameStartCountdown {
@JsonbProperty("gamestartcountdown")
public final int seconds;
public GameStartCountdown(int startingSeconds) {
this.seconds = startingSeconds;
}
}
public static class Heartbeat { public static class Heartbeat {
@JsonbProperty("keepAlive") @JsonbProperty("keepAlive")
public final boolean keepAlive = true; public final boolean keepAlive = true;