From 1214056ebaaaf9b6adf96f9a7f3e59bf8ed5cd56 Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Tue, 23 Oct 2001 02:22:17 +0000 Subject: [PATCH] More table services! Yay! git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@527 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../threerings/parlor/client/ParlorCodes.java | 13 +- .../parlor/client/ParlorDirector.java | 18 +- .../parlor/client/ParlorService.java | 55 +++- .../parlor/client/TableDirector.java | 253 ++++++++++++++++++ .../parlor/client/TableObserver.java | 30 +++ .../com/threerings/parlor/data/Table.java | 15 +- .../parlor/server/ParlorManager.java | 19 +- 7 files changed, 370 insertions(+), 33 deletions(-) create mode 100644 src/java/com/threerings/parlor/client/TableDirector.java create mode 100644 src/java/com/threerings/parlor/client/TableObserver.java diff --git a/src/java/com/threerings/parlor/client/ParlorCodes.java b/src/java/com/threerings/parlor/client/ParlorCodes.java index 92ea6f30e..98d9755a7 100644 --- a/src/java/com/threerings/parlor/client/ParlorCodes.java +++ b/src/java/com/threerings/parlor/client/ParlorCodes.java @@ -1,5 +1,5 @@ // -// $Id: ParlorCodes.java,v 1.7 2001/10/19 22:02:36 mdb Exp $ +// $Id: ParlorCodes.java,v 1.8 2001/10/23 02:22:16 mdb Exp $ package com.threerings.parlor.client; @@ -64,25 +64,20 @@ public interface ParlorCodes extends InvocationCodes /** The response identifier for a table created response. This is * mapped by the invocation services to a call to {@link - * ParlorDirector#handleTableCreated}. */ + * TableManager#handleTableCreated}. */ public static final String TABLE_CREATED_RESPONSE = "TableCreated"; /** The response identifier for a create failed response. This is * mapped by the invocation services to a call to {@link - * ParlorDirector#handleCreateFailed}. */ + * TableManager#handleCreateFailed}. */ public static final String CREATE_FAILED_RESPONSE = "CreateFailed"; /** The message identifier for a join table request. */ public static final String JOIN_TABLE_REQUEST = "JoinTable"; - /** The response identifier for a table joined response. This is - * mapped by the invocation services to a call to {@link - * ParlorDirector#handleTableJoined}. */ - public static final String TABLE_JOINED_RESPONSE = "TableJoined"; - /** The response identifier for a join failed response. This is mapped * by the invocation services to a call to {@link - * ParlorDirector#handleJoinFailed}. */ + * TableManager#handleJoinFailed}. */ public static final String JOIN_FAILED_RESPONSE = "JoinFailed"; /** An error code returned when a user requests to join a table that diff --git a/src/java/com/threerings/parlor/client/ParlorDirector.java b/src/java/com/threerings/parlor/client/ParlorDirector.java index 55e489d30..5777275ed 100644 --- a/src/java/com/threerings/parlor/client/ParlorDirector.java +++ b/src/java/com/threerings/parlor/client/ParlorDirector.java @@ -1,5 +1,5 @@ // -// $Id: ParlorDirector.java,v 1.12 2001/10/22 23:56:25 mdb Exp $ +// $Id: ParlorDirector.java,v 1.13 2001/10/23 02:22:16 mdb Exp $ package com.threerings.parlor.client; @@ -377,22 +377,6 @@ public class ParlorDirector } } - public void handleTableCreated (int invid, int tableId) - { - } - - public void handleCreateFailed (int invid, String reason) - { - } - - public void handleTableJoined (int invid, int tableId) - { - } - - public void handleJoinFailed (int invid, String reason) - { - } - /** * The invitation class is used to track information related to * outstanding invitations generated by or targeted to this client. diff --git a/src/java/com/threerings/parlor/client/ParlorService.java b/src/java/com/threerings/parlor/client/ParlorService.java index a63ab5f75..97e69759f 100644 --- a/src/java/com/threerings/parlor/client/ParlorService.java +++ b/src/java/com/threerings/parlor/client/ParlorService.java @@ -1,5 +1,5 @@ // -// $Id: ParlorService.java,v 1.7 2001/10/11 21:08:21 mdb Exp $ +// $Id: ParlorService.java,v 1.8 2001/10/23 02:22:16 mdb Exp $ package com.threerings.parlor.client; @@ -103,4 +103,57 @@ public class ParlorService implements ParlorCodes "[inviteId=" + inviteId + "]."); return invdir.invoke(MODULE_NAME, CANCEL_INVITE_ID, args, rsptarget); } + + /** + * You probably don't want to call this directly, but want to call + * {@link TableManager#createTable}. Requests that a new table be + * created. + * + * @param client a connected, operational client instance. + * @param lobbyOid the oid of the lobby that will contain the newly + * created table. + * @param config the game config for the game to be matchmade by the + * table. + * @param rsptarget the object reference that will receive and process + * the response. + * + * @return the invocation request id of the generated request. + */ + public static int createTable ( + Client client, int lobbyOid, GameConfig config, Object rsptarget) + { + InvocationDirector invdir = client.getInvocationDirector(); + Object[] args = new Object[] { new Integer(lobbyOid), config }; + Log.info("Sending table creation request " + + "[lobbyOid=" + lobbyOid + ", config=" + config + "]."); + return invdir.invoke( + MODULE_NAME, CREATE_TABLE_REQUEST, args, rsptarget); + } + + /** + * You probably don't want to call this directly, but want to call + * {@link TableManager#joinTable}. Requests that the current user + * be added to the specified table at the specified position. + * + * @param client a connected, operational client instance. + * @param tableId the unique id of the table to which this user wishes + * to be added. + * @param position the position at the table to which this user desires + * to be added. + * @param rsptarget the object reference that will receive and process + * the response. + * + * @return the invocation request id of the generated request. + */ + public static int joinTable ( + Client client, int tableId, int position, Object rsptarget) + { + InvocationDirector invdir = client.getInvocationDirector(); + Object[] args = new Object[] { new Integer(tableId), + new Integer(position) }; + Log.info("Sending join table request " + + "[tableId=" + tableId + ", position=" + position + "]."); + return invdir.invoke( + MODULE_NAME, JOIN_TABLE_REQUEST, args, rsptarget); + } } diff --git a/src/java/com/threerings/parlor/client/TableDirector.java b/src/java/com/threerings/parlor/client/TableDirector.java new file mode 100644 index 000000000..17a9c0346 --- /dev/null +++ b/src/java/com/threerings/parlor/client/TableDirector.java @@ -0,0 +1,253 @@ +// +// $Id: TableDirector.java,v 1.1 2001/10/23 02:22:16 mdb Exp $ + +package com.threerings.parlor.client; + +import com.threerings.presents.dobj.ElementAddedEvent; +import com.threerings.presents.dobj.ElementUpdatedEvent; +import com.threerings.presents.dobj.ElementRemovedEvent; +import com.threerings.presents.dobj.SetListener; + +import com.threerings.crowd.data.BodyObject; +import com.threerings.crowd.data.PlaceObject; + +import com.threerings.parlor.Log; +import com.threerings.parlor.data.Table; +import com.threerings.parlor.data.TableLobbyObject; +import com.threerings.parlor.game.GameConfig; +import com.threerings.parlor.util.ParlorContext; + +/** + * As tables are created and managed within the scope of a place (a + * lobby), we want to fold the table management functionality into the + * standard hierarchy of place controllers that deal with place-related + * functionality on the client. Thus, instead of forcing places that + * expect to have tables to extend a TableLobbyController or + * something similar, we instead provide the table manager which can be + * instantiated by the place controller (or specific table related views) + * to handle the table matchmaking services. + * + *

Entites that do so, will need to implement the {@link + * TableObserver} interface so that the table manager can notify them when + * table related things happen. + * + *

The table services expect that the place object being used as a + * lobby in which the table matchmaking takes place implements the {@link + * TableLobbyObject} interface. + */ +public class TableManager + implements SetListener +{ + /** + * Creates a new table manager to manage tables with the specified + * observer which will receive callbacks when interesting table + * related things happen. + * + * @param ctx the parlor context in use by the client. + * @param tableField the field name of the distributed set that + * contains the tables we will be managing. + * @param observer the entity that will receive callbacks when things + * happen to the tables. + */ + public TableManager ( + ParlorContext ctx, String tableField, TableObserver observer) + { + // keep track of this stuff + _ctx = ctx; + _tableField = tableField; + _observer = observer; + } + + /** + * This must be called by the entity that uses the table manager when + * the using entity prepares to enter and display a place. It is + * assumed that the client is already subscribed to the provided place + * object. + */ + public void willEnterPlace (PlaceObject place) + { + // add ourselves as a listener to the place object + place.addListener(this); + + // and remember this for later + _lobby = place; + } + + /** + * This must be called by the entity that uses the table manager when + * the using entity has left and is done displaying a place. + */ + public void didLeavePlace (PlaceObject place) + { + // remove our listenership + place.removeListener(this); + + // clear out our lobby reference + _lobby = null; + } + + /** + * Sends a request to create a table with the specified game + * configuration. This user will become the owner of this table and + * will be added to the first position in the table. The response will + * be communicated via the {@link TableObserver} interface. + */ + public void createTable (GameConfig config) + { + // if we're already in a table, refuse the request + if (_ourTable != null) { + Log.warning("Ignoring request to create table as we're " + + "already in a table [table=" + _ourTable + "]."); + return; + } + + // make sure we're currently in a place + if (_lobby == null) { + Log.warning("Requested to create a table but we're not " + + "currently in a place [config=" + config + "]."); + return; + } + + // go ahead and issue the create request + ParlorService.createTable( + _ctx.getClient(), _lobby.getOid(), config, this); + } + + /** + * Sends a request to join the specified table at the specified + * position. The response will be communicated via the {@link + * TableObserver} interface. + */ + public void joinTable (int tableId, int position) + { + // if we're already in a table, refuse the request + if (_ourTable != null) { + Log.warning("Ignoring request to join table as we're " + + "already in a table [table=" + _ourTable + "]."); + return; + } + + // make sure we're currently in a place + if (_lobby == null) { + Log.warning("Requested to join a table but we're not " + + "currently in a place [tableId=" + tableId + "]."); + return; + } + + // go ahead and issue the create request + ParlorService.joinTable( + _ctx.getClient(), tableId, position, this); + } + + // documentation inherited + public void elementAdded (ElementAddedEvent event) + { + if (event.getName().equals(_tableField)) { + Table table = (Table)event.getElement(); + _observer.tableAdded(table); + + // check to see if we just joined a table + checkForOurTable(table); + } + } + + // documentation inherited + public void elementUpdated (ElementUpdatedEvent event) + { + if (event.getName().equals(_tableField)) { + Table table = (Table)event.getElement(); + _observer.tableUpdated(table); + + // check to see if we just joined or left a table + checkForOurTable(table); + } + } + + // documentation inherited + public void elementRemoved (ElementRemovedEvent event) + { + if (event.getName().equals(_tableField)) { + Integer tableId = (Integer)event.getKey(); + _observer.tableRemoved(tableId.intValue()); + + // check to see if our table just disappeared + if (_ourTable != null && tableId.equals(_ourTable.tableId)) { + _ourTable = null; + } + } + } + + /** + * Called by the invocation services when a table creation request was + * received by the server and the table was successfully created. + * + * @param invid the invocation id of the invitation request. + */ + public void handleTableCreated (int invid, int tableId) + { + // nothing much to do here + Log.info("Table creation succeeded [tableId=" + tableId + "]."); + } + + /** + * Called by the invocation services when a table creation request + * failed or was rejected for some reason. + * + * @param invid the invocation id of the creation request. + * @param reason a reason code explaining the failure. + */ + public void handleCreateFailed (int invid, String reason) + { + Log.warning("Table creation failed [reason=" + reason + "]."); + } + + /** + * Called by the invocation services when a join table request failed + * or was rejected for some reason. + * + * @param invid the invocation id of the join request. + * @param reason a reason code explaining the failure. + */ + public void handleJoinFailed (int invid, String reason) + { + Log.warning("Join table failed [reason=" + reason + "]."); + } + + /** + * Checks to see if we're a member of this table and notes it as our + * table, if so. + */ + protected void checkForOurTable (Table table) + { + // if this is the same table as our table, clear out our table + // reference and allow it to be added back if we are still in the + // table + if (table.equals(_ourTable)) { + _ourTable = null; + } + + // look for our username in the occupants array + BodyObject self = (BodyObject)_ctx.getClient().getClientObject(); + for (int i = 0; i < table.occupants.length; i++) { + if (self.username.equals(table.occupants[i])) { + _ourTable = table; + return; + } + } + } + + /** A context by which we can access necessary client services. */ + protected ParlorContext _ctx; + + /** The place object in which we're currently managing tables. */ + protected PlaceObject _lobby; + + /** The field name of the distributed set that contains our tables. */ + protected String _tableField; + + /** The entity that we talk to when table stuff happens. */ + protected TableObserver _observer; + + /** The table of which we are a member if any. */ + protected Table _ourTable; +} diff --git a/src/java/com/threerings/parlor/client/TableObserver.java b/src/java/com/threerings/parlor/client/TableObserver.java new file mode 100644 index 000000000..97253fbbe --- /dev/null +++ b/src/java/com/threerings/parlor/client/TableObserver.java @@ -0,0 +1,30 @@ +// +// $Id: TableObserver.java,v 1.1 2001/10/23 02:22:16 mdb Exp $ + +package com.threerings.parlor.client; + +import com.threerings.parlor.data.Table; + +/** + * The {@link TableManager} converts distributed object events into higher + * level callbacks to implementers of this interface, which are expected + * to render these events sensically in a user interface. + */ +public interface TableObserver +{ + /** + * Called when a new table is created. + */ + public void tableAdded (Table table); + + /** + * Called when something has changed about a table (occupant list + * updated, state changed from matchmaking to in-play, etc.). + */ + public void tableUpdated (Table table); + + /** + * Called when a table goes away. + */ + public void tableRemoved (int tableId); +} diff --git a/src/java/com/threerings/parlor/data/Table.java b/src/java/com/threerings/parlor/data/Table.java index d0c70ec49..5ce707723 100644 --- a/src/java/com/threerings/parlor/data/Table.java +++ b/src/java/com/threerings/parlor/data/Table.java @@ -1,5 +1,5 @@ // -// $Id: Table.java,v 1.3 2001/10/22 23:56:01 mdb Exp $ +// $Id: Table.java,v 1.4 2001/10/23 02:22:16 mdb Exp $ package com.threerings.parlor.data; @@ -181,6 +181,19 @@ public class Table _tconfig = (TableConfig)config; } + /** + * Returns true if this table is equal to the supplied object (which + * must be a table with the same table id). + */ + public boolean equals (Object other) + { + if (other != null && other instanceof Table) { + return ((Table)other).tableId.equals(tableId); + } else { + return false; + } + } + /** * Generates a string representation of this table instance. */ diff --git a/src/java/com/threerings/parlor/server/ParlorManager.java b/src/java/com/threerings/parlor/server/ParlorManager.java index 2936e212e..e9cb513db 100644 --- a/src/java/com/threerings/parlor/server/ParlorManager.java +++ b/src/java/com/threerings/parlor/server/ParlorManager.java @@ -1,5 +1,5 @@ // -// $Id: ParlorManager.java,v 1.12 2001/10/19 22:02:36 mdb Exp $ +// $Id: ParlorManager.java,v 1.13 2001/10/23 02:22:17 mdb Exp $ package com.threerings.parlor.server; @@ -240,10 +240,20 @@ public class ParlorManager // create a brand spanking new table Table table = new Table(placeOid, config); - // and stick it into the table lobby object + // stick the creator into position zero + String error = table.setOccupant(0, creator.username); + if (error != null) { + Log.warning("Unable to add creator to position zero of " + + "table!? [table=" + table + + ", creator=" + creator + "]."); + // bail out now and abort the table creation process + throw new ServiceFailedException(error); + } + + // stick the table into the table lobby object tlobj.addToTables(table); - // also stick the table into our tables table + // also stick it into our tables table _tables.put(table.getTableId(), table); // finally let the caller know what the new table id is @@ -373,8 +383,7 @@ public class ParlorManager CrowdServer.omgr.getObject(table.lobbyOid); if (tlobj == null) { Log.warning("Can't update in-play table as lobby's gone " + - "missing [table=" + table + - ", gameOid=" + plobj.getOid() + "]."); + "missing [table=" + table + "]."); return; } tlobj.updateTables(table);