EZgame merges with whirled games.

Starting the checkins, this will break the build.


git-svn-id: svn+ssh://src.earth.threerings.net/vilya/trunk@557 c613c5cb-e716-0410-b11b-feb51c14d237
This commit is contained in:
Ray Greenwell
2008-02-17 00:46:49 +00:00
parent 6fc1f6e068
commit 3a9708b3de
48 changed files with 0 additions and 5864 deletions
@@ -1,69 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame;
import java.util.ArrayList;
/**
* A simple card deck that encodes cards as a string like "Ac" for the
* ace of clubs, or "Td" for the 10 of diamonds.
*/
public class CardDeck
{
public CardDeck (EZGame gameObj)
{
this(gameObj, "deck");
}
public CardDeck (EZGame gameObj, String deckName)
{
_gameObj = gameObj;
_deckName = deckName;
ArrayList<String> deck = new ArrayList<String>();
for (String rank : new String[] { "2", "3", "4", "5", "6", "7", "8",
"9", "T", "J", "Q", "K", "A" }) {
for (String suit : new String[] { "c", "d", "h", "s" }) {
deck.add(rank + suit);
}
}
_gameObj.setCollection(_deckName, deck);
}
public void dealToPlayer (int playerIdx, int count, String msgName)
{
// TODO: support the callback
_gameObj.dealFromCollection(_deckName, count, msgName, null, playerIdx);
}
public void dealToData (int count, String propName)
{
_gameObj.dealFromCollection(_deckName, count, propName, null);
}
/** The game object. */
protected EZGame _gameObj;
/** The name of our deck. */
protected String _deckName;
}
@@ -1,28 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame;
public interface DealListener
{
// TODO: figure out what I want to return here
public void dealt (int someValue);
}
@@ -1,41 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame;
public class EZEvent
{
public EZEvent (EZGame ezgame)
{
_ezgame = ezgame;
}
/**
* Access the game object to which this event applies.
*/
public EZGame getGameObject ()
{
return _ezgame;
}
/** The game object for this event. */
protected EZGame _ezgame;
}
-219
View File
@@ -1,219 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame;
import java.util.Collection;
/**
* The game object that you'll be using to manage your game.
*/
public interface EZGame
{
/**
* Get a property from data.
*/
public Object get (String propName);
/**
* Get a property from data.
*/
public Object get (String propName, int index);
/**
* Set a property that will be distributed.
*/
public void set (String propName, Object value);
/**
* Set a property that will be distributed.
*/
public void set (String propName, Object value, int index);
/**
* Set a property that will be distributed, if the previous value
* matches the test value.
*/
public void testAndSet (String propName, Object value, Object testValue);
/**
* Set a property that will be distributed, if the previous value
* matches the test value.
*/
public void testAndSet (String propName, Object value, Object testValue, int index);
/**
* Register an object to receive whatever events it should receive,
* based on which event listeners it implements. Note that it is not
* necessary to register any objects which appear on the display list,
* as they'll be registered automatically.
*/
public void registerListener (Object obj);
/**
* Unregister the specified object from receiving events.
*/
public void unregisterListener (Object obj);
/**
* Set the specified collection to contain the specified values,
* clearing any previous values.
*
* @param values may be a Collection or array. Note that arrays
* of primitive types will be transmogrified into an Object[] containing
* wrapper objects.
*/
public void setCollection (String collName, Object values);
/**
* Add to an existing collection. If it doesn't exist, it will
* be created. The new values will be inserted randomly into the
* collection.
*
* @param values may be a Collection or array. Note that arrays
* of primitive types will be transmogrified into an Object[] containing
* wrapper objects.
*/
public void addToCollection (String collName, Object values);
/**
* Pick (do not remove) the specified number of elements from a collection,
* and distribute them to a specific player or set them as a property
* in the game data.
*/
// TODO: a way to specify exclusive picks vs. duplicate-OK picks?
public void pickFromCollection (
String collName, int count, String propName);
public void pickFromCollection (
String collName, int count, String msgName, int playerIndex);
/**
* Deal (remove) the specified number of elements from a collection,
* and distribute them to a specific player or set them as a property
* in the game data.
*/
// TODO: figure out the method signature of the callback
public void dealFromCollection (
String collName, int count, String propName,
DealListener listener);
public void dealFromCollection (
String collName, int count, String msgName,
DealListener listener, int playerIndex);
/**
* Merge the specified collection into the other collection.
* The source collection will be destroyed. The elements from
* The source collection will be shuffled and appended to the end
* of the destination collection.
*/
public void mergeCollection (String srcColl, String intoColl);
/**
* Send a "message" to other clients subscribed to the game.
* These is similar to setting a property, except that the
* value will not be saved- it will merely end up coming out
* as a MessageReceivedEvent.
*
* @param playerIndex if -1, sends to all players, otherwise
* the message will be private to just one player
*/
public void sendMessage (
String messageName, Object value);
public void sendMessage (
String messageName, Object value, int playerIndex);
/**
* Start the ticker with the specified name. It will deliver
* messages to the game object at the specified delay,
* the value of each message being a single integer, starting with 0
* and increasing by one with each messsage.
*/
public void startTicker (String tickerName, int msOfDelay);
/**
* Stop the specified ticker.
*/
public void stopTicker (String tickerName);
/**
* Send a message that will be heard by everyone in the game room,
* even observers.
*/
public void sendChat (String msg);
/**
* Display the specified message immediately locally: not sent
* to any other players or observers in the game room.
*/
public void localChat (String msg);
/**
* Get the number of players currently in the game.
*/
public int getPlayerCount ();
/**
* Get the player names, as an array.
*/
public String[] getPlayerNames ();
/**
* Get the index into the player names array of the current player,
* or -1 if the user is not a player.
*/
public int getMyIndex ();
/**
* Get the turn holder's index, or -1 if it's nobody's turn.
*/
public int getTurnHolderIndex ();
/**
* Get the indexes of the winners
*/
public int[] getWinnerIndexes ();
/**
* A convenience method to just check if it's our turn.
*/
public boolean isMyTurn ();
/**
* Is the game currently in play?
*/
public boolean isInPlay ();
/**
* End the current turn. If no next player index is specified,
* then the next player after the current one is used.
*/
public void endTurn ();
public void endTurn (int nextPlayerIndex);
/**
* End the game. The specified player indexes are winners!
*/
public void endGame (int... winners);
}
-36
View File
@@ -1,36 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame;
/**
* This interface should be implemented by some class that lives on the
* display list. When a DisplayObject that implements this interface
* is added, it will be notified of the GameObject.
*/
public interface Game
{
/**
* Called by the mysterious powers of the cosmos to initialize
* your game with the GameObject.
*/
public void setGameObject (EZGame gameObj);
}
-58
View File
@@ -1,58 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Contains a reference to the log object used by this package.
*/
public class Log
{
/** We dispatch our log messages through this logger. */
public static Logger log = Logger.getLogger("com.threerings.ezgame");
/** Convenience function. */
public static void debug (String message)
{
log.fine(message);
}
/** Convenience function. */
public static void info (String message)
{
log.info(message);
}
/** Convenience function. */
public static void warning (String message)
{
log.warning(message);
}
/** Convenience function. */
public static void logStackTrace (Throwable t)
{
log.log(Level.WARNING, t.getMessage(), t);
}
}
@@ -1,58 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame;
public class MessageReceivedEvent extends EZEvent
{
public MessageReceivedEvent (
EZGame ezgame, String messageName, Object value)
{
super(ezgame);
_name = messageName;
_value = value;
}
/**
* Access the message name.
*/
public String getName ()
{
return _name;
}
/**
* Access the message value.
*/
public Object getValue ()
{
return _value;
}
public String toString ()
{
return "[MessageReceivedEvent name=" + _name +
", value=" + _value + "]";
}
protected String _name;
protected Object _value;
}
@@ -1,34 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame;
/**
* Implement this interface to automagically be registered to received
* MessageReceivedEvents.
*/
public interface MessageReceivedListener
{
/**
* Handle a MessageReceivedEvent.
*/
public void messageReceived (MessageReceivedEvent event);
}
@@ -1,88 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame;
/**
* Property change events are dispatched after the property change was
* validated on the server.
*/
public class PropertyChangedEvent extends EZEvent
{
/**
* Constructor.
*/
public PropertyChangedEvent (
EZGame ezgame, String propName, Object newValue, Object oldValue,
int index)
{
super(ezgame);
_name = propName;
_newValue = newValue;
_oldValue = oldValue;
_index = index;
}
/**
* Get the name of the property that changed.
*/
public String getName ()
{
return _name;
}
/**
* Get the property's new value.
*/
public Object getNewValue ()
{
return _newValue;
}
/**
* Get the property's previous value (handy!).
*/
public Object getOldValue ()
{
return _oldValue;
}
/**
* If an array element was updated, get the index, or -1 if not applicable.
*/
public int getIndex ()
{
return _index;
}
@Override
public String toString ()
{
return "[PropertyChangedEvent name=" + _name + ", value=" + _newValue +
((_index < 0) ? "" : (", index=" + _index)) + "]";
}
/** Our implementation details. */
protected String _name;
protected Object _newValue;
protected Object _oldValue;
protected int _index;
}
@@ -1,34 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame;
/**
* Implement this interface to automagically be registered to received
* PropertyChangedEvents.
*/
public interface PropertyChangedListener
{
/**
* Handle a PropertyChangedEvent.
*/
public void propertyChanged (PropertyChangedEvent event);
}
@@ -1,2 +0,0 @@
The code in here is out of date and out of sync, but will not be updated
until needed, as we're focusing on flash development.
@@ -1,56 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame;
/**
* Dispatched when the state of the game has changed.
*/
public class StateChangedEvent extends EZEvent
{
/** Indicates that the game has transitioned to a started state. */
public static final String GAME_STARTED = "GameStarted";
/** Indicates that the game has transitioned to a ended state. */
public static final String GAME_ENDED = "GameEnded";
/** Indicates that the turn has changed. */
// TODO: move to own event?
public static final String TURN_CHANGED = "TurnChanged";
public StateChangedEvent (EZGame ezgame, String type)
{
super(ezgame);
_type = type;
}
public String getType ()
{
return _type;
}
public String toString ()
{
return "[StateChangedEvent type=" + _type + "]";
}
protected String _type;
}
@@ -1,34 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame;
/**
* Implement this interface to automagically be registered to receive
* StateChangedEvents.
*/
public interface StateChangedListener
{
/**
* Handle a StateChangedEvent.
*/
public void stateChanged (StateChangedEvent event);
}
@@ -1,309 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.client;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.logging.Level;
import org.apache.commons.io.IOUtils;
import com.samskivert.swing.HGroupLayout;
import com.samskivert.swing.SimpleSlider;
import com.threerings.util.MessageBundle;
import com.threerings.util.MessageManager;
import com.threerings.parlor.game.client.SwingGameConfigurator;
import com.threerings.parlor.game.data.GameAI;
import com.threerings.ezgame.data.AIParameter;
import com.threerings.ezgame.data.ChoiceParameter;
import com.threerings.ezgame.data.EZGameConfig;
import com.threerings.ezgame.data.FileParameter;
import com.threerings.ezgame.data.GameDefinition;
import com.threerings.ezgame.data.Parameter;
import com.threerings.ezgame.data.RangeParameter;
import com.threerings.ezgame.data.ToggleParameter;
import com.threerings.ezgame.util.EZGameContext;
import static com.threerings.ezgame.Log.log;
/**
* Handles the configuration of an EZ game. This works in conjunction with the {@link EZGameConfig}
* to provide a generic mechanism for defining and obtaining game configuration settings.
*/
public class EZGameConfigurator extends SwingGameConfigurator
{
// documentation inherited
protected void gotGameConfig ()
{
super.gotGameConfig();
EZGameContext ctx = (EZGameContext)_ctx;
EZGameConfig config = (EZGameConfig)_config;
GameDefinition gamedef = config.getGameDefinition();
// create our parameter editors
if (_editors == null) {
MessageBundle msgs = ctx.getMessageManager().getBundle(config.getGameIdent());
_editors = new ParamEditor[gamedef.params.length];
for (int ii = 0; ii < _editors.length; ii++) {
_editors[ii] = createEditor(ctx, msgs, gamedef.params[ii]);
addControl(new JLabel(msgs.get(gamedef.params[ii].getLabel())),
(JComponent) _editors[ii]);
}
}
// now read our parameters
for (int ii = 0; ii < gamedef.params.length; ii++) {
_editors[ii].readParameter(gamedef.params[ii], config);
}
}
// documentation inherited
protected void flushGameConfig ()
{
super.flushGameConfig();
EZGameConfig config = (EZGameConfig)_config;
GameDefinition gamedef = config.getGameDefinition();
for (int ii = 0; ii < gamedef.params.length; ii++) {
_editors[ii].writeParameter(gamedef.params[ii], config);
}
}
protected ParamEditor createEditor (EZGameContext ctx, MessageBundle msgs, Parameter param)
{
if (param instanceof AIParameter) {
return new AIEditor((AIParameter)param);
} else if (param instanceof RangeParameter) {
return new RangeEditor((RangeParameter)param);
} else if (param instanceof ToggleParameter) {
return new ToggleEditor((ToggleParameter)param);
} else if (param instanceof ChoiceParameter) {
return new ChoiceEditor(msgs, (ChoiceParameter)param);
} else if (param instanceof FileParameter) {
return new FileEditor(ctx, (FileParameter)param);
} else {
log.warning("Unknown parameter type! " + param + ".");
return null;
}
}
/** Provides a uniform interface to our UI components. */
protected static interface ParamEditor
{
public void readParameter (Parameter param, EZGameConfig config);
public void writeParameter (Parameter param, EZGameConfig config);
}
protected class RangeEditor extends SimpleSlider implements ParamEditor
{
public RangeEditor (RangeParameter param)
{
super(null, param.minimum, param.maximum, param.start);
}
public void readParameter (Parameter param, EZGameConfig config)
{
setValue((Integer)config.params.get(param.ident));
}
public void writeParameter (Parameter param, EZGameConfig config)
{
config.params.put(param.ident, getValue());
}
}
protected class ToggleEditor extends JPanel implements ParamEditor
{
public ToggleEditor (ToggleParameter param)
{
setLayout(new HGroupLayout(HGroupLayout.NONE, HGroupLayout.LEFT));
add(_box = new JCheckBox(null, null, param.start));
}
public void readParameter (Parameter param, EZGameConfig config)
{
_box.setSelected((Boolean)config.params.get(param.ident));
}
public void writeParameter (Parameter param, EZGameConfig config)
{
config.params.put(param.ident, _box.isSelected());
}
protected JCheckBox _box;
}
protected class ChoiceEditor extends JPanel implements ParamEditor
{
public ChoiceEditor (MessageBundle msgs, ChoiceParameter param)
{
setLayout(new HGroupLayout(HGroupLayout.NONE, HGroupLayout.LEFT));
Choice[] choices = new Choice[param.choices.length];
Choice selection = null;
for (int ii = 0; ii < choices.length; ii++) {
String choice = param.choices[ii];
choices[ii] = new Choice();
choices[ii].choice = choice;
choices[ii].label = msgs.get(param.getChoiceLabel(ii));
if (choice.equals(param.start)) {
selection = choices[ii];
}
}
add(_combo = new JComboBox(choices));
if (selection != null) {
_combo.setSelectedItem(selection);
}
}
public void readParameter (Parameter param, EZGameConfig config)
{
Choice selected = new Choice();
selected.choice = (String)config.params.get(param.ident);
_combo.setSelectedItem(selected);
}
public void writeParameter (Parameter param, EZGameConfig config)
{
config.params.put(param.ident, ((Choice)_combo.getSelectedItem()).choice);
}
protected JComboBox _combo;
}
protected static class Choice
{
public String choice;
public String label;
public String toString () {
return label;
}
public boolean equals (Object other) {
return (other instanceof Choice) && choice.equals(((Choice) other).choice);
}
}
protected class FileEditor extends JPanel
implements ParamEditor, ActionListener
{
public FileEditor (EZGameContext ctx, FileParameter param)
{
_ctx = ctx;
_param = param;
setLayout(new HGroupLayout(HGroupLayout.NONE, HGroupLayout.LEFT));
String label = ctx.getMessageManager().getBundle(
MessageManager.GLOBAL_BUNDLE).get("m.file_unset");
add(_show = new JButton(label));
_show.addActionListener(this);
}
public void readParameter (Parameter param, EZGameConfig config)
{
// nothing doing
}
public void writeParameter (Parameter param, EZGameConfig config)
{
if (_data != null) {
config.params.put(param.ident, _data);
}
}
public void actionPerformed (ActionEvent event)
{
if (event.getSource() == _show) {
if (_chooser == null) {
_chooser = new JFileChooser();
}
int rv = _chooser.showOpenDialog(this);
if (rv == JFileChooser.APPROVE_OPTION) {
File file = _chooser.getSelectedFile();
try {
if (_param.binary) {
_data = IOUtils.toByteArray(new FileInputStream(file));
} else {
_data = IOUtils.toString(new FileReader(file));
}
_show.setText(file.getName());
} catch (IOException ioe) {
String msg = MessageBundle.tcompose(
"m.file_read_failure", ioe.getMessage());
_ctx.getChatDirector().displayFeedback(null, msg);
log.warning("Failed to read '" + file + "': " + ioe.getMessage());
}
}
}
}
protected EZGameContext _ctx;
protected FileParameter _param;
protected JButton _show;
protected JFileChooser _chooser;
protected Object _data;
}
protected class AIEditor extends SimpleSlider implements ParamEditor
{
public AIEditor (AIParameter param)
{
super(null, 0, param.maximum, 0);
}
public void readParameter (Parameter param, EZGameConfig config)
{
setValue((config.ais == null) ? 0 : config.ais.length);
}
public void writeParameter (Parameter param, EZGameConfig config)
{
config.ais = new GameAI[getValue()];
for (int ii = 0; ii < config.ais.length; ii++) {
// TODO: allow specification of difficulty and personality
config.ais[ii] = new GameAI(0, 0);
}
}
}
protected ParamEditor[] _editors;
}
@@ -1,172 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.client;
import com.threerings.util.Name;
import com.threerings.presents.dobj.MessageListener;
import com.threerings.presents.dobj.MessageEvent;
import com.threerings.crowd.client.PlaceView;
import com.threerings.crowd.data.PlaceConfig;
import com.threerings.crowd.data.PlaceObject;
import com.threerings.crowd.util.CrowdContext;
import com.threerings.parlor.game.client.GameController;
import com.threerings.parlor.turn.client.TurnGameController;
import com.threerings.parlor.turn.client.TurnGameControllerDelegate;
import com.threerings.ezgame.data.EZGameObject;
import com.threerings.ezgame.data.PropertySetEvent;
import com.threerings.ezgame.data.PropertySetListener;
import com.threerings.ezgame.util.EZObjectMarshaller;
import com.threerings.ezgame.EZEvent;
import com.threerings.ezgame.MessageReceivedEvent;
import com.threerings.ezgame.PropertyChangedEvent;
import com.threerings.ezgame.StateChangedEvent;
/**
* A controller for flash games.
*/
public class EZGameController extends GameController
implements TurnGameController, PropertySetListener, MessageListener
{
/** The implementation of the GameObject interface for users. */
public GameObjectImpl gameObjImpl;
/**
*/
public EZGameController ()
{
addDelegate(_turnDelegate = new TurnGameControllerDelegate(this));
}
@Override
public void willEnterPlace (PlaceObject plobj)
{
_ezObj = (EZGameObject) plobj;
gameObjImpl = new GameObjectImpl(_ctx, _ezObj);
_ctx.getClient().getClientObject().addListener(_userListener);
super.willEnterPlace(plobj);
}
@Override
public void didLeavePlace (PlaceObject plobj)
{
super.didLeavePlace(plobj);
_ctx.getClient().getClientObject().removeListener(_userListener);
_ezObj = null;
}
// from TurnGameController
public void turnDidChange (Name turnHolder)
{
dispatchUserEvent(
new StateChangedEvent(gameObjImpl, StateChangedEvent.TURN_CHANGED));
}
// from PropertySetListener
public void propertyWasSet (PropertySetEvent event)
{
// notify the user game
dispatchUserEvent(new PropertyChangedEvent(
gameObjImpl, event.getName(), event.getValue(),
event.getOldValue(), event.getIndex()));
}
// from MessageListener
public void messageReceived (MessageEvent event)
{
String name = event.getName();
if (EZGameObject.USER_MESSAGE.equals(name)) {
dispatchUserMessage(event.getArgs());
} else if (EZGameObject.GAME_CHAT.equals(name)) {
// this is chat send by the game, let's route it like
// localChat, which is also sent by the game
gameObjImpl.localChat((String) event.getArgs()[0]);
} else if (EZGameObject.TICKER.equals(name)) {
Object[] args = event.getArgs();
dispatchUserEvent(new MessageReceivedEvent(
gameObjImpl, (String) args[0], (Integer) args[1]));
}
}
/**
* Dispatch the user message.
*/
protected void dispatchUserMessage (Object[] args)
{
dispatchUserEvent(new MessageReceivedEvent(
gameObjImpl, (String) args[0],
EZObjectMarshaller.decode(args[1])));
}
@Override
protected PlaceView createPlaceView (CrowdContext ctx)
{
return new EZGamePanel(ctx, this);
}
@Override
protected void gameDidStart ()
{
super.gameDidStart();
dispatchUserEvent(
new StateChangedEvent(gameObjImpl, StateChangedEvent.GAME_STARTED));
}
@Override
protected void gameDidEnd ()
{
super.gameDidEnd();
dispatchUserEvent(
new StateChangedEvent(gameObjImpl, StateChangedEvent.GAME_ENDED));
}
protected void dispatchUserEvent (EZEvent event)
{
gameObjImpl.dispatch(event);
}
protected EZGameObject _ezObj;
protected TurnGameControllerDelegate _turnDelegate;
/** Listens for message events on the user object. */
protected MessageListener _userListener = new MessageListener() {
public void messageReceived (MessageEvent event) {
// see if it's a message about user games
String msgName = EZGameObject.USER_MESSAGE + ":" + _ezObj.getOid();
if (msgName.equals(event.getName())) {
dispatchUserMessage(event.getArgs());
}
}
};
}
@@ -1,156 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.client;
import java.awt.Component;
import java.awt.Container;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import java.util.WeakHashMap;
import javax.swing.JPanel;
import com.samskivert.swing.VGroupLayout;
import com.samskivert.swing.util.SwingUtil;
import com.threerings.crowd.client.PlaceView;
import com.threerings.crowd.data.PlaceObject;
import com.threerings.crowd.util.CrowdContext;
import com.threerings.ezgame.data.EZGameObject;
import com.threerings.ezgame.Game;
public class EZGamePanel extends JPanel
implements ContainerListener, PlaceView
{
public EZGamePanel (CrowdContext ctx, EZGameController ctrl)
{
super(new VGroupLayout(VGroupLayout.STRETCH));
_ctx = ctx;
_ctrl = ctrl;
// add a listener so that we hear about all new children
addContainerListener(this);
// TODO: sort out if and how EZ games will create their views
// EZGameConfig cfg = (EZGameConfig) ctrl.getPlaceConfig();
// try {
// _gameView = (Component) Class.forName(cfg.gameMedia).newInstance();
// add(_gameView);
// } catch (RuntimeException re) {
// throw re;
// } catch (Exception e) {
// throw new RuntimeException(e);
// }
// TODO: Add a standard chat display?
//addChild(new ChatDisplayBox(ctx));
}
// from PlaceView
public void willEnterPlace (final PlaceObject plobj)
{
// don't start notifying anything of the game until we've
// notified the game manager that we're in the game
// (done in GameController, and it uses callLater, so we do it twice!)
_ctx.getClient().getRunQueue().postRunnable(new Runnable() {
public void run () {
_ctx.getClient().getRunQueue().postRunnable(new Runnable() {
public void run () {
_ezObj = (EZGameObject) plobj;
notifyOfGame(_gameView);
}
});
}
});
}
// from PlaceView
public void didLeavePlace (PlaceObject plobj)
{
removeListeners(_gameView);
_ezObj = null;
}
// from ContainerListener
public void componentAdded (ContainerEvent event)
{
if (_ezObj != null) {
notifyOfGame(event.getChild());
}
}
// from ContainerListener
public void componentRemoved (ContainerEvent event)
{
if (_ezObj != null) {
removeListeners(event.getChild());
}
}
/**
* Find any children of the specified object that implement
* com.metasoy.game.Game and provide them with the GameObject.
*/
protected void notifyOfGame (Component root)
{
SwingUtil.applyToHierarchy(root, new SwingUtil.ComponentOp() {
public void apply (Component comp) {
if (comp instanceof Game) {
// only notify the Game if we haven't seen it before
// TODO: what we really want is a weak identity map,
// so that two keys that are equals() do not collide.
if (null == _seenGames.put(comp, Boolean.TRUE)) {
((Game) comp).setGameObject(_ctrl.gameObjImpl);
}
}
// always check to see if it's a listener
_ctrl.gameObjImpl.registerListener(comp);
}
});
}
protected void removeListeners (Component root)
{
SwingUtil.applyToHierarchy(root, new SwingUtil.ComponentOp() {
public void apply (Component comp) {
_ctrl.gameObjImpl.unregisterListener(comp);
}
});
}
protected CrowdContext _ctx;
protected EZGameController _ctrl;
protected Component _gameView;
/** A weak-key hash of the Game interfaces we've already seen. */
protected WeakHashMap<Component, Boolean> _seenGames =
new WeakHashMap<Component, Boolean>();
protected EZGameObject _ezObj;
}
@@ -1,142 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.client;
import com.threerings.presents.client.Client;
import com.threerings.presents.client.InvocationService;
/**
* Provides services for ez games.
*/
public interface EZGameService extends InvocationService
{
/**
* Request to set the specified property.
*
* @param value either a byte[] if setting a non-array property or a property at an array
* index, or a byte[][] if setting an array property where index is -1.
*/
public void setProperty (Client client, String propName, Object value, int index,
boolean testAndSet, Object testValue, InvocationListener listener);
/**
* Request to end the turn, possibly futzing the next turn holder unless -1 is specified for
* the nextPlayerIndex.
*/
public void endTurn (Client client, int nextPlayerId, InvocationListener listener);
/**
* Requests to end the current round. If nextRoundDelay is greater than zero, the next round
* will be started in the specified number of seconds.
*/
public void endRound (Client client, int nextRoundDelay, InvocationListener listener);
/**
* Request to end the game, with the specified player oids assigned as winners.
*/
public void endGame (Client client, int[] winnerOids, InvocationListener listener);
/**
* Requests to start the game again in the specified number of seconds. This should only be
* used for party games. Seated table games should have each player report that they are ready
* again and the game will automatically start.
*/
public void restartGameIn (Client client, int seconds, InvocationListener listener);
/**
* Request to send a private message to one other player in the game.
*
* @param value either a byte[] if setting a non-array property or a property at an array
* index, or a byte[][] if setting an array property where index is -1.
*/
public void sendMessage (Client client, String msgName, Object value, int playerId,
InvocationListener listener);
/**
* Ask the dictionary service for a set of random letters appropriate for the given
* language/culture settings. These will be returned via a message back to the caller.
*
* @param client stores information about the caller
* @param locale is an RFC 3066 string specifying language settings, for example, "en" or
* "en-us".
* @param dictionary is a String specifier of the dictionary to use, or null for the default.
* @param count is the number of letters to be returned.
* @param listener is the callback function
*/
public void getDictionaryLetterSet (
Client client, String locale, String dictionary, int count, ResultListener listener);
/**
* Ask the dictionary service whether the specified word is valid with the given
* language/culture settings. The result will be returned via a message back to the caller.
*
* @param client stores information about the caller
* @param locale is an RFC 3066 string specifying language settings, for example, "en" or
* "en-us".
* @param dictionary is a String specifier of the dictionary to use, or null for the default.
* @param word is the word to be checked against the dictionary.
* @param listener is the callback function
*/
public void checkDictionaryWord (
Client client, String locale, String dictionary, String word, ResultListener listener);
/**
* Add to the specified named collection.
*
* @param clearExisting if true, wipe the old contents.
*/
public void addToCollection (Client client, String collName, byte[][] data,
boolean clearExisting, InvocationListener listener);
/**
* Merge the specified collection into the other.
*/
public void mergeCollection (
Client client, String srcColl, String intoColl, InvocationListener listener);
/**
* Pick or deal some number of elements from the specified collection, and either set a
* property in the flash object, or delivery the picks to the specified player index via a game
* message.
*/
public void getFromCollection (Client client, String collName, boolean consume, int count,
String msgOrPropName, int playerId, ConfirmListener listener);
/**
* Start a ticker that will send out timestamp information at the interval specified.
*
* @param msOfDelay must be at least 50, or 0 may be set to halt and clear a previously started
* ticker.
*/
public void setTicker (
Client client, String tickerName, int msOfDelay, InvocationListener listener);
/**
* Request to get the specified user's cookie.
*/
public void getCookie (Client client, int playerId, InvocationListener listener);
/**
* Request to set our cookie.
*/
public void setCookie (Client client, byte[] cookie, InvocationListener listener);
}
@@ -1,532 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.client;
import java.io.Externalizable;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.HashMap;
import com.samskivert.util.CompactIntListUtil;
import com.samskivert.util.ObserverList;
import com.samskivert.util.StringUtil;
import com.threerings.util.MessageBundle;
import com.threerings.util.Name;
import com.threerings.presents.client.InvocationService;
import com.threerings.crowd.data.BodyObject;
import com.threerings.crowd.util.CrowdContext;
import com.threerings.parlor.Log; // well, fine
import com.threerings.ezgame.data.EZGameObject;
import com.threerings.ezgame.data.PropertySetEvent;
import com.threerings.ezgame.util.EZObjectMarshaller;
import com.threerings.ezgame.EZGame;
import com.threerings.ezgame.EZEvent;
import com.threerings.ezgame.DealListener;
import com.threerings.ezgame.MessageReceivedEvent;
import com.threerings.ezgame.MessageReceivedListener;
import com.threerings.ezgame.PropertyChangedEvent;
import com.threerings.ezgame.PropertyChangedListener;
import com.threerings.ezgame.StateChangedEvent;
import com.threerings.ezgame.StateChangedListener;
public class GameObjectImpl
implements EZGame
{
public GameObjectImpl (CrowdContext ctx, EZGameObject ezObj)
{
_ctx = ctx;
_ezObj = ezObj;
_props = _ezObj.getUserProps();
}
// from EZGame
public Object get (String propName)
{
return _props.get(propName);
}
// from EZGame
public Object get (String propName, int index)
{
return ((Object[]) get(propName))[index];
}
// from EZGame
public void set (String propName, Object value)
{
set(propName, value, -1);
}
// from EZGame
public void set (String propName, Object value, int index)
{
validatePropertyChange(propName, value, -1);
Object encoded = EZObjectMarshaller.encode(value);
Object reconstituted = EZObjectMarshaller.decode(encoded);
_ezObj.ezGameService.setProperty(
_ctx.getClient(), propName, encoded, index, false, null,
createLoggingListener("setProperty"));
// set it immediately in the game object
_ezObj.applyPropertySet(propName, reconstituted, index);
}
// from EZGame
public void testAndSet (String propName, Object value, Object testValue)
{
testAndSet(propName, value, testValue, -1);
}
// from EZGame
public void testAndSet (
String propName, Object value, Object testValue, int index)
{
validatePropertyChange(propName, value, -1);
Object encoded = EZObjectMarshaller.encode(value);
_ezObj.ezGameService.setProperty(
_ctx.getClient(), propName, encoded, index, true, testValue,
createLoggingListener("testAndSet"));
}
// from EZGame
public void registerListener (Object obj)
{
if ((obj instanceof MessageReceivedListener) ||
(obj instanceof PropertyChangedListener) ||
(obj instanceof StateChangedListener)) {
// silently ignore requests to listen twice
if (!_listeners.contains(obj)) {
_listeners.add(obj);
}
}
}
// from EZGame
public void unregisterListener (Object obj)
{
_listeners.remove(obj);
}
// from EZGame
public void setCollection (String collName, Object values)
{
populateCollection(collName, values, true);
}
// from EZGame
public void addToCollection (String collName, Object values)
{
populateCollection(collName, values, false);
}
// from EZGame
public void pickFromCollection (
String collName, int count, String propName)
{
getFromCollection(collName, count, propName, -1, false, null);
}
// from EZGame
public void pickFromCollection (
String collName, int count, String msgName, int playerIndex)
{
getFromCollection(collName, count, msgName, playerIndex, false, null);
}
// from EZGame
public void dealFromCollection (
String collName, int count, String propName,
DealListener listener)
{
getFromCollection(collName, count, propName, -1, true, listener);
}
// from EZGame
public void dealFromCollection (
String collName, int count, String msgName,
DealListener listener, int playerIndex)
{
getFromCollection(collName, count, msgName, playerIndex, true, listener);
}
// from EZGame
public void mergeCollection (String srcColl, String intoColl)
{
validateName(srcColl);
validateName(intoColl);
_ezObj.ezGameService.mergeCollection(_ctx.getClient(),
srcColl, intoColl, createLoggingListener("mergeCollection"));
}
// from EZGame
public void sendMessage (String messageName, Object value)
{
sendMessage(messageName, value, -1);
}
// from EZGame
public void sendMessage (String messageName, Object value, int playerIndex)
{
validateName(messageName);
validateValue(value);
Object encoded = EZObjectMarshaller.encode(value);
_ezObj.ezGameService.sendMessage(_ctx.getClient(),
messageName, encoded, playerIndex,
createLoggingListener("sendMessage"));
}
// from EZGame
public void startTicker (String tickerName, int msOfDelay)
{
validateName(tickerName);
_ezObj.ezGameService.setTicker(_ctx.getClient(),
tickerName, msOfDelay, createLoggingListener("setTicker"));
}
// from EZGame
public void stopTicker (String tickerName)
{
startTicker(tickerName, 0);
}
// from EZGame
public void sendChat (String msg)
{
validateChat(msg);
// Post a message to the game object, the controller
// will listen and call localChat().
_ezObj.postMessage(EZGameObject.GAME_CHAT, new Object[] { msg });
}
// from EZGame
public void localChat (String msg)
{
validateChat(msg);
// The sendChat() messages will end up being routed
// through this method on each client.
// TODO: make this look distinct from other system chat
_ctx.getChatDirector().displayInfo(null, MessageBundle.taint(msg));
}
// from EZGame
public int getPlayerCount ()
{
return _ezObj.getPlayerCount();
}
// from EZGame
public String[] getPlayerNames ()
{
String[] names = new String[_ezObj.players.length];
int index = 0;
for (Name name : _ezObj.players) {
names[index++] = (name == null) ? null : name.toString();
}
return names;
}
// from EZGame
public int getMyIndex ()
{
return _ezObj.getPlayerIndex(getUsername());
}
// from EZGame
public int getTurnHolderIndex ()
{
return _ezObj.getPlayerIndex(_ezObj.turnHolder);
}
// from EZGame
public int[] getWinnerIndexes ()
{
int[] winners = new int[0];
if (_ezObj.winners != null) {
for (int ii = 0; ii < _ezObj.winners.length; ii++) {
if (_ezObj.winners[ii]) {
winners = CompactIntListUtil.add(winners, ii);
}
}
}
return winners;
}
// from EZGame
public boolean isMyTurn ()
{
return getUsername().equals(_ezObj.turnHolder);
}
// from EZGame
public boolean isInPlay ()
{
return _ezObj.isInPlay();
}
// from EZGame
public void endTurn ()
{
endTurn(-1);
}
// from EZGame
public void endTurn (int nextPlayerIndex)
{
_ezObj.ezGameService.endTurn(_ctx.getClient(), nextPlayerIndex,
createLoggingListener("endTurn"));
}
// from EZGame
public void endGame (int... winners)
{
_ezObj.ezGameService.endGame(_ctx.getClient(), winners,
createLoggingListener("endGame"));
}
/**
* Secret function to dispatch property changed events.
*/
void dispatch (EZEvent event)
{
ObserverList.ObserverOp<Object> op;
if (event instanceof PropertyChangedEvent) {
final PropertyChangedEvent pce = (PropertyChangedEvent) event;
op = new ObserverList.ObserverOp<Object>() {
public boolean apply (Object obs) {
if (obs instanceof PropertyChangedListener) {
((PropertyChangedListener) obs).propertyChanged(pce);
}
return true;
}
};
} else if (event instanceof StateChangedEvent) {
final StateChangedEvent sce = (StateChangedEvent) event;
op = new ObserverList.ObserverOp<Object>() {
public boolean apply (Object obs) {
if (obs instanceof StateChangedListener) {
((StateChangedListener) obs).stateChanged(sce);
}
return true;
}
};
} else if (event instanceof MessageReceivedEvent) {
final MessageReceivedEvent mre = (MessageReceivedEvent) event;
op = new ObserverList.ObserverOp<Object>() {
public boolean apply (Object obs) {
if (obs instanceof MessageReceivedListener) {
((MessageReceivedListener) obs).messageReceived(mre);
}
return true;
}
};
} else {
throw new IllegalArgumentException("Please implement");
}
// and apply the operation
_listeners.apply(op);
}
/**
* Convenience function to get our name.
*/
private Name getUsername ()
{
BodyObject body = (BodyObject) _ctx.getClient().getClientObject();
return body.getVisibleName();
}
/**
* Create a listener for service requests.
*/
private InvocationService.ConfirmListener createLoggingListener (
final String service)
{
return new InvocationService.ConfirmListener() {
public void requestFailed (String cause)
{
Log.warning("Service failure " +
"[service=" + service + ", cause=" + cause + "].");
}
public void requestProcessed ()
{
// nada
}
};
}
/**
* Helper method for setCollection and addToCollection.
*/
private void populateCollection (
String collName, Object values, boolean clearExisting)
{
validateName(collName);
if (values == null) {
throw new IllegalArgumentException(
"Collection values may not be null.");
}
validateValue(values);
byte[][] encodedValues = (byte[][]) EZObjectMarshaller.encode(values);
_ezObj.ezGameService.addToCollection(
_ctx.getClient(), collName, encodedValues, clearExisting,
createLoggingListener("populateCollection"));
}
/**
* Helper method for pickFromCollection and dealFromCollection.
*/
private void getFromCollection(
String collName, final int count, String msgOrPropName, int playerIndex,
boolean consume, final DealListener dealy)
{
validateName(collName);
validateName(msgOrPropName);
if (count < 1) {
throw new IllegalArgumentException(
"Must retrieve at least one element!");
}
InvocationService.ConfirmListener listener;
if (dealy != null) {
// TODO: Figure out the method sig of the callback, and what it
// means
listener = new InvocationService.ConfirmListener() {
public void requestFailed (String cause) {
try {
dealy.dealt(Integer.parseInt(cause));
} catch (NumberFormatException nfe) {
// nada
}
}
public void requestProcessed () {
dealy.dealt(count);
}
};
} else {
listener = createLoggingListener("getFromCollection");
}
_ezObj.ezGameService.getFromCollection(
_ctx.getClient(), collName, consume, count, msgOrPropName,
playerIndex, listener);
}
/**
* Verify that the property name / value are valid.
*/
private void validatePropertyChange (
String propName, Object value, int index)
{
validateName(propName);
// check that we're setting an array element on an array
if (index >= 0) {
if (!(get(propName) instanceof Object[])) {
throw new IllegalArgumentException("Property " + propName +
" is not an Array.");
}
}
// validate the value too
validateValue(value);
}
/**
* Verify that the specified name is valid.
*/
private void validateName (String name)
{
if (name == null) {
throw new IllegalArgumentException(
"Property, message, and collection names must not be null.");
}
}
private void validateChat (String msg)
{
if (StringUtil.isBlank(msg)) {
throw new IllegalArgumentException(
"Empty chat may not be displayed.");
}
}
/**
* Verify that the value is legal to be streamed to other clients.
*/
private void validateValue (Object value)
{
if (value == null) {
return;
} else if (value instanceof Externalizable) {
throw new IllegalArgumentException(
"IExternalizable is not yet supported");
} else if (value.getClass().isArray()) {
int length = Array.getLength(value);
for (int ii=0; ii < length; ii++) {
validateValue(Array.get(value, ii));
}
} else if (value instanceof Iterable) {
for (Object o : (Iterable) value) {
validateValue(o);
}
} else if (!(value instanceof Serializable)) {
throw new IllegalArgumentException(
"Non-serializable properties may not be set.");
}
}
protected CrowdContext _ctx;
protected EZGameObject _ezObj;
protected HashMap<String, Object> _props;
protected ObserverList<Object> _listeners =
new ObserverList<Object>(ObserverList.SAFE_IN_ORDER_NOTIFY);
}
@@ -1,49 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.data;
import com.threerings.util.ActionScript;
/**
* Models a parameter that is used to configure AIs.
*/
@ActionScript(omit=true)
public class AIParameter extends Parameter
{
/** Indicates the maximum number of AIs in the game. */
public int maximum;
// TODO: allow specification of difficulty range
// TODO: allow specification of personality types
@Override // documentation inherited
public String getLabel ()
{
return "m.ai_" + ident;
}
@Override // documentation inherited
public Object getDefaultValue ()
{
return 0;
}
}
@@ -1,57 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.data;
import com.threerings.util.ActionScript;
/**
* Models a parameter that allows the selection of one of a list of choices (specified as strings).
*/
public class ChoiceParameter extends Parameter
{
/** The set of choices available for this parameter. */
public String[] choices;
/** The starting selection. */
public String start;
/**
* Returns the translation key for the specified choice.
*/
@ActionScript(omit=true)
public String getChoiceLabel (int index)
{
return "m.choice_" + choices[index];
}
@Override @ActionScript(omit=true) // documentation inherited
public String getLabel ()
{
return "m.choice_" + ident;
}
@Override // documentation inherited
public Object getDefaultValue ()
{
return start;
}
}
@@ -1,31 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.data;
/**
* Constants related to ezgames.
*/
public interface EZGameCodes
{
/** The message bundle for ezgame stuff. */
public static final String EZGAME_MESSAGE_BUNDLE = "ezgame";
}
@@ -1,120 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.data;
import com.google.common.base.Preconditions;
import com.threerings.util.StreamableHashMap;
import com.threerings.crowd.client.PlaceController;
import com.threerings.parlor.game.client.GameConfigurator;
import com.threerings.parlor.game.data.GameConfig;
import com.threerings.ezgame.client.EZGameConfigurator;
/**
* A game config for a simple multiplayer game.
*/
public class EZGameConfig extends GameConfig
{
/** Our configuration parameters. These will be seeded with the defaults from the game
* definition and then configured by the player in the lobby. */
public StreamableHashMap<String,Object> params = new StreamableHashMap<String,Object>();
/** A zero argument constructor used when unserializing. */
public EZGameConfig ()
{
}
/** Constructs a game config based on the supplied game definition. */
public EZGameConfig (int gameId, GameDefinition gameDef)
{
Preconditions.checkNotNull(gameDef, "Missing GameDefinition");
_gameId = gameId;
_gameDef = gameDef;
// set the default values for our parameters
for (int ii = 0; ii < gameDef.params.length; ii++) {
params.put(gameDef.params[ii].ident, gameDef.params[ii].getDefaultValue());
}
}
/**
* Returns the non-changing metadata that defines this game.
*/
public GameDefinition getGameDefinition ()
{
return _gameDef;
}
@Override // from GameConfig
public int getGameId ()
{
return _gameId;
}
@Override // from GameConfig
public String getGameIdent ()
{
return _gameDef.ident;
}
@Override // from GameConfig
public int getMatchType ()
{
return _gameDef.match.getMatchType();
}
@Override // from GameConfig
public GameConfigurator createConfigurator ()
{
return new EZGameConfigurator();
}
@Override // from PlaceConfig
public PlaceController createController ()
{
String ctrl = getGameDefinition().controller;
if (ctrl == null) {
throw new IllegalStateException("Game definition missing controller [gdef=" + getGameDefinition() + "]");
}
try {
return (PlaceController) Class.forName(getGameDefinition().controller).newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override // from PlaceConfig
public String getManagerClassName ()
{
return _gameDef.manager;
}
/** Our game's unique id. */
protected int _gameId;
/** Our game definition. */
protected GameDefinition _gameDef;
}
@@ -1,221 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.data;
import com.threerings.ezgame.client.EZGameService;
import com.threerings.presents.client.Client;
import com.threerings.presents.client.InvocationService;
import com.threerings.presents.data.InvocationMarshaller;
import com.threerings.presents.dobj.InvocationResponseEvent;
/**
* Provides the implementation of the {@link EZGameService} 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 EZGameMarshaller extends InvocationMarshaller
implements EZGameService
{
/** The method id used to dispatch {@link #addToCollection} requests. */
public static final int ADD_TO_COLLECTION = 1;
// from interface EZGameService
public void addToCollection (Client arg1, String arg2, byte[][] arg3, boolean arg4, InvocationService.InvocationListener arg5)
{
ListenerMarshaller listener5 = new ListenerMarshaller();
listener5.listener = arg5;
sendRequest(arg1, ADD_TO_COLLECTION, new Object[] {
arg2, arg3, Boolean.valueOf(arg4), listener5
});
}
/** The method id used to dispatch {@link #checkDictionaryWord} requests. */
public static final int CHECK_DICTIONARY_WORD = 2;
// from interface EZGameService
public void checkDictionaryWord (Client arg1, String arg2, String arg3, String arg4, InvocationService.ResultListener arg5)
{
InvocationMarshaller.ResultMarshaller listener5 = new InvocationMarshaller.ResultMarshaller();
listener5.listener = arg5;
sendRequest(arg1, CHECK_DICTIONARY_WORD, new Object[] {
arg2, arg3, arg4, listener5
});
}
/** The method id used to dispatch {@link #endGame} requests. */
public static final int END_GAME = 3;
// from interface EZGameService
public void endGame (Client arg1, int[] arg2, InvocationService.InvocationListener arg3)
{
ListenerMarshaller listener3 = new ListenerMarshaller();
listener3.listener = arg3;
sendRequest(arg1, END_GAME, new Object[] {
arg2, listener3
});
}
/** The method id used to dispatch {@link #endRound} requests. */
public static final int END_ROUND = 4;
// from interface EZGameService
public void endRound (Client arg1, int arg2, InvocationService.InvocationListener arg3)
{
ListenerMarshaller listener3 = new ListenerMarshaller();
listener3.listener = arg3;
sendRequest(arg1, END_ROUND, new Object[] {
Integer.valueOf(arg2), listener3
});
}
/** The method id used to dispatch {@link #endTurn} requests. */
public static final int END_TURN = 5;
// from interface EZGameService
public void endTurn (Client arg1, int arg2, InvocationService.InvocationListener arg3)
{
ListenerMarshaller listener3 = new ListenerMarshaller();
listener3.listener = arg3;
sendRequest(arg1, END_TURN, new Object[] {
Integer.valueOf(arg2), listener3
});
}
/** The method id used to dispatch {@link #getCookie} requests. */
public static final int GET_COOKIE = 6;
// from interface EZGameService
public void getCookie (Client arg1, int arg2, InvocationService.InvocationListener arg3)
{
ListenerMarshaller listener3 = new ListenerMarshaller();
listener3.listener = arg3;
sendRequest(arg1, GET_COOKIE, new Object[] {
Integer.valueOf(arg2), listener3
});
}
/** The method id used to dispatch {@link #getDictionaryLetterSet} requests. */
public static final int GET_DICTIONARY_LETTER_SET = 7;
// from interface EZGameService
public void getDictionaryLetterSet (Client arg1, String arg2, String arg3, int arg4, InvocationService.ResultListener arg5)
{
InvocationMarshaller.ResultMarshaller listener5 = new InvocationMarshaller.ResultMarshaller();
listener5.listener = arg5;
sendRequest(arg1, GET_DICTIONARY_LETTER_SET, new Object[] {
arg2, arg3, Integer.valueOf(arg4), listener5
});
}
/** The method id used to dispatch {@link #getFromCollection} requests. */
public static final int GET_FROM_COLLECTION = 8;
// from interface EZGameService
public void getFromCollection (Client arg1, String arg2, boolean arg3, int arg4, String arg5, int arg6, InvocationService.ConfirmListener arg7)
{
InvocationMarshaller.ConfirmMarshaller listener7 = new InvocationMarshaller.ConfirmMarshaller();
listener7.listener = arg7;
sendRequest(arg1, GET_FROM_COLLECTION, new Object[] {
arg2, Boolean.valueOf(arg3), Integer.valueOf(arg4), arg5, Integer.valueOf(arg6), listener7
});
}
/** The method id used to dispatch {@link #mergeCollection} requests. */
public static final int MERGE_COLLECTION = 9;
// from interface EZGameService
public void mergeCollection (Client arg1, String arg2, String arg3, InvocationService.InvocationListener arg4)
{
ListenerMarshaller listener4 = new ListenerMarshaller();
listener4.listener = arg4;
sendRequest(arg1, MERGE_COLLECTION, new Object[] {
arg2, arg3, listener4
});
}
/** The method id used to dispatch {@link #restartGameIn} requests. */
public static final int RESTART_GAME_IN = 10;
// from interface EZGameService
public void restartGameIn (Client arg1, int arg2, InvocationService.InvocationListener arg3)
{
ListenerMarshaller listener3 = new ListenerMarshaller();
listener3.listener = arg3;
sendRequest(arg1, RESTART_GAME_IN, new Object[] {
Integer.valueOf(arg2), listener3
});
}
/** The method id used to dispatch {@link #sendMessage} requests. */
public static final int SEND_MESSAGE = 11;
// from interface EZGameService
public void sendMessage (Client arg1, String arg2, Object arg3, int arg4, InvocationService.InvocationListener arg5)
{
ListenerMarshaller listener5 = new ListenerMarshaller();
listener5.listener = arg5;
sendRequest(arg1, SEND_MESSAGE, new Object[] {
arg2, arg3, Integer.valueOf(arg4), listener5
});
}
/** The method id used to dispatch {@link #setCookie} requests. */
public static final int SET_COOKIE = 12;
// from interface EZGameService
public void setCookie (Client arg1, byte[] arg2, InvocationService.InvocationListener arg3)
{
ListenerMarshaller listener3 = new ListenerMarshaller();
listener3.listener = arg3;
sendRequest(arg1, SET_COOKIE, new Object[] {
arg2, listener3
});
}
/** The method id used to dispatch {@link #setProperty} requests. */
public static final int SET_PROPERTY = 13;
// from interface EZGameService
public void setProperty (Client arg1, String arg2, Object arg3, int arg4, boolean arg5, Object arg6, InvocationService.InvocationListener arg7)
{
ListenerMarshaller listener7 = new ListenerMarshaller();
listener7.listener = arg7;
sendRequest(arg1, SET_PROPERTY, new Object[] {
arg2, arg3, Integer.valueOf(arg4), Boolean.valueOf(arg5), arg6, listener7
});
}
/** The method id used to dispatch {@link #setTicker} requests. */
public static final int SET_TICKER = 14;
// from interface EZGameService
public void setTicker (Client arg1, String arg2, int arg3, InvocationService.InvocationListener arg4)
{
ListenerMarshaller listener4 = new ListenerMarshaller();
listener4.listener = arg4;
sendRequest(arg1, SET_TICKER, new Object[] {
arg2, Integer.valueOf(arg3), listener4
});
}
}
@@ -1,387 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.data;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import com.samskivert.util.ObjectUtil;
import com.threerings.util.Name;
import com.threerings.io.ObjectInputStream;
import com.threerings.io.ObjectOutputStream;
import com.threerings.io.Streamable;
import com.threerings.presents.dobj.DSet;
import com.threerings.parlor.game.data.GameObject;
import com.threerings.parlor.turn.data.TurnGameObject;
import com.threerings.ezgame.util.EZObjectMarshaller;
/**
* Contains the data for an ez game.
*/
public class EZGameObject extends GameObject
implements TurnGameObject
{
/** The identifier for a MessageEvent containing a user message. */
public static final String USER_MESSAGE = "Umsg";
/** The identifier for a MessageEvent containing game-system chat. */
public static final String GAME_CHAT = "Uchat";
/** The identifier for a MessageEvent containing ticker notifications. */
public static final String TICKER = "Utick";
// AUTO-GENERATED: FIELDS START
/** The field name of the <code>controllerOid</code> field. */
public static final String CONTROLLER_OID = "controllerOid";
/** The field name of the <code>turnHolder</code> field. */
public static final String TURN_HOLDER = "turnHolder";
/** The field name of the <code>userCookies</code> field. */
public static final String USER_COOKIES = "userCookies";
/** The field name of the <code>ezGameService</code> field. */
public static final String EZ_GAME_SERVICE = "ezGameService";
// AUTO-GENERATED: FIELDS END
/** The client that is in control of this game. The first client to enter will be assigned
* control and control will subsequently be reassigned if that client disconnects or leaves. */
public int controllerOid;
/** The current turn holder. */
public Name turnHolder;
/** A set of loaded user cookies. */
public DSet<UserCookie> userCookies;
/** The service interface for requesting special things from the server. */
public EZGameMarshaller ezGameService;
/**
* Access the underlying user properties
*/
public HashMap<String, Object> getUserProps ()
{
return _props;
}
// from TurnGameObject
public String getTurnHolderFieldName ()
{
return TURN_HOLDER;
}
// from TurnGameObject
public Name getTurnHolder ()
{
return turnHolder;
}
// from TurnGameObject
public Name[] getPlayers ()
{
return players;
}
/**
* Called by PropertySetEvent to effect the property update.
*
* @return the old value.
*/
public Object applyPropertySet (String propName, Object data, int index)
{
Object oldValue = _props.get(propName);
if (index >= 0) {
if (isOnServer()) {
byte[][] arr = (oldValue instanceof byte[][])
? (byte[][]) oldValue : null;
if (arr == null || arr.length <= index) {
// TODO: in case a user sets element 0 and element 90000,
// we might want to store elements in a hash
byte[][] newArr = new byte[index + 1][];
if (arr != null) {
System.arraycopy(arr, 0, newArr, 0, arr.length);
}
_props.put(propName, newArr);
arr = newArr;
}
oldValue = arr[index];
arr[index] = (byte[]) data;
} else {
Object[] arr = (oldValue instanceof Object[])
? (Object[]) oldValue : null;
if (arr == null || arr.length <= index) {
Object[] newArr = new Object[index + 1];
if (arr != null) {
System.arraycopy(arr, 0, newArr, 0, arr.length);
}
_props.put(propName, newArr);
arr = newArr;
}
oldValue = arr[index];
arr[index] = data;
}
} else if (data != null) {
_props.put(propName, data);
} else {
_props.remove(propName);
}
return oldValue;
}
/**
* Test the specified property against the specified value. This is
* called on the server to validate testAndSet events.
*
* @return true if the property contains the value specified.
*/
public boolean testProperty (
String propName, int index, Object testValue)
{
Object curValue = _props.get(propName);
if (curValue != null && index >= 0) {
// see if there's an array there already
if (isOnServer()) {
if (curValue instanceof byte[][]) {
byte[][] curArray = (byte[][]) curValue;
if (curArray.length > index) {
curValue = curArray[index];
} else {
// the index is out of range, but since we auto-grow,
// we treat it like null
curValue = null;
}
} else {
// curData is not an array, so the test fails
return false;
}
} else {
if (curValue instanceof Object[]) {
Object[] curArray = (Object[]) curValue;
if (curArray.length > index) {
curValue = curArray[index];
} else {
// the index is out of range, but since we auto-grow,
// we treat it like null
curValue = null;
}
} else {
// curData is not an array, so the test fails
return false;
}
}
}
// let's test the values!
if ((testValue instanceof Object[]) && (curValue instanceof Object[])) {
// testing an array against another array
return Arrays.deepEquals((Object[]) testValue, (Object[]) curValue);
} else if ((testValue instanceof byte[]) && (curValue instanceof byte[])) {
// testing a property against another property (may have
// been from inside an array)
return Arrays.equals((byte[]) testValue, (byte[]) curValue);
// TODO: other array types must be tested if we're on the client
// ??
} else {
// will catch null == null...
return ObjectUtil.equals(testValue, curValue);
}
}
// AUTO-GENERATED: METHODS START
/**
* Requests that the <code>controllerOid</code> field be set to the
* specified 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 void setControllerOid (int value)
{
int ovalue = this.controllerOid;
requestAttributeChange(
CONTROLLER_OID, Integer.valueOf(value), Integer.valueOf(ovalue));
this.controllerOid = value;
}
/**
* Requests that the <code>turnHolder</code> field be set to the
* specified 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 void setTurnHolder (Name value)
{
Name ovalue = this.turnHolder;
requestAttributeChange(
TURN_HOLDER, value, ovalue);
this.turnHolder = value;
}
/**
* Requests that the specified entry be added to the
* <code>userCookies</code> set. The set will not change until the event is
* actually propagated through the system.
*/
public void addToUserCookies (UserCookie elem)
{
requestEntryAdd(USER_COOKIES, userCookies, elem);
}
/**
* Requests that the entry matching the supplied key be removed from
* the <code>userCookies</code> set. The set will not change until the
* event is actually propagated through the system.
*/
public void removeFromUserCookies (Comparable key)
{
requestEntryRemove(USER_COOKIES, userCookies, key);
}
/**
* Requests that the specified entry be updated in the
* <code>userCookies</code> set. The set will not change until the event is
* actually propagated through the system.
*/
public void updateUserCookies (UserCookie elem)
{
requestEntryUpdate(USER_COOKIES, userCookies, elem);
}
/**
* Requests that the <code>userCookies</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 void setUserCookies (DSet<com.threerings.ezgame.data.UserCookie> value)
{
requestAttributeChange(USER_COOKIES, value, this.userCookies);
@SuppressWarnings("unchecked") DSet<com.threerings.ezgame.data.UserCookie> clone =
(value == null) ? null : value.typedClone();
this.userCookies = clone;
}
/**
* Requests that the <code>ezGameService</code> field be set to the
* specified 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 void setEzGameService (EZGameMarshaller value)
{
EZGameMarshaller ovalue = this.ezGameService;
requestAttributeChange(
EZ_GAME_SERVICE, value, ovalue);
this.ezGameService = value;
}
// AUTO-GENERATED: METHODS END
/**
* A custom serialization method.
*/
public void writeObject (ObjectOutputStream out)
throws IOException
{
out.defaultWriteObject();
if (isOnServer()) {
// write the number of properties, followed by each one
out.writeInt(_props.size());
for (Map.Entry<String, Object> entry : _props.entrySet()) {
out.writeUTF(entry.getKey());
out.writeObject(entry.getValue());
}
} else {
throw new IllegalStateException();
}
}
/**
* A custom serialization method.
*/
public void readObject (ObjectInputStream ins)
throws IOException, ClassNotFoundException
{
ins.defaultReadObject();
_props.clear();
int count = ins.readInt();
boolean onClient = !isOnServer();
while (count-- > 0) {
String key = ins.readUTF();
Object o = ins.readObject();
if (onClient) {
o = EZObjectMarshaller.decode(o);
}
_props.put(key, o);
}
}
/**
* Called internally and by PropertySetEvent to determine if we're
* on the server or on the client.
*/
boolean isOnServer ()
{
return (_omgr != null) && _omgr.isManager(this);
}
/** The current state of game data.
* On the server, this will be a byte[] for normal properties
* and a byte[][] for array properties.
* On the client, the actual values are kept whole.
*/
protected transient HashMap<String, Object> _props =
new HashMap<String, Object>();
}
@@ -1,52 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.data;
import com.threerings.util.ActionScript;
/**
* Models a paramter that can be used to load the contents of a file into a byte array or string
* and ship it to the server.
*/
@ActionScript(omit=true)
public class FileParameter extends Parameter
{
/** Whether or not the contents of the file should be supplied as binary data. If false, the
* file will be loaded as text in the platform default encoding . */
public boolean binary = false;
@Override // documentation inherited
public String getLabel ()
{
return "m.file_" + ident;
}
@Override // documentation inherited
public Object getDefaultValue ()
{
if (binary) {
return new byte[0];
} else {
return "";
}
}
}
@@ -1,101 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.data;
import java.util.ArrayList;
import com.samskivert.util.StringUtil;
import com.threerings.io.Streamable;
import com.threerings.util.ActionScript;
/**
* Contains the information about a game as described by the game definition XML file.
*/
public abstract class GameDefinition implements Streamable
{
/** A string identifier for the game. */
public String ident;
/** The class name of the <code>GameController</code> derivation that we use to bootstrap on
* the client. */
public String controller;
/** The class name of the <code>GameManager</code> derivation that we use to manage the game on
* the server. */
public String manager;
/** The MD5 digest of the game media file. */
public String digest;
/** The configuration of the match-making mechanism. */
public MatchConfig match;
/** Parameters used to configure the game itself. */
public Parameter[] params;
/**
* Provides the path to this game's media (a jar file or an SWF).
*
* @param gameId the unique id of the game provided when this game definition was registered
* with the system, or -1 if we're running in test mode.
*/
public abstract String getMediaPath (int gameId);
/**
* Returns true if a single player can play this game (possibly against AI opponents), or if
* opponents are needed.
*/
public boolean isSinglePlayerPlayable ()
{
// maybe it's just single player no problem
int minPlayers = 2;
if (match != null) {
minPlayers = match.getMinimumPlayers();
if (minPlayers <= 1) {
return true;
}
}
// or maybe it has AIs
int aiCount = 0;
for (Parameter param : params) {
if (param instanceof AIParameter) {
aiCount = ((AIParameter)param).maximum;
}
}
return (minPlayers - aiCount) <= 1;
}
/** Called when parsing a game definition from XML. */
@ActionScript(omit=true)
public void setParams (ArrayList<Parameter> list)
{
params = list.toArray(new Parameter[list.size()]);
}
/** Generates a string representation of this instance. */
public String toString ()
{
return StringUtil.fieldsToString(this);
}
}
@@ -1,39 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.data;
import com.threerings.io.SimpleStreamableObject;
import com.threerings.parlor.game.data.GameConfig;
/**
* Used to configure the match-making interface for a game. Particular match-making mechanisms
* extend this class and specify their own special configuration parameters.
*/
public abstract class MatchConfig extends SimpleStreamableObject
{
/** Returns the matchmaking type to use for this game, e.g. {@link GameConfig.SEATED_GAME}. */
public abstract int getMatchType ();
/** Returns the minimum number of players needed to play this game. */
public abstract int getMinimumPlayers ();
}
@@ -1,55 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.data;
import com.samskivert.util.StringUtil;
import com.threerings.io.Streamable;
/**
* Defines a configuration parameter for a game. Various derived classes exist that define
* particular types of configuration parameters including choices, toggles, ranges, etc.
*/
public abstract class Parameter implements Streamable
{
/** A string identifier that names this parameter. */
public String ident;
/** A human readable name for this configuration parameter. */
public String name;
/** A human readable tooltip to display when the mouse is hovered over this configuration
* parameter. */
public String tip;
/** Returns the translation key for this parameter's label. */
public abstract String getLabel ();
/** Returns the default value of this parameter. */
public abstract Object getDefaultValue ();
/** Generates a string representation of this instance. */
public String toString ()
{
return StringUtil.fieldsToString(this);
}
}
@@ -1,121 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.data;
import java.io.IOException;
import com.threerings.io.ObjectInputStream;
import com.threerings.io.ObjectOutputStream;
import com.threerings.io.Streamable;
import com.threerings.io.Streamer;
import com.threerings.util.ActionScript;
import com.threerings.presents.dobj.DObject;
import com.threerings.presents.dobj.NamedEvent;
import com.threerings.ezgame.util.EZObjectMarshaller;
/**
* Represents a property change on the actionscript object we use in EZGameObject.
*/
@ActionScript(omit=true)
public class PropertySetEvent extends NamedEvent
{
/** Suitable for unserialization. */
public PropertySetEvent ()
{
}
/**
* Create a PropertySetEvent.
*/
public PropertySetEvent (int targetOid, String propName, Object value, int index, Object ovalue)
{
super(targetOid, propName);
_data = value;
_index = index;
_oldValue = ovalue;
}
/**
* Returns the value that was set for the property.
*/
public Object getValue ()
{
return _data;
}
/**
* Returns the old value.
*/
public Object getOldValue ()
{
return _oldValue;
}
/**
* Returns the index, or -1 if not applicable.
*/
public int getIndex ()
{
return _index;
}
// from abstract DEvent
public boolean applyToObject (DObject target)
{
EZGameObject ezObj = (EZGameObject) target;
if (!ezObj.isOnServer()) {
_data = EZObjectMarshaller.decode(_data);
}
if (_oldValue == UNSET_OLD_VALUE) {
// only apply the property change if we haven't already
_oldValue = ezObj.applyPropertySet(_name, _data, _index);
}
return true;
}
@Override
protected void notifyListener (Object listener)
{
if (listener instanceof PropertySetListener) {
((PropertySetListener) listener).propertyWasSet(this);
}
}
@Override @ActionScript(name="toStringBuf")
protected void toString (StringBuilder buf)
{
buf.append("PropertySetEvent ");
super.toString(buf);
buf.append(", index=").append(_index);
}
/** The index of the property, if applicable. */
protected int _index;
/** The client-side data that is assigned to this property. */
protected Object _data;
/** The old value. */
protected transient Object _oldValue = UNSET_OLD_VALUE;
}
@@ -1,37 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.data;
import com.threerings.presents.dobj.ChangeListener;
/**
* A listener that will be notified of PropertySet events.
*/
public interface PropertySetListener extends ChangeListener
{
/**
* Called when a property was set on a flash game object.
* This will be called <em>after</em> the event has been applied
* to the object.
*/
public void propertyWasSet (PropertySetEvent event);
}
@@ -1,51 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.data;
import com.threerings.util.ActionScript;
/**
* Models a parameter that can contain an integer value in a specified range.
*/
public class RangeParameter extends Parameter
{
/** The minimum value of this parameter. */
public int minimum;
/** The maximum value of this parameter. */
public int maximum;
/** The starting value for this parameter. */
public int start;
@Override @ActionScript(omit=true) // documentation inherited
public String getLabel ()
{
return "m.range_" + ident;
}
@Override // documentation inherited
public Object getDefaultValue ()
{
return start;
}
}
@@ -1,54 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.data;
import com.threerings.parlor.game.data.GameConfig;
/**
* Extends {@link MatchConfig} with information about match-making in the table style.
*/
public class TableMatchConfig extends MatchConfig
{
/** The minimum number of seats at this table. */
public int minSeats;
/** The starting setting for the number of seats at this table. */
public int startSeats;
/** The maximum number of seats at this table. */
public int maxSeats;
/** This is set to true if this is a party game. */
public boolean isPartyGame;
@Override // from MatchConfig
public int getMatchType ()
{
return isPartyGame ? GameConfig.PARTY : GameConfig.SEATED_GAME;
}
@Override // from MatchConfig
public int getMinimumPlayers ()
{
return minSeats;
}
}
@@ -1,45 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.data;
import com.threerings.util.ActionScript;
/**
* Models a parameter that allows the toggling of a single value.
*/
public class ToggleParameter extends Parameter
{
/** The starting state for this parameter. */
public boolean start;
@Override @ActionScript(omit=true) // documentation inherited
public String getLabel ()
{
return "m.toggle_" + ident;
}
@Override // documentation inherited
public Object getDefaultValue ()
{
return start;
}
}
@@ -1,51 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.data;
import com.threerings.presents.dobj.DSet;
/**
* Represents a user's game-specific cookie data.
*/
public class UserCookie
implements DSet.Entry
{
/** The id of the player that has this cookie. */
public int playerId;
/** The cookie value. */
public byte[] cookie;
/**
*/
public UserCookie (int playerId, byte[] cookie)
{
this.playerId = playerId;
this.cookie = cookie;
}
// from DSet.Entry
public Comparable getKey ()
{
return playerId;
}
}
@@ -1,268 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.server;
import com.samskivert.util.Invoker;
import com.samskivert.util.ResultListener;
import com.threerings.crowd.server.CrowdServer;
import com.threerings.presents.client.InvocationService;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Array;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.zip.GZIPInputStream;
import com.samskivert.util.CountHashMap;
import com.samskivert.util.RandomUtil;
import static com.threerings.ezgame.server.Log.log;
/**
* Manages loading and querying word dictionaries in multiple languages.
*
* NOTE: the service supports lazy loading of language files, but does not _unload_ them from
* memory, leading to increasing memory usage.
*
* NOTE: the dictionary service has not yet been tested with language files written in non-default
* character encodings.
*/
public class DictionaryManager
{
/**
* Creates the singleton instance of the dictionary service.
*
* @param prefix used to locate dictionary files in the classpath. A dictionary for "en_US" for
* example, would be searched for as "prefix/en_US.wordlist.gz".
*/
public static void init (String prefix)
{
_singleton = new DictionaryManager(prefix);
}
/**
* Get an instance of the dictionary service.
*/
public static DictionaryManager getInstance ()
{
return _singleton;
}
/**
* Returns true if the language is known to be supported by the dictionary service (would it be
* better to return a whole list of supported languages instead?)
*/
public void isLanguageSupported (final String locale,
final InvocationService.ResultListener listener)
{
// TODO: once we have file paths set up, change this to match against dictionary files
listener.requestProcessed(locale != null && locale.toLowerCase().startsWith("en"));
}
/**
* Retrieves a set of letters from a language definition file, and returns a random sampling of
* /count/ elements.
*/
public void getLetterSet (final String locale, final String dictionary, final int count,
final InvocationService.ResultListener listener)
{
CrowdServer.invoker.postUnit(new Invoker.Unit("DictionaryManager.getLetterSet") {
public boolean invoke () {
Dictionary dict = getDictionary(locale, dictionary);
char[] chars = dict.randomLetters(count);
StringBuilder sb = new StringBuilder();
for (char c : chars) {
sb.append(c);
sb.append(',');
}
sb.deleteCharAt(sb.length() - 1);
_set = sb.toString();
return true;
}
public void handleResult () {
listener.requestProcessed(_set);
}
protected String _set;
});
}
/**
* Checks if the specified word exists in the given language
*/
public void checkWord (final String locale, final String dictionary, final String word,
final InvocationService.ResultListener listener)
{
CrowdServer.invoker.postUnit(new Invoker.Unit("DictionaryManager.checkWord") {
public boolean invoke () {
Dictionary dict = getDictionary(locale, dictionary);
_result = (dict != null && dict.contains(word));
return true;
}
public void handleResult () {
listener.requestProcessed(_result);
}
protected boolean _result;
});
}
/**
* Protected constructor.
*/
protected DictionaryManager (String prefix)
{
_prefix = prefix;
}
/**
* Retrieves the dictionary object for a given locale. Forces the dictionary file to be
* loaded, if it hasn't already.
*/
protected Dictionary getDictionary (String locale, String dictionary)
{
if (locale == null) {
return null;
}
// TODO: honor the dictionary parameter
locale = locale.toLowerCase();
if (!_dictionaries.containsKey(locale)) {
String path = _prefix + "/" + locale + ".wordlist.gz";
try {
InputStream in = getClass().getClassLoader().getResourceAsStream(path);
_dictionaries.put(locale, new Dictionary(locale, new GZIPInputStream(in)));
} catch (Exception e) {
log.log(Level.WARNING, "Failed to load dictionary [path=" + path + "].", e);
}
}
return _dictionaries.get(locale);
}
/**
* Helper class, encapsulates a sorted array of word hashes, which can be used to look up the
* existence of a word.
*/
protected class Dictionary
{
/**
* Constructor, loads up the word list and initializes storage. This naive version assumes
* language files are simple list of words, with one word per line.
*/
public Dictionary (String locale, InputStream words)
throws IOException
{
CountHashMap <Character> letters = new CountHashMap <Character>();
if (words != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(words));
String line = null;
while ((line = reader.readLine()) != null) {
String word = line.toLowerCase();
// add the word to the dictionary
_words.add(word);
// then count characters
for (int ii = word.length() - 1; ii >= 0; ii--) {
char ch = word.charAt(ii);
letters.incrementCount(ch, 1);
}
}
} else {
log.warning("Missing dictionary file [locale=" + locale + "].");
}
initializeLetterCounts(letters);
log.fine("Loaded dictionary [locale=" + locale + ", words=" + _words.size() +
", letters=" + letters + "].");
}
/** Checks if the specified word exists in the word list */
public boolean contains (String word)
{
return (word != null) && _words.contains(word.toLowerCase());
}
/** Gets an array of random letters for the language, with uniform distribution. */
public char[] randomLetters (int count)
{
char[] results = new char[count];
for (int i = 0; i < count; i++) {
// find random index and get its letter
int index = RandomUtil.getWeightedIndex(_counts);
results[i] = _letters[index];
}
return results;
}
// PROTECTED HELPERS
/** Given a CountHashMap of letters, initializes the internal letter and count arrays, used
* by RandomUtil. */
protected void initializeLetterCounts (CountHashMap <Character> letters)
{
Set<Character> keys = letters.keySet();
int keycount = keys.size();
int total = letters.getTotalCount();
if (total == 0) { return; } // Something went wrong, abort.
// Initialize storage
_letters = new char[keycount];
_counts = new float[keycount];
// Copy letters and normalize counts
for (Character key : keys)
{
keycount--;
_letters[keycount] = key;
_counts[keycount] = ((float) letters.getCount(key)) / total; // normalize
}
}
/** The words. */
protected HashSet<String> _words = new HashSet<String>();
/** Letter array. */
protected char[] _letters = new char[] { };
/** Letter count array. */
protected float[] _counts = new float[] { };
}
/** Used to locate dictionaries in the classpath. */
protected String _prefix;
/** Map from locale name to Dictionary object. */
protected HashMap <String, Dictionary> _dictionaries = new HashMap <String, Dictionary>();
/** Singleton instance pointer. */
protected static DictionaryManager _singleton;
}
@@ -1,162 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.server;
import com.threerings.ezgame.client.EZGameService;
import com.threerings.ezgame.data.EZGameMarshaller;
import com.threerings.presents.client.Client;
import com.threerings.presents.client.InvocationService;
import com.threerings.presents.data.ClientObject;
import com.threerings.presents.data.InvocationMarshaller;
import com.threerings.presents.server.InvocationDispatcher;
import com.threerings.presents.server.InvocationException;
/**
* Dispatches requests to the {@link EZGameProvider}.
*/
public class EZGameDispatcher extends InvocationDispatcher
{
/**
* Creates a dispatcher that may be registered to dispatch invocation
* service requests for the specified provider.
*/
public EZGameDispatcher (EZGameProvider provider)
{
this.provider = provider;
}
// from InvocationDispatcher
public InvocationMarshaller createMarshaller ()
{
return new EZGameMarshaller();
}
@SuppressWarnings("unchecked") // from InvocationDispatcher
public void dispatchRequest (
ClientObject source, int methodId, Object[] args)
throws InvocationException
{
switch (methodId) {
case EZGameMarshaller.ADD_TO_COLLECTION:
((EZGameProvider)provider).addToCollection(
source,
(String)args[0], (byte[][])args[1], ((Boolean)args[2]).booleanValue(), (InvocationService.InvocationListener)args[3]
);
return;
case EZGameMarshaller.CHECK_DICTIONARY_WORD:
((EZGameProvider)provider).checkDictionaryWord(
source,
(String)args[0], (String)args[1], (String)args[2], (InvocationService.ResultListener)args[3]
);
return;
case EZGameMarshaller.END_GAME:
((EZGameProvider)provider).endGame(
source,
(int[])args[0], (InvocationService.InvocationListener)args[1]
);
return;
case EZGameMarshaller.END_ROUND:
((EZGameProvider)provider).endRound(
source,
((Integer)args[0]).intValue(), (InvocationService.InvocationListener)args[1]
);
return;
case EZGameMarshaller.END_TURN:
((EZGameProvider)provider).endTurn(
source,
((Integer)args[0]).intValue(), (InvocationService.InvocationListener)args[1]
);
return;
case EZGameMarshaller.GET_COOKIE:
((EZGameProvider)provider).getCookie(
source,
((Integer)args[0]).intValue(), (InvocationService.InvocationListener)args[1]
);
return;
case EZGameMarshaller.GET_DICTIONARY_LETTER_SET:
((EZGameProvider)provider).getDictionaryLetterSet(
source,
(String)args[0], (String)args[1], ((Integer)args[2]).intValue(), (InvocationService.ResultListener)args[3]
);
return;
case EZGameMarshaller.GET_FROM_COLLECTION:
((EZGameProvider)provider).getFromCollection(
source,
(String)args[0], ((Boolean)args[1]).booleanValue(), ((Integer)args[2]).intValue(), (String)args[3], ((Integer)args[4]).intValue(), (InvocationService.ConfirmListener)args[5]
);
return;
case EZGameMarshaller.MERGE_COLLECTION:
((EZGameProvider)provider).mergeCollection(
source,
(String)args[0], (String)args[1], (InvocationService.InvocationListener)args[2]
);
return;
case EZGameMarshaller.RESTART_GAME_IN:
((EZGameProvider)provider).restartGameIn(
source,
((Integer)args[0]).intValue(), (InvocationService.InvocationListener)args[1]
);
return;
case EZGameMarshaller.SEND_MESSAGE:
((EZGameProvider)provider).sendMessage(
source,
(String)args[0], args[1], ((Integer)args[2]).intValue(), (InvocationService.InvocationListener)args[3]
);
return;
case EZGameMarshaller.SET_COOKIE:
((EZGameProvider)provider).setCookie(
source,
(byte[])args[0], (InvocationService.InvocationListener)args[1]
);
return;
case EZGameMarshaller.SET_PROPERTY:
((EZGameProvider)provider).setProperty(
source,
(String)args[0], args[1], ((Integer)args[2]).intValue(), ((Boolean)args[3]).booleanValue(), args[4], (InvocationService.InvocationListener)args[5]
);
return;
case EZGameMarshaller.SET_TICKER:
((EZGameProvider)provider).setTicker(
source,
(String)args[0], ((Integer)args[1]).intValue(), (InvocationService.InvocationListener)args[2]
);
return;
default:
super.dispatchRequest(source, methodId, args);
return;
}
}
}
@@ -1,825 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.server;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import com.samskivert.util.ArrayIntSet;
import com.samskivert.util.ArrayUtil;
import com.samskivert.util.CollectionUtil;
import com.samskivert.util.HashIntMap;
import com.samskivert.util.Interval;
import com.samskivert.util.IntListUtil;
import com.samskivert.util.RandomUtil;
import com.samskivert.util.ResultListener;
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.dobj.DObjectManager;
import com.threerings.presents.dobj.DSet;
import com.threerings.presents.dobj.MessageEvent;
import com.threerings.presents.client.InvocationService;
import com.threerings.presents.server.InvocationException;
import com.threerings.crowd.data.BodyObject;
import com.threerings.crowd.data.OccupantInfo;
import com.threerings.crowd.data.PlaceObject;
import com.threerings.crowd.server.CrowdServer;
import com.threerings.parlor.game.data.GameConfig;
import com.threerings.parlor.game.server.GameManager;
import com.threerings.parlor.turn.server.TurnGameManager;
import com.threerings.util.MessageBundle;
import com.threerings.ezgame.data.EZGameCodes;
import com.threerings.ezgame.data.EZGameMarshaller;
import com.threerings.ezgame.data.EZGameObject;
import com.threerings.ezgame.data.PropertySetEvent;
import com.threerings.ezgame.data.UserCookie;
import static com.threerings.ezgame.server.Log.log;
/**
* A manager for "ez" games.
*/
public class EZGameManager extends GameManager
implements EZGameCodes, EZGameProvider, TurnGameManager
{
public EZGameManager ()
{
// addDelegate(_turnDelegate = new EZGameTurnDelegate());
}
/**
* Configures the oids of the winners of this game. If a game manager delegate wishes to handle
* winner assignment, it should call this method and then call {@link #enddGame}.
*/
public void setWinners (int[] winnerOids)
{
_winnerOids = winnerOids;
}
@Override
public void playerReady (BodyObject caller)
{
// if we're rematching...
if (!_ezObj.isInPlay() && (_ezObj.roundId != 0) && _ezObj.players.length > 1) {
// report to the other players that this player requested a rematch
int pidx = _ezObj.getPlayerIndex(caller.getVisibleName());
if (pidx != -1 && _playerOids[pidx] == 0) {
systemMessage(EZGAME_MESSAGE_BUNDLE,
MessageBundle.tcompose("m.rematch_requested", caller.getVisibleName()));
}
}
super.playerReady(caller);
}
/**
* Confirms that the caller can end the game (or restart it). Requires that they are a player
* and that the game is not in play.
*/
public void validateCanEndGame (ClientObject caller)
throws InvocationException
{
if (!_ezObj.isInPlay()) {
throw new InvocationException("e.already_ended");
}
validateUser(caller);
}
// from TurnGameManager
public void turnWillStart ()
{
}
// from TurnGameManager
public void turnDidStart ()
{
}
// from TurnGameManager
public void turnDidEnd ()
{
}
// from EZGameProvider
public void endTurn (ClientObject caller, int nextPlayerId,
InvocationService.InvocationListener listener)
throws InvocationException
{
validateUser(caller);
// // make sure this player is the turn holder
// Name holder = _ezObj.turnHolder;
// if (holder != null && !holder.equals(((BodyObject) caller).getVisibleName())) {
// throw new InvocationException(InvocationCodes.ACCESS_DENIED);
// }
// Name nextTurnHolder = null;
// if (nextPlayerId != 0) {
// BodyObject target = getPlayerByOid(nextPlayerId);
// if (target != null) {
// nextTurnHolder = target.getVisibleName();
// }
// }
_turnDelegate.endTurn(nextPlayerId);
}
// from EZGameProvider
public void endRound (ClientObject caller, int nextRoundDelay,
InvocationService.InvocationListener listener)
throws InvocationException
{
validateUser(caller);
// let the game know that it is doing something stupid
if (_ezObj.roundId < 0) {
throw new InvocationException("m.round_already_ended");
}
// while we are between rounds, our round id is the negation of the round that just ended
_ezObj.setRoundId(-_ezObj.roundId);
// queue up the start of the next round if requested
if (nextRoundDelay > 0) {
new Interval(CrowdServer.omgr) {
public void expired () {
if (_ezObj.isInPlay()) {
_ezObj.setRoundId(-_ezObj.roundId + 1);
}
}
}.schedule(nextRoundDelay * 1000L);
}
}
// from EZGameProvider
public void endGame (ClientObject caller, int[] winnerOids,
InvocationService.InvocationListener listener)
throws InvocationException
{
validateCanEndGame(caller);
setWinners(winnerOids);
endGame();
}
// from EZGameProvider
public void restartGameIn (ClientObject caller, int seconds,
InvocationService.InvocationListener listener)
throws InvocationException
{
validateUser(caller);
// queue up the start of the next game
if (seconds > 0) {
new Interval(CrowdServer.omgr) {
public void expired () {
if (_ezObj.isActive() && !_ezObj.isInPlay()) {
startGame();
}
}
}.schedule(seconds * 1000L);
} else {
// start immediately
if (_ezObj.isActive()) {
startGame();
}
}
}
// from EZGameProvider
public void sendMessage (ClientObject caller, String msg, Object data, int playerId,
InvocationService.InvocationListener listener)
throws InvocationException
{
validateUser(caller);
if (playerId == 0) {
_ezObj.postMessage(EZGameObject.USER_MESSAGE, msg, data);
} else {
sendPrivateMessage(playerId, msg, data);
}
}
// from EZGameProvider
public void setProperty (ClientObject caller, String propName, Object data, int index,
boolean testAndSet, Object testValue,
InvocationService.InvocationListener listener)
throws InvocationException
{
validateUser(caller);
if (testAndSet && !_ezObj.testProperty(propName, index, testValue)) {
return; // the test failed: do not set the property
}
setProperty(propName, data, index);
}
// from EZGameProvider
public void getDictionaryLetterSet (
ClientObject caller, String locale, String dictionary, int count,
InvocationService.ResultListener listener)
throws InvocationException
{
getDictionaryManager().getLetterSet(locale, dictionary, count, listener);
}
// from EZGameProvider
public void checkDictionaryWord (
ClientObject caller, String locale, String dictionary, String word,
InvocationService.ResultListener listener)
throws InvocationException
{
getDictionaryManager().checkWord(locale, dictionary, word, listener);
}
/**
* Returns the dictionary manager if it has been properly initialized. Throws an INTERNAL_ERROR
* exception if it has not.
*/
protected DictionaryManager getDictionaryManager ()
throws InvocationException
{
DictionaryManager dictionary = DictionaryManager.getInstance();
if (dictionary == null) {
log.warning("DictionaryManager not initialized.");
throw new InvocationException(INTERNAL_ERROR);
}
return dictionary;
}
// 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 playerId,
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 (playerId == 0) {
setProperty(msgOrPropName, result, -1);
} else {
sendPrivateMessage(playerId, msgOrPropName, result);
}
listener.requestProcessed(); // SUCCESS!
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);
}
}
}
}
// from EZGameProvider
public void setTicker (ClientObject caller, String tickerName, int msOfDelay,
InvocationService.InvocationListener listener)
throws InvocationException
{
validateUser(caller);
Ticker t;
if (msOfDelay >= MIN_TICKER_DELAY) {
if (_tickers != null) {
t = _tickers.get(tickerName);
} else {
_tickers = new HashMap<String, Ticker>();
t = null;
}
if (t == null) {
if (_tickers.size() >= MAX_TICKERS) {
throw new InvocationException(ACCESS_DENIED);
}
t = new Ticker(tickerName, _ezObj);
_tickers.put(tickerName, t);
}
t.start(msOfDelay);
} else if (msOfDelay <= 0) {
if (_tickers != null) {
t = _tickers.remove(tickerName);
if (t != null) {
t.stop();
}
}
} else {
throw new InvocationException(ACCESS_DENIED);
}
}
// from EZGameProvider
public void getCookie (ClientObject caller, final int playerOid,
InvocationService.InvocationListener listener)
throws InvocationException
{
if (_ezObj.userCookies != null && _ezObj.userCookies.containsKey(playerOid)) {
// already loaded: we do nothing
return;
}
// we only start looking up the cookie if nobody else already is
if (_cookieLookups.contains(playerOid)) {
return;
}
BodyObject body = getOccupantByOid(playerOid);
if (body == null) {
log.fine("getCookie() called with invalid occupant [occupantId=" + playerOid + "].");
throw new InvocationException(INTERNAL_ERROR);
}
// indicate that we're looking up a cookie
_cookieLookups.add(playerOid);
int ppId = getPlayerPersistentId(body);
getCookieManager().getCookie(_gameconfig.getGameId(), ppId, new ResultListener<byte[]>() {
public void requestCompleted (byte[] result) {
// note that we're done with this lookup
_cookieLookups.remove(playerOid);
// result may be null: that's ok, it means we've looked up the user's nonexistent
// cookie; also only set the cookie if the player is still in the room
if (_ezObj.occupants.contains(playerOid) && _ezObj.isActive()) {
_ezObj.addToUserCookies(new UserCookie(playerOid, result));
}
}
public void requestFailed (Exception cause) {
log.warning("Unable to retrieve cookie [cause=" + cause + "].");
requestCompleted(null);
}
});
}
// from EZGameProvider
public void setCookie (ClientObject caller, byte[] value,
InvocationService.InvocationListener listener)
throws InvocationException
{
validateUser(caller);
// persist this new cookie
getCookieManager().setCookie(
_gameconfig.getGameId(), getPlayerPersistentId((BodyObject)caller), value);
// and update the distributed object
UserCookie cookie = new UserCookie(caller.getOid(), value);
if (_ezObj.userCookies.containsKey(cookie.getKey())) {
_ezObj.updateUserCookies(cookie);
} else {
_ezObj.addToUserCookies(cookie);
}
}
/**
* Helper method to send a private message to the specified player oid (must already be
* verified).
*/
protected void sendPrivateMessage (int playerOid, String msg, Object data)
throws InvocationException
{
BodyObject target = getPlayerByOid(playerOid);
if (target == null) {
// TODO: this code has no corresponding translation
throw new InvocationException("m.player_not_around");
}
target.postMessage(EZGameObject.USER_MESSAGE + ":" + _ezObj.getOid(),
new Object[] { msg, data });
}
/**
* Helper method to post a property set event.
*/
protected void setProperty (String propName, Object value, int index)
{
// apply the property set immediately
Object oldValue = _ezObj.applyPropertySet(propName, value, index);
_ezObj.postEvent(
new PropertySetEvent(_ezObj.getOid(), propName, value, index, oldValue));
}
/**
* Validate that the specified user has access to do things in the game.
*/
protected void validateUser (ClientObject caller)
throws InvocationException
{
// the server is always cool
if (caller == null) {
return;
}
switch (getMatchType()) {
case GameConfig.PARTY:
return; // always validate.
default: {
BodyObject body = (BodyObject)caller;
if (getPlayerIndex(body.getVisibleName()) == -1) {
throw new InvocationException(InvocationCodes.ACCESS_DENIED);
}
return;
}
}
}
/**
* Get the specified player body by Oid.
*/
protected BodyObject getPlayerByOid (int oid)
{
// verify that they're a player
switch (getMatchType()) {
case GameConfig.PARTY:
// all occupants are players in a party game
break;
default:
if (!IntListUtil.contains(_playerOids, oid)) {
return null; // not a player!
}
break;
}
return getOccupantByOid(oid);
}
/**
* Get the specified occupant body by Oid.
*/
protected BodyObject getOccupantByOid (int oid)
{
if (!_ezObj.occupants.contains(oid)) {
return null;
}
// return the body
return (BodyObject) CrowdServer.omgr.getObject(oid);
}
@Override
protected PlaceObject createPlaceObject ()
{
return new EZGameObject();
}
@Override
protected void didInit ()
{
super.didInit();
// initialize the appropriate turn delegate
if (getMatchType() == GameConfig.PARTY) {
EZPartyTurnDelegate del = new EZPartyTurnDelegate();
_turnDelegate = del;
addDelegate(del);
del.didInit(_config);
} else {
EZSeatedTurnDelegate del = new EZSeatedTurnDelegate();
_turnDelegate = del;
addDelegate(del);
del.didInit(_config);
}
}
@Override
protected void didStartup ()
{
super.didStartup();
_ezObj = (EZGameObject) _plobj;
_ezObj.setEzGameService(
(EZGameMarshaller) CrowdServer.invmgr.registerDispatcher(new EZGameDispatcher(this)));
}
@Override // from PlaceManager
protected void bodyEntered (int bodyOid)
{
super.bodyEntered(bodyOid);
// if we have no controller, then our new friend gets control
if (_ezObj.controllerOid == 0) {
_ezObj.setControllerOid(bodyOid);
}
}
@Override // from PlaceManager
protected void bodyUpdated (OccupantInfo info)
{
super.bodyUpdated(info);
// if the controller just disconnected, reassign control
if (info.status == OccupantInfo.DISCONNECTED && info.bodyOid == _ezObj.controllerOid) {
_ezObj.setControllerOid(getControllerOid());
// if everyone in the room was disconnected and this client just reconnected, it becomes
// the new controller
} else if (_ezObj.controllerOid == 0) {
_ezObj.setControllerOid(info.bodyOid);
}
}
@Override // from PlaceManager
protected void bodyLeft (int bodyOid)
{
super.bodyLeft(bodyOid);
// if this player was the controller, reassign control
if (bodyOid == _ezObj.controllerOid) {
_ezObj.setControllerOid(getControllerOid());
}
// nix any of this player's cookies
if (_ezObj.userCookies != null && _ezObj.userCookies.containsKey(bodyOid)) {
_ezObj.removeFromUserCookies(bodyOid);
}
}
@Override // from PlaceManager
protected void playersAllHere ()
{
switch (getMatchType()) {
default:
case GameConfig.SEATED_GAME:
super.playersAllHere();
break;
case GameConfig.PARTY:
case GameConfig.SEATED_CONTINUOUS:
// the first time the first player calls playerReady() in a party or seated continuous
// game, we start the game; after that it's up to the game to restart itself
if (!_haveAutoStarted && _gameobj.state == EZGameObject.PRE_GAME) {
_haveAutoStarted = true;
startGame();
}
break;
}
}
@Override
protected void didShutdown ()
{
CrowdServer.invmgr.clearDispatcher(_ezObj.ezGameService);
stopTickers();
super.didShutdown();
}
@Override
protected void gameWillStart ()
{
// reset the round id to an initial value. note that we don't distribute the initial value,
// because the super's version of this function will immediately increment it, and then
// distribute the new incremented value.
_ezObj.roundId = 0;
// clear out the turn holder in case we're restarting
_ezObj.setTurnHolder(null);
super.gameWillStart();
}
@Override
protected void gameDidEnd ()
{
stopTickers();
super.gameDidEnd();
// EZ games immediately reset to PRE_GAME after they end so that they can be restarted if
// desired by having all players call playerReady() again
_ezObj.setState(EZGameObject.PRE_GAME);
}
@Override
protected void assignWinners (boolean[] winners)
{
if (_winnerOids != null) {
for (int oid : _winnerOids) {
int index = IntListUtil.indexOf(_playerOids, oid);
if (index >= 0 && index < winners.length) {
winners[index] = true;
}
}
_winnerOids = null;
}
}
/**
* Stop and clear all tickers.
*/
protected void stopTickers ()
{
if (_tickers != null) {
for (Ticker ticker : _tickers.values()) {
ticker.stop();
}
_tickers = null;
}
}
/**
* Returns the oid of a player to whom to assign control of the game or zero if no players
* qualify for control.
*/
protected int getControllerOid ()
{
for (OccupantInfo info : _ezObj.occupantInfo) {
if (info.status != OccupantInfo.DISCONNECTED) {
return info.bodyOid;
}
}
return 0;
}
/**
* Get the cookie manager, and do a bit of other setup.
*/
protected GameCookieManager getCookieManager ()
{
if (_cookMgr == null) {
_cookMgr = createCookieManager();
_ezObj.setUserCookies(new DSet<UserCookie>());
}
return _cookMgr;
}
/**
* Creates the cookie manager we'll use to store user cookies.
*/
protected GameCookieManager createCookieManager ()
{
return new GameCookieManager();
}
/**
* A timer that fires message events to a game.
*/
protected static class Ticker
{
/**
* Create a Ticker.
*/
public Ticker (String name, EZGameObject gameObj)
{
_name = name;
// once we are constructed, we want to avoid calling methods on dobjs.
_oid = gameObj.getOid();
_omgr = gameObj.getManager();
}
public void start (int msOfDelay)
{
_value = 0;
_interval.schedule(0, msOfDelay);
}
public void stop ()
{
_interval.cancel();
}
/**
* The interval that does our work. Note well that this is not a 'safe' interval that
* operates using a RunQueue. This interval instead does something that we happen to know
* is safe for any thread: posting an event to the dobj manager. If we were using a
* RunQueue it would be the same event queue and we would be posted there, wait our turn,
* and then do the same thing: post this event. We just expedite the process.
*/
protected Interval _interval = new Interval() {
public void expired () {
_omgr.postEvent(
new MessageEvent(_oid, EZGameObject.TICKER, new Object[] { _name, _value++ }));
}
};
protected int _oid;
protected DObjectManager _omgr;
protected String _name;
protected int _value;
} // End: static class Ticker
/** A nice casted reference to the game object. */
protected EZGameObject _ezObj;
/** Our turn delegate. */
protected EZGameTurnDelegate _turnDelegate;
/** The map of collections, lazy-initialized. */
protected HashMap<String, ArrayList<byte[]>> _collections;
/** The map of tickers, lazy-initialized. */
protected HashMap<String, Ticker> _tickers;
/** Tracks which cookies are currently being retrieved from the db. */
protected ArrayIntSet _cookieLookups = new ArrayIntSet();
/** The array of winner oids, after the user has filled it in. */
protected int[] _winnerOids;
/** Handles the storage of our user cookies; lazily initialized. */
protected GameCookieManager _cookMgr;
/** Tracks whether or not we've auto-started a non-seated game. Unfortunately there's no way to
* derive this from existing game state. */
protected boolean _haveAutoStarted;
/** The minimum delay a ticker can have. */
protected static final int MIN_TICKER_DELAY = 50;
/** The maximum number of tickers allowed at one time. */
protected static final int MAX_TICKERS = 3;
}
@@ -1,119 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.server;
import com.threerings.ezgame.client.EZGameService;
import com.threerings.presents.client.Client;
import com.threerings.presents.client.InvocationService;
import com.threerings.presents.data.ClientObject;
import com.threerings.presents.server.InvocationException;
import com.threerings.presents.server.InvocationProvider;
/**
* Defines the server-side of the {@link EZGameService}.
*/
public interface EZGameProvider extends InvocationProvider
{
/**
* Handles a {@link EZGameService#addToCollection} request.
*/
public void addToCollection (ClientObject caller, String arg1, byte[][] arg2, boolean arg3, InvocationService.InvocationListener arg4)
throws InvocationException;
/**
* Handles a {@link EZGameService#checkDictionaryWord} request.
*/
public void checkDictionaryWord (ClientObject caller, String arg1, String arg2, String arg3, InvocationService.ResultListener arg4)
throws InvocationException;
/**
* Handles a {@link EZGameService#endGame} request.
*/
public void endGame (ClientObject caller, int[] arg1, InvocationService.InvocationListener arg2)
throws InvocationException;
/**
* Handles a {@link EZGameService#endRound} request.
*/
public void endRound (ClientObject caller, int arg1, InvocationService.InvocationListener arg2)
throws InvocationException;
/**
* Handles a {@link EZGameService#endTurn} request.
*/
public void endTurn (ClientObject caller, int arg1, InvocationService.InvocationListener arg2)
throws InvocationException;
/**
* Handles a {@link EZGameService#getCookie} request.
*/
public void getCookie (ClientObject caller, int arg1, InvocationService.InvocationListener arg2)
throws InvocationException;
/**
* Handles a {@link EZGameService#getDictionaryLetterSet} request.
*/
public void getDictionaryLetterSet (ClientObject caller, String arg1, String arg2, int arg3, InvocationService.ResultListener arg4)
throws InvocationException;
/**
* Handles a {@link EZGameService#getFromCollection} request.
*/
public void getFromCollection (ClientObject caller, String arg1, boolean arg2, int arg3, String arg4, int arg5, InvocationService.ConfirmListener arg6)
throws InvocationException;
/**
* Handles a {@link EZGameService#mergeCollection} request.
*/
public void mergeCollection (ClientObject caller, String arg1, String arg2, InvocationService.InvocationListener arg3)
throws InvocationException;
/**
* Handles a {@link EZGameService#restartGameIn} request.
*/
public void restartGameIn (ClientObject caller, int arg1, InvocationService.InvocationListener arg2)
throws InvocationException;
/**
* Handles a {@link EZGameService#sendMessage} request.
*/
public void sendMessage (ClientObject caller, String arg1, Object arg2, int arg3, InvocationService.InvocationListener arg4)
throws InvocationException;
/**
* Handles a {@link EZGameService#setCookie} request.
*/
public void setCookie (ClientObject caller, byte[] arg1, InvocationService.InvocationListener arg2)
throws InvocationException;
/**
* Handles a {@link EZGameService#setProperty} request.
*/
public void setProperty (ClientObject caller, String arg1, Object arg2, int arg3, boolean arg4, Object arg5, InvocationService.InvocationListener arg6)
throws InvocationException;
/**
* Handles a {@link EZGameService#setTicker} request.
*/
public void setTicker (ClientObject caller, String arg1, int arg2, InvocationService.InvocationListener arg3)
throws InvocationException;
}
@@ -1,12 +0,0 @@
//
// $Id$
package com.threerings.ezgame.server;
public interface EZGameTurnDelegate
{
/**
* Start the next turn, specifying the id of the next turn holder or 0.
*/
public void endTurn (int nextTurnHolderId);
}
@@ -1,175 +0,0 @@
//
// $Id: EZGameTurnDelegate.java 523 2007-12-07 21:41:22Z ray $
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.server;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import com.samskivert.util.RandomUtil;
import com.threerings.util.Name;
import com.threerings.crowd.data.BodyObject;
import com.threerings.crowd.data.PlaceObject;
import com.threerings.crowd.server.PlaceManager;
import com.threerings.parlor.game.server.GameManagerDelegate;
import com.threerings.parlor.turn.data.TurnGameObject;
import com.threerings.parlor.turn.server.TurnGameManager;
/**
* A special turn delegate for seated ez games.
*/
public class EZPartyTurnDelegate extends GameManagerDelegate
implements EZGameTurnDelegate
{
@Override
public void setPlaceManager (PlaceManager plmgr)
{
super.setPlaceManager(plmgr);
_tgmgr = (TurnGameManager) plmgr;
}
@Override
public void didStartup (PlaceObject plobj)
{
super.didStartup(plobj);
_plobj = plobj;
_turnGame = (TurnGameObject) plobj;
}
@Override
public void bodyEntered (int bodyOid)
{
super.bodyEntered(bodyOid);
if (_ordering != null) {
_ordering.add(bodyOid);
}
}
@Override
public void bodyLeft (int bodyOid)
{
super.bodyLeft(bodyOid);
if (_ordering != null) {
_ordering.remove(bodyOid);
}
}
@Override
public void gameDidEnd ()
{
super.gameDidEnd();
// we can forget about any ordering now
_ordering = null;
_currentHolderId = 0;
}
// from EZGameTurnDelegate
public void endTurn (int nextPlayerId)
{
_tgmgr.turnDidEnd();
if (!_turnGame.isInPlay()) {
_turnGame.setTurnHolder(null);
_currentHolderId = 0;
return;
}
// set up the ordering if we haven't done so already
if (_ordering == null) {
createOrdering();
}
// try using the player-specified value
if (nextPlayerId != 0 && setNextTurn(nextPlayerId)) {
return;
}
for (int playerId : _ordering) {
if ((playerId != _currentHolderId) && setNextTurn(playerId)) {
return;
}
}
// we may get to the end without finding a new turn holder. Oh well!
}
/**
* Set the next turn holder to the specified id, returning true on success.
*/
protected boolean setNextTurn (int nextPlayerId)
{
BodyObject nextPlayer = ((EZGameManager) _plmgr).getOccupantByOid(nextPlayerId);
if (nextPlayer == null) {
return false;
}
// if the last turn holder was still in there, move them to the end of the list now
if (_ordering.remove(_currentHolderId)) {
_ordering.add(_currentHolderId);
}
_tgmgr.turnWillStart();
_turnGame.setTurnHolder(nextPlayer.getVisibleName());
_tgmgr.turnDidStart();
_currentHolderId = nextPlayerId;
return true;
}
/**
* Add all the occupant body oids to the _ordering list in a random order.
*/
protected void createOrdering ()
{
ArrayList<Integer> list = new ArrayList<Integer>(_plobj.occupants.size());
for (int ii = _plobj.occupants.size() - 1; ii >= 0; ii--) {
list.add(_plobj.occupants.get(ii));
}
// randomize the list
Collections.shuffle(list, RandomUtil.rand);
// and start out the ordering using that random order
_ordering = new LinkedHashSet<Integer>(list);
}
/** The place object. */
protected PlaceObject _plobj;
/** The game manager for which we are delegating. */
protected TurnGameManager _tgmgr;
/** A reference to our game object. */
protected TurnGameObject _turnGame;
/** Tracks the turn ordering for occupants. Initialized only if turns are used by the game. */
protected LinkedHashSet<Integer> _ordering;
/** The oid of the current turn holder. */
protected int _currentHolderId;
}
@@ -1,84 +0,0 @@
//
// $Id: EZGameTurnDelegate.java 523 2007-12-07 21:41:22Z ray $
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.server;
import com.samskivert.util.ListUtil;
import com.samskivert.util.RandomUtil;
import com.threerings.util.Name;
import com.threerings.crowd.data.BodyObject;
import com.threerings.parlor.turn.server.TurnGameManagerDelegate;
/**
* A special turn delegate for seated ez games.
*/
public class EZSeatedTurnDelegate extends TurnGameManagerDelegate
implements EZGameTurnDelegate
{
// from EZGameTurnDelegate
public void endTurn (int nextPlayerId)
{
_nextPlayerId = nextPlayerId;
endTurn();
}
@Override
protected void setFirstTurnHolder ()
{
// make it nobody's turn
_turnIdx = -1;
}
@Override
protected void setNextTurnHolder ()
{
// if the user-supplied value seems to make sense, use it!
if (_nextPlayerId != 0) {
// clear out _nextPlayerId.
int nextId = _nextPlayerId;
_nextPlayerId = 0;
BodyObject nextPlayer = ((EZGameManager) _plmgr).getPlayerByOid(nextId);
if (nextPlayer != null) {
int index = ListUtil.indexOf(_turnGame.getPlayers(), nextPlayer.getVisibleName());
if (index != -1) {
_turnIdx = index;
return;
}
}
}
// Otherwise, if it's nobody's turn- randomly pick a turn holder
if (_turnIdx == -1) {
assignTurnRandomly();
return;
}
// otherwise, do the default behavior
super.setNextTurnHolder();
}
/** An override next turn holder, or 0. */
protected int _nextPlayerId;
}
@@ -1,115 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.server;
import java.util.prefs.Preferences;
import com.samskivert.io.PersistenceException;
import com.samskivert.jdbc.RepositoryListenerUnit;
import com.samskivert.util.Invoker;
import com.samskivert.util.ResultListener;
import com.threerings.crowd.data.BodyObject;
import com.threerings.crowd.server.CrowdServer;
import com.threerings.ezgame.server.persist.GameCookieRepository;
import static com.threerings.ezgame.server.Log.log;
/**
* Manages access to game cookies.
*/
public class GameCookieManager
{
/**
* Creates a game cookie manager that stores cookies in Java preferences on the local machine.
* This should only be used for developer testing.
*/
public GameCookieManager ()
{
_prefs = Preferences.userRoot().node("gameCookieManager");
}
/**
* Creates a game cookie manager that stores cookies in the supplied repository.
*/
public GameCookieManager (GameCookieRepository repo)
{
_repo = repo;
}
/**
* Get the specified user's cookie.
*/
public void getCookie (final int gameId, final int userId, ResultListener<byte[]> rl)
{
if (userId == 0) {
rl.requestCompleted(null);
return;
}
// use our local prefs if our repository is not initialized
if (_repo == null) {
rl.requestCompleted(_prefs.getByteArray(gameId + ":" + userId, (byte[])null));
return;
}
CrowdServer.invoker.postUnit(new RepositoryListenerUnit<byte[]>("getGameCookie", rl) {
public byte[] invokePersistResult () throws PersistenceException {
return _repo.getCookie(gameId, userId);
}
});
}
/**
* Set the specified user's cookie.
*/
public void setCookie (final int gameId, final int userId, final byte[] cookie)
{
if (userId == 0) {
// fail to save, silently
return;
}
// use our local prefs if our repository is not initialized
if (_repo == null) {
_prefs.putByteArray(gameId + ":" + userId, cookie);
return;
}
CrowdServer.invoker.postUnit(new Invoker.Unit("setGameCookie") {
public boolean invoke () {
try {
_repo.setCookie(gameId, userId, cookie);
} catch (PersistenceException pe) {
log.warning("Unable to save game cookie [pe=" + pe + "].");
}
return false;
}
});
}
/** Our database repository, which is used in real operation. */
protected GameCookieRepository _repo;
/** Our local store, which is used when testing. */
protected Preferences _prefs;
}
@@ -1,33 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.server;
import java.util.logging.Logger;
/**
* Contains the log object.
*/
public class Log
{
/** We dispatch our log messages through this logger. */
public static Logger log = Logger.getLogger("com.threerings.ezgame");
}
@@ -1,100 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.server.persist;
import com.samskivert.jdbc.depot.Key;
import com.samskivert.jdbc.depot.PersistentRecord;
import com.samskivert.jdbc.depot.annotation.Column;
import com.samskivert.jdbc.depot.annotation.Entity;
import com.samskivert.jdbc.depot.annotation.Id;
import com.samskivert.jdbc.depot.expression.ColumnExp;
@Entity(name="GAME_COOKIES")
public class GameCookieRecord extends PersistentRecord
{
// AUTO-GENERATED: FIELDS START
/** The column identifier for the {@link #gameId} field. */
public static final String GAME_ID = "gameId";
/** The qualified column identifier for the {@link #gameId} field. */
public static final ColumnExp GAME_ID_C =
new ColumnExp(GameCookieRecord.class, GAME_ID);
/** The column identifier for the {@link #userId} field. */
public static final String USER_ID = "userId";
/** The qualified column identifier for the {@link #userId} field. */
public static final ColumnExp USER_ID_C =
new ColumnExp(GameCookieRecord.class, USER_ID);
/** The column identifier for the {@link #cookie} field. */
public static final String COOKIE = "cookie";
/** The qualified column identifier for the {@link #cookie} field. */
public static final ColumnExp COOKIE_C =
new ColumnExp(GameCookieRecord.class, COOKIE);
// AUTO-GENERATED: FIELDS END
public static final int SCHEMA_VERSION = 1;
/** The id of the game for which this is a cookie. */
@Id
@Column(name="GAME_ID")
public int gameId;
/** The id of the user for which this is a cookie. */
@Id
@Column(name="USER_ID")
public int userId;
/** The actual cookie, as a byte array. */
@Column(name="COOKIE")
public byte[] cookie;
/** A no-argument constructor for deserialization. */
public GameCookieRecord ()
{
}
/** A constructor for configuring all the fields of this record. */
public GameCookieRecord (int gameId, int userId, byte[] cookie)
{
super();
this.gameId = gameId;
this.userId = userId;
this.cookie = cookie;
}
// AUTO-GENERATED: METHODS START
/**
* Create and return a primary {@link Key} to identify a {@link #GameCookieRecord}
* with the supplied key values.
*/
public static Key<GameCookieRecord> getKey (int gameId, int userId)
{
return new Key<GameCookieRecord>(
GameCookieRecord.class,
new String[] { GAME_ID, USER_ID },
new Comparable[] { gameId, userId });
}
// AUTO-GENERATED: METHODS END
}
@@ -1,71 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.server.persist;
import java.util.Set;
import com.samskivert.io.PersistenceException;
import com.samskivert.jdbc.depot.DepotRepository;
import com.samskivert.jdbc.depot.PersistenceContext;
import com.samskivert.jdbc.depot.PersistentRecord;
/**
* Provides storage services for user cookies used in games.
*/
public class GameCookieRepository extends DepotRepository
{
public GameCookieRepository (PersistenceContext ctx)
throws PersistenceException
{
super(ctx);
}
/**
* Get the specified game cookie, or null if none.
*/
public byte[] getCookie (int gameId, int userId)
throws PersistenceException
{
GameCookieRecord record = load(
GameCookieRecord.class, GameCookieRecord.getKey(gameId, userId));
return record != null ? record.cookie : null;
}
/**
* Set the specified user's game cookie.
*/
public void setCookie (int gameId, int userId, byte[] cookie)
throws PersistenceException
{
if (cookie != null) {
store(new GameCookieRecord(gameId, userId, cookie));
} else {
delete(GameCookieRecord.class, GameCookieRecord.getKey(gameId, userId));
}
}
@Override // from DepotRepository
protected void getManagedRecords (Set<Class<? extends PersistentRecord>> classes)
{
classes.add(GameCookieRecord.class);
}
}
@@ -1,35 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.util;
import com.threerings.util.MessageManager;
import com.threerings.parlor.util.ParlorContext;
/**
* Extends the Parlor context with bits needed by the EZ game framework.
*/
public interface EZGameContext extends ParlorContext
{
/** Returns a message manager that can be used to translate strings. */
public MessageManager getMessageManager ();
}
@@ -1,123 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Array;
import java.util.ArrayList;
/**
* Utility methods for transferring flash properties via
* the presents dobj system.
*/
public class EZObjectMarshaller
{
/**
* Encode the specified object as either a byte[] or a byte[][] if it
* is an array. The specific mechanism of encoding is not important,
* as long as decode returns a clone of the original object.
*
* Currently, cycles in the object graph are preserved on the other end.
* TODO: serialize Externalizable implementations, and take
* into account the ClassLoader.
*/
public static Object encode (Object obj)
{
return encode(obj, true);
}
protected static Object encode (Object obj, boolean encodeArrayElements)
{
if (obj == null) {
return null;
}
if (encodeArrayElements) {
if (obj instanceof Iterable) {
ArrayList<byte[]> list = new ArrayList<byte[]>();
for (Object o : (Iterable) obj) {
list.add((byte[]) encode(o, false));
}
byte[][] retval = new byte[list.size()][];
list.toArray(retval);
return retval;
}
if (obj.getClass().isArray()) {
int length = Array.getLength(obj);
byte[][] retval = new byte[length][];
for (int ii=0; ii < length; ii++) {
retval[ii] = (byte[]) encode(Array.get(obj, ii), false);
}
return retval;
}
}
// TODO: Our own encoding?
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
oos.flush();
return baos.toByteArray();
} catch (IOException ioe) {
// TODO: pass outward?
return null; // just crush the object into nothingness
}
}
// TODO: we may extend this to take the client ezgame's ClassLoader
// and reconstitute custom classes that implement Externalizable
public static Object decode (Object encoded)
{
if (encoded == null) {
return null;
}
if (encoded instanceof byte[][]) {
byte[][] src = (byte[][]) encoded;
Object[] retval = new Object[src.length];
for (int ii=0; ii < src.length; ii++) {
retval[ii] = decode(src[ii]);
}
return retval;
}
try {
ByteArrayInputStream bais =
new ByteArrayInputStream((byte[]) encoded);
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
} catch (ClassNotFoundException cnse) {
return null;
} catch (IOException ioe) {
// TODO: pass outward?
return null; // must not have been that important!
}
}
}
@@ -1,203 +0,0 @@
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/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.ezgame.xml;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.apache.commons.digester.Digester;
import org.apache.commons.digester.ObjectCreateRule;
import org.apache.commons.digester.Rule;
import com.samskivert.util.StringUtil;
import com.samskivert.xml.SetFieldRule;
import com.samskivert.xml.SetNextFieldRule;
import com.samskivert.xml.SetPropertyFieldsRule;
import com.threerings.ezgame.data.AIParameter;
import com.threerings.ezgame.data.ChoiceParameter;
import com.threerings.ezgame.data.FileParameter;
import com.threerings.ezgame.data.GameDefinition;
import com.threerings.ezgame.data.MatchConfig;
import com.threerings.ezgame.data.RangeParameter;
import com.threerings.ezgame.data.TableMatchConfig;
import com.threerings.ezgame.data.ToggleParameter;
import com.threerings.parlor.game.data.GameConfig;
/**
* Parses the XML definition of a game.
*/
public class GameParser
{
public GameParser ()
{
// create and configure our digester
_digester = new Digester() {
public void fatalError (SAXParseException exception)
throws SAXException {
// the standard digester needlessly logs a fatal warning here
if (errorHandler != null) {
errorHandler.fatalError(exception);
}
}
};
// add the rules to parse the GameDefinition and its fields
_digester.addObjectCreate("game", getGameDefinitionClass());
_digester.addRule("game/ident", new SetFieldRule("ident"));
_digester.addRule("game/controller", new SetFieldRule("controller"));
_digester.addRule("game/manager", new SetFieldRule("manager"));
_digester.addRule("game/match", new Rule() {
public void begin (String namespace, String name, Attributes attrs) throws Exception {
String type = attrs.getValue("type");
if (StringUtil.isBlank(type)) {
String errmsg = "<match> block missing type attribute.";
throw new Exception(errmsg);
}
addMatchParsingRules(digester, type);
}
public void end (String namespace, String name) throws Exception {
MatchConfig match = (MatchConfig)digester.pop();
((GameDefinition)digester.peek()).match = match;
}
});
// these rules handle customization parameters
_digester.addRule("game/params", new ObjectCreateRule(ArrayList.class));
_digester.addSetNext("game/params", "setParams", ArrayList.class.getName());
addParameter("game/params/ai", AIParameter.class);
addParameter("game/params/range", RangeParameter.class);
addParameter("game/params/choice", ChoiceParameter.class);
addParameter("game/params/toggle", ToggleParameter.class);
addParameter("game/params/file", FileParameter.class);
// add a rule to put the parsed definition onto our list
_digester.addSetNext("game", "add", Object.class.getName());
}
/**
* Parses a game definition from the supplied XML file.
*
* @exception IOException thrown if an error occurs reading the file.
* @exception SAXException thrown if an error occurs parsing the XML.
*/
public GameDefinition parseGame (File source)
throws IOException, SAXException
{
return parseGame(new FileReader(source));
}
/**
* Parses a game definition from the supplied XML source.
*
* @exception IOException thrown if an error occurs reading the file.
* @exception SAXException thrown if an error occurs parsing the XML.
*/
public GameDefinition parseGame (Reader source)
throws IOException, SAXException
{
// make sure nothing is lingering on the stack from a previous failure
_digester.clear();
// push an array list on the digester which will receive the parsed game definition
ArrayList list = new ArrayList();
_digester.push(list);
_digester.parse(source);
return (list.size() > 0) ? (GameDefinition)list.get(0) : null;
}
/**
* Returns the {@link GameDefinition} class (or derived class) to use when parsing our game
* definition.
*/
protected String getGameDefinitionClass ()
{
return GameDefinition.class.getName();
}
protected void addParameter (String path, Class pclass)
{
_digester.addRule(path, new ObjectCreateRule(pclass));
_digester.addRule(path, new SetPropertyFieldsRule(false));
_digester.addSetNext(path, "add", Object.class.getName());
}
/**
* Adds the rules needed to parse a custom match config, as well as the {@link MatchConfig}
* derived instance itself, based on the supplied type.
*/
protected void addMatchParsingRules (Digester digester, String type)
throws Exception
{
int itype = -1;
try {
itype = Integer.valueOf(type);
} catch (Exception e) {
for (int ii = 0; ii < GameConfig.TYPE_STRINGS.length; ii++) {
if (GameConfig.TYPE_STRINGS[ii].equals(type)) {
itype = ii;
break;
}
}
}
switch (itype) {
case GameConfig.SEATED_GAME:
digester.push(createMatchConfig());
digester.addRule("game/match/min_seats", new SetFieldRule("minSeats"));
digester.addRule("game/match/max_seats", new SetFieldRule("maxSeats"));
digester.addRule("game/match/start_seats", new SetFieldRule("startSeats"));
break;
case GameConfig.PARTY:
// party games are handled by a specially configured table
TableMatchConfig config = createMatchConfig();
config.minSeats = config.maxSeats = config.startSeats = 1;
config.isPartyGame = true;
digester.push(config);
break;
case GameConfig.SEATED_CONTINUOUS:
// TODO
default:
String errmsg = "Unknown match-making config type '" + type + "'.";
throw new Exception(errmsg);
}
}
protected TableMatchConfig createMatchConfig ()
{
return new TableMatchConfig();
}
/** Used to process XML descriptions. */
protected Digester _digester;
}