diff --git a/src/java/com/threerings/parlor/game/GameManager.java b/src/java/com/threerings/parlor/game/GameManager.java index 7ab1535d0..91fe371f4 100644 --- a/src/java/com/threerings/parlor/game/GameManager.java +++ b/src/java/com/threerings/parlor/game/GameManager.java @@ -1,5 +1,5 @@ // -// $Id: GameManager.java,v 1.54 2002/11/05 02:24:42 mdb Exp $ +// $Id: GameManager.java,v 1.55 2002/11/26 09:12:10 mdb Exp $ package com.threerings.parlor.game; @@ -7,12 +7,14 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; +import com.samskivert.util.IntervalManager; import com.samskivert.util.StringUtil; import com.threerings.presents.data.ClientObject; import com.threerings.presents.dobj.AttributeChangeListener; import com.threerings.presents.dobj.AttributeChangedEvent; import com.threerings.presents.dobj.MessageEvent; +import com.threerings.presents.server.util.SafeInterval; import com.threerings.crowd.chat.SpeakProvider; @@ -21,7 +23,6 @@ import com.threerings.crowd.data.PlaceObject; import com.threerings.crowd.server.PlaceManager; import com.threerings.crowd.server.CrowdServer; -import com.threerings.crowd.server.CrowdServer; import com.threerings.crowd.server.PlaceManagerDelegate; import com.threerings.parlor.Log; @@ -382,6 +383,15 @@ public class GameManager extends PlaceManager // deliver a game ready notification to the player ParlorSender.gameIsReady(bobj, _gameobj.getOid()); } + + // start up a no-show timer unless this is a party game + if (!_gameconfig.isPartyGame()) { + IntervalManager.register(new SafeInterval(CrowdServer.omgr) { + public void run () { + checkForNoShows(); + } + }, NOSHOW_DELAY, null, false); + } } // documentation inherited @@ -438,6 +448,40 @@ public class GameManager extends PlaceManager } } + /** + * Called after the no-show delay has expired following the delivery + * of notifications to all players that the game is ready. + * Note: this is not called for party games. Those games have + * a human who decides when to start the game. + */ + protected void checkForNoShows () + { + // nothing to worry about if we're already started + if (_gameobj.state != GameObject.AWAITING_PLAYERS) { + return; + } + + // if there's no one in the room, go ahead and clear it out + if (_plobj.occupants.size() == 0) { + Log.info("Cancelling total no-show " + + "[game=" + _gameobj.which() + "]."); + placeBecameEmpty(); + + } else { + handlePartialNoShow(); + } + } + + /** + * 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 () + { + // cancel the game + _gameobj.setState(GameObject.CANCELLED); + } + /** * This is called when the game is ready to start (all players * involved have delivered their "am ready" notifications). It calls @@ -475,9 +519,7 @@ public class GameManager extends PlaceManager // transition the game to started _gameobj.setState(GameObject.IN_PLAY); - // do post-start processing - gameDidStart(); - + // when our events are applied, we'll call gameDidStart() return true; } @@ -647,25 +689,20 @@ 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} and {@link #gameDidReset}. - * The standard game start processing ({@link #gameWillStart} and - * {@link #gameDidStart}) will also be called (in between the calls to - * will and did reset). 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 resets. + * 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); - gameDidStart(); - - // let the derived class do its post-reset stuff - gameDidReset(); } /** @@ -684,22 +721,6 @@ public class GameManager extends PlaceManager }); } - /** - * Called after the game has been reset. Derived classes can override - * this to put whatever wheels they might need into motion now that - * the game is reset, but should be sure to call - * super.gameDidReset(). - */ - protected void gameDidReset () - { - // let our delegates do their business - applyToDelegates(new DelegateOp() { - public void apply (PlaceManagerDelegate delegate) { - ((GameManagerDelegate)delegate).gameDidReset(); - } - }); - } - // documentation inherited from interface public void playerReady (ClientObject caller) { @@ -794,6 +815,10 @@ public class GameManager extends PlaceManager { if (event.getName().equals(GameObject.STATE)) { switch (event.getIntValue()) { + case GameObject.IN_PLAY: + gameDidStart(); + break; + case GameObject.CANCELLED: // fall through to GAME_OVER case case GameObject.GAME_OVER: @@ -845,4 +870,8 @@ public class GameManager extends PlaceManager /** Our delegate operator to tick AIs. */ protected TickAIDelegateOp _tickAIOp; + + /** We give players 30 seconds to turn up in a puzzle and after that, + * they're considered a no show. */ + protected static final long NOSHOW_DELAY = 30 * 1000L; } diff --git a/src/java/com/threerings/parlor/game/GameManagerDelegate.java b/src/java/com/threerings/parlor/game/GameManagerDelegate.java index 5f21a51e6..dbe5e3c99 100644 --- a/src/java/com/threerings/parlor/game/GameManagerDelegate.java +++ b/src/java/com/threerings/parlor/game/GameManagerDelegate.java @@ -1,5 +1,5 @@ // -// $Id: GameManagerDelegate.java,v 1.6 2002/10/27 23:54:32 shaper Exp $ +// $Id: GameManagerDelegate.java,v 1.7 2002/11/26 09:12:10 mdb Exp $ package com.threerings.parlor.game; @@ -68,15 +68,6 @@ public class GameManagerDelegate extends PlaceManagerDelegate { } - /** - * Called after the game has been reset. Derived classes can override - * this to put whatever wheels they might need into motion now that - * the game is reset. - */ - public void gameDidReset () - { - } - /** * Called when the specified player has been set as an AI with the * given skill level (ranging from 0 to 100 inclusive.)