Split Vilya into core and aslib submodules.
This ensures that our ActionScript artifact is properly published to Maven Central for all to use. I'm still putting off creating vilya-tools. Later, later...
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// $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.whirled.client {
|
||||
|
||||
import com.threerings.whirled.data.SceneModel;
|
||||
|
||||
/**
|
||||
* Contains information on a pending scene change.
|
||||
*/
|
||||
public class PendingData
|
||||
{
|
||||
/** The id of the scene to which we are moving. */
|
||||
public var sceneId :int;
|
||||
|
||||
/** The cached scene model for the scene to which wer'e moving, or null. */
|
||||
public var model :SceneModel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
//
|
||||
// $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.whirled.client {
|
||||
|
||||
import com.threerings.presents.dobj.MessageAdapter;
|
||||
import com.threerings.presents.dobj.MessageEvent;
|
||||
import com.threerings.presents.dobj.MessageListener;
|
||||
|
||||
import com.threerings.crowd.client.PlaceController;
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
import com.threerings.crowd.data.PlaceObject;
|
||||
import com.threerings.crowd.util.CrowdContext;
|
||||
|
||||
import com.threerings.whirled.data.SceneCodes;
|
||||
import com.threerings.whirled.data.SceneUpdate;
|
||||
import com.threerings.whirled.util.WhirledContext;
|
||||
|
||||
/**
|
||||
* The base scene controller class. It is expected that users of the
|
||||
* Whirled services will extend this controller class when creating
|
||||
* specialized controllers for their scenes.
|
||||
*/
|
||||
public /*abstract*/ class SceneController extends PlaceController
|
||||
{
|
||||
// documentation inherited
|
||||
override public function init (ctx :CrowdContext, config :PlaceConfig) :void
|
||||
{
|
||||
super.init(ctx, config);
|
||||
_wctx = WhirledContext(ctx);
|
||||
|
||||
_updateListener = new MessageAdapter(
|
||||
function (event :MessageEvent) :void {
|
||||
if (event.getName() == SceneCodes.SCENE_UPDATE) {
|
||||
sceneUpdated(event.getArgs()[0] as SceneUpdate);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function willEnterPlace (plobj :PlaceObject) :void
|
||||
{
|
||||
super.willEnterPlace(plobj);
|
||||
plobj.addListener(_updateListener);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function didLeavePlace (plobj :PlaceObject) :void
|
||||
{
|
||||
super.didLeavePlace(plobj);
|
||||
plobj.removeListener(_updateListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called if a scene update is recorded while we
|
||||
* currently occupy a scene. The default implementation will update
|
||||
* our local scene and scene model, but derived classes will likely
|
||||
* want to ensure that the update is properly displayed.
|
||||
*/
|
||||
protected function sceneUpdated (update :SceneUpdate) :void
|
||||
{
|
||||
// apply the update to the scene
|
||||
_wctx.getSceneDirector().updateReceived(update);
|
||||
}
|
||||
|
||||
/** Used to listen for scene updates. */
|
||||
protected var _updateListener :MessageListener;
|
||||
|
||||
protected var _wctx :WhirledContext;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// $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.whirled.client {
|
||||
|
||||
import com.threerings.presents.client.InvocationDecoder;
|
||||
|
||||
import com.threerings.whirled.client.SceneReceiver;
|
||||
|
||||
/**
|
||||
* Dispatches calls to a {@link SceneReceiver} instance.
|
||||
*/
|
||||
public class SceneDecoder extends InvocationDecoder
|
||||
{
|
||||
/** The generated hash code used to identify this receiver class. */
|
||||
public static const RECEIVER_CODE :String =
|
||||
"c4d0cf66b81a6e83d119b2d607725651";
|
||||
|
||||
/** The method id used to dispatch {@link SceneReceiver#forcedMove}
|
||||
* notifications. */
|
||||
public static const FORCED_MOVE :int = 1;
|
||||
|
||||
/**
|
||||
* Creates a decoder that may be registered to dispatch invocation
|
||||
* service notifications to the specified receiver.
|
||||
*/
|
||||
public function SceneDecoder (receiver :SceneReceiver)
|
||||
{
|
||||
this.receiver = receiver;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function getReceiverCode () :String
|
||||
{
|
||||
return RECEIVER_CODE;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function dispatchNotification (methodId :int, args :Array) :void
|
||||
{
|
||||
switch (methodId) {
|
||||
case FORCED_MOVE:
|
||||
(receiver as SceneReceiver).forcedMove(args[0] as int);
|
||||
return;
|
||||
|
||||
default:
|
||||
super.dispatchNotification(methodId, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,656 @@
|
||||
//
|
||||
// $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.whirled.client {
|
||||
|
||||
import flash.errors.IOError;
|
||||
import flash.errors.IllegalOperationError;
|
||||
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.util.Log;
|
||||
import com.threerings.util.Map;
|
||||
import com.threerings.util.Maps;
|
||||
import com.threerings.util.ResultListener;
|
||||
|
||||
import com.threerings.presents.client.BasicDirector;
|
||||
import com.threerings.presents.client.Client;
|
||||
import com.threerings.presents.client.ClientEvent;
|
||||
import com.threerings.presents.client.ConfirmAdapter;
|
||||
import com.threerings.presents.data.InvocationCodes;
|
||||
|
||||
import com.threerings.crowd.client.LocationDirector;
|
||||
import com.threerings.crowd.client.LocationDirector_FailureHandler;
|
||||
import com.threerings.crowd.client.LocationObserver;
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
import com.threerings.crowd.data.PlaceObject;
|
||||
|
||||
import com.threerings.whirled.client.persist.SceneRepository;
|
||||
import com.threerings.whirled.data.Scene;
|
||||
import com.threerings.whirled.data.SceneCodes;
|
||||
import com.threerings.whirled.data.SceneMarshaller;
|
||||
import com.threerings.whirled.data.SceneModel;
|
||||
import com.threerings.whirled.data.SceneObject;
|
||||
import com.threerings.whirled.data.SceneUpdate;
|
||||
import com.threerings.whirled.util.NoSuchSceneError;
|
||||
import com.threerings.whirled.util.SceneFactory;
|
||||
import com.threerings.whirled.util.WhirledContext;
|
||||
|
||||
/**
|
||||
* The scene director is the client's interface to all things scene related. It interfaces with the
|
||||
* scene repository to ensure that scene objects are available when the client enters a particular
|
||||
* scene. It handles moving from scene to scene (it coordinates with the {@link LocationDirector}
|
||||
* in order to do this).
|
||||
*
|
||||
* <p> Note that when the scene director is in use instead of the location director, scene ids
|
||||
* instead of place oids will be supplied to {@link LocationObserver#locationMayChange} and {@link
|
||||
* LocationObserver#locationChangeFailed}.
|
||||
*/
|
||||
public class SceneDirector extends BasicDirector
|
||||
implements LocationDirector_FailureHandler, SceneReceiver, SceneService_SceneMoveListener,
|
||||
LocationObserver
|
||||
{
|
||||
private static const log :Log = Log.getLog(SceneDirector);
|
||||
|
||||
// statically reference classes we require
|
||||
SceneMarshaller;
|
||||
|
||||
/**
|
||||
* Creates a new scene director with the specified context.
|
||||
*
|
||||
* @param ctx the active client context.
|
||||
* @param locdir the location director in use on the client, with which the scene director will
|
||||
* coordinate when changing location.
|
||||
* @param screp the entity from which the scene director will load scene data from the local
|
||||
* client scene storage. This may be null when the SceneDirector is constructed, but it should
|
||||
* be supplied via {@link #setSceneRepository} prior to really using this director.
|
||||
* @param fact the factory that knows which derivation of {@link Scene} to create for the
|
||||
* current system.
|
||||
*/
|
||||
public function SceneDirector (ctx :WhirledContext, locdir :LocationDirector,
|
||||
screp :SceneRepository, fact :SceneFactory)
|
||||
{
|
||||
super(ctx);
|
||||
|
||||
// we'll need these for later
|
||||
_wctx = ctx;
|
||||
_locdir = locdir;
|
||||
setSceneRepository(screp);
|
||||
_fact = fact;
|
||||
|
||||
// we need to observe scene moves so that we can clear out if we change to a non-scene
|
||||
_locdir.addLocationObserver(this);
|
||||
|
||||
// set ourselves up as a failure handler with the location director because we need to do
|
||||
// special processing
|
||||
_locdir.setFailureHandler(this);
|
||||
|
||||
// register for scene notifications
|
||||
_wctx.getClient().getInvocationDirector().registerReceiver(new SceneDecoder(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the scene repository.
|
||||
*/
|
||||
public function setSceneRepository (screp :SceneRepository) :void
|
||||
{
|
||||
_screp = screp;
|
||||
_scache.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the display scene object associated with the scene we currently occupy or null if we
|
||||
* currently occupy no scene.
|
||||
*/
|
||||
public function getScene () :Scene
|
||||
{
|
||||
return _scene;
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that this client move the specified scene. A request will be made and when the
|
||||
* response is received, the location observers will be notified of success or failure.
|
||||
*
|
||||
* @return true if the move to request was issued, false if it was rejected by a location
|
||||
* observer or because we have another request outstanding.
|
||||
*/
|
||||
public function moveTo (sceneId :int) :Boolean
|
||||
{
|
||||
// make sure the sceneId is valid
|
||||
if (sceneId < 0) {
|
||||
log.warning("Refusing moveTo(): invalid sceneId", "sceneId", sceneId);
|
||||
return false;
|
||||
}
|
||||
|
||||
// sanity-check the destination scene id
|
||||
if (sceneId == _sceneId) {
|
||||
log.warning("Refusing request to move to the same scene", "sceneId", sceneId);
|
||||
return false;
|
||||
}
|
||||
|
||||
// prepare to move to this scene (sets up pending data)
|
||||
if (!prepareMoveTo(sceneId, null)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// do the deed
|
||||
sendMoveRequest();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares to move to the requested scene. The location observers are asked to ratify the move
|
||||
* and our pending scene mode is loaded from the scene repository. This can be called by
|
||||
* cooperating directors that need to coopt the moveTo process.
|
||||
*/
|
||||
public function prepareMoveTo (sceneId :int, rl :ResultListener) :Boolean
|
||||
{
|
||||
// first check to see if our observers are happy with this move request
|
||||
if (!_locdir.mayMoveTo(sceneId, rl)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// we need to call this both to mark that we're issuing a move request and to check to see
|
||||
// if the last issued request should be considered stale
|
||||
var refuse :Boolean = _locdir.checkRepeatMove();
|
||||
|
||||
// complain if we're over-writing a pending request
|
||||
if (movePending()) {
|
||||
if (refuse) {
|
||||
log.warning("Refusing moveTo; We have a request outstanding",
|
||||
"psid", _pendingData.sceneId, "nsid", sceneId);
|
||||
return false;
|
||||
|
||||
} else {
|
||||
log.warning("Overriding stale moveTo request",
|
||||
"psid", _pendingData.sceneId, "nsid", sceneId);
|
||||
}
|
||||
}
|
||||
|
||||
// create and initialize a new pending data record
|
||||
_pendingData = createPendingData();
|
||||
|
||||
// load up the cached pending scene so that we can communicate its version to the server
|
||||
_pendingData.model = loadSceneModel(sceneId);
|
||||
|
||||
// make a note of our pending scene id
|
||||
_pendingData.sceneId = sceneId;
|
||||
|
||||
// all systems go
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a function that may be used to restore the scene director's pendingData to its
|
||||
* current state. This is primarily useful if you know something (such as a logoff) is about
|
||||
* to happen and you want to ensure you can restore the pending data after re-login.
|
||||
*/
|
||||
public function getPendingDataRestoreFunc () :Function
|
||||
{
|
||||
var pendingData :PendingData = _pendingData;
|
||||
|
||||
return function () :void {
|
||||
_pendingData = pendingData;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the model loaded in preparation for a scene transition. This is made available only
|
||||
* for cooperating directors which may need to coopt the scene transition process. The pending
|
||||
* model is only valid immediately following a call to {@link #prepareMoveTo}.
|
||||
*/
|
||||
public function getPendingModel () :SceneModel
|
||||
{
|
||||
return _pendingData == null ? null : _pendingData.model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scene id set in preparation for a scene transition. As with
|
||||
* {@link #getPendingModel}, this is for cooperating directors.
|
||||
*/
|
||||
public function getPendingSceneId () :int
|
||||
{
|
||||
return _pendingData == null ? -1 : _pendingData.sceneId;
|
||||
}
|
||||
|
||||
// from interface SceneService_SceneMoveListener
|
||||
public function moveSucceeded (placeId :int, config :PlaceConfig) :void
|
||||
{
|
||||
// our move request was successful, deal with subscribing to our new place object
|
||||
_locdir.didMoveTo(placeId, config);
|
||||
|
||||
// keep track of our previous scene info
|
||||
_previousSceneId = _sceneId;
|
||||
|
||||
// clear out the old info
|
||||
clearScene();
|
||||
|
||||
// make the pending scene the active scene
|
||||
if (_pendingData == null) {
|
||||
log.warning("Aiya! Scene move succeeded but we have no pending data!",
|
||||
"prevId", _previousSceneId);
|
||||
return;
|
||||
}
|
||||
_sceneId = _pendingData.sceneId;
|
||||
_pendingData = null;
|
||||
|
||||
// since we're committed to moving to the new scene, we'll parallelize and go ahead and
|
||||
// load up the new scene now rather than wait until subscription to our place object
|
||||
// succeeds
|
||||
_model = loadSceneModel(_sceneId);
|
||||
|
||||
// complain if we didn't find a scene
|
||||
if (_model == null) {
|
||||
log.warning("Aiya! Unable to load scene", "sid", _sceneId, "plid", placeId);
|
||||
return;
|
||||
}
|
||||
|
||||
// and finally create a display scene instance with the model and the place config
|
||||
_scene = _fact.createScene(_model, config);
|
||||
|
||||
handlePendingForcedMove();
|
||||
}
|
||||
|
||||
// from interface SceneService_SceneMoveListener
|
||||
public function moveSucceededWithUpdates (
|
||||
placeId :int, config :PlaceConfig, updates :TypedArray) :void
|
||||
{
|
||||
log.info("Got updates", "placeId", placeId, "config", config, "updates", updates);
|
||||
|
||||
// apply the updates to our cached scene
|
||||
var model :SceneModel = loadSceneModel(_pendingData.sceneId);
|
||||
var failure :Boolean = false;
|
||||
for each (var update :SceneUpdate in updates) {
|
||||
try {
|
||||
update.validate(model);
|
||||
} catch (ise :IllegalOperationError) {
|
||||
log.warning("Scene update failed validation",
|
||||
"model", model, "update", update, "error", ise.message);
|
||||
failure = true;
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
update.apply(model);
|
||||
} catch (e :Error) {
|
||||
log.warning("Failure applying scene update", "model", model, "update", update, e);
|
||||
failure = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (failure) {
|
||||
// delete the now half-booched scene model from the repository
|
||||
try {
|
||||
_screp.deleteSceneModel(_pendingData.sceneId);
|
||||
} catch (ioe :IOError) {
|
||||
log.warning("Failure removing booched scene model",
|
||||
"sceneId", _pendingData.sceneId, ioe);
|
||||
}
|
||||
|
||||
// act as if the scene move failed, though we'll be in a funny state because the server
|
||||
// thinks we've changed scenes, but the client can try again without its booched scene
|
||||
// model
|
||||
requestFailed(InvocationCodes.INTERNAL_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
// store the updated scene in the repository
|
||||
persistSceneModel(model);
|
||||
|
||||
// finally pass through to the normal success handler
|
||||
moveSucceeded(placeId, config);
|
||||
}
|
||||
|
||||
// from interface SceneService_SceneMoveListener
|
||||
public function moveSucceededWithScene (
|
||||
placeId :int, config :PlaceConfig, model :SceneModel) :void
|
||||
{
|
||||
log.info("Got updated scene model",
|
||||
"placeId", placeId, "config", config,
|
||||
"scene", model.sceneId + "/" + model.name + "/" + model.version);
|
||||
|
||||
// update the model in the repository
|
||||
persistSceneModel(model);
|
||||
|
||||
// update our scene cache
|
||||
_scache.put(model.sceneId, model);
|
||||
|
||||
// and pass through to the normal move succeeded handler
|
||||
moveSucceeded(placeId, config);
|
||||
}
|
||||
|
||||
// from interface SceneService_SceneMoveListener
|
||||
public function moveRequiresServerSwitch (hostname :String, ports :TypedArray) :void
|
||||
{
|
||||
log.info("Scene switch requires server switch", "host", hostname, "ports", ports);
|
||||
// keep track of our current pending data because it will be cleared when we log off of
|
||||
// this server and onto the next one
|
||||
var pendingData :PendingData = _pendingData;
|
||||
// ship on over to the other server
|
||||
_wctx.getClient().moveToServer(hostname, ports, new ConfirmAdapter(
|
||||
function () :void { // succeeded
|
||||
// resend our move request now that we're connected to the new server
|
||||
_pendingData = pendingData;
|
||||
sendMoveRequest();
|
||||
}, requestFailed));
|
||||
}
|
||||
|
||||
// from interface SceneService_SceneMoveListener
|
||||
public function requestFailed (reason :String) :void
|
||||
{
|
||||
// clear out our pending info
|
||||
var sceneId :int = _pendingData.sceneId;
|
||||
_pendingData = null;
|
||||
|
||||
// let our observers know that something has gone horribly awry
|
||||
_locdir.failedToMoveTo(sceneId, reason);
|
||||
|
||||
handlePendingForcedMove();
|
||||
}
|
||||
|
||||
// from interface LocationObserver
|
||||
public function locationMayChange (placeId :int) :Boolean
|
||||
{
|
||||
return true; // fine with us
|
||||
}
|
||||
|
||||
// from interface LocationObserver
|
||||
public function locationDidChange (place :PlaceObject) :void
|
||||
{
|
||||
// if we're no longer in a scene, we need to clear out our scene information
|
||||
if (!(place is SceneObject)) {
|
||||
clearScene();
|
||||
}
|
||||
}
|
||||
|
||||
// from interface LocationObserver
|
||||
public function locationChangeFailed (placeId :int, reason :String) :void
|
||||
{
|
||||
// we don't care about this notification as we're registered as a LocationDirector
|
||||
// FailureHandler so we will later be requested to recover from our failed move
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by SceneController instances to tell us about an update to the current scene.
|
||||
*/
|
||||
public function updateReceived (update :SceneUpdate) :void
|
||||
{
|
||||
_scene.updateReceived(update);
|
||||
persistSceneModel(_scene.getSceneModel());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to clean up our place and scene state information when we leave a scene.
|
||||
*/
|
||||
public function didLeaveScene () :void
|
||||
{
|
||||
// let the location director know what's up
|
||||
_locdir.didLeavePlace();
|
||||
|
||||
// clear out our own scene state
|
||||
clearScene();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there is a pending move request.
|
||||
*/
|
||||
public function movePending () :Boolean
|
||||
{
|
||||
return (_pendingData != null);
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function forcedMove (sceneId :int) :void
|
||||
{
|
||||
// if we're in the middle of a move, we can't abort it or we will screw everything up, so
|
||||
// just finish up what we're doing and assume that the repeated move request was the
|
||||
// spurious one as it would be in the case of lag causing rapid-fire repeat requests
|
||||
if (movePending()) {
|
||||
if (_pendingData.sceneId == sceneId) {
|
||||
log.info("Dropping forced move because we have a move pending",
|
||||
"pendId", _pendingData.sceneId, "reqId", sceneId);
|
||||
} else {
|
||||
log.info("Delaying forced move because we have a move pending",
|
||||
"pendId", _pendingData.sceneId, "reqId", sceneId);
|
||||
addPendingForcedMove(function() :void {
|
||||
forcedMove(sceneId);
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("Moving at request of server", "sceneId", sceneId);
|
||||
|
||||
// clear out our old scene and place data
|
||||
didLeaveScene();
|
||||
|
||||
// move to the new scene
|
||||
moveTo(sceneId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the moveHandler for use in recoverFailedMove.
|
||||
*/
|
||||
public function setMoveHandler (handler :SceneDirector_MoveHandler) :void
|
||||
{
|
||||
if (_moveHandler != null) {
|
||||
log.warning("Requested to set move handler, but we've already got one. The " +
|
||||
"conflicting entities will likely need to perform more sophisticated " +
|
||||
"coordination to deal with failures.", "old", _moveHandler, "new", handler);
|
||||
|
||||
} else {
|
||||
_moveHandler = handler;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when something breaks down in the process of performing a <code>moveTo</code>
|
||||
* request.
|
||||
*/
|
||||
public function recoverFailedMove (placeId :int) :void
|
||||
{
|
||||
// we'll need this momentarily
|
||||
var sceneId :int = _sceneId;
|
||||
|
||||
// clear out our now bogus scene tracking info
|
||||
clearScene();
|
||||
|
||||
// if we were previously somewhere (and that somewhere isn't where we just tried to go),
|
||||
// try going back to that happy place
|
||||
if (_previousSceneId != -1 && _previousSceneId != sceneId) {
|
||||
// if we have a move handler use that
|
||||
if (_moveHandler != null) {
|
||||
_moveHandler.recoverMoveTo(_previousSceneId);
|
||||
|
||||
} else {
|
||||
moveTo(_previousSceneId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function clientDidLogoff (event :ClientEvent) :void
|
||||
{
|
||||
super.clientDidLogoff(event);
|
||||
|
||||
// clear out our business
|
||||
clearScene();
|
||||
_scache.clear();
|
||||
_pendingData = null;
|
||||
_previousSceneId = -1;
|
||||
_sservice = null;
|
||||
}
|
||||
|
||||
public function cancelMoveRequest () :void
|
||||
{
|
||||
_pendingData = null;
|
||||
handlePendingForcedMove();
|
||||
}
|
||||
|
||||
/**
|
||||
* Issues the scene move request using information from the supplied pending data.
|
||||
*/
|
||||
protected function sendMoveRequest () :void
|
||||
{
|
||||
// check the version of our cached copy of the scene to which we're requesting to move; if
|
||||
// we were unable to load it, assume a cached version of zero
|
||||
var sceneVers :int = 0;
|
||||
if (_pendingData.model != null) {
|
||||
sceneVers = _pendingData.model.version;
|
||||
}
|
||||
|
||||
// issue a moveTo request
|
||||
log.info("Issuing moveTo(" + _pendingData.sceneId + ", " + sceneVers + ").");
|
||||
_sservice.moveTo(_pendingData.sceneId, sceneVers, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a pending scene move request. Derived classes may wish to extend this data with
|
||||
* additional information to be tracked during movement between scenes. This is encapsulated so
|
||||
* that if a scene move requires a switch to a new server, all necessary data can be properly
|
||||
* tracked during the server switch.
|
||||
*/
|
||||
protected function createPendingData () :PendingData
|
||||
{
|
||||
return new PendingData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears out our current scene information and releases the scene model for the loaded scene
|
||||
* back to the cache.
|
||||
*/
|
||||
protected function clearScene () :void
|
||||
{
|
||||
// clear out our scene id info
|
||||
_sceneId = -1;
|
||||
|
||||
// clear out our references
|
||||
_model = null;
|
||||
_scene = null;
|
||||
}
|
||||
|
||||
public function addPendingForcedMove (move :Function) :void
|
||||
{
|
||||
_pendingForcedMoves.push(move);
|
||||
}
|
||||
|
||||
protected function handlePendingForcedMove () :void
|
||||
{
|
||||
if (!_pendingForcedMoves.length == 0) {
|
||||
_ctx.getClient().callLater(_pendingForcedMoves.pop());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a scene from the repository. If the scene is cached, it will be returned from the
|
||||
* cache instead.
|
||||
*/
|
||||
protected function loadSceneModel (sceneId :int) :SceneModel
|
||||
{
|
||||
// first look in the model cache
|
||||
var model :SceneModel = (_scache.get(sceneId) as SceneModel);
|
||||
|
||||
// load from the repository if it's not cached
|
||||
if (model == null) {
|
||||
try {
|
||||
model = _screp.loadSceneModel(sceneId);
|
||||
_scache.put(sceneId, model);
|
||||
|
||||
} catch (nsse :NoSuchSceneError) {
|
||||
// nothing special here, just fall through and return null
|
||||
|
||||
} catch (ioe :IOError) {
|
||||
// complain first, then return null
|
||||
log.warning("Error loading scene", "scid", sceneId, "error", ioe);
|
||||
}
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Persist the scene model to the clientside persistant cache.
|
||||
*/
|
||||
protected function persistSceneModel (model :SceneModel) :void
|
||||
{
|
||||
try {
|
||||
_screp.storeSceneModel(model);
|
||||
} catch (ioe :IOError) {
|
||||
log.warning("Failed to update repository with updated scene",
|
||||
"sceneId", model.sceneId, "nvers", model.version, ioe);
|
||||
}
|
||||
}
|
||||
|
||||
// from BasicDirector
|
||||
override protected function registerServices (client :Client) :void
|
||||
{
|
||||
client.addServiceGroup(SceneCodes.WHIRLED_GROUP);
|
||||
}
|
||||
|
||||
// from BasicDirector
|
||||
override protected function fetchServices (client :Client) :void
|
||||
{
|
||||
// get a handle on our scene service
|
||||
_sservice = (client.requireService(SceneService) as SceneService);
|
||||
}
|
||||
|
||||
/** Access to general client services. */
|
||||
protected var _wctx :WhirledContext;
|
||||
|
||||
/** Access to our scene services. */
|
||||
protected var _sservice :SceneService;
|
||||
|
||||
/** The client's active location director. */
|
||||
protected var _locdir :LocationDirector;
|
||||
|
||||
/** The entity via which we load scene data. */
|
||||
protected var _screp :SceneRepository;
|
||||
|
||||
/** The entity we use to create scenes from scene models. */
|
||||
protected var _fact :SceneFactory;
|
||||
|
||||
/** A cache of scene model information. */
|
||||
protected var _scache :Map = Maps.newBuilder(int).makeLR(5).build();
|
||||
|
||||
/** The display scene object for the scene we currently occupy. */
|
||||
protected var _scene :Scene;
|
||||
|
||||
/** The scene model for the scene we currently occupy. */
|
||||
protected var _model :SceneModel;
|
||||
|
||||
/** The id of the scene we currently occupy. */
|
||||
protected var _sceneId :int = -1;
|
||||
|
||||
/** Information for the scene for which we have an outstanding moveTo request, or null if we
|
||||
* have no outstanding request. */
|
||||
protected var _pendingData :PendingData;
|
||||
|
||||
/** The id of the scene we previously occupied. */
|
||||
protected var _previousSceneId :int = -1;
|
||||
|
||||
/** Reference to our move handler. */
|
||||
protected var _moveHandler :SceneDirector_MoveHandler = null;
|
||||
|
||||
/** Forced move actions we should take once we complete the move we're in the middle of. */
|
||||
protected var _pendingForcedMoves :Array = [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// $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.whirled.client {
|
||||
|
||||
/**
|
||||
* Used to recover from a problem after a completed moveTo.
|
||||
*/
|
||||
public interface SceneDirector_MoveHandler
|
||||
{
|
||||
/**
|
||||
* Should instruct the client to move the last known working
|
||||
* location (as well as clean up after the failed moveTo request).
|
||||
*/
|
||||
function recoverMoveTo (sceneId :int) :void;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// $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.whirled.client {
|
||||
|
||||
import com.threerings.presents.client.InvocationReceiver;
|
||||
|
||||
/**
|
||||
* Defines, for the scene services, a set of notifications delivered
|
||||
* asynchronously by the server to the client.
|
||||
*/
|
||||
public interface SceneReceiver extends InvocationReceiver
|
||||
{
|
||||
/**
|
||||
* Used to communicate a required move notification to the client. The
|
||||
* server will have removed the client from their existing scene
|
||||
* and the client is then responsible for generating a {@link
|
||||
* SceneService#moveTo} request to move to the new scene.
|
||||
*/
|
||||
function forcedMove (sceneId :int) :void
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// $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.whirled.client {
|
||||
|
||||
import com.threerings.presents.client.InvocationService;
|
||||
|
||||
/**
|
||||
* An ActionScript version of the Java SceneService interface.
|
||||
*/
|
||||
public interface SceneService extends InvocationService
|
||||
{
|
||||
// from Java interface SceneService
|
||||
function moveTo (arg1 :int, arg2 :int, arg3 :SceneService_SceneMoveListener) :void;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// $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.whirled.client {
|
||||
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.presents.client.InvocationService_InvocationListener;
|
||||
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
|
||||
import com.threerings.whirled.data.SceneModel;
|
||||
|
||||
/**
|
||||
* An ActionScript version of the Java SceneService_SceneMoveListener interface.
|
||||
*/
|
||||
public interface SceneService_SceneMoveListener
|
||||
extends InvocationService_InvocationListener
|
||||
{
|
||||
// from Java SceneService_SceneMoveListener
|
||||
function moveRequiresServerSwitch (arg1 :String, arg2 :TypedArray /* of int */) :void
|
||||
|
||||
// from Java SceneService_SceneMoveListener
|
||||
function moveSucceeded (arg1 :int, arg2 :PlaceConfig) :void
|
||||
|
||||
// from Java SceneService_SceneMoveListener
|
||||
function moveSucceededWithScene (arg1 :int, arg2 :PlaceConfig, arg3 :SceneModel) :void
|
||||
|
||||
// from Java SceneService_SceneMoveListener
|
||||
function moveSucceededWithUpdates (arg1 :int, arg2 :PlaceConfig, arg3 :TypedArray /* of class com.threerings.whirled.data.SceneUpdate */) :void
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
//
|
||||
// $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.whirled.client.persist {
|
||||
|
||||
import flash.errors.IOError;
|
||||
|
||||
import com.threerings.whirled.data.SceneModel;
|
||||
|
||||
/**
|
||||
* The scene repository provides access to a persistent repository of scene information.
|
||||
*
|
||||
* @see SceneModel
|
||||
*/
|
||||
public interface SceneRepository
|
||||
{
|
||||
/**
|
||||
* Fetches the model for the scene with the specified id.
|
||||
*
|
||||
* @exception IOError thrown if an error occurs attempting to load the scene data.
|
||||
* @exception NoSuchSceneError thrown if no scene exists with the specified scene id.
|
||||
*/
|
||||
function loadSceneModel (sceneId :int) :SceneModel;
|
||||
//throws IOError, NoSuchSceneError;
|
||||
|
||||
/**
|
||||
* Updates or inserts this scene model as appropriate.
|
||||
*
|
||||
* @exception IOError thrown if an error occurs attempting to access the repository.
|
||||
*/
|
||||
function storeSceneModel (model :SceneModel) :void;
|
||||
//throws IOError;
|
||||
|
||||
/**
|
||||
* Deletes the specified scene model from the repository.
|
||||
*
|
||||
* @exception IOError thrown if an error occurs attempting to access the repository.
|
||||
*/
|
||||
function deleteSceneModel (sceneId :int) :void;
|
||||
//throws IOError;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// $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.whirled.data {
|
||||
|
||||
import com.threerings.io.Streamable;
|
||||
|
||||
import com.threerings.util.Cloneable;
|
||||
|
||||
/**
|
||||
* An interface that must be implemented by auxiliary scene models.
|
||||
*/
|
||||
public interface AuxModel extends Streamable, Cloneable
|
||||
{
|
||||
// no new methods
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// $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.whirled.data {
|
||||
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
|
||||
/**
|
||||
* The default scene config simply causes the default scene manager and controller to be created. A
|
||||
* user of the Whirled services would most likely extend the default scene config.
|
||||
*
|
||||
* <p> Note that this place config won't even work on the client side because it instantiates a
|
||||
* SceneController which is an abstract class. It is used only for testing the server side and as a
|
||||
* placeholder in case standard scene configuration information is one day needed. </p>
|
||||
*/
|
||||
public class DefaultSceneConfig extends PlaceConfig
|
||||
{
|
||||
public function DefaultSceneConfig ()
|
||||
{
|
||||
// nothing needed
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function getManagerClassName () :String
|
||||
{
|
||||
return "com.threerings.whirled.server.SceneManager";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
//
|
||||
// $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.whirled.data {
|
||||
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
|
||||
/**
|
||||
* This interface makes available basic scene information. At this basic
|
||||
* level, not much information is available, but extensions to this
|
||||
* interface begin to create a more comprehensive picture of a scene in a
|
||||
* system built from the Whirled services.
|
||||
*/
|
||||
public interface Scene
|
||||
{
|
||||
/**
|
||||
* Returns the unique identifier for this scene.
|
||||
*/
|
||||
function getId () :int;
|
||||
|
||||
/**
|
||||
* Returns the human readable name of this scene.
|
||||
*/
|
||||
function getName () :String;
|
||||
|
||||
/**
|
||||
* Returns the version number of this scene.
|
||||
*/
|
||||
function getVersion () :int;
|
||||
|
||||
/**
|
||||
* Returns the place config that can be used to determine which place
|
||||
* controller instance should be used to display this scene as well as
|
||||
* to obtain runtime configuration information.
|
||||
*/
|
||||
function getPlaceConfig () :PlaceConfig;
|
||||
|
||||
/**
|
||||
* Sets this scene's unique identifier.
|
||||
*/
|
||||
function setId (sceneId :int) :void;
|
||||
|
||||
/**
|
||||
* Sets the human readable name of this scene.
|
||||
*/
|
||||
function setName (name :String) :void;
|
||||
|
||||
/**
|
||||
* Sets this scene's version number.
|
||||
*/
|
||||
function setVersion (version :int) :void;
|
||||
|
||||
/**
|
||||
* Called to inform the scene that an update has been received while
|
||||
* the scene was resolved and active. The update should be applied to
|
||||
* the underlying scene model and any derivative data should be
|
||||
* appropriately updated.
|
||||
*/
|
||||
function updateReceived (update :SceneUpdate) :void;
|
||||
|
||||
/**
|
||||
* Returns the scene model from which this scene was created.
|
||||
*/
|
||||
function getSceneModel () :SceneModel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// $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.whirled.data {
|
||||
|
||||
import com.threerings.crowd.data.LocationCodes;
|
||||
|
||||
/**
|
||||
* Contains codes used by the scene invocation services.
|
||||
*/
|
||||
public class SceneCodes extends LocationCodes
|
||||
{
|
||||
/** Defines our invocation services group. */
|
||||
public static const WHIRLED_GROUP :String = "whirled";
|
||||
|
||||
/** The message identifier for scene update messages. */
|
||||
public static const SCENE_UPDATE :String = "scene_update";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
//
|
||||
// $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.whirled.data {
|
||||
|
||||
import com.threerings.util.Log;
|
||||
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
|
||||
/**
|
||||
* An implementation of the {@link Scene} interface.
|
||||
*/
|
||||
public class SceneImpl implements Scene
|
||||
{
|
||||
/**
|
||||
* Creates an instance that will obtain data from the supplied scene
|
||||
* model and place config.
|
||||
*/
|
||||
public function SceneImpl (
|
||||
model :SceneModel = null, config :PlaceConfig = null)
|
||||
{
|
||||
if (model != null) {
|
||||
_model = model;
|
||||
_config = config;
|
||||
|
||||
} else {
|
||||
_model = SceneModel.blankSceneModel();
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public function getId () :int
|
||||
{
|
||||
return _model.sceneId;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public function getName () :String
|
||||
{
|
||||
return _model.name;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public function getVersion () :int
|
||||
{
|
||||
return _model.version;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public function getPlaceConfig () :PlaceConfig
|
||||
{
|
||||
return _config;
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function setId (sceneId :int) :void
|
||||
{
|
||||
_model.sceneId = sceneId;
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function setName (name :String) :void
|
||||
{
|
||||
_model.name = name;
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function setVersion (version :int) :void
|
||||
{
|
||||
_model.version = version;
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function updateReceived (update :SceneUpdate) :void
|
||||
{
|
||||
try {
|
||||
// validate and apply the update
|
||||
update.validate(_model);
|
||||
update.apply(_model);
|
||||
} catch (e :Error) {
|
||||
var log :Log = Log.getLog(this);
|
||||
log.warning("Error applying update", "scene", this, "update", update, e);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function getSceneModel () :SceneModel
|
||||
{
|
||||
return _model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a string representation of this instance.
|
||||
*/
|
||||
public function toString () :String
|
||||
{
|
||||
return "[model=" + _model + ", config=" + _config + "]";
|
||||
}
|
||||
|
||||
/** A reference to our scene model. */
|
||||
protected var _model :SceneModel;
|
||||
|
||||
/** A reference to our place configuration. */
|
||||
protected var _config :PlaceConfig;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// $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.whirled.data {
|
||||
|
||||
import com.threerings.util.Integer;
|
||||
|
||||
import com.threerings.presents.data.InvocationMarshaller;
|
||||
|
||||
import com.threerings.whirled.client.SceneService;
|
||||
import com.threerings.whirled.client.SceneService_SceneMoveListener;
|
||||
|
||||
/**
|
||||
* Provides the implementation of the <code>SceneService</code> interface
|
||||
* that marshalls the arguments and delivers the request to the provider
|
||||
* on the server. Also provides an implementation of the response listener
|
||||
* interfaces that marshall the response arguments and deliver them back
|
||||
* to the requesting client.
|
||||
*/
|
||||
public class SceneMarshaller extends InvocationMarshaller
|
||||
implements SceneService
|
||||
{
|
||||
/** The method id used to dispatch <code>moveTo</code> requests. */
|
||||
public static const MOVE_TO :int = 1;
|
||||
|
||||
// from interface SceneService
|
||||
public function moveTo (arg1 :int, arg2 :int, arg3 :SceneService_SceneMoveListener) :void
|
||||
{
|
||||
var listener3 :SceneMarshaller_SceneMoveMarshaller = new SceneMarshaller_SceneMoveMarshaller();
|
||||
listener3.listener = arg3;
|
||||
sendRequest(MOVE_TO, [
|
||||
Integer.valueOf(arg1), Integer.valueOf(arg2), listener3
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
//
|
||||
// $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.whirled.data {
|
||||
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.presents.data.InvocationMarshaller_ListenerMarshaller;
|
||||
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
|
||||
import com.threerings.whirled.client.SceneService_SceneMoveListener;
|
||||
|
||||
/**
|
||||
* Marshalls instances of the SceneService_SceneMoveMarshaller interface.
|
||||
*/
|
||||
public class SceneMarshaller_SceneMoveMarshaller
|
||||
extends InvocationMarshaller_ListenerMarshaller
|
||||
{
|
||||
/** The method id used to dispatch <code>moveRequiresServerSwitch</code> responses. */
|
||||
public static const MOVE_REQUIRES_SERVER_SWITCH :int = 1;
|
||||
|
||||
/** The method id used to dispatch <code>moveSucceeded</code> responses. */
|
||||
public static const MOVE_SUCCEEDED :int = 2;
|
||||
|
||||
/** The method id used to dispatch <code>moveSucceededWithScene</code> responses. */
|
||||
public static const MOVE_SUCCEEDED_WITH_SCENE :int = 3;
|
||||
|
||||
/** The method id used to dispatch <code>moveSucceededWithUpdates</code> responses. */
|
||||
public static const MOVE_SUCCEEDED_WITH_UPDATES :int = 4;
|
||||
|
||||
// from InvocationMarshaller_ListenerMarshaller
|
||||
override public function dispatchResponse (methodId :int, args :Array) :void
|
||||
{
|
||||
switch (methodId) {
|
||||
case MOVE_REQUIRES_SERVER_SWITCH:
|
||||
(listener as SceneService_SceneMoveListener).moveRequiresServerSwitch(
|
||||
(args[0] as String), (args[1] as TypedArray /* of int */));
|
||||
return;
|
||||
|
||||
case MOVE_SUCCEEDED:
|
||||
(listener as SceneService_SceneMoveListener).moveSucceeded(
|
||||
(args[0] as int), (args[1] as PlaceConfig));
|
||||
return;
|
||||
|
||||
case MOVE_SUCCEEDED_WITH_SCENE:
|
||||
(listener as SceneService_SceneMoveListener).moveSucceededWithScene(
|
||||
(args[0] as int), (args[1] as PlaceConfig), (args[2] as SceneModel));
|
||||
return;
|
||||
|
||||
case MOVE_SUCCEEDED_WITH_UPDATES:
|
||||
(listener as SceneService_SceneMoveListener).moveSucceededWithUpdates(
|
||||
(args[0] as int), (args[1] as PlaceConfig), (args[2] as TypedArray /* of class com.threerings.whirled.data.SceneUpdate */));
|
||||
return;
|
||||
|
||||
default:
|
||||
super.dispatchResponse(methodId, args);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
//
|
||||
// $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.whirled.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
import com.threerings.io.SimpleStreamableObject;
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.util.ClassUtil;
|
||||
import com.threerings.util.Cloneable;
|
||||
|
||||
/**
|
||||
* The scene model is the bare bones representation of the data for a
|
||||
* scene in the Whirled system. From the scene model, one would create an
|
||||
* instance of {@link Scene}.
|
||||
*
|
||||
* <p> The scene model is what is loaded from the scene repositories and
|
||||
* what is transmitted over the wire when communicating scenes from the
|
||||
* server to the client.
|
||||
*/
|
||||
public class SceneModel extends SimpleStreamableObject
|
||||
implements Cloneable
|
||||
{
|
||||
/** This scene's unique identifier. */
|
||||
public var sceneId :int;
|
||||
|
||||
/** The human readable name of this scene. */
|
||||
public var name :String;
|
||||
|
||||
/** The version number of this scene. Versions are incremented
|
||||
* whenever modifications are made to a scene so that clients can
|
||||
* determine whether or not they have the latest version of a
|
||||
* scene. */
|
||||
public var version :int;
|
||||
|
||||
/** Auxiliary scene model information. */
|
||||
public var auxModels :TypedArray = TypedArray.create(AuxModel);
|
||||
|
||||
/**
|
||||
* Creates and returns a blank scene model.
|
||||
*/
|
||||
public static function blankSceneModel () :SceneModel
|
||||
{
|
||||
var model :SceneModel = new SceneModel();
|
||||
populateBlankSceneModel(model);
|
||||
return model;
|
||||
}
|
||||
|
||||
public function SceneModel ()
|
||||
{
|
||||
// nothing needed
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified auxiliary model to this scene model.
|
||||
*/
|
||||
public function addAuxModel (auxModel :AuxModel) :void
|
||||
{
|
||||
auxModels.push(auxModel);
|
||||
}
|
||||
|
||||
// documentation inherited from interface Cloneable
|
||||
public function clone () :Object
|
||||
{
|
||||
var clazz :Class = ClassUtil.getClass(this);
|
||||
var model :SceneModel = new clazz();
|
||||
|
||||
model.sceneId = sceneId;
|
||||
model.name = name;
|
||||
model.version = version;
|
||||
|
||||
for each (var aux :AuxModel in auxModels) {
|
||||
model.addAuxModel(aux.clone() as AuxModel);
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
// documentation inherited from interface Streamable
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
sceneId = ins.readInt();
|
||||
name = (ins.readField(String) as String);
|
||||
version = ins.readInt();
|
||||
auxModels = TypedArray(ins.readObject());
|
||||
}
|
||||
|
||||
// documentation inherited from interface Streamable
|
||||
override public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
super.writeObject(out);
|
||||
out.writeInt(sceneId);
|
||||
out.writeField(name);
|
||||
out.writeInt(version);
|
||||
out.writeObject(auxModels);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates a blank scene model with blank values.
|
||||
*/
|
||||
protected static function populateBlankSceneModel (model :SceneModel) :void
|
||||
{
|
||||
model.sceneId = -1;
|
||||
model.name = "<blank>";
|
||||
model.version = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
//
|
||||
// $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.whirled.data {
|
||||
|
||||
import com.threerings.crowd.data.PlaceObject;
|
||||
|
||||
public class SceneObject extends PlaceObject
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// $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.whirled.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
|
||||
import com.threerings.crowd.data.BodyObject;
|
||||
import com.threerings.crowd.data.Place;
|
||||
|
||||
/**
|
||||
* Extends {@link Place} with scene information.
|
||||
*/
|
||||
public class ScenePlace extends Place
|
||||
{
|
||||
/** The id of the scene occupied by the body. */
|
||||
public var sceneId :int;
|
||||
|
||||
/**
|
||||
* Returns the scene id occupied by the supplied body or -1 if the body is not in a scene.
|
||||
*/
|
||||
public static function getSceneId (bobj :BodyObject) :int
|
||||
{
|
||||
return (bobj.location is ScenePlace) ? (bobj.location as ScenePlace).sceneId : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a scene place with the supplied {@link SceneObject} oid and scene id.
|
||||
*/
|
||||
public function ScenePlace (sceneOid :int = 0, sceneID :int = 0)
|
||||
{
|
||||
super(sceneOid);
|
||||
this.sceneId = sceneId;
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
sceneId = ins.readInt();
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
super.writeObject(out);
|
||||
out.writeInt(sceneId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
//
|
||||
// $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.whirled.data {
|
||||
|
||||
import flash.errors.IllegalOperationError;
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
import com.threerings.io.Streamable;
|
||||
|
||||
import com.threerings.util.Cloneable;
|
||||
import com.threerings.util.Joiner;
|
||||
import com.threerings.util.Log;
|
||||
|
||||
/**
|
||||
* Used to encapsulate updates to scenes in such a manner that updates can
|
||||
* be stored persistently and sent to clients to update their own local
|
||||
* copies of scenes.
|
||||
*/
|
||||
public class SceneUpdate
|
||||
implements Streamable, Cloneable
|
||||
{
|
||||
public function SceneUpdate ()
|
||||
{
|
||||
// nothing needed
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies this update to the specified scene model. Derived classes
|
||||
* will want to override this method and apply updates of their own,
|
||||
* being sure to call <code>super.apply</code>.
|
||||
*/
|
||||
public function apply (model :SceneModel) :void
|
||||
{
|
||||
// increment the version; disallowing integer overflow
|
||||
model.version = Math.max(_targetVersion + 1, model.version);
|
||||
|
||||
// sanity check for the amazing two billion updates
|
||||
if (model.version == _targetVersion) {
|
||||
Log.getLog(this).warning("Egads! This scene has been updated two" +
|
||||
" billion times [model=" + model + ", update=" + this + "].");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scene id for which this update is appropriate.
|
||||
*/
|
||||
public function getSceneId () :int
|
||||
{
|
||||
return _targetId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scene version for which this update is appropriate.
|
||||
*/
|
||||
public function getSceneVersion () :int
|
||||
{
|
||||
return _targetVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a string representation of this instance.
|
||||
*/
|
||||
public function toString () :String
|
||||
{
|
||||
var j :Joiner = Joiner.createFor(this);
|
||||
toStringJoiner(j);
|
||||
return j.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes this scene update such that it will operate on a scene
|
||||
* with the specified target scene and version number.
|
||||
*
|
||||
* @param targetId the id of the scene on which we are to operate.
|
||||
* @param targetVersion the version of the scene on which we are to
|
||||
* operate.
|
||||
*/
|
||||
public function init (targetId :int, targetVersion :int) :void
|
||||
{
|
||||
_targetId = targetId;
|
||||
_targetVersion = targetVersion;
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
out.writeInt(_targetId);
|
||||
out.writeInt(_targetVersion);
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
_targetId = ins.readInt();
|
||||
_targetVersion = ins.readInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to ensure that the scene is in the appropriate state prior
|
||||
* to applying the update.
|
||||
*
|
||||
* @exception IllegalStateException thrown if the update cannot be
|
||||
* applied to the scene because it is not in a valid state
|
||||
* (appropriate previous updates were not applied, it's the wrong kind
|
||||
* of scene, etc.).
|
||||
*/
|
||||
public function validate (model :SceneModel) :void
|
||||
//throws IllegalStateException
|
||||
{
|
||||
if (model.sceneId != _targetId) {
|
||||
throw new IllegalOperationError("Wrong target scene, expected id " +
|
||||
_targetId + " got id " + model.sceneId);
|
||||
|
||||
} else if (model.version != _targetVersion) {
|
||||
throw new IllegalOperationError("Target scene not proper " +
|
||||
"version, expected " + _targetVersion +
|
||||
" got " + model.version);
|
||||
}
|
||||
}
|
||||
|
||||
// from interface Cloneable
|
||||
public function clone () :Object
|
||||
{
|
||||
throw new Error("Not implemented.");
|
||||
}
|
||||
|
||||
/**
|
||||
* An extensible mechanism for generating a string representation of
|
||||
* this instance.
|
||||
*/
|
||||
protected function toStringJoiner (j :Joiner) :void
|
||||
{
|
||||
j.add("sceneId", _targetId, "version", _targetVersion);
|
||||
}
|
||||
|
||||
/** The version number of the scene on which we operate. */
|
||||
protected var _targetId :int;
|
||||
|
||||
/** The version number of the scene on which we operate. */
|
||||
protected var _targetVersion :int;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// $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.whirled.spot.client {
|
||||
|
||||
import com.threerings.whirled.client.SceneController;
|
||||
|
||||
/**
|
||||
* The base spot scene controller class. It is expected that users of the
|
||||
* Whirled Spot services will extend this controller class when creating
|
||||
* specialized controllers for their scenes. Presently there are no basic
|
||||
* scene services provided by this controller, but its existence affords
|
||||
* the addition of such services should they become necessary in the
|
||||
* future.
|
||||
*/
|
||||
public /*abstract*/ class SpotSceneController extends SceneController
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,505 @@
|
||||
//
|
||||
// $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.whirled.spot.client {
|
||||
import com.threerings.util.Log;
|
||||
import com.threerings.util.ResultListener;
|
||||
|
||||
import com.threerings.presents.client.BasicDirector;
|
||||
import com.threerings.presents.client.Client;
|
||||
import com.threerings.presents.client.ClientEvent;
|
||||
import com.threerings.presents.client.ConfirmAdapter;
|
||||
import com.threerings.presents.dobj.AttributeChangeListener;
|
||||
import com.threerings.presents.dobj.AttributeChangedEvent;
|
||||
import com.threerings.presents.dobj.DObject;
|
||||
import com.threerings.presents.dobj.DObjectManager;
|
||||
import com.threerings.presents.dobj.ObjectAccessError;
|
||||
import com.threerings.presents.dobj.Subscriber;
|
||||
|
||||
import com.threerings.crowd.chat.client.ChatDirector;
|
||||
import com.threerings.crowd.chat.data.ChatCodes;
|
||||
import com.threerings.crowd.client.CrowdClient;
|
||||
import com.threerings.crowd.client.LocationAdapter;
|
||||
import com.threerings.crowd.client.LocationDirector;
|
||||
import com.threerings.crowd.data.BodyObject;
|
||||
import com.threerings.crowd.data.PlaceObject;
|
||||
|
||||
import com.threerings.whirled.client.SceneDirector;
|
||||
import com.threerings.whirled.data.SceneModel;
|
||||
import com.threerings.whirled.data.ScenePlace;
|
||||
import com.threerings.whirled.spot.data.ClusteredBodyObject;
|
||||
import com.threerings.whirled.spot.data.Location;
|
||||
import com.threerings.whirled.spot.data.Portal;
|
||||
import com.threerings.whirled.spot.data.SceneLocation;
|
||||
import com.threerings.whirled.spot.data.SpotCodes;
|
||||
import com.threerings.whirled.spot.data.SpotMarshaller;
|
||||
import com.threerings.whirled.spot.data.SpotScene;
|
||||
import com.threerings.whirled.spot.data.SpotSceneObject;
|
||||
import com.threerings.whirled.util.WhirledContext;
|
||||
|
||||
/**
|
||||
* Extends the standard scene director with facilities to move between locations within a scene.
|
||||
*/
|
||||
public class SpotSceneDirector extends BasicDirector
|
||||
implements Subscriber, AttributeChangeListener
|
||||
{
|
||||
private static const log :Log = Log.getLog(SpotSceneDirector);
|
||||
|
||||
// statically reference classes we require
|
||||
SpotMarshaller;
|
||||
|
||||
/**
|
||||
* Creates a new spot scene director with the specified context and which will cooperate with
|
||||
* the supplied scene director.
|
||||
*
|
||||
* @param ctx the active client context.
|
||||
* @param locdir the location director with which we will be cooperating.
|
||||
* @param scdir the scene director with which we will be cooperating.
|
||||
*/
|
||||
public function SpotSceneDirector (
|
||||
ctx :WhirledContext, locdir :LocationDirector, scdir :SceneDirector)
|
||||
{
|
||||
super(ctx);
|
||||
|
||||
_wctx = ctx;
|
||||
_scdir = scdir;
|
||||
|
||||
// wire ourselves up to hear about leave place notifications
|
||||
locdir.addLocationObserver(new LocationAdapter(null, handleSceneChange, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures this spot scene director with a chat director, with which it will coordinate to
|
||||
* implement cluster chatting.
|
||||
*/
|
||||
public function setChatDirector (chatdir :ChatDirector) :void
|
||||
{
|
||||
_chatdir = chatdir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns our current location unless we have a location change pending, in which case our
|
||||
* pending location is returned.
|
||||
*/
|
||||
public function getIntendedLocation () :Location
|
||||
{
|
||||
return (_pendingLoc != null) ? _pendingLoc : _location;
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that this client move to the location specified by the supplied portal id. A
|
||||
* request will be made and when the response is received, the location observers will be
|
||||
* notified of success or failure.
|
||||
*
|
||||
* @return true if the request was issued, false if it was rejected by a location observer or
|
||||
* because we have another request outstanding.
|
||||
*/
|
||||
public function traversePortal (
|
||||
portalId :int, rl :com.threerings.util.ResultListener = null) :Boolean
|
||||
{
|
||||
// look up the destination scene and location
|
||||
var scene :SpotScene = (_scdir.getScene() as SpotScene);
|
||||
if (scene == null) {
|
||||
log.warning("Requested to traverse portal when we have no scene " +
|
||||
"[portalId=" + portalId + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
// sanity check the server's notion of what scene we're in with our notion of it
|
||||
var sceneId :int = _scdir.getScene().getId();
|
||||
var clSceneId :int = ScenePlace.getSceneId(CrowdClient(_wctx.getClient()).bodyOf());
|
||||
if (sceneId != clSceneId) {
|
||||
log.warning("Client and server differ in opinion of what scene we're in " +
|
||||
"[sSceneId=" + clSceneId + ", cSceneId=" + sceneId + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
// find the portal they're talking about
|
||||
var dest :Portal = scene.getPortal(portalId);
|
||||
if (dest == null) {
|
||||
log.warning("Requested to traverse non-existent portal [portalId=" + portalId +
|
||||
", portals=" + scene.getPortals() + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
// prepare to move to this scene (sets up pending data)
|
||||
if (!_scdir.prepareMoveTo(dest.targetSceneId, rl)) {
|
||||
log.info("Portal traversal vetoed by scene director [portalId=" + portalId + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
// check the version of our cached copy of the scene to which we're requesting to move; if
|
||||
// we were unable to load it, assume a cached version of zero
|
||||
var sceneVer :int = 0;
|
||||
var pendingModel :SceneModel = _scdir.getPendingModel();
|
||||
if (pendingModel != null) {
|
||||
sceneVer = pendingModel.version;
|
||||
}
|
||||
|
||||
// issue a traversePortal request
|
||||
log.info("Issuing traversePortal(" + sceneId + ", " + dest + ", " + sceneVer + ").");
|
||||
_sservice.traversePortal(sceneId, portalId, sceneVer, new SceneDirectorWrapper(_scdir));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Issues a request to change our location within the scene to the specified location.
|
||||
*
|
||||
* @param loc the new location to which to move.
|
||||
* @param listener will be notified of success or failure. Most client entities find out about
|
||||
* location changes via changes to the occupant info data, but the initiator of a location
|
||||
* change request can be notified of its success or failure, primarily so that it can act in
|
||||
* anticipation of a successful location change (like by starting a sprite moving toward the
|
||||
* new location), but backtrack if it finds out that the location change failed.
|
||||
*/
|
||||
public function changeLocation (
|
||||
loc :Location, listener :com.threerings.util.ResultListener) :void
|
||||
{
|
||||
// refuse if there's a pending location change or if we're already at the specified
|
||||
// location
|
||||
if (loc.equivalent(_location)) {
|
||||
log.info("Not going to " + loc + "; we're at " + _location +
|
||||
" and we're headed to " + _pendingLoc + ".");
|
||||
if (listener != null) {
|
||||
// This isn't really a failure, it's just a no-op.
|
||||
listener.requestCompleted(_location);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (_pendingLoc != null) {
|
||||
log.info("Not going to " + loc + "; we're at " + _location +
|
||||
" and we're headed to " + _pendingLoc + ".");
|
||||
if (listener != null) {
|
||||
// Already moving, best thing to do is ignore it.
|
||||
listener.requestCompleted(_pendingLoc);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var scene :SpotScene = (_scdir.getScene() as SpotScene);
|
||||
if (scene == null) {
|
||||
log.warning("Requested to change locations, but we're not currently in any scene " +
|
||||
"[loc=" + loc + "].");
|
||||
if (listener != null) {
|
||||
listener.requestFailed(new Error("m.cant_get_there"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var sceneId :int = _scdir.getScene().getId();
|
||||
// log.info("Sending changeLocation request [scid=" + sceneId + ", loc=" + loc + "].");
|
||||
|
||||
_pendingLoc = (loc.clone() as Location);
|
||||
var clist :ConfirmAdapter = new ConfirmAdapter(
|
||||
function () :void {
|
||||
_location = _pendingLoc;
|
||||
_pendingLoc = null;
|
||||
if (listener != null) {
|
||||
listener.requestCompleted(_location);
|
||||
}
|
||||
},
|
||||
function (reason :String) :void {
|
||||
_pendingLoc = null;
|
||||
if (listener != null) {
|
||||
listener.requestFailed(new Error(reason));
|
||||
}
|
||||
});
|
||||
_sservice.changeLocation(sceneId, loc, clist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Issues a request to join the cluster associated with the specified user (starting one if
|
||||
* necessary).
|
||||
*
|
||||
* @param froid the bodyOid of another user; the calling user will be made to join the target
|
||||
* user's cluster.
|
||||
* @param listener will be notified of success or failure.
|
||||
*/
|
||||
public function joinCluster (froid :int, listener :com.threerings.util.ResultListener) :void
|
||||
{
|
||||
var scene :SpotScene = (_scdir.getScene() as SpotScene);
|
||||
if (scene == null) {
|
||||
log.warning("Requested to join cluster, but we're not currently in any scene " +
|
||||
"[froid=" + froid + "].");
|
||||
if (listener != null) {
|
||||
listener.requestFailed(new Error("m.cant_get_there"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("Joining cluster [friend=" + froid + "].");
|
||||
|
||||
_sservice.joinCluster(froid, new ConfirmAdapter(
|
||||
function () :void {
|
||||
if (listener != null) {
|
||||
listener.requestCompleted(null);
|
||||
}
|
||||
},
|
||||
function (reason :String) :void {
|
||||
if (listener != null) {
|
||||
listener.requestFailed(new Error(reason));
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a chat message to the other users in the cluster to which the location that we
|
||||
* currently occupy belongs.
|
||||
*
|
||||
* @return true if a cluster speak message was delivered, false if we are not in a valid
|
||||
* cluster and refused to deliver the request.
|
||||
*/
|
||||
public function requestClusterSpeak (
|
||||
message :String, mode :int = ChatCodes.DEFAULT_MODE) :Boolean
|
||||
{
|
||||
// make sure we're currently in a scene
|
||||
var scene :SpotScene = (_scdir.getScene() as SpotScene);
|
||||
if (scene == null) {
|
||||
log.warning("Requested to speak to cluster, but we're not currently in any scene " +
|
||||
"[message=" + message + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
// make sure we're part of a cluster
|
||||
if (_self.getClusterOid() <= 0) {
|
||||
log.info("Ignoring cluster speak as we're not in a cluster " +
|
||||
"[cloid=" + _self.getClusterOid() + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
message = _chatdir.filter(message, null, true);
|
||||
if (message != null) {
|
||||
_sservice.clusterSpeak(message, mode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function objectAvailable (object :DObject) :void
|
||||
{
|
||||
clearCluster(false);
|
||||
var oid :int = object.getOid();
|
||||
if (oid != _self.getClusterOid()) {
|
||||
// we got it too late, just unsubscribe
|
||||
var omgr :DObjectManager = _wctx.getDObjectManager();
|
||||
omgr.unsubscribeFromObject(oid, this);
|
||||
} else {
|
||||
// it's our new cluster!
|
||||
_clobj = object;
|
||||
if (_chatdir != null) {
|
||||
_chatdir.addAuxiliarySource(object, SpotCodes.CLUSTER_CHAT_TYPE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function requestFailed (oid :int, cause :ObjectAccessError) :void
|
||||
{
|
||||
log.warning("Unable to subscribe to cluster chat object [oid=" + oid +
|
||||
", cause=" + cause + "].");
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function attributeChanged (event :AttributeChangedEvent) :void
|
||||
{
|
||||
if (event.getName() == _self.getClusterField() && event.getValue() != event.getOldValue()) {
|
||||
maybeUpdateCluster();
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function clientDidLogon (event :ClientEvent) :void
|
||||
{
|
||||
super.clientDidLogon(event);
|
||||
|
||||
var body :BodyObject = CrowdClient(event.getClient()).bodyOf();
|
||||
if (body is ClusteredBodyObject) {
|
||||
// listen to the body
|
||||
body.addListener(this);
|
||||
_self = (body as ClusteredBodyObject);
|
||||
|
||||
// we may need to subscribe to a cluster due to session resumption
|
||||
maybeUpdateCluster();
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function clientObjectDidChange (event :ClientEvent) :void
|
||||
{
|
||||
super.clientObjectDidChange(event);
|
||||
|
||||
var body :BodyObject = CrowdClient(event.getClient()).bodyOf();
|
||||
if (body is ClusteredBodyObject) {
|
||||
// listen to the body
|
||||
body.addListener(this);
|
||||
_self = (body as ClusteredBodyObject);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function clientDidLogoff (event :ClientEvent) :void
|
||||
{
|
||||
super.clientDidLogoff(event);
|
||||
|
||||
// clear out our business
|
||||
_location = null;
|
||||
_pendingLoc = null;
|
||||
_sservice = null;
|
||||
clearCluster(true);
|
||||
|
||||
var body :BodyObject = CrowdClient(event.getClient()).bodyOf();
|
||||
if (body is ClusteredBodyObject) {
|
||||
body.removeListener(this);
|
||||
}
|
||||
_self = null;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override protected function fetchServices (client :Client) :void
|
||||
{
|
||||
_sservice = (client.requireService(SpotService) as SpotService);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when we move from one scene to another, or to a non-scene.
|
||||
*/
|
||||
protected function handleSceneChange (plobj :PlaceObject) :void
|
||||
{
|
||||
// determine our location in the new scene if we have one
|
||||
var scloc :SceneLocation = null;
|
||||
var ssobj :SpotSceneObject = (plobj as SpotSceneObject);
|
||||
if (ssobj != null) {
|
||||
scloc = ssobj.occupantLocs.get(
|
||||
CrowdClient(_wctx.getClient()).bodyOf().getOid()) as SceneLocation;
|
||||
}
|
||||
_location = (scloc == null) ? null : scloc.loc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if our cluster has changed and does the necessary subscription machinations if
|
||||
* necessary.
|
||||
*/
|
||||
protected function maybeUpdateCluster () :void
|
||||
{
|
||||
var cloid :int = _self.getClusterOid();
|
||||
if ((_clobj == null && cloid <= 0) || (_clobj != null && cloid == _clobj.getOid())) {
|
||||
// our cluster didn't change, we can stop now
|
||||
return;
|
||||
}
|
||||
|
||||
// clear out any old cluster object
|
||||
clearCluster(false);
|
||||
|
||||
// if there's a new cluster object, subscribe to it
|
||||
if (_chatdir != null && cloid > 0) {
|
||||
var omgr :DObjectManager = _wctx.getDObjectManager();
|
||||
// we'll wire up to the chat director when this completes
|
||||
omgr.subscribeToObject(cloid, this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience routine to unwire chat for and unsubscribe from our current cluster, if any.
|
||||
*
|
||||
* @param force clear the cluster even if we're still apparently in it.
|
||||
*/
|
||||
protected function clearCluster (force :Boolean) :void
|
||||
{
|
||||
if (_clobj != null && (force || (_clobj.getOid() != _self.getClusterOid()))) {
|
||||
if (_chatdir != null) {
|
||||
_chatdir.removeAuxiliarySource(_clobj);
|
||||
}
|
||||
var omgr :DObjectManager = _wctx.getDObjectManager();
|
||||
omgr.unsubscribeFromObject(_clobj.getOid(), this);
|
||||
_clobj = null;
|
||||
}
|
||||
}
|
||||
|
||||
/** The active client context. */
|
||||
protected var _wctx :WhirledContext;
|
||||
|
||||
/** Access to spot scene services. */
|
||||
protected var _sservice :SpotService;
|
||||
|
||||
/** The scene director with which we are cooperating. */
|
||||
protected var _scdir :SceneDirector;
|
||||
|
||||
/** A casted reference to our clustered body object. */
|
||||
protected var _self :ClusteredBodyObject;
|
||||
|
||||
/** A reference to the chat director with which we coordinate. */
|
||||
protected var _chatdir :ChatDirector;
|
||||
|
||||
/** The location we currently occupy. */
|
||||
protected var _location :Location;
|
||||
|
||||
/** The location to which we have an outstanding change location request. */
|
||||
protected var _pendingLoc :Location;
|
||||
|
||||
/** The cluster chat object for the cluster we currently occupy. */
|
||||
protected var _clobj :DObject;
|
||||
}
|
||||
}
|
||||
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
|
||||
import com.threerings.whirled.client.SceneDirector;
|
||||
import com.threerings.whirled.data.SceneModel;
|
||||
import com.threerings.whirled.spot.client.SpotService_SpotSceneMoveListener;
|
||||
|
||||
class SceneDirectorWrapper
|
||||
implements SpotService_SpotSceneMoveListener
|
||||
{
|
||||
public function SceneDirectorWrapper (scdir :SceneDirector) {
|
||||
_scdir = scdir;
|
||||
}
|
||||
|
||||
public function requestFailed (cause :String) :void {
|
||||
_scdir.requestFailed(cause);
|
||||
}
|
||||
|
||||
public function moveSucceeded (placeId :int, config :PlaceConfig) :void {
|
||||
_scdir.moveSucceeded(placeId, config);
|
||||
}
|
||||
|
||||
public function moveSucceededWithUpdates (
|
||||
placeId :int, config :PlaceConfig, updates :TypedArray) :void{
|
||||
_scdir.moveSucceededWithUpdates(placeId, config, updates);
|
||||
}
|
||||
|
||||
public function moveSucceededWithScene (placeId :int, config :PlaceConfig,
|
||||
model :SceneModel) :void {
|
||||
_scdir.moveSucceededWithScene(placeId, config, model);
|
||||
}
|
||||
|
||||
public function moveRequiresServerSwitch (hostname :String, ports :TypedArray) :void {
|
||||
_scdir.moveRequiresServerSwitch(hostname, ports);
|
||||
}
|
||||
|
||||
public function requestCancelled () :void {
|
||||
_scdir.cancelMoveRequest();
|
||||
}
|
||||
|
||||
protected var _scdir :SceneDirector;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// $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.whirled.spot.client {
|
||||
|
||||
import com.threerings.presents.client.InvocationService;
|
||||
import com.threerings.presents.client.InvocationService_ConfirmListener;
|
||||
|
||||
import com.threerings.whirled.spot.data.Location;
|
||||
|
||||
/**
|
||||
* An ActionScript version of the Java SpotService interface.
|
||||
*/
|
||||
public interface SpotService extends InvocationService
|
||||
{
|
||||
// from Java interface SpotService
|
||||
function changeLocation (arg1 :int, arg2 :Location, arg3 :InvocationService_ConfirmListener) :void;
|
||||
|
||||
// from Java interface SpotService
|
||||
function clusterSpeak (arg1 :String, arg2 :int) :void;
|
||||
|
||||
// from Java interface SpotService
|
||||
function joinCluster (arg1 :int, arg2 :InvocationService_ConfirmListener) :void;
|
||||
|
||||
// from Java interface SpotService
|
||||
function traversePortal (arg1 :int, arg2 :int, arg3 :int, arg4 :SpotService_SpotSceneMoveListener) :void;
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// $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.whirled.spot.client {
|
||||
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.presents.client.InvocationService_InvocationListener;
|
||||
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
|
||||
import com.threerings.whirled.data.SceneModel;
|
||||
|
||||
/**
|
||||
* An ActionScript version of the Java SpotService_SpotSceneMoveListener interface.
|
||||
*/
|
||||
public interface SpotService_SpotSceneMoveListener
|
||||
extends InvocationService_InvocationListener
|
||||
{
|
||||
// from Java SpotService_SpotSceneMoveListener
|
||||
function moveRequiresServerSwitch (arg1 :String, arg2 :TypedArray /* of int */) :void
|
||||
|
||||
// from Java SpotService_SpotSceneMoveListener
|
||||
function moveSucceeded (arg1 :int, arg2 :PlaceConfig) :void
|
||||
|
||||
// from Java SpotService_SpotSceneMoveListener
|
||||
function moveSucceededWithScene (arg1 :int, arg2 :PlaceConfig, arg3 :SceneModel) :void
|
||||
|
||||
// from Java SpotService_SpotSceneMoveListener
|
||||
function moveSucceededWithUpdates (arg1 :int, arg2 :PlaceConfig, arg3 :TypedArray /* of class com.threerings.whirled.data.SceneUpdate */) :void
|
||||
|
||||
// from Java SpotService_SpotSceneMoveListener
|
||||
function requestCancelled () :void
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
//
|
||||
// $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.whirled.spot.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
import com.threerings.io.Streamable;
|
||||
|
||||
import com.threerings.util.Hashable;
|
||||
|
||||
import com.threerings.presents.dobj.DSet_Entry;
|
||||
|
||||
/**
|
||||
* Contains information on clusters.
|
||||
*/
|
||||
public class Cluster
|
||||
implements DSet_Entry, Streamable, Hashable
|
||||
{
|
||||
/** The bounding rectangle of this cluster. */
|
||||
public var x :int;
|
||||
public var y :int;
|
||||
public var width :int;
|
||||
public var height :int;
|
||||
|
||||
/** A unique identifier for this cluster (also the distributed object
|
||||
* id of the cluster chat object). */
|
||||
public var clusterOid :int;
|
||||
|
||||
public function Cluster ()
|
||||
{
|
||||
// nothing needed
|
||||
}
|
||||
|
||||
// from Hashable
|
||||
public function hashCode () :int
|
||||
{
|
||||
return clusterOid;
|
||||
}
|
||||
|
||||
// from Hashable
|
||||
public function equals (o :Object) :Boolean
|
||||
{
|
||||
return (o is Cluster) && ((o as Cluster).clusterOid == this.clusterOid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a string representation of this instance.
|
||||
*/
|
||||
public function toString () :String
|
||||
{
|
||||
return "x=" + x + ", y=" + y + ", width=" + width + ", height=" + height +
|
||||
", clusterOid=" + clusterOid;
|
||||
}
|
||||
|
||||
// documentation inherited from interface DSet_Entry
|
||||
public function getKey () :Object
|
||||
{
|
||||
return clusterOid;
|
||||
}
|
||||
|
||||
// documentation inherited from interface Streamable
|
||||
public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
x = ins.readInt();
|
||||
y = ins.readInt();
|
||||
width = ins.readInt();
|
||||
height = ins.readInt();
|
||||
|
||||
clusterOid = ins.readInt();
|
||||
}
|
||||
|
||||
// documentation inherited from interface Streamable
|
||||
public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
out.writeInt(x);
|
||||
out.writeInt(y);
|
||||
out.writeInt(width);
|
||||
out.writeInt(height);
|
||||
|
||||
out.writeInt(clusterOid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// $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.whirled.spot.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
|
||||
import com.threerings.presents.dobj.DObject;
|
||||
import com.threerings.presents.dobj.OidList;
|
||||
|
||||
/**
|
||||
* Used to dispatch chat in clusters.
|
||||
*/
|
||||
public class ClusterObject extends DObject
|
||||
{
|
||||
// AUTO-GENERATED: FIELDS START
|
||||
/** The field name of the <code>occupants</code> field. */
|
||||
public static const OCCUPANTS :String = "occupants";
|
||||
// AUTO-GENERATED: FIELDS END
|
||||
|
||||
/**
|
||||
* Tracks the oid of the body objects that occupy this cluster.
|
||||
*/
|
||||
public var occupants :OidList = new OidList();
|
||||
|
||||
// // AUTO-GENERATED: METHODS START
|
||||
// /**
|
||||
// * Requests that <code>oid</code> be added to the <code>occupants</code>
|
||||
// * oid list. The list will not change until the event is actually
|
||||
// * propagated through the system.
|
||||
// */
|
||||
// public function addToOccupants (oid :int) :void
|
||||
// {
|
||||
// requestOidAdd(OCCUPANTS, oid);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Requests that <code>oid</code> be removed from the
|
||||
// * <code>occupants</code> oid list. The list will not change until the
|
||||
// * event is actually propagated through the system.
|
||||
// */
|
||||
// public function removeFromOccupants (oid :int) :void
|
||||
// {
|
||||
// requestOidRemove(OCCUPANTS, oid);
|
||||
// }
|
||||
// // AUTO-GENERATED: METHODS END
|
||||
//
|
||||
// override public function writeObject (out :ObjectOutputStream) :void
|
||||
// {
|
||||
// super.writeObject(out);
|
||||
//
|
||||
// out.writeObject(occupants);
|
||||
// }
|
||||
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
|
||||
occupants = OidList(ins.readObject());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
//
|
||||
// $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.whirled.spot.data {
|
||||
|
||||
import com.threerings.crowd.data.BodyObject;
|
||||
|
||||
/**
|
||||
* Defines some required methods for a {@link BodyObject} that is to participate in the Whirled
|
||||
* Spot system.
|
||||
*/
|
||||
public interface ClusteredBodyObject
|
||||
{
|
||||
/**
|
||||
* Returns the field name of the cluster oid distributed object field.
|
||||
*/
|
||||
function getClusterField () :String;
|
||||
|
||||
/**
|
||||
* Returns the oid of the cluster to which this user currently
|
||||
* belongs.
|
||||
*/
|
||||
function getClusterOid () :int;
|
||||
|
||||
// /**
|
||||
// * Sets the oid of the cluster to which this user currently belongs.
|
||||
// */
|
||||
// function setClusterOid (clusterOid :int) :void;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// $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.whirled.spot.data {
|
||||
|
||||
import com.threerings.io.Streamable;
|
||||
|
||||
import com.threerings.util.Cloneable;
|
||||
import com.threerings.util.Hashable;
|
||||
|
||||
/**
|
||||
* Contains information on a scene occupant's position and orientation.
|
||||
*/
|
||||
public interface Location extends Cloneable, Streamable, Hashable
|
||||
{
|
||||
/**
|
||||
* Get a new Location instance that is equals() to this one but that
|
||||
* has an orientation facing the opposite direction.
|
||||
*/
|
||||
function getOpposite () :Location;
|
||||
|
||||
/**
|
||||
* Two locations are equivalent if they specify the same location
|
||||
* and orientation.
|
||||
*/
|
||||
function equivalent (other :Location) :Boolean;
|
||||
|
||||
/** Two locations are equals by coordinates only. */
|
||||
//function equals (other :Object) :Boolean;
|
||||
|
||||
/** The hashcode should be based on coordinates only. */
|
||||
//function hashCode () :int;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
//
|
||||
// $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.whirled.spot.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.whirled.data.SceneModel;
|
||||
import com.threerings.whirled.data.SceneUpdate;
|
||||
|
||||
/**
|
||||
* A scene update to add/remove portals.
|
||||
*/
|
||||
public class ModifyPortalsUpdate extends SceneUpdate
|
||||
{
|
||||
/** The portals to be removed from the room. */
|
||||
public var portalsRemoved :TypedArray;
|
||||
|
||||
/** The portals to be added to the scene. */
|
||||
public var portalsAdded :TypedArray;
|
||||
|
||||
public function ModifyPortalsUpdate ()
|
||||
{
|
||||
// nothing needed
|
||||
}
|
||||
|
||||
override public function apply (model :SceneModel) :void
|
||||
{
|
||||
super.apply(model);
|
||||
|
||||
// extract the spot scene model
|
||||
var spotModel :SpotSceneModel = SpotSceneModel.getSceneModel(model);
|
||||
|
||||
var portal :Portal;
|
||||
if (portalsRemoved != null) {
|
||||
for each (portal in portalsRemoved) {
|
||||
spotModel.removePortal(portal);
|
||||
}
|
||||
}
|
||||
if (portalsAdded != null) {
|
||||
for each (portal in portalsAdded) {
|
||||
spotModel.addPortal(portal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the update with all necessary data.
|
||||
*/
|
||||
public function initialize (
|
||||
targetId :int, targetVersion :int, removed :TypedArray,
|
||||
added :TypedArray) :void
|
||||
{
|
||||
init(targetId, targetVersion);
|
||||
|
||||
portalsRemoved = removed;
|
||||
portalsAdded = added;
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
portalsRemoved = TypedArray(ins.readObject());
|
||||
portalsAdded = TypedArray(ins.readObject());
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
super.writeObject(out);
|
||||
out.writeObject(portalsRemoved);
|
||||
out.writeObject(portalsAdded);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
//
|
||||
// $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.whirled.spot.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
import com.threerings.io.SimpleStreamableObject;
|
||||
|
||||
import com.threerings.util.ClassUtil;
|
||||
import com.threerings.util.Cloneable;
|
||||
import com.threerings.util.Hashable;
|
||||
import com.threerings.util.Joiner;
|
||||
|
||||
/**
|
||||
* Represents an exit to another scene. A body sprite would walk over to a
|
||||
* portal's coordinates and then either proceed off of the edge of the
|
||||
* display, or open a door and walk through it, or fizzle away in a Star
|
||||
* Trekkian transporter style or whatever is appropriate for the game in
|
||||
* question. It contains information on the scene to which the body exits
|
||||
* when using this portal and the location at which the body sprite should
|
||||
* appear in that target scene.
|
||||
*/
|
||||
public class Portal extends SimpleStreamableObject
|
||||
implements Cloneable, Hashable
|
||||
{
|
||||
/** This portal's unique identifier. */
|
||||
public var portalId :int;
|
||||
|
||||
/** The location of the portal.
|
||||
* This field is present on client and server, it is streamed specially. */
|
||||
public var loc :Location;
|
||||
|
||||
/** The scene identifier of the scene to which a body will exit when
|
||||
* they "use" this portal. */
|
||||
public var targetSceneId :int;
|
||||
|
||||
/** The portal identifier of the portal at which a body will enter
|
||||
* the target scene when they "use" this portal, or -1 to specify
|
||||
* that the body enters on the default portal, whatever id it is. */
|
||||
public var targetPortalId :int;
|
||||
|
||||
public function Portal ()
|
||||
{
|
||||
// nothing needed
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a location instance configured with the location and
|
||||
* opposite orientation of this portal. This is useful for when a body
|
||||
* is entering a scene at a portal and we want them to face the
|
||||
* opposite direction (as they are entering via the portal rather than
|
||||
* leaving, which is the natural "orientation" of a portal).
|
||||
*/
|
||||
public function getOppLocation () :Location
|
||||
{
|
||||
return loc.getOpposite();
|
||||
}
|
||||
|
||||
// documentation inherited from interface Hashable
|
||||
public function hashCode () :int
|
||||
{
|
||||
return portalId;
|
||||
}
|
||||
|
||||
// documentation inherited from interface Cloneable
|
||||
public function clone () :Object
|
||||
{
|
||||
var p :Portal = (ClassUtil.newInstance(this) as Portal);
|
||||
p.portalId = portalId;
|
||||
p.loc = loc;
|
||||
p.targetSceneId = targetSceneId;
|
||||
p.targetPortalId = targetPortalId;
|
||||
return p;
|
||||
}
|
||||
|
||||
// documentation inherited from interface Hashable
|
||||
public function equals (other :Object) :Boolean
|
||||
{
|
||||
return (other is Portal) &&
|
||||
((other as Portal).portalId == portalId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a location instance configured with the location and
|
||||
* orientation of this portal.
|
||||
*/
|
||||
public function getLocation () :Location
|
||||
{
|
||||
return (loc.clone() as Location);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the portal has a potentially valid target scene and
|
||||
* portal id (they are not guaranteed to exist, but they are at least
|
||||
* potentially valid values rather than 0).
|
||||
*/
|
||||
public function isValid () :Boolean
|
||||
{
|
||||
return (targetSceneId > 0) &&
|
||||
// the target portal must be positive, or -1
|
||||
((targetPortalId > 0) || (targetPortalId == -1));
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
portalId = ins.readShort();
|
||||
loc = Location(ins.readObject());
|
||||
targetSceneId = ins.readInt();
|
||||
targetPortalId = ins.readShort();
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
super.writeObject(out);
|
||||
out.writeShort(portalId);
|
||||
out.writeObject(loc);
|
||||
out.writeInt(targetSceneId);
|
||||
out.writeShort(targetPortalId);
|
||||
}
|
||||
|
||||
// from SimpleStreamableObject
|
||||
override protected function toStringJoiner (j :Joiner): void
|
||||
{
|
||||
// no super
|
||||
j.add("id", portalId, "destScene", targetSceneId, "loc", loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
//
|
||||
// $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.whirled.spot.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
import com.threerings.io.SimpleStreamableObject;
|
||||
|
||||
import com.threerings.util.Hashable;
|
||||
|
||||
import com.threerings.presents.dobj.DSet_Entry;
|
||||
|
||||
/**
|
||||
* Extends {@link Location} with the data and functionality needed to
|
||||
* represent a particular user's location in a scene.
|
||||
*/
|
||||
public class SceneLocation extends SimpleStreamableObject
|
||||
implements DSet_Entry, Hashable
|
||||
{
|
||||
/** The oid of the body that occupies this location. */
|
||||
public var bodyOid :int;
|
||||
|
||||
/** The actual location, which is interpreted by the display system. */
|
||||
public var loc :Location;
|
||||
|
||||
/**
|
||||
* Creates a scene location with the specified information.
|
||||
*/
|
||||
public function SceneLocation (loc :Location = null, bodyOid :int = 0)
|
||||
{
|
||||
this.loc = loc;
|
||||
this.bodyOid = bodyOid;
|
||||
}
|
||||
|
||||
// documentation inherited from interface Hashable
|
||||
public function hashCode () :int
|
||||
{
|
||||
return loc.hashCode();
|
||||
}
|
||||
|
||||
// documentation inherited from interface Hashable
|
||||
public function equals (other :Object) :Boolean
|
||||
{
|
||||
return (other is SceneLocation) &&
|
||||
this.loc.equals((other as SceneLocation).loc);
|
||||
}
|
||||
|
||||
// documentation inherited from interface DSet_Entry
|
||||
public function getKey () :Object
|
||||
{
|
||||
return bodyOid;
|
||||
}
|
||||
|
||||
// documentation inherited from superinterface Streamable
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
bodyOid = ins.readInt();
|
||||
loc = Location(ins.readObject());
|
||||
}
|
||||
|
||||
// documentation inherited from superinterface Streamable
|
||||
override public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
super.writeObject(out);
|
||||
out.writeInt(bodyOid);
|
||||
out.writeObject(loc);
|
||||
}
|
||||
|
||||
/** Used for {@link #getKey}. */
|
||||
protected var _key :int;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
//
|
||||
// $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.whirled.spot.data {
|
||||
|
||||
import com.threerings.crowd.chat.data.ChatCodes;
|
||||
|
||||
import com.threerings.whirled.data.SceneCodes;
|
||||
|
||||
/**
|
||||
* Contains codes used by the Spot invocation services.
|
||||
*/
|
||||
public class SpotCodes extends SceneCodes /*, ChatCodes */
|
||||
{
|
||||
/** An error code indicating that the portal specified in a
|
||||
* traversePortal request does not exist. */
|
||||
public static const NO_SUCH_PORTAL :String = "m.no_such_portal";
|
||||
|
||||
/** An error code indicating that a location is occupied. Usually
|
||||
* generated by a failed changeLoc request. */
|
||||
public static const LOCATION_OCCUPIED :String = "m.location_occupied";
|
||||
|
||||
/** An error code indicating that a location is not valid. Usually
|
||||
* generated by a failed changeLoc request. */
|
||||
public static const INVALID_LOCATION :String = "m.invalid_location";
|
||||
|
||||
/** An error code indicating that a cluster is not valid. Usually
|
||||
* generated by a failed joinCluster request. */
|
||||
public static const NO_SUCH_CLUSTER :String = "m.no_such_cluster";
|
||||
|
||||
/** An error code indicating that a cluster is full. Usually generated
|
||||
* by a failed joinCluster request. */
|
||||
public static const CLUSTER_FULL :String = "m.cluster_full";
|
||||
|
||||
/** The chat type code with which we register our cluster auxiliary
|
||||
* chat objects. Chat display implementations should interpret chat
|
||||
* messages with this type accordingly. */
|
||||
public static const CLUSTER_CHAT_TYPE :String = "clusterChat";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
//
|
||||
// $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.whirled.spot.data {
|
||||
|
||||
import com.threerings.util.Byte;
|
||||
import com.threerings.util.Integer;
|
||||
|
||||
import com.threerings.presents.client.InvocationService_ConfirmListener;
|
||||
import com.threerings.presents.data.InvocationMarshaller;
|
||||
import com.threerings.presents.data.InvocationMarshaller_ConfirmMarshaller;
|
||||
|
||||
import com.threerings.whirled.spot.client.SpotService;
|
||||
import com.threerings.whirled.spot.client.SpotService_SpotSceneMoveListener;
|
||||
|
||||
/**
|
||||
* Provides the implementation of the <code>SpotService</code> interface
|
||||
* that marshalls the arguments and delivers the request to the provider
|
||||
* on the server. Also provides an implementation of the response listener
|
||||
* interfaces that marshall the response arguments and deliver them back
|
||||
* to the requesting client.
|
||||
*/
|
||||
public class SpotMarshaller extends InvocationMarshaller
|
||||
implements SpotService
|
||||
{
|
||||
/** The method id used to dispatch <code>changeLocation</code> requests. */
|
||||
public static const CHANGE_LOCATION :int = 1;
|
||||
|
||||
// from interface SpotService
|
||||
public function changeLocation (arg1 :int, arg2 :Location, arg3 :InvocationService_ConfirmListener) :void
|
||||
{
|
||||
var listener3 :InvocationMarshaller_ConfirmMarshaller = new InvocationMarshaller_ConfirmMarshaller();
|
||||
listener3.listener = arg3;
|
||||
sendRequest(CHANGE_LOCATION, [
|
||||
Integer.valueOf(arg1), arg2, listener3
|
||||
]);
|
||||
}
|
||||
|
||||
/** The method id used to dispatch <code>clusterSpeak</code> requests. */
|
||||
public static const CLUSTER_SPEAK :int = 2;
|
||||
|
||||
// from interface SpotService
|
||||
public function clusterSpeak (arg1 :String, arg2 :int) :void
|
||||
{
|
||||
sendRequest(CLUSTER_SPEAK, [
|
||||
arg1, Byte.valueOf(arg2)
|
||||
]);
|
||||
}
|
||||
|
||||
/** The method id used to dispatch <code>joinCluster</code> requests. */
|
||||
public static const JOIN_CLUSTER :int = 3;
|
||||
|
||||
// from interface SpotService
|
||||
public function joinCluster (arg1 :int, arg2 :InvocationService_ConfirmListener) :void
|
||||
{
|
||||
var listener2 :InvocationMarshaller_ConfirmMarshaller = new InvocationMarshaller_ConfirmMarshaller();
|
||||
listener2.listener = arg2;
|
||||
sendRequest(JOIN_CLUSTER, [
|
||||
Integer.valueOf(arg1), listener2
|
||||
]);
|
||||
}
|
||||
|
||||
/** The method id used to dispatch <code>traversePortal</code> requests. */
|
||||
public static const TRAVERSE_PORTAL :int = 4;
|
||||
|
||||
// from interface SpotService
|
||||
public function traversePortal (arg1 :int, arg2 :int, arg3 :int, arg4 :SpotService_SpotSceneMoveListener) :void
|
||||
{
|
||||
var listener4 :SpotMarshaller_SpotSceneMoveMarshaller = new SpotMarshaller_SpotSceneMoveMarshaller();
|
||||
listener4.listener = arg4;
|
||||
sendRequest(TRAVERSE_PORTAL, [
|
||||
Integer.valueOf(arg1), Integer.valueOf(arg2), Integer.valueOf(arg3), listener4
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
//
|
||||
// $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.whirled.spot.data {
|
||||
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.presents.data.InvocationMarshaller_ListenerMarshaller;
|
||||
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
|
||||
import com.threerings.whirled.data.SceneModel;
|
||||
import com.threerings.whirled.spot.client.SpotService_SpotSceneMoveListener;
|
||||
|
||||
/**
|
||||
* Marshalls instances of the SpotService_SpotSceneMoveMarshaller interface.
|
||||
*/
|
||||
public class SpotMarshaller_SpotSceneMoveMarshaller
|
||||
extends InvocationMarshaller_ListenerMarshaller
|
||||
{
|
||||
/** The method id used to dispatch <code>moveRequiresServerSwitch</code> responses. */
|
||||
public static const MOVE_REQUIRES_SERVER_SWITCH :int = 1;
|
||||
|
||||
/** The method id used to dispatch <code>moveSucceeded</code> responses. */
|
||||
public static const MOVE_SUCCEEDED :int = 2;
|
||||
|
||||
/** The method id used to dispatch <code>moveSucceededWithScene</code> responses. */
|
||||
public static const MOVE_SUCCEEDED_WITH_SCENE :int = 3;
|
||||
|
||||
/** The method id used to dispatch <code>moveSucceededWithUpdates</code> responses. */
|
||||
public static const MOVE_SUCCEEDED_WITH_UPDATES :int = 4;
|
||||
|
||||
/** The method id used to dispatch <code>requestCancelled</code> responses. */
|
||||
public static const REQUEST_CANCELLED :int = 5;
|
||||
|
||||
// from InvocationMarshaller_ListenerMarshaller
|
||||
override public function dispatchResponse (methodId :int, args :Array) :void
|
||||
{
|
||||
switch (methodId) {
|
||||
case MOVE_REQUIRES_SERVER_SWITCH:
|
||||
(listener as SpotService_SpotSceneMoveListener).moveRequiresServerSwitch(
|
||||
(args[0] as String), (args[1] as TypedArray /* of int */));
|
||||
return;
|
||||
|
||||
case MOVE_SUCCEEDED:
|
||||
(listener as SpotService_SpotSceneMoveListener).moveSucceeded(
|
||||
(args[0] as int), (args[1] as PlaceConfig));
|
||||
return;
|
||||
|
||||
case MOVE_SUCCEEDED_WITH_SCENE:
|
||||
(listener as SpotService_SpotSceneMoveListener).moveSucceededWithScene(
|
||||
(args[0] as int), (args[1] as PlaceConfig), (args[2] as SceneModel));
|
||||
return;
|
||||
|
||||
case MOVE_SUCCEEDED_WITH_UPDATES:
|
||||
(listener as SpotService_SpotSceneMoveListener).moveSucceededWithUpdates(
|
||||
(args[0] as int), (args[1] as PlaceConfig), (args[2] as TypedArray /* of class com.threerings.whirled.data.SceneUpdate */));
|
||||
return;
|
||||
|
||||
case REQUEST_CANCELLED:
|
||||
(listener as SpotService_SpotSceneMoveListener).requestCancelled(
|
||||
);
|
||||
return;
|
||||
|
||||
default:
|
||||
super.dispatchResponse(methodId, args);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// $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.whirled.spot.data {
|
||||
|
||||
import com.threerings.util.Iterator;
|
||||
|
||||
/**
|
||||
* Makes available the spot scene information that the server needs to do
|
||||
* its business.
|
||||
*/
|
||||
public interface SpotScene
|
||||
{
|
||||
/**
|
||||
* Returns a {@link Portal} object for the portal with the specified
|
||||
* id or null if no portal exists with that id.
|
||||
*/
|
||||
function getPortal (portalId :int) :Portal;
|
||||
|
||||
/**
|
||||
* Returns the number of portals in this scene.
|
||||
*/
|
||||
function getPortalCount () :int;
|
||||
|
||||
/**
|
||||
* Returns an iterator over the portals in this scene.
|
||||
*/
|
||||
function getPortals () :Iterator;
|
||||
|
||||
/**
|
||||
* Returns the portal id that should be assigned to the next portal
|
||||
* added to this scene.
|
||||
*/
|
||||
function getNextPortalId () :int;
|
||||
|
||||
/**
|
||||
* Returns the portal that represents the default entrance to this
|
||||
* scene. If a body enters the scene at logon time rather than
|
||||
* entering from some other scene, this is the portal at which they
|
||||
* would appear.
|
||||
*/
|
||||
function getDefaultEntrance () :Portal;
|
||||
|
||||
/**
|
||||
* Adds a portal to this scene, immediately making the requisite
|
||||
* modifications to the underlying scene model. The portal id should
|
||||
* have already been assigned using the value obtained from {@link
|
||||
* #getNextPortalId}.
|
||||
*/
|
||||
function addPortal (portal :Portal) :void;
|
||||
|
||||
/**
|
||||
* Removes the specified portal from the scene.
|
||||
*/
|
||||
function removePortal (portal :Portal) :void;
|
||||
|
||||
/**
|
||||
* Sets the default entrance in this scene, immediately making the
|
||||
* requisite modifications to the underlying scene model.
|
||||
*/
|
||||
function setDefaultEntrance (portal :Portal) :void;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
//
|
||||
// $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.whirled.spot.data {
|
||||
|
||||
import com.threerings.util.ArrayIterator;
|
||||
import com.threerings.util.Iterator;
|
||||
import com.threerings.util.Log;
|
||||
import com.threerings.util.Map;
|
||||
import com.threerings.util.Maps;
|
||||
|
||||
/**
|
||||
* An implementation of the {@link SpotScene} interface.
|
||||
*/
|
||||
public class SpotSceneImpl
|
||||
implements SpotScene
|
||||
{
|
||||
/**
|
||||
* Creates an instance that will obtain data from the supplied spot
|
||||
* scene model.
|
||||
*/
|
||||
public function SpotSceneImpl (model :SpotSceneModel = null)
|
||||
{
|
||||
if (model != null) {
|
||||
_smodel = model;
|
||||
readPortals();
|
||||
|
||||
} else {
|
||||
_smodel = new SpotSceneModel();
|
||||
}
|
||||
}
|
||||
|
||||
protected function readPortals () :void
|
||||
{
|
||||
_portals.clear();
|
||||
for each (var port :Portal in _smodel.portals) {
|
||||
_portals.put(port.portalId, port);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function getPortal (portalId :int) :Portal
|
||||
{
|
||||
if (portalId == -1) {
|
||||
portalId = _smodel.defaultEntranceId;
|
||||
}
|
||||
return (_portals.get(portalId) as Portal);
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function getPortalCount () :int
|
||||
{
|
||||
return _portals.size();
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function getPortals () :Iterator
|
||||
{
|
||||
return new ArrayIterator(_portals.values());
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function getNextPortalId () :int
|
||||
{
|
||||
// compute a new portal id for our friend the portal
|
||||
for (var ii :int = 1; ii < MAX_PORTAL_ID; ii++) {
|
||||
if (!_portals.containsKey(ii)) {
|
||||
return ii;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function getDefaultEntrance () :Portal
|
||||
{
|
||||
return getPortal(-1); // -1 is a shortcut meaning "default"
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function addPortal (portal :Portal) :void
|
||||
{
|
||||
if (portal.portalId <= 0) {
|
||||
Log.getLog(this).warning("Refusing to add zero-id portal " +
|
||||
"[scene=" + this + ", portal=" + portal + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
// add it to our model
|
||||
_smodel.addPortal(portal);
|
||||
|
||||
// and slap it into our table
|
||||
_portals.put(portal.portalId, portal);
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function removePortal (portal :Portal) :void
|
||||
{
|
||||
// remove the portal from our mapping
|
||||
_portals.remove(portal.portalId);
|
||||
|
||||
// remove it from the model
|
||||
_smodel.removePortal(portal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when we're being parsed from an XML scene model.
|
||||
*/
|
||||
public function setDefaultEntranceId (defaultEntranceId :int) :void
|
||||
{
|
||||
_smodel.defaultEntranceId = defaultEntranceId;
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function setDefaultEntrance (portal :Portal) :void
|
||||
{
|
||||
_smodel.defaultEntranceId = (portal == null) ? -1 : portal.portalId;
|
||||
}
|
||||
|
||||
/**
|
||||
* This should be called if a scene update was received that caused
|
||||
* our underlying scene model to change.
|
||||
*/
|
||||
public function updateReceived () :void
|
||||
{
|
||||
readPortals();
|
||||
}
|
||||
|
||||
/** A casted reference to our scene model. */
|
||||
protected var _smodel :SpotSceneModel;
|
||||
|
||||
/** A mapping from portal id to portal. */
|
||||
protected var _portals :Map = Maps.newMapOf(int);
|
||||
|
||||
/** We don't allow more than ~32k portals in a scene. Things would
|
||||
* slow down *way* before we got there. */
|
||||
protected static const MAX_PORTAL_ID :int = int(Math.pow(2, 15) - 1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
//
|
||||
// $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.whirled.spot.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
import com.threerings.io.SimpleStreamableObject;
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.util.Arrays;
|
||||
import com.threerings.util.ClassUtil;
|
||||
|
||||
import com.threerings.whirled.data.AuxModel;
|
||||
import com.threerings.whirled.data.SceneModel;
|
||||
|
||||
/**
|
||||
* The spot scene model extends the standard scene model with information
|
||||
* on portals. Portals are referenced by an identifier, unique within the
|
||||
* scene and unchanging, so that portals can stably reference the target
|
||||
* portal in the scene to which they connect.
|
||||
*/
|
||||
public class SpotSceneModel extends SimpleStreamableObject
|
||||
implements AuxModel
|
||||
{
|
||||
/** An array containing all portals in this scene. */
|
||||
public var portals :TypedArray = TypedArray.create(Portal);
|
||||
|
||||
/** The portal id of the default entrance to this scene. If a body
|
||||
* enters the scene without coming from another scene, this is the
|
||||
* portal at which they would appear. */
|
||||
public var defaultEntranceId :int = -1;
|
||||
|
||||
/**
|
||||
* Locates and returns the {@link SpotSceneModel} among the auxiliary
|
||||
* scene models associated with the supplied scene
|
||||
* model. <code>null</code> is returned if no spot scene model could
|
||||
* be found.
|
||||
*/
|
||||
public static function getSceneModel (model :SceneModel) :SpotSceneModel
|
||||
{
|
||||
for each (var aux :AuxModel in model.auxModels) {
|
||||
if (aux is SpotSceneModel) {
|
||||
return (aux as SpotSceneModel);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function SpotSceneModel ()
|
||||
{
|
||||
// nothing needed
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a portal from this model.
|
||||
*/
|
||||
public function removePortal (portal :Portal) :void
|
||||
{
|
||||
Arrays.removeFirst(portals, portal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a portal to this scene model.
|
||||
*/
|
||||
public function addPortal (portal :Portal) :void
|
||||
{
|
||||
portals.push(portal);
|
||||
}
|
||||
|
||||
// documentation inherited from superinterface Cloneable
|
||||
public function clone () :Object
|
||||
{
|
||||
var clazz :Class = ClassUtil.getClass(this);
|
||||
var model :SpotSceneModel = new clazz();
|
||||
|
||||
for each (var portal :Portal in portals) {
|
||||
model.portals.push(portal.clone());
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
portals = TypedArray(ins.readObject());
|
||||
defaultEntranceId = ins.readInt();
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
super.writeObject(out);
|
||||
out.writeObject(portals);
|
||||
out.writeInt(defaultEntranceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
//
|
||||
// $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.whirled.spot.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
|
||||
import com.threerings.presents.dobj.DSet;
|
||||
import com.threerings.presents.dobj.DSet_Entry;
|
||||
|
||||
import com.threerings.whirled.data.SceneObject;
|
||||
import com.threerings.whirled.spot.data.SceneLocation;
|
||||
|
||||
/**
|
||||
* Extends the {@link SceneObject} with information specific to spots.
|
||||
*/
|
||||
public class SpotSceneObject extends SceneObject
|
||||
{
|
||||
// AUTO-GENERATED: FIELDS START
|
||||
/** The field name of the <code>occupantLocs</code> field. */
|
||||
public static const OCCUPANT_LOCS :String = "occupantLocs";
|
||||
|
||||
/** The field name of the <code>clusters</code> field. */
|
||||
public static const CLUSTERS :String = "clusters";
|
||||
// AUTO-GENERATED: FIELDS END
|
||||
|
||||
/** A distributed set containing {@link SceneLocation} records for all
|
||||
* occupants of this scene. */
|
||||
public var occupantLocs :DSet = new DSet();
|
||||
SceneLocation; // plain reference to force linkage
|
||||
|
||||
/** Contains information on all {@link Cluster}s in this scene. */
|
||||
public var clusters :DSet = new DSet();
|
||||
|
||||
// // AUTO-GENERATED: METHODS START
|
||||
// /**
|
||||
// * Requests that the specified entry be added to the
|
||||
// * <code>occupantLocs</code> set. The set will not change until the event is
|
||||
// * actually propagated through the system.
|
||||
// */
|
||||
// public function addToOccupantLocs (elem :DSet_Entry) :void
|
||||
// {
|
||||
// requestEntryAdd(OCCUPANT_LOCS, elem);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Requests that the entry matching the supplied key be removed from
|
||||
// * the <code>occupantLocs</code> set. The set will not change until the
|
||||
// * event is actually propagated through the system.
|
||||
// */
|
||||
// public function removeFromOccupantLocs (key :Object) :void
|
||||
// {
|
||||
// requestEntryRemove(OCCUPANT_LOCS, key);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Requests that the specified entry be updated in the
|
||||
// * <code>occupantLocs</code> set. The set will not change until the event is
|
||||
// * actually propagated through the system.
|
||||
// */
|
||||
// public function updateOccupantLocs (elem :DSet_Entry) :void
|
||||
// {
|
||||
// requestEntryUpdate(OCCUPANT_LOCS, elem);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Requests that the <code>occupantLocs</code> field be set to the
|
||||
// * specified value. Generally one only adds, updates and removes
|
||||
// * entries of a distributed set, but certain situations call for a
|
||||
// * complete replacement of the set value. The local value will be
|
||||
// * updated immediately and an event will be propagated through the
|
||||
// * system to notify all listeners that the attribute did
|
||||
// * change. Proxied copies of this object (on clients) will apply the
|
||||
// * value change when they received the attribute changed notification.
|
||||
// */
|
||||
// public function setOccupantLocs (value :DSet) :void
|
||||
// {
|
||||
// requestAttributeChange(OCCUPANT_LOCS, value, this.occupantLocs);
|
||||
// this.occupantLocs = value;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Requests that the specified entry be added to the
|
||||
// * <code>clusters</code> set. The set will not change until the event is
|
||||
// * actually propagated through the system.
|
||||
// */
|
||||
// public function addToClusters (elem :DSet_Entry) :void
|
||||
// {
|
||||
// requestEntryAdd(CLUSTERS, elem);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Requests that the entry matching the supplied key be removed from
|
||||
// * the <code>clusters</code> set. The set will not change until the
|
||||
// * event is actually propagated through the system.
|
||||
// */
|
||||
// public function removeFromClusters (key :Object) :void
|
||||
// {
|
||||
// requestEntryRemove(CLUSTERS, key);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Requests that the specified entry be updated in the
|
||||
// * <code>clusters</code> set. The set will not change until the event is
|
||||
// * actually propagated through the system.
|
||||
// */
|
||||
// public function updateClusters (elem :DSet_Entry) :void
|
||||
// {
|
||||
// requestEntryUpdate(CLUSTERS, elem);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Requests that the <code>clusters</code> field be set to the
|
||||
// * specified value. Generally one only adds, updates and removes
|
||||
// * entries of a distributed set, but certain situations call for a
|
||||
// * complete replacement of the set value. The local value will be
|
||||
// * updated immediately and an event will be propagated through the
|
||||
// * system to notify all listeners that the attribute did
|
||||
// * change. Proxied copies of this object (on clients) will apply the
|
||||
// * value change when they received the attribute changed notification.
|
||||
// */
|
||||
// public function setClusters (value :DSet) :void
|
||||
// {
|
||||
// requestAttributeChange(CLUSTERS, value, this.clusters);
|
||||
// this.clusters = value;
|
||||
// }
|
||||
// // AUTO-GENERATED: METHODS END
|
||||
//
|
||||
// // documentation inherited
|
||||
// override public function writeObject (out :ObjectOutputStream) :void
|
||||
// {
|
||||
// super.writeObject(out);
|
||||
//
|
||||
// out.writeObject(occupantLocs);
|
||||
// out.writeObject(clusters);
|
||||
// }
|
||||
|
||||
// documentation inherited
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
|
||||
occupantLocs = DSet(ins.readObject());
|
||||
clusters = DSet(ins.readObject());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// $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.whirled.util {
|
||||
|
||||
/**
|
||||
* Thrown when an attempt to load a non-existent scene is made on the
|
||||
* repository.
|
||||
*/
|
||||
public class NoSuchSceneError extends Error
|
||||
{
|
||||
public function NoSuchSceneError (sceneid :int)
|
||||
{
|
||||
super("No such scene [sceneid=" + sceneid + "]");
|
||||
_sceneid = sceneid;
|
||||
}
|
||||
|
||||
public function getSceneId () :int
|
||||
{
|
||||
return _sceneid;
|
||||
}
|
||||
|
||||
protected var _sceneid :int;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
//
|
||||
// $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.whirled.util {
|
||||
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
|
||||
import com.threerings.whirled.data.Scene;
|
||||
import com.threerings.whirled.data.SceneModel;
|
||||
|
||||
/**
|
||||
* This is used by the Whirled services to obtain a {@link Scene}
|
||||
* implementation given a scene model and associated data.
|
||||
*/
|
||||
public interface SceneFactory
|
||||
{
|
||||
/**
|
||||
* Creates a {@link Scene} implementation given the supplied scene
|
||||
* model and place config.
|
||||
*/
|
||||
function createScene (model :SceneModel, config :PlaceConfig) :Scene;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
//
|
||||
// $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.whirled.util {
|
||||
|
||||
import com.threerings.util.Log;
|
||||
|
||||
import com.threerings.whirled.data.SceneUpdate;
|
||||
|
||||
/**
|
||||
* A list specialized for storing {@link SceneUpdate} objects.
|
||||
*/
|
||||
public class UpdateList
|
||||
{
|
||||
public function UpdateList ()
|
||||
{
|
||||
_updates = new Array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an update to this list. The update must follow appropriately
|
||||
* the chain of updates established by the updates already in the list
|
||||
* (meaning it must operate on one version higher than the most recent
|
||||
* update already in the list).
|
||||
*/
|
||||
public function addUpdate (update :SceneUpdate) :void
|
||||
{
|
||||
if (_minVersion == -1) {
|
||||
// this is our first update, so we initialize our min version
|
||||
_minVersion = update.getSceneVersion();
|
||||
|
||||
} else {
|
||||
var gotVersion :int = update.getSceneVersion();
|
||||
var expVersion :int = _minVersion + _updates.length;
|
||||
if (gotVersion > expVersion) {
|
||||
Log.getLog(this).warning("Update continuity broken, " +
|
||||
"flushing list [got=" + update + ", expect=" + expVersion +
|
||||
", ucount=" + _updates.length + "].");
|
||||
// flush out our old updates and start anew from here
|
||||
_updates.length = 0;
|
||||
_minVersion = expVersion;
|
||||
|
||||
} else if (gotVersion < expVersion) {
|
||||
// we somehow got an update that's older than updates we
|
||||
// already have? wick wick wack
|
||||
throw new ArgumentError("Invalid update version " +
|
||||
"[want=" + expVersion + ", got=" + update + "]");
|
||||
}
|
||||
}
|
||||
_updates.push(update);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all of the updates that should be applied to a scene with
|
||||
* the specified version to bring it up to date. <code>null</code> is
|
||||
* returned if the scene's version is older than the oldest update in
|
||||
* our list, in which case it cannot be brought up to date by applying
|
||||
* updates from this list.
|
||||
*/
|
||||
public function getUpdates (fromVersion :int) :Array /*of SceneUpdate*/
|
||||
{
|
||||
if (_minVersion == -1 || fromVersion < _minVersion) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var offset :int = fromVersion - _minVersion;
|
||||
return _updates.slice(offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the supplied actual scene version is in accordance
|
||||
* with the updates contained in this list.
|
||||
*/
|
||||
public function validate (sceneVersion :int) :Boolean
|
||||
{
|
||||
return ((_minVersion == -1) || // we have no updates
|
||||
(_minVersion + _updates.length == sceneVersion));
|
||||
}
|
||||
|
||||
protected var _updates :Array;
|
||||
protected var _minVersion :int = -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// $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.whirled.util {
|
||||
|
||||
import com.threerings.crowd.util.CrowdContext;
|
||||
|
||||
import com.threerings.whirled.client.SceneDirector;
|
||||
|
||||
/**
|
||||
* The whirled context provides access to the various managers, etc. that
|
||||
* are needed by the whirled client code.
|
||||
*/
|
||||
public interface WhirledContext extends CrowdContext
|
||||
{
|
||||
/**
|
||||
* Returns a reference to the scene director.
|
||||
*/
|
||||
function getSceneDirector () :SceneDirector;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// $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.whirled.zone.client {
|
||||
|
||||
import com.threerings.presents.client.InvocationDecoder;
|
||||
|
||||
import com.threerings.whirled.zone.client.ZoneReceiver;
|
||||
|
||||
/**
|
||||
* Dispatches calls to a {@link ZoneReceiver} instance.
|
||||
*/
|
||||
public class ZoneDecoder extends InvocationDecoder
|
||||
{
|
||||
/** The generated hash code used to identify this receiver class. */
|
||||
public static const RECEIVER_CODE :String =
|
||||
"2d900cf54355111b4bb4befcdff42b82";
|
||||
|
||||
/** The method id used to dispatch {@link ZoneReceiver#forcedMove}
|
||||
* notifications. */
|
||||
public static const FORCED_MOVE :int = 1;
|
||||
|
||||
/**
|
||||
* Creates a decoder that may be registered to dispatch invocation
|
||||
* service notifications to the specified receiver.
|
||||
*/
|
||||
public function ZoneDecoder (receiver :ZoneReceiver)
|
||||
{
|
||||
this.receiver = receiver;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function getReceiverCode () :String
|
||||
{
|
||||
return RECEIVER_CODE;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function dispatchNotification (methodId :int, args :Array) :void
|
||||
{
|
||||
switch (methodId) {
|
||||
case FORCED_MOVE:
|
||||
(receiver as ZoneReceiver).forcedMove(args[0] as int, args[1] as int);
|
||||
return;
|
||||
|
||||
default:
|
||||
super.dispatchNotification(methodId, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,338 @@
|
||||
//
|
||||
// $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.whirled.zone.client {
|
||||
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.util.Log;
|
||||
import com.threerings.util.ResultListener;
|
||||
|
||||
import com.threerings.presents.client.BasicDirector;
|
||||
import com.threerings.presents.client.Client;
|
||||
import com.threerings.presents.client.ClientEvent;
|
||||
import com.threerings.presents.client.ConfirmAdapter;
|
||||
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
|
||||
import com.threerings.whirled.client.PendingData;
|
||||
import com.threerings.whirled.client.SceneDirector;
|
||||
import com.threerings.whirled.client.SceneDirector_MoveHandler;
|
||||
import com.threerings.whirled.data.SceneModel;
|
||||
import com.threerings.whirled.data.SceneUpdate;
|
||||
import com.threerings.whirled.util.WhirledContext;
|
||||
import com.threerings.whirled.zone.client.ZoneService_ZoneMoveListener;
|
||||
import com.threerings.whirled.zone.data.ZoneSummary;
|
||||
import com.threerings.whirled.zone.util.ZoneUtil;
|
||||
|
||||
public class ZoneDirector extends BasicDirector
|
||||
implements ZoneReceiver, ZoneService_ZoneMoveListener, SceneDirector_MoveHandler
|
||||
{
|
||||
private static const log :Log = Log.getLog(ZoneDirector);
|
||||
|
||||
// We could be streamed one of these...
|
||||
SceneUpdate;
|
||||
|
||||
/**
|
||||
* Constructs a zone director with the supplied context, and delegate scene director (which the
|
||||
* zone director will coordinate with when moving from scene to scene). A zone director is
|
||||
* required on the client side for systems that wish to use the zone services.
|
||||
*/
|
||||
public function ZoneDirector (ctx :WhirledContext, scdir :SceneDirector)
|
||||
{
|
||||
super(ctx);
|
||||
_wCtx = ctx;
|
||||
_scdir = scdir;
|
||||
_scdir.setMoveHandler(this);
|
||||
|
||||
// register for zone notifications
|
||||
_wCtx.getClient().getInvocationDirector().registerReceiver(new ZoneDecoder(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the summary for the zone currently occupied by the client or null if the client does
|
||||
* not currently occupy a zone (not a normal situation).
|
||||
*/
|
||||
public function getZoneSummary () :ZoneSummary
|
||||
{
|
||||
return _summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a zone observer to the list. This observer will subsequently be notified of effected
|
||||
* and failed zone changes.
|
||||
*/
|
||||
public function addZoneObserver (observer :ZoneObserver) :void
|
||||
{
|
||||
_observers.add(observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a zone observer from the list.
|
||||
*/
|
||||
public function removeZoneObserver (observer :ZoneObserver) :void
|
||||
{
|
||||
_observers.remove(observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that this client move the specified scene in the specified zone. A request will be
|
||||
* made and when the response is received, the location observers will be notified of success
|
||||
* or failure.
|
||||
*/
|
||||
public function moveTo (zoneId :int, sceneId :int, rl :ResultListener = null) :Boolean
|
||||
{
|
||||
// make sure the zoneId and sceneId are valid
|
||||
if (zoneId < 0 || sceneId < 0) {
|
||||
log.warning("Refusing moveTo(): invalid sceneId or zoneId",
|
||||
"zoneId", zoneId, "sceneId", sceneId);
|
||||
return false;
|
||||
}
|
||||
|
||||
// if the requested zone is the same as our current zone, we just want a regular old moveTo
|
||||
// request
|
||||
if (_summary != null && zoneId == _summary.zoneId) {
|
||||
return _scdir.moveTo(sceneId);
|
||||
}
|
||||
|
||||
// otherwise, we make a zoned moveTo request; prepare to move to this scene (sets up
|
||||
// pending data)
|
||||
if (!_scdir.prepareMoveTo(sceneId, rl)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_pendingZoneId = zoneId;
|
||||
|
||||
sendMoveRequest();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function sendMoveRequest () :void
|
||||
{
|
||||
// let our zone observers know that we're attempting to switch zones
|
||||
notifyObservers(_pendingZoneId);
|
||||
|
||||
// check the version of our cached copy of the scene to which we're requesting to move; if
|
||||
// we were unable to load it, assume a cached version of zero
|
||||
var sceneVers :int = 0;
|
||||
var sceneId :int = _scdir.getPendingSceneId();
|
||||
var pendingModel :SceneModel = _scdir.getPendingModel();
|
||||
if (pendingModel != null) {
|
||||
sceneVers = pendingModel.version;
|
||||
}
|
||||
|
||||
// issue a moveTo request
|
||||
log.info("Issuing zoned moveTo(" + ZoneUtil.toString(_pendingZoneId) +
|
||||
", " + sceneId + ", " + sceneVers + ").");
|
||||
_zservice.moveTo(_pendingZoneId, sceneId, sceneVers, this);
|
||||
}
|
||||
|
||||
override protected function fetchServices (client :Client) :void
|
||||
{
|
||||
_zservice = (ZoneService)(client.requireService(ZoneService));
|
||||
}
|
||||
|
||||
override public function clientDidLogoff (event :ClientEvent) :void
|
||||
{
|
||||
super.clientDidLogoff(event);
|
||||
|
||||
// clear out our business
|
||||
_zservice = null;
|
||||
_summary = null;
|
||||
_previousZoneId = -1;
|
||||
}
|
||||
|
||||
// from interface ZoneService.ZoneMoveListener
|
||||
public function moveSucceeded (placeId :int, config :PlaceConfig, summary :ZoneSummary) :void
|
||||
{
|
||||
if (_summary != null) {
|
||||
// keep track of our previous zone info
|
||||
_previousZoneId = _summary.zoneId;
|
||||
}
|
||||
|
||||
// keep track of the summary
|
||||
_summary = summary;
|
||||
|
||||
// We're not heading there any more.
|
||||
_pendingZoneId = -1;
|
||||
|
||||
// pass the rest off to the standard scene transition code
|
||||
_scdir.moveSucceeded(placeId, config);
|
||||
|
||||
// and let the zone observers know what's up
|
||||
notifyObservers(summary);
|
||||
}
|
||||
|
||||
// from interface ZoneService.ZoneMoveListener
|
||||
public function moveSucceededWithUpdates (
|
||||
placeId :int, config :PlaceConfig, summary :ZoneSummary,
|
||||
updates :TypedArray /* of SceneUpdate */) :void
|
||||
{
|
||||
// keep track of the summary
|
||||
_summary = summary;
|
||||
|
||||
// We're not heading there any more.
|
||||
_pendingZoneId = -1;
|
||||
|
||||
// pass the rest off to the standard scene transition code
|
||||
_scdir.moveSucceededWithUpdates(placeId, config, updates);
|
||||
|
||||
// and let the zone observers know what's up
|
||||
notifyObservers(summary);
|
||||
}
|
||||
|
||||
// from interface ZoneService.ZoneMoveListener
|
||||
public function moveSucceededWithScene (
|
||||
placeId :int, config :PlaceConfig, summary :ZoneSummary, model :SceneModel) :void
|
||||
{
|
||||
// keep track of the summary
|
||||
_summary = summary;
|
||||
|
||||
// We're not heading there any more.
|
||||
_pendingZoneId = -1;
|
||||
|
||||
// pass the rest off to the standard scene transition code
|
||||
_scdir.moveSucceededWithScene(placeId, config, model);
|
||||
|
||||
// and let the zone observers know what's up
|
||||
notifyObservers(summary);
|
||||
}
|
||||
|
||||
// from interface ZoneService_ZoneMoveListener
|
||||
public function moveRequiresServerSwitch (hostname :String, ports :TypedArray) :void
|
||||
{
|
||||
log.info("Zone switch requires server switch", "host", hostname, "ports", ports);
|
||||
// ship on over to the other server
|
||||
|
||||
// keep track of our current pending data because it will be cleared when we log off of
|
||||
// this server and onto the next one
|
||||
var restorePending :Function = _scdir.getPendingDataRestoreFunc();
|
||||
|
||||
_wCtx.getClient().moveToServer(hostname, ports, new ConfirmAdapter(
|
||||
function () :void { // succeeded
|
||||
restorePending();
|
||||
sendMoveRequest();
|
||||
}, requestFailed));
|
||||
}
|
||||
|
||||
// from interface ZoneService.ZoneMoveListener
|
||||
public function requestFailed (reason :String) :void
|
||||
{
|
||||
// let the scene director cope
|
||||
_scdir.requestFailed(reason);
|
||||
|
||||
// and let the observers know what's up
|
||||
notifyObservers(reason);
|
||||
}
|
||||
|
||||
|
||||
// documentation inherited from interface
|
||||
public function forcedMove (zoneId :int, sceneId :int) :void
|
||||
{
|
||||
// if we're in the middle of a move, we can't abort it or we will screw everything up, so
|
||||
// just finish up what we're doing and assume that the repeated move request was the
|
||||
// spurious one as it would be in the case of lag causing rapid-fire repeat requests
|
||||
if (_scdir.movePending()) {
|
||||
if (_scdir.getPendingSceneId() == sceneId) {
|
||||
log.info("Dropping forced move because we have a move pending",
|
||||
"pend", _scdir.getPendingModel(), "rzId", zoneId, "rsId", sceneId);
|
||||
} else {
|
||||
log.info("Delaying forced move because we have a move pending",
|
||||
"pend", _scdir.getPendingModel(), "rzId", zoneId, "rsId", sceneId);
|
||||
_scdir.addPendingForcedMove(function() :void {
|
||||
forcedMove(zoneId, sceneId);
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("Moving at request of server",
|
||||
"zoneId", zoneId, "sceneId", sceneId);
|
||||
// clear out our old scene and place data
|
||||
_scdir.didLeaveScene();
|
||||
// move to the new zone and scene
|
||||
moveTo(zoneId, sceneId, null);
|
||||
}
|
||||
|
||||
// from SceneDirector.MoveHandler
|
||||
public function recoverMoveTo (previousSceneId :int) :void
|
||||
{
|
||||
if (_summary != null) {
|
||||
return; // if we're currently somewhere, just stay there
|
||||
}
|
||||
|
||||
// Not gonna get there, so clear it.
|
||||
_pendingZoneId = -1;
|
||||
|
||||
// otherwise if we were previously in a zone/scene, try going back there
|
||||
if (_previousZoneId != -1) {
|
||||
moveTo(_previousZoneId, previousSceneId);
|
||||
} else {
|
||||
_scdir.moveTo(previousSceneId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies observers of success or failure, depending on the type of object provided as data.
|
||||
*/
|
||||
protected function notifyObservers (data :Object) :void
|
||||
{
|
||||
// let our observers know that all is well on the western front
|
||||
for each (var obs :ZoneObserver in _observers) {
|
||||
try {
|
||||
if (data is Number) {
|
||||
obs.zoneWillChange(data as Number);
|
||||
} else if (data is ZoneSummary) {
|
||||
obs.zoneDidChange(data as ZoneSummary);
|
||||
} else {
|
||||
obs.zoneChangeFailed(data as String);
|
||||
}
|
||||
|
||||
} catch (e :Error) {
|
||||
log.warning("Zone observer choked during notification",
|
||||
"data", data, "obs", obs, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** A reference to the active client context. */
|
||||
protected var _wCtx :WhirledContext;
|
||||
|
||||
/** A reference to the scene director with which we coordinate. */
|
||||
protected var _scdir :SceneDirector;
|
||||
|
||||
/** Provides access to zone services. */
|
||||
protected var _zservice :ZoneService;
|
||||
|
||||
/** A reference to the zone summary for the currently occupied zone. */
|
||||
protected var _summary :ZoneSummary;
|
||||
|
||||
/** Our zone observer list. */
|
||||
protected var _observers :Array = [];
|
||||
|
||||
/** Our previous zone id. */
|
||||
protected var _previousZoneId :int = -1;
|
||||
|
||||
/** Where we're headed. */
|
||||
protected var _pendingZoneId :int = -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// $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.whirled.zone.client {
|
||||
|
||||
import com.threerings.whirled.zone.data.ZoneSummary;
|
||||
|
||||
/**
|
||||
* The zone observer interface makes it possible for entities to be
|
||||
* notified when the client moves to a new zone.
|
||||
*/
|
||||
public interface ZoneObserver
|
||||
{
|
||||
/**
|
||||
* Called when we begin the process of switching to a new zone. This
|
||||
* will be followed by a call to {@link #zoneDidChange} to indicate
|
||||
* that the change was successful or {@link #zoneChangeFailed} if the
|
||||
* change fails.
|
||||
*
|
||||
* @param zoneId the zone id of the zone to which we are changing.
|
||||
*/
|
||||
function zoneWillChange (zoneId :int) :void;
|
||||
|
||||
/**
|
||||
* Called when we have switched to a new zone.
|
||||
*
|
||||
* @param summary the summary information for the new zone or null if
|
||||
* we have switched to no zone.
|
||||
*/
|
||||
function zoneDidChange (summary :ZoneSummary) :void;
|
||||
|
||||
/**
|
||||
* This is called on all zone observers when a zone change request is
|
||||
* rejected by the server or fails for some other reason.
|
||||
*
|
||||
* @param reason the reason code that explains why the zone change
|
||||
* request was rejected or otherwise failed.
|
||||
*/
|
||||
function zoneChangeFailed (reason :String) :void;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// $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.whirled.zone.client {
|
||||
|
||||
import com.threerings.presents.client.InvocationReceiver;
|
||||
|
||||
/**
|
||||
* Defines, for the zone services, a set of notifications delivered asynchronously by the server
|
||||
* to the client.
|
||||
*/
|
||||
public interface ZoneReceiver extends InvocationReceiver
|
||||
{
|
||||
/**
|
||||
* Used to communicate a required move notification to the client. The server will have
|
||||
* removed the client from their existing scene and the client is then responsible for
|
||||
* generating a {@link ZoneService#moveTo} request to move to the new scene in the specified
|
||||
* zone.
|
||||
*/
|
||||
function forcedMove (zoneId :int, sceneId :int) :void;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// $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.whirled.zone.client {
|
||||
|
||||
import com.threerings.presents.client.InvocationService;
|
||||
|
||||
/**
|
||||
* An ActionScript version of the Java ZoneService interface.
|
||||
*/
|
||||
public interface ZoneService extends InvocationService
|
||||
{
|
||||
// from Java interface ZoneService
|
||||
function moveTo (arg1 :int, arg2 :int, arg3 :int, arg4 :ZoneService_ZoneMoveListener) :void;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
//
|
||||
// $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.whirled.zone.client {
|
||||
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.presents.client.InvocationService_InvocationListener;
|
||||
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
|
||||
import com.threerings.whirled.data.SceneModel;
|
||||
import com.threerings.whirled.zone.data.ZoneSummary;
|
||||
|
||||
/**
|
||||
* An ActionScript version of the Java ZoneService_ZoneMoveListener interface.
|
||||
*/
|
||||
public interface ZoneService_ZoneMoveListener
|
||||
extends InvocationService_InvocationListener
|
||||
{
|
||||
// from Java ZoneService_ZoneMoveListener
|
||||
function moveRequiresServerSwitch (arg1 :String, arg2 :TypedArray /* of int */) :void
|
||||
|
||||
// from Java ZoneService_ZoneMoveListener
|
||||
function moveSucceeded (arg1 :int, arg2 :PlaceConfig, arg3 :ZoneSummary) :void
|
||||
|
||||
// from Java ZoneService_ZoneMoveListener
|
||||
function moveSucceededWithScene (arg1 :int, arg2 :PlaceConfig, arg3 :ZoneSummary, arg4 :SceneModel) :void
|
||||
|
||||
// from Java ZoneService_ZoneMoveListener
|
||||
function moveSucceededWithUpdates (arg1 :int, arg2 :PlaceConfig, arg3 :ZoneSummary, arg4 :TypedArray /* of class com.threerings.whirled.data.SceneUpdate */) :void
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
//
|
||||
// $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.whirled.zone.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
import com.threerings.io.Streamable;
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
/**
|
||||
* The scene summary class is used to provide info about the connected
|
||||
* group of scenes that make up a zone. The group of scenes that make up a
|
||||
* zone is a self-contained set of scenes, connected with one another (by
|
||||
* portals) but not to any scenes outside the group.
|
||||
*/
|
||||
public class SceneSummary
|
||||
implements Streamable
|
||||
{
|
||||
/** The id of this scene. */
|
||||
public var sceneId :int;
|
||||
|
||||
/** The name of this scene. */
|
||||
public var name :String;
|
||||
|
||||
/** The ids of the scenes to which this scene is connected via
|
||||
* portals. */
|
||||
public var neighbors :TypedArray;
|
||||
|
||||
/** The directions in which each of the neighbors lay. */
|
||||
public var neighborDirs :TypedArray;
|
||||
|
||||
public function SceneSummary ()
|
||||
{
|
||||
// nothing needed
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a string representation of this instance.
|
||||
*/
|
||||
public function toString () :String
|
||||
{
|
||||
return "[sceneId=" + sceneId + ", name=" + name + "]";
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
sceneId = ins.readInt();
|
||||
name = (ins.readField(String) as String);
|
||||
neighbors = TypedArray(ins.readField(TypedArray.getJavaType(int)));
|
||||
neighborDirs = TypedArray(ins.readField(TypedArray.getJavaType(int)));
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
out.writeInt(sceneId);
|
||||
out.writeField(name);
|
||||
out.writeField(neighbors);
|
||||
out.writeField(neighborDirs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// $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.whirled.zone.data {
|
||||
|
||||
import com.threerings.util.Integer;
|
||||
|
||||
import com.threerings.presents.data.InvocationMarshaller;
|
||||
|
||||
import com.threerings.whirled.zone.client.ZoneService;
|
||||
import com.threerings.whirled.zone.client.ZoneService_ZoneMoveListener;
|
||||
|
||||
/**
|
||||
* Provides the implementation of the <code>ZoneService</code> interface
|
||||
* that marshalls the arguments and delivers the request to the provider
|
||||
* on the server. Also provides an implementation of the response listener
|
||||
* interfaces that marshall the response arguments and deliver them back
|
||||
* to the requesting client.
|
||||
*/
|
||||
public class ZoneMarshaller extends InvocationMarshaller
|
||||
implements ZoneService
|
||||
{
|
||||
/** The method id used to dispatch <code>moveTo</code> requests. */
|
||||
public static const MOVE_TO :int = 1;
|
||||
|
||||
// from interface ZoneService
|
||||
public function moveTo (arg1 :int, arg2 :int, arg3 :int, arg4 :ZoneService_ZoneMoveListener) :void
|
||||
{
|
||||
var listener4 :ZoneMarshaller_ZoneMoveMarshaller = new ZoneMarshaller_ZoneMoveMarshaller();
|
||||
listener4.listener = arg4;
|
||||
sendRequest(MOVE_TO, [
|
||||
Integer.valueOf(arg1), Integer.valueOf(arg2), Integer.valueOf(arg3), listener4
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// $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.whirled.zone.data {
|
||||
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.presents.data.InvocationMarshaller_ListenerMarshaller;
|
||||
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
|
||||
import com.threerings.whirled.data.SceneModel;
|
||||
import com.threerings.whirled.zone.client.ZoneService_ZoneMoveListener;
|
||||
|
||||
/**
|
||||
* Marshalls instances of the ZoneService_ZoneMoveMarshaller interface.
|
||||
*/
|
||||
public class ZoneMarshaller_ZoneMoveMarshaller
|
||||
extends InvocationMarshaller_ListenerMarshaller
|
||||
{
|
||||
/** The method id used to dispatch <code>moveRequiresServerSwitch</code> responses. */
|
||||
public static const MOVE_REQUIRES_SERVER_SWITCH :int = 1;
|
||||
|
||||
/** The method id used to dispatch <code>moveSucceeded</code> responses. */
|
||||
public static const MOVE_SUCCEEDED :int = 2;
|
||||
|
||||
/** The method id used to dispatch <code>moveSucceededWithScene</code> responses. */
|
||||
public static const MOVE_SUCCEEDED_WITH_SCENE :int = 3;
|
||||
|
||||
/** The method id used to dispatch <code>moveSucceededWithUpdates</code> responses. */
|
||||
public static const MOVE_SUCCEEDED_WITH_UPDATES :int = 4;
|
||||
|
||||
// from InvocationMarshaller_ListenerMarshaller
|
||||
override public function dispatchResponse (methodId :int, args :Array) :void
|
||||
{
|
||||
switch (methodId) {
|
||||
case MOVE_REQUIRES_SERVER_SWITCH:
|
||||
(listener as ZoneService_ZoneMoveListener).moveRequiresServerSwitch(
|
||||
(args[0] as String), (args[1] as TypedArray /* of int */));
|
||||
return;
|
||||
|
||||
case MOVE_SUCCEEDED:
|
||||
(listener as ZoneService_ZoneMoveListener).moveSucceeded(
|
||||
(args[0] as int), (args[1] as PlaceConfig), (args[2] as ZoneSummary));
|
||||
return;
|
||||
|
||||
case MOVE_SUCCEEDED_WITH_SCENE:
|
||||
(listener as ZoneService_ZoneMoveListener).moveSucceededWithScene(
|
||||
(args[0] as int), (args[1] as PlaceConfig), (args[2] as ZoneSummary), (args[3] as SceneModel));
|
||||
return;
|
||||
|
||||
case MOVE_SUCCEEDED_WITH_UPDATES:
|
||||
(listener as ZoneService_ZoneMoveListener).moveSucceededWithUpdates(
|
||||
(args[0] as int), (args[1] as PlaceConfig), (args[2] as ZoneSummary), (args[3] as TypedArray /* of class com.threerings.whirled.data.SceneUpdate */));
|
||||
return;
|
||||
|
||||
default:
|
||||
super.dispatchResponse(methodId, args);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
//
|
||||
// $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.whirled.zone.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
import com.threerings.io.SimpleStreamableObject;
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.util.Name;
|
||||
|
||||
/**
|
||||
* The zone summary contains information on a zone, including its name and
|
||||
* summary info on all of the scenes in this zone (which can be used to
|
||||
* generate a map of the zone on the client).
|
||||
*/
|
||||
public class ZoneSummary extends SimpleStreamableObject
|
||||
{
|
||||
/** The zone's fully qualified unique identifier. */
|
||||
public var zoneId :int;
|
||||
|
||||
/** The name of the zone. */
|
||||
public var name :Name;
|
||||
|
||||
/** The summary information for all of the scenes in the zone. */
|
||||
public var scenes :TypedArray;
|
||||
|
||||
public function ZoneSummary ()
|
||||
{
|
||||
// nothing needed
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a string representation of this instance.
|
||||
*/
|
||||
override public function toString () :String
|
||||
{
|
||||
return "[zoneId=" + zoneId + ", name=" + name + "]";
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
zoneId = ins.readInt();
|
||||
name = Name(ins.readObject());
|
||||
scenes = TypedArray(ins.readObject());
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
super.writeObject(out);
|
||||
out.writeInt(zoneId);
|
||||
out.writeObject(name);
|
||||
out.writeObject(scenes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
//
|
||||
// $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.whirled.zone.util {
|
||||
|
||||
/**
|
||||
* Server-specific, zone-related utility functions.
|
||||
*/
|
||||
public class ZoneUtil
|
||||
{
|
||||
/**
|
||||
* Composes the zone type and zone id into a qualified zone id. A
|
||||
* qualified zone id is what should be passed around so that the
|
||||
* server can determine the zone type from the zone id when necessary.
|
||||
*/
|
||||
public static function qualifyZoneId (zoneType :int, zoneId :int) :int
|
||||
{
|
||||
var qualifiedZoneId :int = zoneType;
|
||||
qualifiedZoneId <<= 24;
|
||||
qualifiedZoneId |= zoneId;
|
||||
return qualifiedZoneId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the zone type from a qualified zone id.
|
||||
*/
|
||||
public static function zoneType (qualifiedZoneId :int) :int
|
||||
{
|
||||
return (0xFF000000 & qualifiedZoneId) >> 24;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the zone id from a qualified zone id.
|
||||
*/
|
||||
public static function zoneId (qualifiedZoneId :int) :int
|
||||
{
|
||||
return (0x00FFFFFF & qualifiedZoneId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an easier to read representation of the supplied qualified
|
||||
* zone id: <code>type:id</code>.
|
||||
*/
|
||||
public static function toString (qualifiedZoneId :int) :String
|
||||
{
|
||||
return zoneType(qualifiedZoneId) + ":" + zoneId(qualifiedZoneId);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user