Hold on to your seats kids, it's another installment of "A Boy and His
Blowtorch". Refactored GameConfig and the EZ game framework, cleaning up some old cruft from GameConfig (which will break other projects and which I'll fix ASAP) and moved the XML based configuration system from ToyBox into EZGame. git-svn-id: svn+ssh://src.earth.threerings.net/vilya/trunk@286 c613c5cb-e716-0410-b11b-feb51c14d237
This commit is contained in:
@@ -58,20 +58,17 @@ import com.threerings.parlor.server.ParlorSender;
|
||||
import com.threerings.util.MessageBundle;
|
||||
|
||||
/**
|
||||
* The game manager handles the server side management of a game. It
|
||||
* manipulates the game state in accordance with the logic of the game
|
||||
* flow and generally manages the whole game playing process.
|
||||
* The game manager handles the server side management of a game. It manipulates the game state in
|
||||
* accordance with the logic of the game flow and generally manages the whole game playing process.
|
||||
*
|
||||
* <p> The game manager extends the place manager because games are
|
||||
* implicitly played in a location, the players of the game implicitly
|
||||
* bodies in that location.
|
||||
* <p> The game manager extends the place manager because games are implicitly played in a
|
||||
* location, the players of the game implicitly bodies in that location.
|
||||
*/
|
||||
public class GameManager extends PlaceManager
|
||||
implements ParlorCodes, GameCodes
|
||||
{
|
||||
/**
|
||||
* Returns the configuration object for the game being managed by this
|
||||
* manager.
|
||||
* Returns the configuration object for the game being managed by this manager.
|
||||
*/
|
||||
public GameConfig getGameConfig ()
|
||||
{
|
||||
@@ -81,19 +78,19 @@ public class GameManager extends PlaceManager
|
||||
/**
|
||||
* A convenience method for getting the game type.
|
||||
*/
|
||||
public byte getGameType ()
|
||||
public int getMatchType ()
|
||||
{
|
||||
return _gameconfig.getGameType();
|
||||
return _gameconfig.getMatchType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given player to the game at the first available player
|
||||
* index. This should only be called before the game is started, and
|
||||
* is most likely to be used to add players to party games.
|
||||
* Adds the given player to the game at the first available player index. This should only be
|
||||
* called before the game is started, and is most likely to be used to add players to party
|
||||
* games.
|
||||
*
|
||||
* @param player the username of the player to add to this game.
|
||||
* @return the player index at which the player was added, or
|
||||
* <code>-1</code> if the player could not be added to the game.
|
||||
* @return the player index at which the player was added, or <code>-1</code> if the player
|
||||
* could not be added to the game.
|
||||
*/
|
||||
public int addPlayer (Name player)
|
||||
{
|
||||
@@ -108,10 +105,9 @@ public class GameManager extends PlaceManager
|
||||
|
||||
// sanity-check the player index
|
||||
if (pidx == -1) {
|
||||
Log.warning("Couldn't find free player index for player " +
|
||||
"[game=" + where() + ", player=" + player +
|
||||
", players=" + StringUtil.toString(_gameobj.players) +
|
||||
"].");
|
||||
Log.warning("Couldn't find free player index for player [game=" + where() +
|
||||
", player=" + player +
|
||||
", players=" + StringUtil.toString(_gameobj.players) + "].");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -120,9 +116,8 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given player to the game at the specified player index.
|
||||
* This should only be called before the game is started, and is most
|
||||
* likely to be used to add players to party games.
|
||||
* Adds the given player to the game at the specified player index. This should only be called
|
||||
* before the game is started, and is most likely to be used to add players to party games.
|
||||
*
|
||||
* @param player the username of the player to add to this game.
|
||||
* @param pidx the player index at which the player is to be added.
|
||||
@@ -132,34 +127,31 @@ public class GameManager extends PlaceManager
|
||||
{
|
||||
// make sure the specified player index is valid
|
||||
if (pidx < 0 || pidx >= getPlayerSlots()) {
|
||||
Log.warning("Attempt to add player at an invalid index " +
|
||||
"[game=" + where() + ", player=" + player +
|
||||
", pidx=" + pidx + "].");
|
||||
Log.warning("Attempt to add player at an invalid index [game=" + where() +
|
||||
", player=" + player + ", pidx=" + pidx + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
// make sure the player index is available
|
||||
if (_gameobj.players[pidx] != null) {
|
||||
Log.warning("Attempt to add player at occupied index " +
|
||||
"[game=" + where() + ", player=" + player +
|
||||
", pidx=" + pidx + "].");
|
||||
Log.warning("Attempt to add player at occupied index [game=" + where() +
|
||||
", player=" + player + ", pidx=" + pidx + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
// make sure the player isn't already somehow a part of the game
|
||||
// to avoid any potential badness that might ensue if we added
|
||||
// them more than once
|
||||
// make sure the player isn't already somehow a part of the game to avoid any potential
|
||||
// badness that might ensue if we added them more than once
|
||||
if (_gameobj.getPlayerIndex(player) != -1) {
|
||||
Log.warning("Attempt to add player to game that they're already " +
|
||||
"playing [game=" + where() + ", player=" + player + "].");
|
||||
Log.warning("Attempt to add player to game that they're already playing " +
|
||||
"[game=" + where() + ", player=" + player + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
// get the player's body object
|
||||
BodyObject bobj = CrowdServer.lookupBody(player);
|
||||
if (bobj == null) {
|
||||
Log.warning("Unable to get body object while adding player " +
|
||||
"[game=" + where() + ", player=" + player + "].");
|
||||
Log.warning("Unable to get body object while adding player [game=" + where() +
|
||||
", player=" + player + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -179,9 +171,9 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the given player from the game. This is most likely to be
|
||||
* used to allow players involved in a party game to leave the game
|
||||
* early-on if they realize they'd rather not play for some reason.
|
||||
* Removes the given player from the game. This is most likely to be used to allow players
|
||||
* involved in a party game to leave the game early-on if they realize they'd rather not play
|
||||
* for some reason.
|
||||
*
|
||||
* @param player the username of the player to remove from this game.
|
||||
* @return true if the player was successfully removed, false if not.
|
||||
@@ -193,10 +185,9 @@ public class GameManager extends PlaceManager
|
||||
|
||||
// sanity-check the player index
|
||||
if (pidx == -1) {
|
||||
Log.warning("Attempt to remove non-player from players list " +
|
||||
"[game=" + where() + ", player=" + player +
|
||||
", players=" + StringUtil.toString(_gameobj.players) +
|
||||
"].");
|
||||
Log.warning("Attempt to remove non-player from players list [game=" + where() +
|
||||
", player=" + player +
|
||||
", players=" + StringUtil.toString(_gameobj.players) + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -221,9 +212,8 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the player at the specified index and calls {@link
|
||||
* #playerWasReplaced} to let derived classes and delegates know
|
||||
* what's going on.
|
||||
* Replaces the player at the specified index and calls {@link #playerWasReplaced} to let
|
||||
* derived classes and delegates know what's going on.
|
||||
*/
|
||||
public void replacePlayer (final int pidx, final Name player)
|
||||
{
|
||||
@@ -236,15 +226,14 @@ public class GameManager extends PlaceManager
|
||||
// notify our delegates
|
||||
applyToDelegates(new DelegateOp() {
|
||||
public void apply (PlaceManagerDelegate delegate) {
|
||||
((GameManagerDelegate)delegate).playerWasReplaced(
|
||||
pidx, oplayer, player);
|
||||
((GameManagerDelegate)delegate).playerWasReplaced(pidx, oplayer, player);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user object for the player with the specified index or
|
||||
* null if the player at that index is not online.
|
||||
* Returns the user object for the player with the specified index or null if the player at
|
||||
* that index is not online.
|
||||
*/
|
||||
public BodyObject getPlayer (int playerIdx)
|
||||
{
|
||||
@@ -259,9 +248,8 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specified player as an AI with the specified
|
||||
* configuration. It is assumed that this will be set soon after the
|
||||
* player names for all AIs present in the game. (It should be done
|
||||
* Sets the specified player as an AI with the specified configuration. It is assumed that this
|
||||
* will be set soon after the player names for all AIs present in the game. (It should be done
|
||||
* before human players start trickling into the game.)
|
||||
*
|
||||
* @param pidx the player index of the AI.
|
||||
@@ -288,8 +276,8 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the player with the specified index or null if
|
||||
* no player exists at that index.
|
||||
* Returns the name of the player with the specified index or null if no player exists at that
|
||||
* index.
|
||||
*/
|
||||
public Name getPlayerName (int index)
|
||||
{
|
||||
@@ -297,8 +285,8 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the player index of the given user in the game, or
|
||||
* <code>-1</code> if the player is not involved in the game.
|
||||
* Returns the player index of the given user in the game, or <code>-1</code> if the player is
|
||||
* not involved in the game.
|
||||
*/
|
||||
public int getPlayerIndex (Name username)
|
||||
{
|
||||
@@ -306,14 +294,12 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player index of the specified oid, or -1 if the oid is
|
||||
* not a player or is a player that is not presently in the game.
|
||||
* Get the player index of the specified oid, or -1 if the oid is not a player or is a player
|
||||
* that is not presently in the game.
|
||||
*/
|
||||
public int getPresentPlayerIndex (int bodyOid)
|
||||
{
|
||||
return (_playerOids == null)
|
||||
? -1
|
||||
: IntListUtil.indexOf(_playerOids, bodyOid);
|
||||
return (_playerOids == null) ? -1 : IntListUtil.indexOf(_playerOids, bodyOid);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -349,13 +335,11 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the player at the specified player index is actively
|
||||
* playing the game
|
||||
* Returns whether the player at the specified player index is actively playing the game
|
||||
*/
|
||||
public boolean isActivePlayer (int pidx)
|
||||
{
|
||||
return _gameobj.isActivePlayer(pidx) &&
|
||||
(getPlayerOid(pidx) > 0 || isAI(pidx));
|
||||
return _gameobj.isActivePlayer(pidx) && (getPlayerOid(pidx) > 0 || isAI(pidx));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -377,14 +361,12 @@ public class GameManager extends PlaceManager
|
||||
/**
|
||||
* Sends a system message to the players in the game room.
|
||||
*
|
||||
* @param waitForStart if true, the message will not be sent until the
|
||||
* game has started.
|
||||
* @param waitForStart if true, the message will not be sent until the game has started.
|
||||
*/
|
||||
public void systemMessage (
|
||||
String msgbundle, String msg, boolean waitForStart)
|
||||
{
|
||||
if (waitForStart &&
|
||||
((_gameobj == null) || (_gameobj.state == GameObject.PRE_GAME))) {
|
||||
if (waitForStart && ((_gameobj == null) || (_gameobj.state == GameObject.PRE_GAME))) {
|
||||
// queue up the message.
|
||||
if (_startmsgs == null) {
|
||||
_startmsgs = new ArrayList<Tuple<String,String>>();
|
||||
@@ -398,23 +380,20 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when the game is ready to start (all players
|
||||
* involved have delivered their "am ready" notifications). It calls
|
||||
* {@link #gameWillStart}, sets the necessary wheels in motion and
|
||||
* then calls {@link #gameDidStart}. Derived classes should override
|
||||
* one or both of the calldown functions (rather than this function)
|
||||
* if they need to do things before or after the game starts.
|
||||
* This is called when the game is ready to start (all players involved have delivered their
|
||||
* "am ready" notifications). It calls {@link #gameWillStart}, sets the necessary wheels in
|
||||
* motion and then calls {@link #gameDidStart}. Derived classes should override one or both of
|
||||
* the calldown functions (rather than this function) if they need to do things before or after
|
||||
* the game starts.
|
||||
*
|
||||
* @return true if the game was started, false if it could not be
|
||||
* started because it was already in play or because all players have
|
||||
* not yet reported in.
|
||||
* @return true if the game was started, false if it could not be started because it was
|
||||
* already in play or because all players have not yet reported in.
|
||||
*/
|
||||
public boolean startGame ()
|
||||
{
|
||||
// complain if we're already started
|
||||
if (_gameobj.state == GameObject.IN_PLAY) {
|
||||
Log.warning("Requested to start an already in-play game " +
|
||||
"[game=" + where() + "].");
|
||||
Log.warning("Requested to start an already in-play game [game=" + where() + "].");
|
||||
Thread.dumpStack();
|
||||
return false;
|
||||
}
|
||||
@@ -424,27 +403,24 @@ public class GameManager extends PlaceManager
|
||||
|
||||
// make sure everyone has turned up
|
||||
if (!allPlayersReady()) {
|
||||
Log.warning("Requested to start a game that is still " +
|
||||
"awaiting players [game=" + where() +
|
||||
", pnames=" + StringUtil.toString(_gameobj.players) +
|
||||
Log.warning("Requested to start a game that is still awaiting players " +
|
||||
"[game=" + where() + ", pnames=" + StringUtil.toString(_gameobj.players) +
|
||||
", poids=" + StringUtil.toString(_playerOids) + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
// if we're still waiting for a call to endGame() to propagate,
|
||||
// queue up a runnable to start the game which will allow the
|
||||
// endGame() to propagate before we start things up
|
||||
// if we're still waiting for a call to endGame() to propagate, queue up a runnable to
|
||||
// start the game which will allow the endGame() to propagate before we start things up
|
||||
if (_committedState == GameObject.IN_PLAY) {
|
||||
if (_postponedStart) {
|
||||
// We've already tried postponing once, doesn't do us any
|
||||
// good to throw ourselves into a frenzy trying again.
|
||||
Log.warning("Tried to postpone the start of a still-ending game " +
|
||||
"multiple times [game=" + where() + "].");
|
||||
// We've already tried postponing once, doesn't do us any good to throw ourselves
|
||||
// into a frenzy trying again.
|
||||
Log.warning("Tried to postpone the start of a still-ending game multiple times " +
|
||||
"[game=" + where() + "].");
|
||||
_postponedStart = false;
|
||||
return false;
|
||||
}
|
||||
Log.info("Postponing start of still-ending game " +
|
||||
"[game=" + where() + "].");
|
||||
Log.info("Postponing start of still-ending game [game=" + where() + "].");
|
||||
_postponedStart = true;
|
||||
// TEMP: track down weirdness
|
||||
final Exception firstCall = new Exception();
|
||||
@@ -500,30 +476,27 @@ public class GameManager extends PlaceManager
|
||||
if (shouldEndGame()) {
|
||||
endGame();
|
||||
} else {
|
||||
// otherwise report that the player was knocked out to other
|
||||
// people in his/her room
|
||||
// otherwise report that the player was knocked out to other people in his/her room
|
||||
reportPlayerKnockedOut(pidx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game is known to be over. This will call some
|
||||
* calldown functions to determine the winner of the game and then
|
||||
* transition the game to the {@link GameObject#GAME_OVER} state.
|
||||
* Called when the game is known to be over. This will call some calldown functions to
|
||||
* determine the winner of the game and then transition the game to the {@link
|
||||
* GameObject#GAME_OVER} state.
|
||||
*/
|
||||
public void endGame ()
|
||||
{
|
||||
// TEMP: debug pending rating repeat bug
|
||||
if (_gameEndTracker.checkCall(
|
||||
"Requested to end already ended game " +
|
||||
"[game=" + where() + "].")) {
|
||||
"Requested to end already ended game [game=" + where() + "].")) {
|
||||
return;
|
||||
}
|
||||
// END TEMP
|
||||
|
||||
if (!_gameobj.isInPlay()) {
|
||||
Log.info("Refusing to end game that was not in play " +
|
||||
"[game=" + where() + "].");
|
||||
Log.info("Refusing to end game that was not in play [game=" + where() + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -544,22 +517,19 @@ public class GameManager extends PlaceManager
|
||||
_gameobj.commitTransaction();
|
||||
}
|
||||
|
||||
// wait until we hear the game state transition on the game object
|
||||
// to invoke our game over code so that we can be sure that any
|
||||
// final events dispatched on the game object prior to the call to
|
||||
// endGame() have been dispatched
|
||||
// wait until we hear the game state transition on the game object to invoke our game over
|
||||
// code so that we can be sure that any final events dispatched on the game object prior to
|
||||
// the call to endGame() have been dispatched
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the state of the game to {@link GameObject#CANCELLED}.
|
||||
*
|
||||
* @return true if the game was cancelled, false if it was already over or
|
||||
* cancelled.
|
||||
* @return true if the game was cancelled, false if it was already over or cancelled.
|
||||
*/
|
||||
public boolean cancelGame ()
|
||||
{
|
||||
if (_gameobj.state != GameObject.GAME_OVER &&
|
||||
_gameobj.state != GameObject.CANCELLED) {
|
||||
if (_gameobj.state != GameObject.GAME_OVER && _gameobj.state != GameObject.CANCELLED) {
|
||||
_gameobj.setState(GameObject.CANCELLED);
|
||||
return true;
|
||||
}
|
||||
@@ -567,10 +537,9 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether game conclusion antics such as rating updates
|
||||
* should be performed when an in-play game is ended. Derived classes
|
||||
* may wish to override this method to customize the conditions under
|
||||
* which the game is concluded.
|
||||
* Returns whether game conclusion antics such as rating updates should be performed when an
|
||||
* in-play game is ended. Derived classes may wish to override this method to customize the
|
||||
* conditions under which the game is concluded.
|
||||
*/
|
||||
public boolean shouldConcludeGame ()
|
||||
{
|
||||
@@ -578,13 +547,11 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game is to be reset to its starting state in
|
||||
* preparation for a new game without actually ending the current
|
||||
* game. It calls {@link #gameWillReset} followed by the standard game
|
||||
* start processing ({@link #gameWillStart} and {@link
|
||||
* #gameDidStart}). Derived classes should override these calldown
|
||||
* functions (rather than this function) if they need to do things
|
||||
* before or after the game resets.
|
||||
* Called when the game is to be reset to its starting state in preparation for a new game
|
||||
* without actually ending the current game. It calls {@link #gameWillReset} followed by the
|
||||
* standard game start processing ({@link #gameWillStart} and {@link #gameDidStart}). Derived
|
||||
* classes should override these calldown functions (rather than this function) if they need to
|
||||
* do things before or after the game resets.
|
||||
*/
|
||||
public void resetGame ()
|
||||
{
|
||||
@@ -597,21 +564,20 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the client when the player is ready for the game to start.
|
||||
* This method is dispatched dynamically by {@link #messageReceived}.
|
||||
* Called by the client when the player is ready for the game to start. This method is
|
||||
* dispatched dynamically by {@link #messageReceived}.
|
||||
*/
|
||||
public void playerReady (BodyObject caller)
|
||||
{
|
||||
// get the user's player index
|
||||
int pidx = _gameobj.getPlayerIndex(caller.getVisibleName());
|
||||
if (pidx == -1) {
|
||||
// only complain if this is not a party game, since it's
|
||||
// perfectly normal to receive a player ready notification
|
||||
// from a user entering a party game in which they're not yet
|
||||
// only complain if this is not a party game, since it's perfectly normal to receive a
|
||||
// player ready notification from a user entering a party game in which they're not yet
|
||||
// a participant
|
||||
if (needsNoShowTimer()) {
|
||||
Log.warning("Received playerReady() from non-player? " +
|
||||
"[game=" + where() + ", who=" + caller.who() + "].");
|
||||
Log.warning("Received playerReady() from non-player? [game=" + where() +
|
||||
", who=" + caller.who() + "].");
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -626,8 +592,8 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if all (non-AI) players have delivered their {@link
|
||||
* #playerReady} notifications, false if they have not.
|
||||
* Returns true if all (non-AI) players have delivered their {@link #playerReady}
|
||||
* notifications, false if they have not.
|
||||
*/
|
||||
public boolean allPlayersReady ()
|
||||
{
|
||||
@@ -640,10 +606,9 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the player at the specified slot is ready (or if
|
||||
* there is meant to be no player in that slot), false if there is
|
||||
* meant to be a player in the specified slot and they have not yet
|
||||
* reported that they are ready.
|
||||
* Returns true if the player at the specified slot is ready (or if there is meant to be no
|
||||
* player in that slot), false if there is meant to be a player in the specified slot and they
|
||||
* have not yet reported that they are ready.
|
||||
*/
|
||||
public boolean playerIsReady (int pidx)
|
||||
{
|
||||
@@ -653,20 +618,19 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this game requires a no-show timer. The default
|
||||
* implementation returns true for non-party games and false for party
|
||||
* games. Derived classes may wish to change or augment this behavior.
|
||||
* Returns true if this game requires a no-show timer. The default implementation returns true
|
||||
* for non-party games and false for party games. Derived classes may wish to change or augment
|
||||
* this behavior.
|
||||
*/
|
||||
protected boolean needsNoShowTimer ()
|
||||
{
|
||||
return (getGameType() == GameConfig.SEATED_GAME);
|
||||
return (getMatchType() == GameConfig.SEATED_GAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Derived classes that need their AIs to be ticked periodically
|
||||
* should override this method and return true. Many AIs can act
|
||||
* entirely in reaction to game state changes and need no periodic
|
||||
* ticking which is why ticking is disabled by default.
|
||||
* Derived classes that need their AIs to be ticked periodically should override this method
|
||||
* and return true. Many AIs can act entirely in reaction to game state changes and need no
|
||||
* periodic ticking which is why ticking is disabled by default.
|
||||
*
|
||||
* @see #tickAIs
|
||||
*/
|
||||
@@ -676,9 +640,8 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player was added to the game. Derived classes may
|
||||
* override this method to perform any game-specific actions they
|
||||
* desire, but should be sure to call
|
||||
* Called when a player was added to the game. Derived classes may override this method to
|
||||
* perform any game-specific actions they desire, but should be sure to call
|
||||
* <code>super.playerWasAdded()</code>.
|
||||
*
|
||||
* @param player the username of the player added to the game.
|
||||
@@ -689,22 +652,19 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player was removed from the game. Derived classes
|
||||
* may override this method to perform any game-specific actions they
|
||||
* desire, but should be sure to call
|
||||
* Called when a player was removed from the game. Derived classes may override this method to
|
||||
* perform any game-specific actions they desire, but should be sure to call
|
||||
* <code>super.playerWasRemoved()</code>.
|
||||
*
|
||||
* @param player the username of the player removed from the game.
|
||||
* @param pidx the player index of the player before they were removed
|
||||
* from the game.
|
||||
* @param pidx the player index of the player before they were removed from the game.
|
||||
*/
|
||||
protected void playerWasRemoved (Name player, int pidx)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player has been replaced via a call to {@link
|
||||
* #replacePlayer}.
|
||||
* Called when a player has been replaced via a call to {@link #replacePlayer}.
|
||||
*/
|
||||
protected void playerWasReplaced (int pidx, Name oldPlayer, Name newPlayer)
|
||||
{
|
||||
@@ -717,14 +677,12 @@ public class GameManager extends PlaceManager
|
||||
{
|
||||
BodyObject user = getPlayer(pidx);
|
||||
if (user == null) {
|
||||
// body object can be null for ai players
|
||||
return;
|
||||
return; // body object can be null for ai players
|
||||
}
|
||||
|
||||
DObject place = CrowdServer.omgr.getObject(user.location);
|
||||
if (place != null) {
|
||||
place.postMessage(PLAYER_KNOCKED_OUT,
|
||||
new Object[] { new int[] { user.getOid() } });
|
||||
place.postMessage(PLAYER_KNOCKED_OUT, new Object[] { new int[] { user.getOid() } });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -770,8 +728,8 @@ public class GameManager extends PlaceManager
|
||||
// set up an initial player status array
|
||||
_gameobj.setPlayerStatus(new int[getPlayerSlots()]);
|
||||
|
||||
// save off the number of players so that we needn't repeatedly
|
||||
// iterate through the player name array server-side unnecessarily
|
||||
// save off the number of players so that we needn't repeatedly iterate through the player
|
||||
// name array server-side unnecessarily
|
||||
_playerCount = _gameobj.getPlayerCount();
|
||||
|
||||
// instantiate a player oid array which we'll fill in later
|
||||
@@ -780,8 +738,8 @@ public class GameManager extends PlaceManager
|
||||
// give delegates a chance to do their thing
|
||||
super.didStartup();
|
||||
|
||||
// let the players of this game know that we're ready to roll (if
|
||||
// we have a specific set of players)
|
||||
// let the players of this game know that we're ready to roll (if we have a specific set of
|
||||
// players)
|
||||
for (int ii = 0; ii < getPlayerSlots(); ii++) {
|
||||
// skip non-existent players and AIs
|
||||
if (!_gameobj.isOccupiedPlayer(ii) || isAI(ii)) {
|
||||
@@ -790,8 +748,7 @@ public class GameManager extends PlaceManager
|
||||
|
||||
BodyObject bobj = CrowdServer.lookupBody(_gameobj.players[ii]);
|
||||
if (bobj == null) {
|
||||
Log.warning("Unable to deliver game ready to non-existent " +
|
||||
"player [game=" + where() +
|
||||
Log.warning("Unable to deliver game ready to non-existent player [game=" + where() +
|
||||
", player=" + _gameobj.players[ii] + "].");
|
||||
continue;
|
||||
}
|
||||
@@ -841,22 +798,21 @@ public class GameManager extends PlaceManager
|
||||
endPlayerGame(pidx);
|
||||
}
|
||||
|
||||
// then complete the bodyLeft() processing which may result in a call
|
||||
// to placeBecameEmpty() which will shut the game down
|
||||
// then complete the bodyLeft() processing which may result in a call to placeBecameEmpty()
|
||||
// which will shut the game down
|
||||
super.bodyLeft(bodyOid);
|
||||
}
|
||||
|
||||
/**
|
||||
* When a game room becomes empty, we cancel the game if it's still in
|
||||
* progress and close down the game room.
|
||||
* When a game room becomes empty, we cancel the game if it's still in progress and close down
|
||||
* the game room.
|
||||
*/
|
||||
protected void placeBecameEmpty ()
|
||||
{
|
||||
// Log.info("Game room empty. Going away. [game=" + where() + "].");
|
||||
|
||||
// if we're in play then move to game over
|
||||
if (_gameobj.state != GameObject.PRE_GAME &&
|
||||
_gameobj.state != GameObject.GAME_OVER &&
|
||||
if (_gameobj.state != GameObject.PRE_GAME && _gameobj.state != GameObject.GAME_OVER &&
|
||||
_gameobj.state != GameObject.CANCELLED) {
|
||||
_gameobj.setState(GameObject.GAME_OVER);
|
||||
// and shutdown directly
|
||||
@@ -870,23 +826,21 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when all players have arrived in the game room. By default,
|
||||
* this starts up the game, but a manager may wish to override this
|
||||
* and start the game according to different criterion.
|
||||
* Called when all players have arrived in the game room. By default, this starts up the game,
|
||||
* but a manager may wish to override this and start the game according to different criterion.
|
||||
*/
|
||||
protected void playersAllHere ()
|
||||
{
|
||||
// if we're a seated game and we haven't already started, start.
|
||||
if ((getGameType() == GameConfig.SEATED_GAME) && (_gameobj.state == GameObject.PRE_GAME)) {
|
||||
if ((getMatchType() == GameConfig.SEATED_GAME) && (_gameobj.state == GameObject.PRE_GAME)) {
|
||||
startGame();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the no-show delay has expired following the delivery
|
||||
* of notifications to all players that the game is ready.
|
||||
* <em>Note:</em> this is not called for party games. Those games have
|
||||
* a human who decides when to start the game.
|
||||
* Called after the no-show delay has expired following the delivery of notifications to all
|
||||
* players that the game is ready. <em>Note:</em> this is not called for party games. Those
|
||||
* games have a human who decides when to start the game.
|
||||
*/
|
||||
protected void checkForNoShows ()
|
||||
{
|
||||
@@ -914,14 +868,13 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when some, but not all, players failed to show up
|
||||
* for a game. The default implementation simply cancels the game.
|
||||
* This is called when some, but not all, players failed to show up for a game. The default
|
||||
* implementation simply cancels the game.
|
||||
*/
|
||||
protected void handlePartialNoShow ()
|
||||
{
|
||||
// mark the no-show players; this will cause allPlayersReady() to
|
||||
// think that everyone has arrived, but still allow us to tell who
|
||||
// has not shown up in gameDidStart()
|
||||
// mark the no-show players; this will cause allPlayersReady() to think that everyone has
|
||||
// arrived, but still allow us to tell who has not shown up in gameDidStart()
|
||||
int humansHere = 0;
|
||||
for (int ii = 0; ii < _playerOids.length; ii++) {
|
||||
if (_playerOids[ii] == 0) {
|
||||
@@ -938,9 +891,8 @@ public class GameManager extends PlaceManager
|
||||
cancelGame();
|
||||
|
||||
} else {
|
||||
// go ahead and report that everyone is ready (which will start the
|
||||
// game); gameDidStart() will take care of giving the boot to
|
||||
// anyone who isn't around
|
||||
// go ahead and report that everyone is ready (which will start the game);
|
||||
// gameDidStart() will take care of giving the boot to anyone who isn't around
|
||||
Log.info("Forcing start of partial no-show game [game=" + where() +
|
||||
", poids=" + StringUtil.toString(_playerOids) + "].");
|
||||
playersAllHere();
|
||||
@@ -948,8 +900,8 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if we should start the game even without any humans.
|
||||
* Default implementation always returns false.
|
||||
* @return true if we should start the game even without any humans. Default implementation
|
||||
* always returns false.
|
||||
*/
|
||||
protected boolean startWithoutHumans ()
|
||||
{
|
||||
@@ -957,11 +909,9 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game is about to start, but before the game start
|
||||
* notification has been delivered to the players. Derived classes
|
||||
* should override this if they need to perform some pre-start
|
||||
* activities, but should be sure to call
|
||||
* <code>super.gameWillStart()</code>.
|
||||
* Called when the game is about to start, but before the game start notification has been
|
||||
* delivered to the players. Derived classes should override this if they need to perform some
|
||||
* pre-start activities, but should be sure to call <code>super.gameWillStart()</code>.
|
||||
*/
|
||||
protected void gameWillStart ()
|
||||
{
|
||||
@@ -977,8 +927,8 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game state changes. This happens after the attribute
|
||||
* change event has propagated.
|
||||
* Called when the game state changes. This happens after the attribute change event has
|
||||
* propagated.
|
||||
*
|
||||
* @param state the new game state.
|
||||
* @param oldState the previous game state.
|
||||
@@ -991,8 +941,8 @@ public class GameManager extends PlaceManager
|
||||
break;
|
||||
|
||||
case GameObject.GAME_OVER:
|
||||
// we do some jiggery pokery to allow derived game objects to have
|
||||
// different notions of what it means to be in play
|
||||
// we do some jiggery pokery to allow derived game objects to have different notions of
|
||||
// what it means to be in play
|
||||
_gameobj.state = oldState;
|
||||
boolean wasInPlay = _gameobj.isInPlay();
|
||||
_gameobj.state = state;
|
||||
@@ -1016,11 +966,10 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the game start notification was dispatched. Derived
|
||||
* classes can override this to put whatever wheels they might need
|
||||
* into motion now that the game is started (if anything other than
|
||||
* transitioning the game to {@link GameObject#IN_PLAY} is necessary),
|
||||
* but should be sure to call <code>super.gameDidStart()</code>.
|
||||
* Called after the game start notification was dispatched. Derived classes can override this
|
||||
* to put whatever wheels they might need into motion now that the game is started (if anything
|
||||
* other than transitioning the game to {@link GameObject#IN_PLAY} is necessary), but should be
|
||||
* sure to call <code>super.gameDidStart()</code>.
|
||||
*/
|
||||
protected void gameDidStart ()
|
||||
{
|
||||
@@ -1034,8 +983,7 @@ public class GameManager extends PlaceManager
|
||||
// inform the players of any pending messages.
|
||||
if (_startmsgs != null) {
|
||||
for (Tuple<String,String> mtup : _startmsgs) {
|
||||
systemMessage(mtup.left, // bundle
|
||||
mtup.right); // message
|
||||
systemMessage(mtup.left, /* bundle */ mtup.right /* message */);
|
||||
}
|
||||
_startmsgs = null;
|
||||
}
|
||||
@@ -1045,8 +993,7 @@ public class GameManager extends PlaceManager
|
||||
AIGameTicker.registerAIGame(this);
|
||||
}
|
||||
|
||||
// any players who have not claimed that they are ready should now
|
||||
// be given le boote royale
|
||||
// any players who have not claimed that they are ready should now be given le boote royale
|
||||
for (int ii = 0; ii < _playerOids.length; ii++) {
|
||||
if (_playerOids[ii] == -1) {
|
||||
Log.info("Booting no-show player [game=" + where() +
|
||||
@@ -1058,8 +1005,7 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the {@link AIGameTicker} if we're registered as an AI
|
||||
* game.
|
||||
* Called by the {@link AIGameTicker} if we're registered as an AI game.
|
||||
*/
|
||||
protected void tickAIs ()
|
||||
{
|
||||
@@ -1097,10 +1043,9 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player has been marked as knocked out but before the
|
||||
* knock-out status update has been sent to the players. Any status
|
||||
* information that needs be updated in light of the knocked out
|
||||
* player can be updated here.
|
||||
* Called when a player has been marked as knocked out but before the knock-out status update
|
||||
* has been sent to the players. Any status information that needs be updated in light of the
|
||||
* knocked out player can be updated here.
|
||||
*/
|
||||
protected void playerGameDidEnd (int pidx)
|
||||
{
|
||||
@@ -1109,13 +1054,11 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player leaves the game in order to determine whether
|
||||
* the game should be ended based on its current state, which will
|
||||
* include updated player status for the player in question. The
|
||||
* default implementation returns true if the game is in play and
|
||||
* there is only one player left. Derived classes may wish to
|
||||
* override this method in order to customize the required end-game
|
||||
* conditions.
|
||||
* Called when a player leaves the game in order to determine whether the game should be ended
|
||||
* based on its current state, which will include updated player status for the player in
|
||||
* question. The default implementation returns true if the game is in play and there is only
|
||||
* one player left. Derived classes may wish to override this method in order to customize the
|
||||
* required end-game conditions.
|
||||
*/
|
||||
protected boolean shouldEndGame ()
|
||||
{
|
||||
@@ -1123,11 +1066,10 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns the final winning status for each player to their respect
|
||||
* player index in the supplied array. This will be called by {@link
|
||||
* #endGame} when the game is over. The default implementation marks
|
||||
* no players as winners. Derived classes should override this method
|
||||
* in order to customize the winning conditions.
|
||||
* Assigns the final winning status for each player to their respect player index in the
|
||||
* supplied array. This will be called by {@link #endGame} when the game is over. The default
|
||||
* implementation marks no players as winners. Derived classes should override this method in
|
||||
* order to customize the winning conditions.
|
||||
*/
|
||||
protected void assignWinners (boolean[] winners)
|
||||
{
|
||||
@@ -1135,11 +1077,9 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game is about to end, but before the game end
|
||||
* notification has been delivered to the players. Derived classes
|
||||
* should override this if they need to perform some pre-end
|
||||
* activities, but should be sure to call
|
||||
* <code>super.gameWillEnd()</code>.
|
||||
* Called when the game is about to end, but before the game end notification has been
|
||||
* delivered to the players. Derived classes should override this if they need to perform some
|
||||
* pre-end activities, but should be sure to call <code>super.gameWillEnd()</code>.
|
||||
*/
|
||||
protected void gameWillEnd ()
|
||||
{
|
||||
@@ -1152,9 +1092,8 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the game has transitioned to the {@link
|
||||
* GameObject#GAME_OVER} state. Derived classes should override this
|
||||
* to perform any post-game activities, but should be sure to call
|
||||
* Called after the game has transitioned to the {@link GameObject#GAME_OVER} state. Derived
|
||||
* classes should override this to perform any post-game activities, but should be sure to call
|
||||
* <code>super.gameDidEnd()</code>.
|
||||
*/
|
||||
protected void gameDidEnd ()
|
||||
@@ -1181,15 +1120,13 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to let the manager know that the game was cancelled (and may be
|
||||
* about to be shutdown if there's no one in the room). In the base
|
||||
* framework a game will only be canceled if no one shows up, so {@link
|
||||
* #gameWillStart}, etc. will never have been called and thus {@link
|
||||
* #gameWillEnd}, etc. will not be called. However, if a game chooses to
|
||||
* cancel itself for whatever reason, no effort will be made to call {@link
|
||||
* #endGame} and the game ending call backs so that game can override this
|
||||
* method to do anything it needs. Note that {@link #didShutdown} will be
|
||||
* called in every case and that's generally the best place to free
|
||||
* Called to let the manager know that the game was cancelled (and may be about to be shutdown
|
||||
* if there's no one in the room). In the base framework a game will only be canceled if no one
|
||||
* shows up, so {@link #gameWillStart}, etc. will never have been called and thus {@link
|
||||
* #gameWillEnd}, etc. will not be called. However, if a game chooses to cancel itself for
|
||||
* whatever reason, no effort will be made to call {@link #endGame} and the game ending call
|
||||
* backs so that game can override this method to do anything it needs. Note that {@link
|
||||
* #didShutdown} will be called in every case and that's generally the best place to free
|
||||
* resources so this method may not be needed.
|
||||
*/
|
||||
protected void gameWasCancelled ()
|
||||
@@ -1198,8 +1135,7 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Report winner and loser oids to each room that any of the
|
||||
* winners/losers is in.
|
||||
* Report winner and loser oids to each room that any of the winners/losers is in.
|
||||
*/
|
||||
protected void reportWinnersAndLosers ()
|
||||
{
|
||||
@@ -1218,8 +1154,7 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
}
|
||||
|
||||
Object[] args =
|
||||
new Object[] { winners.toIntArray(), losers.toIntArray() };
|
||||
Object[] args = new Object[] { winners.toIntArray(), losers.toIntArray() };
|
||||
|
||||
// now send a message event to each room
|
||||
for (int ii=0, nn = places.size(); ii < nn; ii++) {
|
||||
@@ -1231,10 +1166,9 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game is about to reset, but before the board has
|
||||
* been re-initialized or any other clearing out of game data has
|
||||
* taken place. Derived classes should override this if they need to
|
||||
* perform some pre-reset activities.
|
||||
* Called when the game is about to reset, but before the board has been re-initialized or any
|
||||
* other clearing out of game data has taken place. Derived classes should override this if
|
||||
* they need to perform some pre-reset activities.
|
||||
*/
|
||||
protected void gameWillReset ()
|
||||
{
|
||||
@@ -1250,8 +1184,8 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives game managers an opportunity to perform periodic processing
|
||||
* that is not driven by events generated by the player.
|
||||
* Gives game managers an opportunity to perform periodic processing that is not driven by
|
||||
* events generated by the player.
|
||||
*/
|
||||
protected void tick (long tickStamp)
|
||||
{
|
||||
@@ -1259,8 +1193,7 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called periodically to call {@link #tick} on all registered game
|
||||
* managers.
|
||||
* Called periodically to call {@link #tick} on all registered game managers.
|
||||
*/
|
||||
protected static void tickAllGames ()
|
||||
{
|
||||
@@ -1271,8 +1204,7 @@ public class GameManager extends PlaceManager
|
||||
try {
|
||||
gmgr.tick(now);
|
||||
} catch (Exception e) {
|
||||
Log.warning(
|
||||
"Game manager choked during tick [gmgr=" + gmgr + "].");
|
||||
Log.warning("Game manager choked during tick [gmgr=" + gmgr + "].");
|
||||
Log.logStackTrace(e);
|
||||
}
|
||||
}
|
||||
@@ -1298,12 +1230,11 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/** Listens for game state changes. */
|
||||
protected AttributeChangeListener _stateListener =
|
||||
new AttributeChangeListener() {
|
||||
protected AttributeChangeListener _stateListener = new AttributeChangeListener() {
|
||||
public void attributeChanged (AttributeChangedEvent event) {
|
||||
if (event.getName().equals(GameObject.STATE)) {
|
||||
stateDidChange(_committedState = event.getIntValue(),
|
||||
((Integer)event.getOldValue()).intValue());
|
||||
((Integer)event.getOldValue()).intValue());
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1320,19 +1251,17 @@ public class GameManager extends PlaceManager
|
||||
/** The oids of our player and AI body objects. */
|
||||
protected int[] _playerOids;
|
||||
|
||||
/** If AIs are present, contains their configuration, or null at human
|
||||
* player indexes. */
|
||||
/** If AIs are present, contains their configuration, or null at human player indexes. */
|
||||
protected GameAI[] _AIs;
|
||||
|
||||
/** If non-null, contains bundles and messages that should be sent as
|
||||
* system messages once the game has started. */
|
||||
/** If non-null, contains bundles and messages that should be sent as system messages once the
|
||||
* game has started. */
|
||||
protected ArrayList<Tuple<String,String>> _startmsgs;
|
||||
|
||||
/** Our delegate operator to tick AIs. */
|
||||
protected TickAIDelegateOp _tickAIOp;
|
||||
|
||||
/** The state of the game that has been propagated to our
|
||||
* subscribers. */
|
||||
/** The state of the game that has been propagated to our subscribers. */
|
||||
protected int _committedState;
|
||||
|
||||
/** TEMP: debugging the pending rating double release bug. */
|
||||
@@ -1342,14 +1271,13 @@ public class GameManager extends PlaceManager
|
||||
protected boolean _postponedStart = false;
|
||||
|
||||
/** A list of all currently active game managers. */
|
||||
protected static ArrayList<GameManager> _managers =
|
||||
new ArrayList<GameManager>();
|
||||
protected static ArrayList<GameManager> _managers = new ArrayList<GameManager>();
|
||||
|
||||
/** The interval for the game manager tick. */
|
||||
protected static Interval _tickInterval;
|
||||
|
||||
/** We give players 30 seconds to turn up in a game; after that,
|
||||
* they're considered a no show. */
|
||||
/** We give players 30 seconds to turn up in a game; after that, they're considered a no
|
||||
* show. */
|
||||
protected static final long NOSHOW_DELAY = 30 * 1000L;
|
||||
|
||||
/** The delay in milliseconds between ticking of all game managers. */
|
||||
|
||||
Reference in New Issue
Block a user