[ Introduction
]
In this tutorial we will take a closer look to Server Side variables
in SmartFoxServer, how they work and why they
are useful. In particular the article is focused on RoomVariables.
We have already encountered them in the board game tutorials and
they have been usefull to keep custom user data in the room without
having to write server side code.
[ Requirements ]
Before proceeding with this tutorial it is necessary that
you're already familiar with the basic SmartFoxServer concepts
explained in the previous articles.
[ Objectives ]
The example application shows the various features of the Room
Variables objects and allow to see them in action.
The interface will show the variables available in each room and you will be
able to create new ones, modify and delete them, change their attributes and
so on.
[ The setRoomVariables()
method ]
As we have already seen in the other articles SmartFoxServer allows
data to be stored on the server side using RoomVariables and UserVariables.
The first ones store data at room level and the second ones store data at User
level. Each has is own advanatges: for example if you want to keep track of
the position of an avatar for each client in the room you can save this property
in each User, by using UserVariables.
On the other hand if you want to keep track of the status of a board game,
say a battle-ship game, it would be better to keep those values at Room level.
In both cases data saved on the server-side is shared across all other users,
so that they are constantly kept in synch as data is updated.
Before we analyze the application I'd like to show you how RoomVariables are
created with a client request.
The SmartFoxServer Client API command used is setRoomVariables(varList) where
varList is an Array of objects each one representing a
variable with the following properties:
name |
the name of the server side variable |
val |
the value of the variable |
priv |
a boolean flag, if true the variable is private and it can't
be changed by another user except the one who created it |
persistent |
a boolean flag, if true the variables persist until the user
who created it disconnects. |
As you can see everything sounds pretty simple, just give your
variables a name and value and you're ready to use them!
The two boolean flags available need a more in-depth look at how
these variables work.
In the most simple case we can set a RoomVariable like this:
var varList:Array = []
var roomVar:Object = {name:"test", value:"Hello world!"}
varList.push(roomVar)
smartFox.setRoomVariables(varList)
We first create an empty array that will hold the variables we'd
like to create, in this case just one variable.
Then we declare an Object with name and value properties which represents our
simple variable and finally we send the request to the server.
By default the variable is going to be created and sent to the
other clients in the room. It will be destroyed when its owner
will go out of the room where the variable was generated.
Once the variable exist in the room other users may update it
as well, and if they do the ownership of the variable is changed
to the last user who has modified it. If you want to avoid this
behaviour you should set the "priv" flag
to true, this way no one will overwrite your server side values.
Setting the "persistent" flag to true
will allow your variables to persist throughout the entire user
session.
[ Variable types ]
Room Variables support all the "primitive" Actionscript
types: Strings, Numbers, Booleans and null.
The null value is used to delete a variable, so if you want to remove one of
them you should use a code like this:
var varList:Array = []
var roomVar:Object = {name:"test", value:null}
varList.push(roomVar)
smartFox.setRoomVariables(varList)
In this case you will delete the variable called "test".
The variable will not be deleted if it's private and you are not
its owner.
[ Other ways of creating variables ]
Using the setRoomVariables method is not the only way in which
you can create RoomVariables.
There are two other ways to create them:
1) In the config.xml file
2) At the time a new room is created
1) Defining room vars in the config.xml file
is useful when you need to create persistent variables at server
start.Here's a code example you could use in the config.xml file:
<Room name="Disco Fever" maxUsers="12" isPrivate="false" isTemp="false">
<Vars>
<Var name="bg" type="n" private="true">5</Var>
</Vars>
</Room>
This example is taken from our "SmartChat" application.
In our chat every room loads a different background image so we
decided to define
each background as a RoomVariable. By defining it in the config.xml file the
variable is created as soon as the server starts so we don't have to worry
about creating them later. Also we wanted to avoid these values to be changed
so we set the private flag.
NOTE: all variables created in the config.xml
file will be always persistent, since the owner of those variable
is the server itself.
You should have also noticed the type="n" attribute.
What is it about? Each Room Variable preserves its type to avoid
mismatches, so if you send a String you will always get back a
String and so on: this is done transparently by the SmartFox
Client API and you don't have to take care of it.
In this particular case you will have to tell the server what
type are the variables you are setting, by using this convention:
n = Number
s = String
b = Boolean
2) An alternative to the previous method is to
declare the room variables when creating a new room
The createRoom method of the SmartFoxClient object accept a rooObj
argument where you can define all properties of the room you want
to create, variables included.
Here's a code example:
room:Object = new Object()
room.name = "The Cave"
room.isGame = true
room.maxUsers = 15
vars:Array = new Array()
vars.push( {name:"ogres", val:5, private:true} )
vars.push( {name:"skeletons", val:4} )
room.variables = vars
smartFox.createRoom(room)
First an empty object is created, then we add the various room
properties and then we define a new Array with a list of Room Variables.
[ Other ways of creating variables ]
By moving the playhead in the main timeline to the "app" label
you can inspect the stage. In the "variable list" panel
we have a datagrid that
will show names and values of each variable defined in the current room.
The "create variable" area allows you to create a new
room variable by assigning name, value, type and the two boolean
flags we've talked about earlier. On the right side of the application
you'll find the usual room list and user list components.
You will notice that most of the code in the example is similar
to the the other applications, so we'll analyze the most important
section.
room:Object = new Object()
room.name = "The Cave"
room.isGame = true
room.maxUsers = 15
vars:Array = new Array()
vars.push( {name:"ogres", val:5, private:true} )
vars.push( {name:"skeletons", val:4} )
room.variables = vars
smartFox.createRoom(room)
This method is called each time you press the "create" button.
We've used a little "trick" to cast the values taken
from the textfield to the appropriate Actionscript type: we created
a variable called "fn" of type Function which will dynamically
point to one of the built-in AS functions String, Number, Boolean
depending on the datatype.
[ Optimizations Tips ]
When you send and receive variables from the server their names
and values should always be kept as short as possible to save precious
bandwidth.
Try keeping the variables names as short as possible, one or two
characters would be the best choice, for example if you have in
your SWF a variable called "enemy_posX" and you need
to save it as a Room Variable try to shorten its name to "ex" or
similar.
Example:
var roomVar:Array = []
roomVar.push( {name:"ex", val:enemy_posX} )
....
Another important aspect is floating point numbers as they can
get pretty big while you may not necessarily need many decimal
places. For example (100 / 3) gives 33.3333333333333 which is 17
characters long: in this case you may try to round them to the
2nd or 3rd decimal place to shorten the amount of data you're sending.
One trick that can help save quite a lot of space is using strings
to compress more data into one single variable. Imagine you have
to send four numbers to the server which in turn will update the
other clients.
You could use the traditional approach :
var roomVar:Array = []
roomVar.push( {name:"x", val:100} )
roomVar.push( {name:"y", val:200} )
roomVar.push( {name:"w", val:50} )
roomVar.push( {name:"h", val:50} )
smartfox.setRoomVariables(roomVar)
... or you could put the four values in one string with a separator
like this:
var roomVar:Array = []
roomVar.push( {name:"s", val:"100,200,50,50"} )
smartfox.setRoomVariables(roomVar)
when you receive them on the client you would use this code:
smartFox.onRoomVariablesUpdate = function(roomObj:Object)
{
var variables:Object = roomObj.getVariables()
var values:Array = variables["s"].split(",")
for (var i:Number = 0; i < value.length; i++)
trace(Number(values[i]))
}
In other words you pack the four values into one single string
choosing the "," (comma) as the delimitator and when
you receive them on the
other clients you use the String split() method to obtain your values back.
[ Conclusions ]
By the end of this article you should be a Server-side variable
master!
Try experimenting some more with this simple application by launching one or
more instances of it at the same time.
|