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;
/**
* 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 <code>TableLobbyController</code> or
* something similar, we instead provide the table director which can be
* instantiated by the place controller (or specific table related views)
* to handle the table matchmaking services.
* 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 <code>TableLobbyController</code> or something similar, we instead provide
* the table director which can be 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
* TableObserver} interface so that the table director can notify them
* when table related things happen.
* <p> Entites that do so, will need to implement the {@link TableObserver} interface so that the
* table director can notify them when table related things happen.
*
* <p> 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.
* <p> 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 TableDirector extends BasicDirector
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
* observer which will receive callbacks when interesting table
* related things happen.
* Creates a new table director 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.
* @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 function TableDirector (
ctx :ParlorContext, tableField :String, observer :TableObserver)
public function TableDirector (ctx :ParlorContext, tableField :String, observer :TableObserver)
{
super(ctx);
@@ -89,39 +82,35 @@ public class TableDirector extends BasicDirector
}
/**
* This must be called by the entity that uses the table director 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.
* This must be called by the entity that uses the table director 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 function willEnterPlace (place :PlaceObject) :void
{
// the place should be a TableLobbyObject
_tlobj = TableLobbyObject(place);
_lobby = place;
// add ourselves as a listener to the place object
place.addListener(this);
}
/**
* This must be called by the entity that uses the table director when
* the using entity has left and is done displaying a place.
* This must be called by the entity that uses the table director when the using entity has
* left and is done displaying a place.
*/
public function didLeavePlace (place :PlaceObject) :void
{
// remove our listenership
place.removeListener(this);
// clear out our lobby reference
_lobby = null;
// clear out our reference
_tlobj = 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.
* 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 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
* observers that are notified when this client sits down at or stands
* up from a table.
* 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 function removeSeatednessObserver (
observer :SeatednessObserver) :void
public function removeSeatednessObserver (observer :SeatednessObserver) :void
{
_seatedObservers.remove(observer);
}
/**
* Returns true if this client is currently seated at a table, false
* if they are not.
* Returns true if this client is currently seated at a table, false if they are not.
*/
public function isSeated () :Boolean
{
@@ -149,13 +135,11 @@ public class TableDirector extends BasicDirector
}
/**
* 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.
* 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 function createTable (
tableConfig :TableConfig, config :GameConfig) :void
public function createTable (tableConfig :TableConfig, config :GameConfig) :void
{
// if we're already in a table, refuse the request
if (_ourTable != null) {
@@ -165,21 +149,19 @@ public class TableDirector extends BasicDirector
}
// 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 " +
"currently in a place [config=" + config + "].");
return;
}
// go ahead and issue the create request
_pservice.createTable(_pctx.getClient(), _lobby.getOid(), tableConfig,
config, this);
_tlobj.getTableService().createTable(_pctx.getClient(), tableConfig, config, this);
}
/**
* Sends a request to join the specified table at the specified
* position. The response will be communicated via the {@link
* TableObserver} interface.
* Sends a request to join the specified table at the specified position. The response will be
* communicated via the {@link TableObserver} interface.
*/
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
if (_lobby == null) {
if (_tlobj == null) {
log.warning("Requested to join a table but we're not " +
"currently in a place [tableId=" + tableId + "].");
return;
}
// issue the join request
_pservice.joinTable(_pctx.getClient(), _lobby.getOid(), tableId,
position, this);
_tlobj.getTableService().joinTable(_pctx.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.
* 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 function leaveTable (tableId :int) :void
{
// 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 " +
"currently in a place [tableId=" + tableId + "].");
return;
}
// 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
* all the seats have not yet been filled.
* Sends a request to have the specified table start now, even if all the seats have not yet
* been filled.
*/
public function startTableNow (tableId :int) :void
{
if (_lobby == null) {
if (_tlobj == null) {
log.warning("Requested to start a table but we're not " +
"currently in a place [tableId=" + tableId + "].");
return;
}
_pservice.startTableNow(_ctx.getClient(), _lobby.getOid(),
tableId, this);
_tlobj.getTableService().startTableNow(_ctx.getClient(), tableId, this);
}
// documentation inherited
override public function clientDidLogoff (event :ClientEvent) :void
{
super.clientDidLogoff(event);
_pservice = null;
_lobby = null;
_tlobj = null;
_ourTable = null;
}
// documentation inherited
override protected function fetchServices (client :Client) :void
{
// get a handle on our parlor services
_pservice = (client.requireService(ParlorService) as ParlorService);
}
// documentation inherited
@@ -257,10 +233,8 @@ public class TableDirector extends BasicDirector
{
if (event.getName() == _tableField) {
var table :Table = (event.getEntry() as Table);
// check to see if we just joined a table
checkSeatedness(table);
// now let the observer know what's up
_observer.tableAdded(table);
}
@@ -271,10 +245,8 @@ public class TableDirector extends BasicDirector
{
if (event.getName() == _tableField) {
var table :Table = (event.getEntry() as Table);
// check to see if we just joined or left a table
checkSeatedness(table);
// now let the observer know what's up
_observer.tableUpdated(table);
}
@@ -285,33 +257,33 @@ public class TableDirector extends BasicDirector
{
if (event.getName() == _tableField) {
var tableId :int = (event.getKey() as int);
// check to see if our table just disappeared
if (_ourTable != null && tableId == _ourTable.tableId) {
_ourTable = null;
notifySeatedness(false);
}
// now let the observer know what's up
_observer.tableRemoved(tableId);
}
}
// 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
log.info("Table created, but no lobby. [tableId=" + tableId + "].");
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);
if (table == null) {
log.warning("Table created, but where is it? [tableId=" + tableId + "]");
return;
}
// All this to check to see if we created a party game (and should now enter).
if (table.gameOid != -1 && (table.occupants == null)) {
// let's boogie!
_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
* table, if so.
* Checks to see if we're a member of this table and notes it as our table, if so.
*/
protected function checkSeatedness (table :Table) :void
{
var oldTable :Table = _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
// 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
var self :BodyObject =
(_pctx.getClient().getClientObject() as BodyObject);
var self :BodyObject = (_pctx.getClient().getClientObject() as BodyObject);
if (ArrayUtil.contains(table.occupants, self.getVisibleName())) {
_ourTable = table;
}
@@ -368,12 +337,6 @@ public class TableDirector extends BasicDirector
/** A context by which we can access necessary client services. */
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. */
protected var _tlobj :TableLobbyObject;
@@ -386,8 +349,7 @@ public class TableDirector extends BasicDirector
/** The table of which we are a member if any. */
protected var _ourTable :Table;
/** An array of entities that want to hear about when we stand up or
* sit down. */
/** An array of entities that want to hear about when we stand up or sit down. */
protected var _seatedObservers :ObserverList = new ObserverList();
}
}
@@ -24,34 +24,43 @@ 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.
* 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.
* 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).
* 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).
* 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).
* Removes the table instance that matches the specified key from the tables set (using the
* appropriate distributed object mechanisms).
*/
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;
}
}