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; +} +}