AVRG FAQ

From Whirled Club Wiki
Jump to: navigation, search
Frequently Asked Questions
Icon-whirled.png General | Icon-bars.png Billing | Icon-whirled.png Technical Issues

Icon-highlighted-avatar.png Avatar Creation | Icon-highlighted-game.png AVR Games | Icon-highlighted-game.png Game Creation | Icon-highlighted-backdrop.png Room Editing | Icon-whirled.png Whirleds (themed)
Icon-whirled.png Example code (SVN) | Icon-whirled.png Content Copying & Derivation | Icon-whirled.png Digital Millennium Copyright Act Policy
Icon-Programming.png Config Troubleshooting

Useful Groups: Bug Hunters | Whirled Builders | Whirled Coders

These are some frequently asked questions about AVR games.

When does the server agent shut down?

The server agent shuts down under 2 conditions:

1. There have been no players playing the game for a certain duration. At the time of this writing, this duration is 5 minutes. So if the game is popular enough, it may never shut down.

2. When you relist the game in the catalog, the game server evicts all the players and restarts the agent. There are plans in place to allow the game code to do the eviction so that the player experience is more pleasant, but we don't know when that will be enabled.

Why can't I set properties from the client?

AVRGs require a server agent in order to run. The restriction on properties is to encourage game authors to embed more of the game logic in the server agent code rather than in the clients.

One exception to the rule is player properties, clients can set properties only for the local player like this:

<actionscript> _control.player.props.set("Property", value); </actionscript>

How do I make a property persistent?

You can use the NetConstants.makePersistent method to flag a property as persistent so that it will remain set even after the server agent has shut down and a new server agent has started.

<actionscript> var propName:String = NetConstants.makePersistent("someProperty"); _control.getRoom(roomId).props.set(propName, {some:"Value"}); </actionscript>

To retrieve a property persisted this way, use the persisted property name generated by makePersistent:

<actionscript> var propName:String = NetConstants.makePersistent("someProperty"); something = _control.getRoom(roomId).props.get(propName); </actionscript>

Message limits

What is the message limit for the server agent?

For the server agent, there are separate message limits for each server that the agent is connected to and how many objects on that server are in use by the game. Here are the rules:

  • "Game messages" are sent via the game server and the limit is 100 * (1 + log(N)) per 10 seconds, where N is the number of players. Here are some sample values of the limit for various numbers of players (that's total number):
Players Messages/second
1 10
2 15
3 21
4 24
10 33
20 40
64 51

Game messages include all operations (not accessors) on GameSubControlServer and all operations and non-avatar methods (like deactivateGame and completeTask) on PlayerSubControlServer.

The logarithmic limit is intended to encourage creators to not use per player messaging and properties very heavily, but instead use room-wide group communications where possible.

  • "Room messages" are sent via the world server connection and the limit is 100 * N per 10 seconds, where N is the number rooms that are active on that server.

Room message include all operations (not accessors) on RoomSubControlServer and the avatar operations on PlayerSubControlServer.

  • There are plans to do some automatic batching for each kind of message and further batching within that for each target property space. This will be announced when it is ready in the SDK release notes.

What is the message limit for the game client?

The game client message limit is simpler than that for the server agent. The client can send up to 100 room messages and 100 game messages per 10 seconds.

On the client, only the PlayerSubControlClient operations (not accessors) perform messaging. In here, the avatar operations contribute to the room total and the other operations contribute to the game total.

How can I avoid hitting the message limit?

The message limits that we set should be adequate for any game. The best thing you can do is design your messaging to be lean and mean. Here are a few rules of thumb:

  • Never send a message from the agent in direct response to a player event. This is almost certain to go over the limit when a lot of players are all interacting rapidly with the game. Instead, batch the player actions and send updates at a fixed frequency, say 2 per second. This can be coupled with some client logic to estimate the game state between official server agent updates and increase smoothness.
  • Avoid per-player private messaging except on rare occasions. For example, rewarding a player with a new item for passing a level may be ok if levels take a few minutes to finish. If you are implementing a minigame that can be played by one player, just have the client send the results of the game and/or periodic sanity checks to the server agent. Don't process every move on the server.
  • Use doBatch. If you have several room operations and several game operations to perform at once, use the doBatch function to send all the room ones together and all the game ones together:

<actionscript> _control.doBatch(function () :void {

   doSomeRoomStuff();
   doSomeGameStuff();

}) </actionscript>

What happens if I exceed the message limit?

If you exceed the message limit on the client, the connection to the server in question will be forcibly terminated. This will usually cause the user's game session to end.

If the game message limit is exceeded by the server agent, the server agent will shut down, causing all players' games to end.

If the world message limit is exceeded by the server agent, the server agent will no longer be able to access any room information and the behavior of the game will most likely become very erratic and unplayable.

This behavior will hopefully be made more sensible at some stage, but until then be sure not to exceed the message limits.

What are the limits on properties (for players, rooms, and games, persistent and transient, maximum size)?

The encoded size of a persistent property can be no more than 4K. We mostly just use AMF3 encoding wrapped in a com.threerings.io.ObjectOutputStream.

Exception #1 to the use of AMF3 encoding: if the property is a Dictionary, we circumvent the AMF3 encoding and assume that the keys are integral. The size followed by a key/value pair for each entry is encoded using AMF3 (see GameMap) prior to wrapping in ObjectOutputStream.

Exception #2 to the use of AMF3 encoding: if the property is an Array, we circumvent the AMF3 encoding and store instead an array of encoded values prior to wrapping in the ObjectOutputStream.

The reason for these exceptions is to allow the implementation of setAt and setIn.

AMF3 introduces some overhead and ObjectOutputStream introduces a very small overhead (since the objects are already converted to assemblies of arrays of bytes by the time they are persisted, only 2 bytes of type information per object are stored). If you think you may be getting close to the limit, convert your property values to a ByteArray before assigning them, or use multiple propeties.

Transient properties have no encoded size limit at this time.

There is no limit at this time on the number of persistent or transient properties a game may store in a particular property space.

How can I track players moving between rooms?

You can listen for a player entering and leaving the room separately. Here's a class that will just trace the enter/leave events to the output console:

RoomTrace.as <actionscript> package {

import com.whirled.avrg.PlayerSubControlBase; import com.whirled.avrg.AVRGameControl; import com.whirled.avrg.AVRServerGameControl; import com.whirled.avrg.AVRGamePlayerEvent;

public class RoomTrace {

   public function RoomTrace (player :PlayerSubControlBase)
   {
       player.addEventListener(AVRGamePlayerEvent.ENTERED_ROOM, entered);
       player.addEventListener(AVRGamePlayerEvent.LEFT_ROOM, left);
   }
   protected function entered (evt :AVRGamePlayerEvent) :void
   {
       trace("Player entered, evt=" + evt);
   }
   protected function left (evt :AVRGamePlayerEvent) :void
   {
       trace("Player left, evt=" + evt);
   }

} } </actionscript>

Here's a server agent that will attach the trace object to any player that enters the game:

Server.as <actionscript> package {

import com.whirled.ServerObject; import com.whirled.avrg.AVRServerGameControl; import com.whirled.avrg.AVRGameControlEvent;

public class Server extends ServerObject {

   public function Server ()
   {
       _control = new AVRServerGameControl(this);
       _control.game.addEventListener(AVRGameControlEvent.PLAYER_JOINED_GAME, joined);
   }
   protected function joined (evt :AVRGameControlEvent) :void
   {
       new RoomTrace(_control.getPlayer(evt.value as int));
   }
   protected var _control :AVRServerGameControl;

} } </actionscript>

Here's a client top-level object that attaches the trace to the local player:

Client.as <actionscript> package {

import flash.display.Sprite; import com.whirled.avrg.AVRGameControl;

public class Client extends Sprite {

   public function Client ()
   {
       _control = new AVRGameControl(this);
       new RoomTrace(_control.player);
   }
   protected var _control :AVRGameControl;

} } </actionscript>

See enteredRoom and leftRoom.

How do I debug my AVRG?

You can use the AVRG probe.