Progress on Ye Olde Parlor services.

git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@363 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2001-10-01 02:56:35 +00:00
parent 278e1f0f6e
commit 2139d4883a
10 changed files with 519 additions and 0 deletions
+38
View File
@@ -0,0 +1,38 @@
//
// $Id: Log.java,v 1.1 2001/10/01 02:56:35 mdb Exp $
package com.threerings.parlor;
/**
* A placeholder class that contains a reference to the log object used by
* the Parlor services.
*/
public class Log
{
public static com.samskivert.util.Log log =
new com.samskivert.util.Log("parlor");
/** Convenience function. */
public static void debug (String message)
{
log.debug(message);
}
/** Convenience function. */
public static void info (String message)
{
log.info(message);
}
/** Convenience function. */
public static void warning (String message)
{
log.warning(message);
}
/** Convenience function. */
public static void logStackTrace (Throwable t)
{
log.logStackTrace(com.samskivert.util.Log.WARNING, t);
}
}
@@ -0,0 +1,37 @@
//
// $Id: InvitationResponseObserver.java,v 1.1 2001/10/01 02:56:35 mdb Exp $
package com.threerings.parlor.client;
/**
* A client entity that wishes to generate invitations for games must
* implement this interface. An invitation can be accepted, rejected 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 InvitationObserver
{
/**
* Called if the invitation was accepted.
*/
public void invitationAccepted (int inviteId);
/**
* Called if the invitation was rejected.
*
* @param message a message provided by the rejecting user explaining
* the reason for their rejection, or the empty string if no message
* was provided.
*/
public void invitationRejected (int inviteId, String message);
/**
* Called if the invitation was countered with an alternate game
* configuration.
*
* @param config the game configuration proposed by the invited
* player.
*/
public void invitationCountered (int inviteId, GameConfig config);
}
@@ -0,0 +1,183 @@
//
// $Id: ParlorDirector.java,v 1.1 2001/10/01 02:56:35 mdb Exp $
package com.threerings.parlor.client;
import com.samskivert.util.HashIntMap;
import com.threerings.parlor.Log;
import com.threerings.parlor.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
{
/**
* 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 wants to know about accepted,
* rejected or countered invitations.
*
* @return a unique id associated with this invitation that can be
* used to discern between various outstanding invitations by the
* invitation observer.
*/
public int invite (ParlorContext ctx, String invitee,
GameConfig config, InvitationObserver observer)
{
// generate the invocation service request
int invid = ParlorService.invite(
ctx.getClient(), invitee, config, this);
// create an invitation record and put it in the submitted table
Invitation invite = new Invitation(invitee, config, observer);
_submittedInvites.put(invid, invite);
return invite.localId;
}
public void counter (ParlorContext ctx, int inviteId,
GameConfig config, InvitationObserver observer)
{
}
/**
* 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 handleInviteNotification (
int remoteId, String inviter, GameConfig config)
{
}
/**
* Called by the invocation services when another user has responded
* to our invitation.
*
* @param remoteId the unique indentifier for the invitation.
* @param code the response code {@link
* ParlorService#INVITATION_ACCEPTED} or {@link
* ParlorService#INVITATION_REJECTED}.
* @param message in the case of a rejected invitation, a message
* provided by the invited user explaining the rejection. The empty
* string if no explanation was provided.
*/
public void handleResponseNotification (
int remoteId, int code, String message)
{
}
/**
* Called by the invocation services when another user has invited us
* to play a game.
*
* @param inviter the username of the inviting user.
* @param config the configuration information for the game to which
* we've been invited.
*/
public void handleInviteNotification (String inviter, GameConfig config)
{
}
/**
* Called by the invocation services when an invitation request was
* received by the server and delivered to the intended invitee.
*
* @param invid the invocation id of the invitation request.
*/
public void handleInviteReceived (int invid, int remoteId)
{
// remove the invitation record from the submitted table and put
// it in the pending table
Invitation invite = (Invitation)_submittedInvites.get(invid);
if (invite == null) {
Log.warning("Received accepted notification for non-existent " +
"invitation request!? [invid=" + invid +
", remoteId=" + remoteId + "].");
return;
}
// now that we know the invitation's unique id, keep track of it
invite.remoteId = remoteId;
// and put it in the new table
_pendingInvites.put(remoteId, invite);
}
/**
* Called by the invocation services when an invitation request failed
* or was rejected for some reason.
*
* @param invid the invocation id of the invitation request.
* @param reason a reason code explaining the rejection or failure.
*/
public void handleInviteFailed (int invid, String reason)
{
}
protected static class Invitation
{
/** A unique id for this invitation assigned on the client which
* is only used to allow the invitation observers to discriminate
* between multiple outstanding invitations. We'd use the remote
* id here except that that is not known until we receive the
* acknowlegedment from the server and we need to provide the
* caller with some sort of unique id at the time the request is
* generated. */
public int localId = _localInvitationId++;
/** 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 remoteId = -1;
/** The name of the user that was invited. */
public String invitee;
/** The configuration of the game to be created. */
public GameConfig config;
/** The invitation observer that created this invitation. */
public InvitationObserver observer;
/** A flag indicating that we were requested to abort this
* invitation before we even heard back with an acknowledgement
* that it was received by the server. */
public boolean aborted = false;
/** Constructs a new invitation request. */
public Invitation (String invitee, GameConfig config,
InvitationObserver observer)
{
this.invitee = invitee;
this.config = config;
this.observer = observer;
}
}
/** A table of submitted (but not acknowledged) invitation requests,
* keyed on invocation request id. */
protected HashIntMap _submittedInvites = new HashIntMap();
/** A table of acknowledged (but not yet accepted or refused)
* invitation requests, keyed on invitation id. */
protected HashIntMap _pendingInvites = new HashIntMap();
/** A counter used to assign a unique id to every invitation. */
protected static int _localInvitationId = 0;
}
@@ -0,0 +1,82 @@
//
// $Id: ParlorService.java,v 1.1 2001/10/01 02:56:35 mdb Exp $
package com.threerings.parlor.client;
import com.threerings.cocktail.cher.client.Client;
import com.threerings.cocktail.cher.client.InvocationManager;
import com.threerings.parlor.Log;
import com.threerings.parlor.data.GameConfig;
/**
* This class provides an interface to the various parlor services that
* are directly invokable by the client (by means of the 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}.
*
* @see ParlorDirector
*/
public class ParlorService
{
/** The module name for the parlor services. */
public static final String MODULE = "parlor";
/** The message identifier for an invitation creation request. */
public static final String INVITE_REQUEST = "Invite";
/** The message identifier for an invitation notification. */
public static final String INVITE_NOTIFICATION = "Invite";
/** The message identifier for an invitation response request. */
public static final String RESPONSE_REQUEST = "Response";
/** The message identifier for an invitation response notification. */
public static final String RESPONSE_NOTIFICATION = "Response";
/** The response code for an accepted invitation. */
public static final int INVITATION_ACCEPTED = 0;
/** The response code for a rejected invitation. */
public static final int INVITATION_REJECTED = 1;
/** The message identifier for an counter invitation request. */
public static final String COUNTER_REQUEST = "Counter";
/** The message identifier for an countered invitation notification. */
public static final String COUNTER_NOTIFICATION = "Counter";
/** The message identifier for an rescind invitation request. */
public static final String RESCIND_REQUEST = "Rescind";
/** The message identifier for an rescinded invitation notification. */
public static final String RESCIND_NOTIFICATION = "Rescind";
/**
* 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 rsptarget the parlor director reference that will receive and
* process the response.
*
* @return the invocation request id of the generated request.
*/
public static int invite (Client client, String invitee,
GameConfig config, Object rsptarget)
{
InvocationManager invmgr = client.getInvocationManager();
Object[] args = new Object[] { invitee, config };
Log.info("Sending invite request [to=" + invitee +
", cfg=" + config + "].");
return invmgr.invoke(MODULE, INVITE_REQUEST, args, rsptarget);
}
}
@@ -0,0 +1,44 @@
//
// $Id: GameConfig.java,v 1.1 2001/10/01 02:56:35 mdb Exp $
package com.threerings.parlor.data;
import java.io.IOException;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import com.threerings.cocktail.cher.io.Streamable;
/**
* The game config class encapsulates the configuration information for a
* particular type of game. The hierarchy of game config objects mimics
* the hierarchy of game managers and the client provides a game config
* object to the game manager at game creation time which is used to set
* the game's configuration options.
*
* <p> A game that has specific configuration needs would extend this
* class (or an appropriate subclass) adding it's configuration
* information, and also overriding {@link #writeTo} and {@link #readFrom}
* to provide code to effect the necessary serialization and
* unserialization of the added fields.
*
* <p> The implementation of the client-side of the game can either use
* the code provided for obtaining configuration parameters from the user,
* or provide its own specialized configuration interface. It need only
* produce a game config object when the configuration process is complete
* and provide that to the server along with the game creation request.
*/
public class GameConfig implements Streamable
{
// documentation inherited
public void writeTo (DataOutputStream out)
throws IOException
{
}
// documentation inherited
public void readFrom (DataInputStream in)
throws IOException
{
}
}
@@ -0,0 +1,16 @@
//
// $Id: GameManager.java,v 1.1 2001/10/01 02:56:35 mdb Exp $
package com.threerings.parlor.server;
import java.util.Properties;
import com.threerings.cocktail.party.server.PlaceManager;
import com.threerings.cocktail.party.server.PlaceRegistry;
public class GameManager extends PlaceManager
{
public void init (PlaceRegistry registry, Properties config)
{
}
}
@@ -0,0 +1,22 @@
//
// $Id: GameObject.dobj,v 1.1 2001/10/01 02:56:35 mdb Exp $
package com.threerings.parlor.data;
import com.threerings.cocktail.party.data.PlaceObject;
/**
* A game object hosts the shared data associated with a game played by
* one or more players. The game object extends the place object so that
* the game can act as a place where players actually go when playing the
* game. Only very basic information is maintained in the base game
* object. It serves as the base for a hierarchy of game object
* derivatives that handle basic gameplay for a suite of different game
* types (ie. turn based games, party games, board games, card games,
* etc.).
*/
public class GameObject extends PlaceObject
{
/** Indicates whether or not this game is rated. */
public boolean isRated;
}
@@ -0,0 +1,35 @@
//
// $Id: ParlorManager.java,v 1.1 2001/10/01 02:56:35 mdb Exp $
package com.threerings.parlor.server;
import com.samskivert.util.Config;
import com.threerings.cocktail.cher.server.InvocationManager;
import com.threerings.parlor.client.ParlorService;
/**
* The parlor manager is responsible for the parlor services in
* aggregate. This includes maintaining the registry of active games,
* handling the necessary coordination for the matchmaking services and
* anything else that falls outside the scope of an actual in-progress
* game.
*/
public class ParlorManager
{
/**
* Initializes the parlor manager. This should be called by the server
* that is making use of the parlor services on the single instance of
* parlor manager that it has created.
*
* @param config the configuration object in use by this server.
* @param invmgr a reference to the invocation manager in use by this
* server.
*/
public void init (Config config, InvocationManager invmgr)
{
// register our invocation provider
ParlorProvider pprov = new ParlorProvider(this);
invmgr.registerProvider(ParlorService.MODULE, pprov);
}
}
@@ -0,0 +1,43 @@
//
// $Id: ParlorProvider.java,v 1.1 2001/10/01 02:56:35 mdb Exp $
package com.threerings.parlor.server;
import com.threerings.cocktail.cher.server.InvocationProvider;
import com.threerings.cocktail.party.data.BodyObject;
import com.threerings.parlor.data.GameConfig;
/**
* The parlor provider handles the server side of the various Parlor
* services that are made available for direct invocation by the client.
* Primarily these are the matchmaking mechanisms.
*/
public class ParlorProvider extends InvocationProvider
{
/**
* Constructs a parlor provider instance which will be used to handle
* all parlor-related invocation service requests. This is
* automatically taken care of by the parlor manager, so no other
* entity need instantiate and register a parlor provider.
*
* @param pmgr a reference to the parlor manager active in this
* server.
*/
public ParlorProvider (ParlorManager pmgr)
{
_pmgr = pmgr;
}
/**
* Processes a request from the client to invite another user to play
* a game.
*/
public void handleInviteRequest (
BodyObject source, int invid, String invitee, GameConfig config)
{
}
/** A reference to the parlor manager we're working with. */
protected ParlorManager _pmgr;
}
@@ -0,0 +1,19 @@
//
// $Id: ParlorContext.java,v 1.1 2001/10/01 02:56:35 mdb Exp $
package com.threerings.parlor.util;
import com.threerings.cocktail.party.util.PartyContext;
import com.threerings.parlor.client.ParlorDirector;
/**
* The parlor context provides access to the various managers, etc. that
* are needed by the parlor client code.
*/
public interface ParlorContext extends PartyContext
{
/**
* Returns a reference to the parlor director.
*/
public ParlorDirector getParlorDirector ();
}