Revamped EZGame to work over the security boundary.
Now, instead of implementing "Game" and having the EZGame object assigned to you, you create it yourself using your top-level component. You must register listeners manually, and keyboard focus is currently an issue that I'm working on. git-svn-id: svn+ssh://src.earth.threerings.net/vilya/trunk@137 c613c5cb-e716-0410-b11b-feb51c14d237
This commit is contained in:
@@ -6,9 +6,9 @@ package com.threerings.ezgame {
|
||||
*/
|
||||
public class CardDeck
|
||||
{
|
||||
public function CardDeck (gameObj :EZGame, deckName :String = "deck")
|
||||
public function CardDeck (gameCtrl :EZGameControl, deckName :String = "deck")
|
||||
{
|
||||
_gameObj = gameObj;
|
||||
_gameCtrl = gameCtrl;
|
||||
_deckName = deckName;
|
||||
|
||||
var deck :Array = new Array();
|
||||
@@ -19,23 +19,23 @@ public class CardDeck
|
||||
}
|
||||
}
|
||||
|
||||
_gameObj.setCollection(_deckName, deck);
|
||||
_gameCtrl.setCollection(_deckName, deck);
|
||||
}
|
||||
|
||||
public function dealToPlayer (
|
||||
playerIdx :int, count :int, msgName :String) :void
|
||||
{
|
||||
// TODO: support the callback
|
||||
_gameObj.dealFromCollection(_deckName, count, msgName, null, playerIdx);
|
||||
_gameCtrl.dealFromCollection(_deckName, count, msgName, null, playerIdx);
|
||||
}
|
||||
|
||||
public function dealToData (count :int, propName :String) :void
|
||||
{
|
||||
_gameObj.dealFromCollection(_deckName, count, propName, null);
|
||||
_gameCtrl.dealFromCollection(_deckName, count, propName, null);
|
||||
}
|
||||
|
||||
/** The game object. */
|
||||
protected var _gameObj :EZGame;
|
||||
/** The game control. */
|
||||
protected var _gameCtrl :EZGameControl;
|
||||
|
||||
/** The name of our deck. */
|
||||
protected var _deckName :String;
|
||||
|
||||
@@ -8,20 +8,20 @@ import flash.events.Event;
|
||||
public /*abstract*/ class EZEvent extends Event
|
||||
{
|
||||
/**
|
||||
* Access the game object to which this event applies.
|
||||
* Access the game control to which this event applies.
|
||||
*/
|
||||
public function get gameObject () :EZGame
|
||||
public function get gameControl () :EZGameControl
|
||||
{
|
||||
return _ezgame;
|
||||
}
|
||||
|
||||
public function EZEvent (type :String, ezgame :EZGame)
|
||||
public function EZEvent (type :String, ezgame :EZGameControl)
|
||||
{
|
||||
super(type);
|
||||
_ezgame = ezgame;
|
||||
}
|
||||
|
||||
/** The game object for this event. */
|
||||
protected var _ezgame :EZGame;
|
||||
/** The game control for this event. */
|
||||
protected var _ezgame :EZGameControl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,219 +0,0 @@
|
||||
package com.threerings.ezgame {
|
||||
|
||||
import flash.events.IEventDispatcher;
|
||||
|
||||
/**
|
||||
* The game object that you'll be using to manage your game.
|
||||
*/
|
||||
public interface EZGame
|
||||
extends IEventDispatcher
|
||||
{
|
||||
/**
|
||||
* Data accessor.
|
||||
*/
|
||||
function get data () :Object;
|
||||
|
||||
/**
|
||||
* Get a property from data.
|
||||
*/
|
||||
function get (propName :String, index :int = -1) :Object;
|
||||
|
||||
/**
|
||||
* Set a property that will be distributed.
|
||||
*/
|
||||
function set (propName :String, value :Object, index :int = -1) :void;
|
||||
|
||||
/**
|
||||
* Register an object to receive whatever events it should receive,
|
||||
* based on which event listeners it implements. Note that it is not
|
||||
* necessary to register any objects which appear on the display list,
|
||||
* as they'll be registered automatically.
|
||||
*/
|
||||
function registerListener (obj :Object) :void;
|
||||
|
||||
/**
|
||||
* Unregister the specified object from receiving events.
|
||||
*/
|
||||
function unregisterListener (obj :Object) :void;
|
||||
|
||||
/**
|
||||
* Set the specified collection to contain the specified values,
|
||||
* clearing any previous values.
|
||||
*/
|
||||
function setCollection (collName :String, values :Array) :void;
|
||||
|
||||
/**
|
||||
* Add to an existing collection. If it doesn't exist, it will
|
||||
* be created. The new values will be inserted randomly into the
|
||||
* collection.
|
||||
*/
|
||||
function addToCollection (collName :String, values :Array) :void;
|
||||
|
||||
/**
|
||||
* Pick (do not remove) the specified number of elements from a collection,
|
||||
* and distribute them to a specific player or set them as a property
|
||||
* in the game data.
|
||||
*
|
||||
* @param collName the collection name.
|
||||
* @param count the number of elements to pick
|
||||
* @param msgOrPropName the name of the message or property
|
||||
* that will contain the picked elements.
|
||||
* @param playerIndex if -1 (or unset), the picked elements should be
|
||||
* set on the gameObject as a property for all to see.
|
||||
* If a playerIndex is specified, only that player will receive
|
||||
* the elements as a message.
|
||||
*/
|
||||
// TODO: a way to specify exclusive picks vs. duplicate-OK picks?
|
||||
function pickFromCollection (
|
||||
collName :String, count :int, msgOrPropName :String,
|
||||
playerIndex :int = -1) :void;
|
||||
|
||||
/**
|
||||
* Deal (remove) the specified number of elements from a collection,
|
||||
* and distribute them to a specific player or set them as a property
|
||||
* in the game data.
|
||||
*
|
||||
* @param collName the collection name.
|
||||
* @param count the number of elements to pick
|
||||
* @param msgOrPropName the name of the message or property
|
||||
* that will contain the picked elements.
|
||||
* @param playerIndex if -1 (or unset), the picked elements should be
|
||||
* set on the gameObject as a property for all to see.
|
||||
* If a playerIndex is specified, only that player will receive
|
||||
* the elements as a message.
|
||||
*/
|
||||
// TODO: figure out the method signature of the callback
|
||||
function dealFromCollection (
|
||||
collName :String, count :int, msgOrPropName :String,
|
||||
callBack :Function = null, playerIndex :int = -1) :void;
|
||||
|
||||
/**
|
||||
* Merge the specified collection into the other collection.
|
||||
* The source collection will be destroyed. The elements from
|
||||
* The source collection will be shuffled and appended to the end
|
||||
* of the destination collection.
|
||||
*/
|
||||
function mergeCollection (srcColl :String, intoColl :String) :void;
|
||||
|
||||
/**
|
||||
* Send a "message" to other clients subscribed to the game.
|
||||
* These is similar to setting a property, except that the
|
||||
* value will not be saved- it will merely end up coming out
|
||||
* as a MessageReceivedEvent.
|
||||
*
|
||||
* @param playerIndex if -1, sends to all players, otherwise
|
||||
* the message will be private to just one player
|
||||
*/
|
||||
function sendMessage (
|
||||
messageName :String, value :Object, playerIndex :int = -1) :void;
|
||||
|
||||
/**
|
||||
* Start the ticker with the specified name. It will deliver
|
||||
* messages to the game object at the specified delay,
|
||||
* the value of each message being a single integer, starting with 0
|
||||
* and increasing by one with each messsage.
|
||||
*/
|
||||
function startTicker (tickerName :String, msOfDelay :int) :void;
|
||||
|
||||
/**
|
||||
* Stop the specified ticker.
|
||||
*/
|
||||
function stopTicker (tickerName :String) :void;
|
||||
|
||||
/**
|
||||
* Send a message that will be heard by everyone in the game room,
|
||||
* even observers.
|
||||
*/
|
||||
function sendChat (msg :String) :void;
|
||||
|
||||
/**
|
||||
* Display the specified message immediately locally: not sent
|
||||
* to any other players or observers in the game room.
|
||||
*/
|
||||
function localChat (msg :String) :void;
|
||||
|
||||
/**
|
||||
* Get the number of players currently in the game.
|
||||
*/
|
||||
function getPlayerCount () :int;
|
||||
|
||||
/**
|
||||
* Get the player names, as an array.
|
||||
*/
|
||||
function getPlayerNames () :Array /* of String */;
|
||||
|
||||
/**
|
||||
* Get the index into the player names array of the current player,
|
||||
* or -1 if the user is not a player.
|
||||
*/
|
||||
function getMyIndex () :int;
|
||||
|
||||
/**
|
||||
* Get the turn holder's index, or -1 if it's nobody's turn.
|
||||
*/
|
||||
function getTurnHolderIndex () :int;
|
||||
|
||||
/**
|
||||
* Get the indexes of the winners
|
||||
*/
|
||||
function getWinnerIndexes () :Array /* of int */;
|
||||
|
||||
/**
|
||||
* A convenience method to just check if it's our turn.
|
||||
*/
|
||||
function isMyTurn () :Boolean;
|
||||
|
||||
/**
|
||||
* Is the game currently in play?
|
||||
*/
|
||||
function isInPlay () :Boolean;
|
||||
|
||||
/**
|
||||
* End the current turn. If no next player index is specified,
|
||||
* then the next player after the current one is used.
|
||||
*/
|
||||
function endTurn (optionalNextPlayerIndex :int = -1) :void;
|
||||
|
||||
/**
|
||||
* End the game. The specified player indexes are winners!
|
||||
*/
|
||||
function endGame (winnerIndex :int, ... rest) :void;
|
||||
|
||||
// function getCurrentRoom () :int;
|
||||
//
|
||||
// function sendPlayerToRoom (playerIndex :int, room :int) :void
|
||||
|
||||
/**
|
||||
* Get the user-specific game data for the specified user. The
|
||||
* first time this is requested per game instance it will be retrieved
|
||||
* from the database. After that, it will be returned from memory.
|
||||
*/
|
||||
function getUserCookie (playerIndex :int, callback :Function) :void;
|
||||
|
||||
/**
|
||||
* Store persistent data that can later be retrieved by an instance
|
||||
* of this game. The maximum size of this data is 4096 bytes AFTER
|
||||
* AMF3 encoding.
|
||||
*
|
||||
* Note: there is no playerIndex parameter because a cookie may only
|
||||
* be stored for the current player.
|
||||
*
|
||||
* @return false if the cookie could not be encoded to 4096 bytes
|
||||
* or less; true if the cookie is going to try to be saved. There is
|
||||
* no guarantee it will be saved and no way to find out if it failed,
|
||||
* but if it fails it will be because the shit hit the fan so hard that
|
||||
* there's nothing you can do anyway.
|
||||
*/
|
||||
function setUserCookie (cookie :Object) :Boolean;
|
||||
//
|
||||
// /**
|
||||
// * Check to see if the user has the specified token.
|
||||
// */
|
||||
// function checkUserToken (token :String, callback :Function) :void;
|
||||
//
|
||||
// /**
|
||||
// * Take the user to a purchase page.
|
||||
// */
|
||||
// function purchaseUserToken (token :String, callback :Function) :void;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,376 @@
|
||||
package com.threerings.ezgame {
|
||||
|
||||
import flash.errors.IllegalOperationError;
|
||||
|
||||
import flash.events.Event;
|
||||
import flash.events.EventDispatcher;
|
||||
|
||||
import flash.display.DisplayObject;
|
||||
|
||||
public class EZGameControl extends EventDispatcher
|
||||
{
|
||||
/**
|
||||
* Create an EZGameControl object using some display object currently
|
||||
* on the hierarchy.
|
||||
*/
|
||||
public function EZGameControl (disp :DisplayObject)
|
||||
{
|
||||
var event :DynEvent = new DynEvent();
|
||||
event.userProps = new Object();
|
||||
populateProperties(event.userProps);
|
||||
disp.root.loaderInfo.sharedEvents.dispatchEvent(event);
|
||||
setEZProps(event.ezProps);
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function get data () :Object
|
||||
{
|
||||
return _gameData;
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function get (propName :String, index :int = -1) :Object
|
||||
{
|
||||
var value :Object = data[propName];
|
||||
if (index >= 0) {
|
||||
if (value is Array) {
|
||||
return (value as Array)[index];
|
||||
|
||||
} else {
|
||||
throw new ArgumentError("Property " + propName +
|
||||
" is not an array.");
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function set (propName :String, value :Object, index :int = -1) :void
|
||||
{
|
||||
callEZCode("setProperty_v1", propName, value, index);
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function registerListener (obj :Object) :void
|
||||
{
|
||||
if (obj is MessageReceivedListener) {
|
||||
var mrl :MessageReceivedListener = (obj as MessageReceivedListener);
|
||||
addEventListener(
|
||||
MessageReceivedEvent.TYPE, mrl.messageReceived,
|
||||
false, 0, true);
|
||||
}
|
||||
if (obj is PropertyChangedListener) {
|
||||
var pcl :PropertyChangedListener = (obj as PropertyChangedListener);
|
||||
addEventListener(
|
||||
PropertyChangedEvent.TYPE, pcl.propertyChanged,
|
||||
false, 0, true);
|
||||
}
|
||||
if (obj is StateChangedListener) {
|
||||
var scl :StateChangedListener = (obj as StateChangedListener);
|
||||
addEventListener(
|
||||
StateChangedEvent.GAME_STARTED, scl.stateChanged,
|
||||
false, 0, true);
|
||||
addEventListener(
|
||||
StateChangedEvent.TURN_CHANGED, scl.stateChanged,
|
||||
false, 0, true);
|
||||
addEventListener(
|
||||
StateChangedEvent.GAME_ENDED, scl.stateChanged,
|
||||
false, 0, true);
|
||||
}
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function unregisterListener (obj :Object) :void
|
||||
{
|
||||
if (obj is MessageReceivedListener) {
|
||||
var mrl :MessageReceivedListener = (obj as MessageReceivedListener);
|
||||
removeEventListener(
|
||||
MessageReceivedEvent.TYPE, mrl.messageReceived);
|
||||
}
|
||||
if (obj is PropertyChangedListener) {
|
||||
var pcl :PropertyChangedListener = (obj as PropertyChangedListener);
|
||||
removeEventListener(
|
||||
PropertyChangedEvent.TYPE, pcl.propertyChanged);
|
||||
}
|
||||
if (obj is StateChangedListener) {
|
||||
var scl :StateChangedListener = (obj as StateChangedListener);
|
||||
removeEventListener(
|
||||
StateChangedEvent.GAME_STARTED, scl.stateChanged);
|
||||
removeEventListener(
|
||||
StateChangedEvent.TURN_CHANGED, scl.stateChanged);
|
||||
removeEventListener(
|
||||
StateChangedEvent.GAME_ENDED, scl.stateChanged);
|
||||
}
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function setCollection (collName :String, values :Array) :void
|
||||
{
|
||||
populateCollection(collName, values, true);
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function addToCollection (collName :String, values :Array) :void
|
||||
{
|
||||
populateCollection(collName, values, false);
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function pickFromCollection (
|
||||
collName :String, count :int, msgOrPropName :String,
|
||||
playerIndex :int = -1) :void
|
||||
{
|
||||
getFromCollection(collName, count, msgOrPropName, playerIndex,
|
||||
false, null);
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function dealFromCollection (
|
||||
collName :String, count :int, msgOrPropName :String,
|
||||
callback :Function = null, playerIndex :int = -1) :void
|
||||
{
|
||||
getFromCollection(collName, count, msgOrPropName, playerIndex,
|
||||
true, callback);
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function mergeCollection (srcColl :String, intoColl :String) :void
|
||||
{
|
||||
callEZCode("mergeCollection_v1", srcColl, intoColl);
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function sendMessage (
|
||||
messageName :String, value :Object, playerIndex :int = -1) :void
|
||||
{
|
||||
callEZCode("sendMessage_v1", messageName, value, playerIndex);
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function startTicker (tickerName :String, msOfDelay :int) :void
|
||||
{
|
||||
callEZCode("setTicker_v1", tickerName, msOfDelay);
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function stopTicker (tickerName :String) :void
|
||||
{
|
||||
startTicker(tickerName, 0);
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function sendChat (msg :String) :void
|
||||
{
|
||||
callEZCode("sendChat_v1", msg);
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function localChat (msg :String) :void
|
||||
{
|
||||
callEZCode("localChat_v1", msg);
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function getPlayerCount () :int
|
||||
{
|
||||
return int(callEZCode("getPlayerCount_v1"));
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function getPlayerNames () :Array
|
||||
{
|
||||
return (callEZCode("getPlayerNames_v1") as Array);
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function getMyIndex () :int
|
||||
{
|
||||
return int(callEZCode("getMyIndex_v1"));
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function getTurnHolderIndex () :int
|
||||
{
|
||||
return int(callEZCode("getTurnHolderIndex_v1"));
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function getWinnerIndexes () :Array /* of int */
|
||||
{
|
||||
return (callEZCode("getWinnerIndexes_v1") as Array);
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function getUserCookie (playerIndex :int, callback :Function) :void
|
||||
{
|
||||
callEZCode("getUserCookie_v1", playerIndex, callback);
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function setUserCookie (cookie :Object) :Boolean
|
||||
{
|
||||
return Boolean(callEZCode("setUserCookie_v1", cookie));
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function isMyTurn () :Boolean
|
||||
{
|
||||
return Boolean(callEZCode("isMyTurn_v1"));
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function isInPlay () :Boolean
|
||||
{
|
||||
return Boolean(callEZCode("isInPlay_v1"));
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function endTurn (nextPlayerIndex :int = -1) :void
|
||||
{
|
||||
callEZCode("endTurn_v1", nextPlayerIndex);
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function endGame (... winnerIndexes) :void
|
||||
{
|
||||
var args :Array = winnerIndexes;
|
||||
args.unshift("endGame_v1");
|
||||
|
||||
// goddamn var-args complications in actionscript
|
||||
callEZCode.apply(null, args);
|
||||
}
|
||||
|
||||
override public function willTrigger (type :String) :Boolean
|
||||
{
|
||||
throw new IllegalOperationError();
|
||||
}
|
||||
|
||||
override public function dispatchEvent (event :Event) :Boolean
|
||||
{
|
||||
// Ideally we want to not be an IEventDispatcher so that people
|
||||
// won't try to do this on us, but if we do that, then some other
|
||||
// object will be the target during dispatch, and that's confusing.
|
||||
// It's really nice to be able to
|
||||
throw new IllegalOperationError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for setCollection and addToCollection.
|
||||
*/
|
||||
protected function populateCollection (
|
||||
collName :String, values :Array, clearExisting :Boolean) :void
|
||||
{
|
||||
callEZCode("populateCollection_v1", collName, values, clearExisting);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for pickFromCollection and dealFromCollection.
|
||||
*/
|
||||
protected function getFromCollection(
|
||||
collName :String, count :int, msgOrPropName :String, playerIndex :int,
|
||||
consume :Boolean, callback :Function) :void
|
||||
{
|
||||
callEZCode("getFromCollection_v1", collName, count, msgOrPropName,
|
||||
playerIndex, consume, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate any properties or functions we want to expose to
|
||||
* the other side of the ezgame security boundary.
|
||||
*/
|
||||
protected function populateProperties (o :Object) :void
|
||||
{
|
||||
o["propertyWasSet_v1"] = propertyWasSet_v1;
|
||||
o["turnDidChange_v1"] = turnDidChange_v1;
|
||||
o["messageReceived_v1"] = messageReceived_v1;
|
||||
o["gameDidStart_v1"] = gameDidStart_v1;
|
||||
o["gameDidEnd_v1"] = gameDidEnd_v1;
|
||||
}
|
||||
|
||||
private function propertyWasSet_v1 (
|
||||
name :String, newValue :Object, oldValue :Object, index :int) :void
|
||||
{
|
||||
dispatch(
|
||||
new PropertyChangedEvent(this, name, newValue, oldValue, index));
|
||||
}
|
||||
|
||||
private function turnDidChange_v1 () :void
|
||||
{
|
||||
dispatch(new StateChangedEvent(StateChangedEvent.TURN_CHANGED, this));
|
||||
}
|
||||
|
||||
private function messageReceived_v1 (name :String, value :Object) :void
|
||||
{
|
||||
dispatch(new MessageReceivedEvent(this, name, value));
|
||||
}
|
||||
|
||||
private function gameDidStart_v1 () :void
|
||||
{
|
||||
dispatch(new StateChangedEvent(StateChangedEvent.GAME_STARTED, this));
|
||||
}
|
||||
|
||||
private function gameDidEnd_v1 () :void
|
||||
{
|
||||
dispatch(new StateChangedEvent(StateChangedEvent.GAME_ENDED, this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the properties we received from the EZ game framework
|
||||
* on the other side of the security boundary.
|
||||
*/
|
||||
protected function setEZProps (o :Object) :void
|
||||
{
|
||||
// get our gamedata
|
||||
_gameData = o.gameData;
|
||||
|
||||
// and functions
|
||||
_funcs = o;
|
||||
}
|
||||
|
||||
protected function callEZCode (name :String, ... args) :*
|
||||
{
|
||||
if (_funcs != null) {
|
||||
try {
|
||||
var func :Function = (_funcs[name] as Function);
|
||||
if (func != null) {
|
||||
return func.apply(null, args);
|
||||
}
|
||||
} catch (err :Error) {
|
||||
trace("Unable to call ez code: " + err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Secret function to dispatch property changed events.
|
||||
*/
|
||||
internal function dispatch (event :Event) :void
|
||||
{
|
||||
try {
|
||||
super.dispatchEvent(event);
|
||||
} catch (err :Error) {
|
||||
trace("Error dispatching event to user game.");
|
||||
trace(err.getStackTrace());
|
||||
}
|
||||
}
|
||||
|
||||
protected var _gameData :Object;
|
||||
|
||||
protected var _funcs :Object;
|
||||
}
|
||||
}
|
||||
|
||||
import flash.events.Event;
|
||||
|
||||
dynamic class DynEvent extends Event
|
||||
{
|
||||
public function DynEvent ()
|
||||
{
|
||||
super("ezgameQuery", true, false);
|
||||
}
|
||||
|
||||
override public function clone () :Event
|
||||
{
|
||||
return new DynEvent();
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package com.threerings.ezgame {
|
||||
|
||||
/**
|
||||
* This interface should be implemented by some class that lives on the
|
||||
* display list. When a DisplayObject that implements this interface
|
||||
* is added, it will be notified of the GameObject.
|
||||
*/
|
||||
public interface Game
|
||||
{
|
||||
/**
|
||||
* Called by the mysterious powers of the cosmos to initialize
|
||||
* your game with the GameObject.
|
||||
*/
|
||||
function setGameObject (gameObj :EZGame) :void;
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ public class MessageReceivedEvent extends EZEvent
|
||||
}
|
||||
|
||||
public function MessageReceivedEvent (
|
||||
ezgame :EZGame, messageName :String, value :Object)
|
||||
ezgame :EZGameControl, messageName :String, value :Object)
|
||||
{
|
||||
super(TYPE, ezgame);
|
||||
_name = messageName;
|
||||
|
||||
@@ -20,12 +20,15 @@ import flash.text.TextFieldAutoSize;
|
||||
* free to copy/modify or extend this class.
|
||||
*/
|
||||
public class PlayersDisplay extends Sprite
|
||||
implements Game, StateChangedListener
|
||||
implements StateChangedListener
|
||||
{
|
||||
// implementation of Game method
|
||||
public function setGameObject (gameObj :EZGame) :void
|
||||
/**
|
||||
* Set the game control that will be used with this display.
|
||||
*/
|
||||
public function setGameControl (gameCtrl :EZGameControl) :void
|
||||
{
|
||||
_gameObj = gameObj;
|
||||
_gameCtrl = gameCtrl;
|
||||
_gameCtrl.registerListener(this);
|
||||
|
||||
configureInterface();
|
||||
}
|
||||
@@ -60,7 +63,7 @@ public class PlayersDisplay extends Sprite
|
||||
|
||||
// create a label for each player
|
||||
var playerIndex :int = 0;
|
||||
for each (var name :String in _gameObj.getPlayerNames()) {
|
||||
for each (var name :String in _gameCtrl.getPlayerNames()) {
|
||||
label = createPlayerLabel(playerIndex, name);
|
||||
icon = createPlayerIcon(playerIndex, name);
|
||||
var iconW :int = 0;
|
||||
@@ -156,15 +159,15 @@ public class PlayersDisplay extends Sprite
|
||||
*/
|
||||
protected function displayCurrentTurn () :void
|
||||
{
|
||||
var idx :int = _gameObj.isInPlay() ? _gameObj.getTurnHolderIndex() : -1;
|
||||
var idx :int = _gameCtrl.isInPlay() ? _gameCtrl.getTurnHolderIndex() : -1;
|
||||
for (var ii :int = 0; ii < _playerLabels.length; ii++) {
|
||||
var label :TextField = (_playerLabels[ii] as TextField);
|
||||
label.backgroundColor = getBackground(ii == idx);
|
||||
}
|
||||
}
|
||||
|
||||
/** Our game object. */
|
||||
protected var _gameObj :EZGame;
|
||||
/** Our game Control. */
|
||||
protected var _gameCtrl :EZGameControl;
|
||||
|
||||
/** An array of labels, one for each player name. */
|
||||
protected var _playerLabels :Array = [];
|
||||
|
||||
@@ -47,7 +47,7 @@ public class PropertyChangedEvent extends EZEvent
|
||||
* Constructor.
|
||||
*/
|
||||
public function PropertyChangedEvent (
|
||||
ezgame :EZGame, propName :String, newValue :Object,
|
||||
ezgame :EZGameControl, propName :String, newValue :Object,
|
||||
oldValue :Object, index :int = -1)
|
||||
{
|
||||
super(TYPE, ezgame);
|
||||
|
||||
@@ -17,7 +17,7 @@ public class StateChangedEvent extends EZEvent
|
||||
// TODO: move to own event?
|
||||
public static const TURN_CHANGED :String = "TurnChanged";
|
||||
|
||||
public function StateChangedEvent (type :String, ezgame :EZGame)
|
||||
public function StateChangedEvent (type :String, ezgame :EZGameControl)
|
||||
{
|
||||
super(type, ezgame);
|
||||
}
|
||||
|
||||
@@ -2,15 +2,8 @@ package com.threerings.ezgame.client {
|
||||
|
||||
import flash.events.Event;
|
||||
|
||||
import flash.utils.ByteArray;
|
||||
|
||||
import com.threerings.util.Integer;
|
||||
import com.threerings.util.Name;
|
||||
|
||||
import com.threerings.presents.dobj.MessageAdapter;
|
||||
import com.threerings.presents.dobj.MessageListener;
|
||||
import com.threerings.presents.dobj.MessageEvent;
|
||||
|
||||
import com.threerings.crowd.client.PlaceView;
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
import com.threerings.crowd.data.PlaceObject;
|
||||
@@ -22,23 +15,13 @@ import com.threerings.parlor.turn.client.TurnGameController;
|
||||
import com.threerings.parlor.turn.client.TurnGameControllerDelegate;
|
||||
|
||||
import com.threerings.ezgame.data.EZGameObject;
|
||||
import com.threerings.ezgame.data.PropertySetEvent;
|
||||
import com.threerings.ezgame.data.PropertySetListener;
|
||||
import com.threerings.ezgame.util.EZObjectMarshaller;
|
||||
|
||||
import com.threerings.ezgame.MessageReceivedEvent;
|
||||
import com.threerings.ezgame.PropertyChangedEvent;
|
||||
import com.threerings.ezgame.StateChangedEvent;
|
||||
|
||||
/**
|
||||
* A controller for flash games.
|
||||
*/
|
||||
public class EZGameController extends GameController
|
||||
implements TurnGameController, PropertySetListener, MessageListener
|
||||
implements TurnGameController
|
||||
{
|
||||
/** The implementation of the GameObject interface for users. */
|
||||
public var gameObjImpl :GameObjectImpl;
|
||||
|
||||
/**
|
||||
*/
|
||||
public function EZGameController ()
|
||||
@@ -49,9 +32,6 @@ public class EZGameController extends GameController
|
||||
override public function willEnterPlace (plobj :PlaceObject) :void
|
||||
{
|
||||
_ezObj = (plobj as EZGameObject);
|
||||
gameObjImpl = new GameObjectImpl(_ctx, _ezObj);
|
||||
|
||||
_ctx.getClient().getClientObject().addListener(_userListener);
|
||||
|
||||
super.willEnterPlace(plobj);
|
||||
}
|
||||
@@ -60,100 +40,39 @@ public class EZGameController extends GameController
|
||||
{
|
||||
super.didLeavePlace(plobj);
|
||||
|
||||
_ctx.getClient().getClientObject().removeListener(_userListener);
|
||||
|
||||
_ezObj = null;
|
||||
}
|
||||
|
||||
// from TurnGameController
|
||||
public function turnDidChange (turnHolder :Name) :void
|
||||
{
|
||||
dispatchUserEvent(
|
||||
new StateChangedEvent(StateChangedEvent.TURN_CHANGED, gameObjImpl));
|
||||
}
|
||||
|
||||
// from PropertySetListener
|
||||
public function propertyWasSet (event :PropertySetEvent) :void
|
||||
{
|
||||
// notify the user game
|
||||
dispatchUserEvent(new PropertyChangedEvent(
|
||||
gameObjImpl, event.getName(), event.getValue(),
|
||||
event.getOldValue(), event.getIndex()));
|
||||
}
|
||||
|
||||
// from MessageListener
|
||||
public function messageReceived (event :MessageEvent) :void
|
||||
{
|
||||
var name :String = event.getName();
|
||||
if (EZGameObject.USER_MESSAGE == name) {
|
||||
dispatchUserMessage(event.getArgs());
|
||||
|
||||
} else if (EZGameObject.GAME_CHAT == name) {
|
||||
// this is chat send by the game, let's route it like
|
||||
// localChat, which is also sent by the game
|
||||
gameObjImpl.localChat(String(event.getArgs()[0]));
|
||||
|
||||
} else if (EZGameObject.TICKER == name) {
|
||||
var args :Array = event.getArgs();
|
||||
dispatchUserEvent(new MessageReceivedEvent(
|
||||
gameObjImpl, (args[0] as String),
|
||||
(args[1] as Integer).value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by our user listener when we receive a message event
|
||||
* on the user object.
|
||||
*/
|
||||
protected function messageReceivedOnUserObject (event :MessageEvent) :void
|
||||
{
|
||||
// see if it's a message about user games
|
||||
var msgName :String =
|
||||
EZGameObject.USER_MESSAGE + ":" + _ezObj.getOid();
|
||||
if (msgName == event.getName()) {
|
||||
dispatchUserMessage(event.getArgs());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch the user message.
|
||||
*/
|
||||
protected function dispatchUserMessage (args :Array) :void
|
||||
{
|
||||
dispatchUserEvent(new MessageReceivedEvent(
|
||||
gameObjImpl, (args[0] as String),
|
||||
EZObjectMarshaller.decode(args[1])));
|
||||
}
|
||||
|
||||
override protected function createPlaceView (ctx :CrowdContext) :PlaceView
|
||||
{
|
||||
return new EZGamePanel(ctx, this);
|
||||
_panel.backend.turnDidChange();
|
||||
}
|
||||
|
||||
override protected function gameDidStart () :void
|
||||
{
|
||||
super.gameDidStart();
|
||||
dispatchUserEvent(
|
||||
new StateChangedEvent(StateChangedEvent.GAME_STARTED, gameObjImpl));
|
||||
|
||||
_panel.backend.gameDidStart();
|
||||
}
|
||||
|
||||
override protected function gameDidEnd () :void
|
||||
{
|
||||
super.gameDidEnd();
|
||||
dispatchUserEvent(
|
||||
new StateChangedEvent(StateChangedEvent.GAME_ENDED, gameObjImpl));
|
||||
|
||||
_panel.backend.gameDidEnd();
|
||||
}
|
||||
|
||||
protected function dispatchUserEvent (event :Event) :void
|
||||
override protected function createPlaceView (ctx :CrowdContext) :PlaceView
|
||||
{
|
||||
gameObjImpl.dispatch(event);
|
||||
_panel = new EZGamePanel(ctx, this);
|
||||
return _panel;
|
||||
}
|
||||
|
||||
protected var _ezObj :EZGameObject;
|
||||
|
||||
protected var _turnDelegate :TurnGameControllerDelegate;
|
||||
|
||||
protected var _userListener :MessageAdapter =
|
||||
new MessageAdapter(messageReceivedOnUserObject);
|
||||
protected var _panel :EZGamePanel;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.threerings.ezgame.client {
|
||||
|
||||
import flash.display.DisplayObject;
|
||||
import flash.display.DisplayObjectContainer;
|
||||
import flash.display.Loader;
|
||||
|
||||
import flash.events.Event;
|
||||
|
||||
@@ -26,106 +27,48 @@ import com.threerings.crowd.util.CrowdContext;
|
||||
import com.threerings.ezgame.data.EZGameConfig;
|
||||
import com.threerings.ezgame.data.EZGameObject;
|
||||
|
||||
import com.threerings.ezgame.Game;
|
||||
|
||||
public class EZGamePanel extends VBox
|
||||
implements PlaceView
|
||||
{
|
||||
/** The game object backend. */
|
||||
public var backend :GameControlBackend;
|
||||
|
||||
public function EZGamePanel (ctx :CrowdContext, ctrl :EZGameController)
|
||||
{
|
||||
_ctx = ctx;
|
||||
_ctrl = ctrl;
|
||||
|
||||
// add a listener so that we hear about all new children
|
||||
addEventListener(Event.ADDED, childAdded);
|
||||
addEventListener(Event.REMOVED, childRemoved);
|
||||
|
||||
var cfg :EZGameConfig = (ctrl.getPlaceConfig() as EZGameConfig);
|
||||
_gameView = new MediaContainer(cfg.configData); // TODO
|
||||
addChild(_gameView);
|
||||
|
||||
//addChild(new ChatDisplayBox(ctx));
|
||||
}
|
||||
|
||||
// from PlaceView
|
||||
public function willEnterPlace (plobj :PlaceObject) :void
|
||||
{
|
||||
// don't start notifying anything of the game until we've
|
||||
// notified the game manager that we're in the game
|
||||
// (done in GameController, and it uses callLater, so we do it twice!)
|
||||
_ctx.getClient().callLater(function () :void {
|
||||
_ctx.getClient().callLater(function () :void {
|
||||
_ezObj = (plobj as EZGameObject);
|
||||
var cfg :EZGameConfig = (_ctrl.getPlaceConfig() as EZGameConfig);
|
||||
|
||||
notifyOfGame(_gameView);
|
||||
});
|
||||
});
|
||||
_ezObj = (plobj as EZGameObject);
|
||||
backend = new GameControlBackend(_ctx, _ezObj);
|
||||
|
||||
_gameView = new GameContainer(cfg.configData); // TODO
|
||||
_gameView.tabEnabled = true;
|
||||
backend.setSharedEvents(
|
||||
Loader(_gameView.getMedia()).contentLoaderInfo.sharedEvents);
|
||||
addChild(_gameView);
|
||||
}
|
||||
|
||||
// from PlaceView
|
||||
public function didLeavePlace (plobj :PlaceObject) :void
|
||||
{
|
||||
removeListeners(_gameView);
|
||||
_ezObj = null;
|
||||
}
|
||||
_gameView.shutdown(true);
|
||||
removeChild(_gameView);
|
||||
|
||||
/**
|
||||
* Handle ADDED events.
|
||||
*/
|
||||
protected function childAdded (event :Event) :void
|
||||
{
|
||||
if (_ezObj != null) {
|
||||
notifyOfGame(event.target as DisplayObject);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle REMOVED events.
|
||||
*/
|
||||
protected function childRemoved (event :Event) :void
|
||||
{
|
||||
if (_ezObj != null) {
|
||||
removeListeners(event.target as DisplayObject);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find any children of the specified object that implement
|
||||
* com.metasoy.game.Game and provide them with the GameObject.
|
||||
*/
|
||||
protected function notifyOfGame (root :DisplayObject) :void
|
||||
{
|
||||
DisplayUtil.walkDisplayObjects(root,
|
||||
function (disp :DisplayObject) :void
|
||||
{
|
||||
if (disp is Game) {
|
||||
// only notify the Game if we haven't seen it before
|
||||
if (null == _seenGames[disp]) {
|
||||
(disp as Game).setGameObject(_ctrl.gameObjImpl);
|
||||
_seenGames[disp] = true;
|
||||
}
|
||||
}
|
||||
// always check to see if it's a listener
|
||||
_ctrl.gameObjImpl.registerListener(disp);
|
||||
});
|
||||
}
|
||||
|
||||
protected function removeListeners (root :DisplayObject) :void
|
||||
{
|
||||
DisplayUtil.walkDisplayObjects(root,
|
||||
function (disp :DisplayObject) :void
|
||||
{
|
||||
_ctrl.gameObjImpl.unregisterListener(disp);
|
||||
});
|
||||
backend.shutdown();
|
||||
}
|
||||
|
||||
protected var _ctx :CrowdContext;
|
||||
protected var _ctrl :EZGameController;
|
||||
|
||||
protected var _gameView :MediaContainer;
|
||||
|
||||
/** A weak-key hash of the Game interfaces we've already seen. */
|
||||
protected var _seenGames :Dictionary = new Dictionary(true);
|
||||
protected var _gameView :GameContainer;
|
||||
|
||||
protected var _ezObj :EZGameObject;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.threerings.ezgame.client {
|
||||
|
||||
import flash.display.InteractiveObject;
|
||||
import flash.display.Loader;
|
||||
|
||||
import mx.managers.IFocusManagerComponent;
|
||||
|
||||
import com.threerings.util.MediaContainer;
|
||||
|
||||
public class GameContainer extends MediaContainer
|
||||
implements IFocusManagerComponent
|
||||
{
|
||||
public function GameContainer (url :String)
|
||||
{
|
||||
super(url);
|
||||
}
|
||||
|
||||
override public function setFocus () :void
|
||||
{
|
||||
super.setFocus();
|
||||
if (systemManager.stage.focus == this) {
|
||||
// TODO
|
||||
//systemManager.stage.focus = InteractiveObject(Loader(_media).content);
|
||||
systemManager.stage.focus = Loader(_media);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+211
-218
@@ -4,6 +4,7 @@ import flash.errors.IllegalOperationError;
|
||||
|
||||
import flash.events.Event;
|
||||
import flash.events.EventDispatcher;
|
||||
import flash.events.IEventDispatcher;
|
||||
|
||||
import flash.utils.IExternalizable;
|
||||
import flash.utils.ByteArray;
|
||||
@@ -12,6 +13,7 @@ import flash.utils.Dictionary;
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.util.ClassUtil;
|
||||
import com.threerings.util.Integer;
|
||||
import com.threerings.util.MessageBundle;
|
||||
import com.threerings.util.Name;
|
||||
import com.threerings.util.StringUtil;
|
||||
@@ -20,61 +22,109 @@ import com.threerings.presents.client.ConfirmAdapter;
|
||||
import com.threerings.presents.client.InvocationService_ConfirmListener;
|
||||
|
||||
import com.threerings.presents.dobj.EntryAddedEvent;
|
||||
import com.threerings.presents.dobj.EntryRemovedEvent;
|
||||
import com.threerings.presents.dobj.EntryUpdatedEvent;
|
||||
import com.threerings.presents.dobj.SetAdapter;
|
||||
import com.threerings.presents.dobj.SetListener;
|
||||
import com.threerings.presents.dobj.MessageAdapter;
|
||||
import com.threerings.presents.dobj.MessageEvent;
|
||||
import com.threerings.presents.dobj.MessageListener;
|
||||
|
||||
import com.threerings.crowd.data.BodyObject;
|
||||
import com.threerings.crowd.util.CrowdContext;
|
||||
|
||||
import com.threerings.ezgame.data.EZGameObject;
|
||||
import com.threerings.ezgame.data.PropertySetEvent;
|
||||
import com.threerings.ezgame.data.PropertySetListener;
|
||||
import com.threerings.ezgame.data.UserCookie;
|
||||
import com.threerings.ezgame.util.EZObjectMarshaller;
|
||||
|
||||
import com.threerings.ezgame.EZGame;
|
||||
import com.threerings.ezgame.MessageReceivedEvent;
|
||||
import com.threerings.ezgame.MessageReceivedListener;
|
||||
import com.threerings.ezgame.PropertyChangedEvent;
|
||||
import com.threerings.ezgame.PropertyChangedListener;
|
||||
import com.threerings.ezgame.StateChangedEvent;
|
||||
import com.threerings.ezgame.StateChangedListener;
|
||||
|
||||
public class GameObjectImpl extends EventDispatcher
|
||||
implements EZGame
|
||||
public class GameControlBackend
|
||||
implements MessageListener, SetListener, PropertySetListener
|
||||
{
|
||||
public function GameObjectImpl (ctx :CrowdContext, ezObj :EZGameObject)
|
||||
public var log :Log = Log.getLog(this);
|
||||
|
||||
public function GameControlBackend (
|
||||
ctx :CrowdContext, ezObj :EZGameObject)
|
||||
{
|
||||
_ctx = ctx;
|
||||
_ezObj = ezObj;
|
||||
_gameData = new GameData(this, _ezObj.getUserProps());
|
||||
_gameData = new GameData(setProperty_v1, _ezObj.getUserProps());
|
||||
|
||||
_ezObj.addListener(new SetAdapter(entryAdded, entryUpdated, null));
|
||||
_ezObj.addListener(this);
|
||||
_ctx.getClient().getClientObject().addListener(_userListener);
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function get data () :Object
|
||||
public function setSharedEvents (disp :IEventDispatcher) :void
|
||||
{
|
||||
return _gameData;
|
||||
disp.addEventListener("ezgameQuery", handleEZQuery);
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function get (propName :String, index :int = -1) :Object
|
||||
public function shutdown () :void
|
||||
{
|
||||
var value :Object = data[propName];
|
||||
if (index >= 0) {
|
||||
if (value is Array) {
|
||||
return (value as Array)[index];
|
||||
_ezObj.removeListener(this);
|
||||
_ctx.getClient().getClientObject().removeListener(_userListener);
|
||||
}
|
||||
|
||||
} else {
|
||||
throw new ArgumentError("Property " + propName +
|
||||
" is not an array.");
|
||||
protected function handleEZQuery (evt :Object) :void
|
||||
{
|
||||
setUserCodeProperties(evt.userProps);
|
||||
evt.ezProps = new Object();
|
||||
populateProperties(evt.ezProps);
|
||||
}
|
||||
|
||||
protected function setUserCodeProperties (o :Object) :void
|
||||
{
|
||||
// here we would handle adapting old functions to a new version
|
||||
|
||||
_userFuncs = o;
|
||||
}
|
||||
|
||||
protected function callUserCode (name :String, ... args) :*
|
||||
{
|
||||
if (_userFuncs != null) {
|
||||
try {
|
||||
var func :Function = (_userFuncs[name] as Function);
|
||||
if (func != null) {
|
||||
return func.apply(null, args);
|
||||
}
|
||||
|
||||
} catch (err :Error) {
|
||||
log.warning("Error in user-code: " + err);
|
||||
log.logStackTrace(err);
|
||||
}
|
||||
}
|
||||
return value;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function set (propName :String, value :Object, index :int = -1) :void
|
||||
protected function populateProperties (o :Object) :void
|
||||
{
|
||||
// straight data
|
||||
o["gameData"] = _gameData;
|
||||
|
||||
// functions
|
||||
o["setProperty_v1"] = setProperty_v1;
|
||||
o["mergeCollection_v1"] = mergeCollection_v1;
|
||||
o["sendMessage_v1"] = sendMessage_v1;
|
||||
o["setTicker_v1"] = setTicker_v1;
|
||||
o["sendChat_v1"] = sendChat_v1;
|
||||
o["localChat_v1"] = localChat_v1;
|
||||
o["getPlayerCount_v1"] = getPlayerCount_v1;
|
||||
o["getPlayerNames_v1"] = getPlayerNames_v1;
|
||||
o["getMyIndex_v1"] = getMyIndex_v1;
|
||||
o["getTurnHolderIndex_v1"] = getTurnHolderIndex_v1;
|
||||
o["getWinnerIndexes_v1"] = getWinnerIndexes_v1;
|
||||
o["getUserCookie_v1"] = getUserCookie_v1;
|
||||
o["setUserCookie_v1"] = setUserCookie_v1;
|
||||
o["isMyTurn_v1"] = isMyTurn_v1;
|
||||
o["isInPlay_v1"] = isInPlay_v1;
|
||||
o["endTurn_v1"] = endTurn_v1;
|
||||
o["endGame_v1"] = endGame_v1;
|
||||
o["populateCollection_v1"] = populateCollection_v1;
|
||||
o["getFromCollection_v1"] = getFromCollection_v1;
|
||||
}
|
||||
|
||||
public function setProperty_v1 (
|
||||
propName :String, value :Object, index :int) :void
|
||||
{
|
||||
validatePropertyChange(propName, value, index);
|
||||
|
||||
@@ -87,91 +137,8 @@ public class GameObjectImpl extends EventDispatcher
|
||||
_ezObj.applyPropertySet(propName, value, index);
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function registerListener (obj :Object) :void
|
||||
{
|
||||
if (obj is MessageReceivedListener) {
|
||||
var mrl :MessageReceivedListener = (obj as MessageReceivedListener);
|
||||
addEventListener(
|
||||
MessageReceivedEvent.TYPE, mrl.messageReceived,
|
||||
false, 0, true);
|
||||
}
|
||||
if (obj is PropertyChangedListener) {
|
||||
var pcl :PropertyChangedListener = (obj as PropertyChangedListener);
|
||||
addEventListener(
|
||||
PropertyChangedEvent.TYPE, pcl.propertyChanged,
|
||||
false, 0, true);
|
||||
}
|
||||
if (obj is StateChangedListener) {
|
||||
var scl :StateChangedListener = (obj as StateChangedListener);
|
||||
addEventListener(
|
||||
StateChangedEvent.GAME_STARTED, scl.stateChanged,
|
||||
false, 0, true);
|
||||
addEventListener(
|
||||
StateChangedEvent.TURN_CHANGED, scl.stateChanged,
|
||||
false, 0, true);
|
||||
addEventListener(
|
||||
StateChangedEvent.GAME_ENDED, scl.stateChanged,
|
||||
false, 0, true);
|
||||
}
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function unregisterListener (obj :Object) :void
|
||||
{
|
||||
if (obj is MessageReceivedListener) {
|
||||
var mrl :MessageReceivedListener = (obj as MessageReceivedListener);
|
||||
removeEventListener(
|
||||
MessageReceivedEvent.TYPE, mrl.messageReceived);
|
||||
}
|
||||
if (obj is PropertyChangedListener) {
|
||||
var pcl :PropertyChangedListener = (obj as PropertyChangedListener);
|
||||
removeEventListener(
|
||||
PropertyChangedEvent.TYPE, pcl.propertyChanged);
|
||||
}
|
||||
if (obj is StateChangedListener) {
|
||||
var scl :StateChangedListener = (obj as StateChangedListener);
|
||||
removeEventListener(
|
||||
StateChangedEvent.GAME_STARTED, scl.stateChanged);
|
||||
removeEventListener(
|
||||
StateChangedEvent.TURN_CHANGED, scl.stateChanged);
|
||||
removeEventListener(
|
||||
StateChangedEvent.GAME_ENDED, scl.stateChanged);
|
||||
}
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function setCollection (collName :String, values :Array) :void
|
||||
{
|
||||
populateCollection(collName, values, true);
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function addToCollection (collName :String, values :Array) :void
|
||||
{
|
||||
populateCollection(collName, values, false);
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function pickFromCollection (
|
||||
collName :String, count :int, msgOrPropName :String,
|
||||
playerIndex :int = -1) :void
|
||||
{
|
||||
getFromCollection(collName, count, msgOrPropName, playerIndex,
|
||||
false, null);
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function dealFromCollection (
|
||||
collName :String, count :int, msgOrPropName :String,
|
||||
callback :Function = null, playerIndex :int = -1) :void
|
||||
{
|
||||
getFromCollection(collName, count, msgOrPropName, playerIndex,
|
||||
true, callback);
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function mergeCollection (srcColl :String, intoColl :String) :void
|
||||
public function mergeCollection_v1 (
|
||||
srcColl :String, intoColl :String) :void
|
||||
{
|
||||
validateName(srcColl);
|
||||
validateName(intoColl);
|
||||
@@ -179,9 +146,8 @@ public class GameObjectImpl extends EventDispatcher
|
||||
srcColl, intoColl, createLoggingListener("mergeCollection"));
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function sendMessage (
|
||||
messageName :String, value :Object, playerIndex :int = -1) :void
|
||||
public function sendMessage_v1 (
|
||||
messageName :String, value :Object, playerIndex :int) :void
|
||||
{
|
||||
validateName(messageName);
|
||||
validateValue(value);
|
||||
@@ -192,22 +158,14 @@ public class GameObjectImpl extends EventDispatcher
|
||||
createLoggingListener("sendMessage"));
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function startTicker (tickerName :String, msOfDelay :int) :void
|
||||
public function setTicker_v1 (tickerName :String, msOfDelay :int) :void
|
||||
{
|
||||
validateName(tickerName);
|
||||
_ezObj.ezGameService.setTicker(_ctx.getClient(),
|
||||
tickerName, msOfDelay, createLoggingListener("setTicker"));
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function stopTicker (tickerName :String) :void
|
||||
{
|
||||
startTicker(tickerName, 0);
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function sendChat (msg :String) :void
|
||||
public function sendChat_v1 (msg :String) :void
|
||||
{
|
||||
validateChat(msg);
|
||||
// Post a message to the game object, the controller
|
||||
@@ -215,8 +173,7 @@ public class GameObjectImpl extends EventDispatcher
|
||||
_ezObj.postMessage(EZGameObject.GAME_CHAT, [ msg ]);
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function localChat (msg :String) :void
|
||||
public function localChat_v1 (msg :String) :void
|
||||
{
|
||||
validateChat(msg);
|
||||
// The sendChat() messages will end up being routed
|
||||
@@ -225,14 +182,12 @@ public class GameObjectImpl extends EventDispatcher
|
||||
_ctx.getChatDirector().displayInfo(null, MessageBundle.taint(msg));
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function getPlayerCount () :int
|
||||
public function getPlayerCount_v1 () :int
|
||||
{
|
||||
return _ezObj.getPlayerCount();
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function getPlayerNames () :Array
|
||||
public function getPlayerNames_v1 () :Array
|
||||
{
|
||||
var names :Array = new Array();
|
||||
for each (var name :Name in _ezObj.players) {
|
||||
@@ -241,20 +196,17 @@ public class GameObjectImpl extends EventDispatcher
|
||||
return names;
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function getMyIndex () :int
|
||||
public function getMyIndex_v1 () :int
|
||||
{
|
||||
return _ezObj.getPlayerIndex(getUsername());
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function getTurnHolderIndex () :int
|
||||
public function getTurnHolderIndex_v1 () :int
|
||||
{
|
||||
return _ezObj.getPlayerIndex(_ezObj.turnHolder);
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function getWinnerIndexes () :Array /* of int */
|
||||
public function getWinnerIndexes_v1 () :Array /* of int */
|
||||
{
|
||||
var arr :Array = new Array();
|
||||
if (_ezObj.winners != null) {
|
||||
@@ -267,8 +219,8 @@ public class GameObjectImpl extends EventDispatcher
|
||||
return arr;
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function getUserCookie (playerIndex :int, callback :Function) :void
|
||||
public function getUserCookie_v1 (
|
||||
playerIndex :int, callback :Function) :void
|
||||
{
|
||||
// see if that cookie is already published
|
||||
if (_ezObj.userCookies != null) {
|
||||
@@ -295,8 +247,7 @@ public class GameObjectImpl extends EventDispatcher
|
||||
createLoggingListener("getUserCookie"));
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function setUserCookie (cookie :Object) :Boolean
|
||||
public function setUserCookie_v1 (cookie :Object) :Boolean
|
||||
{
|
||||
var ba :ByteArray =
|
||||
(EZObjectMarshaller.encode(cookie, false) as ByteArray);
|
||||
@@ -310,91 +261,36 @@ public class GameObjectImpl extends EventDispatcher
|
||||
return true;
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function isMyTurn () :Boolean
|
||||
public function isMyTurn_v1 () :Boolean
|
||||
{
|
||||
return getUsername().equals(_ezObj.turnHolder);
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function isInPlay () :Boolean
|
||||
public function isInPlay_v1 () :Boolean
|
||||
{
|
||||
return _ezObj.isInPlay();
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function endTurn (nextPlayerIndex :int = -1) :void
|
||||
public function endTurn_v1 (nextPlayerIndex :int = -1) :void
|
||||
{
|
||||
_ezObj.ezGameService.endTurn(_ctx.getClient(), nextPlayerIndex,
|
||||
createLoggingListener("endTurn"));
|
||||
}
|
||||
|
||||
// from EZGame
|
||||
public function endGame (winnerIndex :int, ... rest) :void
|
||||
public function endGame_v1 (... winnerDexes) :void
|
||||
{
|
||||
var winners :TypedArray = TypedArray.create(int);
|
||||
winners.push(winnerIndex);
|
||||
while (rest.length > 0) {
|
||||
winners.push(int(rest.shift()));
|
||||
while (winnerDexes.length > 0) {
|
||||
winners.push(int(winnerDexes.shift()));
|
||||
}
|
||||
_ezObj.ezGameService.endGame(_ctx.getClient(), winners,
|
||||
createLoggingListener("endGame"));
|
||||
}
|
||||
|
||||
override public function willTrigger (type :String) :Boolean
|
||||
{
|
||||
throw new IllegalOperationError();
|
||||
}
|
||||
|
||||
override public function dispatchEvent (event :Event) :Boolean
|
||||
{
|
||||
// Ideally we want to not be an IEventDispatcher so that people
|
||||
// won't try to do this on us, but if we do that, then some other
|
||||
// object will be the target during dispatch, and that's confusing.
|
||||
// It's really nice to be able to
|
||||
throw new IllegalOperationError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Secret function to dispatch property changed events.
|
||||
*/
|
||||
internal function dispatch (event :Event) :void
|
||||
{
|
||||
try {
|
||||
super.dispatchEvent(event);
|
||||
} catch (err :Error) {
|
||||
var log :Log = Log.getLog(this);
|
||||
log.warning("Error dispatching event to user game.");
|
||||
log.logStackTrace(err);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function to get our name.
|
||||
*/
|
||||
private function getUsername () :Name
|
||||
{
|
||||
var body :BodyObject =
|
||||
(_ctx.getClient().getClientObject() as BodyObject);
|
||||
return body.getVisibleName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a listener for service requests.
|
||||
*/
|
||||
private function createLoggingListener (
|
||||
service :String) :InvocationService_ConfirmListener
|
||||
{
|
||||
return new ConfirmAdapter(function (cause :String) :void {
|
||||
Log.getLog(this).warning("Service failure " +
|
||||
"[service=" + service + ", cause=" + cause + "].");
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for setCollection and addToCollection.
|
||||
*/
|
||||
private function populateCollection (
|
||||
public function populateCollection_v1 (
|
||||
collName :String, values :Array, clearExisting :Boolean) :void
|
||||
{
|
||||
validateName(collName);
|
||||
@@ -414,7 +310,7 @@ public class GameObjectImpl extends EventDispatcher
|
||||
/**
|
||||
* Helper method for pickFromCollection and dealFromCollection.
|
||||
*/
|
||||
private function getFromCollection(
|
||||
public function getFromCollection_v1 (
|
||||
collName :String, count :int, msgOrPropName :String, playerIndex :int,
|
||||
consume :Boolean, callback :Function) :void
|
||||
{
|
||||
@@ -446,10 +342,32 @@ public class GameObjectImpl extends EventDispatcher
|
||||
playerIndex, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function to get our name.
|
||||
*/
|
||||
protected function getUsername () :Name
|
||||
{
|
||||
var body :BodyObject =
|
||||
(_ctx.getClient().getClientObject() as BodyObject);
|
||||
return body.getVisibleName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a listener for service requests.
|
||||
*/
|
||||
protected function createLoggingListener (
|
||||
service :String) :InvocationService_ConfirmListener
|
||||
{
|
||||
return new ConfirmAdapter(function (cause :String) :void {
|
||||
Log.getLog(this).warning("Service failure " +
|
||||
"[service=" + service + ", cause=" + cause + "].");
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the property name / value are valid.
|
||||
*/
|
||||
private function validatePropertyChange (
|
||||
protected function validatePropertyChange (
|
||||
propName :String, value :Object, index :int) :void
|
||||
{
|
||||
validateName(propName);
|
||||
@@ -469,7 +387,7 @@ public class GameObjectImpl extends EventDispatcher
|
||||
/**
|
||||
* Verify that the specified name is valid.
|
||||
*/
|
||||
private function validateName (name :String) :void
|
||||
protected function validateName (name :String) :void
|
||||
{
|
||||
if (name == null) {
|
||||
throw new ArgumentError(
|
||||
@@ -477,7 +395,7 @@ public class GameObjectImpl extends EventDispatcher
|
||||
}
|
||||
}
|
||||
|
||||
private function validateChat (msg :String) :void
|
||||
protected function validateChat (msg :String) :void
|
||||
{
|
||||
if (StringUtil.isBlank(msg)) {
|
||||
throw new ArgumentError(
|
||||
@@ -488,7 +406,7 @@ public class GameObjectImpl extends EventDispatcher
|
||||
/**
|
||||
* Verify that the value is legal to be streamed to other clients.
|
||||
*/
|
||||
private function validateValue (value :Object) :void
|
||||
protected function validateValue (value :Object) :void
|
||||
{
|
||||
if (value == null) {
|
||||
return;
|
||||
@@ -498,7 +416,7 @@ public class GameObjectImpl extends EventDispatcher
|
||||
"IExternalizable is not yet supported");
|
||||
|
||||
} else if (value is Array) {
|
||||
if (ClassUtil.getClass(value) != Array) {
|
||||
if (ClassUtil.getClassName(value) != "Array") {
|
||||
// We can't allow arrays to be serialized as IExternalizables
|
||||
// because we need to know element values (opaquely) on the
|
||||
// server. Also, we don't allow other types because we wouldn't
|
||||
@@ -532,29 +450,99 @@ public class GameObjectImpl extends EventDispatcher
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle entry updated
|
||||
* Called by the EZGameController when the turn changes.
|
||||
*/
|
||||
private function entryAdded (event :EntryAddedEvent) :void
|
||||
public function turnDidChange () :void
|
||||
{
|
||||
callUserCode("turnDidChange_v1");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the EZGameController when the game starts.
|
||||
*/
|
||||
public function gameDidStart () :void
|
||||
{
|
||||
callUserCode("gameDidStart_v1");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the EZGameController when the game ends.
|
||||
*/
|
||||
public function gameDidEnd () :void
|
||||
{
|
||||
callUserCode("gameDidEnd_v1");
|
||||
}
|
||||
|
||||
// from SetListener
|
||||
public function entryAdded (event :EntryAddedEvent) :void
|
||||
{
|
||||
if (EZGameObject.USER_COOKIES == event.getName()) {
|
||||
receivedUserCookie(event.getEntry() as UserCookie);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle entry updated
|
||||
*/
|
||||
private function entryUpdated (event :EntryUpdatedEvent) :void
|
||||
// from SetListener
|
||||
public function entryUpdated (event :EntryUpdatedEvent) :void
|
||||
{
|
||||
if (EZGameObject.USER_COOKIES == event.getName()) {
|
||||
receivedUserCookie(event.getEntry() as UserCookie);
|
||||
}
|
||||
}
|
||||
|
||||
// from SetListener
|
||||
public function entryRemoved (event :EntryRemovedEvent) :void
|
||||
{
|
||||
// nada
|
||||
}
|
||||
|
||||
// from PropertySetListener
|
||||
public function propertyWasSet (event :PropertySetEvent) :void
|
||||
{
|
||||
callUserCode("propertyWasSet_v1", event.getName(), event.getValue(),
|
||||
event.getOldValue(), event.getIndex());
|
||||
}
|
||||
|
||||
public function messageReceived (event :MessageEvent) :void
|
||||
{
|
||||
var name :String = event.getName();
|
||||
if (EZGameObject.USER_MESSAGE == name) {
|
||||
var args :Array = event.getArgs();
|
||||
callUserCode("messageReceived_v1", (args[0] as String),
|
||||
EZObjectMarshaller.decode(args[1]));
|
||||
|
||||
} else if (EZGameObject.GAME_CHAT == name) {
|
||||
// this is chat send by the game, let's route it like
|
||||
// localChat, which is also sent by the game
|
||||
localChat_v1(String(event.getArgs()[0]));
|
||||
|
||||
} else if (EZGameObject.TICKER == name) {
|
||||
var targs :Array = event.getArgs();
|
||||
callUserCode("messageReceived_v1", (targs[0] as String),
|
||||
(targs[1] as Integer).value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by our user listener when we receive a message event
|
||||
* on the user object.
|
||||
*/
|
||||
protected function messageReceivedOnUserObject (event :MessageEvent) :void
|
||||
{
|
||||
// see if it's a message about user games
|
||||
var msgName :String =
|
||||
EZGameObject.USER_MESSAGE + ":" + _ezObj.getOid();
|
||||
if (msgName == event.getName()) {
|
||||
var args :Array = event.getArgs();
|
||||
callUserCode("messageReceived_v1", (args[0] as String),
|
||||
EZObjectMarshaller.decode(args[1]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle the arrival of a new UserCookie.
|
||||
*/
|
||||
private function receivedUserCookie (cookie :UserCookie) :void
|
||||
protected function receivedUserCookie (cookie :UserCookie) :void
|
||||
{
|
||||
if (_cookieCallbacks != null) {
|
||||
var arr :Array = (_cookieCallbacks[cookie.playerIndex] as Array);
|
||||
@@ -573,8 +561,13 @@ public class GameObjectImpl extends EventDispatcher
|
||||
|
||||
protected var _ctx :CrowdContext;
|
||||
|
||||
protected var _userListener :MessageAdapter =
|
||||
new MessageAdapter(messageReceivedOnUserObject);
|
||||
|
||||
protected var _ezObj :EZGameObject;
|
||||
|
||||
protected var _userFuncs :Object;
|
||||
|
||||
protected var _gameData :GameData;
|
||||
|
||||
/** playerIndex -> callback functions waiting for the cookie. */
|
||||
@@ -10,9 +10,9 @@ use namespace flash_proxy;
|
||||
|
||||
public class GameData extends Proxy
|
||||
{
|
||||
public function GameData (gameObjImpl :GameObjectImpl, props :Object)
|
||||
public function GameData (propSetFn :Function, props :Object)
|
||||
{
|
||||
_gameObjImpl = gameObjImpl;
|
||||
_propSetFn = propSetFn;
|
||||
_props = props;
|
||||
}
|
||||
|
||||
@@ -67,13 +67,13 @@ public class GameData extends Proxy
|
||||
|
||||
override flash_proxy function setProperty (propName :*, value :*) :void
|
||||
{
|
||||
_gameObjImpl.set(String(propName), value);
|
||||
_propSetFn(String(propName), value, -1);
|
||||
}
|
||||
|
||||
override flash_proxy function deleteProperty (propName :*) :Boolean
|
||||
{
|
||||
var hasProp :Boolean = hasProperty(propName);
|
||||
_gameObjImpl.set(String(propName), null);
|
||||
setProperty(propName, null);
|
||||
return hasProp;
|
||||
}
|
||||
|
||||
@@ -109,11 +109,11 @@ public class GameData extends Proxy
|
||||
return _props[nextName(index)];
|
||||
}
|
||||
|
||||
/** The GameObject that controls things. */
|
||||
protected var _gameObjImpl :GameObjectImpl;
|
||||
/** The function which we pass property setting to. */
|
||||
protected var _propSetFn :Function;
|
||||
|
||||
/** The object we're proxying. */
|
||||
protected var _props :Object;
|
||||
protected var _props :Object = { };
|
||||
|
||||
/** Used temporarily while iterating over our names or values. */
|
||||
protected var _propertyList :Array;
|
||||
|
||||
Reference in New Issue
Block a user