diff --git a/src/as/com/threerings/ezgame/EZGameControl.as b/src/as/com/threerings/ezgame/EZGameControl.as index f3bc2c5e..91338264 100644 --- a/src/as/com/threerings/ezgame/EZGameControl.as +++ b/src/as/com/threerings/ezgame/EZGameControl.as @@ -170,6 +170,14 @@ public class EZGameControl extends BaseControl return (_gameData != null); } + /** + * Get any game-specific configurations that were set up in the lobby. + */ + public function getConfig () :Object + { + return _gameConfig; + } + /** * Get the CollectionsControl, which contains methods for utilizing the server to dispatch * private information. @@ -603,6 +611,10 @@ public class EZGameControl extends BaseControl { // get our gamedata _gameData = o.gameData; + _gameConfig = o.gameConfig; + if (_gameConfig == null) { + _gameConfig = {}; + } // and functions _funcs = o; @@ -670,6 +682,9 @@ public class EZGameControl extends BaseControl /** Contains the data properties shared by all players in the game. */ protected var _gameData :Object; + /** Contains any custom game configuration data. */ + protected var _gameConfig :Object; + /** Contains functions exposed to us from the EZGame host. */ protected var _funcs :Object; diff --git a/src/as/com/threerings/ezgame/client/EZGameConfigurator.as b/src/as/com/threerings/ezgame/client/EZGameConfigurator.as new file mode 100644 index 00000000..ccc3f458 --- /dev/null +++ b/src/as/com/threerings/ezgame/client/EZGameConfigurator.as @@ -0,0 +1,197 @@ +// +// $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 mx.core.UIComponent; +import mx.controls.CheckBox; +import mx.controls.ComboBox; +import mx.controls.HSlider; +import mx.controls.Label; + +import com.threerings.util.StringUtil; + +import com.threerings.parlor.game.client.FlexGameConfigurator; + +import com.threerings.ezgame.data.EZGameConfig; + +/** + * Adds custom configuration of options specified in XML. + */ +public class EZGameConfigurator extends FlexGameConfigurator +{ + /** + * Set a String of configData, which is hopefully XML formatted with + * some game configuration options. + */ + public function setXMLConfig (configData :String) :void + { + var log :Log = Log.getLog(this); + + var config :XML = XML(configData); + 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 (ident :String, control :UIComponent) :void + { + var name :String = ident.replace("_", " "); + var lbl :Label = new Label(); + lbl.text = name + ":"; + 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 + "]."); + return; + } + + var slider :HSlider = new HSlider(); + slider.minimum = min; + slider.maximum = max; + slider.value = start; + slider.liveDragging = true; + slider.snapInterval = 1; + + addXMLControl(spec.@ident, 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); + if (startDex == -1) { + log.warning("Choice start value does not appear in list of choices "+ + "[xml=" + spec + "]."); + return; + } + + var box :ComboBox = new ComboBox(); + box.dataProvider = choices; + box.selectedIndex = startDex; + + addXMLControl(spec.@ident, box); + } + + /** + * 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.@ident, box); + } + + override protected function flushGameConfig () :void + { + super.flushGameConfig(); + + // if there were any custom XML configs, flush those as well. + if (_customConfigs.length > 0) { + var options :Object = {}; + + 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 HSlider) { + options[ident] = (control as HSlider).value; + + } else if (control is CheckBox) { + options[ident] = (control as CheckBox).selected; + + } else if (control is ComboBox) { + options[ident] = (control as ComboBox).value; + + } else { + Log.getLog(this).warning("Unknow custom config type " + control); + } + } + + (_config as EZGameConfig).customConfig = options; + } + } + + /** Contains pairs of identString, control, identString, control.. */ + protected var _customConfigs :Array = []; +} +} diff --git a/src/as/com/threerings/ezgame/client/GameControlBackend.as b/src/as/com/threerings/ezgame/client/GameControlBackend.as index e218440e..f1c14c6a 100644 --- a/src/as/com/threerings/ezgame/client/GameControlBackend.as +++ b/src/as/com/threerings/ezgame/client/GameControlBackend.as @@ -73,6 +73,7 @@ import com.threerings.crowd.util.CrowdContext; import com.threerings.parlor.game.data.GameObject; +import com.threerings.ezgame.data.EZGameConfig; import com.threerings.ezgame.data.EZGameObject; import com.threerings.ezgame.data.PropertySetEvent; import com.threerings.ezgame.data.PropertySetListener; @@ -167,6 +168,7 @@ public class GameControlBackend // straight data o["gameData"] = _gameData; + o["gameConfig"] = (_ctrl.getPlaceConfig() as EZGameConfig).customConfig; // functions o["setProperty_v1"] = setProperty_v1; diff --git a/src/as/com/threerings/ezgame/data/EZGameConfig.as b/src/as/com/threerings/ezgame/data/EZGameConfig.as index 6274f3fd..bd28aa00 100644 --- a/src/as/com/threerings/ezgame/data/EZGameConfig.as +++ b/src/as/com/threerings/ezgame/data/EZGameConfig.as @@ -33,6 +33,7 @@ import com.threerings.parlor.game.client.GameConfigurator; import com.threerings.parlor.game.data.GameConfig; import com.threerings.ezgame.client.EZGameController; +import com.threerings.ezgame.util.EZObjectMarshaller; /** * A game config for a simple multiplayer ez game. @@ -53,6 +54,9 @@ public class EZGameConfig extends GameConfig /** The game type. */ public var gameType :int = SEATED_GAME; + /** Any custom configuration options. */ + public var customConfig :Object; + public function EZGameConfig () { // nothing needed @@ -115,6 +119,8 @@ public class EZGameConfig extends GameConfig persistentGameId = ins.readInt(); gameMedia = (ins.readField(String) as String); gameType = ins.readByte(); + + customConfig = EZObjectMarshaller.decode(ins.readObject()); } // from interface Streamable @@ -126,6 +132,8 @@ public class EZGameConfig extends GameConfig out.writeInt(persistentGameId); out.writeField(gameMedia); out.writeByte(gameType); + + out.writeObject(EZObjectMarshaller.encode(customConfig, false)); } } } diff --git a/src/java/com/threerings/ezgame/data/EZGameConfig.java b/src/java/com/threerings/ezgame/data/EZGameConfig.java index 0999fe19..bb40e48b 100644 --- a/src/java/com/threerings/ezgame/data/EZGameConfig.java +++ b/src/java/com/threerings/ezgame/data/EZGameConfig.java @@ -49,6 +49,10 @@ public class EZGameConfig extends GameConfig /** 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 () {