Search in sources :

Example 6 with SOCPlayerElement

use of soc.message.SOCPlayerElement 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)

Example 7 with SOCPlayerElement

use of soc.message.SOCPlayerElement in project JSettlers2 by jdmonin.

the class SOCGameHandler method startGame.

// javadoc inherited from GameHandler
/**
 * {@inheritDoc}
 *<P>
 * If {@link SOCGame#hasSeaBoard}: Once the board is made, send the updated
 * {@link SOCPotentialSettlements potential settlements}.
 *<P>
 * If this code changes, must also update {@link soctest.TestBoardLayouts#testSingleLayout(SOCScenario, int)}.
 */
public void startGame(SOCGame ga) {
    if (ga == null)
        return;
    final String gaName = ga.getName();
    // TODO once multiple handler threads, encapsulate this
    srv.numberOfGamesStarted++;
    /**
     * start the game, place any initial pieces.
     * If anything is added to this game object setup code,
     * update soctest.TestBoardLayouts.testSingleLayout(..).
     */
    // for playerEvent, gameEvent callbacks (since 2.0.00)
    ga.setScenarioEventListener(this);
    ga.startGame();
    // used on sea board; if null, all are legal
    final int[][] legalSeaEdges;
    if (ga.hasSeaBoard) {
        legalSeaEdges = SOCBoardAtServer.getLegalSeaEdges(ga, -1);
        if (legalSeaEdges != null)
            for (int pn = 0; pn < ga.maxPlayers; ++pn) ga.getPlayer(pn).setRestrictedLegalShips(legalSeaEdges[pn]);
        if (ga.isGameOptionSet(SOCGameOption.K_SC_FTRI) || ga.isGameOptionSet(SOCGameOption.K_SC_PIRI)) {
            // scenario has initial pieces
            ((SOCBoardAtServer) (ga.getBoard())).startGame_putInitPieces(ga);
        }
    } else {
        legalSeaEdges = null;
    }
    srv.gameList.takeMonitorForGame(gaName);
    try {
        /**
         * send the board layout
         */
        try {
            srv.messageToGameWithMon(gaName, getBoardLayoutMessage(ga));
        // For scenario option _SC_CLVI, the board layout message
        // includes villages and the general supply cloth count.
        // For _SC_PIRI, it includes the Pirate Path (additional layout part "PP").
        } catch (IllegalArgumentException e) {
            System.err.println("startGame: Cannot send board for " + gaName + ": " + e.getMessage());
            // the enclosing try-finally will releaseMonitorForGame(gaName) before returning
            return;
        }
        if (ga.hasSeaBoard) {
            // See also joinGame which has very similar code.
            // Send the updated Potential/Legal Settlement node list
            // Note: Assumes all players have same potential settlements
            // (sends with playerNumber -1 == all)
            final HashSet<Integer> psList = ga.getPlayer(0).getPotentialSettlements();
            // Some boards may have multiple land areas.
            final HashSet<Integer>[] lan;
            final int pan;
            boolean addedPsList = false;
            final SOCBoardLarge bl = (SOCBoardLarge) ga.getBoard();
            lan = bl.getLandAreasLegalNodes();
            pan = bl.getStartingLandArea();
            if ((lan != null) && (pan != 0) && !lan[pan].equals(psList)) {
                // If potentials != legals[startingLandArea], send as legals[0]
                lan[0] = psList;
                addedPsList = true;
            }
            if (lan == null)
                srv.messageToGameWithMon(gaName, new SOCPotentialSettlements(gaName, -1, new ArrayList<Integer>(psList)));
            else
                srv.messageToGameWithMon(gaName, new SOCPotentialSettlements(gaName, -1, pan, lan, legalSeaEdges));
            if (addedPsList)
                // Undo change to game's copy of landAreasLegalNodes
                lan[0] = null;
        }
        /**
         * send the player info
         */
        boolean sentInitPiecesState = false;
        for (int i = 0; i < ga.maxPlayers; i++) {
            if (ga.isSeatVacant(i))
                continue;
            final SOCPlayer pl = ga.getPlayer(i);
            final int[] counts = new int[(ga.hasSeaBoard) ? 4 : 3];
            counts[0] = pl.getNumPieces(SOCPlayingPiece.ROAD);
            counts[1] = pl.getNumPieces(SOCPlayingPiece.SETTLEMENT);
            counts[2] = pl.getNumPieces(SOCPlayingPiece.CITY);
            if (ga.hasSeaBoard) {
                // Some scenarios like SC_PIRI may place initial pieces at fixed locations.
                // Usually, pieces will be empty.
                final Vector<SOCPlayingPiece> pieces = pl.getPieces();
                if (!pieces.isEmpty()) {
                    if (!sentInitPiecesState) {
                        // Temporary state change, to avoid initial-piece placement actions.
                        // The actual game state will be sent soon.
                        srv.messageToGameWithMon(gaName, new SOCGameState(gaName, SOCGame.READY));
                        sentInitPiecesState = true;
                    }
                    for (SOCPlayingPiece pp : pieces) srv.messageToGameWithMon(gaName, new SOCPutPiece(gaName, i, pp.getType(), pp.getCoordinates()));
                    SOCPlayingPiece pp = pl.getFortress();
                    if (pp != null)
                        srv.messageToGameWithMon(gaName, new SOCPutPiece(gaName, i, pp.getType(), pp.getCoordinates()));
                }
                counts[3] = pl.getNumPieces(SOCPlayingPiece.SHIP);
            }
            if (ga.clientVersionLowest >= SOCPlayerElements.MIN_VERSION)
                srv.messageToGameWithMon(gaName, new SOCPlayerElements(gaName, i, SOCPlayerElement.SET, (ga.hasSeaBoard) ? ELEM_PIECETYPES_SEA : ELEM_PIECETYPES_CLASSIC, counts));
            else
                for (int j = 0; j < counts.length; ++j) srv.messageToGameWithMon(gaName, new SOCPlayerElement(gaName, i, SOCPlayerElement.SET, ELEM_PIECETYPES_SEA[j], counts[j]));
            if (ga.clientVersionLowest < SOCPlayerElement.VERSION_FOR_CARD_ELEMENTS)
                srv.messageToGameWithMon(gaName, new SOCSetPlayedDevCard(gaName, i, false));
        }
        if (ga.clientVersionLowest >= SOCPlayerElement.VERSION_FOR_CARD_ELEMENTS)
            srv.messageToGameWithMon(gaName, new SOCPlayerElement(gaName, -1, SOCPlayerElement.SET, SOCPlayerElement.PLAYED_DEV_CARD_FLAG, 0));
        /**
         * send the number of dev cards
         */
        srv.messageToGameWithMon(gaName, (ga.clientVersionLowest >= SOCGameElements.MIN_VERSION) ? new SOCGameElements(gaName, SOCGameElements.DEV_CARD_COUNT, ga.getNumDevCards()) : new SOCDevCardCount(gaName, ga.getNumDevCards()));
        /**
         * ga.startGame() picks who goes first, but feedback is nice
         */
        srv.messageToGameKeyed(ga, false, // "Randomly picking a starting player..."
        "start.picking.random.starting.player");
    } finally {
        srv.gameList.releaseMonitorForGame(gaName);
    }
    /**
     * send the game state and start the game.
     * send game state and whose turn it is.
     */
    if (ga.clientVersionLowest >= SOCGameState.VERSION_FOR_GAME_STATE_AS_FIELD) {
        srv.messageToGame(gaName, new SOCStartGame(gaName, ga.getGameState()));
        sendTurn(ga, false);
    } else {
        final int cpn = ga.getCurrentPlayerNumber();
        final boolean sendRoll = sendGameState(ga, false, false);
        srv.messageToGame(gaName, new SOCStartGame(gaName, 0));
        srv.messageToGame(gaName, new SOCTurn(gaName, cpn, 0));
        if (sendRoll)
            srv.messageToGame(gaName, new SOCRollDicePrompt(gaName, cpn));
    }
}
Also used : SOCGameState(soc.message.SOCGameState) SOCPotentialSettlements(soc.message.SOCPotentialSettlements) SOCTurn(soc.message.SOCTurn) SOCRollDicePrompt(soc.message.SOCRollDicePrompt) SOCPlayerElement(soc.message.SOCPlayerElement) SOCSetPlayedDevCard(soc.message.SOCSetPlayedDevCard) HashSet(java.util.HashSet) SOCStartGame(soc.message.SOCStartGame) SOCPlayerElements(soc.message.SOCPlayerElements) SOCPutPiece(soc.message.SOCPutPiece) SOCGameElements(soc.message.SOCGameElements) SOCDevCardCount(soc.message.SOCDevCardCount)

Example 8 with SOCPlayerElement

use of soc.message.SOCPlayerElement in project JSettlers2 by jdmonin.

the class SOCGameHandler method reportRsrcGainGold.

/**
 * Report to game members what a player picked from the gold hex.
 * Sends {@link SOCPlayerElement} for resources and to reset the
 * {@link SOCPlayerElement#NUM_PICK_GOLD_HEX_RESOURCES} counter.
 * Sends text "playername has picked ___ from the gold hex.".
 * @param ga      Game with gaining player
 * @param player  Player gaining
 * @param pn      <tt>player</tt>{@link SOCPlayer#getPlayerNumber() .getPlayerNumber()}
 * @param rsrcs   Resources picked
 * @param isNews  Is this element change notably good or an unexpected bad change or loss?
 *                Sets the {@link SOCPlayerElement#isNews()} flag in messages sent by this method.
 *                If there are multiple resource types, flag is set only for the first type sent
 *                to avoid several alert sounds at client.
 * @param includeGoldHexText  If true, text ends with "from the gold hex." after the resource name.
 * @since 2.0.00
 */
void reportRsrcGainGold(final SOCGame ga, final SOCPlayer player, final int pn, final SOCResourceSet rsrcs, final boolean isNews, final boolean includeGoldHexText) {
    final String gn = ga.getName();
    // Send SOCPlayerElement messages
    reportRsrcGainLoss(gn, rsrcs, false, isNews, pn, -1, null, null);
    srv.messageToGameKeyedSpecial(ga, true, ((includeGoldHexText) ? "action.picked.rsrcs.goldhex" : "action.picked.rsrcs"), player.getName(), rsrcs);
    srv.messageToGame(gn, new SOCPlayerElement(gn, pn, SOCPlayerElement.SET, SOCPlayerElement.NUM_PICK_GOLD_HEX_RESOURCES, 0));
}
Also used : SOCPlayerElement(soc.message.SOCPlayerElement)

Example 9 with SOCPlayerElement

use of soc.message.SOCPlayerElement in project JSettlers2 by jdmonin.

the class SOCGameHandler method forceEndGameTurn.

/**
 * Try to force-end the current player's turn in this game.
 * Alter game state and send messages to players.
 * Will call {@link #endGameTurn(SOCGame, SOCPlayer, boolean)} if appropriate.
 * Will send gameState and current player (turn) to clients.
 *<P>
 * If the current player has lost connection, send the {@link SOCLeaveGame LEAVEGAME}
 * message out <b>before</b> calling this method.
 *<P>
 * Assumes, as {@link #endGameTurn(SOCGame, SOCPlayer, boolean)} does:
 * <UL>
 * <LI> ga.canEndTurn already called, returned false
 * <LI> ga.takeMonitor already called (not the same as {@link SOCGameList#takeMonitorForGame(String)})
 * <LI> gamelist.takeMonitorForGame is NOT called, we do NOT have that monitor
 * </UL>
 * @param ga Game to force end turn
 * @param plName Current player's name. Needed because if they have been disconnected by
 *               {@link #leaveGame(SOCGame, Connection)},
 *               their name within game object is already null.
 * @return true if the turn was ended and game is still active;
 *          false if we find that all players have left and
 *          the gamestate has been changed here to {@link SOCGame#OVER}.
 *
 * @see #endGameTurnOrForce(SOCGame, int, String, Connection, boolean)
 * @see SOCGame#forceEndTurn()
 */
private final boolean forceEndGameTurn(SOCGame ga, final String plName) {
    final String gaName = ga.getName();
    final int cpn = ga.getCurrentPlayerNumber();
    final int endFromGameState = ga.getGameState();
    SOCPlayer cp = ga.getPlayer(cpn);
    if (cp.hasAskedSpecialBuild()) {
        cp.setAskedSpecialBuild(false);
        srv.messageToGame(gaName, new SOCPlayerElement(gaName, cpn, SOCPlayerElement.SET, SOCPlayerElement.ASK_SPECIAL_BUILD, 0));
    }
    final SOCForceEndTurnResult res = ga.forceEndTurn();
    // also could be initial placement (START1A or START2A or START3A).
    if (SOCGame.OVER == ga.getGameState())
        // <--- Early return: All players have left ---
        return false;
    /**
     * Report any resources lost or gained.
     * See also forceGamePlayerDiscardOrGain for same reporting code.
     */
    SOCResourceSet resGainLoss = res.getResourcesGainedLost();
    if (resGainLoss != null) {
        /**
         * If gold hex or returning resources to player (not discarding), report actual types/amounts.
         * For discard, tell the discarding player's client that they discarded the resources,
         * tell everyone else that the player discarded unknown resources.
         */
        if (!res.isLoss()) {
            if ((endFromGameState == SOCGame.WAITING_FOR_PICK_GOLD_RESOURCE) || (endFromGameState == SOCGame.STARTS_WAITING_FOR_PICK_GOLD_RESOURCE)) {
                // Send SOCPlayerElement messages, "gains" text
                reportRsrcGainGold(ga, cp, cpn, resGainLoss, true, false);
            } else {
                // Send SOCPlayerElement messages
                reportRsrcGainLoss(gaName, resGainLoss, false, false, cpn, -1, null, null);
            }
        } else {
            Connection c = srv.getConnection(plName);
            if ((c != null) && c.isConnected())
                reportRsrcGainLoss(gaName, resGainLoss, true, true, cpn, -1, null, c);
            int totalRes = resGainLoss.getTotal();
            srv.messageToGameExcept(gaName, c, new SOCPlayerElement(gaName, cpn, SOCPlayerElement.LOSE, SOCPlayerElement.UNKNOWN, totalRes, true), true);
            // "{0} discarded {1} resources."
            srv.messageToGameKeyed(ga, true, "action.discarded", plName, totalRes);
        }
    }
    /**
     * report any dev-card or item returned to player's hand
     */
    final SOCInventoryItem itemCard = res.getReturnedInvItem();
    SOCInventoryItemAction retItemActionMsg = null;
    if (itemCard != null) {
        Connection c = srv.getConnection(plName);
        if ((c != null) && c.isConnected()) {
            if (itemCard instanceof SOCDevCard) {
                int card = itemCard.itype;
                if ((card == SOCDevCardConstants.KNIGHT) && (c.getVersion() < SOCDevCardConstants.VERSION_FOR_NEW_TYPES))
                    card = SOCDevCardConstants.KNIGHT_FOR_VERS_1_X;
                srv.messageToPlayer(c, new SOCDevCardAction(gaName, cpn, SOCDevCardAction.ADD_OLD, card));
            } else {
                retItemActionMsg = new SOCInventoryItemAction(gaName, cpn, (itemCard.isPlayable() ? SOCInventoryItemAction.ADD_PLAYABLE : SOCInventoryItemAction.ADD_OTHER), itemCard.itype, itemCard.isKept(), itemCard.isVPItem(), itemCard.canCancelPlay);
                srv.messageToPlayer(c, retItemActionMsg);
            }
        }
        // Announce item to game with same retItemActionMsg sent to player?
        boolean announceAsInvItemAction = false;
        // Announce this item to game as an unknown dev card type?
        boolean announceAsUnknown = true;
        if (!(itemCard instanceof SOCDevCard)) {
            // SOCInventoryItem: Add any new kinds here, to announce to all players.
            // If it needs a special message, do so and set announceAsUnknown = false
            // If it's private and doesn't need a special message, set handled = true and let it announce as unknown
            boolean handled = false;
            if (ga.isGameOptionSet(SOCGameOption.K_SC_FTRI)) {
                // endFromGameState is PLACING_INV_ITEM.
                // "Gift port" item details are public, send return message to whole game:
                handled = true;
                announceAsInvItemAction = true;
                announceAsUnknown = false;
            }
            // Fallback:
            if (!handled)
                System.err.println("forceEndGameTurn: Unhandled inventory item type " + itemCard.itype + " class " + itemCard.getClass());
        }
        if (announceAsInvItemAction) {
            srv.messageToGameExcept(gaName, c, retItemActionMsg, true);
        } else if (announceAsUnknown) {
            if (ga.clientVersionLowest >= SOCDevCardConstants.VERSION_FOR_NEW_TYPES) {
                srv.messageToGameExcept(gaName, c, new SOCDevCardAction(gaName, cpn, SOCDevCardAction.ADD_OLD, SOCDevCardConstants.UNKNOWN), true);
            } else {
                srv.messageToGameForVersionsExcept(ga, -1, SOCDevCardConstants.VERSION_FOR_NEW_TYPES - 1, c, new SOCDevCardAction(gaName, cpn, SOCDevCardAction.ADD_OLD, SOCDevCardConstants.UNKNOWN_FOR_VERS_1_X), true);
                srv.messageToGameForVersionsExcept(ga, SOCDevCardConstants.VERSION_FOR_NEW_TYPES, Integer.MAX_VALUE, c, new SOCDevCardAction(gaName, cpn, SOCDevCardAction.ADD_OLD, SOCDevCardConstants.UNKNOWN), true);
            }
            srv.messageToGameKeyed(ga, true, "forceend.devcard.returned", plName);
        // "{0}''s just-played development card was returned."
        }
    }
    /**
     * For initial placements, we don't end turns as normal.
     * (Player number may go forward or backwards, new state isn't ROLL_OR_CARD, etc.)
     * Update clients' gamestate, but don't call endGameTurn.
     */
    final int forceRes = res.getResult();
    if ((forceRes == SOCForceEndTurnResult.FORCE_ENDTURN_SKIP_START_ADV) || (forceRes == SOCForceEndTurnResult.FORCE_ENDTURN_SKIP_START_ADVBACK)) {
        if (res.didUpdateFP() || res.didUpdateLP()) {
            final int fpn = ga.getFirstPlayer();
            final SOCMessage msg = (ga.clientVersionLowest >= SOCGameElements.MIN_VERSION) ? new SOCGameElements(gaName, SOCGameElements.FIRST_PLAYER, fpn) : new SOCFirstPlayer(gaName, fpn);
            // will cause clients to recalculate lastPlayer too
            srv.messageToGame(gaName, msg);
        }
        sendTurn(ga, false);
        // <--- Early return ---
        return true;
    }
    /**
     * If the turn can now end, proceed as if player requested it.
     * Otherwise, send current gamestate.  We'll all wait for other
     * players to send discard messages, and afterwards this turn can end.
     */
    if (ga.canEndTurn(cpn))
        // could force gamestate to OVER, if a client leaves
        endGameTurn(ga, null, true);
    else
        sendGameState(ga, false, false);
    return (ga.getGameState() != SOCGame.OVER);
}
Also used : SOCMessage(soc.message.SOCMessage) SOCInventoryItemAction(soc.message.SOCInventoryItemAction) Connection(soc.server.genericServer.Connection) SOCPlayerElement(soc.message.SOCPlayerElement) SOCGameElements(soc.message.SOCGameElements) SOCFirstPlayer(soc.message.SOCFirstPlayer) SOCDevCardAction(soc.message.SOCDevCardAction)

Example 10 with SOCPlayerElement

use of soc.message.SOCPlayerElement in project JSettlers2 by jdmonin.

the class SOCGameHandler method sitDown_sendPrivateInfo.

// javadoc inherited from GameHandler
public void sitDown_sendPrivateInfo(final SOCGame ga, final Connection c, final int pn) {
    final String gaName = ga.getName();
    final SOCPlayer pl = ga.getPlayer(pn);
    /**
     * send all the private information
     */
    SOCResourceSet resources = pl.getResources();
    // CLAY, ORE, SHEEP, WHEAT, WOOD, UNKNOWN
    final int[] counts = resources.getAmounts(true);
    if (c.getVersion() >= SOCPlayerElements.MIN_VERSION)
        srv.messageToPlayer(c, new SOCPlayerElements(gaName, pn, SOCPlayerElement.SET, ELEM_RESOURCES_WITH_UNKNOWN, counts));
    else
        for (int i = 0; i < counts.length; ++i) srv.messageToPlayer(c, new SOCPlayerElement(gaName, pn, SOCPlayerElement.SET, ELEM_RESOURCES_WITH_UNKNOWN[i], counts[i]));
    SOCInventory cardsInv = pl.getInventory();
    final boolean cliVersionNew = (c.getVersion() >= SOCDevCardConstants.VERSION_FOR_NEW_TYPES);
    /**
     * remove the unknown cards
     */
    final SOCDevCardAction cardUnknown = (cliVersionNew) ? new SOCDevCardAction(gaName, pn, SOCDevCardAction.PLAY, SOCDevCardConstants.UNKNOWN) : new SOCDevCardAction(gaName, pn, SOCDevCardAction.PLAY, SOCDevCardConstants.UNKNOWN_FOR_VERS_1_X);
    for (int i = cardsInv.getTotal(); i > 0; --i) {
        srv.messageToPlayer(c, cardUnknown);
    }
    /**
     * send all new dev cards first, then all playable, then all kept (VP cards)
     */
    for (int dcState = SOCInventory.NEW; dcState <= SOCInventory.KEPT; ++dcState) {
        final int dcAge = (dcState == SOCInventory.NEW) ? SOCInventory.NEW : SOCInventory.OLD;
        final int addCmd = (dcAge == SOCInventory.NEW) ? SOCDevCardAction.ADD_NEW : SOCDevCardAction.ADD_OLD;
        for (final SOCInventoryItem card : cardsInv.getByState(dcState)) {
            final SOCMessage addMsg;
            if (card instanceof SOCDevCard) {
                final int dcType = card.itype;
                if (cliVersionNew || (dcType != SOCDevCardConstants.KNIGHT))
                    addMsg = new SOCDevCardAction(gaName, pn, addCmd, dcType);
                else
                    addMsg = new SOCDevCardAction(gaName, pn, addCmd, SOCDevCardConstants.KNIGHT_FOR_VERS_1_X);
            } else {
                // None yet
                System.err.println("L1385: Unrecognized inventory item type " + card.getClass());
                addMsg = null;
            }
            if (addMsg != null)
                srv.messageToPlayer(c, addMsg);
        }
    // for (card)
    }
    // for (dcState)
    /**
     * send game state info such as requests for discards
     */
    sendGameState(ga);
    if ((ga.getCurrentDice() == 7) && pl.getNeedToDiscard()) {
        srv.messageToPlayer(c, new SOCDiscardRequest(gaName, pl.getResources().getTotal() / 2));
    } else if (ga.hasSeaBoard) {
        final int numGoldRes = pl.getNeedToPickGoldHexResources();
        if (numGoldRes > 0)
            srv.messageToPlayer(c, new SOCSimpleRequest(gaName, pn, SOCSimpleRequest.PROMPT_PICK_RESOURCES, numGoldRes));
    }
    /**
     * send what face this player is using
     */
    srv.messageToGame(gaName, new SOCChangeFace(gaName, pn, pl.getFaceId()));
}
Also used : SOCMessage(soc.message.SOCMessage) SOCDiscardRequest(soc.message.SOCDiscardRequest) SOCPlayerElements(soc.message.SOCPlayerElements) SOCChangeFace(soc.message.SOCChangeFace) SOCSimpleRequest(soc.message.SOCSimpleRequest) SOCPlayerElement(soc.message.SOCPlayerElement) SOCDevCardAction(soc.message.SOCDevCardAction)

Aggregations

SOCPlayerElement (soc.message.SOCPlayerElement)12 Connection (soc.server.genericServer.Connection)5 ArrayList (java.util.ArrayList)3 SOCDevCardAction (soc.message.SOCDevCardAction)3 SOCGameElements (soc.message.SOCGameElements)3 SOCPlayerElements (soc.message.SOCPlayerElements)3 HashSet (java.util.HashSet)2 SOCInventoryItemAction (soc.message.SOCInventoryItemAction)2 SOCMessage (soc.message.SOCMessage)2 SOCPieceValue (soc.message.SOCPieceValue)2 SOCRollDicePrompt (soc.message.SOCRollDicePrompt)2 SOCSetPlayedDevCard (soc.message.SOCSetPlayedDevCard)2 SOCSimpleRequest (soc.message.SOCSimpleRequest)2 SOCTurn (soc.message.SOCTurn)2 Date (java.util.Date)1 NoSuchElementException (java.util.NoSuchElementException)1 StringTokenizer (java.util.StringTokenizer)1 SOCChangeFace (soc.message.SOCChangeFace)1 SOCClearOffer (soc.message.SOCClearOffer)1 SOCDevCardCount (soc.message.SOCDevCardCount)1