Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
// http://code.google.com/p/vilya/
//
// 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.client;
import com.google.common.base.Objects;
import com.samskivert.util.ObserverList;
import com.threerings.util.Name;
import com.threerings.presents.client.BasicDirector;
import com.threerings.presents.client.Client;
import com.threerings.presents.dobj.DObject;
import com.threerings.presents.dobj.EntryAddedEvent;
import com.threerings.presents.dobj.EntryRemovedEvent;
import com.threerings.presents.dobj.EntryUpdatedEvent;
import com.threerings.presents.dobj.SetListener;
import com.threerings.crowd.data.BodyObject;
import com.threerings.parlor.data.Table;
import com.threerings.parlor.data.TableConfig;
import com.threerings.parlor.data.TableLobbyObject;
import com.threerings.parlor.game.data.GameCodes;
import com.threerings.parlor.game.data.GameConfig;
import com.threerings.parlor.util.ParlorContext;
import static com.threerings.parlor.Log.log;
/**
* 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 director 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 director 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 TableDirector extends BasicDirector
implements SetListener
, TableService.ResultListener
{
/**
* 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.
*/
public TableDirector (ParlorContext ctx, String tableField, TableObserver observer)
{
super(ctx);
// keep track of this stuff
_ctx = ctx;
_tableField = tableField;
_observer = observer;
}
/**
* This must be called by the entity that uses the table director when the using entity
* prepares to enter and display a place.
*/
public void setTableObject (DObject tlobj)
{
// the place should be a TableLobbyObject
_tlobj = (TableLobbyObject)tlobj;
// listen for table set changes
tlobj.addListener(this);
}
/**
* This must be called by the entity that uses the table director when the using entity has
* left and is done dealing with tables.
*/
public void clearTableObject ()
{
// remove our listenership and clear out
if (_tlobj != null) {
((DObject)_tlobj).removeListener(this);
_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.
*/
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);
}
/**
* Returns the current table this client is seated at, or null.
*/
public Table getSeatedTable ()
{
return _ourTable;
}
/**
* 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 (TableConfig tableConfig, 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 (_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
_tlobj.getTableService().createTable(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.
*/
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 (_tlobj == null) {
log.warning("Requested to join a table but we're not currently in a place " +
"[tableId=" + tableId + "].");
return;
}
// issue the join request
_tlobj.getTableService().joinTable(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 (_tlobj == null) {
log.warning("Requested to leave a table but we're not currently in a place " +
"[tableId=" + tableId + "].");
return;
}
// issue the leave request
_tlobj.getTableService().leaveTable(tableId, this);
}
/**
* Sends a request to have the specified table start now, even if all the seats have not yet
* been filled.
*/
public void startTableNow (int tableId)
{
if (_tlobj == null) {
log.warning("Requested to start a table but we're not currently in a place " +
"[tableId=" + tableId + "].");
return;
}
_tlobj.getTableService().startTableNow(tableId, this);
}
/**
* Sends a request to boot a player from a table.
*/
public void bootPlayer (int tableId, Name target)
{
if (_tlobj == null) {
log.warning("Requesting to boot a player from a table we're not currently in " +
"[tableId=" + tableId + ", target=" + target + "].");
return;
}
_tlobj.getTableService().bootPlayer(tableId, target, this);
}
@Override
public void clientDidLogoff (Client client)
{
super.clientDidLogoff(client);
_ourTable = null;
}
// documentation inherited
public void entryAdded (EntryAddedEvent
event)
{
if (event.getName().equals(_tableField)) {
Table table = event.getEntry();
// check to see if we just joined a table
checkSeatedness(table);
// now let the observer know what's up
_observer.tableAdded(table);
}
}
// documentation inherited
public void entryUpdated (EntryUpdatedEvent
event)
{
if (event.getName().equals(_tableField)) {
Table table = event.getEntry();
// check to see if we just joined or left a table
checkSeatedness(table);
// now let the observer know what's up
_observer.tableUpdated(table);
}
}
// documentation inherited
public void entryRemoved (EntryRemovedEvent
event)
{
if (event.getName().equals(_tableField)) {
int tableId = ((Integer) event.getKey()).intValue();
// 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);
}
}
// from interface TableService.ResultListener
public void requestProcessed (Object result)
{
int tableId = (Integer)result;
if (_tlobj == null) {
// we've left, it's none of our concern anymore
log.info("Table created, but no lobby. [tableId=" + tableId + "].");
return;
}
Table table = _tlobj.getTables().get(tableId);
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.players.length == 0) {
_ctx.getParlorDirector().gameIsReady(table.gameOid); // let's boogie!
}
}
// from interface TableService.ResultListener
public void requestFailed (String reason)
{
log.warning("Table action failed [reason=" + reason + "].");
_ctx.getChatDirector().displayFeedback(GameCodes.GAME_MESSAGE_BUNDLE, reason);
}
/**
* Checks to see if we're a member of this table and notes it as our
* table, if so.
*/
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
if (table.equals(_ourTable)) {
_ourTable = null;
}
// look for our username in the occupants array
BodyObject self = (BodyObject)_ctx.getClient().getClientObject();
if (table.containsPlayer(self.getVisibleName())) {
_ourTable = table;
}
// if nothing changed, bail now
if (Objects.equal(oldTable, _ourTable)) {
return;
}
// otherwise notify the observers
notifySeatedness(_ourTable != null);
}
/**
* Notifies the seatedness observers of a seatedness change.
*/
protected void notifySeatedness (final boolean isSeated)
{
_seatedObservers.apply(new ObserverList.ObserverOp() {
public boolean apply (SeatednessObserver so) {
so.seatednessDidChange(isSeated);
return true;
}
});
}
/** A context by which we can access necessary client services. */
protected ParlorContext _ctx;
/** Our TableLobbyObject. */
protected TableLobbyObject _tlobj;
/** 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;
/** An array of entities that want to hear about when we stand up or sit down. */
protected ObserverList _seatedObservers = ObserverList.newFastUnsafe();
}