ezgame merges with whirledgame.

git-svn-id: svn+ssh://src.earth.threerings.net/vilya/trunk@558 c613c5cb-e716-0410-b11b-feb51c14d237
This commit is contained in:
Ray Greenwell
2008-02-17 00:47:45 +00:00
parent 3a9708b3de
commit 037a45b0f9
37 changed files with 0 additions and 5335 deletions
@@ -1,153 +0,0 @@
//
// $Id: BaseControl.as 414 2007-08-23 00:32:36Z mdb $
//
// 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 {
import flash.errors.IllegalOperationError;
import flash.events.Event;
import flash.events.EventDispatcher;
/**
* The abstract base class for Game controls and subcontrols.
* @private
*/
public class AbstractControl extends EventDispatcher
{
public function AbstractControl ()
{
if (Object(this).constructor == AbstractControl) {
throw new IllegalOperationError("Abstract");
}
}
/**
* Are we connected and running inside the game environment, or has someone just
* loaded up our SWF by itself?
*/
public function isConnected () :Boolean
{
return false;
}
/**
* Execute the specified function as a batch of commands that will be sent to the server
* together. This is no different from executing the commands outside of a batch, but
* may result in better use of the network and should be used if setting a number of things
* at once.
*
* Example:
* <code>
* _ctrl.doBatch(function () :void {
* _ctrl.net.set("board", new Array());
* _ctrl.net.set("scores", new Array());
* _ctrl.net.set("captures", 0);
* });
* </code>
*/
public function doBatch (fn :Function) :void
{
callHostCode("startTransaction");
try {
fn();
} finally {
callHostCode("commitTransaction");
}
}
/**
* Populate any properties or functions we want to expose to the host code.
* @private
*/
protected function populateProperties (o :Object) :void
{
// nothing by default
}
/**
* Grab any properties needed from our host code.
* @private
*/
protected function setHostProps (o :Object) :void
{
// nothing by default
}
/**
* Your own events may not be dispatched here.
* @private
*/
override public function dispatchEvent (event :Event) :Boolean
{
// Ideally we want to not be an EventDispatcher 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 weird.
throw new IllegalOperationError();
}
/**
* Secret function to dispatch property changed events.
* @private
*/
protected function dispatch (event :Event) :void
{
try {
super.dispatchEvent(event);
} catch (err :Error) {
// AFAIK, this will never happen: dispatchEvent catches and copes with all exceptions.
trace("Error dispatching event to user game.");
trace(err.getStackTrace());
}
}
/**
* Call a method exposed by the host code.
* @private
*/
protected function callHostCode (name :String, ... args) :*
{
return undefined; // no-op by default
}
/**
* Exposed to sub controls.
* @private
*/
internal function callHostCodeFriend (name :String, args :Array) :*
{
args.unshift(name);
return callHostCode.apply(this, args);
}
/**
* Helper method to throw an error if we're not connected.
* @private
*/
protected function checkIsConnected () :void
{
if (!isConnected()) {
throw new IllegalOperationError(
"The game is not connected to the host framework, please check isConnected(). " +
"If false, your game is being viewed standalone and should adjust.");
}
}
}
}
@@ -1,269 +0,0 @@
//
// $Id: EZGameControl.as 526 2007-12-13 01:42:10Z ray $
//
// 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 {
import flash.display.DisplayObject;
import flash.errors.IllegalOperationError;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.geom.Point;
/**
* Dispatched when the game client is unloaded and you should clean up any Timers or
* other bits left hanging.
*
* @eventType flash.events.Event.UNLOAD
*/
[Event(name="unload", type="flash.events.Event")]
/**
* Abstract base class for GameControl implementations.
* @private
*/
public class AbstractGameControl extends AbstractControl
{
/**
* @param autoReady if true, the game will automatically be started when initialization is
* complete, if false, the game will not start until all clients call {@link #playerReady}.
*/
public function AbstractGameControl (disp :DisplayObject, autoReady :Boolean)
{
if (disp == null || Object(this).constructor == AbstractGameControl) {
throw new IllegalOperationError("Abstract");
}
createSubControls();
var event :DynEvent = new DynEvent();
event.userProps = new Object();
populateProperties(event.userProps);
event.userProps["autoReady_v1"] = autoReady;
disp.root.loaderInfo.sharedEvents.dispatchEvent(event);
if ("ezProps" in event) {
setHostProps(event.ezProps);
}
// set up our focusing click handler
disp.root.addEventListener(MouseEvent.CLICK, handleRootClick);
// set up the unload event to propagate
disp.root.loaderInfo.addEventListener(Event.UNLOAD, dispatch);
}
/**
* @inheritDoc
*/
override public function isConnected () :Boolean
{
return _connected;
}
/**
* Create any subcontrols used by this game.
* @private
*/
protected function createSubControls () :void
{
_subControls.push(
_localCtrl = createLocalControl(),
_netCtrl = createNetControl(),
_playerCtrl = createPlayerControl(),
_gameCtrl = createGameControl(),
_servicesCtrl = createServicesControl()
);
}
/**
* Create the 'local' subcontrol.
* @private
*/
protected function createLocalControl () :EZLocalSubControl
{
return new EZLocalSubControl(this);
}
/**
* Create the 'net' subcontrol.
* @private
*/
protected function createNetControl () :EZNetSubControl
{
return new EZNetSubControl(this);
}
/**
* Create the 'player' subcontrol.
* @private
*/
protected function createPlayerControl () :EZPlayerSubControl
{
return new EZPlayerSubControl(this);
}
/**
* Create the 'game' subcontrol.
* @private
*/
protected function createGameControl () :EZGameSubControl
{
return new EZGameSubControl(this);
}
/**
* Create the 'services' subcontrol.
* @private
*/
protected function createServicesControl () :EZServicesSubControl
{
return new EZServicesSubControl(this);
}
/**
* Populate any properties or functions we want to expose to the other side of the ezgame
* security boundary.
* @private
*/
override protected function populateProperties (o :Object) :void
{
super.populateProperties(o);
o["connectionClosed_v1"] = connectionClosed_v1;
for each (var ctrl :AbstractSubControl in _subControls) {
ctrl.populatePropertiesFriend(o);
}
}
/**
* Sets the properties we received from the host framework on the other side of the security
* boundary.
* @private
*/
override protected function setHostProps (o :Object) :void
{
super.setHostProps(o);
// see if we're connected
_connected = (o.gameData != null);
for each (var ctrl :AbstractSubControl in _subControls) {
ctrl.setHostPropsFriend(o);
}
// and assign our functions
_funcs = o;
}
/**
* @private
*/
override protected function callHostCode (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(err.getStackTrace());
trace("--");
throw new Error("Unable to call host code: " + err.message);
}
} else {
// if _funcs is null, this will almost certainly throw an error..
checkIsConnected();
}
}
/**
* Internal method that is called whenever the mouse clicks our root.
* @private
*/
protected function handleRootClick (evt :MouseEvent) :void
{
if (!isConnected()) {
return;
}
try {
if (evt.target.stage == null || evt.target.stage.focus != null) {
return;
}
} catch (err :SecurityError) {
}
callHostCode("focusContainer_v1");
}
/**
* Private method called when the backend disconnects from us.
*/
private function connectionClosed_v1 () :void
{
_connected = false;
}
/** Are we connected? @private */
protected var _connected :Boolean;
/** Contains functions exposed to us from the EZGame host. @private */
protected var _funcs :Object;
/** Holds all our sub-controls. @private */
protected var _subControls :Array = [];
/** The local sub-control. @private */
protected var _localCtrl :EZLocalSubControl;
/** The net sub-control. @private */
protected var _netCtrl :EZNetSubControl;
/** The player sub-control. @private */
protected var _playerCtrl :EZPlayerSubControl;
/** The game sub-control. @private */
protected var _gameCtrl :EZGameSubControl;
/** The services sub-control. @private */
protected var _servicesCtrl :EZServicesSubControl;
}
}
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,88 +0,0 @@
//
// $Id: SubControl.as 271 2007-04-07 00:25:58Z dhoover $
//
// 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 {
import flash.errors.IllegalOperationError;
/**
* Abstract base class. Do not instantiate.
* @private
*/
public class AbstractSubControl extends AbstractControl
{
/**
* @private
*/
public function AbstractSubControl (parent :AbstractControl)
{
super();
if (parent == null || Object(this).constructor == AbstractSubControl) {
throw new IllegalOperationError("Abstract");
}
_parent = parent;
}
/**
* @inheritDoc
*/
override public function isConnected () :Boolean
{
return _parent.isConnected();
}
/**
* @inheritDoc
*/
override public function doBatch (fn :Function) :void
{
return _parent.doBatch(fn);
}
/**
* @private
*/
override protected function callHostCode (name :String, ... args) :*
{
return _parent.callHostCodeFriend(name, args);
}
/**
* @private
*/
internal function populatePropertiesFriend (o :Object) :void
{
populateProperties(o);
}
/**
* @private
*/
internal function setHostPropsFriend (o :Object) :void
{
setHostProps(o);
}
/** @private */
protected var _parent :AbstractControl;
}
}
@@ -1,143 +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 {
/**
* Contains 'bags' game services. Do not instantiate this class yourself, access it
* via GameControl.services.bags.
*
* Bags are secret collections containing non-unique elements that are stored on the server.
* They can be used to implement game features where clients can't be trusted to not
* sniff their network.
*
* For example you could create a bag called "dice" and fill it with [ 1, 2, 3, 4, 5, 6 ].
* Now you can roll the die with _ctrl.services.bags.pick("dice", 1, "diceProperty");
*/
public class EZBagsSubControl extends AbstractSubControl
{
/**
* @private Constructed via EZGameControl.
*/
public function EZBagsSubControl (parent :AbstractControl)
{
super(parent);
}
/**
* Create a bag containing the specified values,
* clearing any previous bag with the same name.
*/
public function create (bagName :String, values :Array) :void
{
populate(bagName, values, true);
}
/**
* Add values to an existing bag. If it doesn't exist, it will
* be created.
*/
public function addTo (bagName :String, values :Array) :void
{
populate(bagName, values, false);
}
/**
* Merge all values from the specified bag into the other bag.
* The source bag will be destroyed. The elements from
* the source bag will be shuffled and appended to the end
* of the destination bag.
*/
public function merge (srcBag :String, intoBag :String) :void
{
callHostCode("mergeCollection_v1", srcBag, intoBag);
}
/**
* Pick (do not remove) the specified number of elements from a bag,
* and distribute them to a specific player or set them as a property
* in the game data.
*
* @param bagName 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 playerId if 0 (or unset), the picked elements should be
* set on the gameObject as a property for all to see.
* If a playerId is specified, only that player will receive
* the elements as a message.
*/
// TODO: a way to specify exclusive picks vs. duplicate-OK picks?
public function pick (
bagName :String, count :int, msgOrPropName :String,
playerId :int = 0) :void
{
getFrom(bagName, count, msgOrPropName, playerId, false, null);
}
/**
* Deal (remove) the specified number of elements from a bag,
* and distribute them to a specific player or set them as a property
* in the game data.
*
* @param bagName 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 playerId if 0 (or unset), the picked elements should be
* set on the gameObject as a property for all to see.
* If a playerId is specified, only that player will receive
* the elements as a message.
*/
// TODO: figure out the method signature of the callback
public function deal (
bagName :String, count :int, msgOrPropName :String,
callback :Function = null, playerId :int = 0) :void
{
getFrom(bagName, count, msgOrPropName, playerId, true, callback);
}
// == protected methods ==
/**
* Helper method for create and addTo.
* @private
*/
protected function populate (
bagName :String, values :Array, clearExisting :Boolean) :void
{
callHostCode("populateCollection_v1", bagName, values, clearExisting);
}
/**
* Helper method for pick and deal.
* @private
*/
protected function getFrom (
bagName :String, count :int, msgOrPropName :String, playerId :int,
consume :Boolean, callback :Function) :void
{
callHostCode("getFromCollection_v2", bagName, count, msgOrPropName,
playerId, consume, callback);
}
}
}
@@ -1,90 +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 {
import flash.display.DisplayObject;
/**
* The single point of control for each client in your multiplayer EZGame.
*
* <b>If you are creating a game for Whirled, you should use WhirledGameControl.</b>
* @see com.whirled.WhirledGameControl
*
* Usage: Usually, in your top-level movieclip/sprite:
* _ctrl = new EZGameControl(this);
*
*/
public class EZGameControl extends AbstractGameControl
{
/**
* Create an EZGameControl object using some display object currently on the hierarchy.
*
* @param disp the display object that is the game's UI.
* @param autoReady if true, the game will automatically be started when initialization is
* complete, if false, the game will not start until all clients call {@link #playerReady}.
*/
public function EZGameControl (disp :DisplayObject, autoReady :Boolean = true)
{
super(disp, autoReady);
}
/**
* Access the 'local' services.
*/
public function get local () :EZLocalSubControl
{
return _localCtrl;
}
/**
* Access the 'net' services.
*/
public function get net () :EZNetSubControl
{
return _netCtrl;
}
/**
* Access the 'player' services.
*/
public function get player () :EZPlayerSubControl
{
return _playerCtrl;
}
/**
* Access the 'game' services.
*/
public function get game () :EZGameSubControl
{
return _gameCtrl;
}
/**
* Access the 'services' services.
*/
public function get services () :EZServicesSubControl
{
return _servicesCtrl;
}
}
}
@@ -1,354 +0,0 @@
//
// $Id: SeatingControl.as 271 2007-04-07 00:25:58Z dhoover $
//
// 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 {
/**
* Dispatched when the controller changes for the game.
*
* @eventType com.threerings.ezgame.StateChangedEvent.CONTROL_CHANGED
*/
[Event(name="ControlChanged", type="com.threerings.ezgame.StateChangedEvent")]
/**
* Dispatched when the game starts, usually after all players are present.
*
* @eventType com.threerings.ezgame.StateChangedEvent.GAME_STARTED
*/
[Event(name="GameStarted", type="com.threerings.ezgame.StateChangedEvent")]
/**
* Dispatched when a round starts.
*
* @eventType com.threerings.ezgame.StateChangedEvent.ROUND_STARTED
*/
[Event(name="RoundStarted", type="com.threerings.ezgame.StateChangedEvent")]
/**
* Dispatched when the turn changes in a turn-based game.
*
* @eventType com.threerings.ezgame.StateChangedEvent.TURN_CHANGED
*/
[Event(name="TurnChanged", type="com.threerings.ezgame.StateChangedEvent")]
/**
* Dispatched when a round ends.
*
* @eventType com.threerings.ezgame.StateChangedEvent.ROUND_ENDED
*/
[Event(name="RoundEnded", type="com.threerings.ezgame.StateChangedEvent")]
/**
* Dispatched when the game ends.
*
* @eventType com.threerings.ezgame.StateChangedEvent.GAME_ENDED
*/
[Event(name="GameEnded", type="com.threerings.ezgame.StateChangedEvent")]
/**
* Dispatched when an occupant enters the game.
*
* @eventType com.threerings.ezgame.OccupantChangedEvent.OCCUPANT_ENTERED
*/
[Event(name="OccupantEntered", type="com.threerings.ezgame.OccupantChangedEvent")]
/**
* Dispatched when an occupant leaves the game.
*
* @eventType com.threerings.ezgame.OccupantChangedEvent.OCCUPANT_LEFT
*/
[Event(name="OccupantLeft", type="com.threerings.ezgame.OccupantChangedEvent")]
/**
* Dispatched when a user chats.
*
* @eventType com.threerings.ezgame.UserChatEvent.USER_CHAT
*/
[Event(name="UserChat", type="com.threerings.ezgame.UserChatEvent")]
/**
* Access game-specific controls. Do not instantiate this class yourself.
* Access it via GameControl.game.
*/
public class EZGameSubControl extends AbstractSubControl
{
/**
* @private Constructed via EZGameControl.
*/
public function EZGameSubControl (parent :AbstractGameControl)
{
super(parent);
_seatingCtrl = createSeatingControl();
}
/**
* Access the 'seating' subcontrol.
*/
public function get seating () :EZSeatingSubControl
{
// TODO: this should return null for PARTY games
return _seatingCtrl;
}
/**
* Get any game-specific configurations that were set up in the lobby.
*
* @return an Object containing config names mapping to their values.
*/
public function getConfig () :Object
{
return _gameConfig;
}
/**
* Send a system chat message that will be seen by everyone in the game room,
* even observers.
*/
public function systemMessage (msg :String) :void
{
callHostCode("sendChat_v1", msg);
}
/**
* If the game was not configured to auto-start, all clients must call this function to let the
* server know that they are ready, at which point the game will be started. Once a game is
* over, all clients can call this function again to start a new game.
*/
public function playerReady () :void
{
callHostCode("playerReady_v1");
}
/**
* Returns the player ids of all occupants in the game room: players and watchers.
*/
public function getOccupantIds () :Array /* of playerId */
{
return (callHostCode("getOccupants_v1") as Array);
}
/**
* Get the display name of the specified occupant. Two players may have the same name: always
* use playerId to purposes of identification and comparison. The name is for display
* only. Will be null is the specified playerId is not present.
*/
public function getOccupantName (playerId :int) :String
{
return String(callHostCode("getOccupantName_v1", playerId));
}
/**
* Returns this client's player id.
*/
public function getMyId () :int
{
return int(callHostCode("getMyId_v1"));
}
/**
* Returns true if we are in control of this game. False if another client is in control.
*/
public function amInControl () :Boolean
{
return getControllerId() == getMyId();
}
/**
* Returns the player id of the client that is in control of this game.
*/
public function getControllerId () :int
{
return int(callHostCode("getControllerId_v1"));
}
/**
* Returns the player id of the current turn holder, or 0 if it's nobody's turn.
*/
public function getTurnHolderId () :int
{
return int(callHostCode("getTurnHolder_v1"));
}
/**
* Returns the current round number. Rounds start at 1 and increase if the game calls {@link
* #endRound} with a next round timeout. Between rounds, it returns a negative number,
* corresponding to the negation of the round that just ended.
*/
public function getRound () :int
{
return int(callHostCode("getRound_v1"));
}
/**
* A convenience method to just check if it's our turn.
*/
public function isMyTurn () :Boolean
{
return Boolean(callHostCode("isMyTurn_v1"));
}
/**
* Is the game currently in play?
*/
public function isInPlay () :Boolean
{
return Boolean(callHostCode("isInPlay_v1"));
}
/**
* Start the next player's turn. If a playerId is specified, that player's turn will be
* next. Otherwise the turn will be assigned randomly the first time, after that following
* the "natural" turn order. In a seated game, the natural order follows the seating order.
* In a party game, the natural order is to give the turn to the player that has been
* around the longest without getting a turn.
*/
public function startNextTurn (nextPlayerId :int = 0) :void
{
callHostCode("startNextTurn_v1", nextPlayerId);
}
/**
* Ends the current round. If nextRoundDelay is greater than zero, the next round will be
* started in the specified number of seconds, otherwise no next round will be started. This
* method should not be called at the end of the last round, instead <code>endGame()</code>
* should be called.
*/
public function endRound (nextRoundDelay :int = 0) :void
{
callHostCode("endRound_v1", nextRoundDelay);
}
/**
* End the game. The specified player ids are winners!
*/
public function endGame (winnerIds :Array) :void
{
callHostCode("endGame_v2", winnerIds);
}
/**
* Requests to start the game again in the specified number of seconds. This should only be
* used for party games. Seated table games should have each player report that they are ready
* again and the game will automatically start.
*/
public function restartGameIn (seconds :int) :void
{
callHostCode("restartGameIn_v1", seconds);
}
/**
* Create the 'seating' subcontrol.
* @private
*/
protected function createSeatingControl () :EZSeatingSubControl
{
return new EZSeatingSubControl(_parent, this);
}
/**
* @private
*/
override protected function populateProperties (o :Object) :void
{
super.populateProperties(o);
o["controlDidChange_v1"] = controlDidChange_v1;
o["turnDidChange_v1"] = turnDidChange_v1;
o["gameStateChanged_v1"] = gameStateChanged_v1;
o["roundStateChanged_v1"] = roundStateChanged_v1;
o["occupantChanged_v1"] = occupantChanged_v1;
o["userChat_v1"] = userChat_v1;
_seatingCtrl.populatePropertiesFriend(o);
}
/**
* @private
*/
override protected function setHostProps (o :Object) :void
{
super.setHostProps(o);
_gameConfig = o.gameConfig;
_seatingCtrl.setHostPropsFriend(o);
}
/**
* Private method to post a StateChangedEvent.
*/
private function controlDidChange_v1 () :void
{
dispatch(new StateChangedEvent(StateChangedEvent.CONTROL_CHANGED));
}
/**
* Private method to post a StateChangedEvent.
*/
private function turnDidChange_v1 () :void
{
dispatch(new StateChangedEvent(StateChangedEvent.TURN_CHANGED));
}
/**
* Private method to post a StateChangedEvent.
*/
private function gameStateChanged_v1 (started :Boolean) :void
{
dispatch(new StateChangedEvent(started ? StateChangedEvent.GAME_STARTED
: StateChangedEvent.GAME_ENDED));
}
/**
* Private method to post a StateChangedEvent.
*/
private function roundStateChanged_v1 (started :Boolean) :void
{
dispatch(new StateChangedEvent(started ? StateChangedEvent.ROUND_STARTED
: StateChangedEvent.ROUND_ENDED));
}
/**
* Private method to post a OccupantEvent.
*/
private function occupantChanged_v1 (occupantId :int, player :Boolean, enter :Boolean) :void
{
dispatch(new OccupantChangedEvent(
enter ? OccupantChangedEvent.OCCUPANT_ENTERED
: OccupantChangedEvent.OCCUPANT_LEFT, occupantId, player));
}
/**
* Private method to post a UserChatEvent.
*/
private function userChat_v1 (speaker :int, message :String) :void
{
dispatch(new UserChatEvent(speaker, message));
}
/** Contains any custom game configuration data. @private */
protected var _gameConfig :Object = {};
/** The seating sub-control. @private */
protected var _seatingCtrl :EZSeatingSubControl;
}
}
@@ -1,148 +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 {
import flash.events.KeyboardEvent;
import flash.geom.Point;
/**
* Dispatched when a key is pressed when the game has focus.
*
* @eventType flash.events.KeyboardEvent.KEY_DOWN
*/
[Event(name="keyDown", type="flash.events.KeyboardEvent")]
/**
* Dispatched when a key is released when the game has focus.
*
* @eventType flash.events.KeyboardEvent.KEY_UP
*/
[Event(name="keyUp", type="flash.events.KeyboardEvent")]
/**
* Dispatched when the size of the game area changes.
*
* @eventType com.threerings.ezgame.SizeChangedEvent.SIZE_CHANGED
*/
[Event(name="SizeChanged", type="com.threerings.ezgame.SizeChangedEvent")]
/**
* Access local properties of the game. Do not instantiate this class yourself,
* access it via GameControl.local.
*/
public class EZLocalSubControl extends AbstractSubControl
{
/**
* @private Constructed via EZGameControl.
*/
public function EZLocalSubControl (parent :AbstractGameControl)
{
super(parent);
}
/**
* @inheritDoc
*/
override public function addEventListener (
type :String, listener :Function, useCapture :Boolean = false,
priority :int = 0, useWeakReference :Boolean = false) :void
{
super.addEventListener(type, listener, useCapture, priority, useWeakReference);
switch (type) {
case KeyboardEvent.KEY_UP:
case KeyboardEvent.KEY_DOWN:
if (hasEventListener(type)) { // ensure it was added
callHostCode("alterKeyEvents_v1", type, true);
}
break;
}
}
/**
* @inheritDoc
*/
override public function removeEventListener (
type :String, listener :Function, useCapture :Boolean = false) :void
{
super.removeEventListener(type, listener, useCapture);
switch (type) {
case KeyboardEvent.KEY_UP:
case KeyboardEvent.KEY_DOWN:
if (!hasEventListener(type)) { // once it's no longer needed
callHostCode("alterKeyEvents_v1", type, false);
}
break;
}
}
/**
* Get the size of the game area, expressed as a Point
* (x = width, y = height).
*/
public function getSize () :Point
{
return callHostCode("getSize_v1") as Point;
}
/**
* Display a feedback chat message for the local player only, no other players
* or observers will see it.
*/
public function feedback (msg :String) :void
{
callHostCode("localChat_v1", msg);
}
/**
* Run the specified text through the user's chat filter. This is optional, you can use
* it to clean up user-entered text.
*
* @return the filtered text, or null if it was so bad it's gone.
*/
public function filter (text :String) :String
{
return (callHostCode("filter_v1", text) as String);
}
/**
* @private
*/
override protected function populateProperties (o :Object) :void
{
super.populateProperties(o);
o["dispatchEvent_v1"] = dispatch; // for re-dispatching keyboard events
o["sizeChanged_v1"] = sizeChanged_v1;
}
/**
* Private method to generate a SizeChangedEvent.
*/
private function sizeChanged_v1 (size :Point) :void
{
dispatch(new SizeChangedEvent(size));
}
}
}
@@ -1,184 +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 {
/**
* Dispatched when a property has changed in the shared game state.
*
* @eventType com.threerings.ezgame.PropertyChangedEvent.PROPERTY_CHANGED
*/
[Event(name="PropChanged", type="com.threerings.ezgame.PropertyChangedEvent")]
/**
* Dispatched when a message arrives with information that is not part of the shared game state.
*
* @eventType com.threerings.ezgame.MessageReceivedEvent.MESSAGE_RECEIVED
*/
[Event(name="MsgReceived", type="com.threerings.ezgame.MessageReceivedEvent")]
/**
* Provides access to 'net' game services. Do not instantiate this class yourself,
* access it via GameControl.net.
*
* The 'net' subcontrol is used to communicate shared state between game clients.
*/
public class EZNetSubControl extends AbstractSubControl
{
/**
* @private Constructed via EZGameControl.
*/
public function EZNetSubControl (parent :AbstractGameControl)
{
super(parent);
}
/**
* Get a property value.
*/
public function get (propName :String, index :int = -1) :Object
{
checkIsConnected();
var value :Object = _gameData[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;
}
/**
* Set a property that will be distributed.
*/
public function set (propName :String, value :Object, index :int = -1) :void
{
callHostCode("setProperty_v1", propName, value, index, false);
}
/**
* Set a property, but have this client immediately set the value so that it can be
* re-read. The property change event will still arrive and will be your clue as to when the
* other clients will see the newly set value. Be careful with this method, as it can allow
* data inconsistency: two clients may see different values for a property if one of them
* recently set it immediately, and the resultant PropertyChangedEvent's oldValue also may not
* be consistent.
*/
public function setImmediate (propName :String, value :Object, index :int = -1) :void
{
callHostCode("setProperty_v1", propName, value, index, true);
}
/**
* Set a property that will be distributed, but only if it's equal to the specified test value.
*
* <p> Please note that, unlike in the setImmediate() function, the property will not be
* updated right away, but will require a request to the server and a response back. For this
* reason, there may be a considerable delay between calling testAndSet, and seeing the result
* of the update.
*
* <p> The operation is 'atomic', in the sense that testing and setting take place during the
* same server event. In comparison, a separate 'get' followed by a 'set' operation would
* first read the current value as seen on your client and then send a request to overwrite
* any value with a new value. By the time the 'set' reaches the server the old value
* may no longer be valid. Since that's sketchy, we have this method.
*/
public function testAndSet (
propName :String, newValue :Object, testValue :Object, index :int = -1) :void
{
callHostCode("testAndSetProperty_v1", propName, newValue, testValue, index);
}
/**
* Get the names of all currently-set properties that begin with the specified prefix.
*/
public function getPropertyNames (prefix :String = "") :Array
{
var props :Array = [];
for (var s :String in _gameData) {
if (s.lastIndexOf(prefix, 0) == 0) {
props.push(s);
}
}
return props;
}
/**
* 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 messageName The message to send.
* @param value The value to attach to the message.
* @param playerId if 0 (or unset), sends to all players, otherwise the message will be private
* to just one player
*/
public function sendMessage (messageName :String, value :Object, playerId :int = 0) :void
{
callHostCode("sendMessage_v2", messageName, value, playerId);
}
/**
* @private
*/
override protected function populateProperties (o :Object) :void
{
super.populateProperties(o);
o["propertyWasSet_v1"] = propertyWasSet_v1;
o["messageReceived_v1"] = messageReceived_v1;
}
/**
* @private
*/
override protected function setHostProps (o :Object) :void
{
super.setHostProps(o);
_gameData = o.gameData;
}
/**
* Private method to post a PropertyChangedEvent.
*/
private function propertyWasSet_v1 (
name :String, newValue :Object, oldValue :Object, index :int) :void
{
dispatch(new PropertyChangedEvent(name, newValue, oldValue, index));
}
/**
* Private method to post a MessageReceivedEvent.
*/
private function messageReceived_v1 (name :String, value :Object) :void
{
dispatch(new MessageReceivedEvent(name, value));
}
/** Game properties. @private */
protected var _gameData :Object;
}
}
@@ -1,63 +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 {
/**
* Provides access to 'player' game services. Do not instantiate this class directly,
* instead access it via GameControl.player.
*/
public class EZPlayerSubControl extends AbstractSubControl
{
/**
* @private Constructed via EZGameControl
*/
public function EZPlayerSubControl (parent :AbstractGameControl)
{
super(parent);
}
/**
* 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.
*/
public function getUserCookie (occupantId :int, callback :Function) :void
{
callHostCode("getUserCookie_v2", occupantId, callback);
}
/**
* 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 playerId 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.
*/
public function setUserCookie (cookie :Object) :Boolean
{
return Boolean(callHostCode("setUserCookie_v1", cookie));
}
}
}
@@ -1,83 +0,0 @@
//
// $Id: SeatingControl.as 271 2007-04-07 00:25:58Z dhoover $
//
// 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 {
/**
* Access seating information for a seated game. Do not instantiate this class directly,
* access it via GameControl.game.seating.
*/
// TODO: methods for allowing a player to pick a seat in SEATED_CONTINUOUS games.
public class EZSeatingSubControl extends AbstractSubControl
{
/**
* @private Constructed via EZGameControl.
*/
public function EZSeatingSubControl (parent :AbstractControl, game :EZGameSubControl)
{
super(parent);
_game = game;
}
/**
* Get the player's position (seated index), or -1 if not a player.
*/
public function getPlayerPosition (playerId :int) :int
{
return int(callHostCode("getPlayerPosition_v1", playerId));
}
/**
* A convenient function to get our own player position,
* or -1 if we're not a player.
*/
public function getMyPosition () :int
{
return int(callHostCode("getMyPosition_v1"));
}
/**
* Get all the players at the table, in their seated position.
* Absent players will be represented by a 0.
*/
public function getPlayerIds () :Array /* of playerId (int) */
{
return (callHostCode("getPlayers_v1") as Array);
}
/**
* Get the names of the seated players, in the order of their seated position.
*/
public function getPlayerNames () :Array /* of String */
{
return getPlayerIds().map(
function (playerId :int, o2:*, o3:*) :String
{
return _game.getOccupantName(playerId);
}
);
}
/** Our direct parent. @private */
protected var _game :EZGameSubControl;
}
}
@@ -1,136 +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 {
/**
* Provides access to 'services' game services. Do not instantiate this class yourself,
* access it via GameControl.services.
*/
public class EZServicesSubControl extends AbstractSubControl
{
/**
* @private Constructed via EZGameControl.
*/
public function EZServicesSubControl (parent :AbstractGameControl)
{
super(parent);
_bagsCtrl = createBagsControl();
}
/**
* Access the 'bags' subcontrol.
*/
public function get bags () :EZBagsSubControl
{
return _bagsCtrl;
}
/**
* Requests a set of random letters from the dictionary service. The letters will arrive in a
* separate message with the specified key, as an array of strings.
*
* @param locale RFC 3066 string that represents language settings
* @param dictionary the dictionary to use, or null for the default.
* TODO: document possible parameters.
* @param count the number of letters to be produced
* @param callback the function that will process the results, of the form:
* <pre>function (letters :Array) :void</pre>
* where letters is an array of strings containing letters for the given language settings
* (potentially empty).
*/
public function getDictionaryLetterSet (
locale :String, dictionary :String, count :int, callback :Function) :void
{
callHostCode("getDictionaryLetterSet_v2", locale, dictionary, count, callback);
}
/**
* Checks to see if the dictionary for the given locale contains the given word.
*
* @param locale RFC 3066 string that represents language settings
* @param dictionary the dictionary to use, or null for the default.
* TODO: document possible parameters.
* @param word the string contains the word to be checked
* @param callback the function that will process the results, of the form:
* <pre>function (word :String, result :Boolean) :void</pre>
* where word is a copy of the word that was requested, and result specifies whether the word
* is valid given language settings
*/
public function checkDictionaryWord (
locale :String, dictionary :String, word :String, callback :Function) :void
{
callHostCode("checkDictionaryWord_v2", locale, dictionary, word, callback);
}
/**
* Start the ticker with the specified name. The ticker will deliver messages
* (resulting in a MessageReceivedEvent being dispatched on the 'net' control)
* to all connected clients, at the specified delay. The value of each message is
* a single integer, starting with 0 and increasing by 1 with each messsage.
*/
public function startTicker (tickerName :String, msOfDelay :int) :void
{
callHostCode("setTicker_v1", tickerName, msOfDelay);
}
/**
* Stop the specified ticker.
*/
public function stopTicker (tickerName :String) :void
{
startTicker(tickerName, 0);
}
/**
* Create the 'bags' subcontrol.
* @private
*/
protected function createBagsControl () :EZBagsSubControl
{
return new EZBagsSubControl(_parent);
}
/**
* @private
*/
override protected function populateProperties (o :Object) :void
{
super.populateProperties(o);
_bagsCtrl.populatePropertiesFriend(o);
}
/**
* @private
*/
override protected function setHostProps (o :Object) :void
{
super.setHostProps(o);
_bagsCtrl.setHostPropsFriend(o);
}
/** The bags sub-control. @private */
protected var _bagsCtrl :EZBagsSubControl;
}
}
@@ -1,77 +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 {
import flash.events.Event;
/**
* Dispatched on the 'net' subcontrol when a message is sent by any client.
*/
public class MessageReceivedEvent extends Event
{
/**
* The type of all MessageReceivedEvents.
*
* @eventType MsgReceived
*/
public static const MESSAGE_RECEIVED :String = "MsgReceived";
/**
* Access the message name.
*/
public function get name () :String
{
return _name;
}
/**
* Access the message value.
*/
public function get value () :Object
{
return _value;
}
public function MessageReceivedEvent (messageName :String, value :Object)
{
super(MESSAGE_RECEIVED);
_name = messageName;
_value = value;
}
override public function toString () :String
{
return "[MessageReceivedEvent name=" + _name + ", value=" + _value + "]";
}
override public function clone () :Event
{
return new MessageReceivedEvent(_name, _value);
}
/** @private */
protected var _name :String;
/** @private */
protected var _value :Object;
}
}
@@ -1,81 +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 {
import flash.events.Event;
/**
* Dispatched when an occupant enters or leaves.
*
* If a watcher becomes a player, you may get an OCCUPANT_LEFT event where player == false,
* followed immediately by an OCCUPANT_ENTERED event where player == true.
*/
public class OccupantChangedEvent extends Event
{
/**
* @eventType OccupantEntered
*/
public static const OCCUPANT_ENTERED :String = "OccupantEntered";
/**
* @eventType OccupantLeft
*/
public static const OCCUPANT_LEFT :String = "OccupantLeft";
/** The occupantId of the occupant that entered or left. */
public function get occupantId () :int
{
return _occupantId;
}
/** Is/was the occupant a player? If false, they are/were a watcher. */
public function get player () :Boolean
{
return _player;
}
public function OccupantChangedEvent (type :String, occupantId :int, player :Boolean)
{
super(type);
_occupantId = occupantId;
_player = player;
}
override public function toString () :String
{
return "[OccupantChangedEvent type=" + type +
", occupantId=" + _occupantId +
", player=" + _player + "]";
}
override public function clone () :Event
{
return new OccupantChangedEvent(type, _occupantId, _player);
}
/** @private */
protected var _occupantId :int;
/** @private */
protected var _player :Boolean;
}
}
@@ -1,211 +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 {
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.text.StyleSheet;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
/**
* A sample component that displays the players of a game. If the game has a turn holder, the
* current turn holder will be highlighted.
*
* This class demonstrates that the 'Game' interface may be implemented by any DisplayObject that
* want access to the GameObject, not just the actual DisplayObject that is displaying the
* game. Here, all we are interested in is the names of the players and the current turn holder.
*
* You may use this, with any modifications you desire, in your game. Feel free to copy/modify or
* extend this class.
*
* @private
*/
public class PlayersDisplay extends Sprite
{
/**
* Set the game control that will be used with this display.
*/
public function setGameControl (gameCtrl :EZGameControl) :void
{
_gameCtrl = gameCtrl;
_gameCtrl.game.addEventListener(StateChangedEvent.GAME_STARTED, stateChanged);
_gameCtrl.game.addEventListener(StateChangedEvent.GAME_ENDED, stateChanged);
_gameCtrl.game.addEventListener(StateChangedEvent.TURN_CHANGED, stateChanged);
configureInterface();
}
// from StateChangedListener
public function stateChanged (event :StateChangedEvent) :void
{
displayCurrentTurn();
}
/**
* Set up the player labels and configure the look of the entire UI.
*/
protected function configureInterface () :void
{
var border :int = getBorderSpacing();
var pad :int = getInternalSpacing();
var y :Number = border;
var maxWidth :Number = 0;
var label :TextField;
var icon :DisplayObject;
// create a label at the top, above the player names
label = createHeader();
if (label != null) {
label.x = border;
label.y = y;
addChild(label);
y += label.textHeight + pad;
maxWidth = label.textWidth + TEXTWIDTH_ADD;
}
if (!_gameCtrl.isConnected()) {
return; // nothing to do
}
var players :Array = _gameCtrl.game.seating.getPlayerIds();
// create a label for each player
for each (var playerId :int in players) {
var name :String = _gameCtrl.game.getOccupantName(playerId);
label = createPlayerLabel(playerId, name);
icon = createPlayerIcon(playerId, name);
var iconW :int = 0;
var iconH :int = 0;
if (icon != null) {
iconW = icon.width + pad;
iconH = icon.height;
icon.x = border;
icon.y = y;
addChild(icon);
}
label.x = border + iconW;
label.y = y;
addChild(label);
y += Math.max(label.textHeight, iconH) + pad;
maxWidth = Math.max(maxWidth, iconW + label.textWidth + TEXTWIDTH_ADD);
_playerLabels.push(label);
}
// make all the player labels the same width (looks nice when highlighted)
for each (label in _playerLabels) {
label.autoSize = TextFieldAutoSize.NONE;
label.width = maxWidth - (label.x - border);
}
// y has a pad at the end, we want border instead
y += border - pad;
drawBorder(maxWidth);
displayCurrentTurn();
}
protected function createHeader () :TextField
{
var label :TextField = new TextField();
// damn stylesheet doesn't seem to actually -work-
// var style :StyleSheet = new StyleSheet();
// style.fontWeight = "bold";
// style.color = "#0000FF";
// style.fontFamily = "serif";
// style.fontSize = 18;
// label.styleSheet = style;
label.autoSize = TextFieldAutoSize.LEFT;
label.selectable = false;
label.text = "Players";
return label;
}
/**
* Create a TextArea that will be used to display player names.
*/
protected function createPlayerLabel (playerId :int, name :String) :TextField
{
var label :TextField = new TextField();
label.autoSize = TextFieldAutoSize.LEFT;
label.background = true;
label.selectable = false;
label.text = name;
return label;
}
protected function createPlayerIcon (playerId :int, name :String) :DisplayObject
{
return null;
}
protected function drawBorder (maxWidth :int) :void
{
// draw a blue rectangle around everything
graphics.clear();
graphics.lineStyle(1, 0x0000FF);
graphics.drawRect(0, 0, maxWidth + (getBorderSpacing() * 2), y);
}
protected function getBackground (isTurn :Boolean) :uint
{
return isTurn ? 0xFF9999 : 0xFFFFFF;
}
protected function getBorderSpacing () :int
{
return 6;
}
protected function getInternalSpacing () :int
{
return 2;
}
/**
* Re-set the background color for every player label, highlighting only the player who has the
* turn.
*/
protected function displayCurrentTurn () :void
{
var idx :int = _gameCtrl.game.isInPlay() ?
_gameCtrl.game.seating.getPlayerPosition(_gameCtrl.game.getTurnHolderId()) : -1;
for (var ii :int = 0; ii < _playerLabels.length; ii++) {
var label :TextField = (_playerLabels[ii] as TextField);
label.backgroundColor = getBackground(ii == idx);
}
}
/** Our game Control. */
protected var _gameCtrl :EZGameControl;
/** An array of labels, one for each player name. */
protected var _playerLabels :Array = [];
/** These are fucking ridiculous. */
protected static const TEXTWIDTH_ADD :int = 5;
protected static const TEXTHEIGHT_ADD :int = 4;
}
}
@@ -1,109 +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 {
import flash.events.Event;
/**
* Property change events are dispatched after the property change was
* validated on the server.
*/
public class PropertyChangedEvent extends Event
{
/**
* The type of a property change event.
*
* @eventType PropChanged
*/
public static const PROPERTY_CHANGED :String = "PropChanged";
/**
* Get the name of the property that changed.
*/
public function get name () :String
{
return _name;
}
/**
* Get the property's new value.
* Note: if index is not -1 then this value is merely one element in an array that
* may be fully accessed using the 'net' subcontrol.
*/
public function get newValue () :Object
{
return _newValue;
}
/**
* Get the property's previous value (handy!).
*/
public function get oldValue () :Object
{
return _oldValue;
}
/**
* If an array element was updated, get the index, or -1 if not applicable.
*/
public function get index () :int
{
return _index;
}
/**
* Constructor.
*/
public function PropertyChangedEvent (
propName :String, newValue :Object, oldValue :Object, index :int = -1)
{
super(PROPERTY_CHANGED);
_name = propName;
_newValue = newValue;
_oldValue = oldValue;
_index = index;
}
override public function toString () :String
{
return "[PropertyChangedEvent name=" + _name + ", value=" + _newValue +
((_index < 0) ? "" : (", index=" + _index)) + "]";
}
override public function clone () :Event
{
return new PropertyChangedEvent(_name, _newValue, _oldValue, _index);
}
/** @private */
protected var _name :String;
/** @private */
protected var _newValue :Object;
/** @private */
protected var _oldValue :Object;
/** @private */
protected var _index :int;
}
}
@@ -1,72 +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 {
import flash.events.Event;
import flash.geom.Point;
/**
* Dispatched when the size of the game area changes, for example as a result of the user
* resizing their browser window.
*/
public class SizeChangedEvent extends Event
{
/**
* The type of this event.
*
* @eventType SizeChanged
*/
public static const SIZE_CHANGED :String = "SizeChanged";
/**
* Get the size of the game area, expressed as a Point
* (The width is the x value, the height is the y value).
*/
public function get size () :Point
{
return _size;
}
/**
* Constructor.
*/
public function SizeChangedEvent (size :Point)
{
super(SIZE_CHANGED);
_size = size;
}
override public function toString () :String
{
return "[SizeChangedEvent size=" + _size + "]";
}
override public function clone () :Event
{
return new SizeChangedEvent(_size.clone()); // since _size is mutable
}
/** Our implementation details. @private */
protected var _size: Point;
}
}
@@ -1,83 +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 {
import flash.events.Event;
/**
* Dispatched when the state of the game has changed.
*/
public class StateChangedEvent extends Event
{
/**
* Indicates that the game has transitioned to a started state.
* @eventType GameStarted
*/
public static const GAME_STARTED :String = "GameStarted";
/**
* Indicates that the game has transitioned to a ended state.
* @eventType GameEnded
*/
public static const GAME_ENDED :String = "GameEnded";
/**
* Indicates that a round has started. Games that do not require multiple rounds can ignore
* this event.
* @eventType RoundStarted
*/
public static const ROUND_STARTED :String = "RoundStarted";
/**
* Indicates that the current round has ended.
* @eventType RoundEnded
*/
public static const ROUND_ENDED :String = "RoundEnded";
/**
* Indicates that a new controller has been assigned.
* @eventType ControlChanged
*/
public static const CONTROL_CHANGED :String = "ControlChanged";
/** Indicates that the turn has changed.
* @eventType TurnChanged
*/
// TODO: move to own event?
public static const TURN_CHANGED :String = "TurnChanged";
public function StateChangedEvent (type :String)
{
super(type);
}
override public function toString () :String
{
return "[StateChangedEvent type=" + type + "]";
}
override public function clone () :Event
{
return new StateChangedEvent(type);
}
}
}
@@ -1,76 +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 {
import flash.events.Event;
/**
* Dispatched when a player speaks.
*/
public class UserChatEvent extends Event
{
/**
* The type of a property change event.
* @eventType UserChat
*/
public static const USER_CHAT :String = "UserChat";
/**
* Get the name of the user who spoke.
*/
public function get speaker () :int
{
return _speaker;
}
/**
* Get the content of the chat.
*/
public function get message () :Object
{
return _message;
}
public function UserChatEvent (speaker :int, message :String)
{
super(USER_CHAT);
_speaker = speaker;
_message = message;
}
override public function toString () :String
{
return "[UserChatEvent speaker=" + _speaker + ", message=" + _message + "]";
}
override public function clone () :Event
{
return new UserChatEvent(_speaker, _message);
}
/** @private */
protected var _speaker: int;
/** @private */
protected var _message :String;
}
}
@@ -1,985 +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 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 EZGameBackend
implements MessageListener, SetListener, ElementUpdateListener, PropertySetListener, ChatDisplay
{
public var log :Log = Log.getLog(this);
public function EZGameBackend (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) {
// we want to decode every time, in case usercode mangles the value
var decodedValue :Object = ObjectMarshaller.decode(cookie.cookie);
try {
fn(decodedValue);
} catch (err :Error) {
log.warning("Error in user-code: " + err);
log.logStackTrace(err);
}
}
}
}
}
/**
* 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 (if called before the
* game ever starts) or rematched (if called after the game has ended).
*/
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;
}
}
@@ -1,189 +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 mx.core.UIComponent;
import mx.controls.CheckBox;
import mx.controls.ComboBox;
import mx.controls.HSlider;
import mx.controls.Label;
import com.threerings.util.Integer;
import com.threerings.util.Log;
import com.threerings.util.StreamableHashMap;
import com.threerings.util.StringUtil;
import com.threerings.util.langBoolean;
import com.threerings.flex.LabeledSlider;
import com.threerings.parlor.game.client.FlexGameConfigurator;
import com.threerings.ezgame.data.ChoiceParameter;
import com.threerings.ezgame.data.EZGameConfig;
import com.threerings.ezgame.data.Parameter;
import com.threerings.ezgame.data.RangeParameter;
import com.threerings.ezgame.data.ToggleParameter;
/**
* Adds custom configuration of options specified in XML.
*/
public class EZGameConfigurator extends FlexGameConfigurator
{
public function EZGameConfigurator (ratedParam :ToggleParameter = null)
{
_ratedParam = ratedParam;
}
// from GameConfigurator
override protected function gotGameConfig () :void
{
super.gotGameConfig();
// add an interface for checking ratedness
if (_ratedParam != null) {
_ratedCheck = new CheckBox();
_ratedCheck.selected = _ratedParam.start;
addLabeledControl(_ratedParam, _ratedCheck);
}
var params :Array = (_config as EZGameConfig).getGameDefinition().params;
if (params == null) {
return;
}
for each (var param :Parameter in params) {
if (param is RangeParameter) {
var range :RangeParameter = (param as RangeParameter);
if ((range.maximum - range.minimum) < 16) {
var rcombo :ComboBox = new ComboBox();
var values :Array = [];
var rstartDex :int = 0;
for (var ii :int = range.minimum; ii <= range.maximum; ii++) {
if (ii == range.start) {
rstartDex = ii;
}
values.push(ii);
}
rcombo.dataProvider = values;
rcombo.selectedIndex = rstartDex;
addLabeledControl(param, rcombo);
} else {
var slider :HSlider = new HSlider();
slider.minimum = range.minimum;
slider.maximum = range.maximum;
slider.value = range.start;
slider.liveDragging = true;
slider.snapInterval = 1;
addLabeledControl(param, new LabeledSlider(slider));
}
} else if (param is ChoiceParameter) {
var choice :ChoiceParameter = (param as ChoiceParameter);
var startDex :int = choice.choices.indexOf(choice.start);
if (startDex == -1) {
Log.getLog(this).warning(
"Start value does not appear in list of choices [param=" + choice + "].");
} else {
var combo :ComboBox = new ComboBox();
combo.dataProvider = choice.choices;
combo.selectedIndex = startDex;
addLabeledControl(param, combo);
}
} else if (param is ToggleParameter) {
var check :CheckBox = new CheckBox();
check.selected = (param as ToggleParameter).start;
addLabeledControl(param, check);
} else {
Log.getLog(this).warning("Unknown parameter in config [param=" + param + "].");
}
}
}
override protected function flushGameConfig () :void
{
super.flushGameConfig();
// flush ratedness
if (_ratedCheck != null) {
_config.rated = _ratedCheck.selected;
}
// if there were any custom XML configs, flush those as well.
if (_customConfigs.length > 0) {
var params :StreamableHashMap = new StreamableHashMap();
for (var ii :int = 0; ii < _customConfigs.length; ii += 2) {
var ident :String = String(_customConfigs[ii]);
var control :UIComponent = (_customConfigs[ii + 1] as UIComponent);
if (control is LabeledSlider) {
// this is wrapped in our own Integer class so that it can play in a friendly
// way with Java that deserializes this StreamableHashMap
params.put(ident, new Integer((control as LabeledSlider).slider.value));
} else if (control is CheckBox) {
// ditto above
params.put(ident, new langBoolean((control as CheckBox).selected));
} else if (control is ComboBox) {
params.put(ident, (control as ComboBox).value);
} else {
Log.getLog(this).warning("Unknow custom config type " + control);
}
}
(_config as EZGameConfig).params = params;
}
}
/**
* Add a control that came from parsing our custom option XML.
*/
protected function addLabeledControl (param :Parameter, control :UIComponent) :void
{
if (StringUtil.isBlank(param.name)) {
param.name = param.ident;
}
var lbl :Label = new Label();
lbl.text = param.name;
lbl.styleName = "lobbyLabel";
lbl.toolTip = param.tip;
control.toolTip = param.tip;
addControl(lbl, control);
_customConfigs.push(param.ident, control);
}
/** The parameter to use for whether the game is rated, or null. */
protected var _ratedParam :ToggleParameter;
/** A toggle indicating whether the game should be rated. */
protected var _ratedCheck :CheckBox;
/** Contains pairs of identString, control, identString, control.. */
protected var _customConfigs :Array = [];
}
}
@@ -1,167 +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 flash.events.Event;
import com.threerings.util.Name;
import com.threerings.presents.dobj.AttributeChangedEvent;
import com.threerings.crowd.client.PlaceView;
import com.threerings.crowd.data.BodyObject;
import com.threerings.crowd.data.PlaceConfig;
import com.threerings.crowd.data.PlaceObject;
import com.threerings.crowd.util.CrowdContext;
import com.threerings.parlor.game.client.GameController;
import com.threerings.parlor.game.data.GameConfig;
import com.threerings.parlor.game.data.GameObject;
import com.threerings.parlor.turn.client.TurnGameController;
import com.threerings.parlor.turn.client.TurnGameControllerDelegate;
import com.threerings.ezgame.data.EZGameObject;
/**
* A controller for flash games.
*/
public class EZGameController extends GameController
implements TurnGameController
{
public function EZGameController ()
{
addDelegate(_turnDelegate = new TurnGameControllerDelegate(this));
}
/**
* This is called by the EZGameBackend once it has initialized and made contact with usercode.
*/
public function userCodeIsConnected (autoReady :Boolean) :void
{
// if we're not a player, we don't need to report anything to the server
var bobj :BodyObject = (_ctx.getClient().getClientObject() as BodyObject);
if (_gconfig.getMatchType() != GameConfig.PARTY &&
_gobj.getPlayerIndex(bobj.getVisibleName()) == -1) {
return;
}
if (autoReady) {
// let the game manager know that we're here and we want to start the game now
playerIsReady();
} else {
// let the game manager know that we're here even though we don't want the game to
// start yet
_gobj.manager.invoke("playerInRoom");
}
}
/**
* Called by the EZGameBackend when the game is ready to start. If the game has ended, this can
* be called by all clients to start the game anew.
*/
public function playerIsReady () :void
{
playerReady();
}
// from PlaceController
override public function willEnterPlace (plobj :PlaceObject) :void
{
_ezObj = (plobj as EZGameObject);
super.willEnterPlace(plobj);
}
// from PlaceController
override public function didLeavePlace (plobj :PlaceObject) :void
{
super.didLeavePlace(plobj);
_ezObj = null;
}
// from TurnGameController
public function turnDidChange (turnHolder :Name) :void
{
_panel.backend.turnDidChange();
}
// from GameController
override protected function shouldAutoPlayerReady (bobj :BodyObject) :Boolean
{
// we don't want to auto-player ready in willEnterPlace(), we'll do it ourselves after the
// client code has connected
return false;
}
// from GameController
override public function attributeChanged (event :AttributeChangedEvent) :void
{
var name :String = event.getName();
if (EZGameObject.CONTROLLER_OID == name) {
_panel.backend.controlDidChange();
} else if (GameObject.ROUND_ID == name) {
if ((event.getValue() as int) > 0) {
_panel.backend.roundStateChanged(true);
} else {
_panel.backend.roundStateChanged(false);
}
} else {
super.attributeChanged(event);
}
}
// from GameController
override protected function gameDidStart () :void
{
super.gameDidStart();
_panel.backend.gameStateChanged(true);
}
// from GameController
override protected function gameDidEnd () :void
{
super.gameDidEnd();
_panel.backend.gameStateChanged(false);
}
// from PlaceController
override protected function createPlaceView (ctx :CrowdContext) :PlaceView
{
return new EZGamePanel(ctx, this);
}
// from PlaceController
override protected function didInit () :void
{
super.didInit();
// we can't just assign _panel in createPlaceView() for some exciting reason
_panel = (_view as EZGamePanel);
}
protected var _ezObj :EZGameObject;
protected var _turnDelegate :TurnGameControllerDelegate;
protected var _panel :EZGamePanel;
}
}
@@ -1,111 +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 flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.Loader;
import flash.events.Event;
import flash.utils.Dictionary;
import mx.containers.Canvas;
import mx.core.Container;
import mx.core.IChildList;
import com.threerings.flash.MediaContainer;
import com.threerings.crowd.client.PlaceView;
import com.threerings.crowd.data.PlaceObject;
import com.threerings.crowd.util.CrowdContext;
import com.threerings.ezgame.data.EZGameConfig;
import com.threerings.ezgame.data.EZGameObject;
public class EZGamePanel extends Canvas
implements PlaceView
{
/** The game object backend. */
public var backend :EZGameBackend;
public function EZGamePanel (ctx :CrowdContext, ctrl :EZGameController)
{
_ctx = ctx;
_ctrl = ctrl;
}
// from PlaceView
public function willEnterPlace (plobj :PlaceObject) :void
{
var cfg :EZGameConfig = (_ctrl.getPlaceConfig() as EZGameConfig);
_ezObj = (plobj as EZGameObject);
backend = createBackend();
_gameView = new GameContainer(cfg.getGameDefinition().getMediaPath(cfg.getGameId()));
configureGameView(_gameView);
backend.setSharedEvents(
Loader(_gameView.getMediaContainer().getMedia()).contentLoaderInfo.sharedEvents);
backend.setContainer(_gameView);
addChild(_gameView);
}
// from PlaceView
public function didLeavePlace (plobj :PlaceObject) :void
{
_gameView.getMediaContainer().shutdown(true);
removeChild(_gameView);
backend.shutdown();
}
override protected function updateDisplayList (uw :Number, uh :Number) :void
{
super.updateDisplayList(uw, uh);
if (backend != null) {
backend.sizeChanged();
}
}
/**
* Creates the backend object that will handle requests from user code.
*/
protected function createBackend () :EZGameBackend
{
return new EZGameBackend(_ctx, _ezObj, _ctrl);
}
protected function configureGameView (view :GameContainer) :void
{
view.percentWidth = 100;
view.percentHeight = 100;
}
protected var _ctx :CrowdContext;
protected var _ctrl :EZGameController;
protected var _gameView :GameContainer;
protected var _ezObj :EZGameObject;
}
}
@@ -1,82 +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 flash.utils.ByteArray;
import com.threerings.io.TypedArray;
import com.threerings.ezgame.client.EZGameService;
import com.threerings.presents.client.Client;
import com.threerings.presents.client.InvocationService;
import com.threerings.presents.client.InvocationService_ConfirmListener;
import com.threerings.presents.client.InvocationService_InvocationListener;
import com.threerings.presents.client.InvocationService_ResultListener;
import com.threerings.presents.data.InvocationMarshaller_ConfirmMarshaller;
import com.threerings.presents.data.InvocationMarshaller_ResultMarshaller;
/**
* An ActionScript version of the Java EZGameService interface.
*/
public interface EZGameService extends InvocationService
{
// from Java interface EZGameService
function addToCollection (arg1 :Client, arg2 :String, arg3 :TypedArray /* of class [B */, arg4 :Boolean, arg5 :InvocationService_InvocationListener) :void;
// from Java interface EZGameService
function checkDictionaryWord (arg1 :Client, arg2 :String, arg3 :String, arg4 :String, arg5 :InvocationService_ResultListener) :void;
// from Java interface EZGameService
function endGame (arg1 :Client, arg2 :TypedArray /* of int */, arg3 :InvocationService_InvocationListener) :void;
// from Java interface EZGameService
function endRound (arg1 :Client, arg2 :int, arg3 :InvocationService_InvocationListener) :void;
// from Java interface EZGameService
function endTurn (arg1 :Client, arg2 :int, arg3 :InvocationService_InvocationListener) :void;
// from Java interface EZGameService
function getCookie (arg1 :Client, arg2 :int, arg3 :InvocationService_InvocationListener) :void;
// from Java interface EZGameService
function getDictionaryLetterSet (arg1 :Client, arg2 :String, arg3 :String, arg4 :int, arg5 :InvocationService_ResultListener) :void;
// from Java interface EZGameService
function getFromCollection (arg1 :Client, arg2 :String, arg3 :Boolean, arg4 :int, arg5 :String, arg6 :int, arg7 :InvocationService_ConfirmListener) :void;
// from Java interface EZGameService
function mergeCollection (arg1 :Client, arg2 :String, arg3 :String, arg4 :InvocationService_InvocationListener) :void;
// from Java interface EZGameService
function restartGameIn (arg1 :Client, arg2 :int, arg3 :InvocationService_InvocationListener) :void;
// from Java interface EZGameService
function sendMessage (arg1 :Client, arg2 :String, arg3 :Object, arg4 :int, arg5 :InvocationService_InvocationListener) :void;
// from Java interface EZGameService
function setCookie (arg1 :Client, arg2 :ByteArray, arg3 :InvocationService_InvocationListener) :void;
// from Java interface EZGameService
function setProperty (arg1 :Client, arg2 :String, arg3 :Object, arg4 :int, arg5 :Boolean, arg6 :Object, arg7 :InvocationService_InvocationListener) :void;
// from Java interface EZGameService
function setTicker (arg1 :Client, arg2 :String, arg3 :int, arg4 :InvocationService_InvocationListener) :void;
}
}
@@ -1,99 +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 flash.display.DisplayObject;
import flash.geom.Rectangle;
import mx.core.mx_internal;
import mx.core.IFlexDisplayObject;
import mx.core.IInvalidating;
import mx.containers.VBox;
import mx.managers.IFocusManagerComponent;
import mx.skins.ProgrammaticSkin;
import com.threerings.crowd.chat.client.ChatCantStealFocus;
import com.threerings.flash.MediaContainer;
// TODO: there are focus issues in here that need dealing with.
//
// 1) The focus rectangle is drawn at the wrong size in scrolling games
// 2) We can get focus without having the pink focus rectangle...
// 3) When the mouse leaves the flash player and returns, this
// damn thing doesn't seem to grip onto the focus.
//
public class GameContainer extends VBox
implements ChatCantStealFocus, IFocusManagerComponent
{
public function GameContainer (url :String)
{
rawChildren.addChild(_game = new MediaContainer(url));
tabEnabled = true; // turned off by Container
// focusRect = true; // we need the focus rect
}
public function getMediaContainer () :MediaContainer
{
return _game;
}
// override public function setFocus () :void
// {
// if (stage) {
// try {
// stage.focus = this;
// } catch (e :Error) {
// trace("Apparently, this might happen: " + e)
// }
// }
// }
override protected function adjustFocusRect (obj :DisplayObject = null) :void
{
super.adjustFocusRect(obj);
// TODO: this is probably all wrong
var focusObj :IFlexDisplayObject =
IFlexDisplayObject(mx_internal::getFocusObject());
if (focusObj) {
var r :Rectangle = transform.pixelBounds;
focusObj.setActualSize(r.width - 2, r.height - 2);
focusObj.move(0, 0);
if (focusObj is IInvalidating) {
IInvalidating(focusObj).validateNow();
} else if (focusObj is ProgrammaticSkin) {
ProgrammaticSkin(focusObj).validateNow();
}
}
}
protected var _game :MediaContainer;
}
}
@@ -1,65 +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.data {
import com.threerings.io.ObjectInputStream;
import com.threerings.io.ObjectOutputStream;
import com.threerings.io.TypedArray;
/**
* Models a parameter that allows the selection of one of a list of choices (specified as strings).
*/
public class ChoiceParameter extends Parameter
{
/** The set of choices available for this parameter. */
public var choices :TypedArray;
/** The starting selection. */
public var start :String;
public function ChoiceParameter ()
{
}
// documentation inherited
override public function getDefaultValue () :Object
{
return start;
}
// from interface Streamable
override public function readObject (ins :ObjectInputStream) :void
{
super.readObject(ins);
choices = (ins.readObject() as TypedArray);
start = (ins.readField(String) as String);
}
// from interface Streamable
override public function writeObject (out :ObjectOutputStream) :void
{
super.writeObject(out);
out.writeObject(choices);
out.writeField(start);
}
}
}
@@ -1,134 +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.data {
import com.threerings.util.ClassUtil;
import com.threerings.util.Hashable;
import com.threerings.util.MessageBundle;
import com.threerings.util.StreamableHashMap;
import com.threerings.io.ObjectInputStream;
import com.threerings.io.ObjectOutputStream;
import com.threerings.crowd.client.PlaceController;
import com.threerings.parlor.game.client.GameConfigurator;
import com.threerings.parlor.game.data.GameConfig;
import com.threerings.ezgame.client.EZGameController;
/**
* A game config for a simple multiplayer ez game.
*/
public class EZGameConfig extends GameConfig
{
/** Our configuration parameters. These will be seeded with the defaults from the game
* definition and then configured by the player in the lobby. */
public var params :StreamableHashMap = new StreamableHashMap();
public function EZGameConfig (gameId :int = 0, gameDef :GameDefinition = null)
{
_gameId = gameId;
_gameDef = gameDef;
}
/** Returns the game definition associated with this config instance. */
public function getGameDefinition () :GameDefinition
{
return _gameDef;
}
// from GameConfig
override public function getGameId () :int
{
return _gameId;
}
// from GameConfig
override public function getGameIdent () :String
{
return _gameDef.ident;
}
// from GameConfig
override public function getMatchType () :int
{
return _gameDef.match.getMatchType();
}
// from GameConfig
override public function createConfigurator () :GameConfigurator
{
return null;
}
// from abstract PlaceConfig
override public function getManagerClassName () :String
{
throw new Error("Not implemented.");
}
// from interface Streamable
override public function readObject (ins :ObjectInputStream) :void
{
super.readObject(ins);
params = (ins.readObject() as StreamableHashMap);
_gameId = ins.readInt();
_gameDef = (ins.readObject() as GameDefinition);
}
// from interface Streamable
override public function writeObject (out :ObjectOutputStream) :void
{
super.writeObject(out);
out.writeObject(params);
out.writeInt(_gameId);
out.writeObject(_gameDef);
}
// from PlaceConfig
override public function createController () :PlaceController
{
var controller :String = getGameDefinition().controller;
if (controller == null) {
return createDefaultController();
}
var c :Class = ClassUtil.getClassByName(controller);
return (new c() as PlaceController);
}
/**
* Creates the controller to be used if the game definition does not specify a custom
* controller.
*/
protected function createDefaultController () :PlaceController
{
return new EZGameController();
}
/** Our game's unique id. */
protected var _gameId :int;
/** Our game definition. */
protected var _gameDef :GameDefinition;
}
}
@@ -1,230 +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.data {
import flash.utils.ByteArray;
import com.threerings.util.*; // for Float, Integer, etc.
import com.threerings.io.TypedArray;
import com.threerings.ezgame.client.EZGameService;
import com.threerings.presents.client.Client;
import com.threerings.presents.client.InvocationService_ConfirmListener;
import com.threerings.presents.client.InvocationService_InvocationListener;
import com.threerings.presents.client.InvocationService_ResultListener;
import com.threerings.presents.data.InvocationMarshaller;
import com.threerings.presents.data.InvocationMarshaller_ConfirmMarshaller;
import com.threerings.presents.data.InvocationMarshaller_ListenerMarshaller;
import com.threerings.presents.data.InvocationMarshaller_ResultMarshaller;
/**
* Provides the implementation of the {@link EZGameService} interface
* that marshalls the arguments and delivers the request to the provider
* on the server. Also provides an implementation of the response listener
* interfaces that marshall the response arguments and deliver them back
* to the requesting client.
*/
public class EZGameMarshaller extends InvocationMarshaller
implements EZGameService
{
/** The method id used to dispatch {@link #addToCollection} requests. */
public static const ADD_TO_COLLECTION :int = 1;
// from interface EZGameService
public function addToCollection (arg1 :Client, arg2 :String, arg3 :TypedArray /* of class [B */, arg4 :Boolean, arg5 :InvocationService_InvocationListener) :void
{
var listener5 :InvocationMarshaller_ListenerMarshaller = new InvocationMarshaller_ListenerMarshaller();
listener5.listener = arg5;
sendRequest(arg1, ADD_TO_COLLECTION, [
arg2, arg3, langBoolean.valueOf(arg4), listener5
]);
}
/** The method id used to dispatch {@link #checkDictionaryWord} requests. */
public static const CHECK_DICTIONARY_WORD :int = 2;
// from interface EZGameService
public function checkDictionaryWord (arg1 :Client, arg2 :String, arg3 :String, arg4 :String, arg5 :InvocationService_ResultListener) :void
{
var listener5 :InvocationMarshaller_ResultMarshaller = new InvocationMarshaller_ResultMarshaller();
listener5.listener = arg5;
sendRequest(arg1, CHECK_DICTIONARY_WORD, [
arg2, arg3, arg4, listener5
]);
}
/** The method id used to dispatch {@link #endGame} requests. */
public static const END_GAME :int = 3;
// from interface EZGameService
public function endGame (arg1 :Client, arg2 :TypedArray /* of int */, arg3 :InvocationService_InvocationListener) :void
{
var listener3 :InvocationMarshaller_ListenerMarshaller = new InvocationMarshaller_ListenerMarshaller();
listener3.listener = arg3;
sendRequest(arg1, END_GAME, [
arg2, listener3
]);
}
/** The method id used to dispatch {@link #endRound} requests. */
public static const END_ROUND :int = 4;
// from interface EZGameService
public function endRound (arg1 :Client, arg2 :int, arg3 :InvocationService_InvocationListener) :void
{
var listener3 :InvocationMarshaller_ListenerMarshaller = new InvocationMarshaller_ListenerMarshaller();
listener3.listener = arg3;
sendRequest(arg1, END_ROUND, [
Integer.valueOf(arg2), listener3
]);
}
/** The method id used to dispatch {@link #endTurn} requests. */
public static const END_TURN :int = 5;
// from interface EZGameService
public function endTurn (arg1 :Client, arg2 :int, arg3 :InvocationService_InvocationListener) :void
{
var listener3 :InvocationMarshaller_ListenerMarshaller = new InvocationMarshaller_ListenerMarshaller();
listener3.listener = arg3;
sendRequest(arg1, END_TURN, [
Integer.valueOf(arg2), listener3
]);
}
/** The method id used to dispatch {@link #getCookie} requests. */
public static const GET_COOKIE :int = 6;
// from interface EZGameService
public function getCookie (arg1 :Client, arg2 :int, arg3 :InvocationService_InvocationListener) :void
{
var listener3 :InvocationMarshaller_ListenerMarshaller = new InvocationMarshaller_ListenerMarshaller();
listener3.listener = arg3;
sendRequest(arg1, GET_COOKIE, [
Integer.valueOf(arg2), listener3
]);
}
/** The method id used to dispatch {@link #getDictionaryLetterSet} requests. */
public static const GET_DICTIONARY_LETTER_SET :int = 7;
// from interface EZGameService
public function getDictionaryLetterSet (arg1 :Client, arg2 :String, arg3 :String, arg4 :int, arg5 :InvocationService_ResultListener) :void
{
var listener5 :InvocationMarshaller_ResultMarshaller = new InvocationMarshaller_ResultMarshaller();
listener5.listener = arg5;
sendRequest(arg1, GET_DICTIONARY_LETTER_SET, [
arg2, arg3, Integer.valueOf(arg4), listener5
]);
}
/** The method id used to dispatch {@link #getFromCollection} requests. */
public static const GET_FROM_COLLECTION :int = 8;
// from interface EZGameService
public function getFromCollection (arg1 :Client, arg2 :String, arg3 :Boolean, arg4 :int, arg5 :String, arg6 :int, arg7 :InvocationService_ConfirmListener) :void
{
var listener7 :InvocationMarshaller_ConfirmMarshaller = new InvocationMarshaller_ConfirmMarshaller();
listener7.listener = arg7;
sendRequest(arg1, GET_FROM_COLLECTION, [
arg2, langBoolean.valueOf(arg3), Integer.valueOf(arg4), arg5, Integer.valueOf(arg6), listener7
]);
}
/** The method id used to dispatch {@link #mergeCollection} requests. */
public static const MERGE_COLLECTION :int = 9;
// from interface EZGameService
public function mergeCollection (arg1 :Client, arg2 :String, arg3 :String, arg4 :InvocationService_InvocationListener) :void
{
var listener4 :InvocationMarshaller_ListenerMarshaller = new InvocationMarshaller_ListenerMarshaller();
listener4.listener = arg4;
sendRequest(arg1, MERGE_COLLECTION, [
arg2, arg3, listener4
]);
}
/** The method id used to dispatch {@link #restartGameIn} requests. */
public static const RESTART_GAME_IN :int = 10;
// from interface EZGameService
public function restartGameIn (arg1 :Client, arg2 :int, arg3 :InvocationService_InvocationListener) :void
{
var listener3 :InvocationMarshaller_ListenerMarshaller = new InvocationMarshaller_ListenerMarshaller();
listener3.listener = arg3;
sendRequest(arg1, RESTART_GAME_IN, [
Integer.valueOf(arg2), listener3
]);
}
/** The method id used to dispatch {@link #sendMessage} requests. */
public static const SEND_MESSAGE :int = 11;
// from interface EZGameService
public function sendMessage (arg1 :Client, arg2 :String, arg3 :Object, arg4 :int, arg5 :InvocationService_InvocationListener) :void
{
var listener5 :InvocationMarshaller_ListenerMarshaller = new InvocationMarshaller_ListenerMarshaller();
listener5.listener = arg5;
sendRequest(arg1, SEND_MESSAGE, [
arg2, arg3, Integer.valueOf(arg4), listener5
]);
}
/** The method id used to dispatch {@link #setCookie} requests. */
public static const SET_COOKIE :int = 12;
// from interface EZGameService
public function setCookie (arg1 :Client, arg2 :ByteArray, arg3 :InvocationService_InvocationListener) :void
{
var listener3 :InvocationMarshaller_ListenerMarshaller = new InvocationMarshaller_ListenerMarshaller();
listener3.listener = arg3;
sendRequest(arg1, SET_COOKIE, [
arg2, listener3
]);
}
/** The method id used to dispatch {@link #setProperty} requests. */
public static const SET_PROPERTY :int = 13;
// from interface EZGameService
public function setProperty (arg1 :Client, arg2 :String, arg3 :Object, arg4 :int, arg5 :Boolean, arg6 :Object, arg7 :InvocationService_InvocationListener) :void
{
var listener7 :InvocationMarshaller_ListenerMarshaller = new InvocationMarshaller_ListenerMarshaller();
listener7.listener = arg7;
sendRequest(arg1, SET_PROPERTY, [
arg2, arg3, Integer.valueOf(arg4), langBoolean.valueOf(arg5), arg6, listener7
]);
}
/** The method id used to dispatch {@link #setTicker} requests. */
public static const SET_TICKER :int = 14;
// from interface EZGameService
public function setTicker (arg1 :Client, arg2 :String, arg3 :int, arg4 :InvocationService_InvocationListener) :void
{
var listener4 :InvocationMarshaller_ListenerMarshaller = new InvocationMarshaller_ListenerMarshaller();
listener4.listener = arg4;
sendRequest(arg1, SET_TICKER, [
arg2, Integer.valueOf(arg3), listener4
]);
}
}
}
@@ -1,163 +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.data {
import flash.events.Event;
import flash.utils.ByteArray;
import com.threerings.util.Name;
import com.threerings.util.ObjectMarshaller;
import com.threerings.io.ObjectInputStream;
import com.threerings.io.ObjectOutputStream;
import com.threerings.io.TypedArray;
import com.threerings.presents.dobj.DSet;
import com.threerings.parlor.game.data.GameObject;
import com.threerings.parlor.turn.data.TurnGameObject;
public class EZGameObject extends GameObject
implements TurnGameObject
{
/** The identifier for a MessageEvent containing a user message. */
public static const USER_MESSAGE :String = "Umsg";
/** The identifier for a MessageEvent containing game-system chat. */
public static const GAME_CHAT :String = "Uchat";
/** The identifier for a MessageEvent containing ticker notifications. */
public static const TICKER :String = "Utick";
// AUTO-GENERATED: FIELDS START
/** The field name of the <code>controllerOid</code> field. */
public static const CONTROLLER_OID :String = "controllerOid";
/** The field name of the <code>turnHolder</code> field. */
public static const TURN_HOLDER :String = "turnHolder";
/** The field name of the <code>userCookies</code> field. */
public static const USER_COOKIES :String = "userCookies";
/** The field name of the <code>ezGameService</code> field. */
public static const EZ_GAME_SERVICE :String = "ezGameService";
// AUTO-GENERATED: FIELDS END
/** The client that is in control of this game. The first client to enter will be assigned
* control and control will subsequently be reassigned if that client disconnects or leaves. */
public var controllerOid :int;
/** The current turn holder. */
public var turnHolder :Name;
/** A set of loaded user cookies. */
public var userCookies :DSet;
/** The service interface for requesting special things from the server. */
public var ezGameService :EZGameMarshaller;
/**
* Access the underlying user properties.
*/
public function getUserProps () :Object
{
return _props;
}
// from TurnGameObject
public function getTurnHolderFieldName () :String
{
return TURN_HOLDER;
}
// from TurnGameObject
public function getTurnHolder () :Name
{
return turnHolder;
}
// from TurnGameObject
public function getPlayers () :TypedArray /* of Name */
{
return players;
}
/**
* Called by a PropertySetEvent to enact a property change.
* @return the old value
*/
public function applyPropertySet (propName :String, value :Object, index :int) :Object
{
var oldValue :Object = _props[propName];
if (index >= 0) {
// set an array element
var arr :Array = (oldValue as Array);
if (arr == null) {
arr = [];
_props[propName] = arr;
}
oldValue = arr[index];
arr[index] = value;
} else if (value != null) {
// normal property set
_props[propName] = value;
} else {
// remove a property
delete _props[propName];
}
return oldValue;
}
override public function readObject (ins :ObjectInputStream) :void
{
super.readObject(ins);
// first read any regular bits
readDefaultFields(ins);
// then user properties
var count :int = ins.readInt();
while (count-- > 0) {
var key :String = ins.readUTF();
var value :Object = ObjectMarshaller.decode(ins.readObject());
_props[key] = value;
}
}
/**
* Reads the fields written by the default serializer for this instance.
*/
protected function readDefaultFields (ins :ObjectInputStream) :void
{
controllerOid = ins.readInt();
turnHolder = (ins.readObject() as Name);
userCookies = (ins.readObject() as DSet);
ezGameService = (ins.readObject() as EZGameMarshaller);
}
/** The raw properties set by the game. */
protected var _props :Object = new Object();
}
}
@@ -1,120 +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.data {
import com.threerings.io.ObjectInputStream;
import com.threerings.io.ObjectOutputStream;
import com.threerings.io.Streamable;
import com.threerings.io.TypedArray;
/**
* Contains the information about a game as described by the game definition XML file.
*/
public /*abstract*/ class GameDefinition
implements Streamable
{
/** A string identifier for the game. */
public var ident :String;
/** The class name of the <code>GameController</code> derivation that we use to bootstrap on
* the client. */
public var controller :String;
/** The class name of the <code>GameManager</code> derivation that we use to manage the game on
* the server. */
public var manager :String;
/** The MD5 digest of the game media file. */
public var digest :String;
/** The configuration of the match-making mechanism. */
public var match :MatchConfig;
/** Parameters used to configure the game itself. */
public var params :TypedArray;
public function GameDefinition ()
{
}
/**
* Provides the path to this game's media (a jar file or an SWF).
*
* @param gameId the unique id of the game provided when this game definition was registered
* with the system, or -1 if we're running in test mode.
*/
public function getMediaPath (gameId :int) :String
{
throw new Error("abstract");
}
/**
* Returns true if a single player can play this game (possibly against AI opponents), or if
* opponents are needed.
*/
public function isSinglePlayerPlayable () :Boolean
{
throw new Error("Not implemented");
}
/** Generates a string representation of this instance. */
public function toString () :String
{
return "[ident=" + ident + ", ctrl=" + controller + ", mgr=" + manager +
", match=" + match + ", params=" + params + ", digest=" + digest + "]";
}
// from interface Streamable
public function readObject (ins :ObjectInputStream) :void
{
ident = (ins.readField(String) as String);
controller = (ins.readField(String) as String);
manager = (ins.readField(String) as String);
digest = (ins.readField(String) as String);
match = (ins.readObject() as MatchConfig);
params = (ins.readObject() as TypedArray);
}
// from interface Streamable
public function writeObject (out :ObjectOutputStream) :void
{
out.writeField(ident);
out.writeField(controller);
out.writeField(manager);
out.writeField(digest);
out.writeObject(match);
out.writeObject(params);
}
/** This function is required to ensure that the compiler includes certain classes. */
public function fuckingCompiler () :void
{
var c :Class;
// Parameter derivations
c = RangeParameter;
c = ToggleParameter;
c = ChoiceParameter;
// MatchConfig derivations
c = TableMatchConfig;
}
}
}
@@ -1,50 +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.data {
import com.threerings.io.SimpleStreamableObject;
import com.threerings.parlor.game.data.GameConfig;
/**
* Used to configure the match-making interface for a game. Particular match-making mechanisms
* extend this class and specify their own special configuration parameters.
*/
public /*abstract*/ class MatchConfig extends SimpleStreamableObject
{
public function MatchConfig ()
{
}
/** Returns the matchmaking type to use for this game, e.g. {@link GameConfig.SEATED_GAME}. */
public function getMatchType () :int
{
throw new Error("Abstract");
}
/** Returns the minimum number of players needed to play this game. */
public function getMinimumPlayers () :int
{
throw new Error("Abstract");
}
}
}
@@ -1,81 +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.data {
import com.threerings.io.ObjectInputStream;
import com.threerings.io.ObjectOutputStream;
import com.threerings.io.Streamable;
/**
* Defines a configuration parameter for a game. Various derived classes exist that define
* particular types of configuration parameters including choices, toggles, ranges, etc.
*/
public /*abstract*/ class Parameter
implements Streamable
{
/** A string identifier that names this parameter. */
public var ident :String;
/** A human readable name for this configuration parameter. */
public var name :String;
/** A human readable tooltip to display when the mouse is hovered over this configuration
* parameter. */
public var tip :String;
public function Parameter ()
{
}
public function toString () :String
{
return ident;
}
public function getDefaultValue () :Object
{
throw new Error("Abstract");
}
/** Returns the translation key for this parameter's label. */
public function getLabel () :String
{
return "m." + ident;
}
// from interface Streamable
public function readObject (ins :ObjectInputStream) :void
{
ident = (ins.readField(String) as String);
name = (ins.readField(String) as String);
tip = (ins.readField(String) as String);
}
// from interface Streamable
public function writeObject (out :ObjectOutputStream) :void
{
out.writeField(ident);
out.writeField(name);
out.writeField(tip);
}
}
}
@@ -1,122 +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.data {
import flash.utils.ByteArray;
import flash.utils.IExternalizable;
import com.threerings.io.ObjectInputStream;
import com.threerings.io.ObjectOutputStream;
import com.threerings.io.Streamer;
import com.threerings.util.ObjectMarshaller;
import com.threerings.util.StringBuilder;
import com.threerings.presents.dobj.DObject;
import com.threerings.presents.dobj.NamedEvent;
/**
* Represents a property change on the actionscript object we
* use in FlashGameObject.
*/
public class PropertySetEvent extends NamedEvent
{
/**
* Create a PropertySetEvent.
*/
public function PropertySetEvent () // unserialize-only
{
super(0, null);
}
// from abstract DEvent
override public function applyToObject (target :DObject) :Boolean
{
// since we're in actionscript, we're always on the client
_oldValue = EZGameObject(target).applyPropertySet(_name, _data, _index);
return true;
}
/**
* Get the value that was set for the property.
*/
public function getValue () :Object
{
return _data;
}
/**
* Get the index, or -1 if not applicable.
*/
public function getIndex () :int
{
return _index;
}
/**
* Get the old value.
*/
public function getOldValue () :Object
{
return _oldValue;
}
// from interface Streamable
override public function readObject (ins :ObjectInputStream) :void
{
super.readObject(ins);
_index = ins.readInt();
_data = ObjectMarshaller.decode(ins.readObject());
}
// from interface Streamable
override public function writeObject (out :ObjectOutputStream) :void
{
super.writeObject(out);
out.writeInt(_index);
out.writeObject(_data);
}
override protected function notifyListener (listener :Object) :void
{
if (listener is PropertySetListener) {
(listener as PropertySetListener).propertyWasSet(this);
}
}
override protected function toStringBuf (buf :StringBuilder) :void
{
buf.append("PropertySetEvent ");
super.toStringBuf(buf);
buf.append(", index=").append(_index);
}
/** The index of the property, if applicable. */
protected var _index :int;
/** The client-side data that is assigned to this property. */
protected var _data :Object;
/** The old value. */
protected var _oldValue :Object;
}
}
@@ -1,38 +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.data {
import com.threerings.presents.dobj.ChangeListener;
/**
* A listener that will be notified of PropertySet events.
*/
public interface PropertySetListener extends ChangeListener
{
/**
* Called when a property was set on a flash game object.
* This will be called <em>after</em> the event has been applied
* to the object.
*/
function propertyWasSet (event :PropertySetEvent) :void;
}
}
@@ -1,69 +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.data {
import com.threerings.io.ObjectInputStream;
import com.threerings.io.ObjectOutputStream;
/**
* Models a parameter that can contain an integer value in a specified range.
*/
public class RangeParameter extends Parameter
{
/** The minimum value of this parameter. */
public var minimum :int;
/** The maximum value of this parameter. */
public var maximum :int;
/** The starting value for this parameter. */
public var start :int;
public function RangeParameter ()
{
}
// documentation inherited
override public function getDefaultValue () :Object
{
return start;
}
// from interface Streamable
override public function readObject (ins :ObjectInputStream) :void
{
super.readObject(ins);
minimum = ins.readInt();
maximum = ins.readInt();
start = ins.readInt();
}
// from interface Streamable
override public function writeObject (out :ObjectOutputStream) :void
{
super.writeObject(out);
out.writeInt(minimum);
out.writeInt(maximum);
out.writeInt(start);
}
}
}
@@ -1,82 +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.data {
import com.threerings.io.ObjectInputStream;
import com.threerings.io.ObjectOutputStream;
import com.threerings.parlor.game.data.GameConfig;
/**
* Extends {@link MatchConfig} with information about match-making in the table style.
*/
public class TableMatchConfig extends MatchConfig
{
/** The minimum number of seats at this table. */
public var minSeats :int;
/** The starting setting for the number of seats at this table. */
public var startSeats :int;
/** The maximum number of seats at this table. */
public var maxSeats :int;
/** This is set to true if this is a party game. */
public var isPartyGame :Boolean;
public function TableMatchConfig ()
{
}
// from MatchConfig
override public function getMatchType () :int
{
return isPartyGame ? GameConfig.PARTY : GameConfig.SEATED_GAME;
}
// from MatchConfig
override public function getMinimumPlayers () :int
{
return minSeats;
}
// from interface Streamable
override public function readObject (ins :ObjectInputStream) :void
{
super.readObject(ins);
minSeats = ins.readInt();
startSeats = ins.readInt();
maxSeats = ins.readInt();
isPartyGame = ins.readBoolean();
}
// from interface Streamable
override public function writeObject (out :ObjectOutputStream) :void
{
super.writeObject(out);
out.writeInt(minSeats);
out.writeInt(startSeats);
out.writeInt(maxSeats);
out.writeBoolean(isPartyGame);
}
}
}
@@ -1,59 +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.data {
import com.threerings.io.ObjectInputStream;
import com.threerings.io.ObjectOutputStream;
/**
* Models a parameter that allows the toggling of a single value.
*/
public class ToggleParameter extends Parameter
{
/** The starting state for this parameter. */
public var start :Boolean;
public function ToggleParameter ()
{
}
// documentation inherited
override public function getDefaultValue () :Object
{
return start;
}
// from interface Streamable
override public function readObject (ins :ObjectInputStream) :void
{
super.readObject(ins);
start = ins.readBoolean();
}
// from interface Streamable
override public function writeObject (out :ObjectOutputStream) :void
{
super.writeObject(out);
out.writeBoolean(start);
}
}
}
@@ -1,69 +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.data {
import flash.utils.ByteArray;
import com.threerings.io.ObjectInputStream;
import com.threerings.io.ObjectOutputStream;
import com.threerings.presents.dobj.DSet_Entry;
/**
* Represents a user's game-specific cookie data.
*/
public class UserCookie
implements DSet_Entry
{
/** The id of the player that has this cookie. */
public var playerId :int;
/** The cookie value. */
public var cookie :ByteArray;
public function UserCookie (playerId :int = 0, cookie :ByteArray = null)
{
this.playerId = playerId;
this.cookie = cookie;
}
// from DSet_Entry
public function getKey () :Object
{
return playerId;
}
// from superinterface Streamable
public function readObject (ins :ObjectInputStream) :void
{
playerId = ins.readInt();
cookie = (ins.readField(ByteArray) as ByteArray);
}
// from superinterface Streamable
public function writeObject (out :ObjectOutputStream) :void
{
out.writeInt(playerId);
out.writeField(cookie);
}
}
}