Search in sources :

Example 6 with SOCPlayer

use of soc.game.SOCPlayer in project JSettlers2 by jdmonin.

the class SOCGameMessageHandler method handleSETSPECIALITEM.

/**
 * Handle Special Item requests from a player.
 * Calls {@link SOCSpecialItem#playerPickItem(String, SOCGame, SOCPlayer, int, int)}
 * or {@link SOCSpecialItem#playerSetItem(String, SOCGame, SOCPlayer, int, int, boolean)}
 * which provide scenario-specific responses or decline the request.
 * @param c  the connection that sent the message
 * @param mes  the message
 */
private void handleSETSPECIALITEM(SOCGame ga, Connection c, final SOCSetSpecialItem mes) {
    final String gaName = ga.getName();
    final SOCPlayer pl = ga.getPlayer(c.getData());
    final String typeKey = mes.typeKey;
    final int op = mes.op, gi = mes.gameItemIndex, pi = mes.playerItemIndex;
    // don't trust mes.playerNumber
    final int pn = (pl != null) ? pl.getPlayerNumber() : -1;
    boolean sendDenyReply = false;
    try {
        SOCSpecialItem itm = null;
        // if true, itm's cost was paid by player to PICK or SET or CLEAR
        final boolean paidCost;
        ga.takeMonitor();
        if ((pl == null) || (op < SOCSetSpecialItem.OP_SET) || (op > SOCSetSpecialItem.OP_PICK)) {
            sendDenyReply = true;
            paidCost = false;
        } else {
            final int prevState = ga.getGameState();
            if (op == SOCSetSpecialItem.OP_PICK) {
                // field values to send in reply/announcement
                int pickCoord = -1, pickLevel = 0;
                // sv field value to send
                String pickSV = null;
                // When game index and player index are both given,
                // compare items before and after PICK in case they change
                final SOCSpecialItem gBefore, pBefore;
                if ((gi != -1) && (pi != -1)) {
                    gBefore = ga.getSpecialItem(typeKey, gi);
                    pBefore = pl.getSpecialItem(typeKey, pi);
                } else {
                    gBefore = null;
                    pBefore = null;
                }
                // Before pick, get item as per playerPickItem javadoc for cost, coord, level,
                // in case it's cleared by the pick. If not cleared, will get it again afterwards.
                itm = ga.getSpecialItem(typeKey, gi, pi, pn);
                if (itm != null) {
                    pickCoord = itm.getCoordinates();
                    pickLevel = itm.getLevel();
                    pickSV = itm.getStringValue();
                }
                // perform the PICK in game
                paidCost = SOCSpecialItem.playerPickItem(typeKey, ga, pl, gi, pi);
                // if cost paid, send resource-loss first
                if (paidCost && (itm != null))
                    handler.reportRsrcGainLoss(gaName, itm.getCost(), true, false, pn, -1, null, null);
                if ((gi == -1) || (pi == -1)) {
                    // request didn't specify both gi and pi: only 1 SET/CLEAR message to send
                    final SOCSpecialItem itmAfter = ga.getSpecialItem(typeKey, gi, pi, pn);
                    final SOCSetSpecialItem msg;
                    if (itmAfter != null) {
                        msg = new SOCSetSpecialItem(ga, SOCSetSpecialItem.OP_SET, typeKey, gi, pi, itmAfter);
                        pickCoord = itmAfter.getCoordinates();
                        pickLevel = itmAfter.getLevel();
                        pickSV = itmAfter.getStringValue();
                    } else {
                        msg = new SOCSetSpecialItem(gaName, SOCSetSpecialItem.OP_CLEAR, typeKey, gi, pi, pn);
                    }
                    srv.messageToGame(gaName, msg);
                } else {
                    // request specified both gi and pi: might need to send 1 SET/CLEAR message if shared,
                    // or 2 messages if not the same object for both
                    final SOCSpecialItem gAfter, pAfter;
                    gAfter = ga.getSpecialItem(typeKey, gi);
                    pAfter = pl.getSpecialItem(typeKey, pi);
                    if (gAfter == pAfter) {
                        final SOCSetSpecialItem msg;
                        if (gAfter != null) {
                            msg = new SOCSetSpecialItem(ga, SOCSetSpecialItem.OP_SET, typeKey, gi, pi, gAfter);
                            pickCoord = gAfter.getCoordinates();
                            pickLevel = gAfter.getLevel();
                            pickSV = gAfter.getStringValue();
                        } else {
                            msg = new SOCSetSpecialItem(gaName, SOCSetSpecialItem.OP_CLEAR, typeKey, gi, pi, pn);
                        }
                        srv.messageToGame(gaName, msg);
                    } else {
                        // gi and pi don't share the same object; might need to send 2 messages out if both changed.
                        boolean hasgAfterCoordLevel = false;
                        if (gAfter == null) {
                            if (gBefore != null)
                                srv.messageToGame(gaName, new SOCSetSpecialItem(gaName, SOCSetSpecialItem.OP_CLEAR, typeKey, gi, -1, -1));
                        } else {
                            srv.messageToGame(gaName, new SOCSetSpecialItem(ga, SOCSetSpecialItem.OP_SET, typeKey, gi, -1, gAfter));
                            pickCoord = gAfter.getCoordinates();
                            pickLevel = gAfter.getLevel();
                            pickSV = gAfter.getStringValue();
                            hasgAfterCoordLevel = true;
                        }
                        if (pAfter == null) {
                            if (pBefore != null)
                                srv.messageToGame(gaName, new SOCSetSpecialItem(gaName, SOCSetSpecialItem.OP_CLEAR, typeKey, -1, pi, pn));
                        } else {
                            srv.messageToGame(gaName, new SOCSetSpecialItem(ga, SOCSetSpecialItem.OP_SET, typeKey, -1, pi, pAfter));
                            if (!hasgAfterCoordLevel) {
                                pickCoord = pAfter.getCoordinates();
                                pickLevel = pAfter.getLevel();
                                pickSV = pAfter.getStringValue();
                            }
                        }
                    }
                }
                srv.messageToGame(gaName, new SOCSetSpecialItem(gaName, SOCSetSpecialItem.OP_PICK, typeKey, gi, pi, pn, pickCoord, pickLevel, pickSV));
            } else {
                if (op == SOCSetSpecialItem.OP_CLEAR)
                    // get item before CLEAR
                    itm = ga.getSpecialItem(typeKey, gi, pi, pn);
                paidCost = SOCSpecialItem.playerSetItem(typeKey, ga, pl, gi, pi, (op == SOCSetSpecialItem.OP_SET));
                // if cost paid, send resource-loss first
                if (paidCost && (itm != null))
                    handler.reportRsrcGainLoss(gaName, itm.getCost(), true, false, pn, -1, null, null);
                // get item after SET, in case it's changed
                if (op != SOCSetSpecialItem.OP_CLEAR)
                    itm = ga.getSpecialItem(typeKey, gi, pi, pn);
                if ((op == SOCSetSpecialItem.OP_CLEAR) || (itm == null))
                    srv.messageToGame(gaName, new SOCSetSpecialItem(gaName, SOCSetSpecialItem.OP_CLEAR, typeKey, gi, pi, pn));
                else
                    srv.messageToGame(gaName, new SOCSetSpecialItem(ga, op, typeKey, gi, pi, itm));
            }
            // check game state, check for winner
            final int gstate = ga.getGameState();
            if (gstate != prevState)
                // might be OVER, if player won
                handler.sendGameState(ga);
        }
    } catch (IllegalStateException e) {
        sendDenyReply = true;
    } catch (Exception e) {
        D.ebugPrintStackTrace(e, "Exception caught");
    } finally {
        ga.releaseMonitor();
    }
    if (sendDenyReply)
        c.put(new SOCSetSpecialItem(gaName, SOCSetSpecialItem.OP_DECLINE, typeKey, gi, pi, mes.playerNumber).toCmd());
}
Also used : SOCPlayer(soc.game.SOCPlayer) SOCSpecialItem(soc.game.SOCSpecialItem)

Example 7 with SOCPlayer

use of soc.game.SOCPlayer in project JSettlers2 by jdmonin.

the class SOCGameMessageHandler method handleDISCARD.

/**
 * handle "discard" message.
 *
 * @param c  the connection that sent the message
 * @param mes  the message
 * @since 1.0.0
 */
private void handleDISCARD(SOCGame ga, Connection c, final SOCDiscard mes) {
    final String gn = ga.getName();
    final SOCPlayer player = ga.getPlayer(c.getData());
    final int pn;
    if (player != null)
        pn = player.getPlayerNumber();
    else
        // c's client no longer in the game
        pn = -1;
    ga.takeMonitor();
    try {
        if (player == null) {
            // The catch block will print this out semi-nicely
            throw new IllegalArgumentException("player not found in game");
        }
        if (ga.canDiscard(pn, mes.getResources())) {
            // discard, change gameState
            ga.discard(pn, mes.getResources());
            // Same resource-loss messages are sent in handleROLLDICE after a pirate fleet attack (_SC_PIRI).
            /**
             * tell the player client that the player discarded the resources
             */
            handler.reportRsrcGainLoss(gn, mes.getResources(), true, false, pn, -1, null, c);
            /**
             * tell everyone else that the player discarded unknown resources
             */
            srv.messageToGameExcept(gn, c, new SOCPlayerElement(gn, pn, SOCPlayerElement.LOSE, SOCPlayerElement.UNKNOWN, mes.getResources().getTotal(), true), true);
            srv.messageToGameKeyed(ga, true, "action.discarded", c.getData(), mes.getResources().getTotal());
            /**
             * send the new state, or end turn if was marked earlier as forced
             */
            if ((ga.getGameState() != SOCGame.PLAY1) || !ga.isForcingEndTurn()) {
                handler.sendGameState(ga);
            // if state is WAITING_FOR_ROB_CHOOSE_PLAYER (_SC_PIRI), also sends CHOOSEPLAYERREQUEST
            } else {
                // already did ga.takeMonitor()
                handler.endGameTurn(ga, player, true);
            }
        } else {
            /**
             * (TODO) there could be a better feedback message here
             */
            srv.messageToPlayer(c, gn, "You can't discard that many cards.");
        }
    } catch (Throwable e) {
        D.ebugPrintStackTrace(e, "Exception caught");
    }
    ga.releaseMonitor();
}
Also used : SOCPlayer(soc.game.SOCPlayer)

Example 8 with SOCPlayer

use of soc.game.SOCPlayer in project JSettlers2 by jdmonin.

the class SOCGameMessageHandler method handleREJECTOFFER.

/**
 * handle "reject offer" message.
 *
 * @param c  the connection that sent the message
 * @param mes  the message
 * @since 1.0.0
 */
private void handleREJECTOFFER(SOCGame ga, Connection c, final SOCRejectOffer mes) {
    SOCPlayer player = ga.getPlayer(c.getData());
    if (player == null)
        return;
    final String gaName = ga.getName();
    SOCRejectOffer rejectMessage = new SOCRejectOffer(gaName, player.getPlayerNumber());
    srv.messageToGame(gaName, rejectMessage);
    srv.recordGameEvent(gaName, rejectMessage);
}
Also used : SOCPlayer(soc.game.SOCPlayer)

Example 9 with SOCPlayer

use of soc.game.SOCPlayer in project JSettlers2 by jdmonin.

the class SOCGameMessageHandler method handleSIMPLEREQUEST.

/**
 * Handle the "simple request" message.
 * @param c  the connection
 * @param mes  the message
 * @since 1.1.18
 */
private void handleSIMPLEREQUEST(SOCGame ga, Connection c, final SOCSimpleRequest mes) {
    final String gaName = ga.getName();
    SOCPlayer clientPl = ga.getPlayer(c.getData());
    if (clientPl == null)
        return;
    final int pn = mes.getPlayerNumber();
    // probably required for most request types
    final boolean clientIsPN = (pn == clientPl.getPlayerNumber());
    final int reqtype = mes.getRequestType();
    final int cpn = ga.getCurrentPlayerNumber();
    // if true, reply with generic decline (pn = -1, reqtype, 0, 0)
    boolean replyDecline = false;
    switch(reqtype) {
        case SOCSimpleRequest.SC_PIRI_FORT_ATTACK:
            {
                final SOCShip adjac = ga.canAttackPirateFortress();
                if ((!clientIsPN) || (pn != cpn) || (adjac == null) || (adjac.getPlayerNumber() != cpn)) {
                    c.put(SOCSimpleRequest.toCmd(gaName, -1, reqtype, 0, 0));
                    // <--- early return: deny ---
                    return;
                }
                final int prevState = ga.getGameState();
                final SOCPlayer cp = ga.getPlayer(cpn);
                // in case some are lost, we'll announce that
                final int prevNumWarships = cp.getNumWarships();
                final SOCFortress fort = cp.getFortress();
                final int[] res = ga.attackPirateFortress(adjac);
                if (res.length > 1) {
                    // lost 1 or 2 ships adjacent to fortress.  res[1] == adjac.coordinate
                    srv.messageToGame(gaName, new SOCRemovePiece(gaName, adjac));
                    if (res.length > 2)
                        srv.messageToGame(gaName, new SOCRemovePiece(gaName, cpn, SOCPlayingPiece.SHIP, res[2]));
                    final int n = cp.getNumWarships();
                    if (n != prevNumWarships)
                        srv.messageToGame(gaName, new SOCPlayerElement(gaName, cpn, SOCPlayerElement.SET, SOCPlayerElement.SCENARIO_WARSHIP_COUNT, n));
                } else {
                    // player won
                    final int fortStrength = fort.getStrength();
                    srv.messageToGame(gaName, new SOCPieceValue(gaName, fort.getCoordinates(), fortStrength, 0));
                    if (0 == fortStrength)
                        srv.messageToGame(gaName, new SOCPutPiece(gaName, cpn, SOCPlayingPiece.SETTLEMENT, fort.getCoordinates()));
                }
                srv.messageToGame(gaName, new SOCSimpleAction(gaName, cpn, SOCSimpleAction.SC_PIRI_FORT_ATTACK_RESULT, res[0], res.length - 1));
                // check for end of player's turn
                if (!handler.checkTurn(c, ga)) {
                    handler.endGameTurn(ga, cp, false);
                } else {
                    // still player's turn, even if they won
                    final int gstate = ga.getGameState();
                    if (gstate != prevState)
                        // might be OVER, if player won
                        handler.sendGameState(ga);
                }
            }
            break;
        case SOCSimpleRequest.TRADE_PORT_PLACE:
            {
                if (clientIsPN && (pn == cpn)) {
                    final int edge = mes.getValue1();
                    if ((ga.getGameState() == SOCGame.PLACING_INV_ITEM) && ga.canPlacePort(clientPl, edge)) {
                        final int ptype = ga.placePort(edge);
                        // PLAY1 or SPECIAL_BUILDING
                        handler.sendGameState(ga);
                        srv.messageToGame(gaName, new SOCSimpleRequest(gaName, cpn, SOCSimpleRequest.TRADE_PORT_PLACE, edge, ptype));
                    } else {
                        // client will print a text message, no need to send one
                        replyDecline = true;
                    }
                } else {
                    srv.messageToPlayerKeyed(c, gaName, "reply.not.your.turn");
                    replyDecline = true;
                }
            }
            break;
        default:
            // deny unknown types
            replyDecline = true;
            System.err.println("handleSIMPLEREQUEST: Unknown type " + reqtype + " from " + c.getData() + " in game " + ga);
    }
    if (replyDecline)
        c.put(SOCSimpleRequest.toCmd(gaName, -1, reqtype, 0, 0));
}
Also used : SOCShip(soc.game.SOCShip) SOCPlayer(soc.game.SOCPlayer) SOCFortress(soc.game.SOCFortress)

Example 10 with SOCPlayer

use of soc.game.SOCPlayer in project JSettlers2 by jdmonin.

the class SOCGameMessageHandler method handlePICKRESOURCES.

/**
 * handle "discovery pick" (while playing Discovery/Year of Plenty card) / Gold Hex resource pick message.
 *
 * @param c  the connection that sent the message
 * @param mes  the message
 * @since 1.0.0
 */
private void handlePICKRESOURCES(SOCGame ga, Connection c, final SOCPickResources mes) {
    final String gaName = ga.getName();
    final SOCResourceSet rsrcs = mes.getResources();
    ga.takeMonitor();
    final SOCPlayer player = ga.getPlayer(c.getData());
    final int pn;
    if (player != null)
        pn = player.getPlayerNumber();
    else
        // c's client no longer in the game
        pn = -1;
    try {
        if (player == null) {
            // The catch block will print this out semi-nicely
            throw new IllegalArgumentException("player not found in game");
        }
        final int gstate = ga.getGameState();
        if (gstate == SOCGame.WAITING_FOR_DISCOVERY) {
            if (handler.checkTurn(c, ga)) {
                if (ga.canDoDiscoveryAction(rsrcs)) {
                    ga.doDiscoveryAction(rsrcs);
                    handler.reportRsrcGainLoss(gaName, rsrcs, false, false, pn, -1, null, null);
                    srv.messageToGameKeyedSpecial(ga, true, "action.card.discov.received", player.getName(), rsrcs);
                    // "{0} received {1,rsrcs} from the bank."
                    handler.sendGameState(ga);
                } else {
                    // "That is not a legal Year of Plenty pick."
                    srv.messageToPlayerKeyed(c, gaName, "action.card.discov.notlegal");
                }
            } else {
                // "It's not your turn."
                srv.messageToPlayerKeyed(c, gaName, "reply.not.your.turn");
            }
        } else {
            if (ga.canPickGoldHexResources(pn, rsrcs)) {
                final boolean fromInitPlace = ga.isInitialPlacement();
                final boolean fromPirateFleet = ga.isPickResourceIncludingPirateFleet(pn);
                final int prevState = ga.pickGoldHexResources(pn, rsrcs);
                final int newState = ga.getGameState();
                /**
                 * tell everyone what the player gained
                 */
                handler.reportRsrcGainGold(ga, player, pn, rsrcs, false, !fromPirateFleet);
                /**
                 * send the new state, or end turn if was marked earlier as forced
                 * -- for gold during initial placement, current player might also change.
                 */
                if ((gstate != SOCGame.PLAY1) || (newState == SOCGame.WAITING_FOR_DISCARDS) || !ga.isForcingEndTurn()) {
                    if (!fromInitPlace) {
                        handler.sendGameState(ga);
                        if (newState == SOCGame.WAITING_FOR_DISCARDS) {
                            // happens only in scenario _SC_PIRI, when 7 is rolled, player wins against pirate fleet
                            // and has picked their won resource, and then someone must discard
                            handler.sendGameState_sendDiscardRequests(ga, gaName);
                        }
                    } else {
                        switch(newState) {
                            case SOCGame.START1B:
                            case SOCGame.START2B:
                            case SOCGame.START3B:
                                // pl not changed: previously placed settlement, now placing road or ship
                                handler.sendGameState(ga);
                                break;
                            case SOCGame.START1A:
                            case SOCGame.START2A:
                            case SOCGame.START3A:
                            case SOCGame.ROLL_OR_CARD:
                                // Current player probably changed, announce new player if so
                                // with sendTurn and/or SOCRollDicePrompt
                                handler.sendTurnStateAtInitialPlacement(ga, player, c, prevState);
                                break;
                        }
                    }
                } else {
                    // force-end game turn
                    // locking: already did ga.takeMonitor()
                    handler.endGameTurn(ga, player, true);
                }
            } else {
                srv.messageToPlayer(c, gaName, "You can't pick that many resources.");
                final int npick = player.getNeedToPickGoldHexResources();
                if ((npick > 0) && (gstate < SOCGame.OVER))
                    srv.messageToPlayer(c, new SOCSimpleRequest(gaName, pn, SOCSimpleRequest.PROMPT_PICK_RESOURCES, npick));
                else
                    srv.messageToPlayer(c, new SOCPlayerElement(gaName, pn, SOCPlayerElement.SET, SOCPlayerElement.NUM_PICK_GOLD_HEX_RESOURCES, 0));
            }
        }
    } catch (Exception e) {
        D.ebugPrintStackTrace(e, "Exception caught");
    }
    ga.releaseMonitor();
}
Also used : SOCResourceSet(soc.game.SOCResourceSet) SOCPlayer(soc.game.SOCPlayer)

Aggregations

SOCPlayer (soc.game.SOCPlayer)61 SOCGame (soc.game.SOCGame)17 SOCShip (soc.game.SOCShip)12 SOCSettlement (soc.game.SOCSettlement)11 SOCRoad (soc.game.SOCRoad)9 SOCResourceSet (soc.game.SOCResourceSet)8 SOCCity (soc.game.SOCCity)7 SOCBoardLarge (soc.game.SOCBoardLarge)6 SOCFortress (soc.game.SOCFortress)5 ArrayList (java.util.ArrayList)4 SOCBoard (soc.game.SOCBoard)4 Connection (soc.server.genericServer.Connection)4 SOCInventoryItem (soc.game.SOCInventoryItem)3 SOCVillage (soc.game.SOCVillage)3 SQLException (java.sql.SQLException)2 Iterator (java.util.Iterator)2 Stack (java.util.Stack)2 SOCLRPathData (soc.game.SOCLRPathData)2 SOCPlayingPiece (soc.game.SOCPlayingPiece)2 SOCSpecialItem (soc.game.SOCSpecialItem)2