diff --git a/src/as/com/threerings/ezgame/EZGame.as b/src/as/com/threerings/ezgame/EZGame.as index 1afa3f80..461a79e6 100644 --- a/src/as/com/threerings/ezgame/EZGame.as +++ b/src/as/com/threerings/ezgame/EZGame.as @@ -89,6 +89,19 @@ public interface EZGame function sendMessage ( messageName :String, value :Object, playerIndex :int = -1) :void; + /** + * Start the ticker with the specified name. It will deliver + * messages to the game object at the specified delay, + * the value of each message being a single integer, starting with 0 + * and increasing by one with each messsage. + */ + function startTicker (tickerName :String, msOfDelay :int) :void; + + /** + * Stop the specified ticker. + */ + function stopTicker (tickerName :String) :void; + /** * Send a message that will be heard by everyone in the game room, * even observers. diff --git a/src/as/com/threerings/ezgame/client/EZGameService.as b/src/as/com/threerings/ezgame/client/EZGameService.as index 29c47715..da588df8 100644 --- a/src/as/com/threerings/ezgame/client/EZGameService.as +++ b/src/as/com/threerings/ezgame/client/EZGameService.as @@ -74,5 +74,16 @@ public interface EZGameService extends InvocationService client :Client, collName :String, consume :Boolean, count :int, msgOrPropName :String, playerIndex :int, listener :InvocationService_ConfirmListener) :void; + + /** + * Start a ticker that will send out timestamp information at + * the interval specified. + * + * @param msOfDelay must be at least 50, or 0 may be set to halt + * and clear a previously started ticker. + */ + function setTicker ( + client :Client, tickerName :String, msOfDelay :int, + listener :InvocationService_InvocationListener) :void; } } diff --git a/src/as/com/threerings/ezgame/client/GameObjectImpl.as b/src/as/com/threerings/ezgame/client/GameObjectImpl.as index a2ef7fcd..2c163c60 100644 --- a/src/as/com/threerings/ezgame/client/GameObjectImpl.as +++ b/src/as/com/threerings/ezgame/client/GameObjectImpl.as @@ -184,6 +184,20 @@ public class GameObjectImpl extends EventDispatcher createLoggingListener("sendMessage")); } + // from EZGame + public function startTicker (tickerName :String, msOfDelay :int) :void + { + validateName(tickerName); + _ezObj.ezGameService.setTicker(_ctx.getClient(), + tickerName, msOfDelay, createLoggingListener("setTicker")); + } + + // from EZGame + public function stopTicker (tickerName :String) :void + { + startTicker(tickerName, 0); + } + // from EZGame public function sendChat (msg :String) :void { diff --git a/src/as/com/threerings/ezgame/data/EZGameMarshaller.as b/src/as/com/threerings/ezgame/data/EZGameMarshaller.as index 9c3ec2de..2b049535 100644 --- a/src/as/com/threerings/ezgame/data/EZGameMarshaller.as +++ b/src/as/com/threerings/ezgame/data/EZGameMarshaller.as @@ -121,5 +121,18 @@ public class EZGameMarshaller extends InvocationMarshaller ]); } + /** The method id used to dispatch {@link #setTicker} requests. */ + public static const SET_TICKER :int = 8; + + // documentation inherited from interface + public function setTicker (arg1 :Client, arg2 :String, arg3 :int, arg4 :InvocationService_InvocationListener) :void + { + var listener4 :InvocationMarshaller_ListenerMarshaller = new InvocationMarshaller_ListenerMarshaller(); + listener4.listener = arg4; + sendRequest(arg1, SET_TICKER, [ + arg2, Integer.valueOf(arg3), listener4 + ]); + } + } } diff --git a/src/java/com/threerings/ezgame/EZGame.java b/src/java/com/threerings/ezgame/EZGame.java index a55fa784..9a0a3985 100644 --- a/src/java/com/threerings/ezgame/EZGame.java +++ b/src/java/com/threerings/ezgame/EZGame.java @@ -110,6 +110,19 @@ public interface EZGame public void sendMessage ( String messageName, Object value, int playerIndex); + /** + * Start the ticker with the specified name. It will deliver + * messages to the game object at the specified delay, + * the value of each message being a single integer, starting with 0 + * and increasing by one with each messsage. + */ + public void startTicker (String tickerName, int msOfDelay); + + /** + * Stop the specified ticker. + */ + public void stopTicker (String tickerName); + /** * Send a message that will be heard by everyone in the game room, * even observers. diff --git a/src/java/com/threerings/ezgame/client/EZGameService.java b/src/java/com/threerings/ezgame/client/EZGameService.java index e23e861f..d85a4e62 100644 --- a/src/java/com/threerings/ezgame/client/EZGameService.java +++ b/src/java/com/threerings/ezgame/client/EZGameService.java @@ -72,4 +72,15 @@ public interface EZGameService extends InvocationService public void getFromCollection ( Client client, String collName, boolean consume, int count, String msgOrPropName, int playerIndex, ConfirmListener listener); + + /** + * Start a ticker that will send out timestamp information at + * the interval specified. + * + * @param msOfDelay must be at least 50, or 0 may be set to halt + * and clear a previously started ticker. + */ + public void setTicker ( + Client client, String tickerName, int msOfDelay, + InvocationListener listener); } diff --git a/src/java/com/threerings/ezgame/client/GameObjectImpl.java b/src/java/com/threerings/ezgame/client/GameObjectImpl.java index ac923073..2aa146fb 100644 --- a/src/java/com/threerings/ezgame/client/GameObjectImpl.java +++ b/src/java/com/threerings/ezgame/client/GameObjectImpl.java @@ -168,6 +168,20 @@ public class GameObjectImpl createLoggingListener("sendMessage")); } + // from EZGame + public void startTicker (String tickerName, int msOfDelay) + { + validateName(tickerName); + _ezObj.ezGameService.setTicker(_ctx.getClient(), + tickerName, msOfDelay, createLoggingListener("setTicker")); + } + + // from EZGame + public void stopTicker (String tickerName) + { + startTicker(tickerName, 0); + } + // from EZGame public void sendChat (String msg) { diff --git a/src/java/com/threerings/ezgame/data/EZGameMarshaller.java b/src/java/com/threerings/ezgame/data/EZGameMarshaller.java index 4419aae9..5f6b6b1a 100644 --- a/src/java/com/threerings/ezgame/data/EZGameMarshaller.java +++ b/src/java/com/threerings/ezgame/data/EZGameMarshaller.java @@ -1,5 +1,23 @@ // // $Id$ +// +// Vilya library - tools for developing networked games +// Copyright (C) 2002-2006 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; @@ -110,4 +128,17 @@ public class EZGameMarshaller extends InvocationMarshaller }); } + /** The method id used to dispatch {@link #setTicker} requests. */ + public static final int SET_TICKER = 8; + + // documentation inherited from interface + public void setTicker (Client arg1, String arg2, int arg3, InvocationService.InvocationListener arg4) + { + ListenerMarshaller listener4 = new ListenerMarshaller(); + listener4.listener = arg4; + sendRequest(arg1, SET_TICKER, new Object[] { + arg2, Integer.valueOf(arg3), listener4 + }); + } + } diff --git a/src/java/com/threerings/ezgame/server/EZGameDispatcher.java b/src/java/com/threerings/ezgame/server/EZGameDispatcher.java index c5c4e029..63406994 100644 --- a/src/java/com/threerings/ezgame/server/EZGameDispatcher.java +++ b/src/java/com/threerings/ezgame/server/EZGameDispatcher.java @@ -1,5 +1,23 @@ // // $Id$ +// +// Vilya library - tools for developing networked games +// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved +// http://www.threerings.net/code/vilya/ +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA package com.threerings.ezgame.server; @@ -26,13 +44,13 @@ public class EZGameDispatcher extends InvocationDispatcher this.provider = provider; } - // documentation inherited + // from InvocationDispatcher public InvocationMarshaller createMarshaller () { return new EZGameMarshaller(); } - // documentation inherited + @SuppressWarnings("unchecked") // from InvocationDispatcher public void dispatchRequest ( ClientObject source, int methodId, Object[] args) throws InvocationException @@ -87,6 +105,13 @@ public class EZGameDispatcher extends InvocationDispatcher ); return; + case EZGameMarshaller.SET_TICKER: + ((EZGameProvider)provider).setTicker( + source, + (String)args[0], ((Integer)args[1]).intValue(), (InvocationService.InvocationListener)args[2] + ); + return; + default: super.dispatchRequest(source, methodId, args); return; diff --git a/src/java/com/threerings/ezgame/server/EZGameManager.java b/src/java/com/threerings/ezgame/server/EZGameManager.java index 1d5a21d8..081a4833 100644 --- a/src/java/com/threerings/ezgame/server/EZGameManager.java +++ b/src/java/com/threerings/ezgame/server/EZGameManager.java @@ -8,6 +8,7 @@ import java.util.HashMap; import com.samskivert.util.ArrayUtil; import com.samskivert.util.CollectionUtil; +import com.samskivert.util.Interval; import com.samskivert.util.RandomUtil; import com.threerings.util.Name; @@ -15,6 +16,8 @@ import com.threerings.util.Name; import com.threerings.presents.data.ClientObject; import com.threerings.presents.data.InvocationCodes; import com.threerings.presents.dobj.AccessController; +import com.threerings.presents.dobj.DObjectManager; +import com.threerings.presents.dobj.MessageEvent; import com.threerings.presents.client.InvocationService; import com.threerings.presents.server.InvocationException; @@ -196,6 +199,45 @@ public class EZGameManager extends GameManager } } + // from EZGameProvider + public void setTicker ( + ClientObject caller, String tickerName, int msOfDelay, + InvocationService.InvocationListener listener) + throws InvocationException + { + validateUser(caller); + + Ticker t; + if (msOfDelay >= MIN_TICKER_DELAY) { + if (_tickers != null) { + t = _tickers.get(tickerName); + + } else { + _tickers = new HashMap(); + t = null; + } + if (t == null) { + if (_tickers.size() >= MAX_TICKERS) { + throw new InvocationException(ACCESS_DENIED); + } + t = new Ticker(tickerName, _gameObj); + _tickers.put(tickerName, t); + } + t.start(msOfDelay); + + } else if (msOfDelay <= 0) { + if (_tickers != null) { + t = _tickers.remove(tickerName); + if (t != null) { + t.stop(); + } + } + + } else { + throw new InvocationException(ACCESS_DENIED); + } + } + /** * Helper method to send a private message to the specified player * index (must already be verified). @@ -273,10 +315,19 @@ public class EZGameManager extends GameManager protected void didShutdown () { CrowdServer.invmgr.clearDispatcher(_gameObj.ezGameService); + stopTickers(); super.didShutdown(); } + @Override + protected void gameDidEnd () + { + stopTickers(); + + super.gameDidEnd(); + } + @Override protected void assignWinners (boolean[] winners) { @@ -290,6 +341,70 @@ public class EZGameManager extends GameManager } } + /** + * Stop and clear all tickers. + */ + protected void stopTickers () + { + if (_tickers != null) { + for (Ticker ticker : _tickers.values()) { + ticker.stop(); + } + _tickers = null; + } + } + + /** + * A timer that fires message events to a game. + */ + protected static class Ticker + { + /** + * Create a Ticker. + */ + public Ticker (String name, EZGameObject gameObj) + { + _name = name; + // once we are constructed, we want to avoid calling + // methods on dobjs. + _oid = gameObj.getOid(); + _omgr = gameObj.getManager(); + } + + public void start (int msOfDelay) + { + _value = 0; + _interval.schedule(0, msOfDelay); + } + + public void stop () + { + _interval.cancel(); + } + + /** The interval that does our work. Note well that this is + * not a 'safe' interval that operates using a RunQueue. + * This interval instead does something that we happen to know + * is safe for any thread: posting an event to the dobj manager. + * If we were using a RunQueue it would be the same event queue + * and we would be posted there, wait our turn, and then do the same + * thing: post this event. We just expedite the process. + */ + protected Interval _interval = new Interval() { + public void expired () + { + _omgr.postEvent( + new MessageEvent(_oid, EZGameObject.USER_MESSAGE, + new Object[] { _name, _value++ })); + } + }; + + protected int _oid; + protected DObjectManager _omgr; + protected String _name; + protected int _value; + } // End: static class Ticker + /** A nice casted reference to the game object. */ protected EZGameObject _gameObj; @@ -301,4 +416,13 @@ public class EZGameManager extends GameManager /** The map of collections, lazy-initialized. */ protected HashMap> _collections; + + /** The map of tickers, lazy-initialized. */ + protected HashMap _tickers; + + /** The minimum delay a ticker can have. */ + protected static final int MIN_TICKER_DELAY = 50; + + /** The maximum number of tickers allowed at one time. */ + protected static final int MAX_TICKERS = 3; } diff --git a/src/java/com/threerings/ezgame/server/EZGameProvider.java b/src/java/com/threerings/ezgame/server/EZGameProvider.java index efab18c3..da2e932b 100644 --- a/src/java/com/threerings/ezgame/server/EZGameProvider.java +++ b/src/java/com/threerings/ezgame/server/EZGameProvider.java @@ -1,5 +1,23 @@ // // $Id$ +// +// Vilya library - tools for developing networked games +// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved +// http://www.threerings.net/code/vilya/ +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA package com.threerings.ezgame.server; @@ -56,4 +74,10 @@ public interface EZGameProvider extends InvocationProvider */ public void setProperty (ClientObject caller, String arg1, Object arg2, int arg3, InvocationService.InvocationListener arg4) throws InvocationException; + + /** + * Handles a {@link EZGameService#setTicker} request. + */ + public void setTicker (ClientObject caller, String arg1, int arg2, InvocationService.InvocationListener arg3) + throws InvocationException; }