Prevent multiple players with the same ID from joining the same round

This commit is contained in:
Andrew Guibert 2018-05-23 19:59:09 -05:00
parent 88bf2f5afa
commit dba5e22c42
3 changed files with 14 additions and 19 deletions

View File

@ -147,7 +147,7 @@ export class GameComponent implements OnInit, OnDestroy {
// Event handlers // Event handlers
handleGameError(errorMessage: any) { handleGameError(errorMessage: any) {
console.log('Received error message from server: ' + errorMessage); console.log('Received error message from server: ' + errorMessage);
alert('Your connection to the game server has been closed. You will be redirected to the login page.'); alert(errorMessage + ' Your connection to the game server has been closed. You will be redirected to the login page.');
this.ngZone.run(() => { this.ngZone.run(() => {
this.router.navigate(['/login']); this.router.navigate(['/login']);
}); });

View File

@ -126,14 +126,20 @@ public class GameRound implements Runnable {
c.player.setDirection(msg.direction); c.player.setDirection(msg.direction);
} }
public void addPlayer(Session s, String playerId, String playerName, Boolean hasGameBoard) { public boolean addPlayer(Session s, String playerId, String playerName, Boolean hasGameBoard) {
// Front end should be preventing a player joining a full game but // Front end should be preventing a player joining a full game but
// defensive programming // defensive programming
if (!isOpen()) { if (!isOpen()) {
log("Cannot add player " + playerId + " to game because game has already started."); log("Cannot add player " + playerId + " to game because game has already started.");
return; return false;
} }
for (Client c : clients.values())
if (c.player.id.equals(playerId)) {
log("Cannot add player " + playerId + " to game because a player with that ID is already in the game.");
return false;
}
if (getPlayers().size() + 1 >= Player.MAX_PLAYERS) { if (getPlayers().size() + 1 >= Player.MAX_PLAYERS) {
gameState = State.FULL; gameState = State.FULL;
lobbyCountdown.gameFull(); lobbyCountdown.gameFull();
@ -153,6 +159,7 @@ public class GameRound implements Runnable {
broadcastGameBoard(); broadcastGameBoard();
beginHeartbeat(); beginHeartbeat();
beginLobbyCountdown(s, isPhone); beginLobbyCountdown(s, isPhone);
return true;
} }
public void addAI() { public void addAI() {

View File

@ -41,12 +41,10 @@ public class GameRoundWebsocket {
@OnOpen @OnOpen
public void onOpen(@PathParam("roundId") String roundId, Session session) { public void onOpen(@PathParam("roundId") String roundId, Session session) {
log(roundId, "Opened a session"); log(roundId, "Opened a session");
checkIdleTimeout(session, roundId);
} }
@OnClose @OnClose
public void onClose(@PathParam("roundId") String roundId, Session session) { public void onClose(@PathParam("roundId") String roundId, Session session) {
checkIdleTimeout(session, roundId);
log(roundId, "Closed a session"); log(roundId, "Closed a session");
try { try {
GameRound round = gameSvc.getRound(roundId); GameRound round = gameSvc.getRound(roundId);
@ -60,14 +58,13 @@ public class GameRoundWebsocket {
@OnMessage @OnMessage
public void onMessage(@PathParam("roundId") final String roundId, String message, Session session) { public void onMessage(@PathParam("roundId") final String roundId, String message, Session session) {
checkIdleTimeout(session, roundId);
try { try {
final InboundMessage msg = jsonb.fromJson(message, InboundMessage.class); final InboundMessage msg = jsonb.fromJson(message, InboundMessage.class);
final GameRound round = gameSvc.getRound(roundId); final GameRound round = gameSvc.getRound(roundId);
if (round == null || round.gameState == State.FINISHED) { if (round == null || round.gameState == State.FINISHED) {
log(roundId, "[onMessage] Received message for round that did not exist or has completed. Closing this websocket connection."); log(roundId, "[onMessage] Received message for round that did not exist or has completed. Closing this websocket connection.");
if (round == null) if (round == null)
sendToClient(session, new OutboundMessage.ErrorEvent("Round " + roundId + " did not exist")); sendToClient(session, new OutboundMessage.ErrorEvent("Round " + roundId + " did not exist."));
// don't immediately boot out players that may keep sending messages a few seconds after the game is done // don't immediately boot out players that may keep sending messages a few seconds after the game is done
else if (!round.isPlayer(session)) else if (!round.isPlayer(session))
sendToClient(session, new OutboundMessage.ErrorEvent("Round " + roundId + " has already completed.")); sendToClient(session, new OutboundMessage.ErrorEvent("Round " + roundId + " has already completed."));
@ -82,7 +79,9 @@ public class GameRoundWebsocket {
round.updatePlayerDirection(session, msg); round.updatePlayerDirection(session, msg);
} else if (msg.playerJoinedId != null) { } else if (msg.playerJoinedId != null) {
org.libertybikes.restclient.Player playerResponse = playerSvc.getPlayerById(msg.playerJoinedId); org.libertybikes.restclient.Player playerResponse = playerSvc.getPlayerById(msg.playerJoinedId);
round.addPlayer(session, msg.playerJoinedId, playerResponse.name, msg.hasGameBoard); if (!round.addPlayer(session, msg.playerJoinedId, playerResponse.name, msg.hasGameBoard))
sendToClient(session, new OutboundMessage.ErrorEvent("Unable to add player " + playerResponse.name
+ " to game. This is probably because someone else with the same name is already in the game."));
} else if (Boolean.TRUE == msg.isSpectator) { } else if (Boolean.TRUE == msg.isSpectator) {
round.addSpectator(session); round.addSpectator(session);
} else { } else {
@ -116,15 +115,4 @@ public class GameRoundWebsocket {
System.out.println("[websocket-" + roundId + "] " + msg); System.out.println("[websocket-" + roundId + "] " + msg);
} }
// TODO: remove this method once we find out if session timeout is being altered on cloud env
private static void checkIdleTimeout(Session session, String roundId) {
// See if we can catch a reason why sessions timeout in cloud env
if (session.getMaxIdleTimeout() > 0) {
log(roundId, "WARNING: Session idle timeout is: " + session.getMaxIdleTimeout());
}
if (session.getContainer().getDefaultMaxSessionIdleTimeout() > 0) {
log(roundId, "WARNING: Default session idle timeout is: " + session.getContainer().getDefaultMaxSessionIdleTimeout());
}
}
} }