More progress on table services (can leave a table, things start correctly

now, and much much more).


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@529 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2001-10-23 20:23:29 +00:00
parent 690940db47
commit 246987893d
8 changed files with 312 additions and 31 deletions
@@ -1,5 +1,5 @@
//
// $Id: ParlorCodes.java,v 1.8 2001/10/23 02:22:16 mdb Exp $
// $Id: ParlorCodes.java,v 1.9 2001/10/23 20:23:29 mdb Exp $
package com.threerings.parlor.client;
@@ -80,6 +80,14 @@ public interface ParlorCodes extends InvocationCodes
* TableManager#handleJoinFailed}. */
public static final String JOIN_FAILED_RESPONSE = "JoinFailed";
/** The message identifier for a leave table request. */
public static final String LEAVE_TABLE_REQUEST = "LeaveTable";
/** The response identifier for a leave failed response. This is
* mapped by the invocation services to a call to {@link
* TableManager#handleLeaveFailed}. */
public static final String LEAVE_FAILED_RESPONSE = "LeaveFailed";
/** An error code returned when a user requests to join a table that
* doesn't exist. */
public static final String NO_SUCH_TABLE = "m.no_such_table";
@@ -93,4 +101,8 @@ public interface ParlorCodes extends InvocationCodes
* position that is already occupied. */
public static final String TABLE_POSITION_OCCUPIED =
"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 final String NOT_AT_TABLE = "m.not_at_table";
}
@@ -1,5 +1,5 @@
//
// $Id: ParlorService.java,v 1.8 2001/10/23 02:22:16 mdb Exp $
// $Id: ParlorService.java,v 1.9 2001/10/23 20:23:29 mdb Exp $
package com.threerings.parlor.client;
@@ -156,4 +156,28 @@ public class ParlorService implements ParlorCodes
return invdir.invoke(
MODULE_NAME, JOIN_TABLE_REQUEST, args, rsptarget);
}
/**
* You probably don't want to call this directly, but want to call
* {@link TableManager#leaveTable}. Requests that the current user
* be removed from the specified table.
*
* @param client a connected, operational client instance.
* @param tableId the unique id of the table from which this user
* wishes to be removed.
* @param rsptarget the object reference that will receive and process
* the response.
*
* @return the invocation request id of the generated request.
*/
public static int leaveTable (
Client client, int tableId, Object rsptarget)
{
InvocationDirector invdir = client.getInvocationDirector();
Object[] args = new Object[] { new Integer(tableId) };
Log.info("Sending leave table request " +
"[tableId=" + tableId + "].");
return invdir.invoke(
MODULE_NAME, LEAVE_TABLE_REQUEST, args, rsptarget);
}
}
@@ -0,0 +1,20 @@
//
// $Id: SeatednessObserver.java,v 1.1 2001/10/23 20:23:29 mdb Exp $
package com.threerings.parlor.client;
/**
* Entites that wish to hear about when we sit down at a table or stand up
* from a table can implement this interface and register themselves with
* the {@link TableManager}.
*/
public interface SeatednessObserver
{
/**
* Called when this client sits down at or stands up from a table.
*
* @param isSeated true if the client is now seated at a table, false
* if they are now no longer seated at a table.
*/
public void seatednessDidChange (boolean isSeated);
}
@@ -1,8 +1,10 @@
//
// $Id: TableDirector.java,v 1.1 2001/10/23 02:22:16 mdb Exp $
// $Id: TableDirector.java,v 1.2 2001/10/23 20:23:29 mdb Exp $
package com.threerings.parlor.client;
import java.util.ArrayList;
import com.threerings.presents.dobj.ElementAddedEvent;
import com.threerings.presents.dobj.ElementUpdatedEvent;
import com.threerings.presents.dobj.ElementRemovedEvent;
@@ -86,6 +88,35 @@ public class TableManager
_lobby = null;
}
/**
* Requests that the specified observer be added to the list of
* observers that are notified when this client sits down at or stands
* up from a table.
*/
public void addSeatednessObserver (SeatednessObserver observer)
{
_seatedObservers.add(observer);
}
/**
* Requests that the specified observer be removed from to the list of
* observers that are notified when this client sits down at or stands
* up from a table.
*/
public void removeSeatednessObserver (SeatednessObserver observer)
{
_seatedObservers.remove(observer);
}
/**
* Returns true if this client is currently seated at a table, false
* if they are not.
*/
public boolean isSeated ()
{
return (_ourTable != null);
}
/**
* Sends a request to create a table with the specified game
* configuration. This user will become the owner of this table and
@@ -139,15 +170,35 @@ public class TableManager
_ctx.getClient(), tableId, position, this);
}
/**
* Sends a request to leave the specified table at which we are
* presumably seated. The response will be communicated via the {@link
* TableObserver} interface.
*/
public void leaveTable (int tableId)
{
// make sure we're currently in a place
if (_lobby == null) {
Log.warning("Requested to leave a table but we're not " +
"currently in a place [tableId=" + tableId + "].");
return;
}
// go ahead and issue the create request
ParlorService.leaveTable(_ctx.getClient(), tableId, 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);
checkSeatedness(table);
// now let the observer know what's up
_observer.tableAdded(table);
}
}
@@ -156,10 +207,12 @@ public class TableManager
{
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);
checkSeatedness(table);
// now let the observer know what's up
_observer.tableUpdated(table);
}
}
@@ -168,12 +221,15 @@ public class TableManager
{
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;
notifySeatedness(false);
}
// now let the observer know what's up
_observer.tableRemoved(tableId.intValue());
}
}
@@ -217,8 +273,10 @@ public class TableManager
* Checks to see if we're a member of this table and notes it as our
* table, if so.
*/
protected void checkForOurTable (Table table)
protected void checkSeatedness (Table table)
{
Table oldTable = _ourTable;
// 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
@@ -231,7 +289,35 @@ public class TableManager
for (int i = 0; i < table.occupants.length; i++) {
if (self.username.equals(table.occupants[i])) {
_ourTable = table;
return;
break;
}
}
// if nothing changed, bail now
if (oldTable == _ourTable ||
(oldTable != null && oldTable.equals(_ourTable))) {
return;
}
// otherwise notify the observers
notifySeatedness(_ourTable != null);
}
/**
* Notifies the seatedness observers of a seatedness change.
*/
protected void notifySeatedness (boolean isSeated)
{
int slength = _seatedObservers.size();
for (int i = 0; i < slength; i++) {
SeatednessObserver observer = (SeatednessObserver)
_seatedObservers.get(i);
try {
observer.seatednessDidChange(isSeated);
} catch (Exception e) {
Log.warning("Observer choked in seatednessDidChange() " +
"[observer=" + observer + "].");
Log.logStackTrace(e);
}
}
}
@@ -250,4 +336,8 @@ public class TableManager
/** The table of which we are a member if any. */
protected Table _ourTable;
/** An array of entities that want to hear about when we stand up or
* sit down. */
protected ArrayList _seatedObservers = new ArrayList();
}
+57 -4
View File
@@ -1,5 +1,5 @@
//
// $Id: Table.java,v 1.4 2001/10/23 02:22:16 mdb Exp $
// $Id: Table.java,v 1.5 2001/10/23 20:23:29 mdb Exp $
package com.threerings.parlor.data;
@@ -31,7 +31,7 @@ public class Table
/** The oid of the game that was created from this table or -1 if the
* table is still in matchmaking mode. */
public int gameOid;
public int gameOid = -1;
/** An array of the usernames of the occupants of this table (some
* slots may not be filled. */
@@ -143,13 +143,66 @@ public class Table
return null;
}
/**
* 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 boolean clearOccupant (String username)
{
for (int i = 0; i < occupants.length; i++) {
if (username.equals(occupants[i])) {
occupants[i] = "";
return true;
}
}
return false;
}
/**
* Returns true if this table has occupants in all of the desired
* positions and should be started.
*/
public boolean readyToStart ()
{
return false;
int need = _tconfig.getMinimumPlayers();
if (need == -1) {
need = _tconfig.getMaximumPlayers();
}
// make sure the first "need" players are filled in
for (int i = 0; i < need; i++) {
if (StringUtil.blank(occupants[i])) {
return false;
}
}
return true;
}
/**
* Returns true if there is no one sitting at this table.
*/
public boolean isEmpty ()
{
for (int i = 0; i < occupants.length; i++) {
if (!StringUtil.blank(occupants[i])) {
return false;
}
}
return true;
}
/**
* Returns true if this table is in play, false if it is still being
* matchmade.
*/
public boolean inPlay ()
{
return gameOid != -1;
}
// documentation inherited
@@ -174,8 +227,8 @@ public class Table
throws IOException
{
tableId = new Integer(in.readInt());
gameOid = in.readInt();
lobbyOid = in.readInt();
gameOid = in.readInt();
occupants = (String[])ValueMarshaller.readFrom(in);
config = (GameConfig)ValueMarshaller.readFrom(in);
_tconfig = (TableConfig)config;
@@ -1,5 +1,5 @@
//
// $Id: TableConfig.java,v 1.1 2001/10/19 02:04:29 mdb Exp $
// $Id: TableConfig.java,v 1.2 2001/10/23 20:23:29 mdb Exp $
package com.threerings.parlor.data;
@@ -27,4 +27,9 @@ public interface TableConfig
* creator any time after the minimum number of players has arrived.
*/
public int getDesiredPlayers ();
/**
* Sets the desired number of players to the specified value.
*/
public void setDesiredPlayers (int desiredPlayers);
}
@@ -1,5 +1,5 @@
//
// $Id: ParlorManager.java,v 1.13 2001/10/23 02:22:17 mdb Exp $
// $Id: ParlorManager.java,v 1.14 2001/10/23 20:23:29 mdb Exp $
package com.threerings.parlor.server;
@@ -208,9 +208,9 @@ public class ParlorManager
* will be created.
*
* @param creator the body object that will own the new table.
* @param placeOid the place object id of the place (lobby) in which
* this table should be created. The place object specified must
* implement the {@link TableLobbyObject} interface.
* @param lobbyOid the place object id of the lobby in which this
* table should be created. The place object specified must implement
* the {@link TableLobbyObject} interface.
* @param config the configuration of the game to be created.
*
* @return the id of the newly created table.
@@ -219,26 +219,26 @@ public class ParlorManager
* not able processed for some reason. The explanation will be
* provided in the message data of the exception.
*/
public int createTable (BodyObject creator, int placeOid,
public int createTable (BodyObject creator, int lobbyOid,
GameConfig config)
throws ServiceFailedException
{
// fetch the place object in which we'll be creating a table
try {
TableLobbyObject tlobj = (TableLobbyObject)
CrowdServer.omgr.getObject(placeOid);
CrowdServer.omgr.getObject(lobbyOid);
// make sure the game config implements TableConfig
if (!(config instanceof TableConfig)) {
Log.warning("Requested to matchmake a non-table game " +
"using the table services [creator=" + creator +
", ploid=" + placeOid +
", loboid=" + lobbyOid +
", config=" + config + "].");
throw new ServiceFailedException(INTERNAL_ERROR);
}
// create a brand spanking new table
Table table = new Table(placeOid, config);
Table table = new Table(lobbyOid, config);
// stick the creator into position zero
String error = table.setOccupant(0, creator.username);
@@ -261,7 +261,7 @@ public class ParlorManager
} catch (ClassCastException cce) {
Log.warning("Requested to create table in non-table-lobby " +
"[creator=" + creator + ", ploid=" + placeOid +
"[creator=" + creator + ", loboid=" + lobbyOid +
", config=" + config + ", cce=" + cce + "].");
throw new ServiceFailedException(INTERNAL_ERROR);
}
@@ -282,11 +282,9 @@ public class ParlorManager
* @param tableId the id of the table to be joined.
* @param position the position at which to join the table.
*
* @return the id of the newly created table.
*
* @exception ServiceFailedException thrown if the table creation was
* not able processed for some reason. The explanation will be
* provided in the message data of the exception.
* @exception ServiceFailedException thrown if the joining was not
* able processed for some reason. The explanation will be provided in
* the message data of the exception.
*/
public void joinTable (BodyObject joiner, int tableId, int position)
throws ServiceFailedException
@@ -330,6 +328,60 @@ public class ParlorManager
tlobj.updateTables(table);
}
/**
* Requests that the specified user be removed from the specified
* table. If the user successfully leaves the table, the function will
* return normally. If they are not able to leave for some reason
* (they aren't sitting at the table, etc.), a {@link
* ServiceFailedException} will be thrown with a message code that
* describes the reason for failure.
*
* @param leaver the body object of the user that wishes to leave the
* table.
* @param tableId the id of the table to be left.
*
* @exception ServiceFailedException thrown if the leaving was not
* able processed for some reason. The explanation will be provided in
* the message data of the exception.
*/
public void leaveTable (BodyObject leaver, int tableId)
throws ServiceFailedException
{
// look the table up
Table table = (Table)_tables.get(tableId);
if (table == null) {
throw new ServiceFailedException(NO_SUCH_TABLE);
}
// make sure the lobby for this table is still around
TableLobbyObject tlobj = (TableLobbyObject)
CrowdServer.omgr.getObject(table.lobbyOid);
if (tlobj == null) {
Log.warning("User tried to leave table whose lobby has " +
"disappeared [table=" + table +
", leaver=" + leaver + "].");
throw new ServiceFailedException(INTERNAL_ERROR);
}
// request that the user be removed from the table
if (!table.clearOccupant(leaver.username)) {
throw new ServiceFailedException(NOT_AT_TABLE);
}
// check to see if we just removed the last person from the table
if (table.isEmpty()) {
Log.info("Clearing empty table.");
// remove the table from our tables table and from the lobby
_tables.remove(tableId);
tlobj.removeFromTables(table.tableId);
} else {
Log.info("Updating sparser table.");
// update the table in the lobby
tlobj.updateTables(table);
}
}
/**
* Called when we're ready to create a game (either an invitation has
* been accepted or a table is ready to start. If there is a problem
@@ -373,7 +425,7 @@ public class ParlorManager
public void placeCreated (PlaceObject plobj, PlaceManager pmgr)
{
// see if this place manager is associated with a table
Table table = (Table)_pendingTables.get(pmgr);
Table table = (Table)_pendingTables.remove(pmgr);
if (table != null) {
// update the table with the newly created game object
table.gameOid = plobj.getOid();
@@ -1,5 +1,5 @@
//
// $Id: ParlorProvider.java,v 1.8 2001/10/19 02:04:29 mdb Exp $
// $Id: ParlorProvider.java,v 1.9 2001/10/23 20:23:29 mdb Exp $
package com.threerings.parlor.server;
@@ -141,6 +141,31 @@ public class ParlorProvider
}
}
/**
* Processes a request from the client to leave an existing table.
*/
public void handleLeaveTableRequest (
BodyObject source, int invid, int tableId)
{
Log.info("Handling leave table request [source=" + source +
", invid=" + invid + ", tableId=" + tableId + "].");
String rsp = null;
try {
// pass the request on to the table manager
_pmgr.leaveTable(source, tableId);
// there is normally no response. the client will see
// themselves removed from the table they just left
} catch (ServiceFailedException sfe) {
// the exception message is the code indicating the reason for
// the creation rejection
sendResponse(source, invid, LEAVE_FAILED_RESPONSE,
sfe.getMessage());
}
}
/** A reference to the parlor manager we're working with. */
protected ParlorManager _pmgr;
}