use of soc.message.SOCLeaveGame in project JSettlers2 by jdmonin.
the class SOCGameHandler method leaveGame.
// javadoc inherited from GameHandler. Return true if game is empty and should be ended.
public boolean leaveGame(SOCGame ga, Connection c) {
final String gm = ga.getName();
// Retain name, since will become null within game obj.
final String plName = c.getData();
boolean gameHasHumanPlayer = false;
boolean gameHasObserver = false;
@SuppressWarnings("unused") boolean // TODO checks/messages; added in v1.1.01, TODO not used yet
gameVotingActiveDuringStart = false;
final int gameState = ga.getGameState();
boolean isPlayer = false;
// removing this player number
int playerNumber;
for (playerNumber = 0; playerNumber < ga.maxPlayers; playerNumber++) {
SOCPlayer player = ga.getPlayer(playerNumber);
if ((player != null) && (player.getName() != null) && (player.getName().equals(plName))) {
isPlayer = true;
/**
* About to remove this player from the game. Before doing so:
* If a board-reset vote is in progress, they cannot vote
* once they have left. So to keep the game moving,
* fabricate their response: vote No.
*/
if (ga.getResetVoteActive()) {
if (gameState <= SOCGame.STARTS_WAITING_FOR_PICK_GOLD_RESOURCE)
gameVotingActiveDuringStart = true;
if (ga.getResetPlayerVote(playerNumber) == SOCGame.VOTE_NONE) {
srv.gameList.releaseMonitorForGame(gm);
ga.takeMonitor();
srv.resetBoardVoteNotifyOne(ga, playerNumber, plName, false);
ga.releaseMonitor();
srv.gameList.takeMonitorForGame(gm);
}
}
/**
* Remove the player.
*/
// player obj name becomes null
ga.removePlayer(plName);
// broadcastGameStats(cg);
break;
}
}
SOCLeaveGame leaveMessage = new SOCLeaveGame(plName, "-", gm);
srv.messageToGameWithMon(gm, leaveMessage);
srv.recordGameEvent(gm, leaveMessage);
if (D.ebugOn)
D.ebugPrintln("*** " + plName + " left the game " + gm + " at " + DateFormat.getTimeInstance(DateFormat.SHORT).format(new Date()));
// "{0} left the game"
srv.messageToGameKeyed(ga, false, "member.left.game", plName);
/**
* check if there is at least one person playing the game
*/
for (int pn = 0; pn < ga.maxPlayers; pn++) {
SOCPlayer player = ga.getPlayer(pn);
if ((player != null) && (player.getName() != null) && (!ga.isSeatVacant(pn)) && (!player.isRobot())) {
gameHasHumanPlayer = true;
break;
}
}
/**
* if no human players, check if there is at least one person watching the game (observing).
* Even with observers, end it unless ga.isBotsOnly or PROP_JSETTLERS_BOTS_BOTGAMES_TOTAL != 0.
*/
if ((!gameHasHumanPlayer) && !srv.gameList.isGameEmpty(gm)) {
Enumeration<Connection> membersEnum = srv.gameList.getMembers(gm).elements();
while (membersEnum.hasMoreElements()) {
Connection member = membersEnum.nextElement();
// D.ebugPrintln("*** "+member.data+" is a member of "+gm);
boolean nameMatch = false;
for (int pn = 0; pn < ga.maxPlayers; pn++) {
SOCPlayer player = ga.getPlayer(pn);
if ((player != null) && (player.getName() != null) && (player.getName().equals(member.getData()))) {
nameMatch = true;
break;
}
}
if (!nameMatch) {
gameHasObserver = true;
break;
}
}
if (gameHasObserver && !ga.isBotsOnly) {
if (0 == srv.getConfigIntProperty(SOCServer.PROP_JSETTLERS_BOTS_BOTGAMES_TOTAL, 0))
gameHasObserver = false;
}
}
/**
* if the leaving member was playing the game, and
* the game isn't over, then decide:
* - Do we need to force-end the current turn?
* - Do we need to cancel their initial settlement placement?
* - Should we replace the leaving player with a robot?
*/
if (isPlayer && (gameHasHumanPlayer || gameHasObserver) && ((ga.getPlayer(playerNumber).getPublicVP() > 0) || (gameState == SOCGame.START1A) || (gameState == SOCGame.START1B)) && (gameState < SOCGame.OVER) && !(gameState < SOCGame.START1A)) {
boolean foundNoRobots;
if (ga.getPlayer(playerNumber).isRobot()) {
/**
* don't replace bot with bot; force end-turn instead.
*/
foundNoRobots = true;
} else {
/**
* get a robot to replace this human player;
* just in case, check game-version vs robots-version,
* like at new-game (readyGameAskRobotsJoin).
*/
foundNoRobots = !findRobotAskJoinGame(ga, Integer.valueOf(playerNumber), true);
}
/**
* What to do if no robot was found to fill their spot?
* Must keep the game going, might need to force-end current turn.
*/
if (foundNoRobots) {
final boolean stillActive = endGameTurnOrForce(ga, playerNumber, plName, c, true);
if (!stillActive) {
// force game destruction below
gameHasHumanPlayer = false;
gameHasObserver = false;
}
}
} else {
// observer leaving: If game is bot-only, don't end the game despite no human players/observers
if (ga.isBotsOnly && (ga.getGameState() < SOCGame.OVER))
gameHasObserver = true;
}
return !(gameHasHumanPlayer || gameHasObserver);
}
Aggregations