Moving host coordinator into vilya.

git-svn-id: svn+ssh://src.earth.threerings.net/vilya/trunk@198 c613c5cb-e716-0410-b11b-feb51c14d237
This commit is contained in:
Robert Zubeck
2007-02-19 23:21:28 +00:00
parent e8ada1ac88
commit fa7bf73ddc
2 changed files with 238 additions and 0 deletions
@@ -0,0 +1,205 @@
package com.threerings.ezgame {
import flash.events.EventDispatcher;
/**
HostCoordinator provides methods for determining whether the current
client should consider itself the authority in dealing with game state
(for example, when dealing out cards, or setting up the game board).
Current hosting state can be retrieved from the /status/ property.
Please note that hosting authority can be transferred between clients
at any moment, so all clients should be prepared to suddenly take
over host responsibilities.
Additionally, the client can register itself for notifications
about changes to the /status/ property - see HostEvent.
Usage example:
<pre>
_coord = new HostCoordinator (_gameCtrl);
_coord.addEventListener (HostEvent.CLAIMED, firstHostHandler);
_coord.addEventListener (HostEvent.CHANGED, hostChangeHandler);
...
function firstHostHandler (event : HostEvent)
{
if (_coord.status == HostCoordinator.STATUS_HOST)
{
// I'm the first host in the game - I should set up the initial board, etc.
}
}
function hostChangeHandler (event : HostEvent)
{
if (_coord.status == HostCoordinator.STATUS_HOST)
{
// I just became the host - do whatever is needed.
}
}
</pre>
*/
public class HostCoordinator
extends EventDispatcher
implements OccupantChangedListener, PropertyChangedListener
{
// CONSTANTS
/** Status constant, means that the current status is unknown, either because
the data had not yet arrived from the server, or because nobody claims
to be host for this game. */
public static const STATUS_UNKNOWN : String = "STATUS_UNKNOWN";
/** Status constant, means that this client is the current host. */
public static const STATUS_HOST : String = "STATUS_HOST";
/** Status constant, means that some other client is the current host. */
public static const STATUS_NOT_HOST : String = "STATUS_NOT_HOST";
// PUBLIC INTERFACE
/**
Constructor, expects an initialized instance of EZGameControl.
If the optional showDebug flag is set, it will display host info
as chat messages (only useful for debugging).
*/
public function HostCoordinator (control : EZGameControl, showDebug : Boolean = false)
{
_control = control;
_control.registerListener (this);
_showDebug = showDebug;
// Try set host role if it's not already claimed (i.e. null)
debugLog ("Trying to claim host role.");
debugLog ("Current status: " + status);
tryReplaceHost (null);
}
/**
Retrieves current host coordination status, as one of the STATUS_*
constants.
Note: do not save the value of this property. Hosting status
can change at any moment: when the current host quits the game,
any client can suddenly become the new host.
l */
public function get status () : String
{
var hostId : Number = getHostId ();
if (hostId == _control.getMyId ()) { return STATUS_HOST; }
if (hostId > 0) { return STATUS_NOT_HOST; }
return STATUS_UNKNOWN;
}
// EVENT HANDLERS
/** From OccupantChangedListener: keep track of people coming in */
public function occupantEntered (event : OccupantChangedEvent) : void
{
debugHostStatus ();
}
/** From OccupantChangedListener: keep track of people leaving */
public function occupantLeft (event : OccupantChangedEvent) : void
{
// If the occupant who just left was the host, every client will
// get a shot at trying to claim their role.
debugLog ("My ID: " + _control.getMyId ());
debugLog ("Occupant left: " + event.occupantId);
debugLog ("Current host: " + getHostId());
if (getHostId () == event.occupantId) // Elvis has left the building
{
debugLog ("Removing the old host...");
// Clear the old host value, and put myself in their place.
// Only the first client will succeed in doing this.
tryReplaceHost (event.occupantId);
}
}
/** From PropertyChangedListener: keep track of changing host values */
public function propertyChanged (event : PropertyChangedEvent) : void
{
if (event.name == HOST_NAME)
{
debugLog ("Host variable changed to: " + event.newValue);
// if the host was not known before, dispatch the claimed event
if (event.oldValue == null &&
event.newValue != null)
{
var claimed : HostEvent = new HostEvent (HostEvent.CLAIMED, _control);
this.dispatchEvent (claimed);
}
// always dispatch the changed event
var changed : HostEvent = new HostEvent (HostEvent.CHANGED, _control);
this.dispatchEvent (changed);
}
}
// PRIVATE FUNCTIONS
/** Get the current host ID (will be 0 if there is no authoritative host) */
private function getHostId () : Number
{
var hostvalue : Object = _control.get (HOST_NAME);
if (hostvalue != null && hostvalue is Number)
{
return hostvalue as Number;
}
return 0;
}
/** Helper function: tries to set the host variable to the client's id,
if the current value is equal to /hostId/. If the value of null for
hostId has the meaning of "set me as host only if the role has not
been claimed yet". */
private function tryReplaceHost (hostId : Object) : void
{
_control.testAndSet (HOST_NAME, _control.getMyId (), hostId);
debugHostStatus ();
}
/** Debug only */
private function debugLog (message : String) : void
{
if (_showDebug) { _control.localChat (message); }
}
/** Debug only */
private function debugHostStatus () : void
{
debugLog (
(status == STATUS_HOST ? "I am" : "I'm not") +
" the host (id " + getHostId() + ", mine is " + _control.getMyId() + ")");
}
// PRIVATE VALUES
/** Magic key that stores current authoritative host */
private var HOST_NAME : String = "HOST_COORDINATOR_AUTHORITATIVE_HOST";
/** Controller storage */
private var _control : EZGameControl = null;
/** Debug flag */
private var _showDebug : Boolean;
}
}
+33
View File
@@ -0,0 +1,33 @@
package com.threerings.ezgame {
import flash.events.Event;
/**
* Dispatched by the host coordinator, to signal a change
* in host status.
*/
public class HostEvent extends EZEvent
{
/** Indicates that the current host changed. */
public static const CHANGED :String = "Host Changed";
/** Indicates that the host used to be unknown, but it became claimed
by one of the clients. */
public static const CLAIMED :String = "Host Claimed";
public function HostEvent (type :String, ezgame :EZGameControl)
{
super (type, ezgame);
}
override public function toString () :String
{
return "[HostEvent type=" + type + "]";
}
override public function clone () :Event
{
return new HostEvent (type, _ezgame);
}
}
}