Nixed GameService as it can be more simply implemented with the new dynamically
dispatched message event system. Rearranged the methods in GameManager into some semblance of order. git-svn-id: svn+ssh://src.earth.threerings.net/vilya/trunk@60 c613c5cb-e716-0410-b11b-feb51c14d237
This commit is contained in:
@@ -21,19 +21,22 @@
|
|||||||
|
|
||||||
package com.threerings.parlor;
|
package com.threerings.parlor;
|
||||||
|
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A placeholder class that contains a reference to the log object used by
|
* Contains a reference to the log object used by the Parlor services.
|
||||||
* the Parlor services.
|
|
||||||
*/
|
*/
|
||||||
public class Log
|
public class Log
|
||||||
{
|
{
|
||||||
public static com.samskivert.util.Log log =
|
/** We dispatch our log messages through this logger. */
|
||||||
new com.samskivert.util.Log("parlor");
|
public static Logger log =
|
||||||
|
Logger.getLogger("com.threerings.vilya.parlor");
|
||||||
|
|
||||||
/** Convenience function. */
|
/** Convenience function. */
|
||||||
public static void debug (String message)
|
public static void debug (String message)
|
||||||
{
|
{
|
||||||
log.debug(message);
|
log.fine(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Convenience function. */
|
/** Convenience function. */
|
||||||
@@ -51,6 +54,6 @@ public class Log
|
|||||||
/** Convenience function. */
|
/** Convenience function. */
|
||||||
public static void logStackTrace (Throwable t)
|
public static void logStackTrace (Throwable t)
|
||||||
{
|
{
|
||||||
log.logStackTrace(com.samskivert.util.Log.WARNING, t);
|
log.log(Level.WARNING, t.getMessage(), t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ public abstract class GameController extends PlaceController
|
|||||||
protected void playerReady ()
|
protected void playerReady ()
|
||||||
{
|
{
|
||||||
Log.info("Reporting ready " + _gobj.which() + ".");
|
Log.info("Reporting ready " + _gobj.which() + ".");
|
||||||
_gobj.gameService.playerReady(_ctx.getClient());
|
_gobj.manager.invoke("playerReady");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id: GameService.java 3600 2005-06-15 23:46:31Z ray $
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
|
||||||
// http://www.threerings.net/code/narya/
|
|
||||||
//
|
|
||||||
// This library is free software; you can redistribute it and/or modify it
|
|
||||||
// under the terms of the GNU Lesser General Public License as published
|
|
||||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
// Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public
|
|
||||||
// License along with this library; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
|
|
||||||
package com.threerings.parlor.game.client;
|
|
||||||
|
|
||||||
import com.threerings.presents.client.Client;
|
|
||||||
import com.threerings.presents.client.InvocationService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides services used by game clients to request that actions be taken
|
|
||||||
* by the game manager.
|
|
||||||
*/
|
|
||||||
public interface GameService extends InvocationService
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Lets the game manager know that the calling player is in the game
|
|
||||||
* room and ready to play.
|
|
||||||
*/
|
|
||||||
public void playerReady (Client client);
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id: GameMarshaller.java 4145 2006-05-24 01:24:24Z ray $
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
|
||||||
// http://www.threerings.net/code/narya/
|
|
||||||
//
|
|
||||||
// This library is free software; you can redistribute it and/or modify it
|
|
||||||
// under the terms of the GNU Lesser General Public License as published
|
|
||||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
// Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public
|
|
||||||
// License along with this library; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
|
|
||||||
package com.threerings.parlor.game.data;
|
|
||||||
|
|
||||||
import com.threerings.parlor.game.client.GameService;
|
|
||||||
import com.threerings.presents.client.Client;
|
|
||||||
import com.threerings.presents.data.InvocationMarshaller;
|
|
||||||
import com.threerings.presents.dobj.InvocationResponseEvent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides the implementation of the {@link GameService} interface
|
|
||||||
* that marshalls the arguments and delivers the request to the provider
|
|
||||||
* on the server. Also provides an implementation of the response listener
|
|
||||||
* interfaces that marshall the response arguments and deliver them back
|
|
||||||
* to the requesting client.
|
|
||||||
*/
|
|
||||||
public class GameMarshaller extends InvocationMarshaller
|
|
||||||
implements GameService
|
|
||||||
{
|
|
||||||
/** The method id used to dispatch {@link #playerReady} requests. */
|
|
||||||
public static final int PLAYER_READY = 1;
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void playerReady (Client arg1)
|
|
||||||
{
|
|
||||||
sendRequest(arg1, PLAYER_READY, new Object[] {
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -40,9 +40,6 @@ import com.threerings.crowd.data.PlaceObject;
|
|||||||
public class GameObject extends PlaceObject
|
public class GameObject extends PlaceObject
|
||||||
{
|
{
|
||||||
// AUTO-GENERATED: FIELDS START
|
// AUTO-GENERATED: FIELDS START
|
||||||
/** The field name of the <code>gameService</code> field. */
|
|
||||||
public static final String GAME_SERVICE = "gameService";
|
|
||||||
|
|
||||||
/** The field name of the <code>state</code> field. */
|
/** The field name of the <code>state</code> field. */
|
||||||
public static final String STATE = "state";
|
public static final String STATE = "state";
|
||||||
|
|
||||||
@@ -86,9 +83,6 @@ public class GameObject extends PlaceObject
|
|||||||
* game prematurely. */
|
* game prematurely. */
|
||||||
public static final int PLAYER_LEFT_GAME = 1;
|
public static final int PLAYER_LEFT_GAME = 1;
|
||||||
|
|
||||||
/** Provides general game invocation services. */
|
|
||||||
public GameMarshaller gameService;
|
|
||||||
|
|
||||||
/** The game state, one of {@link #PRE_GAME}, {@link #IN_PLAY},
|
/** The game state, one of {@link #PRE_GAME}, {@link #IN_PLAY},
|
||||||
* {@link #GAME_OVER}, or {@link #CANCELLED}. */
|
* {@link #GAME_OVER}, or {@link #CANCELLED}. */
|
||||||
public int state = PRE_GAME;
|
public int state = PRE_GAME;
|
||||||
@@ -265,22 +259,6 @@ public class GameObject extends PlaceObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AUTO-GENERATED: METHODS START
|
// AUTO-GENERATED: METHODS START
|
||||||
/**
|
|
||||||
* Requests that the <code>gameService</code> field be set to the
|
|
||||||
* specified value. The local value will be updated immediately and an
|
|
||||||
* event will be propagated through the system to notify all listeners
|
|
||||||
* that the attribute did change. Proxied copies of this object (on
|
|
||||||
* clients) will apply the value change when they received the
|
|
||||||
* attribute changed notification.
|
|
||||||
*/
|
|
||||||
public void setGameService (GameMarshaller value)
|
|
||||||
{
|
|
||||||
GameMarshaller ovalue = this.gameService;
|
|
||||||
requestAttributeChange(
|
|
||||||
GAME_SERVICE, value, ovalue);
|
|
||||||
this.gameService = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requests that the <code>state</code> field be set to the
|
* Requests that the <code>state</code> field be set to the
|
||||||
* specified value. The local value will be updated immediately and an
|
* specified value. The local value will be updated immediately and an
|
||||||
|
|||||||
@@ -1,69 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id: GameDispatcher.java 4145 2006-05-24 01:24:24Z ray $
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
|
||||||
// http://www.threerings.net/code/narya/
|
|
||||||
//
|
|
||||||
// This library is free software; you can redistribute it and/or modify it
|
|
||||||
// under the terms of the GNU Lesser General Public License as published
|
|
||||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
// Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public
|
|
||||||
// License along with this library; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
|
|
||||||
package com.threerings.parlor.game.server;
|
|
||||||
|
|
||||||
import com.threerings.parlor.game.client.GameService;
|
|
||||||
import com.threerings.parlor.game.data.GameMarshaller;
|
|
||||||
import com.threerings.presents.client.Client;
|
|
||||||
import com.threerings.presents.data.ClientObject;
|
|
||||||
import com.threerings.presents.data.InvocationMarshaller;
|
|
||||||
import com.threerings.presents.server.InvocationDispatcher;
|
|
||||||
import com.threerings.presents.server.InvocationException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches requests to the {@link GameProvider}.
|
|
||||||
*/
|
|
||||||
public class GameDispatcher extends InvocationDispatcher
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Creates a dispatcher that may be registered to dispatch invocation
|
|
||||||
* service requests for the specified provider.
|
|
||||||
*/
|
|
||||||
public GameDispatcher (GameProvider provider)
|
|
||||||
{
|
|
||||||
this.provider = provider;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public InvocationMarshaller createMarshaller ()
|
|
||||||
{
|
|
||||||
return new GameMarshaller();
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public void dispatchRequest (
|
|
||||||
ClientObject source, int methodId, Object[] args)
|
|
||||||
throws InvocationException
|
|
||||||
{
|
|
||||||
switch (methodId) {
|
|
||||||
case GameMarshaller.PLAYER_READY:
|
|
||||||
((GameProvider)provider).playerReady(
|
|
||||||
source
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
|
||||||
super.dispatchRequest(source, methodId, args);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -37,6 +37,7 @@ import com.threerings.presents.data.ClientObject;
|
|||||||
import com.threerings.presents.dobj.AttributeChangeListener;
|
import com.threerings.presents.dobj.AttributeChangeListener;
|
||||||
import com.threerings.presents.dobj.AttributeChangedEvent;
|
import com.threerings.presents.dobj.AttributeChangedEvent;
|
||||||
import com.threerings.presents.dobj.DObject;
|
import com.threerings.presents.dobj.DObject;
|
||||||
|
import com.threerings.presents.dobj.MessageEvent;
|
||||||
|
|
||||||
import com.threerings.crowd.chat.server.SpeakProvider;
|
import com.threerings.crowd.chat.server.SpeakProvider;
|
||||||
|
|
||||||
@@ -51,7 +52,6 @@ import com.threerings.parlor.data.ParlorCodes;
|
|||||||
import com.threerings.parlor.game.data.GameAI;
|
import com.threerings.parlor.game.data.GameAI;
|
||||||
import com.threerings.parlor.game.data.GameCodes;
|
import com.threerings.parlor.game.data.GameCodes;
|
||||||
import com.threerings.parlor.game.data.GameConfig;
|
import com.threerings.parlor.game.data.GameConfig;
|
||||||
import com.threerings.parlor.game.data.GameMarshaller;
|
|
||||||
import com.threerings.parlor.game.data.GameObject;
|
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;
|
||||||
@@ -68,37 +68,8 @@ import com.threerings.util.MessageBundle;
|
|||||||
* bodies in that location.
|
* bodies in that location.
|
||||||
*/
|
*/
|
||||||
public class GameManager extends PlaceManager
|
public class GameManager extends PlaceManager
|
||||||
implements ParlorCodes, GameCodes, GameProvider, AttributeChangeListener
|
implements ParlorCodes, GameCodes
|
||||||
{
|
{
|
||||||
// documentation inherited
|
|
||||||
protected void didInit ()
|
|
||||||
{
|
|
||||||
super.didInit();
|
|
||||||
|
|
||||||
// save off a casted reference to our config
|
|
||||||
_gameconfig = (GameConfig)_config;
|
|
||||||
|
|
||||||
// register this game manager
|
|
||||||
_managers.add(this);
|
|
||||||
|
|
||||||
// and start up a tick interval if we've not already got one
|
|
||||||
if (_tickInterval == null) {
|
|
||||||
_tickInterval = new Interval(CrowdServer.omgr) {
|
|
||||||
public void expired () {
|
|
||||||
tickAllGames();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
_tickInterval.schedule(TICK_DELAY, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// configure our AIs
|
|
||||||
for (int ii = 0; ii < _gameconfig.ais.length; ii++) {
|
|
||||||
if (_gameconfig.ais[ii] != null) {
|
|
||||||
setAI(ii, _gameconfig.ais[ii]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the configuration object for the game being managed by this
|
* Returns the configuration object for the game being managed by this
|
||||||
* manager.
|
* manager.
|
||||||
@@ -212,19 +183,6 @@ public class GameManager extends PlaceManager
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
* @param pidx the player index of the player added to the game.
|
|
||||||
*/
|
|
||||||
protected void playerWasAdded (Name player, int pidx)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the given player from the game. This is most likely to be
|
* 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
|
* used to allow players involved in a party game to leave the game
|
||||||
@@ -268,20 +226,6 @@ public class GameManager extends PlaceManager
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
protected void playerWasRemoved (Name player, int pidx)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replaces the player at the specified index and calls {@link
|
* Replaces the player at the specified index and calls {@link
|
||||||
* #playerWasReplaced} to let derived classes and delegates know
|
* #playerWasReplaced} to let derived classes and delegates know
|
||||||
@@ -304,14 +248,6 @@ public class GameManager extends PlaceManager
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a player has been replaced via a call to {@link
|
|
||||||
* #replacePlayer}.
|
|
||||||
*/
|
|
||||||
protected void playerWasReplaced (int pidx, Name oldPlayer, Name newPlayer)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the user object for the player with the specified index or
|
* Returns the user object for the player with the specified index or
|
||||||
* null if the player at that index is not online.
|
* null if the player at that index is not online.
|
||||||
@@ -467,6 +403,322 @@ public class GameManager extends PlaceManager
|
|||||||
SpeakProvider.sendInfo(_gameobj, msgbundle, msg);
|
SpeakProvider.sendInfo(_gameobj, msgbundle, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
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=" + _gameobj.which() + "].");
|
||||||
|
Thread.dumpStack();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TEMP: clear out our game end tracker
|
||||||
|
_gameEndTracker.clear();
|
||||||
|
|
||||||
|
// make sure everyone has turned up
|
||||||
|
if (!allPlayersReady()) {
|
||||||
|
Log.warning("Requested to start a game that is still " +
|
||||||
|
"awaiting players [game=" + _gameobj.which() +
|
||||||
|
", 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 (_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 " +
|
||||||
|
"[which=" + _gameobj.which() + "].");
|
||||||
|
_postponedStart = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Log.info("Postponing start of still-ending game " +
|
||||||
|
"[which=" + _gameobj.which() + "].");
|
||||||
|
_postponedStart = true;
|
||||||
|
// TEMP: track down weirdness
|
||||||
|
final Exception firstCall = new Exception();
|
||||||
|
// End: temp
|
||||||
|
CrowdServer.omgr.postRunnable(new Runnable() {
|
||||||
|
public void run () {
|
||||||
|
boolean result = startGame();
|
||||||
|
// TEMP: track down weirdness
|
||||||
|
if (!result && !_postponedStart) {
|
||||||
|
Log.warning("First call to startGame: ");
|
||||||
|
Log.logStackTrace(firstCall);
|
||||||
|
}
|
||||||
|
// End: temp
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ah, good, not postponing.
|
||||||
|
_postponedStart = false;
|
||||||
|
|
||||||
|
// let the derived class do its pre-start stuff
|
||||||
|
gameWillStart();
|
||||||
|
|
||||||
|
// transition the game to started
|
||||||
|
_gameobj.setState(GameObject.IN_PLAY);
|
||||||
|
|
||||||
|
// when our events are applied, we'll call gameDidStart()
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
|
||||||
|
announcePlayerGameOver(pidx);
|
||||||
|
|
||||||
|
} 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 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=" + _gameobj.which() + "].")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// END TEMP
|
||||||
|
|
||||||
|
if (!_gameobj.isInPlay()) {
|
||||||
|
Log.info("Refusing to end game that was not in play " +
|
||||||
|
"[game=" + _gameobj.which() + "].");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_gameobj.startTransaction();
|
||||||
|
try {
|
||||||
|
// let the derived class do its pre-end stuff
|
||||||
|
gameWillEnd();
|
||||||
|
|
||||||
|
// determine winners and set them in the game object
|
||||||
|
boolean[] winners = new boolean[getPlayerSlots()];
|
||||||
|
assignWinners(winners);
|
||||||
|
_gameobj.setWinners(winners);
|
||||||
|
|
||||||
|
// transition to the game over state
|
||||||
|
_gameobj.setState(GameObject.GAME_OVER);
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
_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
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
public boolean cancelGame ()
|
||||||
|
{
|
||||||
|
if (_gameobj.state != GameObject.GAME_OVER &&
|
||||||
|
_gameobj.state != GameObject.CANCELLED) {
|
||||||
|
_gameobj.setState(GameObject.CANCELLED);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 ()
|
||||||
|
{
|
||||||
|
return (_gameobj.state == GameObject.GAME_OVER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 ()
|
||||||
|
{
|
||||||
|
// let the derived class do its pre-reset stuff
|
||||||
|
gameWillReset();
|
||||||
|
// do the standard game start processing
|
||||||
|
gameWillStart();
|
||||||
|
// transition to in-play which will trigger a call to gameDidStart()
|
||||||
|
_gameobj.setState(GameObject.IN_PLAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
// a participant
|
||||||
|
if (!isPartyGame()) {
|
||||||
|
Log.warning("Received playerReady() from non-player? " +
|
||||||
|
"[caller=" + caller + "].");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make a note of this player's oid
|
||||||
|
_playerOids[pidx] = caller.getOid();
|
||||||
|
|
||||||
|
// if everyone is now ready to go, get things underway
|
||||||
|
if (allPlayersReady()) {
|
||||||
|
playersAllHere();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if all (non-AI) players have delivered their {@link
|
||||||
|
* #playerReady} notifications, false if they have not.
|
||||||
|
*/
|
||||||
|
public boolean allPlayersReady ()
|
||||||
|
{
|
||||||
|
for (int ii = 0; ii < getPlayerSlots(); ii++) {
|
||||||
|
if (!playerIsReady(ii)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
return (!_gameobj.isOccupiedPlayer(pidx) || // unoccupied slot
|
||||||
|
_playerOids[pidx] != 0 || // player is ready
|
||||||
|
isAI(pidx)); // player is AI
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 !isPartyGame();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
protected boolean needsAITick ()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
* @param pidx the player index of the player added to the game.
|
||||||
|
*/
|
||||||
|
protected void playerWasAdded (Name player, int pidx)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
protected void playerWasRemoved (Name player, int pidx)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a player has been replaced via a call to {@link
|
||||||
|
* #replacePlayer}.
|
||||||
|
*/
|
||||||
|
protected void playerWasReplaced (int pidx, Name oldPlayer, Name newPlayer)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Report to the knocked-out player's room that they were knocked out.
|
* Report to the knocked-out player's room that they were knocked out.
|
||||||
*/
|
*/
|
||||||
@@ -485,11 +737,41 @@ public class GameManager extends PlaceManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited
|
@Override // from PlaceManager
|
||||||
|
protected void didInit ()
|
||||||
|
{
|
||||||
|
super.didInit();
|
||||||
|
|
||||||
|
// save off a casted reference to our config
|
||||||
|
_gameconfig = (GameConfig)_config;
|
||||||
|
|
||||||
|
// register this game manager
|
||||||
|
_managers.add(this);
|
||||||
|
|
||||||
|
// and start up a tick interval if we've not already got one
|
||||||
|
if (_tickInterval == null) {
|
||||||
|
_tickInterval = new Interval(CrowdServer.omgr) {
|
||||||
|
public void expired () {
|
||||||
|
tickAllGames();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
_tickInterval.schedule(TICK_DELAY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// configure our AIs
|
||||||
|
for (int ii = 0; ii < _gameconfig.ais.length; ii++) {
|
||||||
|
if (_gameconfig.ais[ii] != null) {
|
||||||
|
setAI(ii, _gameconfig.ais[ii]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override // from PlaceManager
|
||||||
protected void didStartup ()
|
protected void didStartup ()
|
||||||
{
|
{
|
||||||
// obtain a casted reference to our game object
|
// obtain a casted reference to our game object
|
||||||
_gameobj = (GameObject)_plobj;
|
_gameobj = (GameObject)_plobj;
|
||||||
|
_gameobj.addListener(_stateListener);
|
||||||
|
|
||||||
// stick the players into the game object
|
// stick the players into the game object
|
||||||
_gameobj.setPlayers(_gameconfig.players);
|
_gameobj.setPlayers(_gameconfig.players);
|
||||||
@@ -504,11 +786,6 @@ public class GameManager extends PlaceManager
|
|||||||
// instantiate a player oid array which we'll fill in later
|
// instantiate a player oid array which we'll fill in later
|
||||||
_playerOids = new int[getPlayerSlots()];
|
_playerOids = new int[getPlayerSlots()];
|
||||||
|
|
||||||
// create and fill in our game service object
|
|
||||||
GameMarshaller service = (GameMarshaller)
|
|
||||||
_invmgr.registerDispatcher(new GameDispatcher(this), false);
|
|
||||||
_gameobj.setGameService(service);
|
|
||||||
|
|
||||||
// give delegates a chance to do their thing
|
// give delegates a chance to do their thing
|
||||||
super.didStartup();
|
super.didStartup();
|
||||||
|
|
||||||
@@ -542,30 +819,7 @@ public class GameManager extends PlaceManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override // from 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.
|
|
||||||
*/
|
|
||||||
protected boolean needsNoShowTimer ()
|
|
||||||
{
|
|
||||||
return !isPartyGame();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
protected boolean needsAITick ()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
protected void didShutdown ()
|
protected void didShutdown ()
|
||||||
{
|
{
|
||||||
super.didShutdown();
|
super.didShutdown();
|
||||||
@@ -579,11 +833,13 @@ public class GameManager extends PlaceManager
|
|||||||
_tickInterval = null;
|
_tickInterval = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear out our service registration
|
if (_gameobj != null) {
|
||||||
_invmgr.clearDispatcher(_gameobj.gameService);
|
// remove our state listener
|
||||||
|
_gameobj.removeListener(_stateListener);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited
|
@Override // from PlaceManager
|
||||||
protected void bodyLeft (int bodyOid)
|
protected void bodyLeft (int bodyOid)
|
||||||
{
|
{
|
||||||
// first resign the player from the game
|
// first resign the player from the game
|
||||||
@@ -704,86 +960,6 @@ 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.
|
|
||||||
*
|
|
||||||
* @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=" + _gameobj.which() + "].");
|
|
||||||
Thread.dumpStack();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TEMP: clear out our game end tracker
|
|
||||||
_gameEndTracker.clear();
|
|
||||||
|
|
||||||
// make sure everyone has turned up
|
|
||||||
if (!allPlayersReady()) {
|
|
||||||
Log.warning("Requested to start a game that is still " +
|
|
||||||
"awaiting players [game=" + _gameobj.which() +
|
|
||||||
", 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 (_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 " +
|
|
||||||
"[which=" + _gameobj.which() + "].");
|
|
||||||
_postponedStart = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Log.info("Postponing start of still-ending game " +
|
|
||||||
"[which=" + _gameobj.which() + "].");
|
|
||||||
_postponedStart = true;
|
|
||||||
// TEMP: track down weirdness
|
|
||||||
final Exception firstCall = new Exception();
|
|
||||||
// End: temp
|
|
||||||
CrowdServer.omgr.postRunnable(new Runnable() {
|
|
||||||
public void run () {
|
|
||||||
boolean result = startGame();
|
|
||||||
// TEMP: track down weirdness
|
|
||||||
if (!result && !_postponedStart) {
|
|
||||||
Log.warning("First call to startGame: ");
|
|
||||||
Log.logStackTrace(firstCall);
|
|
||||||
}
|
|
||||||
// End: temp
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ah, good, not postponing.
|
|
||||||
_postponedStart = false;
|
|
||||||
|
|
||||||
// let the derived class do its pre-start stuff
|
|
||||||
gameWillStart();
|
|
||||||
|
|
||||||
// transition the game to started
|
|
||||||
_gameobj.setState(GameObject.IN_PLAY);
|
|
||||||
|
|
||||||
// when our events are applied, we'll call gameDidStart()
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if we should start the game even without any humans.
|
* @return true if we should start the game even without any humans.
|
||||||
* Default implementation always returns false.
|
* Default implementation always returns false.
|
||||||
@@ -916,38 +1092,6 @@ 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);
|
|
||||||
|
|
||||||
announcePlayerGameOver(pidx);
|
|
||||||
|
|
||||||
} 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Announce to everyone in the game that a player's game has ended.
|
* Announce to everyone in the game that a player's game has ended.
|
||||||
*/
|
*/
|
||||||
@@ -982,66 +1126,6 @@ public class GameManager extends PlaceManager
|
|||||||
return (_gameobj.isInPlay() && _gameobj.getActivePlayerCount() == 1);
|
return (_gameobj.isInPlay() && _gameobj.getActivePlayerCount() == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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=" + _gameobj.which() + "].")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// END TEMP
|
|
||||||
|
|
||||||
if (!_gameobj.isInPlay()) {
|
|
||||||
Log.info("Refusing to end game that was not in play " +
|
|
||||||
"[game=" + _gameobj.which() + "].");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_gameobj.startTransaction();
|
|
||||||
try {
|
|
||||||
// let the derived class do its pre-end stuff
|
|
||||||
gameWillEnd();
|
|
||||||
|
|
||||||
// determine winners and set them in the game object
|
|
||||||
boolean[] winners = new boolean[getPlayerSlots()];
|
|
||||||
assignWinners(winners);
|
|
||||||
_gameobj.setWinners(winners);
|
|
||||||
|
|
||||||
// transition to the game over state
|
|
||||||
_gameobj.setState(GameObject.GAME_OVER);
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
_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
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
public boolean cancelGame ()
|
|
||||||
{
|
|
||||||
if (_gameobj.state != GameObject.GAME_OVER &&
|
|
||||||
_gameobj.state != GameObject.CANCELLED) {
|
|
||||||
_gameobj.setState(GameObject.CANCELLED);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assigns the final winning status for each player to their respect
|
* Assigns the final winning status for each player to their respect
|
||||||
* player index in the supplied array. This will be called by {@link
|
* player index in the supplied array. This will be called by {@link
|
||||||
@@ -1054,17 +1138,6 @@ public class GameManager extends PlaceManager
|
|||||||
Arrays.fill(winners, false);
|
Arrays.fill(winners, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 ()
|
|
||||||
{
|
|
||||||
return (_gameobj.state == GameObject.GAME_OVER);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the game is about to end, but before the game end
|
* Called when the game is about to end, but before the game end
|
||||||
* notification has been delivered to the players. Derived classes
|
* notification has been delivered to the players. Derived classes
|
||||||
@@ -1161,25 +1234,6 @@ 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.
|
|
||||||
*/
|
|
||||||
public void resetGame ()
|
|
||||||
{
|
|
||||||
// let the derived class do its pre-reset stuff
|
|
||||||
gameWillReset();
|
|
||||||
// do the standard game start processing
|
|
||||||
gameWillStart();
|
|
||||||
// transition to in-play which will trigger a call to gameDidStart()
|
|
||||||
_gameobj.setState(GameObject.IN_PLAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the game is about to reset, but before the board has
|
* 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
|
* been re-initialized or any other clearing out of game data has
|
||||||
@@ -1199,61 +1253,6 @@ public class GameManager extends PlaceManager
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void playerReady (ClientObject caller)
|
|
||||||
{
|
|
||||||
BodyObject plobj = (BodyObject)caller;
|
|
||||||
|
|
||||||
// get the user's player index
|
|
||||||
int pidx = _gameobj.getPlayerIndex(plobj.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
|
|
||||||
// a participant
|
|
||||||
if (!isPartyGame()) {
|
|
||||||
Log.warning("Received playerReady() from non-player? " +
|
|
||||||
"[caller=" + caller + "].");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// make a note of this player's oid
|
|
||||||
_playerOids[pidx] = plobj.getOid();
|
|
||||||
|
|
||||||
// if everyone is now ready to go, get things underway
|
|
||||||
if (allPlayersReady()) {
|
|
||||||
playersAllHere();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if all (non-AI) players have delivered their {@link
|
|
||||||
* #playerReady} notifications, false if they have not.
|
|
||||||
*/
|
|
||||||
public boolean allPlayersReady ()
|
|
||||||
{
|
|
||||||
for (int ii = 0; ii < getPlayerSlots(); ii++) {
|
|
||||||
if (!playerIsReady(ii)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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)
|
|
||||||
{
|
|
||||||
return (!_gameobj.isOccupiedPlayer(pidx) || // unoccupied slot
|
|
||||||
_playerOids[pidx] != 0 || // player is ready
|
|
||||||
isAI(pidx)); // player is AI
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gives game managers an opportunity to perform periodic processing
|
* Gives game managers an opportunity to perform periodic processing
|
||||||
* that is not driven by events generated by the player.
|
* that is not driven by events generated by the player.
|
||||||
@@ -1263,15 +1262,6 @@ public class GameManager extends PlaceManager
|
|||||||
// nothing for now
|
// nothing for now
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
public void attributeChanged (AttributeChangedEvent event)
|
|
||||||
{
|
|
||||||
if (event.getName().equals(GameObject.STATE)) {
|
|
||||||
stateDidChange(_committedState = event.getIntValue(),
|
|
||||||
((Integer)event.getOldValue()).intValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called periodically to call {@link #tick} on all registered game
|
* Called periodically to call {@link #tick} on all registered game
|
||||||
* managers.
|
* managers.
|
||||||
@@ -1311,6 +1301,17 @@ public class GameManager extends PlaceManager
|
|||||||
protected GameAI _ai;
|
protected GameAI _ai;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Listens for game state changes. */
|
||||||
|
protected AttributeChangeListener _stateListener =
|
||||||
|
new AttributeChangeListener() {
|
||||||
|
public void attributeChanged (AttributeChangedEvent event) {
|
||||||
|
if (event.getName().equals(GameObject.STATE)) {
|
||||||
|
stateDidChange(_committedState = event.getIntValue(),
|
||||||
|
((Integer)event.getOldValue()).intValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/** A reference to our game config. */
|
/** A reference to our game config. */
|
||||||
protected GameConfig _gameconfig;
|
protected GameConfig _gameconfig;
|
||||||
|
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
//
|
|
||||||
// $Id: GameProvider.java 4145 2006-05-24 01:24:24Z ray $
|
|
||||||
//
|
|
||||||
// Narya library - tools for developing networked games
|
|
||||||
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
|
||||||
// http://www.threerings.net/code/narya/
|
|
||||||
//
|
|
||||||
// This library is free software; you can redistribute it and/or modify it
|
|
||||||
// under the terms of the GNU Lesser General Public License as published
|
|
||||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
// Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public
|
|
||||||
// License along with this library; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
|
|
||||||
package com.threerings.parlor.game.server;
|
|
||||||
|
|
||||||
import com.threerings.parlor.game.client.GameService;
|
|
||||||
import com.threerings.presents.client.Client;
|
|
||||||
import com.threerings.presents.data.ClientObject;
|
|
||||||
import com.threerings.presents.server.InvocationException;
|
|
||||||
import com.threerings.presents.server.InvocationProvider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines the server-side of the {@link GameService}.
|
|
||||||
*/
|
|
||||||
public interface GameProvider extends InvocationProvider
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Handles a {@link GameService#playerReady} request.
|
|
||||||
*/
|
|
||||||
public void playerReady (ClientObject caller);
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user