Hold on to your seats kids, it's another installment of "A Boy and His
Blowtorch". Refactored GameConfig and the EZ game framework, cleaning up some old cruft from GameConfig (which will break other projects and which I'll fix ASAP) and moved the XML based configuration system from ToyBox into EZGame. git-svn-id: svn+ssh://src.earth.threerings.net/vilya/trunk@286 c613c5cb-e716-0410-b11b-feb51c14d237
This commit is contained in:
@@ -93,11 +93,16 @@
|
||||
classname="com.threerings.presents.tools.GenActionScriptTask"/>
|
||||
<!-- now generate the associated files -->
|
||||
<genscript header="lib/SOURCE_HEADER" asroot="src/as">
|
||||
<!-- TODO: expand this to the whole enchilada when we're ready -->
|
||||
<fileset dir="src/java" includes="**/parlor/data/*.java"/>
|
||||
<fileset dir="src/java" includes="**/parlor/**/data/*.java"/>
|
||||
<fileset dir="src/java" includes="**/whirled/data/*.java"/>
|
||||
<fileset dir="src/java" includes="**/whirled/**/data/*.java"/>
|
||||
<fileset dir="src/java">
|
||||
<include name="**/parlor/data/*.java"/>
|
||||
<include name="**/parlor/**/data/*.java"/>
|
||||
<exclude name="**/parlor/game/data/GameConfig.java"/> <!-- fiddly bits -->
|
||||
<exclude name="**/parlor/tourney/**"/>
|
||||
<include name="**/ezgame/data/*.java"/>
|
||||
<include name="**/whirled/data/*.java"/>
|
||||
<include name="**/whirled/**/data/*.java"/>
|
||||
<exclude name="**/whirled/spot/data/Cluster.java"/> <!-- fiddly bits -->
|
||||
</fileset>
|
||||
</genscript>
|
||||
</target>
|
||||
|
||||
|
||||
@@ -27,148 +27,67 @@ import mx.controls.ComboBox;
|
||||
import mx.controls.HSlider;
|
||||
import mx.controls.Label;
|
||||
|
||||
import com.threerings.util.StreamableHashMap;
|
||||
import com.threerings.util.StringUtil;
|
||||
|
||||
import com.threerings.flex.LabeledSlider;
|
||||
|
||||
import com.threerings.parlor.game.client.FlexGameConfigurator;
|
||||
|
||||
import com.threerings.ezgame.data.ChoiceParameter;
|
||||
import com.threerings.ezgame.data.EZGameConfig;
|
||||
import com.threerings.ezgame.data.Parameter;
|
||||
import com.threerings.ezgame.data.RangeParameter;
|
||||
import com.threerings.ezgame.data.ToggleParameter;
|
||||
|
||||
/**
|
||||
* Adds custom configuration of options specified in XML.
|
||||
*/
|
||||
public class EZGameConfigurator extends FlexGameConfigurator
|
||||
{
|
||||
/**
|
||||
* Set XML game configuration options.
|
||||
*/
|
||||
public function setXMLConfig (config :XML) :void
|
||||
// from GameConfigurator
|
||||
override protected function gotGameConfig () :void
|
||||
{
|
||||
var log :Log = Log.getLog(this);
|
||||
super.gotGameConfig();
|
||||
|
||||
for each (var param :XML in config..params.children()) {
|
||||
if (StringUtil.isBlank(param.@ident)) {
|
||||
log.warning("Bad configuration option: no 'ident' in " +
|
||||
param + ", ignoring.");
|
||||
continue;
|
||||
}
|
||||
switch (param.localName().toLowerCase()) {
|
||||
case "range":
|
||||
addRangeOption(param, log);
|
||||
break;
|
||||
|
||||
case "choice":
|
||||
addChoiceOption(param, log);
|
||||
break;
|
||||
|
||||
case "toggle":
|
||||
addToggleOption(param, log);
|
||||
break;
|
||||
|
||||
default:
|
||||
log.warning("Unknown XML configuration option: " + param +
|
||||
", ignoring.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a control that came from parsing our custom option XML.
|
||||
*/
|
||||
protected function addXMLControl (spec :XML, control :UIComponent) :void
|
||||
{
|
||||
var ident :String = String(spec.@ident);
|
||||
var name :String = String(spec.@name);
|
||||
var tip :String = String(spec.@tip);
|
||||
if (StringUtil.isBlank(name)) {
|
||||
name = ident;
|
||||
}
|
||||
|
||||
var lbl :Label = new Label();
|
||||
lbl.text = name + ":";
|
||||
lbl.styleName = "lobbyLabel";
|
||||
lbl.toolTip = tip == "" ? name : tip;
|
||||
control.toolTip = tip == "" ? name : tip;
|
||||
|
||||
addControl(lbl, control);
|
||||
_customConfigs.push(ident, control);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a 'range' option specified in XML
|
||||
*/
|
||||
protected function addRangeOption (spec :XML, log :Log) :void
|
||||
{
|
||||
var min :Number = Number(spec.@minimum);
|
||||
var max :Number = Number(spec.@maximum);
|
||||
var start :Number = Number(spec.@start);
|
||||
if (isNaN(min) || isNaN(max) || isNaN(start)) {
|
||||
log.warning("Unable to parse range specification. " +
|
||||
"Required numeric values: minimum, maximum, start " +
|
||||
"[xml=" + spec + "].");
|
||||
var params :Array = (_config as EZGameConfig).getGameDefinition().params;
|
||||
if (params == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for each (var param :Parameter in params) {
|
||||
if (param is RangeParameter) {
|
||||
var range :RangeParameter = (param as RangeParameter);
|
||||
var slider :HSlider = new HSlider();
|
||||
slider.minimum = min;
|
||||
slider.maximum = max;
|
||||
slider.value = start;
|
||||
slider.minimum = range.minimum;
|
||||
slider.maximum = range.maximum;
|
||||
slider.value = range.start;
|
||||
slider.liveDragging = true;
|
||||
slider.snapInterval = 1;
|
||||
addLabeledControl(param, new LabeledSlider(slider));
|
||||
|
||||
addXMLControl(spec, new LabeledSlider(slider));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a 'choice' option specified in XML
|
||||
*/
|
||||
protected function addChoiceOption (spec :XML, log :Log) :void
|
||||
{
|
||||
if (spec.@choices.length == 0 || spec.@start.length == 0) {
|
||||
log.warning("Unable to parse choice specification. " +
|
||||
"Required 'choices' or 'start' is missing. " +
|
||||
"[xml=" + spec + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
var choiceString :String = String(spec.@choices);
|
||||
var start :String = String(spec.@start);
|
||||
|
||||
var choices :Array = choiceString.split(",");
|
||||
var startDex :int = choices.indexOf(start);
|
||||
} else if (param is ChoiceParameter) {
|
||||
var choice :ChoiceParameter = (param as ChoiceParameter);
|
||||
var startDex :int = choice.choices.indexOf(choice.start);
|
||||
if (startDex == -1) {
|
||||
log.warning("Choice start value does not appear in list of choices "+
|
||||
"[xml=" + spec + "].");
|
||||
return;
|
||||
Log.getLog(this).warning(
|
||||
"Start value does not appear in list of choices [param=" + choice + "].");
|
||||
} else {
|
||||
var combo :ComboBox = new ComboBox();
|
||||
combo.dataProvider = choice.choices;
|
||||
combo.selectedIndex = startDex;
|
||||
addLabeledControl(param, combo);
|
||||
}
|
||||
|
||||
var box :ComboBox = new ComboBox();
|
||||
box.dataProvider = choices;
|
||||
box.selectedIndex = startDex;
|
||||
} else if (param is ToggleParameter) {
|
||||
var check :CheckBox = new CheckBox();
|
||||
check.selected = (param as ToggleParameter).start;
|
||||
addLabeledControl(param, check);
|
||||
|
||||
addXMLControl(spec, box);
|
||||
} else {
|
||||
Log.getLog(this).warning("Unknown parameter in config [param=" + param + "].");
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a 'toggle' option specified in XML
|
||||
*/
|
||||
protected function addToggleOption (spec :XML, log :Log) :void
|
||||
{
|
||||
if (spec.@start.length == 0) {
|
||||
log.warning("Unable to parse toggle specification. " +
|
||||
"Required 'start' is missing. " +
|
||||
"[xml=" + spec + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
var startStr :String = String(spec.@start).toLowerCase();
|
||||
|
||||
var box :CheckBox = new CheckBox();
|
||||
box.selected = ("true" == startStr);
|
||||
|
||||
addXMLControl(spec, box);
|
||||
}
|
||||
|
||||
override protected function flushGameConfig () :void
|
||||
@@ -177,29 +96,48 @@ public class EZGameConfigurator extends FlexGameConfigurator
|
||||
|
||||
// if there were any custom XML configs, flush those as well.
|
||||
if (_customConfigs.length > 0) {
|
||||
var options :Object = {};
|
||||
var params :StreamableHashMap = new StreamableHashMap();
|
||||
|
||||
for (var ii :int = 0; ii < _customConfigs.length; ii += 2) {
|
||||
var ident :String = String(_customConfigs[ii]);
|
||||
var control :UIComponent = (_customConfigs[ii + 1] as UIComponent);
|
||||
if (control is LabeledSlider) {
|
||||
options[ident] = (control as LabeledSlider).slider.value;
|
||||
params.put(ident, (control as LabeledSlider).slider.value);
|
||||
|
||||
} else if (control is CheckBox) {
|
||||
options[ident] = (control as CheckBox).selected;
|
||||
params.put(ident, (control as CheckBox).selected);
|
||||
|
||||
} else if (control is ComboBox) {
|
||||
options[ident] = (control as ComboBox).value;
|
||||
params.put(ident, (control as ComboBox).value);
|
||||
|
||||
} else {
|
||||
Log.getLog(this).warning("Unknow custom config type " + control);
|
||||
}
|
||||
}
|
||||
|
||||
(_config as EZGameConfig).customConfig = options;
|
||||
(_config as EZGameConfig).params = params;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a control that came from parsing our custom option XML.
|
||||
*/
|
||||
protected function addLabeledControl (param :Parameter, control :UIComponent) :void
|
||||
{
|
||||
if (StringUtil.isBlank(param.name)) {
|
||||
param.name = param.ident;
|
||||
}
|
||||
|
||||
var lbl :Label = new Label();
|
||||
lbl.text = param.name + ":";
|
||||
lbl.styleName = "lobbyLabel";
|
||||
lbl.toolTip = param.tip;
|
||||
control.toolTip = param.tip;
|
||||
|
||||
addControl(lbl, control);
|
||||
_customConfigs.push(param.ident, control);
|
||||
}
|
||||
|
||||
/** Contains pairs of identString, control, identString, control.. */
|
||||
protected var _customConfigs :Array = [];
|
||||
}
|
||||
|
||||
@@ -63,12 +63,11 @@ public class EZGamePanel extends Canvas
|
||||
_ezObj = (plobj as EZGameObject);
|
||||
backend = createBackend();
|
||||
|
||||
_gameView = new GameContainer(cfg.gameMedia);
|
||||
_gameView = new GameContainer(cfg.getGameDefinition().getMediaPath(cfg.getGameId()));
|
||||
_gameView.percentWidth = 100;
|
||||
_gameView.percentHeight = 100;
|
||||
backend.setSharedEvents(
|
||||
Loader(_gameView.getMediaContainer().getMedia()).
|
||||
contentLoaderInfo.sharedEvents);
|
||||
Loader(_gameView.getMediaContainer().getMedia()).contentLoaderInfo.sharedEvents);
|
||||
backend.setContainer(_gameView);
|
||||
addChild(_gameView);
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ import com.threerings.util.Iterator;
|
||||
import com.threerings.util.MessageBundle;
|
||||
import com.threerings.util.Name;
|
||||
import com.threerings.util.StringUtil;
|
||||
import com.threerings.util.Wrapped;
|
||||
|
||||
import com.threerings.presents.client.ConfirmAdapter;
|
||||
import com.threerings.presents.client.ResultWrapper;
|
||||
@@ -176,7 +177,14 @@ public class GameControlBackend
|
||||
|
||||
// straight data
|
||||
o["gameData"] = _gameData;
|
||||
o["gameConfig"] = (_ctrl.getPlaceConfig() as EZGameConfig).customConfig;
|
||||
|
||||
// convert our game config from a HashMap to a Dictionary
|
||||
var gameConfig :Object = {};
|
||||
var cfg :EZGameConfig = (_ctrl.getPlaceConfig() as EZGameConfig);
|
||||
cfg.params.forEach(function (key :Object, value :Object) :void {
|
||||
gameConfig[key] = (value is Wrapped) ? Wrapped(value).unwrap() : value;
|
||||
});
|
||||
o["gameConfig"] = gameConfig;
|
||||
|
||||
// functions
|
||||
o["setProperty_v1"] = setProperty_v1;
|
||||
@@ -388,7 +396,7 @@ public class GameControlBackend
|
||||
var uc :UserCookie =
|
||||
(_ezObj.userCookies.get(playerId) as UserCookie);
|
||||
if (uc != null) {
|
||||
callback(uc.cookie);
|
||||
callback(EZObjectMarshaller.decode(uc.cookie));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -901,7 +909,7 @@ public class GameControlBackend
|
||||
delete _cookieCallbacks[cookie.playerId];
|
||||
for each (var fn :Function in arr) {
|
||||
try {
|
||||
fn(cookie.cookie);
|
||||
fn(EZObjectMarshaller.decode(cookie.cookie));
|
||||
} catch (err :Error) {
|
||||
// cope
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
//
|
||||
// $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.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
/**
|
||||
* 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 var choices :TypedArray;
|
||||
|
||||
/** The starting selection. */
|
||||
public var start :String;
|
||||
|
||||
public function ChoiceParameter ()
|
||||
{
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function getDefaultValue () :Object
|
||||
{
|
||||
return start;
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
choices = (ins.readObject() as TypedArray);
|
||||
start = (ins.readField(String) as String);
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
super.writeObject(out);
|
||||
out.writeObject(choices);
|
||||
out.writeField(start);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ package com.threerings.ezgame.data {
|
||||
|
||||
import com.threerings.util.Hashable;
|
||||
import com.threerings.util.MessageBundle;
|
||||
import com.threerings.util.StreamableHashMap;
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
@@ -39,53 +40,45 @@ import com.threerings.ezgame.util.EZObjectMarshaller;
|
||||
* A game config for a simple multiplayer ez game.
|
||||
*/
|
||||
public class EZGameConfig extends GameConfig
|
||||
implements Hashable
|
||||
{
|
||||
/** The name of the game. */
|
||||
public var name :String;
|
||||
/** Our configuration parameters. These will be seeded with the defaults from the game
|
||||
* definition and then configured by the player in the lobby. */
|
||||
public var params :StreamableHashMap = new StreamableHashMap();
|
||||
|
||||
/** If non-zero, a game id used to persistently identify the game.
|
||||
* This could be thought of as a new-style rating id. */
|
||||
public var persistentGameId:int;
|
||||
|
||||
/** The media for the game. In flash, this is the URL to the SWF file. */
|
||||
public var gameMedia :String;
|
||||
|
||||
/** The game type. */
|
||||
public var gameType :int = SEATED_GAME;
|
||||
|
||||
/** Any custom configuration options. */
|
||||
public var customConfig :Object;
|
||||
|
||||
public function EZGameConfig ()
|
||||
public function EZGameConfig (gameId :int = 0, gameDef :GameDefinition = null)
|
||||
{
|
||||
// nothing needed
|
||||
_gameId = gameId;
|
||||
_gameDef = gameDef;
|
||||
}
|
||||
|
||||
override public function getGameType () :int
|
||||
/** Returns the game definition associated with this config instance. */
|
||||
public function getGameDefinition () :GameDefinition
|
||||
{
|
||||
return gameType;
|
||||
return _gameDef;
|
||||
}
|
||||
|
||||
// from abstract GameConfig
|
||||
override public function getBundleName () :String
|
||||
// from GameConfig
|
||||
override public function getGameId () :int
|
||||
{
|
||||
return "general";
|
||||
return _gameId;
|
||||
}
|
||||
|
||||
// TODO
|
||||
//override public function createConfigurator () :GameConfigurator
|
||||
|
||||
|
||||
override public function getGameName () :String
|
||||
// from GameConfig
|
||||
override public function getGameIdent () :String
|
||||
{
|
||||
return MessageBundle.taint(name);
|
||||
return _gameDef.ident;
|
||||
}
|
||||
|
||||
// from PlaceConfig
|
||||
override public function createController () :PlaceController
|
||||
// from GameConfig
|
||||
override public function getMatchType () :int
|
||||
{
|
||||
return new EZGameController();
|
||||
return _gameDef.match.getMatchType();
|
||||
}
|
||||
|
||||
// from GameConfig
|
||||
override public function createConfigurator () :GameConfigurator
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// from abstract PlaceConfig
|
||||
@@ -94,46 +87,40 @@ public class EZGameConfig extends GameConfig
|
||||
throw new Error("Not implemented.");
|
||||
}
|
||||
|
||||
override public function hashCode () :int
|
||||
{
|
||||
return super.hashCode() ^ persistentGameId;
|
||||
}
|
||||
|
||||
override public function equals (other :Object) :Boolean
|
||||
{
|
||||
if (!super.equals(other)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var that :EZGameConfig = (other as EZGameConfig);
|
||||
return (this.persistentGameId == that.persistentGameId) &&
|
||||
(this.gameMedia === that.gameMedia);
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
|
||||
name = (ins.readField(String) as String)
|
||||
persistentGameId = ins.readInt();
|
||||
gameMedia = (ins.readField(String) as String);
|
||||
gameType = ins.readByte();
|
||||
|
||||
customConfig = EZObjectMarshaller.decode(ins.readObject());
|
||||
params = (ins.readObject() as StreamableHashMap);
|
||||
_gameId = ins.readInt();
|
||||
_gameDef = (ins.readObject() as GameDefinition);
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
super.writeObject(out);
|
||||
|
||||
out.writeField(name);
|
||||
out.writeInt(persistentGameId);
|
||||
out.writeField(gameMedia);
|
||||
out.writeByte(gameType);
|
||||
|
||||
out.writeObject(EZObjectMarshaller.encode(customConfig, false));
|
||||
out.writeObject(params);
|
||||
out.writeInt(_gameId);
|
||||
out.writeObject(_gameDef);
|
||||
}
|
||||
|
||||
/** Returns true if this is a party game, false otherwise. */
|
||||
public function isPartyGame () :Boolean
|
||||
{
|
||||
return getMatchType() == PARTY;
|
||||
}
|
||||
|
||||
// from PlaceConfig
|
||||
override public function createController () :PlaceController
|
||||
{
|
||||
return new EZGameController();
|
||||
}
|
||||
|
||||
/** Our game's unique id. */
|
||||
protected var _gameId :int;
|
||||
|
||||
/** Our game definition. */
|
||||
protected var _gameDef :GameDefinition;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
//
|
||||
// $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.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
import com.threerings.io.Streamable;
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
/**
|
||||
* 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 var ident :String;
|
||||
|
||||
/** The class name of the <code>GameController</code> derivation that we use to bootstrap on
|
||||
* the client. */
|
||||
public var controller :String;
|
||||
|
||||
/** The class name of the <code>GameManager</code> derivation that we use to manage the game on
|
||||
* the server. */
|
||||
public var manager :String;
|
||||
|
||||
/** The MD5 digest of the game media file. */
|
||||
public var digest :String;
|
||||
|
||||
/** The configuration of the match-making mechanism. */
|
||||
public var match :MatchConfig;
|
||||
|
||||
/** Parameters used to configure the game itself. */
|
||||
public var params :TypedArray;
|
||||
|
||||
public function GameDefinition ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 function getMediaPath (gameId :int) :String
|
||||
{
|
||||
throw new Error("abstract");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a single player can play this game (possibly against AI opponents), or if
|
||||
* opponents are needed.
|
||||
*/
|
||||
public function isSinglePlayerPlayable () :Boolean
|
||||
{
|
||||
throw new Error("Not implemented");
|
||||
}
|
||||
|
||||
/** Generates a string representation of this instance. */
|
||||
public function toString () :String
|
||||
{
|
||||
return "[ident=" + ident + ", ctrl=" + controller + ", mgr=" + manager +
|
||||
", match=" + match + ", params=" + params + ", digest=" + digest + "]";
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
ident = (ins.readField(String) as String);
|
||||
controller = (ins.readField(String) as String);
|
||||
manager = (ins.readField(String) as String);
|
||||
digest = (ins.readField(String) as String);
|
||||
match = (ins.readObject() as MatchConfig);
|
||||
params = (ins.readObject() as TypedArray);
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
out.writeField(ident);
|
||||
out.writeField(controller);
|
||||
out.writeField(manager);
|
||||
out.writeField(digest);
|
||||
out.writeObject(match);
|
||||
out.writeObject(params);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// $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
|
||||
{
|
||||
public function MatchConfig ()
|
||||
{
|
||||
}
|
||||
|
||||
/** Returns the matchmaking type to use for this game, e.g. {@link GameConfig.SEATED_GAME}. */
|
||||
public function getMatchType () :int
|
||||
{
|
||||
throw new Error("Abstract");
|
||||
}
|
||||
|
||||
/** Returns the minimum number of players needed to play this game. */
|
||||
public function getMinimumPlayers () :int
|
||||
{
|
||||
throw new Error("Abstract");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// $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.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
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 var ident :String;
|
||||
|
||||
/** A human readable name for this configuration parameter. */
|
||||
public var name :String;
|
||||
|
||||
/** A human readable tooltip to display when the mouse is hovered over this configuration
|
||||
* parameter. */
|
||||
public var tip :String;
|
||||
|
||||
public function Parameter ()
|
||||
{
|
||||
}
|
||||
|
||||
public function toString () :String
|
||||
{
|
||||
return ident;
|
||||
}
|
||||
|
||||
public function getDefaultValue () :Object
|
||||
{
|
||||
throw new Error("Abstract");
|
||||
}
|
||||
|
||||
/** Returns the translation key for this parameter's label. */
|
||||
public function getLabel () :String
|
||||
{
|
||||
return "m." + ident;
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
ident = (ins.readField(String) as String);
|
||||
name = (ins.readField(String) as String);
|
||||
tip = (ins.readField(String) as String);
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
out.writeField(ident);
|
||||
out.writeField(name);
|
||||
out.writeField(tip);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,8 +53,7 @@ public class PropertySetEvent extends NamedEvent
|
||||
override public function applyToObject (target :DObject) :Boolean
|
||||
{
|
||||
// since we're in actionscript, we're always on the client
|
||||
_oldValue =
|
||||
EZGameObject(target).applyPropertySet(_name, _data, _index);
|
||||
_oldValue = EZGameObject(target).applyPropertySet(_name, _data, _index);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -63,7 +62,7 @@ public class PropertySetEvent extends NamedEvent
|
||||
*/
|
||||
public function getValue () :Object
|
||||
{
|
||||
return _data;
|
||||
return EZObjectMarshaller.decode(_data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,7 +86,7 @@ public class PropertySetEvent extends NamedEvent
|
||||
{
|
||||
super.readObject(ins);
|
||||
_index = ins.readInt();
|
||||
_data = EZObjectMarshaller.decode(ins.readObject());
|
||||
_data = (ins.readObject() as Object);
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// $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.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
|
||||
/**
|
||||
* 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 var minimum :int;
|
||||
|
||||
/** The maximum value of this parameter. */
|
||||
public var maximum :int;
|
||||
|
||||
/** The starting value for this parameter. */
|
||||
public var start :int;
|
||||
|
||||
public function RangeParameter ()
|
||||
{
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function getDefaultValue () :Object
|
||||
{
|
||||
return start;
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
minimum = ins.readInt();
|
||||
maximum = ins.readInt();
|
||||
start = ins.readInt();
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
super.writeObject(out);
|
||||
out.writeInt(minimum);
|
||||
out.writeInt(maximum);
|
||||
out.writeInt(start);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
//
|
||||
// $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.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
|
||||
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 var minSeats :int;
|
||||
|
||||
/** The starting setting for the number of seats at this table. */
|
||||
public var startSeats :int;
|
||||
|
||||
/** The maximum number of seats at this table. */
|
||||
public var maxSeats :int;
|
||||
|
||||
/** This is set to true if this is a party game. */
|
||||
public var isPartyGame :Boolean;
|
||||
|
||||
public function TableMatchConfig ()
|
||||
{
|
||||
}
|
||||
|
||||
// from MatchConfig
|
||||
override public function getMatchType () :int
|
||||
{
|
||||
return isPartyGame ? GameConfig.PARTY : GameConfig.SEATED_GAME;
|
||||
}
|
||||
|
||||
// from MatchConfig
|
||||
override public function getMinimumPlayers () :int
|
||||
{
|
||||
return minSeats;
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
minSeats = ins.readInt();
|
||||
startSeats = ins.readInt();
|
||||
maxSeats = ins.readInt();
|
||||
isPartyGame = ins.readBoolean();
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
super.writeObject(out);
|
||||
out.writeInt(minSeats);
|
||||
out.writeInt(startSeats);
|
||||
out.writeInt(maxSeats);
|
||||
out.writeBoolean(isPartyGame);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// $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.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
|
||||
/**
|
||||
* Models a parameter that allows the toggling of a single value.
|
||||
*/
|
||||
public class ToggleParameter extends Parameter
|
||||
{
|
||||
/** The starting state for this parameter. */
|
||||
public var start :Boolean;
|
||||
|
||||
public function ToggleParameter ()
|
||||
{
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function getDefaultValue () :Object
|
||||
{
|
||||
return start;
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
start = ins.readBoolean();
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
super.writeObject(out);
|
||||
out.writeBoolean(start);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,16 +28,23 @@ import com.threerings.io.ObjectOutputStream;
|
||||
|
||||
import com.threerings.presents.dobj.DSet_Entry;
|
||||
|
||||
import com.threerings.ezgame.util.EZObjectMarshaller;
|
||||
|
||||
/**
|
||||
* Represents a user's game-specific cookie data.
|
||||
*/
|
||||
public class UserCookie
|
||||
implements DSet_Entry
|
||||
{
|
||||
/** The id of the player that has this cookie. */
|
||||
public var playerId :int;
|
||||
|
||||
/** The decoded cookie value. */
|
||||
public var cookie :Object;
|
||||
/** The cookie value. */
|
||||
public var cookie :ByteArray;
|
||||
|
||||
public function UserCookie (playerId :int = 0, cookie :ByteArray = null)
|
||||
{
|
||||
this.playerId = playerId;
|
||||
this.cookie = cookie;
|
||||
}
|
||||
|
||||
// from DSet_Entry
|
||||
public function getKey () :Object
|
||||
@@ -49,14 +56,14 @@ public class UserCookie
|
||||
public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
playerId = ins.readInt();
|
||||
var ba :ByteArray = (ins.readField(ByteArray) as ByteArray);
|
||||
cookie = EZObjectMarshaller.decode(ba);
|
||||
cookie = (ins.readField(ByteArray) as ByteArray);
|
||||
}
|
||||
|
||||
// from superinterface Streamable
|
||||
public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
throw new Error();
|
||||
out.writeInt(playerId);
|
||||
out.writeField(cookie);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,8 +40,7 @@ import com.threerings.parlor.data.ParlorCodes;
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
|
||||
/**
|
||||
* This class represents a table that is being used to matchmake a game by
|
||||
* the Parlor services.
|
||||
* This class represents a table that is being used to matchmake a game by the Parlor services.
|
||||
*/
|
||||
public class Table
|
||||
implements DSet_Entry, Hashable
|
||||
@@ -49,28 +48,25 @@ public class Table
|
||||
/** The unique identifier for this table. */
|
||||
public var tableId :int;
|
||||
|
||||
/** The object id of the lobby object with which this table is
|
||||
* associated. */
|
||||
/** The object id of the lobby object with which this table is associated. */
|
||||
public var lobbyOid :int;
|
||||
|
||||
/** The oid of the game that was created from this table or -1 if the
|
||||
* table is still in matchmaking mode. */
|
||||
/** The oid of the game that was created from this table or -1 if the table is still in
|
||||
* matchmaking mode. */
|
||||
public var gameOid :int = -1;
|
||||
|
||||
/** An array of the usernames of the occupants of this table (some
|
||||
* slots may not be filled), or null if a party game. */
|
||||
/** An array of the usernames of the occupants of this table (some slots may not be filled), or
|
||||
* null if a party game. */
|
||||
public var occupants :TypedArray;
|
||||
|
||||
/** The body oids of the occupants of this table, or null if a party game.
|
||||
* (This is not propagated to remote instances.) */
|
||||
public /*transient*/ var bodyOids :TypedArray;
|
||||
/** The body oids of the occupants of this table, or null if a party game. (This is not
|
||||
* propagated to remote instances.) */
|
||||
public var bodyOids :TypedArray;
|
||||
|
||||
/** For a running game, the total number of players. For FFA party games,
|
||||
* this is everyone. */
|
||||
/** For a running game, the total number of players. For FFA party games, this is everyone. */
|
||||
public var playerCount :int;
|
||||
|
||||
/** For a running game, the total number of watchers. For FFA party games,
|
||||
* this is always 0. */
|
||||
/** For a running game, the total number of watchers. For FFA party games, this is always 0. */
|
||||
public var watcherCount :int;
|
||||
|
||||
/** The game config for the game that is being matchmade. */
|
||||
@@ -84,6 +80,25 @@ public class Table
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Once a table is ready to play (see {@link #mayBeStarted} and {@link #shouldBeStarted}), the
|
||||
* players array can be fetched using this method. It will return an array containing the
|
||||
* usernames of all of the players in the game, sized properly and with each player in the
|
||||
* appropriate position.
|
||||
*/
|
||||
public function getPlayers () :Array
|
||||
{
|
||||
// create and populate the players array
|
||||
var players :Array = new Array();
|
||||
for (var ii :int = 0; ii < occupants.length; ii++) {
|
||||
if (occupants[ii] != null) {
|
||||
players.push(occupants[ii]);
|
||||
}
|
||||
}
|
||||
|
||||
return players;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the number of players currently occupying this table.
|
||||
*/
|
||||
@@ -101,28 +116,8 @@ public class Table
|
||||
}
|
||||
|
||||
/**
|
||||
* Once a table is ready to play (see {@link #mayBeStarted} and {@link
|
||||
* #shouldBeStarted}), the players array can be fetched using this
|
||||
* method. It will return an array containing the usernames of all of
|
||||
* the players in the game, sized properly and with each player in the
|
||||
* appropriate position.
|
||||
*/
|
||||
public function getPlayers () :Array
|
||||
{
|
||||
// create and populate the players array
|
||||
var players :Array = new Array();
|
||||
for (var ii :int = 0; ii < occupants.length; ii++) {
|
||||
if (occupants[ii] != null) {
|
||||
players.push(occupants[ii]);
|
||||
}
|
||||
}
|
||||
|
||||
return players;
|
||||
}
|
||||
|
||||
/**
|
||||
* For a team game, get the team member indices of the compressed
|
||||
* players array returned by getPlayers().
|
||||
* For a team game, get the team member indices of the compressed players array returned by
|
||||
* getPlayers().
|
||||
*/
|
||||
public function getTeamMemberIndices () :TypedArray /* of Array of int */
|
||||
{
|
||||
@@ -150,98 +145,13 @@ public class Table
|
||||
return newTeams;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Requests to seat the specified user at the specified position in
|
||||
// * this table.
|
||||
// *
|
||||
// * @param position the position in which to seat the user.
|
||||
// * @param occupant the occupant to set.
|
||||
// *
|
||||
// * @return null if the user was successfully seated, a string error
|
||||
// * code explaining the failure if the user was not able to be seated
|
||||
// * at that position.
|
||||
// */
|
||||
// public function setOccupant (position :int, occupant :BodyObject) :String
|
||||
// {
|
||||
// // make sure the requested position is a valid one
|
||||
// if (position >= tconfig.desiredPlayerCount || position < 0) {
|
||||
// return ParlorCodes.INVALID_TABLE_POSITION;
|
||||
// }
|
||||
//
|
||||
// // make sure the requested position is not already occupied
|
||||
// if (occupants[position] != null) {
|
||||
// return ParlorCodes.TABLE_POSITION_OCCUPIED;
|
||||
// }
|
||||
//
|
||||
// // otherwise all is well, stick 'em in
|
||||
// setOccupantPos(position, occupant);
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * This method is used for party games, it does no bounds checking
|
||||
// * or verification of the player's ability to join, if you are unsure
|
||||
// * you should call 'setOccupant'.
|
||||
// */
|
||||
// public function setOccupantPos (position :int, occupant :BodyObject) :void
|
||||
// {
|
||||
// occupants[position] = occupant.getVisibleName();
|
||||
// bodyOids[position] = occupant.getOid();
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Requests that the specified user be removed from their seat at this
|
||||
// * table.
|
||||
// *
|
||||
// * @return true if the user was seated at the table and has now been
|
||||
// * removed, false if the user was never seated at the table in the
|
||||
// * first place.
|
||||
// */
|
||||
// public function clearOccupant (username :Name) :Boolean
|
||||
// {
|
||||
// var dex :int = ArrayUtil.indexOf(occupants, username);
|
||||
// if (dex != -1) {
|
||||
// clearOccupantPos(dex);
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Requests that the user identified by the specified body object id
|
||||
// * be removed from their seat at this table.
|
||||
// *
|
||||
// * @return true if the user was seated at the table and has now been
|
||||
// * removed, false if the user was never seated at the table in the
|
||||
// * first place.
|
||||
// */
|
||||
// public function clearOccupantByOid (bodyOid :int) :Boolean
|
||||
// {
|
||||
// var dex :int = ArrayUtil.indexOf(bodyOids, bodyOid);
|
||||
// if (dex != -1) {
|
||||
// clearOccupantPos(dex);
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Called to clear an occupant at the specified position.
|
||||
// * Only call this method if you know what you're doing.
|
||||
// */
|
||||
// public function clearOccupantPos (position :int) :void
|
||||
// {
|
||||
// occupants[position] = null;
|
||||
// bodyOids[position] = 0;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Returns true if this table has a sufficient number of occupants
|
||||
* that the game can be started.
|
||||
* Returns true if this table has a sufficient number of occupants that the game can be
|
||||
* started.
|
||||
*/
|
||||
public function mayBeStarted () :Boolean
|
||||
{
|
||||
switch (config.getGameType()) {
|
||||
switch (config.getMatchType()) {
|
||||
case GameConfig.SEATED_CONTINUOUS:
|
||||
case GameConfig.PARTY:
|
||||
return true;
|
||||
@@ -270,25 +180,23 @@ public class Table
|
||||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Returns true if sufficient seats are occupied that the game should
|
||||
// * be automatically started.
|
||||
// */
|
||||
// public function shouldBeStarted () :Boolean
|
||||
// {
|
||||
// switch (config.getGameType()) {
|
||||
// case GameConfig.SEATED_CONTINUOUS:
|
||||
// case GameConfig.PARTY:
|
||||
// return true;
|
||||
//
|
||||
// default:
|
||||
// return (tconfig.desiredPlayerCount <= getOccupiedCount());
|
||||
// }
|
||||
// }
|
||||
/**
|
||||
* Returns true if sufficient seats are occupied that the game should be automatically started.
|
||||
*/
|
||||
public function shouldBeStarted () :Boolean
|
||||
{
|
||||
switch (config.getMatchType()) {
|
||||
case GameConfig.SEATED_CONTINUOUS:
|
||||
case GameConfig.PARTY:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return (tconfig.desiredPlayerCount <= getOccupiedCount());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this table is in play, false if it is still being
|
||||
* matchmade.
|
||||
* Returns true if this table is in play, false if it is still being matchmade.
|
||||
*/
|
||||
public function inPlay () :Boolean
|
||||
{
|
||||
@@ -304,8 +212,7 @@ public class Table
|
||||
// from Hashable
|
||||
public function equals (other :Object) :Boolean
|
||||
{
|
||||
return (other is Table) &&
|
||||
(tableId == (other as Table).tableId);
|
||||
return (other is Table) && (tableId == (other as Table).tableId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -327,19 +234,6 @@ public class Table
|
||||
return tableId;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Returns true if there is no one sitting at this table.
|
||||
// */
|
||||
// public function isEmpty () :Boolean
|
||||
// {
|
||||
// for (var ii :int = 0; ii < bodyOids.length; ii++) {
|
||||
// if ((bodyOids[ii] as int) !== 0) {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// from Streamable
|
||||
public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
@@ -356,13 +250,14 @@ public class Table
|
||||
// from Streamable
|
||||
public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
throw new Error();
|
||||
// out.writeInt(tableId);
|
||||
// out.writeInt(lobbyOid);
|
||||
// out.writeInt(gameOid);
|
||||
// out.writeObject(occupants);
|
||||
// out.writeObject(config);
|
||||
// out.writeObject(tconfig);
|
||||
out.writeInt(tableId);
|
||||
out.writeInt(lobbyOid);
|
||||
out.writeInt(gameOid);
|
||||
out.writeObject(occupants);
|
||||
out.writeShort(playerCount);
|
||||
out.writeShort(watcherCount);
|
||||
out.writeObject(config);
|
||||
out.writeObject(tconfig);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -373,7 +268,7 @@ public class Table
|
||||
buf.append("tableId=").append(tableId);
|
||||
buf.append(", lobbyOid=").append(lobbyOid);
|
||||
buf.append(", gameOid=").append(gameOid);
|
||||
buf.append(", occupants=").append(occupants.join());
|
||||
buf.append(", occupants=").append(occupants == null ? "<null?>" : occupants.join());
|
||||
buf.append(", config=").append(config);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,24 +27,21 @@ import com.threerings.io.SimpleStreamableObject;
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
/**
|
||||
* Table configuration parameters for a game that is to be matchmade
|
||||
* using the table services.
|
||||
* Table configuration parameters for a game that is to be matchmade using the table services.
|
||||
*/
|
||||
public class TableConfig extends SimpleStreamableObject
|
||||
{
|
||||
/** The total number of players that are desired for the table.
|
||||
* For team games, this should be set to the total number of players
|
||||
* overall, as teams may be unequal. */
|
||||
/** The total number of players that are desired for the table. For team games, this should be
|
||||
* set to the total number of players overall, as teams may be unequal. */
|
||||
public var desiredPlayerCount :int;
|
||||
|
||||
/** The minimum number of players needed overall (or per-team if a
|
||||
* team-based game) for the game to start at the creator's discretion. */
|
||||
/** The minimum number of players needed overall (or per-team if a team-based game) for the
|
||||
* game to start at the creator's discretion. */
|
||||
public var minimumPlayerCount :int;
|
||||
|
||||
/** If non-null, indicates that this is a team-based game and contains
|
||||
* the team assignments for each player. For example, a game with
|
||||
* three players in two teams- players 0 and 2 versus player 1- would
|
||||
* have { {0, 2}, {1} }; */
|
||||
/** If non-null, indicates that this is a team-based game and contains the team assignments for
|
||||
* each player. For example, a game with three players in two teams- players 0 and 2 versus
|
||||
* player 1- would have { {0, 2}, {1} }; */
|
||||
public var teamMemberIndices :TypedArray;
|
||||
|
||||
/** Whether the table is "private". */
|
||||
|
||||
@@ -31,14 +31,12 @@ import com.threerings.parlor.game.data.GameConfig;
|
||||
import com.threerings.parlor.util.ParlorContext;
|
||||
|
||||
/**
|
||||
* Provides the base from which interfaces can be built to configure games
|
||||
* prior to starting them. Derived classes would extend the base
|
||||
* configurator adding interface elements and wiring them up properly to
|
||||
* allow the user to configure an instance of their game.
|
||||
* Provides the base from which interfaces can be built to configure games prior to starting them.
|
||||
* Derived classes would extend the base configurator adding interface elements and wiring them up
|
||||
* properly to allow the user to configure an instance of their game.
|
||||
*
|
||||
* <p> Clients that use the game configurator will want to instantiate one
|
||||
* based on the class returned from the {@link GameConfig} and then
|
||||
* initialize it with a call to {@link #init}.
|
||||
* <p> Clients that use the game configurator will want to instantiate one based on the class
|
||||
* returned from the {@link GameConfig} and then initialize it with a call to {@link #init}.
|
||||
*/
|
||||
public /*abstract*/ class FlexGameConfigurator extends GameConfigurator
|
||||
{
|
||||
@@ -54,14 +52,12 @@ public /*abstract*/ class FlexGameConfigurator extends GameConfigurator
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a control to the interface. This should be the standard way
|
||||
* that configurator controls are added, but note also that external
|
||||
* entities may add their own controls that are related to the game,
|
||||
* but do not directly alter the game config, so that all the controls
|
||||
* are added in a uniform manner and are well aligned.
|
||||
* Add a control to the interface. This should be the standard way that configurator controls
|
||||
* are added, but note also that external entities may add their own controls that are related
|
||||
* to the game, but do not directly alter the game config, so that all the controls are added
|
||||
* in a uniform manner and are well aligned.
|
||||
*/
|
||||
public function addControl (
|
||||
label :UIComponent, control :UIComponent) :void
|
||||
public function addControl (label :UIComponent, control :UIComponent) :void
|
||||
{
|
||||
var item :HBox = new HBox();
|
||||
item.width = 225;
|
||||
|
||||
@@ -25,20 +25,18 @@ import com.threerings.parlor.game.data.GameConfig;
|
||||
import com.threerings.parlor.util.ParlorContext;
|
||||
|
||||
/**
|
||||
* Provides the base from which interfaces can be built to configure games
|
||||
* prior to starting them. Derived classes would extend the base
|
||||
* configurator adding interface elements and wiring them up properly to
|
||||
* allow the user to configure an instance of their game.
|
||||
* Provides the base from which interfaces can be built to configure games prior to starting
|
||||
* them. Derived classes would extend the base configurator adding interface elements and wiring
|
||||
* them up properly to allow the user to configure an instance of their game.
|
||||
*
|
||||
* <p> Clients that use the game configurator will want to instantiate one
|
||||
* based on the class returned from the {@link GameConfig} and then
|
||||
* initialize it with a call to {@link #init}.
|
||||
* <p> Clients that use the game configurator will want to instantiate one based on the class
|
||||
* returned from the {@link GameConfig} and then initialize it with a call to {@link #init}.
|
||||
*/
|
||||
public /*abstract*/ class GameConfigurator
|
||||
{
|
||||
/**
|
||||
* Initializes this game configurator, creates its user interface
|
||||
* elements and prepares it for display.
|
||||
* Initializes this game configurator, creates its user interface elements and prepares it for
|
||||
* display.
|
||||
*/
|
||||
public function init (ctx :ParlorContext) :void
|
||||
{
|
||||
@@ -57,8 +55,8 @@ public /*abstract*/ class GameConfigurator
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides this configurator with its configuration. It should set up
|
||||
* all of its user interface elements to reflect the configuration.
|
||||
* Provides this configurator with its configuration. It should set up all of its user
|
||||
* interface elements to reflect the configuration.
|
||||
*/
|
||||
public function setGameConfig (config :GameConfig) :void
|
||||
{
|
||||
@@ -68,8 +66,8 @@ public /*abstract*/ class GameConfigurator
|
||||
}
|
||||
|
||||
/**
|
||||
* Derived classes will likely want to override this method and
|
||||
* configure their user interface elements accordingly.
|
||||
* Derived classes will likely want to override this method and configure their user interface
|
||||
* elements accordingly.
|
||||
*/
|
||||
protected function gotGameConfig () :void
|
||||
{
|
||||
@@ -86,10 +84,9 @@ public /*abstract*/ class GameConfigurator
|
||||
}
|
||||
|
||||
/**
|
||||
* Derived classes will want to override this method, flushing values
|
||||
* from the user interface to the game config object so that it is
|
||||
* properly configured prior to being returned to the {@link
|
||||
* #getGameConfig} caller.
|
||||
* Derived classes will want to override this method, flushing values from the user interface
|
||||
* to the game config object so that it is properly configured prior to being returned to the
|
||||
* {@link #getGameConfig} caller.
|
||||
*/
|
||||
protected function flushGameConfig () :void
|
||||
{
|
||||
|
||||
@@ -294,9 +294,9 @@ public /*abstract*/ class GameController extends PlaceController
|
||||
/**
|
||||
* Convenience method to determine the type of game.
|
||||
*/
|
||||
protected function getGameType () :int
|
||||
protected function getMatchType () :int
|
||||
{
|
||||
return _gconfig.getGameType();
|
||||
return _gconfig.getMatchType();
|
||||
}
|
||||
|
||||
/** A reference to the active parlor context. */
|
||||
|
||||
@@ -37,48 +37,43 @@ import com.threerings.parlor.client.TableConfigurator;
|
||||
import com.threerings.parlor.game.client.GameConfigurator;
|
||||
|
||||
/**
|
||||
* The game config class encapsulates the configuration information for a
|
||||
* particular type of game. The hierarchy of game config objects mimics the
|
||||
* hierarchy of game managers and controllers. Both the game manager and game
|
||||
* controller are provided with the game config object when the game is
|
||||
* created.
|
||||
* The game config class encapsulates the configuration information for a particular type of
|
||||
* game. The hierarchy of game config objects mimics the hierarchy of game managers and
|
||||
* controllers. Both the game manager and game controller are provided with the game config object
|
||||
* when the game is created.
|
||||
*
|
||||
* <p> The game config object is also the mechanism used to instantiate the
|
||||
* appropriate game manager and controller. Every game must have an associated
|
||||
* game config derived class that overrides {@link #createController} and
|
||||
* {@link #getManagerClassName}, returning the appropriate game controller and
|
||||
* manager class for that game. Thus the entire chain of events that causes a
|
||||
* particular game to be created is the construction of the appropriate game
|
||||
* config instance which is provided to the server as part of an invitation or
|
||||
* via some other matchmaking mechanism.
|
||||
* <p> The game config object is also the mechanism used to instantiate the appropriate game
|
||||
* manager and controller. Every game must have an associated game config derived class that
|
||||
* overrides {@link #createController} and {@link #getManagerClassName}, returning the appropriate
|
||||
* game controller and manager class for that game. Thus the entire chain of events that causes a
|
||||
* particular game to be created is the construction of the appropriate game config instance which
|
||||
* is provided to the server as part of an invitation or via some other matchmaking mechanism.
|
||||
*/
|
||||
public /*abstract*/ class GameConfig extends PlaceConfig
|
||||
implements Cloneable, Hashable
|
||||
{
|
||||
/** Game type constant: a game that is started with a list of players,
|
||||
* and those are the only players that may play. */
|
||||
/** Game type constant: a game that is started with a list of players, and those are the only
|
||||
* players that may play. */
|
||||
public static const SEATED_GAME :int = 0;
|
||||
|
||||
/** Game type constant: a game that starts immediately, but only has
|
||||
* a certain number of player slots. Users enter the game room, and
|
||||
* then choose where to sit. */
|
||||
/** Game type constant: a game that starts immediately, but only has a certain number of player
|
||||
* slots. Users enter the game room, and then choose where to sit. */
|
||||
public static const SEATED_CONTINUOUS :int = 1;
|
||||
|
||||
/** Game type constant: a game that starts immediately, and every
|
||||
* user that enters is a player. */
|
||||
/** Game type constant: a game that starts immediately, and every user that enters is a
|
||||
* player. */
|
||||
public static const PARTY :int = 2;
|
||||
|
||||
/** The usernames of the players involved in this game, or an empty
|
||||
* array if such information is not needed by this particular game. */
|
||||
/** The usernames of the players involved in this game, or an empty array if such information
|
||||
* is not needed by this particular game. */
|
||||
public var players :TypedArray = TypedArray.create(Name);
|
||||
|
||||
/** Indicates whether or not this game is rated. */
|
||||
public var rated :Boolean = true;
|
||||
|
||||
/** Configurations for AIs to be used in this game. Slots with real
|
||||
* players should be null and slots with AIs should contain
|
||||
* configuration for those AIs. A null array indicates no use of AIs
|
||||
* at all. */
|
||||
/** Configurations for AIs to be used in this game. Slots with real players should be null and
|
||||
* slots with AIs should contain configuration for those AIs. A null array indicates no use of
|
||||
* AIs at all. */
|
||||
public var ais :TypedArray = TypedArray.create(GameAI);
|
||||
|
||||
public function GameConfig ()
|
||||
@@ -87,27 +82,31 @@ public /*abstract*/ class GameConfig extends PlaceConfig
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of game.
|
||||
* Returns a numeric identifier for this game class. This may be used to track persisent
|
||||
* information on a per-game basis.
|
||||
*/
|
||||
public function getGameType () :int
|
||||
public function getGameId () :int
|
||||
{
|
||||
return SEATED_GAME;
|
||||
throw new Error("abstract");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the message bundle identifier for the bundle that should be
|
||||
* used to translate the translatable strings used to describe the
|
||||
* game config parameters.
|
||||
*/
|
||||
public /*abstract*/ function getBundleName () :String
|
||||
public function getGameIdent () :String
|
||||
{
|
||||
throw new Error("abstract");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a configurator that can be used to create a user interface
|
||||
* for configuring this instance prior to starting the game. If no
|
||||
* configuration is necessary, this method should return null.
|
||||
* Get the type of game.
|
||||
*/
|
||||
public function getMatchType () :int
|
||||
{
|
||||
return SEATED_GAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a configurator that can be used to create a user interface for configuring this
|
||||
* instance prior to starting the game. If no configuration is necessary, this method should
|
||||
* return null.
|
||||
*/
|
||||
public /*abstract*/ function createConfigurator () :GameConfigurator
|
||||
{
|
||||
@@ -115,8 +114,8 @@ public /*abstract*/ class GameConfig extends PlaceConfig
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a table configurator for initializing 'table' properties
|
||||
* of the game. The default implementation returns null.
|
||||
* Creates a table configurator for initializing 'table' properties of the game. The default
|
||||
* implementation returns null.
|
||||
*/
|
||||
public function createTableConfigurator () :TableConfigurator
|
||||
{
|
||||
@@ -124,34 +123,13 @@ public /*abstract*/ class GameConfig extends PlaceConfig
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a translatable label describing this game.
|
||||
*/
|
||||
public function getGameName () :String
|
||||
{
|
||||
// the whole getRatingTypeId(), getGameName(), getBundleName()
|
||||
// business should be cleaned up. we should have getGameIdent()
|
||||
// and everything should have a default implementation using that
|
||||
return "m." + getBundleName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the game rating type, if the system uses such things.
|
||||
*/
|
||||
public function getRatingTypeId () :int
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a hashcode for this game config object that supports our
|
||||
* {@link #equals} implementation. Objects that are equal should have
|
||||
* the same hashcode.
|
||||
* Computes a hashcode for this game config object that supports our {@link #equals}
|
||||
* implementation. Objects that are equal should have the same hashcode.
|
||||
*/
|
||||
public function hashCode () :int
|
||||
{
|
||||
// look ma, it's so sophisticated!
|
||||
return StringUtil.hashCode(ClassUtil.getClassName(this)) +
|
||||
(rated ? 1 : 0);
|
||||
return StringUtil.hashCode(ClassUtil.getClassName(this)) + (rated ? 1 : 0);
|
||||
}
|
||||
|
||||
// from Cloneable
|
||||
@@ -161,30 +139,27 @@ public /*abstract*/ class GameConfig extends PlaceConfig
|
||||
copy.players = this.players;
|
||||
copy.rated = this.rated;
|
||||
copy.ais = this.ais;
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this game config object is equal to the supplied
|
||||
* object (meaning it is also a game config object and its
|
||||
* configuration settings are the same as ours).
|
||||
* Returns true if this game config object is equal to the supplied object (meaning it is also
|
||||
* a game config object and its configuration settings are the same as ours).
|
||||
*/
|
||||
public function equals (other :Object) :Boolean
|
||||
{
|
||||
// make sure they're of the same class
|
||||
if (ClassUtil.isSameClass(other, this)) {
|
||||
var that :GameConfig = GameConfig(other);
|
||||
return this.rated == that.rated;
|
||||
|
||||
return this.getGameId() == that.getGameId() && this.rated == that.rated;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an Array of strings that describe the configuration of this
|
||||
* game. Default implementation returns an empty array.
|
||||
* Returns an Array of strings that describe the configuration of this game. Default
|
||||
* implementation returns an empty array.
|
||||
*/
|
||||
public function getDescription () :Array
|
||||
{
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
//
|
||||
// $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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,309 @@
|
||||
//
|
||||
// $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;
|
||||
}
|
||||
@@ -38,7 +38,6 @@ import com.threerings.crowd.client.PlaceView;
|
||||
import com.threerings.crowd.data.PlaceObject;
|
||||
import com.threerings.crowd.util.CrowdContext;
|
||||
|
||||
import com.threerings.ezgame.data.EZGameConfig;
|
||||
import com.threerings.ezgame.data.EZGameObject;
|
||||
|
||||
import com.threerings.ezgame.Game;
|
||||
@@ -56,16 +55,17 @@ public class EZGamePanel extends JPanel
|
||||
// add a listener so that we hear about all new children
|
||||
addContainerListener(this);
|
||||
|
||||
EZGameConfig cfg = (EZGameConfig) ctrl.getPlaceConfig();
|
||||
try {
|
||||
_gameView = (Component) Class.forName(cfg.gameMedia).newInstance();
|
||||
add(_gameView);
|
||||
} catch (RuntimeException re) {
|
||||
throw re;
|
||||
// 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);
|
||||
}
|
||||
// } catch (Exception e) {
|
||||
// throw new RuntimeException(e);
|
||||
// }
|
||||
|
||||
// TODO: Add a standard chat display?
|
||||
//addChild(new ChatDisplayBox(ctx));
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// $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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
//
|
||||
// $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;
|
||||
}
|
||||
}
|
||||
@@ -21,90 +21,80 @@
|
||||
|
||||
package com.threerings.ezgame.data;
|
||||
|
||||
import com.threerings.util.MessageBundle;
|
||||
|
||||
import com.threerings.crowd.client.PlaceController;
|
||||
import com.threerings.util.StreamableHashMap;
|
||||
|
||||
import com.threerings.parlor.game.client.GameConfigurator;
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
|
||||
import com.threerings.ezgame.client.EZGameController;
|
||||
import com.threerings.ezgame.client.EZGameConfigurator;
|
||||
|
||||
/**
|
||||
* A game config for a simple multiplayer game.
|
||||
*/
|
||||
public class EZGameConfig extends GameConfig
|
||||
{
|
||||
/** The name of the game. */
|
||||
public String name;
|
||||
/** 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>();
|
||||
|
||||
/** If non-zero, a game id used to persistently identify the game.
|
||||
* This could be thought of as a new-style rating id. */
|
||||
public int persistentGameId;
|
||||
|
||||
/** The media for the game. In flash this is the URL to the SWF file.
|
||||
* In Java, this will be a class name, or maybe a Jar. TODO? */
|
||||
public String gameMedia;
|
||||
|
||||
/** The game type. */
|
||||
public byte gameType = SEATED_GAME;
|
||||
|
||||
/** Custom configuration for the game. May only be interpretable on the
|
||||
* client. */
|
||||
public Object customConfig;
|
||||
|
||||
@Override
|
||||
public byte getGameType ()
|
||||
/** A zero argument constructor used when unserializing. */
|
||||
public EZGameConfig ()
|
||||
{
|
||||
return gameType;
|
||||
}
|
||||
|
||||
// from abstract GameConfig
|
||||
public String getBundleName ()
|
||||
/** Constructs a game config based on the supplied game definition. */
|
||||
public EZGameConfig (int gameId, GameDefinition gameDef)
|
||||
{
|
||||
return "general";
|
||||
_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());
|
||||
}
|
||||
}
|
||||
|
||||
// from abstract GameConfig
|
||||
/**
|
||||
* 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 ()
|
||||
{
|
||||
// TODO
|
||||
return null;
|
||||
return new EZGameConfigurator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGameName ()
|
||||
{
|
||||
return MessageBundle.taint(name);
|
||||
}
|
||||
|
||||
@Override // from PlaceConfig
|
||||
public PlaceController createController ()
|
||||
{
|
||||
return new EZGameController();
|
||||
}
|
||||
|
||||
// from abstract PlaceConfig
|
||||
@Override // from GameConfig
|
||||
public String getManagerClassName ()
|
||||
{
|
||||
return "com.threerings.ezgame.server.EZGameManager";
|
||||
return _gameDef.manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals (Object other)
|
||||
{
|
||||
if (!super.equals(other)) {
|
||||
return false;
|
||||
}
|
||||
/** Our game's unique id. */
|
||||
protected int _gameId;
|
||||
|
||||
EZGameConfig that = (EZGameConfig) other;
|
||||
return this.persistentGameId == that.persistentGameId &&
|
||||
this.gameMedia.equals(that.gameMedia);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode ()
|
||||
{
|
||||
return super.hashCode() ^ persistentGameId;
|
||||
}
|
||||
/** Our game definition. */
|
||||
protected GameDefinition _gameDef;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// $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 "";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
//
|
||||
// $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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// $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 ();
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// $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);
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ 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;
|
||||
@@ -34,8 +35,7 @@ import com.threerings.presents.dobj.NamedEvent;
|
||||
import com.threerings.ezgame.util.EZObjectMarshaller;
|
||||
|
||||
/**
|
||||
* Represents a property change on the actionscript object we
|
||||
* use in EZGameObject.
|
||||
* Represents a property change on the actionscript object we use in EZGameObject.
|
||||
*/
|
||||
public class PropertySetEvent extends NamedEvent
|
||||
{
|
||||
@@ -47,17 +47,16 @@ public class PropertySetEvent extends NamedEvent
|
||||
/**
|
||||
* Create a PropertySetEvent.
|
||||
*/
|
||||
public PropertySetEvent (
|
||||
int targetOid, String propName, Object value, int index, Object oldValue)
|
||||
public PropertySetEvent (int targetOid, String propName, Object value, int index, Object ovalue)
|
||||
{
|
||||
super(targetOid, propName);
|
||||
_data = value;
|
||||
_index = index;
|
||||
_oldValue = oldValue;
|
||||
_oldValue = ovalue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value that was set for the property.
|
||||
* Returns the value that was set for the property.
|
||||
*/
|
||||
public Object getValue ()
|
||||
{
|
||||
@@ -65,7 +64,7 @@ public class PropertySetEvent extends NamedEvent
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the old value.
|
||||
* Returns the old value.
|
||||
*/
|
||||
public Object getOldValue ()
|
||||
{
|
||||
@@ -73,7 +72,7 @@ public class PropertySetEvent extends NamedEvent
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the index, or -1 if not applicable.
|
||||
* Returns the index, or -1 if not applicable.
|
||||
*/
|
||||
public int getIndex ()
|
||||
{
|
||||
@@ -102,7 +101,7 @@ public class PropertySetEvent extends NamedEvent
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override @ActionScript(name="toStringBuf")
|
||||
protected void toString (StringBuilder buf)
|
||||
{
|
||||
buf.append("PropertySetEvent ");
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
//
|
||||
// $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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// $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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// $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;
|
||||
}
|
||||
}
|
||||
@@ -58,9 +58,8 @@ import com.threerings.parlor.game.server.GameManager;
|
||||
|
||||
import com.threerings.parlor.turn.server.TurnGameManager;
|
||||
|
||||
import com.threerings.ezgame.data.EZGameConfig;
|
||||
import com.threerings.ezgame.data.EZGameObject;
|
||||
import com.threerings.ezgame.data.EZGameMarshaller;
|
||||
import com.threerings.ezgame.data.EZGameObject;
|
||||
import com.threerings.ezgame.data.PropertySetEvent;
|
||||
import com.threerings.ezgame.data.UserCookie;
|
||||
|
||||
@@ -355,7 +354,7 @@ public class EZGameManager extends GameManager
|
||||
throw new InvocationException(INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
gcm.getCookie(getPersistentGameId(), body, new ResultListener<byte[]>() {
|
||||
gcm.getCookie(_gameconfig.getGameId(), body, new ResultListener<byte[]>() {
|
||||
public void requestCompleted (byte[] result) {
|
||||
// Result may be null: that's ok, it means we've looked up the user's
|
||||
// nonexistant cookie. Only set the cookie if the playerIndex is still in the
|
||||
@@ -391,7 +390,7 @@ public class EZGameManager extends GameManager
|
||||
_gameObj.addToUserCookies(cookie);
|
||||
}
|
||||
|
||||
gcm.setCookie(getPersistentGameId(), caller, value);
|
||||
gcm.setCookie(_gameconfig.getGameId(), caller, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -442,26 +441,13 @@ public class EZGameManager extends GameManager
|
||||
new PropertySetEvent(_gameObj.getOid(), propName, value, index, oldValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the game id of this ezgame, as set in the config.
|
||||
*/
|
||||
protected int getPersistentGameId ()
|
||||
throws InvocationException
|
||||
{
|
||||
int id = ((EZGameConfig) _config).persistentGameId;
|
||||
if (id == 0) {
|
||||
throw new InvocationException("Persistent game id not set.");
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that the specified user has access to do things in the game.
|
||||
*/
|
||||
protected void validateUser (ClientObject caller)
|
||||
throws InvocationException
|
||||
{
|
||||
switch (getGameType()) {
|
||||
switch (getMatchType()) {
|
||||
case GameConfig.PARTY:
|
||||
return; // always validate.
|
||||
|
||||
@@ -495,7 +481,7 @@ public class EZGameManager extends GameManager
|
||||
protected BodyObject getPlayerByOid (int oid)
|
||||
{
|
||||
// verify that they're a player
|
||||
switch (getGameType()) {
|
||||
switch (getMatchType()) {
|
||||
case GameConfig.PARTY:
|
||||
// all occupants are players in a party game
|
||||
break;
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// $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 ();
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
//
|
||||
// $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());
|
||||
_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;
|
||||
}
|
||||
@@ -40,24 +40,20 @@ public interface ParlorCodes extends InvocationCodes
|
||||
/** The response code for a countered invitation. */
|
||||
public static final int INVITATION_COUNTERED = 2;
|
||||
|
||||
/** An error code explaining that an invitation was rejected because
|
||||
* the invited user was not online at the time the invitation was
|
||||
* received. */
|
||||
/** An error code explaining that an invitation was rejected because the invited user was not
|
||||
* online at the time the invitation was received. */
|
||||
public static final String INVITEE_NOT_ONLINE = "m.invitee_not_online";
|
||||
|
||||
/** An error code returned when a user requests to join a table that
|
||||
* doesn't exist. */
|
||||
/** An error code returned when a user requests to join a table that doesn't exist. */
|
||||
public static final String NO_SUCH_TABLE = "m.no_such_table";
|
||||
|
||||
/** An error code returned when a user requests to join a table at a
|
||||
* position that is not valid. */
|
||||
public static final String INVALID_TABLE_POSITION =
|
||||
"m.invalid_table_position";
|
||||
/** An error code returned when a user requests to join a table at a position that is not
|
||||
* valid. */
|
||||
public static final String INVALID_TABLE_POSITION = "m.invalid_table_position";
|
||||
|
||||
/** An error code returned when a user requests to join a table in a
|
||||
* position that is already occupied. */
|
||||
public static final String TABLE_POSITION_OCCUPIED =
|
||||
"m.table_position_occupied";
|
||||
/** An error code returned when a user requests to join a table in a position that is already
|
||||
* occupied. */
|
||||
public static final String TABLE_POSITION_OCCUPIED = "m.table_position_occupied";
|
||||
|
||||
/** An error code returned when a user requests to leave a table that
|
||||
* they were not sitting at in the first place. */
|
||||
|
||||
@@ -36,8 +36,7 @@ import com.threerings.parlor.data.ParlorCodes;
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
|
||||
/**
|
||||
* This class represents a table that is being used to matchmake a game by
|
||||
* the Parlor services.
|
||||
* This class represents a table that is being used to matchmake a game by the Parlor services.
|
||||
*/
|
||||
public class Table
|
||||
implements DSet.Entry, ParlorCodes
|
||||
@@ -45,28 +44,25 @@ public class Table
|
||||
/** The unique identifier for this table. */
|
||||
public int tableId;
|
||||
|
||||
/** The object id of the lobby object with which this table is
|
||||
* associated. */
|
||||
/** The object id of the lobby object with which this table is associated. */
|
||||
public int lobbyOid;
|
||||
|
||||
/** The oid of the game that was created from this table or -1 if the
|
||||
* table is still in matchmaking mode. */
|
||||
/** The oid of the game that was created from this table or -1 if the table is still in
|
||||
* matchmaking mode. */
|
||||
public int gameOid = -1;
|
||||
|
||||
/** An array of the usernames of the occupants of this table (some
|
||||
* slots may not be filled), or null if a party game. */
|
||||
/** An array of the usernames of the occupants of this table (some slots may not be filled), or
|
||||
* null if a party game. */
|
||||
public Name[] occupants;
|
||||
|
||||
/** The body oids of the occupants of this table, or null if a party game.
|
||||
* (This is not propagated to remote instances.) */
|
||||
/** The body oids of the occupants of this table, or null if a party game. (This is not
|
||||
* propagated to remote instances.) */
|
||||
public transient int[] bodyOids;
|
||||
|
||||
/** For a running game, the total number of players. For FFA party games,
|
||||
* this is everyone. */
|
||||
/** For a running game, the total number of players. For FFA party games, this is everyone. */
|
||||
public short playerCount;
|
||||
|
||||
/** For a running game, the total number of watchers. For FFA party games,
|
||||
* this is always 0. */
|
||||
/** For a running game, the total number of watchers. For FFA party games, this is always 0. */
|
||||
public short watcherCount;
|
||||
|
||||
/** The game config for the game that is being matchmade. */
|
||||
@@ -83,15 +79,13 @@ public class Table
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a new table instance, and assigns it the next monotonically
|
||||
* increasing table id.
|
||||
* Initializes a new table instance, and assigns it the next monotonically increasing table id.
|
||||
*
|
||||
* @param lobbyOid the object id of the lobby in which this table is
|
||||
* to live.
|
||||
* @param lobbyOid the object id of the lobby in which this table is to live.
|
||||
* @param tconfig the table configuration for this table.
|
||||
* @param config the configuration of the game being matchmade by this
|
||||
* table.
|
||||
* @param config the configuration of the game being matchmade by this table.
|
||||
*/
|
||||
@ActionScript(omit=true)
|
||||
public void init (int lobbyOid, TableConfig tconfig, GameConfig config)
|
||||
{
|
||||
// assign a unique table id
|
||||
@@ -105,7 +99,7 @@ public class Table
|
||||
this.config = config;
|
||||
|
||||
// make room for the maximum number of players
|
||||
if (config.getGameType() != GameConfig.PARTY) {
|
||||
if (config.getMatchType() != GameConfig.PARTY) {
|
||||
occupants = new Name[tconfig.desiredPlayerCount];
|
||||
bodyOids = new int[occupants.length];
|
||||
|
||||
@@ -121,6 +115,7 @@ public class Table
|
||||
/**
|
||||
* Returns true if there is no one sitting at this table.
|
||||
*/
|
||||
@ActionScript(omit=true)
|
||||
public boolean isEmpty ()
|
||||
{
|
||||
for (int i = 0; i < bodyOids.length; i++) {
|
||||
@@ -148,21 +143,20 @@ public class Table
|
||||
}
|
||||
|
||||
/**
|
||||
* Once a table is ready to play (see {@link #mayBeStarted} and {@link
|
||||
* #shouldBeStarted}), the players array can be fetched using this
|
||||
* method. It will return an array containing the usernames of all of
|
||||
* the players in the game, sized properly and with each player in the
|
||||
* Once a table is ready to play (see {@link #mayBeStarted} and {@link #shouldBeStarted}), the
|
||||
* players array can be fetched using this method. It will return an array containing the
|
||||
* usernames of all of the players in the game, sized properly and with each player in the
|
||||
* appropriate position.
|
||||
*/
|
||||
public Name[] getPlayers ()
|
||||
{
|
||||
// seated party games need a spot for every seat
|
||||
if (GameConfig.SEATED_CONTINUOUS == config.getGameType()) {
|
||||
if (GameConfig.SEATED_CONTINUOUS == config.getMatchType()) {
|
||||
return new Name[tconfig.desiredPlayerCount];
|
||||
}
|
||||
|
||||
// FFA party games have 0-length players array, and non-party
|
||||
// games will have the players who are ready-to-go for the game start.
|
||||
// FFA party games have 0-length players array, and non-party games will have the players
|
||||
// who are ready-to-go for the game start.
|
||||
Name[] players = new Name[getOccupiedCount()];
|
||||
if (occupants != null) {
|
||||
for (int ii = 0, dex = 0; ii < occupants.length; ii++) {
|
||||
@@ -176,8 +170,8 @@ public class Table
|
||||
}
|
||||
|
||||
/**
|
||||
* For a team game, get the team member indices of the compressed
|
||||
* players array returned by getPlayers().
|
||||
* For a team game, get the team member indices of the compressed players array returned by
|
||||
* getPlayers().
|
||||
*/
|
||||
public int[][] getTeamMemberIndices ()
|
||||
{
|
||||
@@ -205,16 +199,15 @@ public class Table
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests to seat the specified user at the specified position in
|
||||
* this table.
|
||||
* Requests to seat the specified user at the specified position in this table.
|
||||
*
|
||||
* @param position the position in which to seat the user.
|
||||
* @param occupant the occupant to set.
|
||||
*
|
||||
* @return null if the user was successfully seated, a string error
|
||||
* code explaining the failure if the user was not able to be seated
|
||||
* at that position.
|
||||
* @return null if the user was successfully seated, a string error code explaining the failure
|
||||
* if the user was not able to be seated at that position.
|
||||
*/
|
||||
@ActionScript(omit=true)
|
||||
public String setOccupant (int position, BodyObject occupant)
|
||||
{
|
||||
// make sure the requested position is a valid one
|
||||
@@ -233,10 +226,10 @@ public class Table
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used for party games, it does no bounds checking
|
||||
* or verification of the player's ability to join, if you are unsure
|
||||
* you should call 'setOccupant'.
|
||||
* This method is used for party games, it does no bounds checking or verification of the
|
||||
* player's ability to join, if you are unsure you should call 'setOccupant'.
|
||||
*/
|
||||
@ActionScript(omit=true)
|
||||
public void setOccupantPos (int position, BodyObject occupant)
|
||||
{
|
||||
occupants[position] = occupant.getVisibleName();
|
||||
@@ -244,13 +237,12 @@ public class Table
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that the specified user be removed from their seat at this
|
||||
* table.
|
||||
* Requests that the specified user be removed from their seat at this table.
|
||||
*
|
||||
* @return true if the user was seated at the table and has now been
|
||||
* removed, false if the user was never seated at the table in the
|
||||
* first place.
|
||||
* @return true if the user was seated at the table and has now been removed, false if the user
|
||||
* was never seated at the table in the first place.
|
||||
*/
|
||||
@ActionScript(omit=true)
|
||||
public boolean clearOccupant (Name username)
|
||||
{
|
||||
if (occupants != null) {
|
||||
@@ -265,13 +257,13 @@ public class Table
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that the user identified by the specified body object id
|
||||
* be removed from their seat at this table.
|
||||
* Requests that the user identified by the specified body object id be removed from their seat
|
||||
* at this table.
|
||||
*
|
||||
* @return true if the user was seated at the table and has now been
|
||||
* removed, false if the user was never seated at the table in the
|
||||
* first place.
|
||||
* @return true if the user was seated at the table and has now been removed, false if the user
|
||||
* was never seated at the table in the first place.
|
||||
*/
|
||||
@ActionScript(omit=true)
|
||||
public boolean clearOccupantByOid (int bodyOid)
|
||||
{
|
||||
if (bodyOids != null) {
|
||||
@@ -286,9 +278,10 @@ public class Table
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to clear an occupant at the specified position.
|
||||
* Only call this method if you know what you're doing.
|
||||
* Called to clear an occupant at the specified position. Only call this method if you know
|
||||
* what you're doing.
|
||||
*/
|
||||
@ActionScript(omit=true)
|
||||
public void clearOccupantPos (int position)
|
||||
{
|
||||
occupants[position] = null;
|
||||
@@ -296,12 +289,12 @@ public class Table
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this table has a sufficient number of occupants
|
||||
* that the game can be started.
|
||||
* Returns true if this table has a sufficient number of occupants that the game can be
|
||||
* started.
|
||||
*/
|
||||
public boolean mayBeStarted ()
|
||||
{
|
||||
switch (config.getGameType()) {
|
||||
switch (config.getMatchType()) {
|
||||
case GameConfig.SEATED_CONTINUOUS:
|
||||
case GameConfig.PARTY:
|
||||
return true;
|
||||
@@ -330,12 +323,11 @@ public class Table
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if sufficient seats are occupied that the game should
|
||||
* be automatically started.
|
||||
* Returns true if sufficient seats are occupied that the game should be automatically started.
|
||||
*/
|
||||
public boolean shouldBeStarted ()
|
||||
{
|
||||
switch (config.getGameType()) {
|
||||
switch (config.getMatchType()) {
|
||||
case GameConfig.SEATED_CONTINUOUS:
|
||||
case GameConfig.PARTY:
|
||||
return true;
|
||||
@@ -346,8 +338,7 @@ public class Table
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this table is in play, false if it is still being
|
||||
* matchmade.
|
||||
* Returns true if this table is in play, false if it is still being matchmade.
|
||||
*/
|
||||
public boolean inPlay ()
|
||||
{
|
||||
@@ -363,8 +354,7 @@ public class Table
|
||||
// documentation inherited
|
||||
public boolean equals (Object other)
|
||||
{
|
||||
return (other instanceof Table) &&
|
||||
(tableId == ((Table) other).tableId);
|
||||
return (other instanceof Table) && (tableId == ((Table) other).tableId);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
|
||||
@@ -24,24 +24,21 @@ package com.threerings.parlor.data;
|
||||
import com.threerings.io.SimpleStreamableObject;
|
||||
|
||||
/**
|
||||
* Table configuration parameters for a game that is to be matchmade
|
||||
* using the table services.
|
||||
* Table configuration parameters for a game that is to be matchmade using the table services.
|
||||
*/
|
||||
public class TableConfig extends SimpleStreamableObject
|
||||
{
|
||||
/** The total number of players that are desired for the table.
|
||||
* For team games, this should be set to the total number of players
|
||||
* overall, as teams may be unequal. */
|
||||
/** The total number of players that are desired for the table. For team games, this should be
|
||||
* set to the total number of players overall, as teams may be unequal. */
|
||||
public int desiredPlayerCount;
|
||||
|
||||
/** The minimum number of players needed overall (or per-team if a
|
||||
* team-based game) for the game to start at the creator's discretion. */
|
||||
/** The minimum number of players needed overall (or per-team if a team-based game) for the
|
||||
* game to start at the creator's discretion. */
|
||||
public int minimumPlayerCount;
|
||||
|
||||
/** If non-null, indicates that this is a team-based game and contains
|
||||
* the team assignments for each player. For example, a game with
|
||||
* three players in two teams- players 0 and 2 versus player 1- would
|
||||
* have { {0, 2}, {1} }; */
|
||||
/** If non-null, indicates that this is a team-based game and contains the team assignments for
|
||||
* each player. For example, a game with three players in two teams- players 0 and 2 versus
|
||||
* player 1- would have { {0, 2}, {1} }; */
|
||||
public int[][] teamMemberIndices;
|
||||
|
||||
/** Whether the table is "private". */
|
||||
|
||||
@@ -25,20 +25,18 @@ import com.threerings.parlor.game.data.GameConfig;
|
||||
import com.threerings.parlor.util.ParlorContext;
|
||||
|
||||
/**
|
||||
* Provides the base from which interfaces can be built to configure games
|
||||
* prior to starting them. Derived classes would extend the base
|
||||
* configurator adding interface elements and wiring them up properly to
|
||||
* allow the user to configure an instance of their game.
|
||||
* Provides the base from which interfaces can be built to configure games prior to starting
|
||||
* them. Derived classes would extend the base configurator adding interface elements and wiring
|
||||
* them up properly to allow the user to configure an instance of their game.
|
||||
*
|
||||
* <p> Clients that use the game configurator will want to instantiate one
|
||||
* based on the class returned from the {@link GameConfig} and then
|
||||
* initialize it with a call to {@link #init}.
|
||||
* <p> Clients that use the game configurator will want to instantiate one based on the class
|
||||
* returned from the {@link GameConfig} and then initialize it with a call to {@link #init}.
|
||||
*/
|
||||
public abstract class GameConfigurator
|
||||
{
|
||||
/**
|
||||
* Initializes this game configurator, creates its user interface
|
||||
* elements and prepares it for display.
|
||||
* Initializes this game configurator, creates its user interface elements and prepares it for
|
||||
* display.
|
||||
*/
|
||||
public void init (ParlorContext ctx)
|
||||
{
|
||||
@@ -57,8 +55,8 @@ public abstract class GameConfigurator
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides this configurator with its configuration. It should set up
|
||||
* all of its user interface elements to reflect the configuration.
|
||||
* Provides this configurator with its configuration. It should set up all of its user
|
||||
* interface elements to reflect the configuration.
|
||||
*/
|
||||
public void setGameConfig (GameConfig config)
|
||||
{
|
||||
@@ -68,8 +66,8 @@ public abstract class GameConfigurator
|
||||
}
|
||||
|
||||
/**
|
||||
* Derived classes will likely want to override this method and
|
||||
* configure their user interface elements accordingly.
|
||||
* Derived classes will likely want to override this method and configure their user interface
|
||||
* elements accordingly.
|
||||
*/
|
||||
protected void gotGameConfig ()
|
||||
{
|
||||
@@ -86,10 +84,9 @@ public abstract class GameConfigurator
|
||||
}
|
||||
|
||||
/**
|
||||
* Derived classes will want to override this method, flushing values
|
||||
* from the user interface to the game config object so that it is
|
||||
* properly configured prior to being returned to the {@link
|
||||
* #getGameConfig} caller.
|
||||
* Derived classes will want to override this method, flushing values from the user interface
|
||||
* to the game config object so that it is properly configured prior to being returned to the
|
||||
* {@link #getGameConfig} caller.
|
||||
*/
|
||||
protected void flushGameConfig ()
|
||||
{
|
||||
|
||||
@@ -40,24 +40,21 @@ import com.threerings.parlor.game.data.GameObject;
|
||||
import com.threerings.parlor.util.ParlorContext;
|
||||
|
||||
/**
|
||||
* The game controller manages the flow and control of a game on the
|
||||
* client side. This class serves as the root of a hierarchy of controller
|
||||
* classes that aim to provide functionality shared between various
|
||||
* similar games. The base controller provides functionality for starting
|
||||
* and ending the game and for calculating ratings adjustements when a
|
||||
* game ends normally. It also handles the basic house keeping like
|
||||
* subscription to the game object and dispatch of commands and
|
||||
* distributed object events.
|
||||
* The game controller manages the flow and control of a game on the client side. This class serves
|
||||
* as the root of a hierarchy of controller classes that aim to provide functionality shared
|
||||
* between various similar games. The base controller provides functionality for starting and
|
||||
* ending the game and for calculating ratings adjustements when a game ends normally. It also
|
||||
* handles the basic house keeping like subscription to the game object and dispatch of commands
|
||||
* and distributed object events.
|
||||
*/
|
||||
public abstract class GameController extends PlaceController
|
||||
implements AttributeChangeListener
|
||||
{
|
||||
/**
|
||||
* Initializes this game controller with the game configuration that
|
||||
* was established during the match making process. Derived classes
|
||||
* may want to override this method to initialize themselves with
|
||||
* game-specific configuration parameters but they should be sure to
|
||||
* call <code>super.init</code> in such cases.
|
||||
* Initializes this game controller with the game configuration that was established during the
|
||||
* match making process. Derived classes may want to override this method to initialize
|
||||
* themselves with game-specific configuration parameters but they should be sure to call
|
||||
* <code>super.init</code> in such cases.
|
||||
*
|
||||
* @param ctx the client context.
|
||||
* @param config the configuration of the game we are intended to
|
||||
@@ -65,9 +62,8 @@ public abstract class GameController extends PlaceController
|
||||
*/
|
||||
public void init (CrowdContext ctx, PlaceConfig config)
|
||||
{
|
||||
// cast our references before we call super.init() so that when
|
||||
// super.init() calls createPlaceView(), we have our casted
|
||||
// references already in place
|
||||
// cast our references before we call super.init() so that when super.init() calls
|
||||
// createPlaceView(), we have our casted references already in place
|
||||
_ctx = (ParlorContext)ctx;
|
||||
_config = (GameConfig)config;
|
||||
|
||||
@@ -75,9 +71,8 @@ public abstract class GameController extends PlaceController
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds this controller as a listener to the game object (thus derived
|
||||
* classes need not do so) and lets the game manager know that we are
|
||||
* now ready to go.
|
||||
* Adds this controller as a listener to the game object (thus derived classes need not do so)
|
||||
* and lets the game manager know that we are now ready to go.
|
||||
*/
|
||||
public void willEnterPlace (PlaceObject plobj)
|
||||
{
|
||||
@@ -86,27 +81,24 @@ public abstract class GameController extends PlaceController
|
||||
// obtain a casted reference
|
||||
_gobj = (GameObject)plobj;
|
||||
|
||||
// if this place object is not our current location we'll need to
|
||||
// add it as an auxiliary chat source
|
||||
// if this place object is not our current location we'll need to add it as an auxiliary
|
||||
// chat source
|
||||
BodyObject bobj = (BodyObject)_ctx.getClient().getClientObject();
|
||||
if (bobj.location != plobj.getOid()) {
|
||||
_ctx.getChatDirector().addAuxiliarySource(
|
||||
_gobj, GameCodes.GAME_CHAT_TYPE);
|
||||
_ctx.getChatDirector().addAuxiliarySource(_gobj, GameCodes.GAME_CHAT_TYPE);
|
||||
}
|
||||
|
||||
// and add ourselves as a listener
|
||||
_gobj.addListener(this);
|
||||
|
||||
// we don't want to claim to be finished until any derived classes
|
||||
// that overrode this method have executed, so we'll queue up a
|
||||
// runnable here that will let the game manager know that we're
|
||||
// ready on the next pass through the distributed event loop
|
||||
// we don't want to claim to be finished until any derived classes that overrode this
|
||||
// method have executed, so we'll queue up a runnable here that will let the game manager
|
||||
// know that we're ready on the next pass through the distributed event loop
|
||||
Log.info("Entering game " + _gobj.which() + ".");
|
||||
if (_gobj.getPlayerIndex(bobj.getVisibleName()) != -1) {
|
||||
_ctx.getClient().getRunQueue().postRunnable(new Runnable() {
|
||||
public void run () {
|
||||
// finally let the game manager know that we're ready
|
||||
// to roll
|
||||
// finally let the game manager know that we're ready to roll
|
||||
playerReady();
|
||||
}
|
||||
});
|
||||
@@ -114,8 +106,7 @@ public abstract class GameController extends PlaceController
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes our listener registration from the game object and cleans
|
||||
* house.
|
||||
* Removes our listener registration from the game object and cleans house.
|
||||
*/
|
||||
public void didLeavePlace (PlaceObject plobj)
|
||||
{
|
||||
@@ -131,9 +122,9 @@ public abstract class GameController extends PlaceController
|
||||
/**
|
||||
* Convenience method to determine the type of game.
|
||||
*/
|
||||
public byte getGameType ()
|
||||
public int getMatchType ()
|
||||
{
|
||||
return _config.getGameType();
|
||||
return _config.getMatchType();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -141,15 +132,13 @@ public abstract class GameController extends PlaceController
|
||||
*/
|
||||
public boolean isGameOver ()
|
||||
{
|
||||
boolean gameOver = (_gobj == null) ||
|
||||
(_gobj.state != GameObject.IN_PLAY);
|
||||
boolean gameOver = (_gobj == null) || (_gobj.state != GameObject.IN_PLAY);
|
||||
return (_gameOver || gameOver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the client game over override. This is used in situations
|
||||
* where we determine that the game is over before the server has
|
||||
* informed us of such.
|
||||
* Sets the client game over override. This is used in situations where we determine that the
|
||||
* game is over before the server has informed us of such.
|
||||
*/
|
||||
public void setGameOver (boolean gameOver)
|
||||
{
|
||||
@@ -157,13 +146,11 @@ public abstract class GameController extends PlaceController
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls {@link #gameWillReset}, ends the current game (locally, it
|
||||
* does not tell the server to end the game), and waits to receive a
|
||||
* reset notification (which is simply an event setting the game state
|
||||
* to <code>IN_PLAY</code> even though it's already set to
|
||||
* <code>IN_PLAY</code>) from the server which will start up a new
|
||||
* game. Derived classes should override {@link #gameWillReset} to
|
||||
* perform any game-specific animations.
|
||||
* Calls {@link #gameWillReset}, ends the current game (locally, it does not tell the server to
|
||||
* end the game), and waits to receive a reset notification (which is simply an event setting
|
||||
* the game state to <code>IN_PLAY</code> even though it's already set to <code>IN_PLAY</code>)
|
||||
* from the server which will start up a new game. Derived classes should override {@link
|
||||
* #gameWillReset} to perform any game-specific animations.
|
||||
*/
|
||||
public void resetGame ()
|
||||
{
|
||||
@@ -183,9 +170,8 @@ public abstract class GameController extends PlaceController
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles basic game controller action events. Derived classes should
|
||||
* be sure to call <code>super.handleAction</code> for events they
|
||||
* don't specifically handle.
|
||||
* Handles basic game controller action events. Derived classes should be sure to call
|
||||
* <code>super.handleAction</code> for events they don't specifically handle.
|
||||
*/
|
||||
public boolean handleAction (ActionEvent action)
|
||||
{
|
||||
@@ -197,8 +183,7 @@ public abstract class GameController extends PlaceController
|
||||
*/
|
||||
public void systemMessage (String bundle, String msg)
|
||||
{
|
||||
_ctx.getChatDirector().displayInfo(
|
||||
bundle, msg, GameCodes.GAME_CHAT_TYPE);
|
||||
_ctx.getChatDirector().displayInfo(bundle, msg, GameCodes.GAME_CHAT_TYPE);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
@@ -208,16 +193,16 @@ public abstract class GameController extends PlaceController
|
||||
if (event.getName().equals(GameObject.STATE)) {
|
||||
int newState = event.getIntValue();
|
||||
if (!stateDidChange(newState)) {
|
||||
Log.warning("Game transitioned to unknown state " +
|
||||
"[gobj=" + _gobj + ", state=" + newState + "].");
|
||||
Log.warning("Game transitioned to unknown state [gobj=" + _gobj +
|
||||
", state=" + newState + "].");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Derived classes can override this method if they add additional game
|
||||
* states and should handle transitions to those states, returning true to
|
||||
* indicate they were handled and calling super for the normal game states.
|
||||
* Derived classes can override this method if they add additional game states and should
|
||||
* handle transitions to those states, returning true to indicate they were handled and calling
|
||||
* super for the normal game states.
|
||||
*/
|
||||
protected boolean stateDidChange (int state)
|
||||
{
|
||||
@@ -236,8 +221,8 @@ public abstract class GameController extends PlaceController
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after we've entered the game and everything has initialized
|
||||
* to notify the server that we, as a player, are ready to play.
|
||||
* Called after we've entered the game and everything has initialized to notify the server that
|
||||
* we, as a player, are ready to play.
|
||||
*/
|
||||
protected void playerReady ()
|
||||
{
|
||||
@@ -246,9 +231,8 @@ public abstract class GameController extends PlaceController
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game transitions to the <code>IN_PLAY</code>
|
||||
* state. This happens when all of the players have arrived and the
|
||||
* server starts the game.
|
||||
* Called when the game transitions to the <code>IN_PLAY</code> state. This happens when all of
|
||||
* the players have arrived and the server starts the game.
|
||||
*/
|
||||
protected void gameDidStart ()
|
||||
{
|
||||
@@ -269,9 +253,8 @@ public abstract class GameController extends PlaceController
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game transitions to the <code>GAME_OVER</code>
|
||||
* state. This happens when the game reaches some end condition by
|
||||
* normal means (is not cancelled or aborted).
|
||||
* Called when the game transitions to the <code>GAME_OVER</code> state. This happens when the
|
||||
* game reaches some end condition by normal means (is not cancelled or aborted).
|
||||
*/
|
||||
protected void gameDidEnd ()
|
||||
{
|
||||
@@ -297,9 +280,8 @@ public abstract class GameController extends PlaceController
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to give derived classes a chance to display animations, send
|
||||
* a final packet, or do any other business they care to do when the
|
||||
* game is about to reset.
|
||||
* Called to give derived classes a chance to display animations, send a final packet, or do
|
||||
* any other business they care to do when the game is about to reset.
|
||||
*/
|
||||
protected void gameWillReset ()
|
||||
{
|
||||
@@ -317,12 +299,10 @@ public abstract class GameController extends PlaceController
|
||||
/** Our game configuration information. */
|
||||
protected GameConfig _config;
|
||||
|
||||
/** A reference to the game object for the game that we're
|
||||
* controlling. */
|
||||
/** A reference to the game object for the game that we're controlling. */
|
||||
protected GameObject _gobj;
|
||||
|
||||
/** A local flag overriding the game over state for situations where
|
||||
* the client knows the game is over before the server has
|
||||
* transitioned the game object accordingly. */
|
||||
/** A local flag overriding the game over state for situations where the client knows the game
|
||||
* is over before the server has transitioned the game object accordingly. */
|
||||
protected boolean _gameOver;
|
||||
}
|
||||
|
||||
@@ -31,74 +31,81 @@ import com.threerings.parlor.client.TableConfigurator;
|
||||
import com.threerings.parlor.game.client.GameConfigurator;
|
||||
|
||||
/**
|
||||
* The game config class encapsulates the configuration information for a
|
||||
* particular type of game. The hierarchy of game config objects mimics the
|
||||
* hierarchy of game managers and controllers. Both the game manager and game
|
||||
* controller are provided with the game config object when the game is
|
||||
* The game config class encapsulates the configuration information for a particular type of game.
|
||||
* The hierarchy of game config objects mimics the hierarchy of game managers and controllers. Both
|
||||
* the game manager and game controller are provided with the game config object when the game is
|
||||
* created.
|
||||
*
|
||||
* <p> The game config object is also the mechanism used to instantiate the
|
||||
* appropriate game manager and controller. Every game must have an associated
|
||||
* game config derived class that overrides {@link #createController} and
|
||||
* {@link #getManagerClassName}, returning the appropriate game controller and
|
||||
* manager class for that game. Thus the entire chain of events that causes a
|
||||
* particular game to be created is the construction of the appropriate game
|
||||
* config instance which is provided to the server as part of an invitation or
|
||||
* via some other matchmaking mechanism.
|
||||
* <p> The game config object is also the mechanism used to instantiate the appropriate game
|
||||
* manager and controller. Every game must have an associated game config derived class that
|
||||
* overrides {@link #createController} and {@link #getManagerClassName}, returning the appropriate
|
||||
* game controller and manager class for that game. Thus the entire chain of events that causes a
|
||||
* particular game to be created is the construction of the appropriate game config instance which
|
||||
* is provided to the server as part of an invitation or via some other matchmaking mechanism.
|
||||
*/
|
||||
public abstract class GameConfig extends PlaceConfig implements Cloneable
|
||||
{
|
||||
/** Game type constant: a game that is started with a list of players,
|
||||
* and those are the only players that may play. */
|
||||
public static final byte SEATED_GAME = 0;
|
||||
/** Matchmaking type constant: a game that is started with a list of players, and those are the
|
||||
* only players that may play. */
|
||||
public static final int SEATED_GAME = 0;
|
||||
|
||||
/** Game type constant: a game that starts immediately, but only has
|
||||
* a certain number of player slots. Users enter the game room, and
|
||||
* then choose where to sit. */
|
||||
public static final byte SEATED_CONTINUOUS = 1;
|
||||
/** Matchmaking type constant: a game that starts immediately, but only has a certain number of
|
||||
* player slots. Users enter the game room, and then choose where to sit. */
|
||||
public static final int SEATED_CONTINUOUS = 1;
|
||||
|
||||
/** Game type constant: a game that starts immediately, and every
|
||||
* user that enters is a player. */
|
||||
public static final byte PARTY = 2;
|
||||
/** Matchmaking type constant: a game that starts immediately, and every user that enters is a
|
||||
* player. */
|
||||
public static final int PARTY = 2;
|
||||
|
||||
/** The usernames of the players involved in this game, or an empty
|
||||
* array if such information is not needed by this particular game. */
|
||||
/** Maps the matchmaking type codes into strings used in our XML configuration. */
|
||||
public static final String[] TYPE_STRINGS = { "table", "entersit", "party" };
|
||||
|
||||
/** The usernames of the players involved in this game, or an empty array if such information
|
||||
* is not needed by this particular game. */
|
||||
public Name[] players = new Name[0];
|
||||
|
||||
/** Indicates whether or not this game is rated. */
|
||||
public boolean rated = true;
|
||||
|
||||
/** Configurations for AIs to be used in this game. Slots with real
|
||||
* players should be null and slots with AIs should contain
|
||||
* configuration for those AIs. A null array indicates no use of AIs
|
||||
* at all. */
|
||||
/** Configurations for AIs to be used in this game. Slots with real players should be null and
|
||||
* slots with AIs should contain configuration for those AIs. A null array indicates no use of
|
||||
* AIs at all. */
|
||||
public GameAI[] ais = new GameAI[0];
|
||||
|
||||
/**
|
||||
* Get the type of game.
|
||||
* Returns a numeric identifier for this game class. This may be used to track persisent
|
||||
* information on a per-game basis.
|
||||
*/
|
||||
public byte getGameType ()
|
||||
public abstract int getGameId ();
|
||||
|
||||
/**
|
||||
* Returns a string identifier for this game class (e.g. "spades"). This may be used to
|
||||
* identify a message bundle for which to obtain translations for this game configuration and
|
||||
* to look up the name of the game in said bundle.
|
||||
*/
|
||||
public abstract String getGameIdent ();
|
||||
|
||||
/**
|
||||
* Returns the matchmaking type of this game: {@link #SEATED_GAME}, etc.
|
||||
*/
|
||||
public int getMatchType ()
|
||||
{
|
||||
return SEATED_GAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the message bundle identifier for the bundle that should be
|
||||
* used to translate the translatable strings used to describe the
|
||||
* game config parameters.
|
||||
* Creates a configurator that can be used to create a user interface for configuring this
|
||||
* instance prior to starting the game. If no configuration is necessary, this method should
|
||||
* return null.
|
||||
*/
|
||||
public abstract String getBundleName ();
|
||||
public GameConfigurator createConfigurator ()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a configurator that can be used to create a user interface
|
||||
* for configuring this instance prior to starting the game. If no
|
||||
* configuration is necessary, this method should return null.
|
||||
*/
|
||||
public abstract GameConfigurator createConfigurator ();
|
||||
|
||||
/**
|
||||
* Creates a table configurator for initializing 'table' properties
|
||||
* of the game. The default implementation returns null.
|
||||
* Creates a table configurator for initializing 'table' properties of the game. The default
|
||||
* implementation returns null.
|
||||
*/
|
||||
public TableConfigurator createTableConfigurator ()
|
||||
{
|
||||
@@ -106,27 +113,8 @@ public abstract class GameConfig extends PlaceConfig implements Cloneable
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a translatable label describing this game.
|
||||
*/
|
||||
public String getGameName ()
|
||||
{
|
||||
// the whole getRatingTypeId(), getGameName(), getBundleName()
|
||||
// business should be cleaned up. we should have getGameIdent()
|
||||
// and everything should have a default implementation using that
|
||||
return "m." + getBundleName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the game rating type, if the system uses such things.
|
||||
*/
|
||||
public byte getRatingTypeId ()
|
||||
{
|
||||
return (byte)-1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a List of strings that describe the configuration of this
|
||||
* game. Default implementation returns an empty list.
|
||||
* Returns a List of strings that describe the configuration of this game. Default
|
||||
* implementation returns an empty list.
|
||||
*/
|
||||
public List<String> getDescription ()
|
||||
{
|
||||
@@ -134,26 +122,21 @@ public abstract class GameConfig extends PlaceConfig implements Cloneable
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this game config object is equal to the supplied
|
||||
* object (meaning it is also a game config object and its
|
||||
* configuration settings are the same as ours).
|
||||
* Returns true if this game config object is equal to the supplied object (meaning it is a
|
||||
* game config for the same game and its configuration settings are the same as ours).
|
||||
*/
|
||||
public boolean equals (Object other)
|
||||
{
|
||||
// make sure they're of the same class
|
||||
if (other.getClass() == this.getClass()) {
|
||||
GameConfig that = (GameConfig) other;
|
||||
return this.rated == that.rated;
|
||||
|
||||
} else {
|
||||
if (!(other instanceof GameConfig)) {
|
||||
return false;
|
||||
}
|
||||
GameConfig that = (GameConfig) other;
|
||||
return (this.getGameId() == that.getGameId()) && (this.rated == that.rated);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a hashcode for this game config object that supports our
|
||||
* {@link #equals} implementation. Objects that are equal should have
|
||||
* the same hashcode.
|
||||
* Computes a hashcode for this game config object that supports our {@link #equals}
|
||||
* implementation. Objects that are equal should have the same hashcode.
|
||||
*/
|
||||
public int hashCode ()
|
||||
{
|
||||
|
||||
@@ -58,20 +58,17 @@ import com.threerings.parlor.server.ParlorSender;
|
||||
import com.threerings.util.MessageBundle;
|
||||
|
||||
/**
|
||||
* The game manager handles the server side management of a game. It
|
||||
* manipulates the game state in accordance with the logic of the game
|
||||
* flow and generally manages the whole game playing process.
|
||||
* The game manager handles the server side management of a game. It manipulates the game state in
|
||||
* accordance with the logic of the game flow and generally manages the whole game playing process.
|
||||
*
|
||||
* <p> The game manager extends the place manager because games are
|
||||
* implicitly played in a location, the players of the game implicitly
|
||||
* bodies in that location.
|
||||
* <p> The game manager extends the place manager because games are implicitly played in a
|
||||
* location, the players of the game implicitly bodies in that location.
|
||||
*/
|
||||
public class GameManager extends PlaceManager
|
||||
implements ParlorCodes, GameCodes
|
||||
{
|
||||
/**
|
||||
* Returns the configuration object for the game being managed by this
|
||||
* manager.
|
||||
* Returns the configuration object for the game being managed by this manager.
|
||||
*/
|
||||
public GameConfig getGameConfig ()
|
||||
{
|
||||
@@ -81,19 +78,19 @@ public class GameManager extends PlaceManager
|
||||
/**
|
||||
* A convenience method for getting the game type.
|
||||
*/
|
||||
public byte getGameType ()
|
||||
public int getMatchType ()
|
||||
{
|
||||
return _gameconfig.getGameType();
|
||||
return _gameconfig.getMatchType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given player to the game at the first available player
|
||||
* index. This should only be called before the game is started, and
|
||||
* is most likely to be used to add players to party games.
|
||||
* Adds the given player to the game at the first available player index. This should only be
|
||||
* called before the game is started, and is most likely to be used to add players to party
|
||||
* games.
|
||||
*
|
||||
* @param player the username of the player to add to this game.
|
||||
* @return the player index at which the player was added, or
|
||||
* <code>-1</code> if the player could not be added to the game.
|
||||
* @return the player index at which the player was added, or <code>-1</code> if the player
|
||||
* could not be added to the game.
|
||||
*/
|
||||
public int addPlayer (Name player)
|
||||
{
|
||||
@@ -108,10 +105,9 @@ public class GameManager extends PlaceManager
|
||||
|
||||
// sanity-check the player index
|
||||
if (pidx == -1) {
|
||||
Log.warning("Couldn't find free player index for player " +
|
||||
"[game=" + where() + ", player=" + player +
|
||||
", players=" + StringUtil.toString(_gameobj.players) +
|
||||
"].");
|
||||
Log.warning("Couldn't find free player index for player [game=" + where() +
|
||||
", player=" + player +
|
||||
", players=" + StringUtil.toString(_gameobj.players) + "].");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -120,9 +116,8 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given player to the game at the specified player index.
|
||||
* This should only be called before the game is started, and is most
|
||||
* likely to be used to add players to party games.
|
||||
* Adds the given player to the game at the specified player index. This should only be called
|
||||
* before the game is started, and is most likely to be used to add players to party games.
|
||||
*
|
||||
* @param player the username of the player to add to this game.
|
||||
* @param pidx the player index at which the player is to be added.
|
||||
@@ -132,34 +127,31 @@ public class GameManager extends PlaceManager
|
||||
{
|
||||
// make sure the specified player index is valid
|
||||
if (pidx < 0 || pidx >= getPlayerSlots()) {
|
||||
Log.warning("Attempt to add player at an invalid index " +
|
||||
"[game=" + where() + ", player=" + player +
|
||||
", pidx=" + pidx + "].");
|
||||
Log.warning("Attempt to add player at an invalid index [game=" + where() +
|
||||
", player=" + player + ", pidx=" + pidx + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
// make sure the player index is available
|
||||
if (_gameobj.players[pidx] != null) {
|
||||
Log.warning("Attempt to add player at occupied index " +
|
||||
"[game=" + where() + ", player=" + player +
|
||||
", pidx=" + pidx + "].");
|
||||
Log.warning("Attempt to add player at occupied index [game=" + where() +
|
||||
", player=" + player + ", pidx=" + pidx + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
// make sure the player isn't already somehow a part of the game
|
||||
// to avoid any potential badness that might ensue if we added
|
||||
// them more than once
|
||||
// make sure the player isn't already somehow a part of the game to avoid any potential
|
||||
// badness that might ensue if we added them more than once
|
||||
if (_gameobj.getPlayerIndex(player) != -1) {
|
||||
Log.warning("Attempt to add player to game that they're already " +
|
||||
"playing [game=" + where() + ", player=" + player + "].");
|
||||
Log.warning("Attempt to add player to game that they're already playing " +
|
||||
"[game=" + where() + ", player=" + player + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
// get the player's body object
|
||||
BodyObject bobj = CrowdServer.lookupBody(player);
|
||||
if (bobj == null) {
|
||||
Log.warning("Unable to get body object while adding player " +
|
||||
"[game=" + where() + ", player=" + player + "].");
|
||||
Log.warning("Unable to get body object while adding player [game=" + where() +
|
||||
", player=" + player + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -179,9 +171,9 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the given player from the game. This is most likely to be
|
||||
* used to allow players involved in a party game to leave the game
|
||||
* early-on if they realize they'd rather not play for some reason.
|
||||
* Removes the given player from the game. This is most likely to be used to allow players
|
||||
* involved in a party game to leave the game early-on if they realize they'd rather not play
|
||||
* for some reason.
|
||||
*
|
||||
* @param player the username of the player to remove from this game.
|
||||
* @return true if the player was successfully removed, false if not.
|
||||
@@ -193,10 +185,9 @@ public class GameManager extends PlaceManager
|
||||
|
||||
// sanity-check the player index
|
||||
if (pidx == -1) {
|
||||
Log.warning("Attempt to remove non-player from players list " +
|
||||
"[game=" + where() + ", player=" + player +
|
||||
", players=" + StringUtil.toString(_gameobj.players) +
|
||||
"].");
|
||||
Log.warning("Attempt to remove non-player from players list [game=" + where() +
|
||||
", player=" + player +
|
||||
", players=" + StringUtil.toString(_gameobj.players) + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -221,9 +212,8 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the player at the specified index and calls {@link
|
||||
* #playerWasReplaced} to let derived classes and delegates know
|
||||
* what's going on.
|
||||
* Replaces the player at the specified index and calls {@link #playerWasReplaced} to let
|
||||
* derived classes and delegates know what's going on.
|
||||
*/
|
||||
public void replacePlayer (final int pidx, final Name player)
|
||||
{
|
||||
@@ -236,15 +226,14 @@ public class GameManager extends PlaceManager
|
||||
// notify our delegates
|
||||
applyToDelegates(new DelegateOp() {
|
||||
public void apply (PlaceManagerDelegate delegate) {
|
||||
((GameManagerDelegate)delegate).playerWasReplaced(
|
||||
pidx, oplayer, player);
|
||||
((GameManagerDelegate)delegate).playerWasReplaced(pidx, oplayer, player);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user object for the player with the specified index or
|
||||
* null if the player at that index is not online.
|
||||
* Returns the user object for the player with the specified index or null if the player at
|
||||
* that index is not online.
|
||||
*/
|
||||
public BodyObject getPlayer (int playerIdx)
|
||||
{
|
||||
@@ -259,9 +248,8 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specified player as an AI with the specified
|
||||
* configuration. It is assumed that this will be set soon after the
|
||||
* player names for all AIs present in the game. (It should be done
|
||||
* Sets the specified player as an AI with the specified configuration. It is assumed that this
|
||||
* will be set soon after the player names for all AIs present in the game. (It should be done
|
||||
* before human players start trickling into the game.)
|
||||
*
|
||||
* @param pidx the player index of the AI.
|
||||
@@ -288,8 +276,8 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the player with the specified index or null if
|
||||
* no player exists at that index.
|
||||
* Returns the name of the player with the specified index or null if no player exists at that
|
||||
* index.
|
||||
*/
|
||||
public Name getPlayerName (int index)
|
||||
{
|
||||
@@ -297,8 +285,8 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the player index of the given user in the game, or
|
||||
* <code>-1</code> if the player is not involved in the game.
|
||||
* Returns the player index of the given user in the game, or <code>-1</code> if the player is
|
||||
* not involved in the game.
|
||||
*/
|
||||
public int getPlayerIndex (Name username)
|
||||
{
|
||||
@@ -306,14 +294,12 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player index of the specified oid, or -1 if the oid is
|
||||
* not a player or is a player that is not presently in the game.
|
||||
* Get the player index of the specified oid, or -1 if the oid is not a player or is a player
|
||||
* that is not presently in the game.
|
||||
*/
|
||||
public int getPresentPlayerIndex (int bodyOid)
|
||||
{
|
||||
return (_playerOids == null)
|
||||
? -1
|
||||
: IntListUtil.indexOf(_playerOids, bodyOid);
|
||||
return (_playerOids == null) ? -1 : IntListUtil.indexOf(_playerOids, bodyOid);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -349,13 +335,11 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the player at the specified player index is actively
|
||||
* playing the game
|
||||
* Returns whether the player at the specified player index is actively playing the game
|
||||
*/
|
||||
public boolean isActivePlayer (int pidx)
|
||||
{
|
||||
return _gameobj.isActivePlayer(pidx) &&
|
||||
(getPlayerOid(pidx) > 0 || isAI(pidx));
|
||||
return _gameobj.isActivePlayer(pidx) && (getPlayerOid(pidx) > 0 || isAI(pidx));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -377,14 +361,12 @@ public class GameManager extends PlaceManager
|
||||
/**
|
||||
* Sends a system message to the players in the game room.
|
||||
*
|
||||
* @param waitForStart if true, the message will not be sent until the
|
||||
* game has started.
|
||||
* @param waitForStart if true, the message will not be sent until the game has started.
|
||||
*/
|
||||
public void systemMessage (
|
||||
String msgbundle, String msg, boolean waitForStart)
|
||||
{
|
||||
if (waitForStart &&
|
||||
((_gameobj == null) || (_gameobj.state == GameObject.PRE_GAME))) {
|
||||
if (waitForStart && ((_gameobj == null) || (_gameobj.state == GameObject.PRE_GAME))) {
|
||||
// queue up the message.
|
||||
if (_startmsgs == null) {
|
||||
_startmsgs = new ArrayList<Tuple<String,String>>();
|
||||
@@ -398,23 +380,20 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when the game is ready to start (all players
|
||||
* involved have delivered their "am ready" notifications). It calls
|
||||
* {@link #gameWillStart}, sets the necessary wheels in motion and
|
||||
* then calls {@link #gameDidStart}. Derived classes should override
|
||||
* one or both of the calldown functions (rather than this function)
|
||||
* if they need to do things before or after the game starts.
|
||||
* This is called when the game is ready to start (all players involved have delivered their
|
||||
* "am ready" notifications). It calls {@link #gameWillStart}, sets the necessary wheels in
|
||||
* motion and then calls {@link #gameDidStart}. Derived classes should override one or both of
|
||||
* the calldown functions (rather than this function) if they need to do things before or after
|
||||
* the game starts.
|
||||
*
|
||||
* @return true if the game was started, false if it could not be
|
||||
* started because it was already in play or because all players have
|
||||
* not yet reported in.
|
||||
* @return true if the game was started, false if it could not be started because it was
|
||||
* already in play or because all players have not yet reported in.
|
||||
*/
|
||||
public boolean startGame ()
|
||||
{
|
||||
// complain if we're already started
|
||||
if (_gameobj.state == GameObject.IN_PLAY) {
|
||||
Log.warning("Requested to start an already in-play game " +
|
||||
"[game=" + where() + "].");
|
||||
Log.warning("Requested to start an already in-play game [game=" + where() + "].");
|
||||
Thread.dumpStack();
|
||||
return false;
|
||||
}
|
||||
@@ -424,27 +403,24 @@ public class GameManager extends PlaceManager
|
||||
|
||||
// make sure everyone has turned up
|
||||
if (!allPlayersReady()) {
|
||||
Log.warning("Requested to start a game that is still " +
|
||||
"awaiting players [game=" + where() +
|
||||
", pnames=" + StringUtil.toString(_gameobj.players) +
|
||||
Log.warning("Requested to start a game that is still awaiting players " +
|
||||
"[game=" + where() + ", pnames=" + StringUtil.toString(_gameobj.players) +
|
||||
", poids=" + StringUtil.toString(_playerOids) + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
// if we're still waiting for a call to endGame() to propagate,
|
||||
// queue up a runnable to start the game which will allow the
|
||||
// endGame() to propagate before we start things up
|
||||
// if we're still waiting for a call to endGame() to propagate, queue up a runnable to
|
||||
// start the game which will allow the endGame() to propagate before we start things up
|
||||
if (_committedState == GameObject.IN_PLAY) {
|
||||
if (_postponedStart) {
|
||||
// We've already tried postponing once, doesn't do us any
|
||||
// good to throw ourselves into a frenzy trying again.
|
||||
Log.warning("Tried to postpone the start of a still-ending game " +
|
||||
"multiple times [game=" + where() + "].");
|
||||
// We've already tried postponing once, doesn't do us any good to throw ourselves
|
||||
// into a frenzy trying again.
|
||||
Log.warning("Tried to postpone the start of a still-ending game multiple times " +
|
||||
"[game=" + where() + "].");
|
||||
_postponedStart = false;
|
||||
return false;
|
||||
}
|
||||
Log.info("Postponing start of still-ending game " +
|
||||
"[game=" + where() + "].");
|
||||
Log.info("Postponing start of still-ending game [game=" + where() + "].");
|
||||
_postponedStart = true;
|
||||
// TEMP: track down weirdness
|
||||
final Exception firstCall = new Exception();
|
||||
@@ -500,30 +476,27 @@ public class GameManager extends PlaceManager
|
||||
if (shouldEndGame()) {
|
||||
endGame();
|
||||
} else {
|
||||
// otherwise report that the player was knocked out to other
|
||||
// people in his/her room
|
||||
// otherwise report that the player was knocked out to other people in his/her room
|
||||
reportPlayerKnockedOut(pidx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game is known to be over. This will call some
|
||||
* calldown functions to determine the winner of the game and then
|
||||
* transition the game to the {@link GameObject#GAME_OVER} state.
|
||||
* Called when the game is known to be over. This will call some calldown functions to
|
||||
* determine the winner of the game and then transition the game to the {@link
|
||||
* GameObject#GAME_OVER} state.
|
||||
*/
|
||||
public void endGame ()
|
||||
{
|
||||
// TEMP: debug pending rating repeat bug
|
||||
if (_gameEndTracker.checkCall(
|
||||
"Requested to end already ended game " +
|
||||
"[game=" + where() + "].")) {
|
||||
"Requested to end already ended game [game=" + where() + "].")) {
|
||||
return;
|
||||
}
|
||||
// END TEMP
|
||||
|
||||
if (!_gameobj.isInPlay()) {
|
||||
Log.info("Refusing to end game that was not in play " +
|
||||
"[game=" + where() + "].");
|
||||
Log.info("Refusing to end game that was not in play [game=" + where() + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -544,22 +517,19 @@ public class GameManager extends PlaceManager
|
||||
_gameobj.commitTransaction();
|
||||
}
|
||||
|
||||
// wait until we hear the game state transition on the game object
|
||||
// to invoke our game over code so that we can be sure that any
|
||||
// final events dispatched on the game object prior to the call to
|
||||
// endGame() have been dispatched
|
||||
// wait until we hear the game state transition on the game object to invoke our game over
|
||||
// code so that we can be sure that any final events dispatched on the game object prior to
|
||||
// the call to endGame() have been dispatched
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the state of the game to {@link GameObject#CANCELLED}.
|
||||
*
|
||||
* @return true if the game was cancelled, false if it was already over or
|
||||
* cancelled.
|
||||
* @return true if the game was cancelled, false if it was already over or cancelled.
|
||||
*/
|
||||
public boolean cancelGame ()
|
||||
{
|
||||
if (_gameobj.state != GameObject.GAME_OVER &&
|
||||
_gameobj.state != GameObject.CANCELLED) {
|
||||
if (_gameobj.state != GameObject.GAME_OVER && _gameobj.state != GameObject.CANCELLED) {
|
||||
_gameobj.setState(GameObject.CANCELLED);
|
||||
return true;
|
||||
}
|
||||
@@ -567,10 +537,9 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether game conclusion antics such as rating updates
|
||||
* should be performed when an in-play game is ended. Derived classes
|
||||
* may wish to override this method to customize the conditions under
|
||||
* which the game is concluded.
|
||||
* Returns whether game conclusion antics such as rating updates should be performed when an
|
||||
* in-play game is ended. Derived classes may wish to override this method to customize the
|
||||
* conditions under which the game is concluded.
|
||||
*/
|
||||
public boolean shouldConcludeGame ()
|
||||
{
|
||||
@@ -578,13 +547,11 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game is to be reset to its starting state in
|
||||
* preparation for a new game without actually ending the current
|
||||
* game. It calls {@link #gameWillReset} followed by the standard game
|
||||
* start processing ({@link #gameWillStart} and {@link
|
||||
* #gameDidStart}). Derived classes should override these calldown
|
||||
* functions (rather than this function) if they need to do things
|
||||
* before or after the game resets.
|
||||
* Called when the game is to be reset to its starting state in preparation for a new game
|
||||
* without actually ending the current game. It calls {@link #gameWillReset} followed by the
|
||||
* standard game start processing ({@link #gameWillStart} and {@link #gameDidStart}). Derived
|
||||
* classes should override these calldown functions (rather than this function) if they need to
|
||||
* do things before or after the game resets.
|
||||
*/
|
||||
public void resetGame ()
|
||||
{
|
||||
@@ -597,21 +564,20 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the client when the player is ready for the game to start.
|
||||
* This method is dispatched dynamically by {@link #messageReceived}.
|
||||
* Called by the client when the player is ready for the game to start. This method is
|
||||
* dispatched dynamically by {@link #messageReceived}.
|
||||
*/
|
||||
public void playerReady (BodyObject caller)
|
||||
{
|
||||
// get the user's player index
|
||||
int pidx = _gameobj.getPlayerIndex(caller.getVisibleName());
|
||||
if (pidx == -1) {
|
||||
// only complain if this is not a party game, since it's
|
||||
// perfectly normal to receive a player ready notification
|
||||
// from a user entering a party game in which they're not yet
|
||||
// only complain if this is not a party game, since it's perfectly normal to receive a
|
||||
// player ready notification from a user entering a party game in which they're not yet
|
||||
// a participant
|
||||
if (needsNoShowTimer()) {
|
||||
Log.warning("Received playerReady() from non-player? " +
|
||||
"[game=" + where() + ", who=" + caller.who() + "].");
|
||||
Log.warning("Received playerReady() from non-player? [game=" + where() +
|
||||
", who=" + caller.who() + "].");
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -626,8 +592,8 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if all (non-AI) players have delivered their {@link
|
||||
* #playerReady} notifications, false if they have not.
|
||||
* Returns true if all (non-AI) players have delivered their {@link #playerReady}
|
||||
* notifications, false if they have not.
|
||||
*/
|
||||
public boolean allPlayersReady ()
|
||||
{
|
||||
@@ -640,10 +606,9 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the player at the specified slot is ready (or if
|
||||
* there is meant to be no player in that slot), false if there is
|
||||
* meant to be a player in the specified slot and they have not yet
|
||||
* reported that they are ready.
|
||||
* Returns true if the player at the specified slot is ready (or if there is meant to be no
|
||||
* player in that slot), false if there is meant to be a player in the specified slot and they
|
||||
* have not yet reported that they are ready.
|
||||
*/
|
||||
public boolean playerIsReady (int pidx)
|
||||
{
|
||||
@@ -653,20 +618,19 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this game requires a no-show timer. The default
|
||||
* implementation returns true for non-party games and false for party
|
||||
* games. Derived classes may wish to change or augment this behavior.
|
||||
* Returns true if this game requires a no-show timer. The default implementation returns true
|
||||
* for non-party games and false for party games. Derived classes may wish to change or augment
|
||||
* this behavior.
|
||||
*/
|
||||
protected boolean needsNoShowTimer ()
|
||||
{
|
||||
return (getGameType() == GameConfig.SEATED_GAME);
|
||||
return (getMatchType() == GameConfig.SEATED_GAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Derived classes that need their AIs to be ticked periodically
|
||||
* should override this method and return true. Many AIs can act
|
||||
* entirely in reaction to game state changes and need no periodic
|
||||
* ticking which is why ticking is disabled by default.
|
||||
* Derived classes that need their AIs to be ticked periodically should override this method
|
||||
* and return true. Many AIs can act entirely in reaction to game state changes and need no
|
||||
* periodic ticking which is why ticking is disabled by default.
|
||||
*
|
||||
* @see #tickAIs
|
||||
*/
|
||||
@@ -676,9 +640,8 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player was added to the game. Derived classes may
|
||||
* override this method to perform any game-specific actions they
|
||||
* desire, but should be sure to call
|
||||
* Called when a player was added to the game. Derived classes may override this method to
|
||||
* perform any game-specific actions they desire, but should be sure to call
|
||||
* <code>super.playerWasAdded()</code>.
|
||||
*
|
||||
* @param player the username of the player added to the game.
|
||||
@@ -689,22 +652,19 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player was removed from the game. Derived classes
|
||||
* may override this method to perform any game-specific actions they
|
||||
* desire, but should be sure to call
|
||||
* Called when a player was removed from the game. Derived classes may override this method to
|
||||
* perform any game-specific actions they desire, but should be sure to call
|
||||
* <code>super.playerWasRemoved()</code>.
|
||||
*
|
||||
* @param player the username of the player removed from the game.
|
||||
* @param pidx the player index of the player before they were removed
|
||||
* from the game.
|
||||
* @param pidx the player index of the player before they were removed from the game.
|
||||
*/
|
||||
protected void playerWasRemoved (Name player, int pidx)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player has been replaced via a call to {@link
|
||||
* #replacePlayer}.
|
||||
* Called when a player has been replaced via a call to {@link #replacePlayer}.
|
||||
*/
|
||||
protected void playerWasReplaced (int pidx, Name oldPlayer, Name newPlayer)
|
||||
{
|
||||
@@ -717,14 +677,12 @@ public class GameManager extends PlaceManager
|
||||
{
|
||||
BodyObject user = getPlayer(pidx);
|
||||
if (user == null) {
|
||||
// body object can be null for ai players
|
||||
return;
|
||||
return; // body object can be null for ai players
|
||||
}
|
||||
|
||||
DObject place = CrowdServer.omgr.getObject(user.location);
|
||||
if (place != null) {
|
||||
place.postMessage(PLAYER_KNOCKED_OUT,
|
||||
new Object[] { new int[] { user.getOid() } });
|
||||
place.postMessage(PLAYER_KNOCKED_OUT, new Object[] { new int[] { user.getOid() } });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -770,8 +728,8 @@ public class GameManager extends PlaceManager
|
||||
// set up an initial player status array
|
||||
_gameobj.setPlayerStatus(new int[getPlayerSlots()]);
|
||||
|
||||
// save off the number of players so that we needn't repeatedly
|
||||
// iterate through the player name array server-side unnecessarily
|
||||
// save off the number of players so that we needn't repeatedly iterate through the player
|
||||
// name array server-side unnecessarily
|
||||
_playerCount = _gameobj.getPlayerCount();
|
||||
|
||||
// instantiate a player oid array which we'll fill in later
|
||||
@@ -780,8 +738,8 @@ public class GameManager extends PlaceManager
|
||||
// give delegates a chance to do their thing
|
||||
super.didStartup();
|
||||
|
||||
// let the players of this game know that we're ready to roll (if
|
||||
// we have a specific set of players)
|
||||
// let the players of this game know that we're ready to roll (if we have a specific set of
|
||||
// players)
|
||||
for (int ii = 0; ii < getPlayerSlots(); ii++) {
|
||||
// skip non-existent players and AIs
|
||||
if (!_gameobj.isOccupiedPlayer(ii) || isAI(ii)) {
|
||||
@@ -790,8 +748,7 @@ public class GameManager extends PlaceManager
|
||||
|
||||
BodyObject bobj = CrowdServer.lookupBody(_gameobj.players[ii]);
|
||||
if (bobj == null) {
|
||||
Log.warning("Unable to deliver game ready to non-existent " +
|
||||
"player [game=" + where() +
|
||||
Log.warning("Unable to deliver game ready to non-existent player [game=" + where() +
|
||||
", player=" + _gameobj.players[ii] + "].");
|
||||
continue;
|
||||
}
|
||||
@@ -841,22 +798,21 @@ public class GameManager extends PlaceManager
|
||||
endPlayerGame(pidx);
|
||||
}
|
||||
|
||||
// then complete the bodyLeft() processing which may result in a call
|
||||
// to placeBecameEmpty() which will shut the game down
|
||||
// then complete the bodyLeft() processing which may result in a call to placeBecameEmpty()
|
||||
// which will shut the game down
|
||||
super.bodyLeft(bodyOid);
|
||||
}
|
||||
|
||||
/**
|
||||
* When a game room becomes empty, we cancel the game if it's still in
|
||||
* progress and close down the game room.
|
||||
* When a game room becomes empty, we cancel the game if it's still in progress and close down
|
||||
* the game room.
|
||||
*/
|
||||
protected void placeBecameEmpty ()
|
||||
{
|
||||
// Log.info("Game room empty. Going away. [game=" + where() + "].");
|
||||
|
||||
// if we're in play then move to game over
|
||||
if (_gameobj.state != GameObject.PRE_GAME &&
|
||||
_gameobj.state != GameObject.GAME_OVER &&
|
||||
if (_gameobj.state != GameObject.PRE_GAME && _gameobj.state != GameObject.GAME_OVER &&
|
||||
_gameobj.state != GameObject.CANCELLED) {
|
||||
_gameobj.setState(GameObject.GAME_OVER);
|
||||
// and shutdown directly
|
||||
@@ -870,23 +826,21 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when all players have arrived in the game room. By default,
|
||||
* this starts up the game, but a manager may wish to override this
|
||||
* and start the game according to different criterion.
|
||||
* Called when all players have arrived in the game room. By default, this starts up the game,
|
||||
* but a manager may wish to override this and start the game according to different criterion.
|
||||
*/
|
||||
protected void playersAllHere ()
|
||||
{
|
||||
// if we're a seated game and we haven't already started, start.
|
||||
if ((getGameType() == GameConfig.SEATED_GAME) && (_gameobj.state == GameObject.PRE_GAME)) {
|
||||
if ((getMatchType() == GameConfig.SEATED_GAME) && (_gameobj.state == GameObject.PRE_GAME)) {
|
||||
startGame();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the no-show delay has expired following the delivery
|
||||
* of notifications to all players that the game is ready.
|
||||
* <em>Note:</em> this is not called for party games. Those games have
|
||||
* a human who decides when to start the game.
|
||||
* Called after the no-show delay has expired following the delivery of notifications to all
|
||||
* players that the game is ready. <em>Note:</em> this is not called for party games. Those
|
||||
* games have a human who decides when to start the game.
|
||||
*/
|
||||
protected void checkForNoShows ()
|
||||
{
|
||||
@@ -914,14 +868,13 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when some, but not all, players failed to show up
|
||||
* for a game. The default implementation simply cancels the game.
|
||||
* This is called when some, but not all, players failed to show up for a game. The default
|
||||
* implementation simply cancels the game.
|
||||
*/
|
||||
protected void handlePartialNoShow ()
|
||||
{
|
||||
// mark the no-show players; this will cause allPlayersReady() to
|
||||
// think that everyone has arrived, but still allow us to tell who
|
||||
// has not shown up in gameDidStart()
|
||||
// mark the no-show players; this will cause allPlayersReady() to think that everyone has
|
||||
// arrived, but still allow us to tell who has not shown up in gameDidStart()
|
||||
int humansHere = 0;
|
||||
for (int ii = 0; ii < _playerOids.length; ii++) {
|
||||
if (_playerOids[ii] == 0) {
|
||||
@@ -938,9 +891,8 @@ public class GameManager extends PlaceManager
|
||||
cancelGame();
|
||||
|
||||
} else {
|
||||
// go ahead and report that everyone is ready (which will start the
|
||||
// game); gameDidStart() will take care of giving the boot to
|
||||
// anyone who isn't around
|
||||
// go ahead and report that everyone is ready (which will start the game);
|
||||
// gameDidStart() will take care of giving the boot to anyone who isn't around
|
||||
Log.info("Forcing start of partial no-show game [game=" + where() +
|
||||
", poids=" + StringUtil.toString(_playerOids) + "].");
|
||||
playersAllHere();
|
||||
@@ -948,8 +900,8 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if we should start the game even without any humans.
|
||||
* Default implementation always returns false.
|
||||
* @return true if we should start the game even without any humans. Default implementation
|
||||
* always returns false.
|
||||
*/
|
||||
protected boolean startWithoutHumans ()
|
||||
{
|
||||
@@ -957,11 +909,9 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game is about to start, but before the game start
|
||||
* notification has been delivered to the players. Derived classes
|
||||
* should override this if they need to perform some pre-start
|
||||
* activities, but should be sure to call
|
||||
* <code>super.gameWillStart()</code>.
|
||||
* Called when the game is about to start, but before the game start notification has been
|
||||
* delivered to the players. Derived classes should override this if they need to perform some
|
||||
* pre-start activities, but should be sure to call <code>super.gameWillStart()</code>.
|
||||
*/
|
||||
protected void gameWillStart ()
|
||||
{
|
||||
@@ -977,8 +927,8 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game state changes. This happens after the attribute
|
||||
* change event has propagated.
|
||||
* Called when the game state changes. This happens after the attribute change event has
|
||||
* propagated.
|
||||
*
|
||||
* @param state the new game state.
|
||||
* @param oldState the previous game state.
|
||||
@@ -991,8 +941,8 @@ public class GameManager extends PlaceManager
|
||||
break;
|
||||
|
||||
case GameObject.GAME_OVER:
|
||||
// we do some jiggery pokery to allow derived game objects to have
|
||||
// different notions of what it means to be in play
|
||||
// we do some jiggery pokery to allow derived game objects to have different notions of
|
||||
// what it means to be in play
|
||||
_gameobj.state = oldState;
|
||||
boolean wasInPlay = _gameobj.isInPlay();
|
||||
_gameobj.state = state;
|
||||
@@ -1016,11 +966,10 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the game start notification was dispatched. Derived
|
||||
* classes can override this to put whatever wheels they might need
|
||||
* into motion now that the game is started (if anything other than
|
||||
* transitioning the game to {@link GameObject#IN_PLAY} is necessary),
|
||||
* but should be sure to call <code>super.gameDidStart()</code>.
|
||||
* Called after the game start notification was dispatched. Derived classes can override this
|
||||
* to put whatever wheels they might need into motion now that the game is started (if anything
|
||||
* other than transitioning the game to {@link GameObject#IN_PLAY} is necessary), but should be
|
||||
* sure to call <code>super.gameDidStart()</code>.
|
||||
*/
|
||||
protected void gameDidStart ()
|
||||
{
|
||||
@@ -1034,8 +983,7 @@ public class GameManager extends PlaceManager
|
||||
// inform the players of any pending messages.
|
||||
if (_startmsgs != null) {
|
||||
for (Tuple<String,String> mtup : _startmsgs) {
|
||||
systemMessage(mtup.left, // bundle
|
||||
mtup.right); // message
|
||||
systemMessage(mtup.left, /* bundle */ mtup.right /* message */);
|
||||
}
|
||||
_startmsgs = null;
|
||||
}
|
||||
@@ -1045,8 +993,7 @@ public class GameManager extends PlaceManager
|
||||
AIGameTicker.registerAIGame(this);
|
||||
}
|
||||
|
||||
// any players who have not claimed that they are ready should now
|
||||
// be given le boote royale
|
||||
// any players who have not claimed that they are ready should now be given le boote royale
|
||||
for (int ii = 0; ii < _playerOids.length; ii++) {
|
||||
if (_playerOids[ii] == -1) {
|
||||
Log.info("Booting no-show player [game=" + where() +
|
||||
@@ -1058,8 +1005,7 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the {@link AIGameTicker} if we're registered as an AI
|
||||
* game.
|
||||
* Called by the {@link AIGameTicker} if we're registered as an AI game.
|
||||
*/
|
||||
protected void tickAIs ()
|
||||
{
|
||||
@@ -1097,10 +1043,9 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player has been marked as knocked out but before the
|
||||
* knock-out status update has been sent to the players. Any status
|
||||
* information that needs be updated in light of the knocked out
|
||||
* player can be updated here.
|
||||
* Called when a player has been marked as knocked out but before the knock-out status update
|
||||
* has been sent to the players. Any status information that needs be updated in light of the
|
||||
* knocked out player can be updated here.
|
||||
*/
|
||||
protected void playerGameDidEnd (int pidx)
|
||||
{
|
||||
@@ -1109,13 +1054,11 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player leaves the game in order to determine whether
|
||||
* the game should be ended based on its current state, which will
|
||||
* include updated player status for the player in question. The
|
||||
* default implementation returns true if the game is in play and
|
||||
* there is only one player left. Derived classes may wish to
|
||||
* override this method in order to customize the required end-game
|
||||
* conditions.
|
||||
* Called when a player leaves the game in order to determine whether the game should be ended
|
||||
* based on its current state, which will include updated player status for the player in
|
||||
* question. The default implementation returns true if the game is in play and there is only
|
||||
* one player left. Derived classes may wish to override this method in order to customize the
|
||||
* required end-game conditions.
|
||||
*/
|
||||
protected boolean shouldEndGame ()
|
||||
{
|
||||
@@ -1123,11 +1066,10 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns the final winning status for each player to their respect
|
||||
* player index in the supplied array. This will be called by {@link
|
||||
* #endGame} when the game is over. The default implementation marks
|
||||
* no players as winners. Derived classes should override this method
|
||||
* in order to customize the winning conditions.
|
||||
* Assigns the final winning status for each player to their respect player index in the
|
||||
* supplied array. This will be called by {@link #endGame} when the game is over. The default
|
||||
* implementation marks no players as winners. Derived classes should override this method in
|
||||
* order to customize the winning conditions.
|
||||
*/
|
||||
protected void assignWinners (boolean[] winners)
|
||||
{
|
||||
@@ -1135,11 +1077,9 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game is about to end, but before the game end
|
||||
* notification has been delivered to the players. Derived classes
|
||||
* should override this if they need to perform some pre-end
|
||||
* activities, but should be sure to call
|
||||
* <code>super.gameWillEnd()</code>.
|
||||
* Called when the game is about to end, but before the game end notification has been
|
||||
* delivered to the players. Derived classes should override this if they need to perform some
|
||||
* pre-end activities, but should be sure to call <code>super.gameWillEnd()</code>.
|
||||
*/
|
||||
protected void gameWillEnd ()
|
||||
{
|
||||
@@ -1152,9 +1092,8 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the game has transitioned to the {@link
|
||||
* GameObject#GAME_OVER} state. Derived classes should override this
|
||||
* to perform any post-game activities, but should be sure to call
|
||||
* Called after the game has transitioned to the {@link GameObject#GAME_OVER} state. Derived
|
||||
* classes should override this to perform any post-game activities, but should be sure to call
|
||||
* <code>super.gameDidEnd()</code>.
|
||||
*/
|
||||
protected void gameDidEnd ()
|
||||
@@ -1181,15 +1120,13 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to let the manager know that the game was cancelled (and may be
|
||||
* about to be shutdown if there's no one in the room). In the base
|
||||
* framework a game will only be canceled if no one shows up, so {@link
|
||||
* #gameWillStart}, etc. will never have been called and thus {@link
|
||||
* #gameWillEnd}, etc. will not be called. However, if a game chooses to
|
||||
* cancel itself for whatever reason, no effort will be made to call {@link
|
||||
* #endGame} and the game ending call backs so that game can override this
|
||||
* method to do anything it needs. Note that {@link #didShutdown} will be
|
||||
* called in every case and that's generally the best place to free
|
||||
* Called to let the manager know that the game was cancelled (and may be about to be shutdown
|
||||
* if there's no one in the room). In the base framework a game will only be canceled if no one
|
||||
* shows up, so {@link #gameWillStart}, etc. will never have been called and thus {@link
|
||||
* #gameWillEnd}, etc. will not be called. However, if a game chooses to cancel itself for
|
||||
* whatever reason, no effort will be made to call {@link #endGame} and the game ending call
|
||||
* backs so that game can override this method to do anything it needs. Note that {@link
|
||||
* #didShutdown} will be called in every case and that's generally the best place to free
|
||||
* resources so this method may not be needed.
|
||||
*/
|
||||
protected void gameWasCancelled ()
|
||||
@@ -1198,8 +1135,7 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Report winner and loser oids to each room that any of the
|
||||
* winners/losers is in.
|
||||
* Report winner and loser oids to each room that any of the winners/losers is in.
|
||||
*/
|
||||
protected void reportWinnersAndLosers ()
|
||||
{
|
||||
@@ -1218,8 +1154,7 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
}
|
||||
|
||||
Object[] args =
|
||||
new Object[] { winners.toIntArray(), losers.toIntArray() };
|
||||
Object[] args = new Object[] { winners.toIntArray(), losers.toIntArray() };
|
||||
|
||||
// now send a message event to each room
|
||||
for (int ii=0, nn = places.size(); ii < nn; ii++) {
|
||||
@@ -1231,10 +1166,9 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game is about to reset, but before the board has
|
||||
* been re-initialized or any other clearing out of game data has
|
||||
* taken place. Derived classes should override this if they need to
|
||||
* perform some pre-reset activities.
|
||||
* Called when the game is about to reset, but before the board has been re-initialized or any
|
||||
* other clearing out of game data has taken place. Derived classes should override this if
|
||||
* they need to perform some pre-reset activities.
|
||||
*/
|
||||
protected void gameWillReset ()
|
||||
{
|
||||
@@ -1250,8 +1184,8 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives game managers an opportunity to perform periodic processing
|
||||
* that is not driven by events generated by the player.
|
||||
* Gives game managers an opportunity to perform periodic processing that is not driven by
|
||||
* events generated by the player.
|
||||
*/
|
||||
protected void tick (long tickStamp)
|
||||
{
|
||||
@@ -1259,8 +1193,7 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Called periodically to call {@link #tick} on all registered game
|
||||
* managers.
|
||||
* Called periodically to call {@link #tick} on all registered game managers.
|
||||
*/
|
||||
protected static void tickAllGames ()
|
||||
{
|
||||
@@ -1271,8 +1204,7 @@ public class GameManager extends PlaceManager
|
||||
try {
|
||||
gmgr.tick(now);
|
||||
} catch (Exception e) {
|
||||
Log.warning(
|
||||
"Game manager choked during tick [gmgr=" + gmgr + "].");
|
||||
Log.warning("Game manager choked during tick [gmgr=" + gmgr + "].");
|
||||
Log.logStackTrace(e);
|
||||
}
|
||||
}
|
||||
@@ -1298,8 +1230,7 @@ public class GameManager extends PlaceManager
|
||||
}
|
||||
|
||||
/** Listens for game state changes. */
|
||||
protected AttributeChangeListener _stateListener =
|
||||
new AttributeChangeListener() {
|
||||
protected AttributeChangeListener _stateListener = new AttributeChangeListener() {
|
||||
public void attributeChanged (AttributeChangedEvent event) {
|
||||
if (event.getName().equals(GameObject.STATE)) {
|
||||
stateDidChange(_committedState = event.getIntValue(),
|
||||
@@ -1320,19 +1251,17 @@ public class GameManager extends PlaceManager
|
||||
/** The oids of our player and AI body objects. */
|
||||
protected int[] _playerOids;
|
||||
|
||||
/** If AIs are present, contains their configuration, or null at human
|
||||
* player indexes. */
|
||||
/** If AIs are present, contains their configuration, or null at human player indexes. */
|
||||
protected GameAI[] _AIs;
|
||||
|
||||
/** If non-null, contains bundles and messages that should be sent as
|
||||
* system messages once the game has started. */
|
||||
/** If non-null, contains bundles and messages that should be sent as system messages once the
|
||||
* game has started. */
|
||||
protected ArrayList<Tuple<String,String>> _startmsgs;
|
||||
|
||||
/** Our delegate operator to tick AIs. */
|
||||
protected TickAIDelegateOp _tickAIOp;
|
||||
|
||||
/** The state of the game that has been propagated to our
|
||||
* subscribers. */
|
||||
/** The state of the game that has been propagated to our subscribers. */
|
||||
protected int _committedState;
|
||||
|
||||
/** TEMP: debugging the pending rating double release bug. */
|
||||
@@ -1342,14 +1271,13 @@ public class GameManager extends PlaceManager
|
||||
protected boolean _postponedStart = false;
|
||||
|
||||
/** A list of all currently active game managers. */
|
||||
protected static ArrayList<GameManager> _managers =
|
||||
new ArrayList<GameManager>();
|
||||
protected static ArrayList<GameManager> _managers = new ArrayList<GameManager>();
|
||||
|
||||
/** The interval for the game manager tick. */
|
||||
protected static Interval _tickInterval;
|
||||
|
||||
/** We give players 30 seconds to turn up in a game; after that,
|
||||
* they're considered a no show. */
|
||||
/** We give players 30 seconds to turn up in a game; after that, they're considered a no
|
||||
* show. */
|
||||
protected static final long NOSHOW_DELAY = 30 * 1000L;
|
||||
|
||||
/** The delay in milliseconds between ticking of all game managers. */
|
||||
|
||||
+1
-1
@@ -96,7 +96,7 @@
|
||||
<!-- build the java class files -->
|
||||
<target name="compile" depends="prepare">
|
||||
<javac srcdir="${src.dir}" destdir="${classes.dir}"
|
||||
debug="on" optimize="off" deprecation="off">
|
||||
debug="on" optimize="off" deprecation="on">
|
||||
<classpath refid="classpath"/>
|
||||
<exclude name="com/threerings/**/tools/xml/**" unless="build.xml"/>
|
||||
</javac>
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
package com.threerings.parlor;
|
||||
|
||||
import com.threerings.crowd.client.PlaceController;
|
||||
import com.threerings.parlor.game.client.GameConfigurator;
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
|
||||
@@ -29,19 +30,24 @@ public class TestConfig extends GameConfig
|
||||
/** The foozle parameter. */
|
||||
public int foozle;
|
||||
|
||||
public int getGameId ()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String getGameIdent ()
|
||||
{
|
||||
return "test";
|
||||
}
|
||||
|
||||
public GameConfigurator createConfigurator ()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public Class getControllerClass ()
|
||||
public PlaceController createController ()
|
||||
{
|
||||
return TestController.class;
|
||||
}
|
||||
|
||||
public String getBundleName ()
|
||||
{
|
||||
return "test";
|
||||
return new TestController();
|
||||
}
|
||||
|
||||
public String getManagerClassName ()
|
||||
|
||||
@@ -21,14 +21,15 @@
|
||||
|
||||
package com.threerings.whirled;
|
||||
|
||||
import com.threerings.crowd.client.PlaceController;
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
import com.threerings.whirled.server.SceneManager;
|
||||
|
||||
public class TestConfig extends PlaceConfig
|
||||
{
|
||||
public Class getControllerClass ()
|
||||
public PlaceController createController ()
|
||||
{
|
||||
return TestController.class;
|
||||
return new TestController();
|
||||
}
|
||||
|
||||
public String getManagerClassName ()
|
||||
|
||||
Reference in New Issue
Block a user