Moved the serverless game stuff out of msoy and back into the vilya library.

We'll be using this in game gardens, at least.
Note that the actionscript side currently doesn't compile because of
limitations in building a .swc file, but that'll be fixed soon.


git-svn-id: svn+ssh://src.earth.threerings.net/vilya/trunk@47 c613c5cb-e716-0410-b11b-feb51c14d237
This commit is contained in:
Ray Greenwell
2006-08-23 02:28:36 +00:00
parent a90d7e655b
commit 70b0d759c0
27 changed files with 2835 additions and 0 deletions
@@ -0,0 +1,304 @@
//
// $Id$
package com.threerings.ezgame.server;
import java.util.ArrayList;
import java.util.HashMap;
import com.samskivert.util.ArrayUtil;
import com.samskivert.util.CollectionUtil;
import com.samskivert.util.RandomUtil;
import com.threerings.util.Name;
import com.threerings.presents.data.ClientObject;
import com.threerings.presents.data.InvocationCodes;
import com.threerings.presents.dobj.AccessController;
import com.threerings.presents.client.InvocationService;
import com.threerings.presents.server.InvocationException;
import com.threerings.crowd.data.BodyObject;
import com.threerings.crowd.data.PlaceObject;
import com.threerings.crowd.server.CrowdServer;
import com.threerings.parlor.game.server.GameManager;
import com.threerings.parlor.turn.server.TurnGameManager;
import com.threerings.ezgame.data.EZGameObject;
import com.threerings.ezgame.data.EZGameMarshaller;
import com.threerings.ezgame.data.PropertySetEvent;
/**
* A manager for "ez" games.
*/
public class EZGameManager extends GameManager
implements EZGameProvider, TurnGameManager
{
public EZGameManager ()
{
addDelegate(_turnDelegate = new EZGameTurnDelegate(this));
}
// from TurnGameManager
public void turnWillStart ()
{
}
// from TurnGameManager
public void turnDidStart ()
{
}
// from TurnGameManager
public void turnDidEnd ()
{
}
// from EZGameProvider
public void endTurn (
ClientObject caller, int nextPlayerIndex,
InvocationService.InvocationListener listener)
throws InvocationException
{
validateStateModification(caller);
_turnDelegate.endTurn(nextPlayerIndex);
}
// from EZGameProvider
public void endGame (
ClientObject caller, int[] winners,
InvocationService.InvocationListener listener)
throws InvocationException
{
validateStateModification(caller);
_winnerIndexes = winners;
endGame();
}
// from EZGameProvider
public void sendMessage (
ClientObject caller, String msg, Object data, int playerIdx,
InvocationService.InvocationListener listener)
throws InvocationException
{
validateUser(caller);
if (playerIdx < 0 || playerIdx >= _gameObj.players.length) {
_gameObj.postMessage(EZGameObject.USER_MESSAGE,
new Object[] { msg, data });
} else {
sendPrivateMessage(playerIdx, msg, data);
}
}
// from EZGameProvider
public void setProperty (
ClientObject caller, String propName, Object data, int index,
InvocationService.InvocationListener listener)
throws InvocationException
{
validateUser(caller);
setProperty(propName, data, index);
}
// from EZGameProvider
public void addToCollection (
ClientObject caller, String collName, byte[][] data,
boolean clearExisting, InvocationService.InvocationListener listener)
throws InvocationException
{
validateUser(caller);
if (_collections == null) {
_collections = new HashMap<String, ArrayList<byte[]>>();
}
// figure out if we're adding to an existing collection
// or creating a new one
ArrayList<byte[]> list = null;
if (!clearExisting) {
list = _collections.get(collName);
}
if (list == null) {
list = new ArrayList<byte[]>();
_collections.put(collName, list);
}
CollectionUtil.addAll(list, data);
}
// from EZGameProvider
public void getFromCollection (
ClientObject caller, String collName, boolean consume, int count,
String msgOrPropName, int playerIndex,
InvocationService.ConfirmListener listener)
throws InvocationException
{
validateUser(caller);
int srcSize = 0;
if (_collections != null) {
ArrayList<byte[]> src = _collections.get(collName);
srcSize = (src == null) ? 0 : src.size();
if (srcSize >= count) {
byte[][] result = new byte[count][];
for (int ii=0; ii < count; ii++) {
int pick = RandomUtil.getInt(srcSize);
if (consume) {
result[ii] = src.remove(pick);
srcSize--;
} else {
result[ii] = src.get(pick);
}
}
if (playerIndex >= 0 && playerIndex < _gameObj.players.length) {
sendPrivateMessage(playerIndex, msgOrPropName, result);
} else {
setProperty(msgOrPropName, result, -1);
}
// SUCCESS!
listener.requestProcessed();
return;
}
}
// TODO: decide what we want to return here
throw new InvocationException(String.valueOf(srcSize));
}
// from EZGameProvider
public void mergeCollection (
ClientObject caller, String srcColl, String intoColl,
InvocationService.InvocationListener listener)
throws InvocationException
{
validateUser(caller);
// non-existent collections are treated as empty, so if the
// source doesn't exist, we silently accept it
if (_collections != null) {
ArrayList<byte[]> src = _collections.remove(srcColl);
if (src != null) {
ArrayList<byte[]> dest = _collections.get(intoColl);
if (dest == null) {
_collections.put(intoColl, src);
} else {
dest.addAll(src);
}
}
}
}
/**
* Helper method to send a private message to the specified player
* index (must already be verified).
*/
protected void sendPrivateMessage (
int playerIdx, String msg, Object data)
throws InvocationException
{
BodyObject target = getPlayer(playerIdx);
if (target == null) {
// TODO: this code has no corresponding translation
throw new InvocationException("m.player_not_around");
}
target.postMessage(
EZGameObject.USER_MESSAGE + ":" + _gameObj.getOid(),
new Object[] { msg, data });
}
/**
* Helper method to post a property set event.
*/
protected void setProperty (String propName, Object value, int index)
{
_gameObj.postEvent(
new PropertySetEvent(_gameObj.getOid(), propName, value, index));
}
/**
* Validate that the specified user has access to do things in the game.
*/
protected void validateUser (ClientObject caller)
throws InvocationException
{
if (getPresentPlayerIndex(caller.getOid()) == -1) {
throw new InvocationException(InvocationCodes.ACCESS_DENIED);
}
}
/**
* Validate that the specified listener has access to make a
* change.
*/
protected void validateStateModification (ClientObject caller)
throws InvocationException
{
validateUser(caller);
Name holder = _gameObj.turnHolder;
if (holder != null &&
!holder.equals(((BodyObject) caller).getVisibleName())) {
throw new InvocationException(InvocationCodes.ACCESS_DENIED);
}
}
@Override
protected Class<? extends PlaceObject> getPlaceObjectClass ()
{
return EZGameObject.class;
}
@Override
protected void didStartup ()
{
super.didStartup();
_gameObj = (EZGameObject) _plobj;
_gameObj.setEZGameService(
(EZGameMarshaller) CrowdServer.invmgr.registerDispatcher(
new EZGameDispatcher(this), false));
}
@Override
protected void didShutdown ()
{
CrowdServer.invmgr.clearDispatcher(_gameObj.ezGameService);
super.didShutdown();
}
@Override
protected void assignWinners (boolean[] winners)
{
if (_winnerIndexes != null) {
for (int index : _winnerIndexes) {
if (index >= 0 && index < winners.length) {
winners[index] = true;
}
}
_winnerIndexes = null;
}
}
/** A nice casted reference to the game object. */
protected EZGameObject _gameObj;
/** Our turn delegate. */
protected EZGameTurnDelegate _turnDelegate;
/** The array of winners, after the user has filled it in. */
protected int[] _winnerIndexes;
/** The map of collections, lazy-initialized. */
protected HashMap<String, ArrayList<byte[]>> _collections;
}