Search in sources :

Example 1 with SOCGame

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

the class SOCGameListAtServer method createGame.

/**
 * create a new game, and add to the list; game will expire in {@link #GAME_TIME_EXPIRE_MINUTES} minutes.
 * If a game already exists (per {@link #isGame(String)}), do nothing.
 *
 * @param gaName  the name of the game
 * @param gaOwner the game owner/creator's player name, or null (added in 1.1.10)
 * @param gaLocaleStr  the game creator's locale, to later set {@link SOCGame#hasMultiLocales} if needed (added in 2.0.00)
 * @param gaOpts  if game has options, its {@link SOCGameOption}s; otherwise null.
 *                Must already be validated, by calling
 *                {@link SOCGameOption#adjustOptionsToKnown(Map, Map, boolean)}
 *                with <tt>doServerPreadjust</tt> true.
 *                That call is also needed to add any {@code "SC"} options into {@code gaOpts}.
 * @param handler  Game type handler for this game
 * @return new game object, or null if it already existed
 * @throws IllegalArgumentException  if {@code handler} is null
 */
public synchronized SOCGame createGame(final String gaName, final String gaOwner, final String gaLocaleStr, final Map<String, SOCGameOption> gaOpts, final GameHandler handler) throws IllegalArgumentException {
    if (isGame(gaName))
        return null;
    if (handler == null)
        throw new IllegalArgumentException("handler");
    // Double-check class in case server is started at client after a client SOCGame.
    if ((SOCGame.boardFactory == null) || !(SOCGame.boardFactory instanceof SOCBoardAtServer.BoardFactoryAtServer))
        SOCGame.boardFactory = new SOCBoardAtServer.BoardFactoryAtServer();
    Vector<Connection> members = new Vector<Connection>();
    gameMembers.put(gaName, members);
    SOCGame game = new SOCGame(gaName, gaOpts);
    if (gaOwner != null)
        game.setOwner(gaOwner, gaLocaleStr);
    // set the expiration to 90 min. from now
    game.setExpiration(game.getStartTime().getTime() + (60 * 1000 * GAME_TIME_EXPIRE_MINUTES));
    // also creates MutexFlag
    gameInfo.put(gaName, new GameInfoAtServer(game.getGameOptions(), handler));
    gameData.put(gaName, game);
    return game;
}
Also used : Connection(soc.server.genericServer.Connection) SOCGame(soc.game.SOCGame) Vector(java.util.Vector)

Example 2 with SOCGame

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

the class SOCGameListAtServer method addMember.

/**
 * add a member to the game.
 * Also checks client's version against game's current range of client versions.
 * Please call {@link #takeMonitorForGame(String)} before calling this.
 *
 * @param  gaName   the name of the game
 * @param  conn     the member's connection; version should already be set
 */
public synchronized void addMember(Connection conn, String gaName) {
    Vector<Connection> members = getMembers(gaName);
    if ((members != null) && (!members.contains(conn))) {
        final boolean firstMember = members.isEmpty();
        members.addElement(conn);
        // Check version range
        SOCGame ga = getGameData(gaName);
        final int cliVers = conn.getVersion();
        if (firstMember) {
            ga.clientVersionLowest = cliVers;
            ga.clientVersionHighest = cliVers;
            ga.hasOldClients = (cliVers < Version.versionNumber());
        } else {
            final int cliLowestAlready = ga.clientVersionLowest;
            final int cliHighestAlready = ga.clientVersionHighest;
            if (cliVers < cliLowestAlready) {
                ga.clientVersionLowest = cliVers;
                if (cliVers < Version.versionNumber())
                    ga.hasOldClients = true;
            }
            if (cliVers > cliHighestAlready) {
                ga.clientVersionHighest = cliVers;
            }
        }
        if (!ga.hasMultiLocales) {
            final String gaLocale = ga.getOwnerLocale();
            if (gaLocale != null) {
                final SOCClientData scd = (SOCClientData) conn.getAppData();
                if ((scd != null) && (scd.localeStr != null) && !gaLocale.equals(scd.localeStr))
                    // client's locale differs from other game members'
                    ga.hasMultiLocales = true;
            }
        }
    }
}
Also used : Connection(soc.server.genericServer.Connection) SOCGame(soc.game.SOCGame)

Example 3 with SOCGame

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

the class SOCGameListAtServer method memberGames.

/**
 * List of games containing this member.
 *
 * @param c  Connection
 * @param firstGameName  Game name that should be first element of list
 *           (if <tt>newConn</tt> is a member of it), or null.
 * @return The games, in no particular order (past firstGameName),
 *           or a 0-length Vector, if member isn't in any game.
 *
 * @see #replaceMemberAllGames(Connection, Connection)
 * @since 1.1.08
 */
public List<SOCGame> memberGames(Connection c, final String firstGameName) {
    List<SOCGame> cGames = new ArrayList<SOCGame>();
    synchronized (gameData) {
        SOCGame firstGame = null;
        if (firstGameName != null) {
            firstGame = getGameData(firstGameName);
            if (firstGame != null) {
                Vector<?> members = getMembers(firstGameName);
                if ((members != null) && members.contains(c))
                    cGames.add(firstGame);
            }
        }
        for (SOCGame ga : getGamesData()) {
            if (ga == firstGame)
                continue;
            Vector<?> members = getMembers(ga.getName());
            if ((members == null) || !members.contains(c))
                continue;
            cGames.add(ga);
        }
    }
    return cGames;
}
Also used : ArrayList(java.util.ArrayList) SOCGame(soc.game.SOCGame)

Example 4 with SOCGame

use of soc.game.SOCGame 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 5 with SOCGame

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

the class SOCRobotClient method handleRESETBOARDAUTH.

/**
 * handle board reset
 * (new game with same players, same game name).
 * Destroy old Game object.
 * Unlike <tt>SOCDisplaylessPlayerClient.handleRESETBOARDAUTH</tt>, don't call {@link SOCGame#resetAsCopy()}.
 *<P>
 * Take robotbrain out of old game, don't yet put it in new game.
 * Let server know we've done so, by sending LEAVEGAME via {@link #leaveGame(SOCGame, String, boolean, boolean)}.
 * Server will soon send a BOTJOINGAMEREQUEST if we should join the new game.
 *
 * @param mes  the message
 *
 * @see soc.server.SOCServer#resetBoardAndNotify(String, int)
 * @see #handleBOTJOINGAMEREQUEST(SOCBotJoinGameRequest)
 */
@Override
protected void handleRESETBOARDAUTH(SOCResetBoardAuth mes) {
    D.ebugPrintln("**** handleRESETBOARDAUTH ****");
    String gname = mes.getGame();
    SOCGame ga = games.get(gname);
    if (ga == null)
        // Not one of our games
        return;
    SOCRobotBrain brain = robotBrains.get(gname);
    if (brain != null)
        brain.kill();
    // Same as in handleROBOTDISMISS
    leaveGame(ga, "resetboardauth", false, false);
    ga.destroyGame();
}
Also used : SOCGame(soc.game.SOCGame)

Aggregations

SOCGame (soc.game.SOCGame)60 SOCPlayer (soc.game.SOCPlayer)17 Connection (soc.server.genericServer.Connection)7 SOCBoardLarge (soc.game.SOCBoardLarge)5 MissingResourceException (java.util.MissingResourceException)3 Vector (java.util.Vector)3 SOCBoard (soc.game.SOCBoard)3 StringConnection (soc.server.genericServer.StringConnection)3 SQLException (java.sql.SQLException)2 HashMap (java.util.HashMap)2 SOCResourceSet (soc.game.SOCResourceSet)2 SOCShip (soc.game.SOCShip)2 SOCTradeOffer (soc.game.SOCTradeOffer)2 SOCVillage (soc.game.SOCVillage)2 SOCGameBoardReset (soc.util.SOCGameBoardReset)2 Color (java.awt.Color)1 IOException (java.io.IOException)1 InterruptedIOException (java.io.InterruptedIOException)1 ArrayList (java.util.ArrayList)1 EnumMap (java.util.EnumMap)1