Files
vilya/src/as/com/threerings/ezgame/client/GameControlBackend.as
T
Ray Greenwell 26f5a67328 Log -> com.threerings.util.Log
git-svn-id: svn+ssh://src.earth.threerings.net/vilya/trunk@493 c613c5cb-e716-0410-b11b-feb51c14d237
2007-11-13 09:31:12 +00:00

983 lines
32 KiB
ActionScript

//
// $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 flash.display.DisplayObject;
import flash.display.InteractiveObject;
import flash.errors.IllegalOperationError;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.utils.ByteArray;
import flash.utils.Dictionary;
import com.threerings.io.TypedArray;
import com.threerings.util.ArrayUtil;
import com.threerings.util.ClassUtil;
import com.threerings.util.Integer;
import com.threerings.util.Iterator;
import com.threerings.util.Log;
import com.threerings.util.MessageBundle;
import com.threerings.util.Name;
import com.threerings.util.ObjectMarshaller;
import com.threerings.util.StringUtil;
import com.threerings.util.Wrapped;
import com.threerings.presents.client.ConfirmAdapter;
import com.threerings.presents.client.ResultWrapper;
import com.threerings.presents.client.InvocationService_ConfirmListener;
import com.threerings.presents.client.InvocationService_ResultListener;
import com.threerings.presents.dobj.ElementUpdateListener;
import com.threerings.presents.dobj.ElementUpdatedEvent;
import com.threerings.presents.dobj.EntryAddedEvent;
import com.threerings.presents.dobj.EntryRemovedEvent;
import com.threerings.presents.dobj.EntryUpdatedEvent;
import com.threerings.presents.dobj.MessageAdapter;
import com.threerings.presents.dobj.MessageEvent;
import com.threerings.presents.dobj.MessageListener;
import com.threerings.presents.dobj.ObjectAddedEvent;
import com.threerings.presents.dobj.ObjectRemovedEvent;
import com.threerings.presents.dobj.OidListListener;
import com.threerings.presents.dobj.SetListener;
import com.threerings.crowd.chat.client.ChatDisplay;
import com.threerings.crowd.chat.data.ChatCodes;
import com.threerings.crowd.chat.data.ChatMessage;
import com.threerings.crowd.chat.data.UserMessage;
import com.threerings.crowd.data.BodyObject;
import com.threerings.crowd.data.OccupantInfo;
import com.threerings.crowd.data.PlaceObject;
import com.threerings.crowd.util.CrowdContext;
import com.threerings.parlor.game.data.GameObject;
import com.threerings.ezgame.data.EZGameConfig;
import com.threerings.ezgame.data.EZGameObject;
import com.threerings.ezgame.data.PropertySetEvent;
import com.threerings.ezgame.data.PropertySetListener;
import com.threerings.ezgame.data.UserCookie;
/**
* Manages the backend of the game.
*/
public class GameControlBackend
implements MessageListener, SetListener, ElementUpdateListener, PropertySetListener, ChatDisplay
{
public var log :Log = Log.getLog(this);
public function GameControlBackend (
ctx :CrowdContext, ezObj :EZGameObject, ctrl :EZGameController)
{
_ctx = ctx;
_ezObj = ezObj;
_ctrl = ctrl;
_gameData = _ezObj.getUserProps();
_ezObj.addListener(this);
_ctx.getClient().getClientObject().addListener(_userListener);
_ctx.getChatDirector().addChatDisplay(this);
}
public function setSharedEvents (disp :IEventDispatcher) :void
{
disp.addEventListener("ezgameQuery", handleEZQuery);
}
/**
* Are we connected to the usercode on the front-end?
*/
public function isConnected () :Boolean
{
return (_userFuncs != null);
}
public function setContainer (container :GameContainer) :void
{
_container = container;
}
public function shutdown () :void
{
_ezObj.removeListener(this);
_ctx.getChatDirector().removeChatDisplay(this);
_ctx.getClient().getClientObject().removeListener(_userListener);
callUserCode("connectionClosed_v1");
_userFuncs = null; // disconnect
}
/**
* Convenience function to get our name.
*/
public function getUsername () :Name
{
var body :BodyObject = (_ctx.getClient().getClientObject() as BodyObject);
return body.getVisibleName();
}
/**
* Validate that we're not shutdown.
*/
public function validateConnected () :void
{
if (_userFuncs == null) {
throw new Error("Not connected.");
}
}
/**
* Called by the EZGameController when the controller changes.
*/
public function controlDidChange () :void
{
callUserCode("controlDidChange_v1");
}
/**
* Called by the EZGameController when the turn changes.
*/
public function turnDidChange () :void
{
callUserCode("turnDidChange_v1");
}
/**
* Called by the EZGameController when the game starts or ends.
*/
public function gameStateChanged (started :Boolean) :void
{
if (started && _userFuncs["gameDidStart_v1"] != null) {
callUserCode("gameDidStart_v1"); // backwards compatibility
} else if (!started && _userFuncs["gameDidEnd_v1"] != null) {
callUserCode("gameDidEnd_v1"); // backwards compatibility
} else {
callUserCode("gameStateChanged_v1", started); // new hotness
}
}
/**
* Called by the EZGameController when a round starts or ends.
*/
public function roundStateChanged (started :Boolean) :void
{
callUserCode("roundStateChanged_v1", started);
}
/**
* Called by the EZGamePanel when the size of the game area has changed.
*/
public function sizeChanged () :void
{
callUserCode("sizeChanged_v1", getSize_v1());
}
// from SetListener
public function entryAdded (event :EntryAddedEvent) :void
{
var name :String = event.getName();
switch (name) {
case EZGameObject.USER_COOKIES:
receivedUserCookie(event.getEntry() as UserCookie);
break;
case PlaceObject.OCCUPANT_INFO:
var occInfo :OccupantInfo = (event.getEntry() as OccupantInfo)
callUserCode("occupantChanged_v1", occInfo.bodyOid, isPlayer(occInfo.username), true);
break;
}
}
// from SetListener
public function entryUpdated (event :EntryUpdatedEvent) :void
{
var name :String = event.getName();
switch (name) {
case EZGameObject.USER_COOKIES:
receivedUserCookie(event.getEntry() as UserCookie);
break;
}
}
// from SetListener
public function entryRemoved (event :EntryRemovedEvent) :void
{
var name :String = event.getName();
switch (name) {
case PlaceObject.OCCUPANT_INFO:
var occInfo :OccupantInfo = (event.getOldEntry() as OccupantInfo)
callUserCode("occupantChanged_v1", occInfo.bodyOid, isPlayer(occInfo.username), false);
break;
}
}
// from ElementUpdateListener
public function elementUpdated (event :ElementUpdatedEvent) :void
{
var name :String = event.getName();
if (name == GameObject.PLAYERS) {
var oldPlayer :Name = (event.getOldValue() as Name);
var newPlayer :Name = (event.getValue() as Name);
var occInfo :OccupantInfo;
if (oldPlayer != null) {
occInfo = _ezObj.getOccupantInfo(oldPlayer);
if (occInfo != null) {
// old player became a watcher
// send player-left, then occupant-added
callUserCode("occupantChanged_v1", occInfo.bodyOid, true, false);
callUserCode("occupantChanged_v1", occInfo.bodyOid, false, true);
}
}
if (newPlayer != null) {
occInfo = _ezObj.getOccupantInfo(newPlayer);
if (occInfo != null) {
// watcher became a player
// send occupant-left, then player-added
callUserCode("occupantChanged_v1", occInfo.bodyOid, false, false);
callUserCode("occupantChanged_v1", occInfo.bodyOid, true, true);
}
}
}
}
// 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
{
callUserCode("propertyWasSet_v1", event.getName(), event.getValue(),
event.getOldValue(), event.getIndex());
}
// from ChatDisplay
public function clear () :void
{
// we do nothing
}
// from ChatDisplay
public function displayMessage (msg :ChatMessage, alreadyDisplayed :Boolean) :Boolean
{
if (msg is UserMessage && msg.localtype == ChatCodes.PLACE_CHAT_TYPE) {
var info :OccupantInfo = _ezObj.getOccupantInfo((msg as UserMessage).speaker);
if (info != null) {
callUserCode("userChat_v1", info.bodyOid, msg.message);
}
}
return true;
}
/**
* 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 + "].");
});
}
/**
* 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.");
}
}
/**
* 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 evtName :String = EZGameObject.USER_MESSAGE + ":" + _ezObj.getOid();
if (evtName == event.getName()) {
var args :Array = event.getArgs();
var mname :String = (args[0] as String);
callUserCode("messageReceived_v1", mname, ObjectMarshaller.decode(args[1]));
}
}
/**
* Handle the arrival of a new UserCookie.
*/
protected function receivedUserCookie (cookie :UserCookie) :void
{
if (_cookieCallbacks != null) {
var arr :Array = (_cookieCallbacks[cookie.playerId] as Array);
if (arr != null) {
delete _cookieCallbacks[cookie.playerId];
for each (var fn :Function in arr) {
try {
fn(ObjectMarshaller.decode(cookie.cookie));
} catch (err :Error) {
// cope
}
}
}
}
}
/**
* Given the specified occupant name, return if they are a player.
*/
protected function isPlayer (occupantName :Name) :Boolean
{
if (_ezObj.players.length == 0) {
return true; // party game: all occupants are players
}
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_v2"] = getDictionaryLetterSet_v2;
o["checkDictionaryWord_v2"] = checkDictionaryWord_v2;
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["startNextTurn_v1"] = startNextTurn_v1;
o["endRound_v1"] = endRound_v1;
o["endGame_v2"] = endGame_v2;
o["restartGameIn_v1"] = restartGameIn_v1;
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;
o["getSize_v1"] = getSize_v1;
// compatability
o["endTurn_v2"] = startNextTurn_v1; // it's the same!
o["getDictionaryLetterSet_v1"] = getDictionaryLetterSet_v1;
o["checkDictionaryWord_v1"] = checkDictionaryWord_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 startNextTurn_v1 (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();
_ezObj.ezGameService.endGame(
_ctx.getClient(), toTypedIntArray(winnerIds), createLoggingConfirmListener("endGame"));
}
protected function restartGameIn_v1 (seconds :int) :void
{
validateConnected();
_ezObj.ezGameService.restartGameIn(
_ctx.getClient(), seconds, createLoggingConfirmListener("restartGameIn"));
}
protected function getDictionaryLetterSet_v1 (
locale :String, count :int, callback :Function) :void
{
getDictionaryLetterSet_v2(locale, null, count, callback);
}
protected function getDictionaryLetterSet_v2 (
locale :String, dictionary :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, dictionary, count, listener);
}
protected function checkDictionaryWord_v1 (
locale :String, word :String, callback :Function) :void
{
checkDictionaryWord_v2(locale, null, word, callback);
}
protected function checkDictionaryWord_v2 (
locale :String, dictionary :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, dictionary, 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();
}
/**
* Starts a transaction that will group all game state changes into a single message.
*/
protected function startTransaction_v1 () :void
{
validateConnected();
_ctx.getClient().getInvocationDirector().startTransaction();
}
/**
* Commits a transaction started with {@link #startTransaction_v1}.
*/
protected function commitTransaction_v1 () :void
{
_ctx.getClient().getInvocationDirector().commitTransaction();
}
/**
* Get the size of the game area.
*/
protected function getSize_v1 () :Point
{
return new Point(_container.width, _container.height);
}
/**
* Converts a Flash array of ints to a TypedArray for delivery over the wire to the server.
*/
protected function toTypedIntArray (array :Array) :TypedArray
{
var tarray :TypedArray = TypedArray.create(int);
tarray.addAll(array);
return tarray;
}
protected var _ctx :CrowdContext;
protected var _userListener :MessageAdapter = new MessageAdapter(messageReceivedOnUserObject);
protected var _container :GameContainer;
protected var _ezObj :EZGameObject;
/** Handles trusted clientside control. */
protected var _ctrl :EZGameController;
protected var _userFuncs :Object;
/** The function on the EZGameControl which we can use to directly dispatch events to the
* user's game. */
protected var _ezDispatcher :Function;
protected var _gameData :Object;
/** playerIndex -> callback functions waiting for the cookie. */
protected var _cookieCallbacks :Dictionary;
protected static const MAX_USER_COOKIE :int = 4096;
}
}