partial fix to 'logged off players automatically win all matches in tourneys'
git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@3639 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -28,6 +28,13 @@ import com.threerings.presents.data.InvocationCodes;
|
|||||||
*/
|
*/
|
||||||
public interface GameCodes extends InvocationCodes
|
public interface GameCodes extends InvocationCodes
|
||||||
{
|
{
|
||||||
|
/** The message bundle identifier for general game messages. */
|
||||||
|
public static final String GAME_MESSAGE_BUNDLE = "game.general";
|
||||||
|
|
||||||
|
/** The name of the message event to a placeObject that a player
|
||||||
|
* was knocked out of a puzzle. */
|
||||||
|
public static final String PLAYER_KNOCKED_OUT = "playerKnocked";
|
||||||
|
|
||||||
/** The name of the message event to a placeObject that reports
|
/** The name of the message event to a placeObject that reports
|
||||||
* the winners and losers of a game. */
|
* the winners and losers of a game. */
|
||||||
public static final String WINNERS_AND_LOSERS = "winnersAndLosers";
|
public static final String WINNERS_AND_LOSERS = "winnersAndLosers";
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ import com.threerings.parlor.game.data.GameObject;
|
|||||||
import com.threerings.parlor.game.data.PartyGameConfig;
|
import com.threerings.parlor.game.data.PartyGameConfig;
|
||||||
import com.threerings.parlor.server.ParlorSender;
|
import com.threerings.parlor.server.ParlorSender;
|
||||||
|
|
||||||
|
import com.threerings.util.MessageBundle;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The game manager handles the server side management of a game. It
|
* The game manager handles the server side management of a game. It
|
||||||
* manipulates the game state in accordance with the logic of the game
|
* manipulates the game state in accordance with the logic of the game
|
||||||
@@ -412,6 +414,26 @@ public class GameManager extends PlaceManager
|
|||||||
SpeakProvider.sendInfo(_gameobj, msgbundle, msg);
|
SpeakProvider.sendInfo(_gameobj, msgbundle, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report to the knocked-out player's room that they were knocked out.
|
||||||
|
*/
|
||||||
|
protected void reportPlayerKnockedOut (int pidx)
|
||||||
|
{
|
||||||
|
BodyObject user = getPlayer(pidx);
|
||||||
|
if (user == null) {
|
||||||
|
// body object can be null for ai players
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OidList knocky = new OidList(1);
|
||||||
|
knocky.add(user.getOid());
|
||||||
|
|
||||||
|
DObject place = CrowdServer.omgr.getObject(user.location);
|
||||||
|
if (place != null) {
|
||||||
|
place.postMessage(PLAYER_KNOCKED_OUT, new Object[] { knocky });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// documentation inherited
|
// documentation inherited
|
||||||
protected Class getPlaceObjectClass ()
|
protected Class getPlaceObjectClass ()
|
||||||
{
|
{
|
||||||
@@ -594,11 +616,22 @@ public class GameManager extends PlaceManager
|
|||||||
*/
|
*/
|
||||||
protected void handlePartialNoShow ()
|
protected void handlePartialNoShow ()
|
||||||
{
|
{
|
||||||
// cancel the game
|
// mark the no-show players; this will cause allPlayersReady() to
|
||||||
if (_gameobj.state != GameObject.GAME_OVER &&
|
// think that everyone has arrived, but still allow us to tell who
|
||||||
_gameobj.state != GameObject.CANCELLED) {
|
// has not shown up in gameDidStart()
|
||||||
_gameobj.setState(GameObject.CANCELLED);
|
for (int ii = 0; ii < _playerOids.length; ii++) {
|
||||||
|
if (_playerOids[ii] == 0) {
|
||||||
|
_playerOids[ii] = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// go ahead and 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=" + _gameobj.which() +
|
||||||
|
", players=" + StringUtil.toString(_gameobj.players) +
|
||||||
|
", poids=" + StringUtil.toString(_playerOids) + "].");
|
||||||
|
startGame();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -626,6 +659,18 @@ public class GameManager extends PlaceManager
|
|||||||
// TEMP: clear out our game end tracker
|
// TEMP: clear out our game end tracker
|
||||||
_gameEndTracker.clear();
|
_gameEndTracker.clear();
|
||||||
|
|
||||||
|
// TODO: find the right place to put this
|
||||||
|
// 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=" + _gameobj.which() +
|
||||||
|
", player=" + getPlayerName(ii) + "].");
|
||||||
|
_playerOids[ii] = 0; // unfiddle the blank oid
|
||||||
|
endPlayerGame(ii);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// make sure everyone has turned up
|
// make sure everyone has turned up
|
||||||
if (!allPlayersReady()) {
|
if (!allPlayersReady()) {
|
||||||
Log.warning("Requested to start a game that is still " +
|
Log.warning("Requested to start a game that is still " +
|
||||||
@@ -735,6 +780,65 @@ public class GameManager extends PlaceManager
|
|||||||
applyToDelegates(_tickAIOp);
|
applyToDelegates(_tickAIOp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ends the game for the given player.
|
||||||
|
*/
|
||||||
|
public void endPlayerGame (int pidx)
|
||||||
|
{
|
||||||
|
// go for a little transactional efficiency
|
||||||
|
_gameobj.startTransaction();
|
||||||
|
try {
|
||||||
|
// end the player's game
|
||||||
|
if (_gameobj.playerStatus != null) {
|
||||||
|
_gameobj.setPlayerStatusAt(GameObject.PLAYER_LEFT_GAME, pidx);
|
||||||
|
|
||||||
|
// let derived classes do some business
|
||||||
|
playerGameDidEnd(pidx);
|
||||||
|
}
|
||||||
|
|
||||||
|
String message = MessageBundle.tcompose(
|
||||||
|
"m.player_game_over", getPlayerName(pidx));
|
||||||
|
systemMessage(GAME_MESSAGE_BUNDLE, message);
|
||||||
|
} finally {
|
||||||
|
_gameobj.commitTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if it's time to end the game, then do so
|
||||||
|
if (shouldEndGame()) {
|
||||||
|
endGame();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// otherwise report that the player was knocked out to other
|
||||||
|
// people in his/her room
|
||||||
|
reportPlayerKnockedOut(pidx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 ()
|
||||||
|
{
|
||||||
|
return (_gameobj.isInPlay() && _gameobj.getActivePlayerCount() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the game is known to be over. This will call some
|
* Called when the game is known to be over. This will call some
|
||||||
* calldown functions to determine the winner of the game and then
|
* calldown functions to determine the winner of the game and then
|
||||||
|
|||||||
@@ -124,46 +124,10 @@ public abstract class PuzzleManager extends GameManager
|
|||||||
updateBoardSummary(pidx);
|
updateBoardSummary(pidx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// go for a little transactional efficiency
|
super.endPlayerGame(pidx);
|
||||||
_puzobj.startTransaction();
|
|
||||||
try {
|
|
||||||
// end the player's game
|
|
||||||
_puzobj.setPlayerStatusAt(GameObject.PLAYER_LEFT_GAME, pidx);
|
|
||||||
|
|
||||||
// let derived classes do some business
|
// force a status update
|
||||||
playerGameDidEnd(pidx);
|
updateStatus();
|
||||||
|
|
||||||
// force a status update
|
|
||||||
updateStatus();
|
|
||||||
|
|
||||||
// notify the players
|
|
||||||
String message = MessageBundle.tcompose(
|
|
||||||
"m.player_game_over", getPlayerName(pidx));
|
|
||||||
systemMessage(PUZZLE_MESSAGE_BUNDLE, message);
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
_puzobj.commitTransaction();
|
|
||||||
}
|
|
||||||
|
|
||||||
// if it's time to end the game, then do so
|
|
||||||
if (shouldEndGame()) {
|
|
||||||
endGame();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// otherwise report that the player was knocked out to other
|
|
||||||
// people in his/her room
|
|
||||||
reportPlayerKnockedOut(pidx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited
|
// documentation inherited
|
||||||
@@ -195,27 +159,6 @@ public abstract class PuzzleManager extends GameManager
|
|||||||
_puzobj.setPuzzleGameService(service);
|
_puzobj.setPuzzleGameService(service);
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
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()
|
|
||||||
for (int ii = 0; ii < _playerOids.length; ii++) {
|
|
||||||
if (_playerOids[ii] == 0) {
|
|
||||||
_playerOids[ii] = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// go ahead and 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=" + _puzobj.which() +
|
|
||||||
", players=" + StringUtil.toString(_puzobj.players) +
|
|
||||||
", poids=" + StringUtil.toString(_playerOids) + "].");
|
|
||||||
startGame();
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
// documentation inherited
|
||||||
protected void gameWillStart ()
|
protected void gameWillStart ()
|
||||||
{
|
{
|
||||||
@@ -294,17 +237,6 @@ public abstract class PuzzleManager extends GameManager
|
|||||||
{
|
{
|
||||||
super.gameDidStart();
|
super.gameDidStart();
|
||||||
|
|
||||||
// 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=" + _puzobj.which() +
|
|
||||||
", player=" + getPlayerName(ii) + "].");
|
|
||||||
_playerOids[ii] = 0; // unfiddle the blank oid
|
|
||||||
endPlayerGame(ii);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// log the AI skill levels for games involving AIs as it's useful
|
// log the AI skill levels for games involving AIs as it's useful
|
||||||
// when tuning AI algorithms
|
// when tuning AI algorithms
|
||||||
if (_AIs != null) {
|
if (_AIs != null) {
|
||||||
@@ -417,26 +349,6 @@ public abstract class PuzzleManager extends GameManager
|
|||||||
super.gameDidEnd();
|
super.gameDidEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Report to the knocked-out player's room that they were knocked out.
|
|
||||||
*/
|
|
||||||
protected void reportPlayerKnockedOut (int pidx)
|
|
||||||
{
|
|
||||||
BodyObject user = getPlayer(pidx);
|
|
||||||
if (user == null) {
|
|
||||||
// body object can be null for ai players
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
OidList knocky = new OidList(1);
|
|
||||||
knocky.add(user.getOid());
|
|
||||||
|
|
||||||
DObject place = CrowdServer.omgr.getObject(user.location);
|
|
||||||
if (place != null) {
|
|
||||||
place.postMessage(PLAYER_KNOCKED_OUT, new Object[] { knocky });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
// documentation inherited
|
||||||
protected void didShutdown ()
|
protected void didShutdown ()
|
||||||
{
|
{
|
||||||
@@ -559,20 +471,6 @@ public abstract class PuzzleManager extends GameManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 ()
|
|
||||||
{
|
|
||||||
return (_puzobj.isInPlay() && _puzobj.getActivePlayerCount() == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overrides the game manager implementation to mark all active
|
* Overrides the game manager implementation to mark all active
|
||||||
* players as winners. Derived classes may wish to override this
|
* players as winners. Derived classes may wish to override this
|
||||||
|
|||||||
Reference in New Issue
Block a user