Search in sources :

Example 6 with Connection

use of soc.server.genericServer.Connection in project JSettlers2 by jdmonin.

the class SOCGameHandler method findRobotAskJoinGame.

/**
 * When a human player has left an active game, or a game is starting and a
 * bot from that game's {@link SOCServer#robotJoinRequests} has disconnected,
 * look for a robot player which can take a seat and continue the game.
 *<P>
 * If found the bot will be added to {@link SOCServer#robotJoinRequests} and
 * sent a {@link SOCBotJoinGameRequest}. Otherwise the game will be sent a
 * {@link SOCGameServerText} explaining failure to find any robot; human players
 * might need to leave the game and start a new one.
 * @param ga   Game to look in
 * @param seatNumberObj  Seat number to fill, as an {@link Integer} object.
 *     If {@code ! gameIsActive}, this comes from {@link SOCServer#robotJoinRequests}
 *     via {@link SOCServer#leaveConnection(Connection)}.
 * @param gameIsActive  True if for active game, not a game still starting
 * @return true if an available bot was found
 * @since 2.0.00
 */
public boolean findRobotAskJoinGame(final SOCGame ga, Object seatNumberObj, final boolean gameIsActive) {
    if (gameIsActive)
        // "Fetching a robot player..."
        srv.messageToGameKeyed(ga, false, "member.bot.join.fetching");
    if (srv.robots.isEmpty()) {
        srv.messageToGameKeyed(ga, false, "member.bot.join.no.bots.server");
        // <--- Early return: No bot available ---
        return false;
    } else if (ga.getClientVersionMinRequired() > Version.versionNumber()) {
        srv.messageToGameKeyed(ga, false, "member.bot.join.interror.version", ga.getClientVersionMinRequired());
        // <--- Early return: No bot available ---
        return false;
    }
    // the bot selected to join
    Connection robotConn = null;
    // false if can select a bot that isn't already playing in or requested in this game
    boolean nameMatch = true;
    final String gaName = ga.getName();
    Hashtable<Connection, Object> requestedBots = srv.robotJoinRequests.get(gaName);
    if (// should not happen; check just in case
    !(seatNumberObj instanceof Integer)) {
        seatNumberObj = null;
    // nameMatch remains true; will announce can't find a bot
    } else {
        /**
         * request a robot that isn't already playing this game or
         * is not already requested to play in this game
         */
        final HashSet<String> gameBots = new HashSet<String>();
        for (int i = 0; i < ga.maxPlayers; i++) {
            SOCPlayer pl = ga.getPlayer(i);
            if (pl != null) {
                String pname = pl.getName();
                if (pname != null)
                    gameBots.add(pname);
            }
        }
        // Shuffle to distribute load
        final int[] robotIndexes = srv.robotShuffleForJoin();
        for (int idx = 0; idx < srv.robots.size(); idx++) {
            robotConn = srv.robots.get(robotIndexes[idx]);
            nameMatch = gameBots.contains(robotConn.getData());
            if ((!nameMatch) && (requestedBots != null))
                nameMatch = requestedBots.containsKey(robotConn);
            if (!nameMatch)
                break;
        }
    }
    if (!nameMatch) {
        /**
         * make the request
         */
        D.ebugPrintln("@@@ JOIN GAME REQUEST for " + robotConn.getData());
        final int seatNumber = ((Integer) seatNumberObj).intValue();
        if (ga.getSeatLock(seatNumber) != SOCGame.SeatLockState.UNLOCKED) {
            // make sure bot can sit
            ga.setSeatLock(seatNumber, SOCGame.SeatLockState.UNLOCKED);
            srv.messageToGameWithMon(gaName, new SOCSetSeatLock(gaName, seatNumber, SOCGame.SeatLockState.UNLOCKED));
        }
        /**
         * record the request
         */
        if (requestedBots == null) {
            requestedBots = new Hashtable<Connection, Object>();
            requestedBots.put(robotConn, seatNumberObj);
            srv.robotJoinRequests.put(gaName, requestedBots);
        } else {
            requestedBots.put(robotConn, seatNumberObj);
        }
        robotConn.put(SOCBotJoinGameRequest.toCmd(gaName, seatNumber, ga.getGameOptions()));
    } else {
        // "*** Can't find a robot! ***"
        srv.messageToGameKeyed(ga, false, "member.bot.join.cantfind");
        // <--- Early return: No bot available ---
        return false;
    }
    return true;
}
Also used : SOCSetSeatLock(soc.message.SOCSetSeatLock) Connection(soc.server.genericServer.Connection) HashSet(java.util.HashSet)

Example 7 with Connection

use of soc.server.genericServer.Connection in project JSettlers2 by jdmonin.

the class SOCGameHandler method sendGamePendingMessages.

/**
 * Sends the contents of this game's {@link SOCGame#pendingMessagesOut}, then empties that list.
 * To avoid unnecessary work here, check if the list is empty before calling this method.
 *<P>
 * <B>I18N:</B> Checks {@code pendingMessagesOut} for {@link SOCKeyedMessage}s and handles them accordingly.
 * Currently this is the only method that checks for those, because other places send text messages
 * immediately instead of queueing them and localizing/sending later.
 * Also checks for {@link UnlocalizedString}s, to be localized and sent with
 * {@link SOCServer#messageToGameKeyed(SOCGame, boolean, String, Object...)}
 * or {@link SOCServer#messageToGameKeyedSpecial(SOCGame, boolean, String, Object...)}.
 *<P>
 * <B>Locks:</B> If {@code takeMon} is true, takes and releases
 * {@link SOCGameList#takeMonitorForGame(String) gameList.takeMonitorForGame(gameName)}.
 * Otherwise call {@link SOCGameList#takeMonitorForGame(String) gameList.takeMonitorForGame(gameName)}
 * before calling this method.
 * @param ga  game with pending messages
 * @param takeMon Should this method take and release game's monitor via
 *     {@link SOCGameList#takeMonitorForGame(String) gameList.takeMonitorForGame(gameName)}?
 *     True unless caller already holds that monitor.
 * @see #updatePlayerSVPPendingMessage(SOCGame, SOCPlayer, int, String)
 * @since 2.0.00
 */
void sendGamePendingMessages(SOCGame ga, final boolean takeMon) {
    final String gaName = ga.getName();
    if (takeMon)
        srv.gameList.takeMonitorForGame(gaName);
    for (final Object msg : ga.pendingMessagesOut) {
        if (msg instanceof SOCKeyedMessage)
            srv.messageToGameKeyedType(ga, (SOCKeyedMessage) msg, false);
        else if (msg instanceof SOCMessage)
            srv.messageToGameWithMon(gaName, (SOCMessage) msg);
        else if (msg instanceof UnlocalizedString) {
            final UnlocalizedString us = (UnlocalizedString) msg;
            if (us.isSpecial)
                srv.messageToGameKeyedSpecial(ga, false, us.key, us.params);
            else
                srv.messageToGameKeyed(ga, false, us.key, us.params);
        }
    // else: ignore
    }
    ga.pendingMessagesOut.clear();
    for (SOCPlayer p : ga.getPlayers()) {
        final List<Object> pq = p.pendingMessagesOut;
        final int L = pq.size();
        if (L >= 0) {
            final Connection c = srv.getConnection(p.getName());
            if (c != null)
                for (int i = 0; i < L; ++i) c.put(((SOCMessage) pq.get(i)).toCmd());
            pq.clear();
        }
    }
    if (takeMon)
        srv.gameList.releaseMonitorForGame(gaName);
}
Also used : SOCMessage(soc.message.SOCMessage) SOCKeyedMessage(soc.message.SOCKeyedMessage) Connection(soc.server.genericServer.Connection)

Example 8 with Connection

use of soc.server.genericServer.Connection in project JSettlers2 by jdmonin.

the class SOCGameHandler method reportRobbery.

/**
 * The current player is stealing from another player.
 * Send messages saying what was stolen.
 *
 * @param ga  the game
 * @param pe  the perpetrator
 * @param vi  the victim
 * @param rsrc  type of resource stolen, as in {@link SOCResourceConstants#SHEEP},
 *              or {@link SOCResourceConstants#CLOTH_STOLEN_LOCAL} for cloth
 *              (scenario option {@link SOCGameOption#K_SC_CLVI _SC_CLVI}).
 */
void reportRobbery(SOCGame ga, SOCPlayer pe, SOCPlayer vi, final int rsrc) {
    if (ga == null)
        return;
    final String gaName = ga.getName();
    final String peName = pe.getName();
    final String viName = vi.getName();
    final int pePN = pe.getPlayerNumber();
    final int viPN = vi.getPlayerNumber();
    if (rsrc == SOCResourceConstants.CLOTH_STOLEN_LOCAL) {
        // Send players' cloth counts and text.
        // Client's game will recalculate players' VP based on
        // the cloth counts, so we don't need to also send VP.
        srv.messageToGame(gaName, new SOCPlayerElement(gaName, viPN, SOCPlayerElement.SET, SOCPlayerElement.SCENARIO_CLOTH_COUNT, vi.getCloth(), true));
        srv.messageToGame(gaName, new SOCPlayerElement(gaName, pePN, SOCPlayerElement.SET, SOCPlayerElement.SCENARIO_CLOTH_COUNT, pe.getCloth()));
        // "{0} stole a cloth from {1}."
        srv.messageToGameKeyed(ga, true, "robber.stole.cloth.from", peName, viName);
        // <--- early return: cloth is announced to entire game ---
        return;
    }
    SOCPlayerElement gainRsrc = null;
    SOCPlayerElement loseRsrc = null;
    SOCPlayerElement gainUnknown;
    SOCPlayerElement loseUnknown;
    // This works because SOCPlayerElement.SHEEP == SOCResourceConstants.SHEEP.
    gainRsrc = new SOCPlayerElement(gaName, pePN, SOCPlayerElement.GAIN, rsrc, 1);
    loseRsrc = new SOCPlayerElement(gaName, viPN, SOCPlayerElement.LOSE, rsrc, 1, true);
    /**
     * send the game data messages
     */
    Connection peCon = srv.getConnection(peName);
    Connection viCon = srv.getConnection(viName);
    srv.messageToPlayer(peCon, gainRsrc);
    srv.messageToPlayer(peCon, loseRsrc);
    srv.messageToPlayer(viCon, gainRsrc);
    srv.messageToPlayer(viCon, loseRsrc);
    // Don't send generic message to pe or vi
    List<Connection> sendNotTo = new ArrayList<Connection>(2);
    sendNotTo.add(peCon);
    sendNotTo.add(viCon);
    gainUnknown = new SOCPlayerElement(gaName, pePN, SOCPlayerElement.GAIN, SOCPlayerElement.UNKNOWN, 1);
    loseUnknown = new SOCPlayerElement(gaName, viPN, SOCPlayerElement.LOSE, SOCPlayerElement.UNKNOWN, 1);
    srv.messageToGameExcept(gaName, sendNotTo, gainUnknown, true);
    srv.messageToGameExcept(gaName, sendNotTo, loseUnknown, true);
    /**
     * send the text messages:
     * "You stole a sheep from viName."  [In v1.x.xx, "stole a sheep resource"]
     * "peName stole a sheep from you."
     * "peName stole a resource from viName."
     */
    // "You stole {0,rsrcs} from {2}."
    srv.messageToPlayerKeyedSpecial(peCon, ga, "robber.you.stole.resource.from", -1, rsrc, viName);
    // "{0} stole {1,rsrcs} from you."
    srv.messageToPlayerKeyedSpecial(viCon, ga, "robber.stole.resource.from.you", peName, -1, rsrc);
    // "{0} stole a resource from {1}."
    srv.messageToGameKeyedSpecialExcept(ga, true, sendNotTo, "robber.stole.resource.from", peName, viName);
}
Also used : Connection(soc.server.genericServer.Connection) ArrayList(java.util.ArrayList) SOCPlayerElement(soc.message.SOCPlayerElement)

Example 9 with Connection

use of soc.server.genericServer.Connection in project JSettlers2 by jdmonin.

the class SOCGameHandler method sendGameState.

/**
 * Send all game members the current state of the game with a message.
 * May also send other messages to the current player.
 * Note that the current (or new) player number is not sent here.
 * If game is now OVER, sends appropriate messages.
 *<P>
 * State {@link SOCGame#WAITING_FOR_DISCARDS}:
 * If a 7 is rolled, will also say who must discard (in a GAMETEXTMSG).
 *<P>
 * State {@link SOCGame#WAITING_FOR_ROB_CHOOSE_PLAYER}:
 * If current player must choose which player to rob,
 * will also prompt their client to choose (in a CHOOSEPLAYERREQUEST).
 *<P>
 * State {@link SOCGame#STARTS_WAITING_FOR_PICK_GOLD_RESOURCE}:
 * To announce the player must pick a resource to gain from the gold hex initial placement,
 * please call {@link #sendGameState_sendGoldPickAnnounceText(SOCGame, String, Connection, SOCGame.RollResult)}.
 *<P>
 * State {@link SOCGame#WAITING_FOR_PICK_GOLD_RESOURCE}:
 * If a gold hex is rolled, does not say who
 * must pick resources to gain (because of timing).  Please call
 * {@link #sendGameState_sendGoldPickAnnounceText(SOCGame, String, Connection, SOCGame.RollResult)}
 * after sending the resource gain text ("x gets 1 sheep").
 *<P>
 * <b>Note:</b> If game is now {@link SOCGame#OVER OVER} and the {@link SOCGame#isBotsOnly} flag is set,
 * {@link #sendGameStateOVER(SOCGame)} will call {@link SOCServer#destroyGameAndBroadcast(String, String)}.
 * Be sure that callers to {@code sendGameState} don't assume the game will still exist after calling this method.
 * Also, {@code destroyGame} might create more {@link SOCGame#isBotsOnly} games, depending on server settings.
 *<P>
 * <b>Locks:</b> Does not hold {@link SOCGameList#takeMonitor()} or
 * {@link SOCGameList#takeMonitorForGame}<tt>(gaName)</tt> when called.
 * Some callers call {@link SOCGame#takeMonitor()} before calling; not important here.
 *
 * @see #sendTurn(SOCGame, boolean)
 * @see #sendGameState(SOCGame)
 * @see #sendGameStateOVER(SOCGame)
 *
 * @param ga  the game
 * @param omitGameStateMessage  if true, don't send the {@link SOCGameState} message itself
 *    but do send any other messages as described above. For use just after sending a message which
 *    includes a Game State field.
 * @param sendRollPrompt  If true, and if we send a text message to prompt
 *    the player to roll, send a RollDicePrompt data message.
 *    If the client is too old (1.0.6), it will ignore the prompt.
 *
 * @return    did we send a text message to prompt the player to roll?
 *    If so, sendTurn can also send a RollDicePrompt data message.
 * @since 1.1.00
 */
boolean sendGameState(SOCGame ga, final boolean omitGameStateMessage, final boolean sendRollPrompt) {
    if (ga == null)
        return false;
    final int gaState = ga.getGameState();
    final int cpn = ga.getCurrentPlayerNumber();
    final String gname = ga.getName();
    boolean promptedRoll = false;
    if (gaState == SOCGame.OVER) {
        /**
         * Before sending state "OVER", enforce current player number.
         * This helps the client's copy of game recognize winning condition.
         */
        srv.messageToGame(gname, (ga.clientVersionLowest >= SOCGameElements.MIN_VERSION) ? new SOCGameElements(gname, SOCGameElements.CURRENT_PLAYER, cpn) : new SOCSetTurn(gname, cpn));
    }
    if (!omitGameStateMessage)
        srv.messageToGame(gname, new SOCGameState(gname, gaState));
    SOCPlayer player = null;
    if (cpn != -1)
        player = ga.getPlayer(cpn);
    switch(gaState) {
        case SOCGame.START1A:
        case SOCGame.START2A:
        case SOCGame.START3A:
            // "It's Joe's turn to build a settlement."
            srv.messageToGameKeyed(ga, true, "prompt.turn.to.build.stlmt", player.getName());
            if ((gaState >= SOCGame.START2A) && ga.isGameOptionSet(SOCGameOption.K_SC_3IP)) {
                // reminder to player before their 2nd, 3rd settlements
                Connection con = srv.getConnection(player.getName());
                if (con != null) {
                    srv.messageToPlayerKeyed(con, gname, "prompt.gameopt._SC_3IP.part1");
                    // "This game gives you 3 initial settlements and roads."
                    srv.messageToPlayerKeyed(con, gname, "prompt.gameopt._SC_3IP.part2");
                // "Your free resources will be from the third settlement."
                }
            }
            break;
        case SOCGame.START1B:
        case SOCGame.START2B:
        case SOCGame.START3B:
            srv.messageToGameKeyed(ga, true, (// "It's Joe's turn to build a road or ship."
            (ga.hasSeaBoard) ? // "It's Joe's turn to build a road or ship."
            "prompt.turn.to.build.road.or.ship" : "prompt.turn.to.build.road"), player.getName());
            break;
        case SOCGame.ROLL_OR_CARD:
            // "It's Joe's turn to roll the dice."
            srv.messageToGameKeyed(ga, true, "prompt.turn.to.roll.dice", player.getName());
            promptedRoll = true;
            if (sendRollPrompt)
                srv.messageToGame(gname, new SOCRollDicePrompt(gname, player.getPlayerNumber()));
            break;
        case SOCGame.WAITING_FOR_DISCARDS:
            {
                ArrayList<String> names = new ArrayList<String>();
                for (int i = 0; i < ga.maxPlayers; i++) if (ga.getPlayer(i).getNeedToDiscard())
                    names.add(ga.getPlayer(i).getName());
                if (names.size() == 1)
                    // "Joe needs to discard"
                    srv.messageToGameKeyed(ga, true, "prompt.discard.1", names.get(0));
                else
                    // "Joe and Ed need to discard"
                    srv.messageToGameKeyedSpecial(ga, true, "prompt.discard.n", names);
            }
            break;
        case SOCGame.WAITING_FOR_ROBBER_OR_PIRATE:
            // "{0} must choose to move the robber or the pirate."
            srv.messageToGameKeyed(ga, true, "robber.willmove.choose", player.getName());
            break;
        case SOCGame.PLACING_ROBBER:
            // "{0} will move the robber."
            srv.messageToGameKeyed(ga, true, "robber.willmove", player.getName());
            break;
        case SOCGame.PLACING_PIRATE:
            // "{0} will move the pirate ship."
            srv.messageToGameKeyed(ga, true, "robber.willmove.pirate", player.getName());
            break;
        case SOCGame.WAITING_FOR_ROB_CHOOSE_PLAYER:
            /**
             * get the choices from the game
             */
            final boolean canStealNone = ga.isGameOptionSet(SOCGameOption.K_SC_PIRI);
            boolean[] choices = new boolean[ga.maxPlayers + (canStealNone ? 1 : 0)];
            Arrays.fill(choices, false);
            if (canStealNone)
                choices[ga.maxPlayers] = true;
            for (SOCPlayer pl : ga.getPossibleVictims()) choices[pl.getPlayerNumber()] = true;
            /**
             * ask the current player to choose a player to steal from
             */
            Connection con = srv.getConnection(ga.getPlayer(cpn).getName());
            if (con != null) {
                con.put(SOCChoosePlayerRequest.toCmd(gname, choices));
            }
            break;
        case SOCGame.OVER:
            sendGameStateOVER(ga);
            break;
    }
    return promptedRoll;
}
Also used : SOCGameState(soc.message.SOCGameState) Connection(soc.server.genericServer.Connection) ArrayList(java.util.ArrayList) SOCRollDicePrompt(soc.message.SOCRollDicePrompt) SOCGameElements(soc.message.SOCGameElements) SOCSetTurn(soc.message.SOCSetTurn)

Example 10 with Connection

use of soc.server.genericServer.Connection in project JSettlers2 by jdmonin.

the class SOCGameHandler method playerEvent.

/**
 * Listener callback for per-player scenario events on the large sea board.
 * For example, there might be an SVP awarded for settlements.
 * Server sends messages to the game to announce it (PLAYERELEMENT,
 * {@link #updatePlayerSVPPendingMessage(SOCGame, SOCPlayer, int, String)}, etc).
 *<P>
 * <em>Threads:</em> The game's treater thread handles incoming client messages and calls
 * game methods that change state. Those same game methods will trigger the scenario events;
 * so, the treater thread will also run this <tt>playerEvent</tt> callback.
 *
 * @param ga  Game
 * @param pl  Player
 * @param evt  Event code
 * @see #gameEvent(SOCGame, SOCScenarioGameEvent, Object)
 * @param flagsChanged  True if this event changed {@link SOCPlayer#getScenarioPlayerEvents()},
 *             {@link SOCPlayer#getSpecialVP()}, or another flag documented for <tt>evt</tt> in
 *             {@link SOCScenarioPlayerEvent}
 * @param obj  Object related to the event, or null; documented for <tt>evt</tt> in {@link SOCScenarioPlayerEvent}.
 *             Example: The {@link SOCVillage} for {@link SOCScenarioPlayerEvent#CLOTH_TRADE_ESTABLISHED_VILLAGE}.
 * @since 2.0.00
 */
public void playerEvent(final SOCGame ga, final SOCPlayer pl, final SOCScenarioPlayerEvent evt, final boolean flagsChanged, final Object obj) {
    // Note: Some SOCGameHandler code assumes that player events are fired only during
    // SOCGameMessageHandler.handlePUTPIECE and handleMOVEPIECE.
    // Most handle* methods don't check pendingMessagesOut before sending game state.
    // If a new player event breaks this assumption, adjust SOCGameHandler.playerEvent(...)
    // and related code; search where SOCGame.pendingMessagesOut is used.
    final String gaName = ga.getName(), plName = pl.getName();
    final int pn = pl.getPlayerNumber();
    boolean sendSVP = true;
    boolean sendPlayerEventsBitmask = true;
    switch(evt) {
        case SVP_SETTLED_ANY_NEW_LANDAREA:
            {
                final String newSettleEventStr = (playerEvent_newSettlementIsByShip(ga, (SOCSettlement) obj)) ? // "growing past the main island"
                "event.svp.sc_sany.island" : // "growing to a new area"
                "event.svp.sc_sany.area";
                updatePlayerSVPPendingMessage(ga, pl, 1, newSettleEventStr);
            }
            break;
        case SVP_SETTLED_EACH_NEW_LANDAREA:
            {
                final String newSettleEventStr = (playerEvent_newSettlementIsByShip(ga, (SOCSettlement) obj)) ? // "settling a new island"
                "event.svp.sc_seac.island" : // "settling a new area"
                "event.svp.sc_seac.area";
                updatePlayerSVPPendingMessage(ga, pl, 2, newSettleEventStr);
                sendPlayerEventsBitmask = false;
                final int las = pl.getScenarioSVPLandAreas();
                if (las != 0)
                    ga.pendingMessagesOut.add(new SOCPlayerElement(gaName, pn, SOCPlayerElement.SET, SOCPlayerElement.SCENARIO_SVP_LANDAREAS_BITMASK, las));
            }
            break;
        case CLOTH_TRADE_ESTABLISHED_VILLAGE:
            {
                sendSVP = false;
                if (!flagsChanged)
                    sendPlayerEventsBitmask = false;
                ga.pendingMessagesOut.add(new UnlocalizedString("event.sc_clvi.established", // "{0} established a trade route with a village."
                plName));
                if (flagsChanged)
                    srv.messageToPlayerPendingKeyed(pl, gaName, "event.sc_clvi.not.prevented.pirate");
                // "You are no longer prevented from moving the pirate ship."
                // Player gets 1 cloth for establishing trade
                SOCVillage vi = (SOCVillage) obj;
                srv.messageToGame(gaName, new SOCPieceValue(gaName, vi.getCoordinates(), vi.getCloth(), 0));
                srv.messageToGame(gaName, new SOCPlayerElement(gaName, pn, SOCPlayerElement.SET, SOCPlayerElement.SCENARIO_CLOTH_COUNT, pl.getCloth()));
            }
            break;
        case DEV_CARD_REACHED_SPECIAL_EDGE:
            {
                sendPlayerEventsBitmask = false;
                sendSVP = false;
                IntPair edge_cardType = (IntPair) obj;
                Connection c = srv.getConnection(plName);
                ga.pendingMessagesOut.add(new UnlocalizedString("action.built.sc_ftri.dev", // "{0} gets a Development Card as a gift from the Lost Tribe."
                plName));
                srv.messageToPlayer(c, new SOCDevCardAction(gaName, pn, SOCDevCardAction.DRAW, edge_cardType.getB()));
                srv.messageToGameExcept(gaName, c, new SOCDevCardAction(gaName, pn, SOCDevCardAction.DRAW, SOCDevCardConstants.UNKNOWN), true);
                srv.messageToGame(gaName, new SOCSimpleAction(gaName, -1, SOCSimpleAction.BOARD_EDGE_SET_SPECIAL, edge_cardType.getA(), 0));
            }
            break;
        case SVP_REACHED_SPECIAL_EDGE:
            {
                // "a gift from the Lost Tribe"
                updatePlayerSVPPendingMessage(ga, pl, 1, "event.svp.sc_ftri.gift");
                sendPlayerEventsBitmask = false;
                srv.messageToGame(gaName, new SOCSimpleAction(gaName, -1, SOCSimpleAction.BOARD_EDGE_SET_SPECIAL, ((Integer) obj).intValue(), 0));
            }
            break;
        case REMOVED_TRADE_PORT:
            {
                sendPlayerEventsBitmask = false;
                sendSVP = false;
                IntPair edge_portType = (IntPair) obj;
                final int edge = edge_portType.getA(), portType = edge_portType.getB();
                if ((edge & 0xFF) <= ga.getBoard().getBoardWidth())
                    // announce removal from board, unless (for debugging)
                    // this port wasn't really on the board at clients
                    srv.messageToGame(gaName, new SOCSimpleAction(gaName, pn, SOCSimpleAction.TRADE_PORT_REMOVED, edge, portType));
                if (ga.getGameState() == SOCGame.PLACING_INV_ITEM) {
                    // Removal happens during ship piece placement, which is followed at server with sendGameState.
                    // When sendGameState gives the new state, client will prompt current player to place now.
                    // We just need to send the client PLACING_EXTRA, for the port type and not-cancelable flag.
                    Connection c = srv.getConnection(plName);
                    srv.messageToPlayer(c, new SOCInventoryItemAction(gaName, pn, SOCInventoryItemAction.PLACING_EXTRA, -portType, false, false, false));
                } else {
                    // port was added to player's inventory;
                    // if this message changes, also update SOCGameHandler.processDebugCommand_scenario
                    srv.messageToGame(gaName, new SOCInventoryItemAction(gaName, pn, SOCInventoryItemAction.ADD_PLAYABLE, -portType, false, false, true));
                }
            }
            break;
        default:
            // Suppress warning; not all enum values need a handler here
            break;
    }
    if (sendSVP)
        ga.pendingMessagesOut.add(new SOCPlayerElement(gaName, pn, SOCPlayerElement.SET, SOCPlayerElement.SCENARIO_SVP, pl.getSpecialVP()));
    if (sendPlayerEventsBitmask)
        ga.pendingMessagesOut.add(new SOCPlayerElement(gaName, pn, SOCPlayerElement.SET, SOCPlayerElement.SCENARIO_PLAYEREVENTS_BITMASK, pl.getScenarioPlayerEvents()));
}
Also used : SOCPieceValue(soc.message.SOCPieceValue) SOCInventoryItemAction(soc.message.SOCInventoryItemAction) Connection(soc.server.genericServer.Connection) SOCSimpleAction(soc.message.SOCSimpleAction) IntPair(soc.util.IntPair) SOCPlayerElement(soc.message.SOCPlayerElement) SOCDevCardAction(soc.message.SOCDevCardAction)

Aggregations

Connection (soc.server.genericServer.Connection)44 StringConnection (soc.server.genericServer.StringConnection)24 SQLException (java.sql.SQLException)8 MissingResourceException (java.util.MissingResourceException)8 SOCGame (soc.game.SOCGame)7 EOFException (java.io.EOFException)5 IOException (java.io.IOException)5 SocketException (java.net.SocketException)5 ArrayList (java.util.ArrayList)5 SOCPlayerElement (soc.message.SOCPlayerElement)5 DBSettingMismatchException (soc.server.database.DBSettingMismatchException)5 SOCPlayer (soc.game.SOCPlayer)4 Date (java.util.Date)3 SOCGameElements (soc.message.SOCGameElements)3 HashSet (java.util.HashSet)2 Hashtable (java.util.Hashtable)2 TimerTask (java.util.TimerTask)2 Vector (java.util.Vector)2 SOCDevCardAction (soc.message.SOCDevCardAction)2 SOCInventoryItemAction (soc.message.SOCInventoryItemAction)2