diff --git a/src/as/com/threerings/parlor/game/client/GameController.as b/src/as/com/threerings/parlor/game/client/GameController.as
index a1b024d2..daddb4d3 100644
--- a/src/as/com/threerings/parlor/game/client/GameController.as
+++ b/src/as/com/threerings/parlor/game/client/GameController.as
@@ -250,14 +250,10 @@ public /*abstract*/ class GameController extends PlaceController
// clear out our game over flag
setGameOver(false);
-/* TODO
// let our delegates do their business
- applyToDelegates(new DelegateOp() {
- public void apply (PlaceControllerDelegate delegate) {
- ((GameControllerDelegate)delegate).gameDidStart();
- }
+ applyToDelegates(function (del :GameControllerDelegate) :void {
+ del.gameDidStart();
});
-*/
}
/**
@@ -267,14 +263,10 @@ public /*abstract*/ class GameController extends PlaceController
*/
protected function gameDidEnd () :void
{
-/* TODO
// let our delegates do their business
- applyToDelegates(new DelegateOp() {
- public void apply (PlaceControllerDelegate delegate) {
- ((GameControllerDelegate)delegate).gameDidEnd();
- }
+ applyToDelegates(function (del :GameControllerDelegate) :void {
+ del.gameDidEnd();
});
-*/
}
/**
@@ -282,14 +274,10 @@ public /*abstract*/ class GameController extends PlaceController
*/
protected function gameWasCancelled () :void
{
-/*
// let our delegates do their business
- applyToDelegates(new DelegateOp() {
- public void apply (PlaceControllerDelegate delegate) {
- ((GameControllerDelegate)delegate).gameWasCancelled();
- }
+ applyToDelegates(function (del :GameControllerDelegate) :void {
+ del.gameWasCancelled();
});
-*/
}
/**
@@ -299,14 +287,10 @@ public /*abstract*/ class GameController extends PlaceController
*/
protected function gameWillReset () :void
{
-/* TODO
// let our delegates do their business
- applyToDelegates(new DelegateOp() {
- public void apply (PlaceControllerDelegate delegate) {
- ((GameControllerDelegate)delegate).gameWillReset();
- }
+ applyToDelegates(function (del :GameControllerDelegate) :void {
+ del.gameWillReset();
});
-*/
}
/**
diff --git a/src/as/com/threerings/parlor/game/client/GameControllerDelegate.as b/src/as/com/threerings/parlor/game/client/GameControllerDelegate.as
new file mode 100644
index 00000000..d461ea80
--- /dev/null
+++ b/src/as/com/threerings/parlor/game/client/GameControllerDelegate.as
@@ -0,0 +1,75 @@
+//
+// $Id: GameControllerDelegate.java 3381 2005-03-03 19:36:34Z mdb $
+//
+// 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.crowd.client.PlaceControllerDelegate;
+
+/**
+ * Extends the {@link PlaceControllerDelegate} mechanism with game
+ * controller specific methods.
+ */
+public class GameControllerDelegate extends PlaceControllerDelegate
+{
+ /**
+ * Provides the delegate with a reference to the game controller for
+ * which it is delegating.
+ */
+ public function GameControllerDelegate (ctrl :GameController)
+ {
+ super(ctrl);
+ }
+
+ /**
+ * Called when the game transitions to the IN_PLAY
+ * state. This happens when all of the players have arrived and the
+ * server starts the game.
+ */
+ public function gameDidStart () :void
+ {
+ }
+
+ /**
+ * Called when the game transitions to the GAME_OVER
+ * state. This happens when the game reaches some end condition by
+ * normal means (is not cancelled or aborted).
+ */
+ public function gameDidEnd () :void
+ {
+ }
+
+ /**
+ * Called when the game was cancelled for some reason.
+ */
+ public function gameWasCancelled () :void
+ {
+ }
+
+ /**
+ * Called to give derived classes a chance to display animations, send
+ * a final packet, or do any other business they care to do when the
+ * game is about to reset.
+ */
+ public function gameWillReset () :void
+ {
+ }
+}
+}
diff --git a/src/as/com/threerings/parlor/turn/client/TurnGameController.as b/src/as/com/threerings/parlor/turn/client/TurnGameController.as
new file mode 100644
index 00000000..6f4e6f7c
--- /dev/null
+++ b/src/as/com/threerings/parlor/turn/client/TurnGameController.as
@@ -0,0 +1,45 @@
+//
+// $Id: TurnGameController.java 3381 2005-03-03 19:36:34Z mdb $
+//
+// 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.turn.client {
+
+import com.threerings.util.Name;
+
+import com.threerings.parlor.game.client.GameController;
+
+/**
+ * Games that wish to make use of the turn game services should have their
+ * controller implement this interface and create an instance of {@link
+ * TurnGameControllerDelegate} which should be passed to {@link
+ * GameController#addDelegate}.
+ */
+public interface TurnGameController
+{
+ /**
+ * Called when the turn changed. This indicates the start of a turn
+ * and the user interface should adjust itself accordingly (activating
+ * controls if it is our turn and deactivating them if it is not).
+ *
+ * @param turnHolder the username of the new holder of the turn.
+ */
+ function turnDidChange (turnHolder :Name) :void;
+}
+}
diff --git a/src/as/com/threerings/parlor/turn/client/TurnGameControllerDelegate.as b/src/as/com/threerings/parlor/turn/client/TurnGameControllerDelegate.as
new file mode 100644
index 00000000..7b76e2a7
--- /dev/null
+++ b/src/as/com/threerings/parlor/turn/client/TurnGameControllerDelegate.as
@@ -0,0 +1,157 @@
+//
+// $Id: TurnGameControllerDelegate.java 3758 2005-11-10 23:18:58Z mdb $
+//
+// 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.turn.client {
+
+import com.threerings.util.Name;
+
+import com.threerings.presents.dobj.AttributeChangedEvent;
+import com.threerings.presents.dobj.AttributeChangeListener;
+
+import com.threerings.crowd.data.BodyObject;
+import com.threerings.crowd.data.PlaceConfig;
+import com.threerings.crowd.data.PlaceObject;
+import com.threerings.crowd.util.CrowdContext;
+
+import com.threerings.parlor.game.client.GameController;
+import com.threerings.parlor.game.client.GameControllerDelegate;
+import com.threerings.parlor.game.data.GameObject;
+
+import com.threerings.parlor.turn.data.TurnGameObject;
+
+/**
+ * Performs the client-side processing for a turn-based game. Games which
+ * wish to make use of these services must construct a delegate and call
+ * out to it at the appropriate times (see the method documentation for
+ * which methods should be called when). The game's controller must also
+ * implement the {@link TurnGameController} interface so that it can be
+ * notified when turn-based game events take place.
+ */
+public class TurnGameControllerDelegate extends GameControllerDelegate
+ implements AttributeChangeListener
+{
+ /** A special value used to communicate to the client that the current
+ * turn holder was replaced (perhaps due to disconnection or departure
+ * and being replaced by an AI). */
+ public static const TURN_HOLDER_REPLACED :Name =
+ new Name("__TURN_HOLDER_REPLACED__");
+
+ /**
+ * Constructs a delegate which will call back to the supplied {@link
+ * TurnGameController} implementation wen turn-based game related
+ * things happen.
+ */
+ public function TurnGameControllerDelegate (tgctrl :TurnGameController)
+ {
+ super(GameController(tgctrl));
+
+ // keep this around for later
+ _tgctrl = tgctrl;
+ }
+
+ /**
+ * Returns true if the game is in progress and it is our turn; false
+ * otherwise.
+ */
+ public function isOurTurn () :Boolean
+ {
+ var self :BodyObject =
+ (_ctx.getClient().getClientObject() as BodyObject);
+ return (_gameObj.isInPlay() &&
+ self.getVisibleName().equals(_turnGame.getTurnHolder()));
+ }
+
+ /**
+ * Returns the index of the current turn holder as configured in the
+ * game object.
+ *
+ * @return the index into the players array of the current turn holder
+ * or -1 if there is no current turn holder.
+ */
+ public function getTurnHolderIndex () :int
+ {
+ return _gameObj.getPlayerIndex(_turnGame.getTurnHolder());
+ }
+
+ // documentation inherited
+ override public function init (ctx :CrowdContext, config :PlaceConfig) :void
+ {
+ _ctx = ctx;
+ }
+
+ // documentation inherited
+ override public function willEnterPlace (plobj :PlaceObject) :void
+ {
+ // get a casted reference to the object
+ _gameObj = (plobj as GameObject);
+ _turnGame = (plobj as TurnGameObject);
+ _thfield = _turnGame.getTurnHolderFieldName();
+
+ // and add ourselves as a listener
+ plobj.addListener(this);
+ }
+
+ // documentation inherited
+ override public function didLeavePlace (plobj :PlaceObject) :void
+ {
+ // remove our listenership
+ plobj.removeListener(this);
+
+ // clean up
+ _turnGame = null;
+ }
+
+ // documentation inherited
+ public function attributeChanged (event :AttributeChangedEvent) :void
+ {
+ // handle turn changes
+ if (event.getName() == _thfield) {
+ var name :Name = (event.getValue() as Name);
+ var oname :Name = (event.getOldValue() as Name);
+ if (TURN_HOLDER_REPLACED.equals(name) ||
+ TURN_HOLDER_REPLACED.equals(oname)) {
+ // small hackery: ignore the turn holder being set to
+ // TURN_HOLDER_REPLACED as it means that we're replacing
+ // the current turn holder rather than switching turns;
+ // also ignore the new turn holder when we switch from THR
+ // to a real name again
+ } else {
+ _tgctrl.turnDidChange(name);
+ }
+ }
+ }
+
+ /** The turn game controller for whom we are delegating. */
+ protected var _tgctrl :TurnGameController;
+
+ /** A reference to our client context. */
+ protected var _ctx :CrowdContext;
+
+ /** A reference to our game object. */
+ protected var _gameObj :GameObject;
+
+ /** A casted reference to our game object as a turn game. */
+ protected var _turnGame :TurnGameObject;
+
+ /** The name of the turn holder field. */
+ protected var _thfield :String;
+}
+}
diff --git a/src/as/com/threerings/parlor/turn/data/TurnGameObject.as b/src/as/com/threerings/parlor/turn/data/TurnGameObject.as
new file mode 100644
index 00000000..7356014a
--- /dev/null
+++ b/src/as/com/threerings/parlor/turn/data/TurnGameObject.as
@@ -0,0 +1,73 @@
+//
+// $Id: TurnGameObject.java 3667 2005-08-03 07:46:54Z mdb $
+//
+// 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.turn.data {
+
+import com.threerings.io.TypedArray;
+
+import com.threerings.util.Name;
+
+import com.threerings.parlor.game.data.GameObject;
+
+/**
+ * Games that wish to support turn-based play must implement this
+ * interface with their {@link GameObject}.
+ */
+public interface TurnGameObject
+{
+ /** A special value used to communicate to the client that the current
+ * turn holder was replaced (perhaps due to disconnection or departure
+ * and being replaced by an AI). */
+// public static final Name TURN_HOLDER_REPLACED =
+// new Name("__TURN_HOLDER_REPLACED__");
+
+ /**
+ * Returns the distributed object field name of the
+ * turnHolder field in the object that implements this
+ * interface.
+ */
+ function getTurnHolderFieldName () :String;
+
+ /**
+ * Returns the username of the player who is currently taking their
+ * turn in this turn-based game or null if no user
+ * currently holds the turn.
+ */
+ function getTurnHolder () :Name;
+
+ /**
+ * Requests that the turnHolder field be set to the specified
+ * value.
+ */
+ function setTurnHolder (turnHolder :Name) :void;
+
+ /**
+ * Returns the array of player names involved in the game.
+ */
+ function getPlayers () :TypedArray /* of Name */;
+
+ /**
+ * Returns true if the game is in play, false if not. If a game is not in
+ * play after a turn has ended, the next turn will not be started.
+ */
+ function isInPlay () :Boolean;
+}
+}