Behold Vilya, Ring of Air and repository for our game and virtual worldly
extensions to the distributed environment provided by Narya. git-svn-id: svn+ssh://src.earth.threerings.net/vilya/trunk@1 c613c5cb-e716-0410-b11b-feb51c14d237
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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 javax.swing.JCheckBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import com.samskivert.swing.SimpleSlider;
|
||||
import com.samskivert.swing.VGroupLayout;
|
||||
|
||||
import com.threerings.parlor.data.TableConfig;
|
||||
import com.threerings.parlor.util.ParlorContext;
|
||||
|
||||
import com.threerings.parlor.game.client.SwingGameConfigurator;
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
|
||||
/**
|
||||
* Provides a default implementation of a TableConfigurator for
|
||||
* a Swing interface.
|
||||
*/
|
||||
public class DefaultSwingTableConfigurator extends TableConfigurator
|
||||
{
|
||||
/**
|
||||
* Create a TableConfigurator that allows only the specified number
|
||||
* of players and lets the configuring user enable private games
|
||||
* only if the number of players is greater than 2.
|
||||
*/
|
||||
public DefaultSwingTableConfigurator (int players)
|
||||
{
|
||||
this(players, (players > 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a TableConfigurator that allows only the specified number
|
||||
* of players and lets the user configure a private table, or not.
|
||||
*/
|
||||
public DefaultSwingTableConfigurator (int players, boolean allowPrivate)
|
||||
{
|
||||
this(players, players, players, allowPrivate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a TableConfigurator that allows for the specified configuration
|
||||
* parameters.
|
||||
*/
|
||||
public DefaultSwingTableConfigurator (int minPlayers,
|
||||
int desiredPlayers, int maxPlayers, boolean allowPrivate)
|
||||
{
|
||||
_config.minimumPlayerCount = minPlayers;
|
||||
|
||||
// create a slider for players, if applicable
|
||||
if (minPlayers != maxPlayers) {
|
||||
_playerSlider = new SimpleSlider(
|
||||
"", minPlayers, maxPlayers, desiredPlayers);
|
||||
|
||||
} else {
|
||||
_config.desiredPlayerCount = desiredPlayers;
|
||||
}
|
||||
|
||||
// create up the checkbox for private games, if applicable
|
||||
if (allowPrivate) {
|
||||
_privateCheck = new JCheckBox();
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected void createConfigInterface ()
|
||||
{
|
||||
super.createConfigInterface();
|
||||
|
||||
SwingGameConfigurator gconf = (SwingGameConfigurator) _gameConfigurator;
|
||||
|
||||
if (_playerSlider != null) {
|
||||
// TODO: proper translation
|
||||
gconf.addControl(new JLabel("Players:"), _playerSlider);
|
||||
}
|
||||
|
||||
if (_privateCheck != null) {
|
||||
// TODO: proper translation
|
||||
gconf.addControl(new JLabel("Private:"), _privateCheck);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public boolean isEmpty ()
|
||||
{
|
||||
return (_playerSlider == null) && (_privateCheck == null);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected void flushTableConfig()
|
||||
{
|
||||
super.flushTableConfig();
|
||||
|
||||
if (_playerSlider != null) {
|
||||
_config.desiredPlayerCount = _playerSlider.getValue();
|
||||
}
|
||||
if (_privateCheck != null) {
|
||||
_config.privateTable = _privateCheck.isSelected();
|
||||
}
|
||||
}
|
||||
|
||||
/** A slider for configuring the number of players at the table. */
|
||||
protected SimpleSlider _playerSlider;
|
||||
|
||||
/** A checkbox to allow the table creator to specify if the table is
|
||||
* private. */
|
||||
protected JCheckBox _privateCheck;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// $Id: GameReadyObserver.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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;
|
||||
|
||||
/**
|
||||
* Used to inform interested parties when the {@link ParlorDirector}
|
||||
* receives a game ready notification. The observers can ratify the
|
||||
* decision to head directly into the game or can take responsibility
|
||||
* themselves for doing so.
|
||||
*/
|
||||
public interface GameReadyObserver
|
||||
{
|
||||
/**
|
||||
* Called when a game ready notification is received.
|
||||
*
|
||||
* @param gameOid the place oid of the ready game.
|
||||
*
|
||||
* @return if the observer returns true from this method, the parlor
|
||||
* director assumes they will take care of entering the game room
|
||||
* after performing processing of their own. If all observers return
|
||||
* false, the director will enter the game room automatically.
|
||||
*/
|
||||
public boolean receivedGameReady (int gameOid);
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
//
|
||||
// $Id: Invitation.java 3381 2005-03-03 19:36:34Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.threerings.util.Name;
|
||||
|
||||
import com.threerings.parlor.Log;
|
||||
import com.threerings.parlor.data.ParlorCodes;
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
import com.threerings.parlor.util.ParlorContext;
|
||||
|
||||
/**
|
||||
* The invitation class is used to track information related to
|
||||
* outstanding invitations generated by or targeted to this client.
|
||||
*/
|
||||
public class Invitation
|
||||
implements ParlorCodes, ParlorService.InviteListener
|
||||
{
|
||||
/** The unique id for this invitation (as assigned by the
|
||||
* server). This is -1 until we receive an acknowledgement from
|
||||
* the server that our invitation was delivered. */
|
||||
public int inviteId = -1;
|
||||
|
||||
/** The name of the other user involved in this invitation. */
|
||||
public Name opponent;
|
||||
|
||||
/** The configuration of the game to be created. */
|
||||
public GameConfig config;
|
||||
|
||||
/** Constructs a new invitation record. */
|
||||
public Invitation (ParlorContext ctx, ParlorService pservice,
|
||||
Name opponent, GameConfig config,
|
||||
InvitationResponseObserver observer)
|
||||
{
|
||||
_ctx = ctx;
|
||||
_pservice = pservice;
|
||||
_observer = observer;
|
||||
this.opponent = opponent;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts this invitation.
|
||||
*/
|
||||
public void accept ()
|
||||
{
|
||||
// generate the invocation service request
|
||||
_pservice.respond(_ctx.getClient(), inviteId,
|
||||
INVITATION_ACCEPTED, null, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Refuses this invitation.
|
||||
*
|
||||
* @param message the message to deliver to the inviting user
|
||||
* explaining the reason for the refusal or null if no message is to
|
||||
* be provided.
|
||||
*/
|
||||
public void refuse (String message)
|
||||
{
|
||||
// generate the invocation service request
|
||||
_pservice.respond(_ctx.getClient(), inviteId,
|
||||
INVITATION_REFUSED, message, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels this invitation.
|
||||
*/
|
||||
public void cancel ()
|
||||
{
|
||||
// if the invitation has not yet been acknowleged by the
|
||||
// server, we make a note that it should be cancelled when we
|
||||
// do receive the acknowlegement
|
||||
if (inviteId == -1) {
|
||||
_cancelled = true;
|
||||
|
||||
} else {
|
||||
// otherwise, generate the invocation service request
|
||||
_pservice.cancel(_ctx.getClient(), inviteId, this);
|
||||
// and remove it from the pending table
|
||||
_ctx.getParlorDirector().clearInvitation(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Counters this invitation with an invitation with different game
|
||||
* configuration parameters.
|
||||
*
|
||||
* @param config the updated game configuration.
|
||||
* @param observer the entity that will be notified if this
|
||||
* counter-invitation is accepted, refused or countered.
|
||||
*/
|
||||
public void counter (GameConfig config, InvitationResponseObserver observer)
|
||||
{
|
||||
// update our observer (who will eventually be hearing back from
|
||||
// the other client about their counter-invitation)
|
||||
_observer = observer;
|
||||
|
||||
// generate the invocation service request
|
||||
_pservice.respond(_ctx.getClient(), inviteId,
|
||||
INVITATION_COUNTERED, config, this);
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public void inviteReceived (int inviteId)
|
||||
{
|
||||
// fill in our invitation id
|
||||
this.inviteId = inviteId;
|
||||
|
||||
// if the invitation was cancelled before we heard back about
|
||||
// it, we need to send off a cancellation request now
|
||||
if (_cancelled) {
|
||||
_pservice.cancel(_ctx.getClient(), inviteId, this);
|
||||
} else {
|
||||
// otherwise, put it in the pending invites table
|
||||
_ctx.getParlorDirector().registerInvitation(this);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public void requestFailed (String reason)
|
||||
{
|
||||
// let the observer know what's up
|
||||
_observer.invitationRefused(this, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the parlor director when we receive a response to an
|
||||
* invitation initiated by this client.
|
||||
*/
|
||||
protected void receivedResponse (int code, Object arg)
|
||||
{
|
||||
// make sure we have an observer to notify
|
||||
if (_observer == null) {
|
||||
Log.warning("No observer registered for invitation " +
|
||||
this + ".");
|
||||
return;
|
||||
}
|
||||
|
||||
// notify the observer
|
||||
try {
|
||||
switch (code) {
|
||||
case INVITATION_ACCEPTED:
|
||||
_observer.invitationAccepted(this);
|
||||
break;
|
||||
|
||||
case INVITATION_REFUSED:
|
||||
_observer.invitationRefused(this, (String)arg);
|
||||
break;
|
||||
|
||||
case INVITATION_COUNTERED:
|
||||
_observer.invitationCountered(this, (GameConfig)arg);
|
||||
break;
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.warning("Invitation response observer choked on response " +
|
||||
"[code=" + code + ", arg=" + arg +
|
||||
", invite=" + this + "].");
|
||||
Log.logStackTrace(e);
|
||||
}
|
||||
|
||||
// unless the invitation was countered, we can remove it from the
|
||||
// pending table because it's resolved
|
||||
if (code != INVITATION_COUNTERED) {
|
||||
_ctx.getParlorDirector().clearInvitation(this);
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns a string representation of this invitation record. */
|
||||
public String toString ()
|
||||
{
|
||||
return "[inviteId=" + inviteId + ", opponent=" + opponent +
|
||||
", config=" + config + ", observer=" + _observer +
|
||||
", cancelled=" + _cancelled + "]";
|
||||
}
|
||||
|
||||
/** Provides access to client services. */
|
||||
protected ParlorContext _ctx;
|
||||
|
||||
/** Provides access to parlor services. */
|
||||
protected ParlorService _pservice;
|
||||
|
||||
/** The entity to notify when we receive a response for this
|
||||
* invitation. */
|
||||
protected InvitationResponseObserver _observer;
|
||||
|
||||
/** A flag indicating that we were requested to cancel this
|
||||
* invitation before we even heard back with an acknowledgement
|
||||
* that it was received by the server. */
|
||||
protected boolean _cancelled = false;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// $Id: InvitationHandler.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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;
|
||||
|
||||
/**
|
||||
* A client entity that wishes to handle invitations received by other
|
||||
* clients should implement this interface and register itself with the
|
||||
* parlor director. It will subsequently be notified of any incoming
|
||||
* invitations. It is also responsible for handling cancelled invitations.
|
||||
*/
|
||||
public interface InvitationHandler
|
||||
{
|
||||
/**
|
||||
* Called when an invitation is received from another player.
|
||||
*
|
||||
* @param invite the received invitation.
|
||||
*/
|
||||
public void invitationReceived (Invitation invite);
|
||||
|
||||
/**
|
||||
* Called when an invitation is cancelled by the inviting player.
|
||||
*
|
||||
* @param invite the cancelled invitation.
|
||||
*/
|
||||
public void invitationCancelled (Invitation invite);
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// $Id: InvitationResponseObserver.java 3381 2005-03-03 19:36:34Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.threerings.parlor.game.data.GameConfig;
|
||||
|
||||
/**
|
||||
* A client entity that wishes to generate invitations for games must
|
||||
* implement this interface. An invitation can be accepted, refused or
|
||||
* countered. A countered invitation is one where the game configuration
|
||||
* is adjusted by the invited player and proposed back to the inviting
|
||||
* player.
|
||||
*/
|
||||
public interface InvitationResponseObserver
|
||||
{
|
||||
/**
|
||||
* Called if the invitation was accepted.
|
||||
*
|
||||
* @param invite the invitation for which we received a response.
|
||||
*/
|
||||
public void invitationAccepted (Invitation invite);
|
||||
|
||||
/**
|
||||
* Called if the invitation was refused.
|
||||
*
|
||||
* @param invite the invitation for which we received a response.
|
||||
* @param message a message provided by the invited user explaining
|
||||
* the reason for their refusal, or the empty string if no message was
|
||||
* provided.
|
||||
*/
|
||||
public void invitationRefused (Invitation invite, String message);
|
||||
|
||||
/**
|
||||
* Called if the invitation was countered with an alternate game
|
||||
* configuration.
|
||||
*
|
||||
* @param invite the invitation for which we received a response.
|
||||
* @param config the game configuration proposed by the invited
|
||||
* player.
|
||||
*/
|
||||
public void invitationCountered (Invitation invite, GameConfig config);
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
//
|
||||
// $Id: ParlorDecoder.java 4145 2006-05-24 01:24:24Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.threerings.parlor.client.ParlorReceiver;
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
import com.threerings.presents.client.InvocationDecoder;
|
||||
import com.threerings.util.Name;
|
||||
|
||||
/**
|
||||
* Dispatches calls to a {@link ParlorReceiver} instance.
|
||||
*/
|
||||
public class ParlorDecoder extends InvocationDecoder
|
||||
{
|
||||
/** The generated hash code used to identify this receiver class. */
|
||||
public static final String RECEIVER_CODE = "5ef9ee0d359c42a9024498ee9aad119a";
|
||||
|
||||
/** The method id used to dispatch {@link ParlorReceiver#gameIsReady}
|
||||
* notifications. */
|
||||
public static final int GAME_IS_READY = 1;
|
||||
|
||||
/** The method id used to dispatch {@link ParlorReceiver#receivedInvite}
|
||||
* notifications. */
|
||||
public static final int RECEIVED_INVITE = 2;
|
||||
|
||||
/** The method id used to dispatch {@link ParlorReceiver#receivedInviteCancellation}
|
||||
* notifications. */
|
||||
public static final int RECEIVED_INVITE_CANCELLATION = 3;
|
||||
|
||||
/** The method id used to dispatch {@link ParlorReceiver#receivedInviteResponse}
|
||||
* notifications. */
|
||||
public static final int RECEIVED_INVITE_RESPONSE = 4;
|
||||
|
||||
/**
|
||||
* Creates a decoder that may be registered to dispatch invocation
|
||||
* service notifications to the specified receiver.
|
||||
*/
|
||||
public ParlorDecoder (ParlorReceiver receiver)
|
||||
{
|
||||
this.receiver = receiver;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public String getReceiverCode ()
|
||||
{
|
||||
return RECEIVER_CODE;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void dispatchNotification (int methodId, Object[] args)
|
||||
{
|
||||
switch (methodId) {
|
||||
case GAME_IS_READY:
|
||||
((ParlorReceiver)receiver).gameIsReady(
|
||||
((Integer)args[0]).intValue()
|
||||
);
|
||||
return;
|
||||
|
||||
case RECEIVED_INVITE:
|
||||
((ParlorReceiver)receiver).receivedInvite(
|
||||
((Integer)args[0]).intValue(), (Name)args[1], (GameConfig)args[2]
|
||||
);
|
||||
return;
|
||||
|
||||
case RECEIVED_INVITE_CANCELLATION:
|
||||
((ParlorReceiver)receiver).receivedInviteCancellation(
|
||||
((Integer)args[0]).intValue()
|
||||
);
|
||||
return;
|
||||
|
||||
case RECEIVED_INVITE_RESPONSE:
|
||||
((ParlorReceiver)receiver).receivedInviteResponse(
|
||||
((Integer)args[0]).intValue(), ((Integer)args[1]).intValue(), (Object)args[2]
|
||||
);
|
||||
return;
|
||||
|
||||
default:
|
||||
super.dispatchNotification(methodId, args);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
//
|
||||
// $Id: ParlorDirector.java 3381 2005-03-03 19:36:34Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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 java.util.ArrayList;
|
||||
|
||||
import com.samskivert.util.HashIntMap;
|
||||
import com.threerings.util.Name;
|
||||
|
||||
import com.threerings.presents.client.BasicDirector;
|
||||
import com.threerings.presents.client.Client;
|
||||
import com.threerings.presents.client.InvocationService;
|
||||
|
||||
import com.threerings.parlor.Log;
|
||||
import com.threerings.parlor.data.ParlorCodes;
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
import com.threerings.parlor.util.ParlorContext;
|
||||
|
||||
/**
|
||||
* The parlor director manages the client side of the game configuration
|
||||
* and matchmaking processes. It is also the entity that is listening for
|
||||
* game start notifications which it then dispatches the client entity
|
||||
* that will actually create and display the user interface for the game
|
||||
* that started.
|
||||
*/
|
||||
public class ParlorDirector extends BasicDirector
|
||||
implements ParlorCodes, ParlorReceiver
|
||||
{
|
||||
/**
|
||||
* Constructs a parlor director and provides it with the parlor
|
||||
* context that it can use to access the client services that it needs
|
||||
* to provide its own services. Only one parlor director should be
|
||||
* active in the client at one time and it should be made available
|
||||
* via the parlor context.
|
||||
*
|
||||
* @param ctx the parlor context in use by the client.
|
||||
*/
|
||||
public ParlorDirector (ParlorContext ctx)
|
||||
{
|
||||
super(ctx);
|
||||
_ctx = ctx;
|
||||
|
||||
// register ourselves with the invocation director as a parlor
|
||||
// notification receiver
|
||||
_ctx.getClient().getInvocationDirector().registerReceiver(
|
||||
new ParlorDecoder(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the invitation handler, which is the entity that will be
|
||||
* notified when we receive incoming invitation notifications and when
|
||||
* invitations have been cancelled.
|
||||
*
|
||||
* @param handler our new invitation handler.
|
||||
*/
|
||||
public void setInvitationHandler (InvitationHandler handler)
|
||||
{
|
||||
_handler = handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified observer to the list of entities that are
|
||||
* notified when we receive a game ready notification.
|
||||
*/
|
||||
public void addGameReadyObserver (GameReadyObserver observer)
|
||||
{
|
||||
_grobs.add(observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified observer from the list of entities that are
|
||||
* notified when we receive a game ready notification.
|
||||
*/
|
||||
public void removeGameReadyObserver (GameReadyObserver observer)
|
||||
{
|
||||
_grobs.remove(observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that the named user be invited to a game described by the
|
||||
* supplied game config.
|
||||
*
|
||||
* @param invitee the user to invite.
|
||||
* @param config the configuration of the game to which the user is
|
||||
* being invited.
|
||||
* @param observer the entity that will be notified if this invitation
|
||||
* is accepted, refused or countered.
|
||||
*
|
||||
* @return an invitation object that can be used to manage the
|
||||
* outstanding invitation.
|
||||
*/
|
||||
public Invitation invite (Name invitee, GameConfig config,
|
||||
InvitationResponseObserver observer)
|
||||
{
|
||||
// create the invitation record
|
||||
Invitation invite = new Invitation(
|
||||
_ctx, _pservice, invitee, config, observer);
|
||||
// submit the invitation request to the server
|
||||
_pservice.invite(_ctx.getClient(), invitee, config, invite);
|
||||
// and return the invitation to the caller
|
||||
return invite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that the specified single player game be started.
|
||||
*
|
||||
* @param config the configuration of the single player game to be
|
||||
* started.
|
||||
* @param listener a listener to be informed of failure if the game
|
||||
* cannot be started.
|
||||
*/
|
||||
public void startSolitaire (
|
||||
GameConfig config, InvocationService.ConfirmListener listener)
|
||||
{
|
||||
_pservice.startSolitaire(_ctx.getClient(), config, listener);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void clientDidLogoff (Client client)
|
||||
{
|
||||
super.clientDidLogoff(client);
|
||||
_pservice = null;
|
||||
_pendingInvites.clear();
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected void fetchServices (Client client)
|
||||
{
|
||||
// get a handle on our parlor services
|
||||
_pservice = (ParlorService)client.requireService(ParlorService.class);
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public void gameIsReady (int gameOid)
|
||||
{
|
||||
Log.info("Handling game ready [goid=" + gameOid + "].");
|
||||
|
||||
// see what our observers have to say about it
|
||||
boolean handled = false;
|
||||
for (int i = 0; i < _grobs.size(); i++) {
|
||||
GameReadyObserver grob = (GameReadyObserver)_grobs.get(i);
|
||||
handled = grob.receivedGameReady(gameOid) || handled;
|
||||
}
|
||||
|
||||
// if none of the observers took matters into their own hands,
|
||||
// then we'll head on over to the game room ourselves
|
||||
if (!handled) {
|
||||
_ctx.getLocationDirector().moveTo(gameOid);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public void receivedInvite (int remoteId, Name inviter, GameConfig config)
|
||||
{
|
||||
// create an invitation record for this invitation
|
||||
Invitation invite = new Invitation(
|
||||
_ctx, _pservice, inviter, config, null);
|
||||
invite.inviteId = remoteId;
|
||||
|
||||
// put it in the pending invitations table
|
||||
_pendingInvites.put(remoteId, invite);
|
||||
|
||||
try {
|
||||
// notify the invitation handler of the incoming invitation
|
||||
_handler.invitationReceived(invite);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.warning("Invitation handler choked on invite " +
|
||||
"notification " + invite + ".");
|
||||
Log.logStackTrace(e);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public void receivedInviteResponse (
|
||||
int remoteId, int code, Object arg)
|
||||
{
|
||||
// look up the invitation record for this invitation
|
||||
Invitation invite = (Invitation)_pendingInvites.get(remoteId);
|
||||
if (invite == null) {
|
||||
Log.warning("Have no record of invitation for which we " +
|
||||
"received a response?! [remoteId=" + remoteId +
|
||||
", code=" + code + ", arg=" + arg + "].");
|
||||
|
||||
} else {
|
||||
invite.receivedResponse(code, arg);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public void receivedInviteCancellation (int remoteId)
|
||||
{
|
||||
// TBD
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new invitation in our pending invitations table. The
|
||||
* invitation will call this when it knows its invitation id.
|
||||
*/
|
||||
protected void registerInvitation (Invitation invite)
|
||||
{
|
||||
_pendingInvites.put(invite.inviteId, invite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by an invitation when it knows it is no longer and can be
|
||||
* cleared from the pending invitations table.
|
||||
*/
|
||||
protected void clearInvitation (Invitation invite)
|
||||
{
|
||||
_pendingInvites.remove(invite.inviteId);
|
||||
}
|
||||
|
||||
/** An active parlor context. */
|
||||
protected ParlorContext _ctx;
|
||||
|
||||
/** Provides access to parlor server side services. */
|
||||
protected ParlorService _pservice;
|
||||
|
||||
/** The entity that has registered itself to handle incoming
|
||||
* invitation notifications. */
|
||||
protected InvitationHandler _handler;
|
||||
|
||||
/** A table of acknowledged (but not yet accepted or refused)
|
||||
* invitation requests, keyed on invitation id. */
|
||||
protected HashIntMap _pendingInvites = new HashIntMap();
|
||||
|
||||
/** We notify the entities on this list when we get a game ready
|
||||
* notification. */
|
||||
protected ArrayList _grobs = new ArrayList();
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
//
|
||||
// $Id: ParlorReceiver.java 3381 2005-03-03 19:36:34Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.threerings.util.Name;
|
||||
|
||||
import com.threerings.presents.client.InvocationReceiver;
|
||||
|
||||
import com.threerings.parlor.data.ParlorCodes;
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
|
||||
/**
|
||||
* Defines, for the parlor services, a set of notifications delivered
|
||||
* asynchronously by the server to the client. These are handled by the
|
||||
* {@link ParlorDirector}.
|
||||
*/
|
||||
public interface ParlorReceiver extends InvocationReceiver
|
||||
{
|
||||
/**
|
||||
* Dispatched to the client when a game in which they are a
|
||||
* participant is ready for play. The client will then enter the game
|
||||
* room which will trigger the loading of the appropriate game UI code
|
||||
* and generally get things started.
|
||||
*
|
||||
* @param gameOid the object id of the game object.
|
||||
*/
|
||||
public void gameIsReady (int gameOid);
|
||||
|
||||
/**
|
||||
* Called by the invocation services when another user has invited us
|
||||
* to play a game.
|
||||
*
|
||||
* @param remoteId the unique indentifier for this invitation (used
|
||||
* when countering or responding).
|
||||
* @param inviter the username of the inviting user.
|
||||
* @param config the configuration information for the game to which
|
||||
* we've been invited.
|
||||
*/
|
||||
public void receivedInvite (int remoteId, Name inviter, GameConfig config);
|
||||
|
||||
/**
|
||||
* Called by the invocation services when another user has responded
|
||||
* to our invitation by either accepting, refusing or countering it.
|
||||
*
|
||||
* @param remoteId the indentifier for the invitation on question.
|
||||
* @param code the response code, either {@link
|
||||
* ParlorCodes#INVITATION_ACCEPTED} or {@link
|
||||
* ParlorCodes#INVITATION_REFUSED} or {@link
|
||||
* ParlorCodes#INVITATION_COUNTERED}.
|
||||
* @param arg in the case of a refused invitation, a string
|
||||
* containing a message provided by the invited user explaining the
|
||||
* reason for refusal (the empty string if no explanation was
|
||||
* provided). In the case of a countered invitation, a new game config
|
||||
* object with the modified game configuration.
|
||||
*/
|
||||
public void receivedInviteResponse (int remoteId, int code, Object arg);
|
||||
|
||||
/**
|
||||
* Called by the invocation services when an outstanding invitation
|
||||
* has been cancelled by the inviting user.
|
||||
*
|
||||
* @param remoteId the indentifier of the cancelled invitation.
|
||||
*/
|
||||
public void receivedInviteCancellation (int remoteId);
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
//
|
||||
// $Id: ParlorService.java 3525 2005-04-26 02:38:42Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.threerings.util.Name;
|
||||
|
||||
import com.threerings.presents.client.Client;
|
||||
import com.threerings.presents.client.InvocationService;
|
||||
|
||||
import com.threerings.parlor.data.TableConfig;
|
||||
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
|
||||
/**
|
||||
* Provides an interface to the various parlor invocation services.
|
||||
* Presently these services are limited to the various matchmaking
|
||||
* mechanisms. It is unlikely that client code will want to make direct
|
||||
* use of this class, instead they would make use of the programmatic
|
||||
* interface provided by the {@link ParlorDirector}.
|
||||
*/
|
||||
public interface ParlorService extends InvocationService
|
||||
{
|
||||
/**
|
||||
* Used to communicate responses to {@link #invite} requests.
|
||||
*/
|
||||
public static interface InviteListener extends InvocationListener
|
||||
{
|
||||
/**
|
||||
* Called in response to a successful {@link #invite} request.
|
||||
*/
|
||||
public void inviteReceived (int inviteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* You probably don't want to call this directly, but want to generate
|
||||
* your invitation request via {@link ParlorDirector#invite}. Requests
|
||||
* that an invitation be delivered to the named user, requesting that
|
||||
* they join the inviting user in a game, the details of which are
|
||||
* specified in the supplied game config object.
|
||||
*
|
||||
* @param client a connected, operational client instance.
|
||||
* @param invitee the username of the user to be invited.
|
||||
* @param config a game config object detailing the type and
|
||||
* configuration of the game to be created.
|
||||
* @param listener will receive and process the response.
|
||||
*/
|
||||
public void invite (Client client, Name invitee, GameConfig config,
|
||||
InviteListener listener);
|
||||
|
||||
/**
|
||||
* You probably don't want to call this directly, but want to call one
|
||||
* of {@link Invitation#accept}, {@link Invitation#refuse}, or {@link
|
||||
* Invitation#counter}. Requests that an invitation response be
|
||||
* delivered with the specified parameters.
|
||||
*
|
||||
* @param client a connected, operational client instance.
|
||||
* @param inviteId the unique id previously assigned by the server to
|
||||
* this invitation.
|
||||
* @param code the response code to use in responding to the
|
||||
* invitation.
|
||||
* @param arg the argument associated with the response (a string
|
||||
* message from the player explaining why the response was refused in
|
||||
* the case of an invitation refusal or an updated game configuration
|
||||
* object in the case of a counter-invitation, or null in the case of
|
||||
* an accepted invitation).
|
||||
* @param listener will receive and process the response.
|
||||
*/
|
||||
public void respond (Client client, int inviteId, int code, Object arg,
|
||||
InvocationListener listener);
|
||||
|
||||
/**
|
||||
* You probably don't want to call this directly, but want to call
|
||||
* {@link Invitation#cancel}. Requests that an outstanding
|
||||
* invitation be cancelled.
|
||||
*
|
||||
* @param client a connected, operational client instance.
|
||||
* @param inviteId the unique id previously assigned by the server to
|
||||
* this invitation.
|
||||
* @param listener will receive and process the response.
|
||||
*/
|
||||
public void cancel (Client client, int inviteId,
|
||||
InvocationListener listener);
|
||||
|
||||
/**
|
||||
* Used to communicate responses to {@link #createTable}, {@link
|
||||
* #joinTable}, and {@link #leaveTable} requests.
|
||||
*/
|
||||
public static interface TableListener extends InvocationListener
|
||||
{
|
||||
public void tableCreated (int tableId);
|
||||
}
|
||||
|
||||
/**
|
||||
* You probably don't want to call this directly, but want to call
|
||||
* {@link TableDirector#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 tableConfig the table configuration parameters.
|
||||
* @param config the game config for the game to be matchmade by the
|
||||
* table.
|
||||
* @param listener will receive and process the response.
|
||||
*/
|
||||
public void createTable (Client client, int lobbyOid,
|
||||
TableConfig tableConfig, GameConfig config, TableListener listener);
|
||||
|
||||
/**
|
||||
* You probably don't want to call this directly, but want to call
|
||||
* {@link TableDirector#joinTable}. Requests that the current user
|
||||
* be added to the specified table at the specified position.
|
||||
*
|
||||
* @param client a connected, operational client instance.
|
||||
* @param lobbyOid the oid of the lobby that contains the table.
|
||||
* @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 listener will receive and process the response.
|
||||
*/
|
||||
public void joinTable (Client client, int lobbyOid, int tableId,
|
||||
int position, InvocationListener listener);
|
||||
|
||||
/**
|
||||
* You probably don't want to call this directly, but want to call
|
||||
* {@link TableDirector#leaveTable}. Requests that the current user be
|
||||
* removed from the specified table.
|
||||
*
|
||||
* @param client a connected, operational client instance.
|
||||
* @param lobbyOid the oid of the lobby that contains the table.
|
||||
* @param tableId the unique id of the table from which this user
|
||||
* wishes to be removed.
|
||||
* @param listener will receive and process the response.
|
||||
*/
|
||||
public void leaveTable (Client client, int lobbyOid, int tableId,
|
||||
InvocationListener listener);
|
||||
|
||||
/**
|
||||
* Requests to start a single player game with the specified game
|
||||
* configuration.
|
||||
*/
|
||||
public void startSolitaire (Client client, GameConfig config,
|
||||
ConfirmListener listener);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// $Id: SeatednessObserver.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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;
|
||||
|
||||
/**
|
||||
* 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 TableDirector}.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.threerings.parlor.util.ParlorContext;
|
||||
|
||||
import com.threerings.parlor.data.TableConfig;
|
||||
|
||||
import com.threerings.parlor.game.client.GameConfigurator;
|
||||
|
||||
/**
|
||||
* This should be implemented some user-interface element that allows
|
||||
* the user to configure whichever TableConfig options are relevant.
|
||||
*/
|
||||
public abstract class TableConfigurator
|
||||
{
|
||||
/**
|
||||
* Create a TableConfigurator.
|
||||
*/
|
||||
public TableConfigurator ()
|
||||
{
|
||||
_config = createTableConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* Optionally, you can set a pre-configured TableConfig
|
||||
* that will be used to initialize the display parameters (if possible).
|
||||
* This should be called prior to init().
|
||||
*/
|
||||
public void setTableConfig (TableConfig config)
|
||||
{
|
||||
if (config != null) {
|
||||
_config = config;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the TableConfigurator.
|
||||
*
|
||||
* At the time this is called, the GameConfigurator should have
|
||||
* already been initialized.
|
||||
*/
|
||||
public void init (ParlorContext ctx, GameConfigurator gameConfigurator)
|
||||
{
|
||||
_ctx = ctx;
|
||||
_gameConfigurator = gameConfigurator;
|
||||
createConfigInterface();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the table config object that will be used.
|
||||
*/
|
||||
protected TableConfig createTableConfig ()
|
||||
{
|
||||
return new TableConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the config interface.
|
||||
*/
|
||||
protected void createConfigInterface ()
|
||||
{
|
||||
// nothing by default
|
||||
}
|
||||
|
||||
/**
|
||||
* If true, the TableConfigurator is empty, which doesn't mean that
|
||||
* it will not return a TableConfig object (for it must), but rather
|
||||
* that there are no user-editable options being presented in the
|
||||
* config interface.
|
||||
*/
|
||||
public abstract boolean isEmpty ();
|
||||
|
||||
/**
|
||||
* Return the fully configured table config according to the currently
|
||||
* configured user interface elements.
|
||||
*/
|
||||
public TableConfig getTableConfig ()
|
||||
{
|
||||
flushTableConfig();
|
||||
return _config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Derived classes will want to override this method, flushing
|
||||
* values from the user interface to the table config object.
|
||||
*/
|
||||
protected void flushTableConfig ()
|
||||
{
|
||||
// nothing by default
|
||||
}
|
||||
|
||||
/** Provides access to client services. */
|
||||
protected ParlorContext _ctx;
|
||||
|
||||
/** The config we're configurating. */
|
||||
protected TableConfig _config;
|
||||
|
||||
/** The game configurator, which we may wish to reference. */
|
||||
protected GameConfigurator _gameConfigurator;
|
||||
}
|
||||
@@ -0,0 +1,363 @@
|
||||
//
|
||||
// $Id: TableDirector.java 3758 2005-11-10 23:18:58Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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 java.util.ArrayList;
|
||||
|
||||
import com.threerings.presents.client.BasicDirector;
|
||||
import com.threerings.presents.client.Client;
|
||||
|
||||
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.crowd.data.PlaceObject;
|
||||
|
||||
import com.threerings.parlor.Log;
|
||||
import com.threerings.parlor.data.Table;
|
||||
import com.threerings.parlor.data.TableConfig;
|
||||
import com.threerings.parlor.data.TableLobbyObject;
|
||||
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.
|
||||
*
|
||||
* <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.
|
||||
*/
|
||||
public class TableDirector extends BasicDirector
|
||||
implements SetListener, ParlorService.TableListener
|
||||
{
|
||||
/**
|
||||
* 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. 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 director 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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 (_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
|
||||
_pservice.createTable(_ctx.getClient(), _lobby.getOid(), 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 (_lobby == 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(_ctx.getClient(), _lobby.getOid(), 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;
|
||||
}
|
||||
|
||||
// issue the leave request
|
||||
_pservice.leaveTable(_ctx.getClient(), _lobby.getOid(), tableId, this);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void clientDidLogoff (Client client)
|
||||
{
|
||||
super.clientDidLogoff(client);
|
||||
_pservice = null;
|
||||
_lobby = null;
|
||||
_ourTable = null;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected void fetchServices (Client client)
|
||||
{
|
||||
// get a handle on our parlor services
|
||||
_pservice = (ParlorService)client.requireService(ParlorService.class);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void entryAdded (EntryAddedEvent event)
|
||||
{
|
||||
if (event.getName().equals(_tableField)) {
|
||||
Table 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 = (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)) {
|
||||
Integer tableId = (Integer)event.getKey();
|
||||
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public void tableCreated (int tableId)
|
||||
{
|
||||
// nothing much to do here
|
||||
Log.info("Table creation succeeded [tableId=" + tableId + "].");
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public void requestFailed (String reason)
|
||||
{
|
||||
Log.warning("Table creation failed [reason=" + 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();
|
||||
for (int i = 0; i < table.occupants.length; i++) {
|
||||
if (self.getVisibleName().equals(table.occupants[i])) {
|
||||
_ourTable = table;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** A context by which we can access necessary client services. */
|
||||
protected ParlorContext _ctx;
|
||||
|
||||
/** Parlor server-side services. */
|
||||
protected ParlorService _pservice;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** An array of entities that want to hear about when we stand up or
|
||||
* sit down. */
|
||||
protected ArrayList _seatedObservers = new ArrayList();
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
//
|
||||
// $Id: TableObserver.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.threerings.parlor.data.Table;
|
||||
|
||||
/**
|
||||
* The {@link TableDirector} 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);
|
||||
}
|
||||
Reference in New Issue
Block a user