use of soc.server.genericServer.Connection in project JSettlers2 by jdmonin.
the class SOCServer method messageToGameExcept.
/**
* Send a message to all the connections in a game, excluding one.
*
* @param gn the name of the game
* @param ex the excluded connection, or null
* @param mes the message
* @param takeMon Should this method take and release
* game's monitor via {@link SOCGameList#takeMonitorForGame(String)} ?
* @see #messageToGameExcept(String, Connection, String, boolean)
* @see #messageToGameExcept(String, List, SOCMessage, boolean)
* @see #messageToGameForVersionsExcept(SOCGame, int, int, Connection, SOCMessage, boolean)
*/
public void messageToGameExcept(String gn, Connection ex, SOCMessage mes, boolean takeMon) {
if (takeMon)
gameList.takeMonitorForGame(gn);
try {
Vector<Connection> v = gameList.getMembers(gn);
if (v != null) {
// D.ebugPrintln("M2GE - "+mes);
final String mesCmd = mes.toCmd();
Enumeration<Connection> menum = v.elements();
while (menum.hasMoreElements()) {
Connection con = menum.nextElement();
if ((con == null) || (con == ex))
continue;
// currentGameEventRecord.addMessageOut(new SOCMessageRecord(mes, "SERVER", con.getData()));
con.put(mesCmd);
}
}
} catch (Exception e) {
D.ebugPrintStackTrace(e, "Exception in messageToGameExcept");
}
if (takeMon)
gameList.releaseMonitorForGame(gn);
}
use of soc.server.genericServer.Connection in project JSettlers2 by jdmonin.
the class SOCServer method messageToGame.
/**
* Send a server text message to the given game.
* Equivalent to: messageToGame(ga, new SOCGameServerText(ga, txt));
*<P>
* Do not pass SOCSomeMessage.toCmd() into this method; the message type number
* will be GAMESERVERTEXT, not the desired SOMEMESSAGE.
*<P>
* Client versions older than v2.0.00 will be sent
* {@link SOCGameTextMsg}(ga, {@link #SERVERNAME}, txt).
*<P>
* <b>Locks:</b> Takes, releases {@link SOCGameList#takeMonitorForGame(String)}.
*
* @param ga the name of the game
* @param txt the message text to send. If
* text begins with ">>>", the client should consider this
* an urgent message, and draw the user's attention in some way.
* (See {@link #messageToGameUrgent(String, String)})
* @see #messageToGameKeyed(SOCGame, boolean, String)
* @see #messageToGameKeyed(SOCGame, boolean, String, Object...)
* @see #messageToGame(String, SOCMessage)
* @see #messageToGameWithMon(String, SOCMessage)
* @see #messageToGameExcept(String, Connection, String, boolean)
* @since 1.1.08
*/
public void messageToGame(final String ga, final String txt) {
final String gameServTxtMsg = SOCGameServerText.toCmd(ga, txt);
gameList.takeMonitorForGame(ga);
try {
Vector<Connection> v = gameList.getMembers(ga);
if (v != null) {
Enumeration<Connection> menum = v.elements();
while (menum.hasMoreElements()) {
Connection c = menum.nextElement();
if (c != null) {
if (c.getVersion() >= SOCGameServerText.VERSION_FOR_GAMESERVERTEXT)
c.put(gameServTxtMsg);
else
c.put(SOCGameTextMsg.toCmd(ga, SERVERNAME, txt));
}
}
}
} catch (Throwable e) {
D.ebugPrintStackTrace(e, "Exception in messageToGame");
}
gameList.releaseMonitorForGame(ga);
}
use of soc.server.genericServer.Connection in project JSettlers2 by jdmonin.
the class SOCServer method impl_messageToGameKeyedSpecial.
/**
* Implement {@link #messageToGameKeyed(SOCGame, boolean, String, Object...)},
* {@code messageToGameKeyedSpecial}, and {@code messageToGameKeyedSpecialExcept}.
*
* @param ga the game object
* @param takeMon Should this method take and release
* game's monitor via {@link SOCGameList#takeMonitorForGame(String)} ?
* True unless caller already holds that monitor.
* @param members Game members to send to, from {@link SOCGameListAtServer#getMembers(String)}.
* Any member in this list with null locale (such as robots) will be skipped and not sent the message.
* If we're excluding several members of the game, make a new list from getMembers, remove them from
* that list, then pass it to this method.
* Returns immediately if {@code null}.
* @param ex the excluded connection, or {@code null}
* @param fmtSpecial Should this method call {@link SOCStringManager#getSpecial(SOCGame, String, Object...)}
* instead of the usual {@link SOCStringManager#get(String, Object...)} ?
* True if called from {@code messageToGameKeyedSpecial*}, false from other
* {@code messageToGameKeyed} methods.
* @param key the message localization key, from {@link SOCStringManager#get(String)}, to look up and send text of.
* If its localized text begins with ">>>", the client should consider this
* an urgent message, and draw the user's attention in some way.
* (See {@link #messageToGameUrgent(String, String)})
* @param params Objects to use with <tt>{0}</tt>, <tt>{1}</tt>, etc in the localized string
* by calling {@link MessageFormat#format(String, Object...)}.
* <P>
* If {@code fmtSpecial}, these objects can include {@link SOCResourceSet} or pairs of
* Integers for a resource count and type; see {@link SOCStringManager#getSpecial(SOCGame, String, Object...)}.
* @throws MissingResourceException if no string can be found for {@code key}; this is a RuntimeException
* @throws IllegalArgumentException if the localized pattern string has a parse error (closing '}' brace without opening '{' brace, etc)
* @since 2.0.00
*/
private final void impl_messageToGameKeyedSpecial(SOCGame ga, final boolean takeMon, final List<Connection> members, final Connection ex, final boolean fmtSpecial, final String key, final Object... params) throws MissingResourceException, IllegalArgumentException {
if (members == null)
return;
// Very similar code to messageToGameKeyedType:
// If you change code here, change it there too.
// Indentation within try/catch matches messageToGameKeyedType's.
final boolean hasMultiLocales = ga.hasMultiLocales;
final String gaName = ga.getName();
if (takeMon)
gameList.takeMonitorForGame(gaName);
try {
Iterator<Connection> miter = members.iterator();
// as rendered for previous client during loop
String gameTextMsg = null, gameTxtLocale = null;
while (miter.hasNext()) {
Connection c = miter.next();
if ((c == null) || (c == ex))
continue;
final String cliLocale = c.getI18NLocale();
if (cliLocale == null)
// skip bots
continue;
if ((gameTextMsg == null) || (hasMultiLocales && !cliLocale.equals(gameTxtLocale))) {
if (fmtSpecial)
gameTextMsg = SOCGameServerText.toCmd(gaName, c.getLocalizedSpecial(ga, key, params));
else
gameTextMsg = SOCGameServerText.toCmd(gaName, (params != null) ? c.getLocalized(key, params) : c.getLocalized(key));
gameTxtLocale = cliLocale;
}
if ((c.getVersion() >= SOCGameServerText.VERSION_FOR_GAMESERVERTEXT) && (gameTextMsg != null))
c.put(gameTextMsg);
else // old client (this is uncommon) needs a different message type
if (fmtSpecial)
c.put(SOCGameTextMsg.toCmd(gaName, SERVERNAME, c.getLocalizedSpecial(ga, key, params)));
else
c.put(SOCGameTextMsg.toCmd(gaName, SERVERNAME, (params != null) ? c.getLocalized(key, params) : c.getLocalized(key)));
}
} catch (Throwable e) {
D.ebugPrintStackTrace(e, (fmtSpecial) ? "Exception in messageToGameKeyedSpecial" : "Exception in messageToGameKeyed");
}
if (takeMon)
gameList.releaseMonitorForGame(gaName);
}
use of soc.server.genericServer.Connection in project JSettlers2 by jdmonin.
the class SOCServer method readyGameAskRobotsJoin.
/**
* Fill all the unlocked empty seats with robots, by asking them to join.
* Builds a set of the {@link Connection}s of robots asked to join,
* and adds it to the {@code robotJoinRequests} table.
* Game state should be {@code READY}.
*<P>
* At most {@link SOCGame#getAvailableSeatCount()} robots will
* be asked. If third-party bots are connected to the server,
* optional property {@link #PROP_JSETTLERS_BOTS_PERCENT3P} can
* set a goal for the minimum percentage of third-party bots in
* the game; see its javadoc.
*<P>
* Called by {@link SOCServerMessageHandler#handleSTARTGAME(Connection, SOCStartGame) handleSTARTGAME},
* {@link #resetBoardAndNotify(String, int) resetBoardAndNotify}.
*<P>
* Once the robots have all responded (from their own threads/clients)
* and joined up, the game can begin.
*<P>
* Before v1.1.00, this method was part of {@code handleSTARTGAME}.
*
* @param ga Game to ask robots to join
* @param robotSeats If robotSeats is null, robots are randomly selected.
* If non-null, a MAXPLAYERS-sized array of Connections.
* Any vacant non-locked seat, with index i,
* is filled with the robot whose connection is robotSeats[i].
* Other indexes should be null, and won't be used.
* @param maxBots Maximum number of bots to add, or 0 to fill all empty seats
*
* @throws IllegalStateException if {@link SOCGame#getGameState() ga.gamestate} is not READY,
* or if {@link SOCGame#getClientVersionMinRequired() ga.version} is
* somehow newer than server's version (which is assumed to be robots' version).
* @throws IllegalArgumentException if robotSeats is not null but wrong length,
* or if a robotSeat element is null but that seat wants a robot (vacant non-locked).
* @since 1.1.00
*/
void readyGameAskRobotsJoin(SOCGame ga, Connection[] robotSeats, final int maxBots) throws IllegalStateException, IllegalArgumentException {
if (ga.getGameState() != SOCGame.READY)
throw new IllegalStateException("SOCGame state not READY: " + ga.getGameState());
if (ga.getClientVersionMinRequired() > Version.versionNumber())
throw new IllegalStateException("SOCGame version somehow newer than server and robots, it's " + ga.getClientVersionMinRequired());
// These bots will be asked to join.
// Key = bot Connection, value = seat number as {@link Integer} like in SOCServer.robotJoinRequests
Hashtable<Connection, Object> robotsRequested = null;
int[] robotIndexes = null;
if (robotSeats == null) {
// shuffle the indexes to distribute load
robotIndexes = robotShuffleForJoin();
} else {
// robotSeats not null: check length
if (robotSeats.length != ga.maxPlayers)
throw new IllegalArgumentException("robotSeats Length must be MAXPLAYERS");
}
final String gname = ga.getName();
final Map<String, SOCGameOption> gopts = ga.getGameOptions();
int seatsOpen = ga.getAvailableSeatCount();
if ((maxBots > 0) && (maxBots < seatsOpen))
seatsOpen = maxBots;
int idx = 0;
Connection[] robotSeatsConns = new Connection[ga.maxPlayers];
for (int i = 0; (i < ga.maxPlayers) && (seatsOpen > 0); i++) {
if (ga.isSeatVacant(i) && (ga.getSeatLock(i) == SOCGame.SeatLockState.UNLOCKED)) {
/**
* fetch a robot player; game will start when all bots have arrived.
* Similar to SOCGameHandler.findRobotAskJoinGame (called from SGH.leaveGame),
* where a player has left and must be replaced by a bot.
*/
if (idx < robots.size()) {
// "Fetching a robot player..."
messageToGameKeyed(ga, true, "member.bot.join.fetching");
Connection robotConn;
if (robotSeats != null) {
robotConn = robotSeats[i];
if (robotConn == null)
throw new IllegalArgumentException("robotSeats[" + i + "] was needed but null");
} else {
robotConn = robots.get(robotIndexes[idx]);
}
idx++;
--seatsOpen;
robotSeatsConns[i] = robotConn;
/**
* record the request
*/
if (robotsRequested == null)
robotsRequested = new Hashtable<Connection, Object>();
robotsRequested.put(robotConn, Integer.valueOf(i));
}
}
}
if (robotsRequested != null) {
// request third-party bots, if available and wanted
final int reqPct3p = getConfigIntProperty(PROP_JSETTLERS_BOTS_PERCENT3P, 0);
if (reqPct3p > 0)
readyGameAskRobotsMix3p(reqPct3p, robotsRequested, robotSeatsConns);
// we know robotRequests isn't empty,
// so add to the request table
robotJoinRequests.put(gname, robotsRequested);
// now, make the requests
for (int i = 0; i < ga.maxPlayers; ++i) {
if (robotSeatsConns[i] != null) {
D.ebugPrintln("@@@ JOIN GAME REQUEST for " + robotSeatsConns[i].getData());
robotSeatsConns[i].put(SOCBotJoinGameRequest.toCmd(gname, i, gopts));
}
}
}
}
use of soc.server.genericServer.Connection in project JSettlers2 by jdmonin.
the class SOCServer method messageToGameExcept.
/**
* Send a message to all the connections in a game, excluding some.
*
* @param gn the name of the game
* @param ex the list of excluded connections; not {@code null}
* @param mes the message
* @param takeMon Should this method take and release
* game's monitor via {@link SOCGameList#takeMonitorForGame(String)} ?
* @see #messageToGameExcept(String, Connection, SOCMessage, boolean)
*/
public void messageToGameExcept(final String gn, final List<Connection> ex, final SOCMessage mes, final boolean takeMon) {
if (takeMon)
gameList.takeMonitorForGame(gn);
try {
Vector<Connection> v = gameList.getMembers(gn);
if (v != null) {
// D.ebugPrintln("M2GE - "+mes);
final String mesCmd = mes.toCmd();
Enumeration<Connection> menum = v.elements();
while (menum.hasMoreElements()) {
Connection con = menum.nextElement();
if ((con != null) && !ex.contains(con)) {
// currentGameEventRecord.addMessageOut(new SOCMessageRecord(mes, "SERVER", con.getData()));
con.put(mesCmd);
}
}
}
} catch (Exception e) {
D.ebugPrintStackTrace(e, "Exception in messageToGameExcept");
}
if (takeMon)
gameList.releaseMonitorForGame(gn);
}
Aggregations