EZGameControl updates:

- switched everything to be based on playerId instead of index
  (which doesn't make sense for a party game.)
- started adding new functions
- backwards compatible with all old games!


git-svn-id: svn+ssh://src.earth.threerings.net/vilya/trunk@186 c613c5cb-e716-0410-b11b-feb51c14d237
This commit is contained in:
Ray Greenwell
2007-02-14 01:59:29 +00:00
parent 00e771e7a5
commit e5d5480e9b
9 changed files with 368 additions and 189 deletions
+51 -44
View File
@@ -282,17 +282,17 @@ public class EZGameControl extends EventDispatcher
* @param count the number of elements to pick
* @param msgOrPropName the name of the message or property
* that will contain the picked elements.
* @param playerIndex if -1 (or unset), the picked elements should be
* @param playerId if 0 (or unset), the picked elements should be
* set on the gameObject as a property for all to see.
* If a playerIndex is specified, only that player will receive
* 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 pickFromCollection (
collName :String, count :int, msgOrPropName :String,
playerIndex :int = -1) :void
playerId :int = 0) :void
{
getFromCollection(collName, count, msgOrPropName, playerIndex,
getFromCollection(collName, count, msgOrPropName, playerId,
false, null);
}
@@ -305,17 +305,17 @@ public class EZGameControl extends EventDispatcher
* @param count the number of elements to pick
* @param msgOrPropName the name of the message or property
* that will contain the picked elements.
* @param playerIndex if -1 (or unset), the picked elements should be
* @param playerId if 0 (or unset), the picked elements should be
* set on the gameObject as a property for all to see.
* If a playerIndex is specified, only that player will receive
* 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 dealFromCollection (
collName :String, count :int, msgOrPropName :String,
callback :Function = null, playerIndex :int = -1) :void
callback :Function = null, playerId :int = 0) :void
{
getFromCollection(collName, count, msgOrPropName, playerIndex,
getFromCollection(collName, count, msgOrPropName, playerId,
true, callback);
}
@@ -336,13 +336,13 @@ public class EZGameControl extends EventDispatcher
* value will not be saved- it will merely end up coming out
* as a MessageReceivedEvent.
*
* @param playerIndex if -1, sends to all players, otherwise
* @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, playerIndex :int = -1) :void
messageName :String, value :Object, playerId :int = 0) :void
{
callEZCode("sendMessage_v1", messageName, value, playerIndex);
callEZCode("sendMessage_v2", messageName, value, playerId);
}
/**
@@ -382,45 +382,52 @@ public class EZGameControl extends EventDispatcher
callEZCode("localChat_v1", msg);
}
/**
* Get the number of players currently in the game.
*/
public function getPlayerCount () :int
// TODO: NEW
public function getOccupants () :Array /* of playerId */
{
return int(callEZCode("getPlayerCount_v1"));
return (callEZCode("getOccupants_v1") as Array);
}
// TODO: NEW
/**
* Get the player names, as an 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.
*/
public function getPlayerNames () :Array
public function getOccupantName (playerId :int) :String
{
return (callEZCode("getPlayerNames_v1") as Array);
return String(callEZCode("getOccupantName_v1", playerId));
}
// TODO: NEW: Table control
/**
* Get the index into the player names array of the current player,
* or -1 if the user is not a player.
* Get the player's position, or -1 if not a player.
*/
public function getMyIndex () :int
public function getPlayerPosition (playerId :int) :int
{
return int(callEZCode("getMyIndex_v1"));
return int(callEZCode("getPlayerPosition_v1", playerId));
}
// TODO: NEW: Table control
/**
* Get the turn holder's index, or -1 if it's nobody's turn.
* Get all the players at the table, in their seated position.
* Absent players will be represented by a 0.
*/
public function getTurnHolderIndex () :int
public function getPlayers () :Array /* of playerId (int) */
{
return int(callEZCode("getTurnHolderIndex_v1"));
return (callEZCode("getPlayers_v1") as Array);
}
/**
* Get the indexes of the winners
*/
public function getWinnerIndexes () :Array /* of int */
// TODO: NEW
public function getMyId () :int
{
return (callEZCode("getWinnerIndexes_v1") as Array);
return int(callEZCode("getMyId_v1"));
}
public function getTurnHolder () :int
{
return int(callEZCode("getTurnHolder_v1"));
}
/**
@@ -428,9 +435,9 @@ public class EZGameControl extends EventDispatcher
* 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 (playerIndex :int, callback :Function) :void
public function getUserCookie (playerId :int, callback :Function) :void
{
callEZCode("getUserCookie_v1", playerIndex, callback);
callEZCode("getUserCookie_v1", playerId, callback);
}
/**
@@ -469,21 +476,21 @@ public class EZGameControl extends EventDispatcher
}
/**
* End the current turn. If no next player index is specified,
* End the current turn. If no next player id is specified,
* then the next player after the current one is used.
*/
public function endTurn (nextPlayerIndex :int = -1) :void
public function endTurn (nextPlayerId :int = 0) :void
{
callEZCode("endTurn_v1", nextPlayerIndex);
callEZCode("endTurn_v2", nextPlayerId);
}
/**
* End the game. The specified player indexes are winners!
* End the game. The specified player ids are winners!
*/
public function endGame (... winnerIndexes) :void
public function endGame (... winnerIds) :void
{
var args :Array = winnerIndexes;
args.unshift("endGame_v1");
var args :Array = winnerIds;
args.unshift("endGame_v2");
// goddamn var-args complications in actionscript
callEZCode.apply(null, args);
@@ -513,12 +520,12 @@ public class EZGameControl extends EventDispatcher
/**
* Helper method for pickFromCollection and dealFromCollection.
*/
protected function getFromCollection(
collName :String, count :int, msgOrPropName :String, playerIndex :int,
protected function getFromCollection (
collName :String, count :int, msgOrPropName :String, playerId :int,
consume :Boolean, callback :Function) :void
{
callEZCode("getFromCollection_v1", collName, count, msgOrPropName,
playerIndex, consume, callback);
callEZCode("getFromCollection_v2", collName, count, msgOrPropName,
playerId, consume, callback);
}
/**
@@ -61,11 +61,13 @@ public class PlayersDisplay extends Sprite
maxWidth = label.textWidth;
}
var players :Array = _gameCtrl.getPlayers();
// create a label for each player
var playerIndex :int = 0;
for each (var name :String in _gameCtrl.getPlayerNames()) {
label = createPlayerLabel(playerIndex, name);
icon = createPlayerIcon(playerIndex, name);
for each (var playerId :int in players) {
var name :String = _gameCtrl.getOccupantName(playerId);
label = createPlayerLabel(playerId, name);
icon = createPlayerIcon(playerId, name);
var iconW :int = 0;
var iconH :int = 0;
if (icon != null) {
@@ -83,7 +85,6 @@ public class PlayersDisplay extends Sprite
maxWidth = Math.max(maxWidth, iconW + label.textWidth);
_playerLabels.push(label);
playerIndex++;
}
// make all the player labels the same width
@@ -123,7 +124,7 @@ public class PlayersDisplay extends Sprite
/**
* Create a TextArea that will be used to display player names.
*/
protected function createPlayerLabel (idx :int, name :String) :TextField
protected function createPlayerLabel (playerId :int, name :String) :TextField
{
var label :TextField = new TextField();
label.autoSize = TextFieldAutoSize.LEFT;
@@ -133,7 +134,7 @@ public class PlayersDisplay extends Sprite
return label;
}
protected function createPlayerIcon (idx :int, name :String) :DisplayObject
protected function createPlayerIcon (playerId :int, name :String) :DisplayObject
{
return null;
}
@@ -159,7 +160,7 @@ public class PlayersDisplay extends Sprite
*/
protected function displayCurrentTurn () :void
{
var idx :int = _gameCtrl.isInPlay() ? _gameCtrl.getTurnHolderIndex() : -1;
var idx :int = _gameCtrl.isInPlay() ? _gameCtrl.getPlayerPosition(_gameCtrl.getTurnHolder()) : -1;
for (var ii :int = 0; ii < _playerLabels.length; ii++) {
var label :TextField = (_playerLabels[ii] as TextField);
label.backgroundColor = getBackground(ii == idx);
@@ -19,6 +19,7 @@ import flash.utils.getQualifiedSuperclassName;
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;
@@ -125,27 +126,40 @@ public class GameControlBackend
// functions
o["setProperty_v1"] = setProperty_v1;
o["mergeCollection_v1"] = mergeCollection_v1;
o["sendMessage_v1"] = sendMessage_v1;
o["setTicker_v1"] = setTicker_v1;
o["sendChat_v1"] = sendChat_v1;
o["localChat_v1"] = localChat_v1;
o["getPlayerCount_v1"] = getPlayerCount_v1;
o["setUserCookie_v1"] = setUserCookie_v1;
o["isMyTurn_v1"] = isMyTurn_v1;
o["isInPlay_v1"] = isInPlay_v1;
o["getDictionaryLetterSet_v1"] = getDictionaryLetterSet_v1;
o["checkDictionaryWord_v1"] = checkDictionaryWord_v1;
o["populateCollection_v1"] = populateCollection_v1;
o["alterKeyEvents_v1"] = alterKeyEvents_v1;
o["focusContainer_v1"] = focusContainer_v1;
// newest
o["getFromCollection_v2"] = getFromCollection_v2;
o["sendMessage_v2"] = sendMessage_v2;
o["getOccupants_v1"] = getOccupants_v1;
o["getMyId_v1"] = getMyId_v1;
o["getUserCookie_v2"] = getUserCookie_v2;
o["endTurn_v2"] = endTurn_v2;
o["endGame_v2"] = endGame_v2;
o["getTurnHolder_v1"] = getTurnHolder_v1;
o["getPlayers_v1"] = getPlayers_v1;
// deprecated, will be removed soon
o["getFromCollection_v1"] = getFromCollection_v1;
o["sendMessage_v1"] = sendMessage_v1;
o["getPlayerCount_v1"] = getPlayerCount_v1; // no replacement
o["getPlayerNames_v1"] = getPlayerNames_v1;
o["getMyIndex_v1"] = getMyIndex_v1;
o["getTurnHolderIndex_v1"] = getTurnHolderIndex_v1;
o["getWinnerIndexes_v1"] = getWinnerIndexes_v1;
o["getUserCookie_v1"] = getUserCookie_v1;
o["setUserCookie_v1"] = setUserCookie_v1;
o["isMyTurn_v1"] = isMyTurn_v1;
o["isInPlay_v1"] = isInPlay_v1;
o["endTurn_v1"] = endTurn_v1;
o["endGame_v1"] = endGame_v1;
o["getDictionaryLetterSet_v1"] = getDictionaryLetterSet_v1;
o["checkDictionaryWord_v1"] = checkDictionaryWord_v1;
o["populateCollection_v1"] = populateCollection_v1;
o["getFromCollection_v1"] = getFromCollection_v1;
o["alterKeyEvents_v1"] = alterKeyEvents_v1;
o["focusContainer_v1"] = focusContainer_v1;
}
public function setProperty_v1 (
@@ -171,15 +185,15 @@ public class GameControlBackend
srcColl, intoColl, createLoggingConfirmListener("mergeCollection"));
}
public function sendMessage_v1 (
messageName :String, value :Object, playerIndex :int) :void
public function sendMessage_v2 (
messageName :String, value :Object, playerId :int) :void
{
validateName(messageName);
validateValue(value);
var encoded :Object = EZObjectMarshaller.encode(value, false);
_ezObj.ezGameService.sendMessage(_ctx.getClient(),
messageName, encoded, playerIndex,
messageName, encoded, playerId,
createLoggingConfirmListener("sendMessage"));
}
@@ -207,74 +221,63 @@ public class GameControlBackend
_ctx.getChatDirector().displayInfo(null, MessageBundle.taint(msg));
}
public function getPlayerCount_v1 () :int
public function getOccupants_v1 () :Array
{
if (_ezObj.players.length == 0) {
// party game
return _ezObj.occupants.size();
} else {
return _ezObj.getPlayerCount();
var occs :Array = [];
for (var ii :int = _ezObj.occupants.size() - 1; ii >= 0; ii--) {
occs.push(_ezObj.occupants.get(ii));
}
return occs;
}
public function getPlayerNames_v1 () :Array
public function getPlayers_v1 () :Array
{
var names :Array = new Array();
if (_ezObj.players.length == 0) {
// party game, count all occupants
var itr :Iterator = _ezObj.occupantInfo.iterator();
while (itr.hasNext()) {
var occInfo :OccupantInfo = (itr.next() as OccupantInfo);
names.push(occInfo.username.toString());
}
} else {
for each (var name :Name in _ezObj.players) {
names.push((name == null) ? null : name.toString());
}
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 names;
return playerIds;
}
public function getMyIndex_v1 () :int
public function getOccupantName_v1 (playerId :int) :String
{
if (_ezObj.players.length == 0) {
// party game
// TODO: this shouldn't be based off of the String form of the name.
var array :Array = getPlayerNames_v1();
return array.indexOf(getUsername().toString());
var occInfo :OccupantInfo =
(_ezObj.occupantInfo.get(playerId) as OccupantInfo);
return (occInfo == null) ? null : occInfo.username.toString();
}
} else {
return _ezObj.getPlayerIndex(getUsername());
public function getMyId_v1 () :int
{
return _ctx.getClient().getClientObject().getOid();
}
// TODO: table games only
public function getPlayerPosition_v1 (playerId :int) :int
{
var occInfo :OccupantInfo =
(_ezObj.occupantInfo.get(playerId) as OccupantInfo);
if (occInfo == null) {
return -1;
}
return ArrayUtil.indexOf(_ezObj.players, occInfo.username);
}
public function getTurnHolderIndex_v1 () :int
// TODO: table only
public function getTurnHolder_v1 () :int
{
return _ezObj.getPlayerIndex(_ezObj.turnHolder);
var occInfo :OccupantInfo = _ezObj.getOccupantInfo(_ezObj.turnHolder);
return (occInfo == null) ? 0 : occInfo.bodyOid;
}
public function getWinnerIndexes_v1 () :Array /* of int */
{
var arr :Array = new Array();
if (_ezObj.winners != null) {
for (var ii :int = 0; ii < _ezObj.winners.length; ii++) {
if (_ezObj.winners[ii]) {
arr.push(ii);
}
}
}
return arr;
}
public function getUserCookie_v1 (
playerIndex :int, callback :Function) :void
public function getUserCookie_v2 (
playerId :int, callback :Function) :void
{
// see if that cookie is already published
if (_ezObj.userCookies != null) {
var uc :UserCookie =
(_ezObj.userCookies.get(playerIndex) as UserCookie);
(_ezObj.userCookies.get(playerId) as UserCookie);
if (uc != null) {
callback(uc.cookie);
return;
@@ -284,15 +287,15 @@ public class GameControlBackend
if (_cookieCallbacks == null) {
_cookieCallbacks = new Dictionary();
}
var arr :Array = (_cookieCallbacks[playerIndex] as Array);
var arr :Array = (_cookieCallbacks[playerId] as Array);
if (arr == null) {
arr = [];
_cookieCallbacks[playerIndex] = arr;
_cookieCallbacks[playerId] = arr;
}
arr.push(callback);
// request it to be made so by the server
_ezObj.ezGameService.getCookie(_ctx.getClient(), playerIndex,
_ezObj.ezGameService.getCookie(_ctx.getClient(), playerId,
createLoggingConfirmListener("getUserCookie"));
}
@@ -320,17 +323,17 @@ public class GameControlBackend
return _ezObj.isInPlay();
}
public function endTurn_v1 (nextPlayerIndex :int = -1) :void
public function endTurn_v2 (nextPlayerId :int) :void
{
_ezObj.ezGameService.endTurn(_ctx.getClient(), nextPlayerIndex,
_ezObj.ezGameService.endTurn(_ctx.getClient(), nextPlayerId,
createLoggingConfirmListener("endTurn"));
}
public function endGame_v1 (... winnerDexes) :void
public function endGame_v2 (... winnerIds) :void
{
var winners :TypedArray = TypedArray.create(int);
while (winnerDexes.length > 0) {
winners.push(int(winnerDexes.shift()));
while (winnerIds.length > 0) {
winners.push(int(winnerIds.shift()));
}
_ezObj.ezGameService.endGame(_ctx.getClient(), winners,
createLoggingConfirmListener("endGame"));
@@ -406,8 +409,8 @@ public class GameControlBackend
/**
* Helper method for pickFromCollection and dealFromCollection.
*/
public function getFromCollection_v1 (
collName :String, count :int, msgOrPropName :String, playerIndex :int,
public function getFromCollection_v2 (
collName :String, count :int, msgOrPropName :String, playerId :int,
consume :Boolean, callback :Function) :void
{
validateName(collName);
@@ -435,7 +438,7 @@ public class GameControlBackend
_ezObj.ezGameService.getFromCollection(
_ctx.getClient(), collName, consume, count, msgOrPropName,
playerIndex, listener);
playerId, listener);
}
public function alterKeyEvents_v1 (
@@ -675,16 +678,15 @@ public class GameControlBackend
}
}
/**
* Handle the arrival of a new UserCookie.
*/
protected function receivedUserCookie (cookie :UserCookie) :void
{
if (_cookieCallbacks != null) {
var arr :Array = (_cookieCallbacks[cookie.playerIndex] as Array);
var arr :Array = (_cookieCallbacks[cookie.playerId] as Array);
if (arr != null) {
delete _cookieCallbacks[cookie.playerIndex];
delete _cookieCallbacks[cookie.playerId];
for each (var fn :Function in arr) {
try {
fn(cookie.cookie);
@@ -696,6 +698,131 @@ public class GameControlBackend
}
}
// Some methods included for backwards compatability.
// Most of these were only ever used internally, so we should be able to
// get rid of them sooner rather than later.
/**
* BackCompat: turn a player index into an oid.
*/
protected function indexToId (index :int) :int
{
var name :Name = _ezObj.players[index];
if (name != null) {
var occInfo :OccupantInfo = _ezObj.getOccupantInfo(name);
if (occInfo != null) {
return occInfo.bodyOid;
}
}
return 0;
}
// OLD
protected function getFromCollection_v1 (
collName :String, count :int, msgOrPropName :String,
playerIndex :int, consume :Boolean, callback :Function) :void
{
getFromCollection_v2(collName, count, msgOrPropName,
indexToId(playerIndex), consume, callback);
}
// OLD
public function sendMessage_v1 (
messageName :String, value :Object, playerIndex :int) :void
{
sendMessage_v2(messageName, value, indexToId(playerIndex));
}
// OLD
public function getPlayerCount_v1 () :int
{
if (_ezObj.players.length == 0) {
// party game
return _ezObj.occupants.size();
} else {
return _ezObj.getPlayerCount();
}
}
// OLD
public function getPlayerNames_v1 () :Array
{
var names :Array = new Array();
if (_ezObj.players.length == 0) {
// party game, count all occupants
var itr :Iterator = _ezObj.occupantInfo.iterator();
while (itr.hasNext()) {
var occInfo :OccupantInfo = (itr.next() as OccupantInfo);
names.push(occInfo.username.toString());
}
} else {
for each (var name :Name in _ezObj.players) {
names.push((name == null) ? null : name.toString());
}
}
return names;
}
// OLD
public function getMyIndex_v1 () :int
{
if (_ezObj.players.length == 0) {
// party game
// TODO: this shouldn't be based off of the String form of the name.
var array :Array = getPlayerNames_v1();
return array.indexOf(getUsername().toString());
} else {
return _ezObj.getPlayerIndex(getUsername());
}
}
// OLD
public function getTurnHolderIndex_v1 () :int
{
return _ezObj.getPlayerIndex(_ezObj.turnHolder);
}
// OLD
public function getWinnerIndexes_v1 () :Array /* of int */
{
var arr :Array = new Array();
if (_ezObj.winners != null) {
for (var ii :int = 0; ii < _ezObj.winners.length; ii++) {
if (_ezObj.winners[ii]) {
arr.push(ii);
}
}
}
return arr;
}
// OLD
public function getUserCookie_v1 (
playerIndex :int, callback :Function) :void
{
getUserCookie_v2(indexToId(playerIndex), callback);
}
// OLD
public function endTurn_v1 (nextPlayerIndex :int) :void
{
endTurn_v2(indexToId(nextPlayerIndex));
}
// OLD
public function endGame_v1 (... winnerDexes) :void
{
var winnerIds :Array = [];
for each (var dex :int in winnerDexes) {
winnerIds.push(indexToId(dex));
}
endGame_v2.apply(this, winnerIds);
}
protected var _ctx :CrowdContext;
protected var _userListener :MessageAdapter =
@@ -15,8 +15,8 @@ import com.threerings.ezgame.util.EZObjectMarshaller;
public class UserCookie
implements DSet_Entry
{
/** The index of the player that has this cookie. */
public var playerIndex :int;
/** The id of the player that has this cookie. */
public var playerId :int;
/** The decoded cookie value. */
public var cookie :Object;
@@ -24,13 +24,13 @@ public class UserCookie
// from DSet_Entry
public function getKey () :Object
{
return playerIndex;
return playerId;
}
// from superinterface Streamable
public function readObject (ins :ObjectInputStream) :void
{
playerIndex = ins.readInt();
playerId = ins.readInt();
var ba :ByteArray = (ins.readField(ByteArray) as ByteArray);
cookie = EZObjectMarshaller.decode(ba);
}