Search in sources :

Example 1 with SOCVillage

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

the class SOCGameMessageHandler method handleROLLDICE.

// / Roll dice and pick resources ///
/**
 * handle "roll dice" message.
 *
 * @param c  the connection that sent the message
 * @param mes  the message
 * @since 1.0.0
 */
private void handleROLLDICE(SOCGame ga, Connection c, final SOCRollDice mes) {
    final String gn = ga.getName();
    ga.takeMonitor();
    try {
        final String plName = c.getData();
        final SOCPlayer pl = ga.getPlayer(plName);
        if ((pl != null) && ga.canRollDice(pl.getPlayerNumber())) {
            /**
             * Roll dice, distribute resources in game
             */
            SOCGame.RollResult roll = ga.rollDice();
            /**
             * Send roll results and then text to client.
             * Note that only the total is sent, not the 2 individual dice.
             * (Only the _SC_PIRI scenario cares about them indivdually, and
             * in that case it prints the result when needed.)
             *
             * If a 7 is rolled, sendGameState will also say who must discard
             * (in a GAMETEXTMSG).
             * If a gold hex is rolled, sendGameState will also say who
             * must pick resources to gain (in a GAMETEXTMSG).
             */
            srv.messageToGame(gn, new SOCDiceResult(gn, ga.getCurrentDice()));
            if (ga.clientVersionLowest < SOCGameTextMsg.VERSION_FOR_DICE_RESULT_INSTEAD) {
                // backwards-compat: this text message is redundant to v2.0.00 and newer clients
                // because they print the roll results from SOCDiceResult.  Use SOCGameTextMsg
                // because pre-2.0.00 clients don't understand SOCGameServerText messages.
                srv.messageToGameForVersions(ga, 0, SOCGameTextMsg.VERSION_FOR_DICE_RESULT_INSTEAD - 1, new SOCGameTextMsg(gn, SOCGameTextMsg.SERVERNAME, // I18N
                plName + " rolled a " + roll.diceA + " and a " + roll.diceB + "."), true);
            }
            // For 7, give visual feedback before sending discard request
            handler.sendGameState(ga);
            if (ga.isGameOptionSet(SOCGameOption.K_SC_PIRI)) {
                // pirate moves on every roll
                srv.messageToGame(gn, new SOCMoveRobber(gn, ga.getCurrentPlayerNumber(), -(((SOCBoardLarge) ga.getBoard()).getPirateHex())));
                if (roll.sc_piri_fleetAttackVictim != null) {
                    final SOCResourceSet loot = roll.sc_piri_fleetAttackRsrcs;
                    final int lootTotal = (loot != null) ? loot.getTotal() : 0;
                    if (lootTotal != 0) {
                        // use same resource-loss messages sent in handleDISCARD
                        final boolean won = (loot.contains(SOCResourceConstants.GOLD_LOCAL));
                        SOCPlayer vic = roll.sc_piri_fleetAttackVictim;
                        final String vicName = vic.getName();
                        final Connection vCon = srv.getConnection(vicName);
                        final int vpn = vic.getPlayerNumber();
                        final int strength = (roll.diceA < roll.diceB) ? roll.diceA : roll.diceB;
                        if (won) {
                            srv.messageToGameKeyed(ga, true, "action.rolled.sc_piri.player.won.pick.free", vicName, strength);
                        // "{0} won against the pirate fleet (strength {1}) and will pick a free resource."
                        } else {
                            /**
                             * tell the victim client that the player lost the resources
                             */
                            handler.reportRsrcGainLoss(gn, loot, true, true, vpn, -1, null, vCon);
                            srv.messageToPlayerKeyedSpecial(vCon, ga, "action.rolled.sc_piri.you.lost.rsrcs.to.fleet", loot, strength);
                            // "You lost {0,rsrcs} to the pirate fleet (strength {1,number})."
                            /**
                             * tell everyone else that the player lost unknown resources
                             */
                            srv.messageToGameExcept(gn, vCon, new SOCPlayerElement(gn, vpn, SOCPlayerElement.LOSE, SOCPlayerElement.UNKNOWN, lootTotal), true);
                            srv.messageToGameKeyedSpecialExcept(ga, true, vCon, "action.rolled.sc_piri.player.lost.rsrcs.to.fleet", vicName, lootTotal, strength);
                        // "Joe lost 1 resource to pirate fleet attack (strength 3)." or
                        // "Joe lost 3 resources to pirate fleet attack (strength 3)."
                        }
                    }
                }
            }
            /**
             * if the roll is not 7, tell players what they got
             * (if 7, sendGameState already told them what they lost).
             */
            if (ga.getCurrentDice() != 7) {
                boolean noPlayersGained = true;
                /**
                 * Clients v2.0.00 and newer get an i18n-neutral SOCDiceResultResources message.
                 * Older clients get a string such as "Joe gets 3 sheep. Mike gets 1 clay."
                 */
                String rollRsrcTxtOldCli = null;
                SOCDiceResultResources rollRsrcMsgNewCli = null;
                if (ga.clientVersionHighest >= SOCDiceResultResources.VERSION_FOR_DICERESULTRESOURCES) {
                    rollRsrcMsgNewCli = SOCDiceResultResources.buildForGame(ga);
                    noPlayersGained = (rollRsrcMsgNewCli == null);
                }
                if (ga.clientVersionLowest < SOCDiceResultResources.VERSION_FOR_DICERESULTRESOURCES) {
                    // Build a string to announce to v1.x.xx clients
                    StringBuffer gainsText = new StringBuffer();
                    // for string spacing; might be false due to loop for new clients in game
                    noPlayersGained = true;
                    for (int pn = 0; pn < ga.maxPlayers; ++pn) {
                        if (!ga.isSeatVacant(pn)) {
                            SOCPlayer pp = ga.getPlayer(pn);
                            SOCResourceSet rsrcs = pp.getRolledResources();
                            if (rsrcs.getKnownTotal() != 0) {
                                if (noPlayersGained)
                                    noPlayersGained = false;
                                else
                                    gainsText.append(" ");
                                gainsText.append(c.getLocalizedSpecial(ga, "_nolocaliz.roll.gets.resources", pp.getName(), rsrcs));
                                // "{0} gets {1,rsrcs}."
                                // get it from any connection's StringManager, because that string is never localized
                                // Announce SOCPlayerElement.GAIN messages
                                handler.reportRsrcGainLoss(gn, rsrcs, false, false, pn, -1, null, null);
                            }
                        }
                    }
                    if (!noPlayersGained)
                        rollRsrcTxtOldCli = gainsText.toString();
                }
                if (noPlayersGained) {
                    String key;
                    if (roll.cloth == null)
                        // "No player gets anything."
                        key = "action.rolled.no.player.gets.anything";
                    else
                        // "No player gets resources."
                        key = "action.rolled.no.player.gets.resources";
                    // debug_printPieceDiceNumbers(ga, message);
                    srv.messageToGameKeyed(ga, true, key);
                } else {
                    if (rollRsrcTxtOldCli == null)
                        srv.messageToGame(gn, rollRsrcMsgNewCli);
                    else if (rollRsrcMsgNewCli == null)
                        srv.messageToGame(gn, rollRsrcTxtOldCli);
                    else {
                        // neither is null: we have old and new clients
                        srv.messageToGameForVersions(ga, 0, (SOCDiceResultResources.VERSION_FOR_DICERESULTRESOURCES - 1), new SOCGameTextMsg(gn, SOCGameTextMsg.SERVERNAME, rollRsrcTxtOldCli), true);
                        srv.messageToGameForVersions(ga, SOCDiceResultResources.VERSION_FOR_DICERESULTRESOURCES, Integer.MAX_VALUE, rollRsrcMsgNewCli, true);
                    }
                    // 
                    for (int pn = 0; pn < ga.maxPlayers; ++pn) {
                        final SOCPlayer pp = ga.getPlayer(pn);
                        Connection playerCon = srv.getConnection(pp.getName());
                        if (playerCon == null)
                            continue;
                        if (pp.getRolledResources().getKnownTotal() == 0)
                            // skip if player didn't gain; before v2.0.00 each player in game got these
                            continue;
                        // send CLAY, ORE, SHEEP, WHEAT, WOOD even if player's amount is 0
                        final SOCResourceSet resources = pp.getResources();
                        final int[] counts = resources.getAmounts(false);
                        if (playerCon.getVersion() >= SOCPlayerElements.MIN_VERSION)
                            srv.messageToPlayer(playerCon, new SOCPlayerElements(gn, pn, SOCPlayerElement.SET, SOCGameHandler.ELEM_RESOURCES, counts));
                        else
                            for (int i = 0; i < counts.length; ++i) srv.messageToPlayer(playerCon, new SOCPlayerElement(gn, pn, SOCPlayerElement.SET, SOCGameHandler.ELEM_RESOURCES[i], counts[i]));
                        if (ga.clientVersionLowest < SOCDiceResultResources.VERSION_FOR_DICERESULTRESOURCES)
                            srv.messageToGame(gn, new SOCResourceCount(gn, pn, resources.getTotal()));
                    // else, already-sent SOCDiceResultResources included players' new resource totals
                    // we'll send gold picks text, PLAYERELEMENT, and SIMPLEREQUEST(PROMPT_PICK_RESOURCES)
                    // after the per-player loop
                    }
                }
                if (roll.cloth != null) {
                    // Send village cloth trade distribution
                    final int coord = roll.cloth[1];
                    final SOCBoardLarge board = (SOCBoardLarge) (ga.getBoard());
                    SOCVillage vi = board.getVillageAtNode(coord);
                    if (vi != null)
                        srv.messageToGame(gn, new SOCPieceValue(gn, coord, vi.getCloth(), 0));
                    if (roll.cloth[0] > 0)
                        // some taken from board general supply
                        srv.messageToGame(gn, new SOCPlayerElement(gn, -1, SOCPlayerElement.SET, SOCPlayerElement.SCENARIO_CLOTH_COUNT, board.getCloth()));
                    // name of first player to receive cloth
                    String clplName = null;
                    // names of all players receiving cloth, if more than one
                    ArrayList<String> clpls = null;
                    for (int i = 2; i < roll.cloth.length; ++i) {
                        if (roll.cloth[i] == 0)
                            // this player didn't receive cloth
                            continue;
                        final int pn = i - 2;
                        final SOCPlayer clpl = ga.getPlayer(pn);
                        srv.messageToGame(gn, new SOCPlayerElement(gn, pn, SOCPlayerElement.SET, SOCPlayerElement.SCENARIO_CLOTH_COUNT, clpl.getCloth()));
                        if (clplName == null) {
                            // first pl to receive cloth
                            clplName = clpl.getName();
                        } else {
                            // second or further player
                            if (clpls == null) {
                                clpls = new ArrayList<String>();
                                clpls.add(clplName);
                            }
                            clpls.add(clpl.getName());
                        }
                    }
                    if (clpls == null)
                        srv.messageToGameKeyed(ga, true, "action.rolled.sc_clvi.received.cloth.1", clplName);
                    else
                        // "{0} received 1 cloth from a village."
                        srv.messageToGameKeyedSpecial(ga, true, "action.rolled.sc_clvi.received.cloth.n", clpls);
                // "{0,list} each received 1 cloth from a village."
                }
                if (ga.getGameState() == SOCGame.WAITING_FOR_PICK_GOLD_RESOURCE)
                    // gold picks text, PLAYERELEMENT, and SIMPLEREQUEST(PROMPT_PICK_RESOURCES)s
                    handler.sendGameState_sendGoldPickAnnounceText(ga, gn, null, roll);
            /*
                       if (D.ebugOn) {
                       for (int i=0; i < SOCGame.MAXPLAYERS; i++) {
                       SOCResourceSet rsrcs = ga.getPlayer(i).getResources();
                       String resourceMessage = "PLAYER "+i+" RESOURCES: ";
                       resourceMessage += rsrcs.getAmount(SOCResourceConstants.CLAY)+" ";
                       resourceMessage += rsrcs.getAmount(SOCResourceConstants.ORE)+" ";
                       resourceMessage += rsrcs.getAmount(SOCResourceConstants.SHEEP)+" ";
                       resourceMessage += rsrcs.getAmount(SOCResourceConstants.WHEAT)+" ";
                       resourceMessage += rsrcs.getAmount(SOCResourceConstants.WOOD)+" ";
                       resourceMessage += rsrcs.getAmount(SOCResourceConstants.UNKNOWN)+" ";
                       messageToGame(gn, new SOCGameTextMsg(gn, SERVERNAME, resourceMessage));
                       }
                       }
                     */
            } else {
                /**
                 * player rolled 7
                 * If anyone needs to discard, prompt them.
                 */
                if (ga.getGameState() == SOCGame.WAITING_FOR_DISCARDS) {
                    handler.sendGameState_sendDiscardRequests(ga, gn);
                } else if (ga.getGameState() == SOCGame.WAITING_FOR_PICK_GOLD_RESOURCE) {
                    // Used in _SC_PIRI, when 7 is rolled and a player wins against the pirate fleet
                    for (int pn = 0; pn < ga.maxPlayers; ++pn) {
                        final SOCPlayer pp = ga.getPlayer(pn);
                        final int numPick = pp.getNeedToPickGoldHexResources();
                        if ((!ga.isSeatVacant(pn)) && (numPick > 0)) {
                            Connection con = srv.getConnection(pp.getName());
                            if (con != null) {
                                srv.messageToGame(gn, new SOCPlayerElement(gn, pn, SOCPlayerElement.SET, SOCPlayerElement.NUM_PICK_GOLD_HEX_RESOURCES, numPick));
                                con.put(SOCSimpleRequest.toCmd(gn, pn, SOCSimpleRequest.PROMPT_PICK_RESOURCES, numPick, 0));
                            }
                        }
                    }
                }
            }
        } else {
            srv.messageToPlayer(c, gn, "You can't roll right now.");
        }
    } catch (Exception e) {
        D.ebugPrintStackTrace(e, "Exception caught at handleROLLDICE" + e);
    }
    ga.releaseMonitor();
}
Also used : SOCVillage(soc.game.SOCVillage) SOCBoardLarge(soc.game.SOCBoardLarge) Connection(soc.server.genericServer.Connection) SOCPlayer(soc.game.SOCPlayer) SOCResourceSet(soc.game.SOCResourceSet) SOCGame(soc.game.SOCGame)

Example 2 with SOCVillage

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

the class SOCDisplaylessPlayerClient method handlePIECEVALUE.

/**
 * Update a village piece's value on the board (cloth remaining) in _SC_CLVI,
 * or a pirate fortress's strength in _SC_PIRI.
 * @since 2.0.00
 */
protected void handlePIECEVALUE(final SOCPieceValue mes) {
    final String gaName = mes.getGame();
    SOCGame ga = games.get(gaName);
    if (ga == null)
        // Not one of our games
        return;
    if (!ga.hasSeaBoard)
        // should not happen
        return;
    final int coord = mes.getParam1();
    final int pv = mes.getParam2();
    if (ga.isGameOptionSet(SOCGameOption.K_SC_CLVI)) {
        SOCVillage vi = ((SOCBoardLarge) (ga.getBoard())).getVillageAtNode(coord);
        if (vi != null)
            vi.setCloth(pv);
    } else if (ga.isGameOptionSet(SOCGameOption.K_SC_PIRI)) {
        SOCFortress fort = ga.getFortress(coord);
        if (fort != null)
            fort.setStrength(pv);
    }
}
Also used : SOCVillage(soc.game.SOCVillage) SOCBoardLarge(soc.game.SOCBoardLarge) SOCFortress(soc.game.SOCFortress) SOCGame(soc.game.SOCGame)

Example 3 with SOCVillage

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

the class SOCPlayerInterface method updateAtPutPiece.

/**
 * Handle updates after putting a piece on the board,
 * or moving a ship that was already placed.
 * Place or move the piece within our {@link SOCGame}
 * and visually on our {@link SOCBoardPanel}.
 *
 * @param mesPn  The piece's player number
 * @param coord  The piece's coordinate.  If <tt>isMove</tt>, the coordinate to move <em>from</em>.
 * @param pieceType  Piece type, like {@link SOCPlayingPiece#CITY}
 * @param isMove   If true, it's a move, not a new placement; valid only for ships.
 * @param moveToCoord  If <tt>isMove</tt>, the coordinate to move <em>to</em>.  Otherwise ignored.
 *
 * @see #updateAtPiecesChanged()
 * @since 2.0.00
 */
public void updateAtPutPiece(final int mesPn, final int coord, final int pieceType, final boolean isMove, final int moveToCoord) {
    // TODO consider more effic way for flushBoardLayoutAndRepaint, without the =null
    final SOCPlayer pl = (pieceType != SOCPlayingPiece.VILLAGE) ? game.getPlayer(mesPn) : null;
    final SOCPlayer oldLongestRoadPlayer = game.getPlayerWithLongestRoad();
    final SOCHandPanel mesHp = (pieceType != SOCPlayingPiece.VILLAGE) ? getPlayerHandPanel(mesPn) : null;
    final boolean[] debugShowPotentials = boardPanel.debugShowPotentials;
    final SOCPlayingPiece pp;
    switch(pieceType) {
        case SOCPlayingPiece.ROAD:
            pp = new SOCRoad(pl, coord, null);
            game.putPiece(pp);
            mesHp.updateValue(PlayerClientListener.UpdateType.Road);
            if (debugShowPotentials[4] || debugShowPotentials[5] || debugShowPotentials[7])
                boardPanel.flushBoardLayoutAndRepaint();
            break;
        case SOCPlayingPiece.SETTLEMENT:
            pp = new SOCSettlement(pl, coord, null);
            game.putPiece(pp);
            mesHp.updateValue(PlayerClientListener.UpdateType.Settlement);
            /**
             * if this is the second initial settlement, then update the resource display
             */
            mesHp.updateValue(PlayerClientListener.UpdateType.ResourceTotalAndDetails);
            if (debugShowPotentials[4] || debugShowPotentials[5] || debugShowPotentials[7] || debugShowPotentials[6])
                boardPanel.flushBoardLayoutAndRepaint();
            break;
        case SOCPlayingPiece.CITY:
            pp = new SOCCity(pl, coord, null);
            game.putPiece(pp);
            mesHp.updateValue(PlayerClientListener.UpdateType.Settlement);
            mesHp.updateValue(PlayerClientListener.UpdateType.City);
            if (debugShowPotentials[4] || debugShowPotentials[5] || debugShowPotentials[7] || debugShowPotentials[6])
                boardPanel.flushBoardLayoutAndRepaint();
            break;
        case SOCPlayingPiece.SHIP:
            pp = new SOCShip(pl, coord, null);
            if (!isMove) {
                game.putPiece(pp);
                mesHp.updateValue(PlayerClientListener.UpdateType.Ship);
            } else {
                game.moveShip((SOCShip) pp, moveToCoord);
                if (mesHp == clientHand)
                    // just in case; it probably wasn't enabled
                    mesHp.disableBankUndoButton();
            }
            if (debugShowPotentials[4] || debugShowPotentials[5] || debugShowPotentials[7])
                boardPanel.flushBoardLayoutAndRepaint();
            break;
        case SOCPlayingPiece.VILLAGE:
            // no need to refresh boardPanel after receiving each village
            pp = new SOCVillage(coord, game.getBoard());
            game.putPiece(pp);
            // <--- Early return: Piece is part of board initial layout, not player info ---
            return;
        case SOCPlayingPiece.FORTRESS:
            pp = new SOCFortress(pl, coord, game.getBoard());
            game.putPiece(pp);
            // <--- Early return: Piece is part of board initial layout, not added during game ---
            return;
        default:
            chatPrintDebug("* Unknown piece type " + pieceType + " at coord 0x" + Integer.toHexString(coord));
            // <--- Early return ---
            return;
    }
    mesHp.updateValue(PlayerClientListener.UpdateType.VictoryPoints);
    boardPanel.repaint();
    buildingPanel.updateButtonStatus();
    if (game.isDebugFreePlacement() && game.isInitialPlacement())
        // update here, since gamestate doesn't change to trigger update
        boardPanel.updateMode();
    if (hasCalledBegan && (game.getGameState() >= SOCGame.START1A))
        playSound(SOUND_PUT_PIECE);
    /**
     * Check for and announce change in longest road; update all players' victory points.
     */
    SOCPlayer newLongestRoadPlayer = game.getPlayerWithLongestRoad();
    if (newLongestRoadPlayer != oldLongestRoadPlayer) {
        updateLongestLargest(true, oldLongestRoadPlayer, newLongestRoadPlayer);
    }
}
Also used : SOCSettlement(soc.game.SOCSettlement) SOCVillage(soc.game.SOCVillage) SOCCity(soc.game.SOCCity) SOCPlayingPiece(soc.game.SOCPlayingPiece) SOCShip(soc.game.SOCShip) SOCPlayer(soc.game.SOCPlayer) SOCFortress(soc.game.SOCFortress) SOCRoad(soc.game.SOCRoad)

Example 4 with SOCVillage

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

the class SOCDisplaylessPlayerClient method handlePUTPIECE.

/**
 * handle the "put piece" message
 *<P>
 * This method is public static for access by
 * {@code SOCRobotBrain.handlePUTPIECE_updateGameData(SOCPutPiece)}.
 * @param mes  the message
 * @param ga  Message's game from {@link SOCPutPiece#getGame()}; if {@code null}, message is ignored
 */
public static void handlePUTPIECE(final SOCPutPiece mes, SOCGame ga) {
    if (ga != null) {
        final int pieceType = mes.getPieceType();
        final int coord = mes.getCoordinates();
        final SOCPlayer pl = (pieceType != SOCPlayingPiece.VILLAGE) ? ga.getPlayer(mes.getPlayerNumber()) : null;
        switch(pieceType) {
            case SOCPlayingPiece.ROAD:
                ga.putPiece(new SOCRoad(pl, coord, null));
                break;
            case SOCPlayingPiece.SETTLEMENT:
                ga.putPiece(new SOCSettlement(pl, coord, null));
                break;
            case SOCPlayingPiece.CITY:
                ga.putPiece(new SOCCity(pl, coord, null));
                break;
            case SOCPlayingPiece.SHIP:
                ga.putPiece(new SOCShip(pl, coord, null));
                break;
            case SOCPlayingPiece.FORTRESS:
                ga.putPiece(new SOCFortress(pl, coord, ga.getBoard()));
                break;
            case SOCPlayingPiece.VILLAGE:
                ga.putPiece(new SOCVillage(coord, ga.getBoard()));
                break;
            default:
                System.err.println("Displayless.handlePUTPIECE: game " + ga.getName() + ": Unknown pieceType " + pieceType);
        }
    }
}
Also used : SOCSettlement(soc.game.SOCSettlement) SOCVillage(soc.game.SOCVillage) SOCCity(soc.game.SOCCity) SOCShip(soc.game.SOCShip) SOCPlayer(soc.game.SOCPlayer) SOCFortress(soc.game.SOCFortress) SOCRoad(soc.game.SOCRoad)

Example 5 with SOCVillage

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

the class SOCBoardPanel method drawBoardEmpty.

/**
 * Draw the whole board (water, hexes, ports, numbers) but no placed pieces.
 * This is drawn once, then stored.
 * If the board layout changes (at start of game or
 * {@link SOCBoardLarge#FOG_HEX fog hex} reveal, for example),
 * call {@link #flushBoardLayoutAndRepaint()} to clear the buffered copy.
 *<P>
 * For scenario option {@link SOCGameOption#K_SC_CLVI _SC_CLVI},
 * <tt>drawBoardEmpty</tt> draws the board's {@link SOCVillage}s.
 *<P>
 * If {@link #panelMarginX} or {@link #panelMarginY} != 0, do not translate {@code g}
 * before calling. This method will internally translate.
 *
 * @param g Graphics, typically from {@link #emptyBoardBuffer}
 * @since 1.1.08
 * @see SOCPlayerInterface#updateAtNewBoard()
 */
private void drawBoardEmpty(Graphics g) {
    // ask for antialiasing if available
    if (g instanceof Graphics2D)
        ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    Set<Integer> landHexShow;
    final int SC_6;
    if (debugShowPotentials[8] && isLargeBoard) {
        landHexShow = ((SOCBoardLarge) board).getLandHexCoordsSet();
        SC_6 = scaleToActual(6);
    } else {
        // almost always null, unless debugging large board
        landHexShow = null;
        // unused unless debugging large board
        SC_6 = 0;
    }
    g.setPaintMode();
    g.setColor(getBackground());
    g.fillRect(0, 0, scaledPanelW, scaledPanelH);
    if (scaledPorts[0] == null) {
        // Check if port graphics are ready.  This probably isn't needed, because
        // doLayout already called position/sizing methods which call rescaleBoard.
        renderPortImages();
    }
    final boolean xlat = (panelMarginX != 0) || (panelMarginY != 0);
    if (xlat)
        g.translate(panelMarginX, panelMarginY);
    // drawHex will set scaledMissedImage if missed.
    if (!isLargeBoard) {
        // Draw water hexes to all edges of the panel;
        // these are outside the board coordinate system.
        boolean isRowOffset = isRotated;
        for (int hy = -deltaY; hy < panelMinBH; hy += deltaY, isRowOffset = !isRowOffset) {
            int hx = 0;
            if (isRowOffset)
                hx -= halfdeltaX;
            for (; hx < panelMinBW; hx += deltaX) if (0 == findHex(hx, hy))
                drawHex(g, hx, hy, SOCBoard.WATER_HEX, -1, -1);
        }
        if (is6player)
            drawPortsRing(g);
        for (int i = 0; i < hexX.length; i++) if ((inactiveHexNums == null) || !inactiveHexNums[i])
            drawHex(g, i);
    } else {
        // Large Board has a rectangular array of hexes.
        // (r,c) are board coordinates.
        // (x,y) are unscaled pixel coordinates.
        // Top border rows:
        final int bMarginX = scaleFromActual(panelMarginX), marginNumHex = (bMarginX + deltaX - 1) / deltaX;
        // Top border ("row -2"): Needed only when panelMarginY is +1 or more "VS" units (1/4 or more of row height)
        if (panelMarginY >= (halfdeltaY / 2)) {
            final int y = -halfdeltaY - deltaY, xmin = -(deltaX * marginNumHex) - halfdeltaX;
            for (int x = xmin; x < panelMinBW; x += deltaX) {
                drawHex(g, x, y, SOCBoard.WATER_HEX, -1, -1);
            }
        }
        // The initial x-coord formula aligns just enough water hexes to cover -panelMarginX.
        for (int x = -(deltaX * marginNumHex); x < panelMinBW; x += deltaX) {
            drawHex(g, x, -halfdeltaY, SOCBoard.WATER_HEX, -1, -1);
        }
        // In-bounds board hexes and bottom border:
        final int bw = board.getBoardWidth(), bh = board.getBoardHeight();
        for (int r = 1, y = halfdeltaY; r < bh || y < (scaledPanelH + HEXY_OFF_SLOPE_HEIGHT); r += 2, y += deltaY) {
            final int rshift = (r << 8);
            int c, x;
            if (((r / 2) % 2) == 1) {
                // odd hex rows start at 1
                c = 1;
                x = 0;
            } else {
                // top row, even rows start at 2
                c = 2;
                x = halfdeltaX;
            }
            if ((panelMarginX != 0) || (x != 0)) {
                // xleft drawn at >= 0 after g.translate for panelMarginX
                for (int xleft = x; xleft > -(panelMarginX + deltaX); xleft -= deltaX) drawHex(g, xleft, y, SOCBoard.WATER_HEX, -1, -1);
            }
            for (; c < bw; c += 2, x += deltaX) {
                final int hexCoord = rshift | c;
                final int hexType = (r < bh) ? board.getHexTypeFromCoord(hexCoord) : SOCBoard.WATER_HEX;
                drawHex(g, x, y, hexType, -1, hexCoord);
                if ((landHexShow != null) && landHexShow.contains(new Integer(hexCoord))) {
                    g.setColor(Color.RED);
                    g.drawRoundRect(scaleToActual(x + (halfdeltaX / 2)), scaleToActual(y + ((halfdeltaY + HEXY_OFF_SLOPE_HEIGHT) / 2) + 1), scaleToActual(halfdeltaX), scaleToActual(halfdeltaY + 1), SC_6, SC_6);
                }
            }
            // If board is narrower than panel, fill in with water
            int xmax = panelMinBW - 1;
            if (panelMarginX < 0)
                xmax -= panelMarginX;
            while (x < xmax) {
                final int hexCoord = rshift | c;
                drawHex(g, x, y, SOCBoard.WATER_HEX, -1, hexCoord);
                c += 2;
                x += deltaX;
            }
        }
        // All ports
        drawPorts_LargeBoard(g);
        // For scenario _SC_PIRI, check for the Pirate Path and Lone Settlement locations.
        // Draw path only if the pirate fleet is still on the board
        // Draw our player's permitted sea edges for ships, if restricted
        {
            final int[] ppath = ((SOCBoardLarge) board).getAddedLayoutPart("PP");
            if ((ppath != null) && (0 != ((SOCBoardLarge) board).getPirateHex()))
                drawBoardEmpty_drawPiratePath(g, ppath);
            final int[] ls = ((SOCBoardLarge) board).getAddedLayoutPart("LS");
            if (ls != null) {
                for (int pn = 0; pn < ls.length; ++pn) if (ls[pn] != 0)
                    drawSettlement(g, ls[pn], pn, false, true);
            }
            final HashSet<Integer> lse = (player != null) ? player.getRestrictedLegalShips() : null;
            if (lse != null)
                drawSeaEdgeLines(g, null, lse);
        }
        // For scenario _SC_FTRI, draw markers at the SVP edges and dev card edges (added layout parts "CE", "VE")
        if (((SOCBoardLarge) board).hasSpecialEdges())
            drawBoardEmpty_specialEdges(g);
        // For scenario _SC_CLVI, draw the cloth villages
        HashMap<Integer, SOCVillage> villages = ((SOCBoardLarge) board).getVillages();
        if (villages != null) {
            Iterator<SOCVillage> villIter = villages.values().iterator();
            while (villIter.hasNext()) drawVillage(g, villIter.next());
        }
        // For scenario _SC_WOND, draw special nodes (layout parts N1, N2, N3)
        if (game.isGameOptionSet(SOCGameOption.K_SC_WOND)) {
            // brown
            drawBoardEmpty_specialNodes(g, "N1", new Color(180, 90, 40));
            // violet
            drawBoardEmpty_specialNodes(g, "N2", new Color(120, 40, 120));
            drawBoardEmpty_specialNodes(g, "N3", Color.RED);
        }
        // check debugShowPotentials[0 - 9]
        drawBoardEmpty_drawDebugShowPotentials(g);
    }
    if (xlat)
        g.translate(-panelMarginX, -panelMarginY);
    if (scaledMissedImage) {
        // With recent board resize, one or more rescaled images still hasn't
        // been completed after 7 seconds.  We've asked for a new scaled copy
        // of this image.  Repaint now, and repaint 3 seconds later.
        // (The delay gives time for the new scaling to complete.)
        scaledAt = System.currentTimeMillis();
        repaint();
        new DelayedRepaint(this).start();
    }
}
Also used : SOCVillage(soc.game.SOCVillage) SOCBoardLarge(soc.game.SOCBoardLarge) Color(java.awt.Color) Graphics2D(java.awt.Graphics2D) HashSet(java.util.HashSet)

Aggregations

SOCVillage (soc.game.SOCVillage)6 SOCFortress (soc.game.SOCFortress)4 SOCBoardLarge (soc.game.SOCBoardLarge)3 SOCPlayer (soc.game.SOCPlayer)3 SOCCity (soc.game.SOCCity)2 SOCGame (soc.game.SOCGame)2 SOCRoad (soc.game.SOCRoad)2 SOCSettlement (soc.game.SOCSettlement)2 SOCShip (soc.game.SOCShip)2 Color (java.awt.Color)1 Graphics (java.awt.Graphics)1 Graphics2D (java.awt.Graphics2D)1 Image (java.awt.Image)1 BufferedImage (java.awt.image.BufferedImage)1 HashSet (java.util.HashSet)1 SOCPlayingPiece (soc.game.SOCPlayingPiece)1 SOCResourceSet (soc.game.SOCResourceSet)1 Connection (soc.server.genericServer.Connection)1