Don't forget kids. We get to write everything twice now. It's great!

git-svn-id: svn+ssh://src.earth.threerings.net/vilya/trunk@256 c613c5cb-e716-0410-b11b-feb51c14d237
This commit is contained in:
Michael Bayne
2007-03-21 21:44:11 +00:00
parent b71007a909
commit 9b5369ef99
2 changed files with 79 additions and 108 deletions
@@ -44,41 +44,34 @@ import com.threerings.parlor.game.data.GameConfig;
import com.threerings.parlor.util.ParlorContext; import com.threerings.parlor.util.ParlorContext;
/** /**
* As tables are created and managed within the scope of a place (a * As tables are created and managed within the scope of a place (a lobby), we want to fold the
* lobby), we want to fold the table management functionality into the * table management functionality into the standard hierarchy of place controllers that deal with
* standard hierarchy of place controllers that deal with place-related * place-related functionality on the client. Thus, instead of forcing places that expect to have
* functionality on the client. Thus, instead of forcing places that * tables to extend a <code>TableLobbyController</code> or something similar, we instead provide
* expect to have tables to extend a <code>TableLobbyController</code> or * the table director which can be instantiated by the place controller (or specific table related
* something similar, we instead provide the table director which can be * views) to handle the table matchmaking services.
* instantiated by the place controller (or specific table related views)
* to handle the table matchmaking services.
* *
* <p> Entites that do so, will need to implement the {@link * <p> Entites that do so, will need to implement the {@link TableObserver} interface so that the
* TableObserver} interface so that the table director can notify them * table director can notify them when table related things happen.
* when table related things happen.
* *
* <p> The table services expect that the place object being used as a * <p> The table services expect that the place object being used as a lobby in which the table
* lobby in which the table matchmaking takes place implements the {@link * matchmaking takes place implements the {@link TableLobbyObject} interface.
* TableLobbyObject} interface.
*/ */
public class TableDirector extends BasicDirector public class TableDirector extends BasicDirector
implements SetListener, ParlorService_TableListener implements SetListener, ParlorService_TableListener
{ {
private static const log :Log = Log.getLog(TableDirector); protected static const log :Log = Log.getLog(TableDirector);
/** /**
* Creates a new table director to manage tables with the specified * Creates a new table director to manage tables with the specified observer which will receive
* observer which will receive callbacks when interesting table * callbacks when interesting table related things happen.
* related things happen.
* *
* @param ctx the parlor context in use by the client. * @param ctx the parlor context in use by the client.
* @param tableField the field name of the distributed set that * @param tableField the field name of the distributed set that contains the tables we will be
* contains the tables we will be managing. * managing.
* @param observer the entity that will receive callbacks when things * @param observer the entity that will receive callbacks when things happen to the tables.
* happen to the tables.
*/ */
public function TableDirector ( public function TableDirector (ctx :ParlorContext, tableField :String, observer :TableObserver)
ctx :ParlorContext, tableField :String, observer :TableObserver)
{ {
super(ctx); super(ctx);
@@ -89,39 +82,35 @@ public class TableDirector extends BasicDirector
} }
/** /**
* This must be called by the entity that uses the table director when * This must be called by the entity that uses the table director when the using entity
* the using entity prepares to enter and display a place. It is * prepares to enter and display a place. It is assumed that the client is already subscribed
* assumed that the client is already subscribed to the provided place * to the provided place object.
* object.
*/ */
public function willEnterPlace (place :PlaceObject) :void public function willEnterPlace (place :PlaceObject) :void
{ {
// the place should be a TableLobbyObject // the place should be a TableLobbyObject
_tlobj = TableLobbyObject(place); _tlobj = TableLobbyObject(place);
_lobby = place;
// add ourselves as a listener to the place object // add ourselves as a listener to the place object
place.addListener(this); place.addListener(this);
} }
/** /**
* This must be called by the entity that uses the table director when * This must be called by the entity that uses the table director when the using entity has
* the using entity has left and is done displaying a place. * left and is done displaying a place.
*/ */
public function didLeavePlace (place :PlaceObject) :void public function didLeavePlace (place :PlaceObject) :void
{ {
// remove our listenership // remove our listenership
place.removeListener(this); place.removeListener(this);
// clear out our lobby reference // clear out our reference
_lobby = null;
_tlobj = null; _tlobj = null;
} }
/** /**
* Requests that the specified observer be added to the list of * Requests that the specified observer be added to the list of observers that are notified
* observers that are notified when this client sits down at or stands * when this client sits down at or stands up from a table.
* up from a table.
*/ */
public function addSeatednessObserver (observer :SeatednessObserver) :void public function addSeatednessObserver (observer :SeatednessObserver) :void
{ {
@@ -129,19 +118,16 @@ public class TableDirector extends BasicDirector
} }
/** /**
* Requests that the specified observer be removed from to the list of * Requests that the specified observer be removed from to the list of observers that are
* observers that are notified when this client sits down at or stands * notified when this client sits down at or stands up from a table.
* up from a table.
*/ */
public function removeSeatednessObserver ( public function removeSeatednessObserver (observer :SeatednessObserver) :void
observer :SeatednessObserver) :void
{ {
_seatedObservers.remove(observer); _seatedObservers.remove(observer);
} }
/** /**
* Returns true if this client is currently seated at a table, false * Returns true if this client is currently seated at a table, false if they are not.
* if they are not.
*/ */
public function isSeated () :Boolean public function isSeated () :Boolean
{ {
@@ -149,13 +135,11 @@ public class TableDirector extends BasicDirector
} }
/** /**
* Sends a request to create a table with the specified game * Sends a request to create a table with the specified game configuration. This user will
* configuration. This user will become the owner of this table and * become the owner of this table and will be added to the first position in the table. The
* will be added to the first position in the table. The response will * response will be communicated via the {@link TableObserver} interface.
* be communicated via the {@link TableObserver} interface.
*/ */
public function createTable ( public function createTable (tableConfig :TableConfig, config :GameConfig) :void
tableConfig :TableConfig, config :GameConfig) :void
{ {
// if we're already in a table, refuse the request // if we're already in a table, refuse the request
if (_ourTable != null) { if (_ourTable != null) {
@@ -165,21 +149,19 @@ public class TableDirector extends BasicDirector
} }
// make sure we're currently in a place // make sure we're currently in a place
if (_lobby == null) { if (_tlobj == null) {
log.warning("Requested to create a table but we're not " + log.warning("Requested to create a table but we're not " +
"currently in a place [config=" + config + "]."); "currently in a place [config=" + config + "].");
return; return;
} }
// go ahead and issue the create request // go ahead and issue the create request
_pservice.createTable(_pctx.getClient(), _lobby.getOid(), tableConfig, _tlobj.getTableService().createTable(_pctx.getClient(), tableConfig, config, this);
config, this);
} }
/** /**
* Sends a request to join the specified table at the specified * Sends a request to join the specified table at the specified position. The response will be
* position. The response will be communicated via the {@link * communicated via the {@link TableObserver} interface.
* TableObserver} interface.
*/ */
public function joinTable (tableId :int, position :int) :void public function joinTable (tableId :int, position :int) :void
{ {
@@ -191,65 +173,59 @@ public class TableDirector extends BasicDirector
} }
// make sure we're currently in a place // make sure we're currently in a place
if (_lobby == null) { if (_tlobj == null) {
log.warning("Requested to join a table but we're not " + log.warning("Requested to join a table but we're not " +
"currently in a place [tableId=" + tableId + "]."); "currently in a place [tableId=" + tableId + "].");
return; return;
} }
// issue the join request // issue the join request
_pservice.joinTable(_pctx.getClient(), _lobby.getOid(), tableId, _tlobj.getTableService().joinTable(_pctx.getClient(), tableId, position, this);
position, this);
} }
/** /**
* Sends a request to leave the specified table at which we are * Sends a request to leave the specified table at which we are presumably seated. The response
* presumably seated. The response will be communicated via the {@link * will be communicated via the {@link TableObserver} interface.
* TableObserver} interface.
*/ */
public function leaveTable (tableId :int) :void public function leaveTable (tableId :int) :void
{ {
// make sure we're currently in a place // make sure we're currently in a place
if (_lobby == null) { if (_tlobj == null) {
log.warning("Requested to leave a table but we're not " + log.warning("Requested to leave a table but we're not " +
"currently in a place [tableId=" + tableId + "]."); "currently in a place [tableId=" + tableId + "].");
return; return;
} }
// issue the leave request // issue the leave request
_pservice.leaveTable(_pctx.getClient(), _lobby.getOid(), tableId, this); _tlobj.getTableService().leaveTable(_pctx.getClient(), tableId, this);
} }
/** /**
* Sends a request to have the specified table start now, even if * Sends a request to have the specified table start now, even if all the seats have not yet
* all the seats have not yet been filled. * been filled.
*/ */
public function startTableNow (tableId :int) :void public function startTableNow (tableId :int) :void
{ {
if (_lobby == null) { if (_tlobj == null) {
log.warning("Requested to start a table but we're not " + log.warning("Requested to start a table but we're not " +
"currently in a place [tableId=" + tableId + "]."); "currently in a place [tableId=" + tableId + "].");
return; return;
} }
_pservice.startTableNow(_ctx.getClient(), _lobby.getOid(), _tlobj.getTableService().startTableNow(_ctx.getClient(), tableId, this);
tableId, this);
} }
// documentation inherited // documentation inherited
override public function clientDidLogoff (event :ClientEvent) :void override public function clientDidLogoff (event :ClientEvent) :void
{ {
super.clientDidLogoff(event); super.clientDidLogoff(event);
_pservice = null; _tlobj = null;
_lobby = null;
_ourTable = null; _ourTable = null;
} }
// documentation inherited // documentation inherited
override protected function fetchServices (client :Client) :void override protected function fetchServices (client :Client) :void
{ {
// get a handle on our parlor services
_pservice = (client.requireService(ParlorService) as ParlorService);
} }
// documentation inherited // documentation inherited
@@ -257,10 +233,8 @@ public class TableDirector extends BasicDirector
{ {
if (event.getName() == _tableField) { if (event.getName() == _tableField) {
var table :Table = (event.getEntry() as Table); var table :Table = (event.getEntry() as Table);
// check to see if we just joined a table // check to see if we just joined a table
checkSeatedness(table); checkSeatedness(table);
// now let the observer know what's up // now let the observer know what's up
_observer.tableAdded(table); _observer.tableAdded(table);
} }
@@ -271,10 +245,8 @@ public class TableDirector extends BasicDirector
{ {
if (event.getName() == _tableField) { if (event.getName() == _tableField) {
var table :Table = (event.getEntry() as Table); var table :Table = (event.getEntry() as Table);
// check to see if we just joined or left a table // check to see if we just joined or left a table
checkSeatedness(table); checkSeatedness(table);
// now let the observer know what's up // now let the observer know what's up
_observer.tableUpdated(table); _observer.tableUpdated(table);
} }
@@ -285,33 +257,33 @@ public class TableDirector extends BasicDirector
{ {
if (event.getName() == _tableField) { if (event.getName() == _tableField) {
var tableId :int = (event.getKey() as int); var tableId :int = (event.getKey() as int);
// check to see if our table just disappeared // check to see if our table just disappeared
if (_ourTable != null && tableId == _ourTable.tableId) { if (_ourTable != null && tableId == _ourTable.tableId) {
_ourTable = null; _ourTable = null;
notifySeatedness(false); notifySeatedness(false);
} }
// now let the observer know what's up // now let the observer know what's up
_observer.tableRemoved(tableId); _observer.tableRemoved(tableId);
} }
} }
// documentation inherited from interface // documentation inherited from interface
public function tableCreated (tableId :int) :void public function requestProcessed (result :Object) :void
{ {
if (_lobby == null) { var tableId :int = int(result);
if (_tlobj == null) {
// we've left, it's none of our concern anymore // we've left, it's none of our concern anymore
log.info("Table created, but no lobby. [tableId=" + tableId + "]."); log.info("Table created, but no lobby. [tableId=" + tableId + "].");
return; return;
} }
// All this to check to see if we created a party game (and should now enter).
var table :Table = (_tlobj.getTables().get(tableId) as Table); var table :Table = (_tlobj.getTables().get(tableId) as Table);
if (table == null) { if (table == null) {
log.warning("Table created, but where is it? [tableId=" + tableId + "]"); log.warning("Table created, but where is it? [tableId=" + tableId + "]");
return; return;
} }
// All this to check to see if we created a party game (and should now enter).
if (table.gameOid != -1 && (table.occupants == null)) { if (table.gameOid != -1 && (table.occupants == null)) {
// let's boogie! // let's boogie!
_pctx.getParlorDirector().gameIsReady(table.gameOid); _pctx.getParlorDirector().gameIsReady(table.gameOid);
@@ -325,23 +297,20 @@ public class TableDirector extends BasicDirector
} }
/** /**
* Checks to see if we're a member of this table and notes it as our * Checks to see if we're a member of this table and notes it as our table, if so.
* table, if so.
*/ */
protected function checkSeatedness (table :Table) :void protected function checkSeatedness (table :Table) :void
{ {
var oldTable :Table = _ourTable; var oldTable :Table = _ourTable;
// if this is the same table as our table, clear out our table // if this is the same table as our table, clear out our table reference and allow it to be
// reference and allow it to be added back if we are still in the // added back if we are still in the table
// table
if (table.equals(_ourTable)) { if (table.equals(_ourTable)) {
_ourTable = null; _ourTable = null;
} }
// look for our username in the occupants array // look for our username in the occupants array
var self :BodyObject = var self :BodyObject = (_pctx.getClient().getClientObject() as BodyObject);
(_pctx.getClient().getClientObject() as BodyObject);
if (ArrayUtil.contains(table.occupants, self.getVisibleName())) { if (ArrayUtil.contains(table.occupants, self.getVisibleName())) {
_ourTable = table; _ourTable = table;
} }
@@ -368,12 +337,6 @@ public class TableDirector extends BasicDirector
/** A context by which we can access necessary client services. */ /** A context by which we can access necessary client services. */
protected var _pctx :ParlorContext; protected var _pctx :ParlorContext;
/** Parlor server-side services. */
protected var _pservice :ParlorService;
/** The place object in which we're currently managing tables. */
protected var _lobby :PlaceObject;
/** The place object, cast as a TableLobbyObject. */ /** The place object, cast as a TableLobbyObject. */
protected var _tlobj :TableLobbyObject; protected var _tlobj :TableLobbyObject;
@@ -386,8 +349,7 @@ public class TableDirector extends BasicDirector
/** The table of which we are a member if any. */ /** The table of which we are a member if any. */
protected var _ourTable :Table; protected var _ourTable :Table;
/** An array of entities that want to hear about when we stand up or /** An array of entities that want to hear about when we stand up or sit down. */
* sit down. */
protected var _seatedObservers :ObserverList = new ObserverList(); protected var _seatedObservers :ObserverList = new ObserverList();
} }
} }
@@ -24,34 +24,43 @@ package com.threerings.parlor.data {
import com.threerings.presents.dobj.DSet; import com.threerings.presents.dobj.DSet;
/** /**
* This interface must be implemented by the place object used by a lobby * This interface must be implemented by the place object used by a lobby that wishes to make use
* that wishes to make use of the table services. * of the table services.
*/ */
public interface TableLobbyObject public interface TableLobbyObject
{ {
/** /**
* Returns a reference to the distributed set instance that will be * Returns a reference to the distributed set instance that will be holding the tables.
* holding the tables.
*/ */
function getTables () :DSet; function getTables () :DSet;
/** /**
* Adds the supplied table instance to the tables set (using the * Adds the supplied table instance to the tables set (using the appropriate distributed object
* appropriate distributed object mechanisms). * mechanisms).
*/ */
function addToTables (table :Table) :void; function addToTables (table :Table) :void;
/** /**
* Updates the value of the specified table instance in the tables * Updates the value of the specified table instance in the tables distributed set (using the
* distributed set (using the appropriate distributed object * appropriate distributed object mechanisms).
* mechanisms).
*/ */
function updateTables (table :Table) :void; function updateTables (table :Table) :void;
/** /**
* Removes the table instance that matches the specified key from the * Removes the table instance that matches the specified key from the tables set (using the
* tables set (using the appropriate distributed object mechanisms). * appropriate distributed object mechanisms).
*/ */
function removeFromTables (key :Object) :void; function removeFromTables (key :Object) :void;
/**
* Returns a reference to the table service configured in this object.
*/
function getTableService () :TableMarshaller;
/**
* Configures the table service that clients should use to communicate table requests back to
* the table manager handling these tables.
*/
function setTableService (service :TableMarshaller) :void;
} }
} }