From 1a272ef171351a1cba0a489d53f1fb84c723abdc Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Wed, 22 Aug 2007 23:29:54 +0000 Subject: [PATCH] Widening and removal of compatibility code for never-in-the-wild functionality. git-svn-id: svn+ssh://src.earth.threerings.net/vilya/trunk@412 c613c5cb-e716-0410-b11b-feb51c14d237 --- .../ezgame/client/GameControlBackend.as | 1178 ++++++++--------- .../ezgame/client/GameControlCompatibility.as | 179 --- 2 files changed, 577 insertions(+), 780 deletions(-) delete mode 100644 src/as/com/threerings/ezgame/client/GameControlCompatibility.as diff --git a/src/as/com/threerings/ezgame/client/GameControlBackend.as b/src/as/com/threerings/ezgame/client/GameControlBackend.as index 7b27d945..e63f9637 100644 --- a/src/as/com/threerings/ezgame/client/GameControlBackend.as +++ b/src/as/com/threerings/ezgame/client/GameControlBackend.as @@ -88,8 +88,7 @@ import com.threerings.ezgame.data.UserCookie; * Manages the backend of the game. */ public class GameControlBackend - implements MessageListener, SetListener, ElementUpdateListener, - PropertySetListener, ChatDisplay + implements MessageListener, SetListener, ElementUpdateListener, PropertySetListener, ChatDisplay { public var log :Log = Log.getLog(this); @@ -129,545 +128,17 @@ public class GameControlBackend _ezObj.removeListener(this); _ctx.getChatDirector().removeChatDisplay(this); _ctx.getClient().getClientObject().removeListener(_userListener); - _userFuncs = null; // disconnect } - protected function handleEZQuery (evt :Object) :void - { - setUserCodeProperties(evt.userProps); - evt.ezProps = new Object(); - populateProperties(evt.ezProps); - - // determine whether to automatically start the game in a backwards compatible way - var autoReady :Boolean = - ("autoReady_v1" in evt.userProps) ? evt.userProps["autoReady_v1"] : true; - - // ok, we're now hooked-up with the game code - _ctrl.userCodeIsConnected(autoReady); - } - - protected function setUserCodeProperties (o :Object) :void - { - // here we would handle adapting old functions to a new version - _ezDispatcher = (o["dispatchEvent_v1"] as Function); - _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 undefined; - } - - protected function populateProperties (o :Object) :void - { - // add in any backwards-compatible functions - new GameControlCompatibility(_ezObj, this).populateProperties(o); - - // straight data - o["gameData"] = _gameData; - - // convert our game config from a HashMap to a Dictionary - var gameConfig :Object = {}; - var cfg :EZGameConfig = (_ctrl.getPlaceConfig() as EZGameConfig); - cfg.params.forEach(function (key :Object, value :Object) :void { - gameConfig[key] = (value is Wrapped) ? Wrapped(value).unwrap() : value; - }); - o["gameConfig"] = gameConfig; - - // functions - o["playerReady_v1"] = playerReady_v1; - o["setProperty_v1"] = setProperty_v1; - o["testAndSetProperty_v1"] = testAndSetProperty_v1; - o["mergeCollection_v1"] = mergeCollection_v1; - o["setTicker_v1"] = setTicker_v1; - o["sendChat_v1"] = sendChat_v1; - o["localChat_v1"] = localChat_v1; - o["setUserCookie_v1"] = setUserCookie_v1; - o["isMyTurn_v1"] = isMyTurn_v1; - o["isInPlay_v1"] = isInPlay_v1; - o["getDictionaryLetterSet_v1"] = getDictionaryLetterSet_v1; - o["checkDictionaryWord_v1"] = checkDictionaryWord_v1; - o["populateCollection_v1"] = populateCollection_v1; - o["alterKeyEvents_v1"] = alterKeyEvents_v1; - o["focusContainer_v1"] = focusContainer_v1; - - // newest - o["getFromCollection_v2"] = getFromCollection_v2; - o["sendMessage_v2"] = sendMessage_v2; - o["getOccupants_v1"] = getOccupants_v1; - o["getMyId_v1"] = getMyId_v1; - o["getControllerId_v1"] = getControllerId_v1; - o["getUserCookie_v2"] = getUserCookie_v2; - o["endTurn_v2"] = endTurn_v2; - o["endRound_v1"] = endRound_v1; - o["endGame_v2"] = endGame_v2; - o["getTurnHolder_v1"] = getTurnHolder_v1; - o["getRound_v1"] = getRound_v1; - o["getOccupantName_v1"] = getOccupantName_v1; - o["getPlayers_v1"] = getPlayers_v1; - o["getPlayerPosition_v1"] = getPlayerPosition_v1; - o["getMyPosition_v1"] = getMyPosition_v1; - o["filter_v1"] = filter_v1; - - o["startTransaction"] = startTransaction_v1; - o["commitTransaction"] = commitTransaction_v1; - } - - /** - * Called by the client code when it is ready for the game to be started. - */ - public function playerReady_v1 () :void - { - _ctrl.playerIsReady(); - } - - /** - * Sets a property. - * - * Note: immediate defaults to true, even though immediate=false is the general case. We are - * providing some backwards compatibility to old versions of setProperty_v1() that assumed - * immediate and did not pass a 4th value. All callers should now specify that value - * explicitly. - */ - public function setProperty_v1 ( - propName :String, value :Object, index :int, immediate :Boolean = true) :void - { - validateConnected(); - validatePropertyChange(propName, value, index); - - var encoded :Object = ObjectMarshaller.encode(value, (index == -1)); - _ezObj.ezGameService.setProperty( - _ctx.getClient(), propName, encoded, index, - false, null, createLoggingConfirmListener("setProperty")); - if (immediate) { - _ezObj.applyPropertySet(propName, value, index); - } - } - - public function testAndSetProperty_v1 ( - propName :String, value :Object, testValue :Object, index :int) :void - { - validateConnected(); - validatePropertyChange(propName, value, index); - - var encodedValue :Object = ObjectMarshaller.encode(value, (index == -1)); - var encodedTestValue :Object = ObjectMarshaller.encode(testValue, (index == -1)); - _ezObj.ezGameService.setProperty( - _ctx.getClient(), propName, encodedValue, index, - true, encodedTestValue, createLoggingConfirmListener("setProperty")); - } - - - public function mergeCollection_v1 ( - srcColl :String, intoColl :String) :void - { - validateConnected(); - validateName(srcColl); - validateName(intoColl); - _ezObj.ezGameService.mergeCollection(_ctx.getClient(), - srcColl, intoColl, createLoggingConfirmListener("mergeCollection")); - } - - public function sendMessage_v2 ( - messageName :String, value :Object, playerId :int) :void - { - validateConnected(); - validateName(messageName); - validateValue(value); - - var encoded :Object = ObjectMarshaller.encode(value, false); - _ezObj.ezGameService.sendMessage(_ctx.getClient(), - messageName, encoded, playerId, - createLoggingConfirmListener("sendMessage")); - } - - public function setTicker_v1 (tickerName :String, msOfDelay :int) :void - { - validateConnected(); - validateName(tickerName); - _ezObj.ezGameService.setTicker(_ctx.getClient(), - tickerName, msOfDelay, createLoggingConfirmListener("setTicker")); - } - - public function sendChat_v1 (msg :String) :void - { - validateConnected(); - validateChat(msg); - // Post a message to the game object, the controller - // will listen and call localChat(). - _ezObj.postMessage(EZGameObject.GAME_CHAT, [ msg ]); - } - - public function localChat_v1 (msg :String) :void - { - validateChat(msg); - // The sendChat() messages will end up being routed - // through this method on each client. - // TODO: make this look distinct from other system chat - _ctx.getChatDirector().displayInfo(null, MessageBundle.taint(msg)); - } - - public function filter_v1 (text :String) :String - { - return _ctx.getChatDirector().filter(text, null, true); - } - - public function getOccupants_v1 () :Array - { - validateConnected(); - var occs :Array = []; - for (var ii :int = _ezObj.occupants.size() - 1; ii >= 0; ii--) { - occs.push(_ezObj.occupants.get(ii)); - } - - return occs; - } - - public function getPlayers_v1 () :Array - { - validateConnected(); - if (_ezObj.players.length == 0) { - // party game - return getOccupants_v1(); - } - var playerIds :Array = []; - for (var ii :int = 0; ii < _ezObj.players.length; ii++) { - var occInfo :OccupantInfo = _ezObj.getOccupantInfo(_ezObj.players[ii] as Name); - playerIds.push((occInfo == null) ? 0 : occInfo.bodyOid); - } - return playerIds; - } - - public function getOccupantName_v1 (playerId :int) :String - { - validateConnected(); - var occInfo :OccupantInfo = - (_ezObj.occupantInfo.get(playerId) as OccupantInfo); - return (occInfo == null) ? null : occInfo.username.toString(); - } - - public function getMyId_v1 () :int - { - validateConnected(); - return _ctx.getClient().getClientObject().getOid(); - } - - public function getControllerId_v1 () :int - { - validateConnected(); - return _ezObj.controllerOid; - } - - // TODO: table games only - public function getPlayerPosition_v1 (playerId :int) :int - { - validateConnected(); - var occInfo :OccupantInfo = - (_ezObj.occupantInfo.get(playerId) as OccupantInfo); - if (occInfo == null) { - return -1; - } - return _ezObj.getPlayerIndex(occInfo.username); - } - - // TODO: table only - public function getMyPosition_v1 () :int - { - validateConnected(); - return _ezObj.getPlayerIndex( - (_ctx.getClient().getClientObject() as BodyObject).getVisibleName()); - } - - // TODO: table only - public function getTurnHolder_v1 () :int - { - validateConnected(); - var occInfo :OccupantInfo = _ezObj.getOccupantInfo(_ezObj.turnHolder); - return (occInfo == null) ? 0 : occInfo.bodyOid; - } - - public function getRound_v1 () :int - { - validateConnected(); - return _ezObj.roundId; - } - - public function getUserCookie_v2 ( - playerId :int, callback :Function) :void - { - validateConnected(); - // see if that cookie is already published - if (_ezObj.userCookies != null) { - var uc :UserCookie = - (_ezObj.userCookies.get(playerId) as UserCookie); - if (uc != null) { - callback(ObjectMarshaller.decode(uc.cookie)); - return; - } - } - - if (_cookieCallbacks == null) { - _cookieCallbacks = new Dictionary(); - } - var arr :Array = (_cookieCallbacks[playerId] as Array); - if (arr == null) { - arr = []; - _cookieCallbacks[playerId] = arr; - } - arr.push(callback); - - // request it to be made so by the server - _ezObj.ezGameService.getCookie(_ctx.getClient(), playerId, - createLoggingConfirmListener("getUserCookie")); - } - - public function setUserCookie_v1 (cookie :Object) :Boolean - { - validateConnected(); - validateValue(cookie); - var ba :ByteArray = - (ObjectMarshaller.encode(cookie, false) as ByteArray); - if (ba.length > MAX_USER_COOKIE) { - // not saved! - return false; - } - - _ezObj.ezGameService.setCookie(_ctx.getClient(), ba, - createLoggingConfirmListener("setUserCookie")); - return true; - } - - public function isMyTurn_v1 () :Boolean - { - validateConnected(); - return getUsername().equals(_ezObj.turnHolder); - } - - public function isInPlay_v1 () :Boolean - { - validateConnected(); - return _ezObj.isInPlay(); - } - - public function endTurn_v2 (nextPlayerId :int) :void - { - validateConnected(); - _ezObj.ezGameService.endTurn( - _ctx.getClient(), nextPlayerId, createLoggingConfirmListener("endTurn")); - } - - public function endRound_v1 (nextRoundDelay :int) :void - { - validateConnected(); - _ezObj.ezGameService.endRound( - _ctx.getClient(), nextRoundDelay, createLoggingConfirmListener("endRound")); - } - - public function endGame_v2 (... winnerIds) :void - { - validateConnected(); - var winners :TypedArray = TypedArray.create(int); - while (winnerIds.length > 0) { - winners.push(int(winnerIds.shift())); - } - _ezObj.ezGameService.endGame( - _ctx.getClient(), winners, createLoggingConfirmListener("endGame")); - } - - public function getDictionaryLetterSet_v1 (locale :String, count :int, callback :Function) :void - { - validateConnected(); - var listener :InvocationService_ResultListener; - if (callback != null) { - var failure :Function = function (cause :String = null) :void { - // ignore the cause, return an empty array - callback ([]); - } - var success :Function = function (result :String = null) :void { - // splice the resulting string, and return as array - var r : Array = result.split(","); - callback (r); - }; - listener = new ResultWrapper (failure, success); - } else { - listener = createLoggingResultListener ("checkDictionaryWord"); - } - - // just relay the data over to the server - _ezObj.ezGameService.getDictionaryLetterSet(_ctx.getClient(), locale, count, listener); - } - - public function checkDictionaryWord_v1 ( - locale :String, word :String, callback :Function) :void - { - validateConnected(); - var listener :InvocationService_ResultListener; - if (callback != null) { - var failure :Function = function (cause :String = null) :void { - // ignore the cause, return failure - callback (word, false); - } - var success :Function = function (result :Object = null) :void { - // server returns a boolean, so convert it and send it over - var r : Boolean = Boolean(result); - callback (word, r); - }; - listener = new ResultWrapper (failure, success); - } else { - listener = createLoggingResultListener ("checkDictionaryWord"); - } - - // just relay the data over to the server - _ezObj.ezGameService.checkDictionaryWord(_ctx.getClient(), locale, word, listener); - - } - - /** - * Helper method for setCollection and addToCollection. - */ - public function populateCollection_v1 ( - collName :String, values :Array, clearExisting :Boolean) :void - { - validateConnected(); - validateName(collName); - if (values == null) { - throw new ArgumentError("Collection values may not be null."); - } - validateValue(values); - - var encodedValues :TypedArray = - (ObjectMarshaller.encode(values, true) as TypedArray); - - _ezObj.ezGameService.addToCollection( - _ctx.getClient(), collName, encodedValues, clearExisting, - createLoggingConfirmListener("populateCollection")); - } - - /** - * Helper method for pickFromCollection and dealFromCollection. - */ - public function getFromCollection_v2 ( - collName :String, count :int, msgOrPropName :String, playerId :int, - consume :Boolean, callback :Function) :void - { - validateConnected(); - validateName(collName); - validateName(msgOrPropName); - if (count < 1) { - throw new ArgumentError("Must retrieve at least one element!"); - } - - var listener :InvocationService_ConfirmListener; - if (callback != null) { - // TODO: Figure out the method sig of the callback, and what it - // means - var fn :Function = function (cause :String = null) :void { - if (cause == null) { - callback(count); - } else { - callback(parseInt(cause)); - } - }; - listener = new ConfirmAdapter(fn, fn); - - } else { - listener = createLoggingConfirmListener("getFromCollection"); - } - - _ezObj.ezGameService.getFromCollection( - _ctx.getClient(), collName, consume, count, msgOrPropName, - playerId, listener); - } - - public function alterKeyEvents_v1 ( - keyEventType :String, add :Boolean) :void - { - validateConnected(); - if (add) { - _container.addEventListener(keyEventType, handleKeyEvent); - } else { - _container.removeEventListener(keyEventType, handleKeyEvent); - } - } - - public function focusContainer_v1 () :void - { - validateConnected(); - _container.setFocus(); - } - - /** - * Start a dobj transaction on the game object. - */ - public function startTransaction_v1 () :void - { - validateConnected(); - _ezObj.startTransaction(); - } - - /** - * Commit a dobj transaction on the game object. - */ - public function commitTransaction_v1 () :void - { - _ezObj.commitTransaction(); - } - /** * Convenience function to get our name. */ public function getUsername () :Name { - var body :BodyObject = - (_ctx.getClient().getClientObject() as BodyObject); + var body :BodyObject = (_ctx.getClient().getClientObject() as BodyObject); return body.getVisibleName(); } - - /** - * Handle key events on our container and pass them into the game. - */ - protected function handleKeyEvent (evt :KeyboardEvent) :void - { - // dispatch a cloned copy of the event, so that it's safe - _ezDispatcher(evt.clone()); - } - - /** - * Create a logging confirm listener for service requests. - */ - protected function createLoggingConfirmListener ( - service :String) :InvocationService_ConfirmListener - { - return new ConfirmAdapter(function (cause :String) :void { - Log.getLog(this).warning("Service failure " + - "[service=" + service + ", cause=" + cause + "]."); - }); - } - - /** - * Create a logging result listener for service requests. - */ - protected function createLoggingResultListener ( - service :String) :InvocationService_ResultListener - { - return new ResultWrapper(function (cause :String) :void { - Log.getLog(this).warning("Service failure " + - "[service=" + service + ", cause=" + cause + "]."); - }); - } /** * Validate that we're not shutdown. @@ -679,56 +150,6 @@ public class GameControlBackend } } - /** - * Verify that the property name / value are valid. - */ - protected function validatePropertyChange ( - propName :String, value :Object, index :int) :void - { - validateName(propName); - - // check that we're setting an array element on an array - if (index >= 0) { - if (!(_gameData[propName] is Array)) { - throw new ArgumentError("Property " + propName + - " is not an Array."); - } - - } else if (index != -1) { - throw new ArgumentError("Invalid index specified: " + index); - } - - // validate the value too - validateValue(value); - } - - /** - * Verify that the specified name is valid. - */ - protected function validateName (name :String) :void - { - if (name == null) { - throw new ArgumentError( - "Property, message, and collection names must not be null."); - } - } - - protected function validateChat (msg :String) :void - { - if (StringUtil.isBlank(msg)) { - throw new ArgumentError( - "Empty chat may not be displayed."); - } - } - - /** - * Verify that the value is legal to be streamed to other clients. - */ - protected function validateValue (value :Object) :void - { - ObjectMarshaller.validateValue(value); - } - /** * Called by the EZGameController when the controller changes. */ @@ -835,6 +256,25 @@ public class GameControlBackend } } + // from MessageListener + public function messageReceived (event :MessageEvent) :void + { + var name :String = event.getName(); + if (EZGameObject.USER_MESSAGE == name) { + var args :Array = event.getArgs(); + var mname :String = (args[0] as String); + callUserCode("messageReceived_v1", mname, ObjectMarshaller.decode(args[1])); + + } else if (EZGameObject.GAME_CHAT == name) { + // chat sent 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 int)); + } + } + // from PropertySetListener public function propertyWasSet (event :PropertySetEvent) :void { @@ -859,38 +299,99 @@ public class GameControlBackend return true; } - public function messageReceived (event :MessageEvent) :void + /** + * Handle key events on our container and pass them into the game. + */ + protected function handleKeyEvent (evt :KeyboardEvent) :void { - var name :String = event.getName(); - if (EZGameObject.USER_MESSAGE == name) { - var args :Array = event.getArgs(); - callUserCode("messageReceived_v1", (args[0] as String), - ObjectMarshaller.decode(args[1])); + // dispatch a cloned copy of the event, so that it's safe + _ezDispatcher(evt.clone()); + } - } 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])); + /** + * Create a logging confirm listener for service requests. + */ + protected function createLoggingConfirmListener ( + service :String) :InvocationService_ConfirmListener + { + return new ConfirmAdapter(function (cause :String) :void { + Log.getLog(this).warning( + "Service failure [service=" + service + ", cause=" + cause + "]."); + }); + } - } else if (EZGameObject.TICKER == name) { - var targs :Array = event.getArgs(); - callUserCode("messageReceived_v1", (targs[0] as String), (targs[1] as int)); + /** + * Create a logging result listener for service requests. + */ + protected function createLoggingResultListener ( + service :String) :InvocationService_ResultListener + { + return new ResultWrapper(function (cause :String) :void { + Log.getLog(this).warning( + "Service failure [service=" + service + ", cause=" + cause + "]."); + }); + } + + /** + * Verify that the property name / value are valid. + */ + protected function validatePropertyChange (propName :String, value :Object, index :int) :void + { + validateName(propName); + + // check that we're setting an array element on an array + if (index >= 0) { + if (!(_gameData[propName] is Array)) { + throw new ArgumentError("Property " + propName + " is not an Array."); + } + + } else if (index != -1) { + throw new ArgumentError("Invalid index specified: " + index); + } + + // validate the value too + validateValue(value); + } + + /** + * Verify that the specified name is valid. + */ + protected function validateName (name :String) :void + { + if (name == null) { + throw new ArgumentError("Property, message, and collection names must not be null."); } } /** - * Called by our user listener when we receive a message event - * on the user object. + * Verify that the supplied chat message is valid. + */ + protected function validateChat (msg :String) :void + { + if (StringUtil.isBlank(msg)) { + throw new ArgumentError("Empty chat may not be displayed."); + } + } + + /** + * Verify that the value is legal to be streamed to other clients. + */ + protected function validateValue (value :Object) :void + { + ObjectMarshaller.validateValue(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 evtName :String = EZGameObject.USER_MESSAGE + ":" + _ezObj.getOid(); + if (evtName == event.getName()) { var args :Array = event.getArgs(); - callUserCode("messageReceived_v1", (args[0] as String), - ObjectMarshaller.decode(args[1])); + var mname :String = (args[0] as String); + callUserCode("messageReceived_v1", mname, ObjectMarshaller.decode(args[1])); } } @@ -925,6 +426,481 @@ public class GameControlBackend return (-1 != _ezObj.getPlayerIndex(occupantName)); } + protected function handleEZQuery (evt :Object) :void + { + setUserCodeProperties(evt.userProps); + evt.ezProps = new Object(); + populateProperties(evt.ezProps); + + // determine whether to automatically start the game in a backwards compatible way + var autoReady :Boolean = ("autoReady_v1" in evt.userProps) ? + evt.userProps["autoReady_v1"] : true; + + // ok, we're now hooked-up with the game code + _ctrl.userCodeIsConnected(autoReady); + } + + protected function setUserCodeProperties (o :Object) :void + { + // here we would handle adapting old functions to a new version + _ezDispatcher = (o["dispatchEvent_v1"] as Function); + _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 undefined; + } + + protected function populateProperties (o :Object) :void + { + // straight data + o["gameData"] = _gameData; + + // convert our game config from a HashMap to a Dictionary + var gameConfig :Object = {}; + var cfg :EZGameConfig = (_ctrl.getPlaceConfig() as EZGameConfig); + cfg.params.forEach(function (key :Object, value :Object) :void { + gameConfig[key] = (value is Wrapped) ? Wrapped(value).unwrap() : value; + }); + o["gameConfig"] = gameConfig; + + // functions + o["playerReady_v1"] = playerReady_v1; + o["setProperty_v1"] = setProperty_v1; + o["testAndSetProperty_v1"] = testAndSetProperty_v1; + o["mergeCollection_v1"] = mergeCollection_v1; + o["setTicker_v1"] = setTicker_v1; + o["sendChat_v1"] = sendChat_v1; + o["localChat_v1"] = localChat_v1; + o["setUserCookie_v1"] = setUserCookie_v1; + o["isMyTurn_v1"] = isMyTurn_v1; + o["isInPlay_v1"] = isInPlay_v1; + o["getDictionaryLetterSet_v1"] = getDictionaryLetterSet_v1; + o["checkDictionaryWord_v1"] = checkDictionaryWord_v1; + o["populateCollection_v1"] = populateCollection_v1; + o["alterKeyEvents_v1"] = alterKeyEvents_v1; + o["focusContainer_v1"] = focusContainer_v1; + + // newest + o["getFromCollection_v2"] = getFromCollection_v2; + o["sendMessage_v2"] = sendMessage_v2; + o["getOccupants_v1"] = getOccupants_v1; + o["getMyId_v1"] = getMyId_v1; + o["getControllerId_v1"] = getControllerId_v1; + o["getUserCookie_v2"] = getUserCookie_v2; + o["endTurn_v2"] = endTurn_v2; + o["endRound_v1"] = endRound_v1; + o["endGame_v2"] = endGame_v2; + o["getTurnHolder_v1"] = getTurnHolder_v1; + o["getRound_v1"] = getRound_v1; + o["getOccupantName_v1"] = getOccupantName_v1; + o["getPlayers_v1"] = getPlayers_v1; + o["getPlayerPosition_v1"] = getPlayerPosition_v1; + o["getMyPosition_v1"] = getMyPosition_v1; + o["filter_v1"] = filter_v1; + + o["startTransaction"] = startTransaction_v1; + o["commitTransaction"] = commitTransaction_v1; + } + + /** + * Called by the client code when it is ready for the game to be started. + */ + protected function playerReady_v1 () :void + { + _ctrl.playerIsReady(); + } + + /** + * Sets a property. + * + * Note: immediate defaults to true, even though immediate=false is the general case. We are + * providing some backwards compatibility to old versions of setProperty_v1() that assumed + * immediate and did not pass a 4th value. All callers should now specify that value + * explicitly. + */ + protected function setProperty_v1 ( + propName :String, value :Object, index :int, immediate :Boolean = true) :void + { + validateConnected(); + validatePropertyChange(propName, value, index); + + var encoded :Object = ObjectMarshaller.encode(value, (index == -1)); + _ezObj.ezGameService.setProperty( + _ctx.getClient(), propName, encoded, index, + false, null, createLoggingConfirmListener("setProperty")); + if (immediate) { + _ezObj.applyPropertySet(propName, value, index); + } + } + + protected function testAndSetProperty_v1 ( + propName :String, value :Object, testValue :Object, index :int) :void + { + validateConnected(); + validatePropertyChange(propName, value, index); + + var encodedValue :Object = ObjectMarshaller.encode(value, (index == -1)); + var encodedTestValue :Object = ObjectMarshaller.encode(testValue, (index == -1)); + _ezObj.ezGameService.setProperty( + _ctx.getClient(), propName, encodedValue, index, true, encodedTestValue, + createLoggingConfirmListener("setProperty")); + } + + + protected function mergeCollection_v1 (srcColl :String, intoColl :String) :void + { + validateConnected(); + validateName(srcColl); + validateName(intoColl); + _ezObj.ezGameService.mergeCollection(_ctx.getClient(), + srcColl, intoColl, createLoggingConfirmListener("mergeCollection")); + } + + protected function sendMessage_v2 (messageName :String, value :Object, playerId :int) :void + { + validateConnected(); + validateName(messageName); + validateValue(value); + + var encoded :Object = ObjectMarshaller.encode(value, false); + _ezObj.ezGameService.sendMessage(_ctx.getClient(), messageName, encoded, playerId, + createLoggingConfirmListener("sendMessage")); + } + + protected function setTicker_v1 (tickerName :String, msOfDelay :int) :void + { + validateConnected(); + validateName(tickerName); + _ezObj.ezGameService.setTicker( + _ctx.getClient(), tickerName, msOfDelay, createLoggingConfirmListener("setTicker")); + } + + protected function sendChat_v1 (msg :String) :void + { + validateConnected(); + validateChat(msg); + // Post a message to the game object, the controller will listen and call localChat(). + _ezObj.postMessage(EZGameObject.GAME_CHAT, [ msg ]); + } + + protected function localChat_v1 (msg :String) :void + { + validateChat(msg); + // The sendChat() messages will end up being routed through this method on each client. + // TODO: make this look distinct from other system chat + _ctx.getChatDirector().displayInfo(null, MessageBundle.taint(msg)); + } + + protected function filter_v1 (text :String) :String + { + return _ctx.getChatDirector().filter(text, null, true); + } + + protected function getOccupants_v1 () :Array + { + validateConnected(); + var occs :Array = []; + for (var ii :int = _ezObj.occupants.size() - 1; ii >= 0; ii--) { + occs.push(_ezObj.occupants.get(ii)); + } + return occs; + } + + protected function getPlayers_v1 () :Array + { + validateConnected(); + if (_ezObj.players.length == 0) { + // party game + return getOccupants_v1(); + } + var playerIds :Array = []; + for (var ii :int = 0; ii < _ezObj.players.length; ii++) { + var occInfo :OccupantInfo = _ezObj.getOccupantInfo(_ezObj.players[ii] as Name); + playerIds.push((occInfo == null) ? 0 : occInfo.bodyOid); + } + return playerIds; + } + + protected function getOccupantName_v1 (playerId :int) :String + { + validateConnected(); + var occInfo :OccupantInfo = (_ezObj.occupantInfo.get(playerId) as OccupantInfo); + return (occInfo == null) ? null : occInfo.username.toString(); + } + + protected function getMyId_v1 () :int + { + validateConnected(); + return _ctx.getClient().getClientObject().getOid(); + } + + protected function getControllerId_v1 () :int + { + validateConnected(); + return _ezObj.controllerOid; + } + + // TODO: table games only + protected function getPlayerPosition_v1 (playerId :int) :int + { + validateConnected(); + var occInfo :OccupantInfo = (_ezObj.occupantInfo.get(playerId) as OccupantInfo); + if (occInfo == null) { + return -1; + } + return _ezObj.getPlayerIndex(occInfo.username); + } + + // TODO: table only + protected function getMyPosition_v1 () :int + { + validateConnected(); + return _ezObj.getPlayerIndex( + (_ctx.getClient().getClientObject() as BodyObject).getVisibleName()); + } + + // TODO: table only + protected function getTurnHolder_v1 () :int + { + validateConnected(); + var occInfo :OccupantInfo = _ezObj.getOccupantInfo(_ezObj.turnHolder); + return (occInfo == null) ? 0 : occInfo.bodyOid; + } + + protected function getRound_v1 () :int + { + validateConnected(); + return _ezObj.roundId; + } + + protected function getUserCookie_v2 (playerId :int, callback :Function) :void + { + validateConnected(); + // see if that cookie is already published + if (_ezObj.userCookies != null) { + var uc :UserCookie = (_ezObj.userCookies.get(playerId) as UserCookie); + if (uc != null) { + callback(ObjectMarshaller.decode(uc.cookie)); + return; + } + } + + if (_cookieCallbacks == null) { + _cookieCallbacks = new Dictionary(); + } + var arr :Array = (_cookieCallbacks[playerId] as Array); + if (arr == null) { + arr = []; + _cookieCallbacks[playerId] = arr; + } + arr.push(callback); + + // request it to be made so by the server + _ezObj.ezGameService.getCookie( + _ctx.getClient(), playerId, createLoggingConfirmListener("getUserCookie")); + } + + protected function setUserCookie_v1 (cookie :Object) :Boolean + { + validateConnected(); + validateValue(cookie); + var ba :ByteArray = (ObjectMarshaller.encode(cookie, false) as ByteArray); + if (ba.length > MAX_USER_COOKIE) { + // not saved! + return false; + } + + _ezObj.ezGameService.setCookie( + _ctx.getClient(), ba, createLoggingConfirmListener("setUserCookie")); + return true; + } + + protected function isMyTurn_v1 () :Boolean + { + validateConnected(); + return getUsername().equals(_ezObj.turnHolder); + } + + protected function isInPlay_v1 () :Boolean + { + validateConnected(); + return _ezObj.isInPlay(); + } + + protected function endTurn_v2 (nextPlayerId :int) :void + { + validateConnected(); + _ezObj.ezGameService.endTurn( + _ctx.getClient(), nextPlayerId, createLoggingConfirmListener("endTurn")); + } + + protected function endRound_v1 (nextRoundDelay :int) :void + { + validateConnected(); + _ezObj.ezGameService.endRound( + _ctx.getClient(), nextRoundDelay, createLoggingConfirmListener("endRound")); + } + + protected function endGame_v2 (... winnerIds) :void + { + validateConnected(); + var winners :TypedArray = TypedArray.create(int); + while (winnerIds.length > 0) { + winners.push(int(winnerIds.shift())); + } + _ezObj.ezGameService.endGame( + _ctx.getClient(), winners, createLoggingConfirmListener("endGame")); + } + + protected function getDictionaryLetterSet_v1 ( + locale :String, count :int, callback :Function) :void + { + validateConnected(); + var listener :InvocationService_ResultListener; + if (callback != null) { + var failure :Function = function (cause :String = null) :void { + // ignore the cause, return an empty array + callback ([]); + } + var success :Function = function (result :String = null) :void { + // splice the resulting string, and return as array + var r : Array = result.split(","); + callback (r); + }; + listener = new ResultWrapper (failure, success); + } else { + listener = createLoggingResultListener ("checkDictionaryWord"); + } + + // just relay the data over to the server + _ezObj.ezGameService.getDictionaryLetterSet(_ctx.getClient(), locale, count, listener); + } + + protected function checkDictionaryWord_v1 ( + locale :String, word :String, callback :Function) :void + { + validateConnected(); + var listener :InvocationService_ResultListener; + if (callback != null) { + var failure :Function = function (cause :String = null) :void { + // ignore the cause, return failure + callback (word, false); + } + var success :Function = function (result :Object = null) :void { + // server returns a boolean, so convert it and send it over + var r : Boolean = Boolean(result); + callback (word, r); + }; + listener = new ResultWrapper (failure, success); + } else { + listener = createLoggingResultListener ("checkDictionaryWord"); + } + + // just relay the data over to the server + _ezObj.ezGameService.checkDictionaryWord(_ctx.getClient(), locale, word, listener); + + } + + /** + * Helper method for setCollection and addToCollection. + */ + protected function populateCollection_v1 ( + collName :String, values :Array, clearExisting :Boolean) :void + { + validateConnected(); + validateName(collName); + if (values == null) { + throw new ArgumentError("Collection values may not be null."); + } + validateValue(values); + + var encodedValues :TypedArray = (ObjectMarshaller.encode(values, true) as TypedArray); + _ezObj.ezGameService.addToCollection( + _ctx.getClient(), collName, encodedValues, clearExisting, + createLoggingConfirmListener("populateCollection")); + } + + /** + * Helper method for pickFromCollection and dealFromCollection. + */ + protected function getFromCollection_v2 ( + collName :String, count :int, msgOrPropName :String, playerId :int, + consume :Boolean, callback :Function) :void + { + validateConnected(); + validateName(collName); + validateName(msgOrPropName); + if (count < 1) { + throw new ArgumentError("Must retrieve at least one element!"); + } + + var listener :InvocationService_ConfirmListener; + if (callback != null) { + // TODO: Figure out the method sig of the callback, and what it means + var fn :Function = function (cause :String = null) :void { + if (cause == null) { + callback(count); + } else { + callback(parseInt(cause)); + } + }; + listener = new ConfirmAdapter(fn, fn); + + } else { + listener = createLoggingConfirmListener("getFromCollection"); + } + + _ezObj.ezGameService.getFromCollection( + _ctx.getClient(), collName, consume, count, msgOrPropName, playerId, listener); + } + + protected function alterKeyEvents_v1 (keyEventType :String, add :Boolean) :void + { + validateConnected(); + if (add) { + _container.addEventListener(keyEventType, handleKeyEvent); + } else { + _container.removeEventListener(keyEventType, handleKeyEvent); + } + } + + protected function focusContainer_v1 () :void + { + validateConnected(); + _container.setFocus(); + } + + /** + * Start a dobj transaction on the game object. + */ + protected function startTransaction_v1 () :void + { + validateConnected(); + _ezObj.startTransaction(); + } + + /** + * Commit a dobj transaction on the game object. + */ + protected function commitTransaction_v1 () :void + { + _ezObj.commitTransaction(); + } + protected var _ctx :CrowdContext; protected var _userListener :MessageAdapter = diff --git a/src/as/com/threerings/ezgame/client/GameControlCompatibility.as b/src/as/com/threerings/ezgame/client/GameControlCompatibility.as deleted file mode 100644 index 7330dbf8..00000000 --- a/src/as/com/threerings/ezgame/client/GameControlCompatibility.as +++ /dev/null @@ -1,179 +0,0 @@ -// -// $Id$ -// -// Vilya library - tools for developing networked games -// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved -// http://www.threerings.net/code/vilya/ -// -// 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.ezgame.client { - -import com.threerings.util.Iterator; -import com.threerings.util.Name; - -import com.threerings.crowd.data.OccupantInfo; -import com.threerings.ezgame.data.EZGameObject; - -/** - * Contains adapter functions to provide backwards compatibility for - * older EZ games. - */ -public class GameControlCompatibility -{ - public function GameControlCompatibility ( - ezObj :EZGameObject, backend :GameControlBackend) - { - _ezObj = ezObj; - _backend = backend; - } - - public function populateProperties (o :Object) :void - { - // The below were all deprecated on Feb 13, 2007. - // These were ever only used internally at Three Rings. - // These can be removed sooner rather than later. - o["getFromCollection_v1"] = getFromCollection_v1; - o["sendMessage_v1"] = sendMessage_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["endTurn_v1"] = endTurn_v1; - o["endGame_v1"] = endGame_v1; - } - - /** - * BackCompat: turn a player index into an oid. - */ - protected function indexToId (index :int) :int - { - var name :Name = _ezObj.players[index]; - if (name != null) { - var occInfo :OccupantInfo = _ezObj.getOccupantInfo(name); - if (occInfo != null) { - return occInfo.bodyOid; - } - } - - return 0; - } - - protected function getFromCollection_v1 ( - collName :String, count :int, msgOrPropName :String, - playerIndex :int, consume :Boolean, callback :Function) :void - { - _backend.getFromCollection_v2(collName, count, msgOrPropName, - indexToId(playerIndex), consume, callback); - } - - public function sendMessage_v1 ( - messageName :String, value :Object, playerIndex :int) :void - { - _backend.sendMessage_v2(messageName, value, indexToId(playerIndex)); - } - - public function getPlayerCount_v1 () :int - { - _backend.validateConnected(); - if (_ezObj.players.length == 0) { - // party game - return _ezObj.occupants.size(); - - } else { - return _ezObj.getPlayerCount(); - } - } - - public function getPlayerNames_v1 () :Array - { - _backend.validateConnected(); - var names :Array = []; - if (_ezObj.players.length == 0) { - // party game, count all occupants - var itr :Iterator = _ezObj.occupantInfo.iterator(); - while (itr.hasNext()) { - var occInfo :OccupantInfo = (itr.next() as OccupantInfo); - names.push(occInfo.username.toString()); - } - - } else { - for each (var name :Name in _ezObj.players) { - names.push((name == null) ? null : name.toString()); - } - } - return names; - } - - public function getMyIndex_v1 () :int - { - _backend.validateConnected(); - if (_ezObj.players.length == 0) { - // TODO: this shouldn't be based off of the String form of the name. - var array :Array = getPlayerNames_v1(); - return array.indexOf(_backend.getUsername().toString()); - - } else { - return _ezObj.getPlayerIndex(_backend.getUsername()); - } - } - - public function getTurnHolderIndex_v1 () :int - { - _backend.validateConnected(); - return _ezObj.getPlayerIndex(_ezObj.turnHolder); - } - - public function getWinnerIndexes_v1 () :Array /* of int */ - { - _backend.validateConnected(); - var arr :Array = new Array(); - if (_ezObj.winners != null) { - for (var ii :int = 0; ii < _ezObj.winners.length; ii++) { - if (_ezObj.winners[ii]) { - arr.push(ii); - } - } - } - return arr; - } - - public function getUserCookie_v1 ( - playerIndex :int, callback :Function) :void - { - _backend.getUserCookie_v2(indexToId(playerIndex), callback); - } - - public function endTurn_v1 (nextPlayerIndex :int) :void - { - _backend.endTurn_v2(indexToId(nextPlayerIndex)); - } - - public function endGame_v1 (... winnerDexes) :void - { - var winnerIds :Array = []; - for each (var dex :int in winnerDexes) { - winnerIds.push(indexToId(dex)); - } - _backend.endGame_v2.apply(this, winnerIds); - } - - protected var _ezObj :EZGameObject; - - protected var _backend :GameControlBackend; -} -}