Checkpoint: converting parlor stuff to actionscript.

git-svn-id: svn+ssh://src.earth.threerings.net/vilya/trunk@30 c613c5cb-e716-0410-b11b-feb51c14d237
This commit is contained in:
Ray Greenwell
2006-07-28 02:47:21 +00:00
parent b82ab59b1d
commit 7ee319bb2b
33 changed files with 3870 additions and 0 deletions
@@ -0,0 +1,63 @@
//
// $Id: ParlorCodes.java 3359 2005-02-19 22:38:06Z mdb $
//
// Narya library - tools for developing networked games
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/narya/
//
// 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.parlor.data {
import com.threerings.presents.data.InvocationCodes;
/**
* Contains codes used by the parlor invocation services.
*/
public class ParlorCodes extends InvocationCodes
{
/** The response code for an accepted invitation. */
public static const INVITATION_ACCEPTED :int = 0;
/** The response code for a refused invitation. */
public static const INVITATION_REFUSED :int = 1;
/** The response code for a countered invitation. */
public static const INVITATION_COUNTERED :int = 2;
/** An error code explaining that an invitation was rejected because
* the invited user was not online at the time the invitation was
* received. */
public static const INVITEE_NOT_ONLINE :String = "m.invitee_not_online";
/** An error code returned when a user requests to join a table that
* doesn't exist. */
public static const NO_SUCH_TABLE :String = "m.no_such_table";
/** An error code returned when a user requests to join a table at a
* position that is not valid. */
public static const INVALID_TABLE_POSITION :String =
"m.invalid_table_position";
/** An error code returned when a user requests to join a table in a
* position that is already occupied. */
public static const TABLE_POSITION_OCCUPIED :String =
"m.table_position_occupied";
/** An error code returned when a user requests to leave a table that
* they were not sitting at in the first place. */
public static const NOT_AT_TABLE :String = "m.not_at_table";
}
}
@@ -0,0 +1,143 @@
//
// $Id: ParlorMarshaller.java 4145 2006-05-24 01:24:24Z ray $
//
// Narya library - tools for developing networked games
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/narya/
//
// 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.parlor.data {
import com.threerings.parlor.client.ParlorService;
import com.threerings.parlor.data.TableConfig;
import com.threerings.parlor.game.data.GameConfig;
import com.threerings.presents.client.Client;
import com.threerings.presents.client.InvocationService;
import com.threerings.presents.client.InvocationService_InvocationListener;
import com.threerings.presents.data.InvocationMarshaller;
import com.threerings.presents.dobj.InvocationResponseEvent;
import com.threerings.util.Name;
/**
* Provides the implementation of the {@link ParlorService} 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 ParlorMarshaller extends InvocationMarshaller
implements ParlorService
{
/** The method id used to dispatch {@link #cancel} requests. */
public static const CANCEL :int = 1;
// documentation inherited from interface
public function cancel (arg1 :Client, arg2 :int, arg3 :InvocationService_InvocationListener) :void
{
var listener3 :InvocationMarshaller_ListenerMarshaller =
new InvocationMarshaller_ListenerMarshaller();
listener3.listener = arg3;
sendRequest(arg1, CANCEL, [
Integer.valueOf(arg2), listener3
]);
}
/** The method id used to dispatch {@link #createTable} requests. */
public static const CREATE_TABLE :int = 2;
// documentation inherited from interface
public function createTable (arg1 :Client, arg2 :int, arg3 :TableConfig, arg4 :GameConfig, arg5 :ParlorService_TableListener) :void
{
var listener5 :ParlorMarshaller_TableMarshaller =
new ParlorMarshaller_TableMarshaller();
listener5.listener = arg5;
sendRequest(arg1, CREATE_TABLE, [
Integer.valueOf(arg2), arg3, arg4, listener5
]);
}
/** The method id used to dispatch {@link #invite} requests. */
public static const INVITE :int = 3;
// documentation inherited from interface
public function invite (arg1 :Client, arg2 :Name, arg3 :GameConfig, arg4 :ParlorService_InviteListener) :void
{
var listener4 :ParlorMarshaller_InviteMarshaller =
new ParlorMarshaller_InviteMarshaller();
listener4.listener = arg4;
sendRequest(arg1, INVITE, [
arg2, arg3, listener4
]);
}
/** The method id used to dispatch {@link #joinTable} requests. */
public static const JOIN_TABLE :int = 4;
// documentation inherited from interface
public function joinTable (arg1 :Client, arg2 :int, arg3 :int, arg4 :int, arg5 :InvocationService_InvocationListener) :void
{
var listener5 :InvocationMarshaller_ListenerMarshaller listener5 =
new InvocationMarshaller_ListenerMarshaller();
listener5.listener = arg5;
sendRequest(arg1, JOIN_TABLE, [
Integer.valueOf(arg2), Integer.valueOf(arg3), Integer.valueOf(arg4), listener5
]);
}
/** The method id used to dispatch {@link #leaveTable} requests. */
public static const LEAVE_TABLE :int = 5;
// documentation inherited from interface
public function leaveTable (arg1 :Client, arg2 :int, arg3 :int, arg4 :InvocationService_InvocationListener) :void
{
var listener4 :InvocationMarshaller_ListenerMarshaller =
new InvocationMarshaller_ListenerMarshaller();
listener4.listener = arg4;
sendRequest(arg1, LEAVE_TABLE, [
Integer.valueOf(arg2), Integer.valueOf(arg3), listener4
]);
}
/** The method id used to dispatch {@link #respond} requests. */
public static const RESPOND :int = 6;
// documentation inherited from interface
public function respond (arg1 :Client, arg2 :int, arg3 :int, arg4 :Object, arg5 :InvocationService_InvocationListener) :void
{
var listener5 :InvocationMarshaller_ListenerMarshaller =
new InvocationMarshallerListenerMarshaller();
listener5.listener = arg5;
sendRequest(arg1, RESPOND, [
Integer.valueOf(arg2), Integer.valueOf(arg3), arg4, listener5
]);
}
/** The method id used to dispatch {@link #startSolitaire} requests. */
public static const START_SOLITAIRE :int = 7;
// documentation inherited from interface
public function startSolitaire (arg1 :Client, arg2 :GameConfig, arg3 :InvocationService_ConfirmListener) :void
{
var listener3 :InvocationMarshaller_ConfirmMarshaller =
new InvocationMarshaller_ConfirmMarshaller();
listener3.listener = arg3;
sendRequest(arg1, START_SOLITAIRE, [
arg2, listener3
]);
}
}
}
@@ -0,0 +1,39 @@
package com.threerings.parlor.data {
import com.threerings.util.Integer;
import com.threerings.presents.data.InvocationMarshaller_ListenerMarshaller;
public class ParlorMarshaller_InviteMarshaller
extends InvocationMarshaller_ListenerMarshaller
implements InviteListener
{
/** The method id used to dispatch {@link #inviteReceived}
* responses. */
public static const INVITE_RECEIVED :int = 1;
// documentation inherited from interface
public function inviteReceived (arg1 :int) :void
{
_invId = null;
omgr.postEvent(new InvocationResponseEvent(
callerOid, requestId, INVITE_RECEIVED,
[ Integer.valueOf(arg1) ]));
}
// documentation inherited
override public function dispatchResponse (methodId :int, args :Array) :void
{
switch (methodId) {
case INVITE_RECEIVED:
(listener as InviteListener).inviteReceived(
(args[0] as Integer).value);
return;
default:
super.dispatchResponse(methodId, args);
return;
}
}
}
}
@@ -0,0 +1,39 @@
package com.threerings.parlor.data {
import com.threerings.util.Integer;
import com.threerings.presents.data.InvocationMarshaller_ListenerMarshaller;
public class ParlorMarshaller_TableMarshaller
extends InvocationMarshaller_ListenerMarshaller
implements TableListener
{
/** The method id used to dispatch {@link #tableCreated}
* responses. */
public static const TABLE_CREATED :int = 1;
// documentation inherited from interface
public function tableCreated (arg1 :int) :void
{
_invId = null;
omgr.postEvent(new InvocationResponseEvent(
callerOid, requestId, TABLE_CREATED,
[ Integer.valueOf(arg1) ]));
}
// documentation inherited
override public function dispatchResponse (methodId :int, args :Array) :void
{
switch (methodId) {
case TABLE_CREATED:
(listener as TableListener).tableCreated(
(args[0] as Integer).value);
return;
default:
super.dispatchResponse(methodId, args);
return;
}
}
}
}
+378
View File
@@ -0,0 +1,378 @@
//
// $Id: Table.java 4191 2006-06-13 22:42:20Z ray $
//
// Narya library - tools for developing networked games
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/narya/
//
// 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.parlor.data {
import com.threerings.util.Hashable;
import com.threerings.util.Name;
import com.threerings.util.StringBuilder;
import com.threerings.io.ObjectInputStream;
import com.threerings.io.ObjectOutputStream;
import com.threerings.presents.dobj.DSet;
import com.threerings.presents.dobj.DSet_Entry;
import com.threerings.crowd.data.BodyObject;
import com.threerings.parlor.data.ParlorCodes;
import com.threerings.parlor.game.data.GameConfig;
import com.threerings.parlor.game.data.PartyGameConfig;
/**
* This class represents a table that is being used to matchmake a game by
* the Parlor services.
*/
public class Table
implements Hashable, DSet_Entry, ParlorCodes
{
/** The unique identifier for this table. */
public var tableId :int;
/** The object id of the lobby object with which this table is
* associated. */
public var lobbyOid :int;
/** The oid of the game that was created from this table or -1 if the
* table is still in matchmaking mode. */
public var gameOid :int = -1;
/** An array of the usernames of the occupants of this table (some
* slots may not be filled), or null if a party game. */
public var occupants :TypedArray /* of Name */;
/** The body oids of the occupants of this table, or null if a party game.
* (This is not propagated to remote instances.) */
public var bodyOids :TypedArray /* of int */;
/** The game config for the game that is being matchmade. */
public var config :GameConfig;
/** The table configuration object. */
public var tconfig :TableConfig;
/** Suitable for unserialization. */
public function Table ()
{
}
/**
* Returns true if there is no one sitting at this table.
*/
public function isEmpty () :Boolean
{
for (var ii :int = 0; ii < bodyOids.length; ii++) {
if ((bodyOids[ii] as int) !== 0) {
return false;
}
}
return true;
}
/**
* Count the number of players currently occupying this table.
*/
public function getOccupiedCount () :int
{
var count :int = 0;
for (var ii :int = 0; ii < occupants.length; ii++) {
if (occupants[ii] != null) {
count++;
}
}
return count;
}
/**
* Once a table is ready to play (see {@link #mayBeStarted} and {@link
* #shouldBeStarted}), the players array can be fetched using this
* method. It will return an array containing the usernames of all of
* the players in the game, sized properly and with each player in the
* appropriate position.
*/
public function getPlayers () :Array
{
if (isPartyGame()) {
return occupants;
}
// create and populate the players array
var players :Array = new Array();
for (var ii :int = 0; ii < occupants.length; ii++) {
if (occupants[ii] != null) {
players.push(occupants[ii]);
}
}
return players;
}
/**
* For a team game, get the team member indices of the compressed
* players array returned by getPlayers().
*/
public function getTeamMemberIndices () :Array /* of Array of int */
{
var teams :Array = tconfig.teamMemberIndices;
if (teams == null) {
return null;
}
// TODO
// compress the team indexes down
ArrayIntSet set = new ArrayIntSet();
int[][] newTeams = new int[teams.length][];
Name[] players = getPlayers();
for (int ii=0; ii < teams.length; ii++) {
set.clear();
for (int jj=0; jj < teams[ii].length; jj++) {
Name occ = occupants[teams[ii][jj]];
if (occ != null) {
set.add(ListUtil.indexOf(players, occ));
}
}
newTeams[ii] = set.toIntArray();
}
return newTeams;
}
/**
* Return true if the game is a party game.
*/
public function isPartyGame () :Boolean
{
return (PartyGameConfig.NOT_PARTY_GAME != getPartyGameType());
}
/**
* Get the type of party game being played at this table, or
* PartyGameConfig.NOT_PARTY_GAME.
*/
public function getPartyGameType () :int
{
if (config is PartyGameConfig) {
return (config as PartyGameConfig).getPartyGameType();
} else {
return PartyGameConfig.NOT_PARTY_GAME;
}
}
/**
* Requests to seat the specified user at the specified position in
* this table.
*
* @param position the position in which to seat the user.
* @param occupant the occupant to set.
*
* @return null if the user was successfully seated, a string error
* code explaining the failure if the user was not able to be seated
* at that position.
*/
public function setOccupant (position :int, occupant :BodyObject) :String
{
// make sure the requested position is a valid one
if (position >= tconfig.desiredPlayerCount || position < 0) {
return INVALID_TABLE_POSITION;
}
// make sure the requested position is not already occupied
if (occupants[position] != null) {
return TABLE_POSITION_OCCUPIED;
}
// otherwise all is well, stick 'em in
setOccupantPos(position, occupant);
return null;
}
/**
* This method is used for party games, it does no bounds checking
* or verification of the player's ability to join, if you are unsure
* you should call 'setOccupant'.
*/
public function setOccupantPos (position :int, occupant :BodyObject) :void
{
occupants[position] = occupant.getVisibleName();
bodyOids[position] = occupant.getOid();
}
/**
* Requests that the specified user be removed from their seat at this
* table.
*
* @return true if the user was seated at the table and has now been
* removed, false if the user was never seated at the table in the
* first place.
*/
public function clearOccupant (username :Name) :void
{
var dex :int = ArrayUtil.indexOf(occupants, username);
if (dex != -1) {
clearOccupantPos(dex);
return true;
}
return false;
}
/**
* Requests that the user identified by the specified body object id
* be removed from their seat at this table.
*
* @return true if the user was seated at the table and has now been
* removed, false if the user was never seated at the table in the
* first place.
*/
public function clearOccupant (bodyOid :int) :Boolean
{
var dex :int = ArrayUtil.indexOf(bodyOids, bodyOid);
if (dex != -1) {
clearOccupantPos(dex);
return true;
}
return false;
}
/**
* Called to clear an occupant at the specified position.
* Only call this method if you know what you're doing.
*/
public function clearOccupantPos (position :int) :void
{
occupants[position] = null;
bodyOids[position] = 0;
}
/**
* Returns true if this table has a sufficient number of occupants
* that the game can be started.
*/
public function mayBeStarted () :Boolean
{
if (tconfig.teamMemberIndices == null) {
// for a normal game, just check to see if we're past the minimum
return tconfig.minimumPlayerCount <= getOccupiedCount();
} else {
// for a team game, make sure each team has the minimum players
var teams :Array = tconfig.teamMemberIndices;
for (var ii :int = 0; ii < teams.length; ii++) {
var teamCount :int = 0;
var members :Array = (teams[ii] as Array);
for (var jj :int = 0; jj < members.length; jj++) {
if (occupants[members[jj]] != null) {
teamCount++;
}
}
if (teamCount < tconfig.minimumPlayerCount) {
return false;
}
}
return true;
}
}
/**
* Returns true if sufficient seats are occupied that the game should
* be automatically started.
*/
public function shouldBeStarted () :Boolean
{
return tconfig.desiredPlayerCount <= getOccupiedCount();
}
/**
* Returns true if this table is in play, false if it is still being
* matchmade.
*/
public function inPlay () :Boolean
{
return gameOid != -1;
}
// documentation inherited
public function getKey () :Object
{
return tableId;
}
// from Hashable
public function equals (other :Object) :Boolean
{
return (other is Table) &&
(tableId == ((Table) other).tableId);
}
// from Hashable
public function hashCode () :int
{
return tableId;
}
// from Streamable
public function writeObject (out :ObjectOutputStream) :void
{
out.writeInt(tableId);
out.writeInt(lobbyOid);
out.writeInt(gameOid);
out.writeObject(occupants);
out.writeObject(config);
out.writeObject(tconfig);
}
// from Streamable
public function readObject (ins :ObjectInputStream) :void
{
tableId = ins.readInt();
lobbyOid = ins.readInt();
gameOid = ins.readInt();
occupants = (ins.readObject() as TypedArray);
config = (ins.readObject() as GameConfig);
tconfig = (ins.readObject() as TableConfig);
}
/**
* Generates a string representation of this table instance.
*/
public function toString () :String
{
var buf :StringBuilder = new StringBuilder();
buf.append(ClassUtil.shortClassName(this));
buf.append(" [");
toStringBuf(buf);
buf.append("]");
return buf.toString();
}
/**
* Helper method for toString, ripe for overrideability.
*/
protected function toStringBuf (buf :StringBuilder) :void
{
buf.append("tableId=").append(tableId);
buf.append(", lobbyOid=").append(lobbyOid);
buf.append(", gameOid=").append(gameOid);
buf.append(", occupants=").append(occupants.join());
buf.append(", config=").append(config);
}
}
}
@@ -0,0 +1,72 @@
//
// $Id: TableConfig.java 3604 2005-06-17 20:25:28Z ray $
//
// Narya library - tools for developing networked games
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/narya/
//
// 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.parlor.data {
import com.threerings.io.ObjectInputStream;
import com.threerings.io.ObjectOutputStream;
import com.threerings.io.Streamable;
import com.threerings.io.TypedArray;
/**
* Table configuration parameters for a game that is to be matchmade
* using the table services.
*/
public class TableConfig
implements Streamable
{
/** The total number of players that are desired for the table,
* or -1 for a party game. For team games, this should be set to the
* total number of players overall, as teams may be unequal. */
public var desiredPlayerCount :int;
/** The minimum number of players needed overall (or per-team if a
* team-based game) for the game to start at the creator's discretion. */
public var minimumPlayerCount :int;
/** If non-null, indicates that this is a team-based game and contains
* the team assignments for each player. For example, a game with
* three players in two teams- players 0 and 2 versus player 1- would
* have { {0, 2}, {1} }; */
public var teamMemberIndices :TypedArray;
/** Whether the table is "private". */
public var privateTable :Boolean;
// from Streamable
public function writeObject (out :ObjectOutputStream) :void
{
out.writeInt(desiredPlayerCount);
out.writeInt(minimumPlayerCount);
out.writeField(teamMemberIndices);
out.writeBoolean(privateTable);
}
// from Streamable
public function readObject (ins :ObjectInputStream) :void
{
desiredPlayerCount = ins.readInt();
minimumPlayerCount = ins.readInt();
teamMemberIndices = (ins.readField("[[I") as TypedArray);
privateTable = ins.readBoolean();
}
}
}
@@ -0,0 +1,57 @@
//
// $Id: TableLobbyObject.java 4145 2006-05-24 01:24:24Z ray $
//
// Narya library - tools for developing networked games
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/narya/
//
// 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.parlor.data {
import com.threerings.presents.dobj.DSet;
/**
* This interface must be implemented by the place object used by a lobby
* that wishes to make use of the table services.
*/
public interface TableLobbyObject
{
/**
* Returns a reference to the distributed set instance that will be
* holding the tables.
*/
function getTables () :DSet;
/**
* Adds the supplied table instance to the tables set (using the
* appropriate distributed object mechanisms).
*/
function addToTables (table :Table) :void;
/**
* Updates the value of the specified table instance in the tables
* distributed set (using the appropriate distributed object
* mechanisms).
*/
function updateTables (table :Table) :void;
/**
* Removes the table instance that matches the specified key from the
* tables set (using the appropriate distributed object mechanisms).
*/
function removeFromTables (key :Object) :void;
}
}