Search in sources :

Example 1 with SOCGameBoardReset

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;
}
Also used : SOCGameBoardReset(soc.util.SOCGameBoardReset) SOCGame(soc.game.SOCGame)

Example 2 with SOCGameBoardReset

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.
}
Also used : SOCGameBoardReset(soc.util.SOCGameBoardReset) StringConnection(soc.server.genericServer.StringConnection) Connection(soc.server.genericServer.Connection)

Example 3 with SOCGameBoardReset

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);
}
Also used : SOCGameBoardReset(soc.util.SOCGameBoardReset) SOCGame(soc.game.SOCGame)

Aggregations

SOCGameBoardReset (soc.util.SOCGameBoardReset)3 SOCGame (soc.game.SOCGame)2 Connection (soc.server.genericServer.Connection)1 StringConnection (soc.server.genericServer.StringConnection)1