use of soc.util.SOCGameBoardReset in project JSettlers2 by jdmonin.
the class SOCGameListAtServer method resetBoard.
/**
* Reset the board of this game, create a new game of same name,
* same players, new layout. The new "reset" board takes the place
* of the old game in the game list.
*<P>
* Robots are not copied and
* must re-join the game. (They're removed from the list of game members.)
* If the game had robots, they must leave the old game before any players can
* join the new game; the new game's {@link SOCGame#boardResetOngoingInfo} field
* is set to the object returned by this method, and its gameState will be
* {@link SOCGame#READY_RESET_WAIT_ROBOT_DISMISS} instead of {@link SOCGame#NEW}.
*<P>
* <b>Locking:</b>
* Takes game monitor.
* Copies old game.
* Adds reset-copy to gamelist.
* Destroys old game.
* Releases game monitor.
*
* @param gaName Name of game - If not found, do nothing. No monitor is taken.
* @return New game if gaName was found and copied; null if no game called gaName,
* or if a problem occurs during reset
* @see soc.game.SOCGame#resetAsCopy()
*/
public SOCGameBoardReset resetBoard(String gaName) {
SOCGame oldGame = gameData.get(gaName);
if (oldGame == null)
return null;
takeMonitorForGame(gaName);
// Create reset-copy of game;
// also removes robots from game obj and its member list,
// and sets boardResetOngoingInfo field/gamestate if there are robots.
SOCGameBoardReset reset = null;
try {
reset = new SOCGameBoardReset(oldGame, getMembers(gaName));
SOCGame rgame = reset.newGame;
// As in createGame, set expiration timer to 90 min. from now
rgame.setExpiration(System.currentTimeMillis() + (60 * 1000 * GAME_TIME_EXPIRE_MINUTES));
// Adjust game-list
gameData.remove(gaName);
gameData.put(gaName, rgame);
// Done.
oldGame.destroyGame();
} catch (Throwable e) {
D.ebugPrintStackTrace(e, "ERROR -> gamelist.resetBoard");
} finally {
releaseMonitorForGame(gaName);
}
// null if error during reset
return reset;
}
use of soc.util.SOCGameBoardReset in project JSettlers2 by jdmonin.
the class SOCServer method resetBoardAndNotify.
/**
* Reset the board, to a copy with same players but new layout.
* Here's the general outline; step 1 and 2 are done immediately here,
* steps 3 through n are done (after robots are dismissed) within
* {@link #resetBoardAndNotify_finish(SOCGameBoardReset, SOCGame)}.
*<OL>
* <LI value=1> Reset the board, remember player positions.
* If there are robots, set game state to
* {@link SOCGame#READY_RESET_WAIT_ROBOT_DISMISS}.
* <LI value=2a> Send ResetBoardAuth to each client (like sending JoinGameAuth at new game)
* Humans will reset their copy of the game.
* Robots will leave the game, and soon be requested to re-join.
* (This simplifies the robot client.)
* If the game was in initial placement or was already over at reset time, different robots will
* be randomly chosen to join the reset game.
* <LI value=2b> If there were robots, wait for them all to leave the old game.
* Otherwise, (race condition) they may leave the new game as it is forming.
* Set {@link SOCGame#boardResetOngoingInfo}.
* Wait for them to leave the old game before continuing.
* The call will be made from {@link SOCServerMessageHandler#handleLEAVEGAME_maybeGameReset_oldRobot(String)}.
* <LI value=2c> If no robots, immediately call {@link #resetBoardAndNotify_finish(SOCGameBoardReset, SOCGame)}.
* <P>
* <b>This ends this method.</b> Step 3 and the rest are in
* {@link #resetBoardAndNotify_finish(SOCGameBoardReset, SOCGame)}.
* <LI value=3> Send messages as if each human player has clicked "join" (except JoinGameAuth)
* <LI value=4> Send as if each human player has clicked "sit here"
* <LI value=5a> If no robots, send to game as if someone else has
* clicked "start game", and set up state to begin game play.
* <LI value=5b> If there are robots, set up wait-request
* queue (robotJoinRequests). Game will wait for robots to send
* JOINGAME and SITDOWN, as they do when joining a newly created game.
* Once all robots have re-joined, the game will begin.
*</OL>
* @since 1.1.00
*/
void resetBoardAndNotify(final String gaName, final int requestingPlayer) {
/**
* 1. Reset the board, remember player positions.
* Takes the monitorForGame and (when reset is ready) releases it.
* If robots, resetBoard will also set gamestate
* and boardResetOngoingInfo field.
*/
SOCGameBoardReset reBoard = gameList.resetBoard(gaName);
if (reBoard == null) {
final SOCGame ga = gameList.getGameData(gaName);
if (ga != null)
messageToGameKeyed(ga, true, "resetboard.doit.interror", gaName);
// <---- Early return: reset failed ----
return;
}
SOCGame reGame = reBoard.newGame;
// Announce who asked for this reset
{
String plName = reGame.getPlayer(requestingPlayer).getName();
final String key = (plName != null) ? // ">>> Game {0} board reset by {1}"
"resetboard.doit.announce.requester" : // ">>> Game {0} board reset by a player who left"
"resetboard.doit.announce.playerwholeft";
messageToGameKeyed(reGame, true, key, gaName, plName);
}
// If game is still initial-placing or was over, we'll shuffle the robots
final boolean resetWithShuffledBots = (reBoard.oldGameState < SOCGame.ROLL_OR_CARD) || (reBoard.oldGameState == SOCGame.OVER);
/**
* Player connection data:
* - Humans are copied from old to new game
* - Robots aren't copied to new game, must re-join
*/
Connection[] huConns = reBoard.humanConns;
Connection[] roConns = reBoard.robotConns;
/**
* Notify old game's players. (Humans and robots)
*
* 2a. Send ResetBoardAuth to each (like sending JoinGameAuth at new game).
* Humans will reset their copy of the game.
* Robots will leave the game, and soon will be requested to re-join.
*/
for (int pn = 0; pn < reGame.maxPlayers; ++pn) {
SOCResetBoardAuth resetMsg = new SOCResetBoardAuth(gaName, pn, requestingPlayer);
if (huConns[pn] != null)
messageToPlayer(huConns[pn], resetMsg);
else if (roConns[pn] != null) {
if (!resetWithShuffledBots)
// same robot will rejoin
messageToPlayer(roConns[pn], resetMsg);
else
// could be different bot
messageToPlayer(roConns[pn], new SOCRobotDismiss(gaName));
}
}
if (!reBoard.hadRobots)
resetBoardAndNotify_finish(reBoard, reGame);
// else
// gameState is READY_RESET_WAIT_ROBOT_DISMISS,
// and once the last robot leaves this game,
// SOCServerMessageHandler.handleLEAVEGAME will take care of the reset,
// by calling resetBoardAndNotify_finish.
}
use of soc.util.SOCGameBoardReset in project JSettlers2 by jdmonin.
the class SOCServerMessageHandler method handleLEAVEGAME_maybeGameReset_oldRobot.
/**
* Handle an unattached robot saying it is leaving the game,
* from {@link #handleLEAVEGAME(Connection, SOCLeaveGame)}.
* Ignore the robot (since it's not a member of the game) unless
* gamestate is {@link SOCGame#READY_RESET_WAIT_ROBOT_DISMISS}.
*
* @since 1.1.07
*/
private void handleLEAVEGAME_maybeGameReset_oldRobot(final String gaName) {
SOCGame cg = gameList.getGameData(gaName);
if (cg.getGameState() != SOCGame.READY_RESET_WAIT_ROBOT_DISMISS)
return;
boolean gameResetRobotsAllDismissed = false;
// TODO locks
SOCGameBoardReset gr = cg.boardResetOngoingInfo;
if (gr != null) {
--gr.oldRobotCount;
if (0 == gr.oldRobotCount)
gameResetRobotsAllDismissed = true;
}
if (gameResetRobotsAllDismissed)
// TODO locks?
srv.resetBoardAndNotify_finish(gr, cg);
}
Aggregations