[SmartFox] Advanced chat (part 2)
[ August 10, 2004 ] by Marco Lapi, a.k.a Lapo
Article 6: learn how to build a more advanced chat application (part 2)

An interesting feature planned for this tutorial is the creation of new rooms.

Before we dive in the code I'd like to talk a little bit more about rooms and how they work in SmartFoxServer.

Basically everything in SmartFox is a Room. Every time you're interacting with other users you're doing this in a room, whether there're 2 users only or 200, whether you're chatting, playing a game or drawing on a whiteboard.

There are essentially two types of Rooms: rooms created by the server (static) and rooms created by the clients (dynamic).

Static rooms

The first type represents the default set of rooms for your application and they will be always present in your zone; they're created
when at server boot and you won't be able to delete or alter them unless you modify the config file and restart the server.

Open the config.xml located in the root of the SmartFoxServer folder and you will find something like this code:

<Zone name="simpleChat">
    <Room name="The Hall" maxUsers="70" isPrivate="false" isTemp="false" isGame="false"
    autoJoin="true" />
    <Room name="The Kitchen" maxUsers="70" isPrivate="false" isTemp="false" isGame="false"/>
    <Room name="The Garden" maxUsers="70" isPrivate="false" isTemp="false" isGame="false" />
    <Room name="The Bathroom" maxUsers="70" isPrivate="false" isTemp="false" isGame="false" />
    <Room name="The Garage" maxUsers="70" isPrivate="false" isTemp="false" isGame="false" />
    <Room name="The Living Room" maxUsers="50" isPrivate="true" isTemp="false" pwd="piddu"
    isGame="false" />

Here's represented a zone named "simplechat" and its set of default rooms that will be created as the server is launched.

Every room tag can have the following attributes:

name = a unique room name (unique in this zone)
maxUsers = max capacity of the room
isPrivate = set to "true" if the room is password protected
isTemp = set to "true" if the room is temporary. All dynamic rooms are set to "true"
isGame = set to "true" if the room holds a game
pwd = the room password

The only one mandatory attribute is the name, all the others can also be skipped. If you don't specify a maxUser value the default of 30 will be used and the boolean parameters will be all set to "false".

The changes made to this config file won't be applied until you restart the server.

Dynamic rooms

The second type of rooms can be dynamically created at runtime by the client using the SmartFoxClient API. These rooms can be destroyed by the server when there're no more users inside, and its creator isn't logged anymore in the zone.
This means that if all users have logged out of the room but its creator is still present in the zone the room will not be removed.

A dynamic room is created using the SmartFoxClient createRoom() method like this:


The roomObj argument is an object with the following properties:

name = a unique room name (unique in this zone)
maxUsers = max capacity of the room
isGame = set to "true" if the room holds a game
password = the room password

The code used in the "Advanced Chat" to create a new room is the following:

function makeNewRoom()
function createRoom(name, pwd, max)
var roomObj = new Object()
roomObj.name = name
roomObj.password = pwd
roomObj.maxUsers = max

First we call the makeNewRoom function to show a dialog box where the user will input the room name, password and maximum capacity of the new room. When the "OK" button in the window is pressed the createRoom() method is called passing the values submitted by the user.

Finally the roomObj is passed to the SmartFoxClient API mehtod, createRoom().

we have here two methods with the same name that may create a little confusion. However is worth noticing that one exist in the main timeline and the other exist only in the SmartFoxClient object called smartfox. This is why there's no problem with using two identical method names.

If the room is created succesfully it will immediately appear in your room list. If something goes wrong (i.e. you've chosen a room name that already exist) a onCreateRoomError will be fired.

Here's how we handled it in the sample application:

smartfox.onCreateRoomError = function(errorMsg)
var win = showWindow("errorWindow")
win.errorMsg.text = errorMsg

The handler shows an error dialog box and dynamically attaches the error message sent by the server in the errorMsg text box.

The last feature we have to talk about is how to send private messages. PMs are very useful in a chat when you want to privately talk for a while with another user. All private messages are exclusively exchanged between two users, so no one else in the room can read them.

In the previous part of the article we said that the PM function was going to be activated when a user clicks on a name in the user list component.

Here's the code from the source FLA:

function userSelected()
uid = userList_lb.getSelectedItem().data
// If it's not me...
if (uid != smartfox.myUserId)
// store the recipient for later use
_global.pmUid = uid
var win = showWindow("pmWindow")
var uList = smartfox.getActiveRoom().getUserList()
var targetUsr = uList[uid]
win.title_txt.text = "Send a private message to " + targetUsr.getName()

You will notice that this function behaves pretty much like the one we used for loggin in another room.
First of all we get the user id from the listbox data property and we check that the id clicked is not our current user id. Then we store this identifier in a _global variable for later use and we show a dialog box where the user can write the message.
If you wish to inspect the window open the library (F11) and check the clip called "pmWindow" in the "_windows" folder.

When the "OK" button is clicked this code is executed:

function sendMessage()
var m = message.text
if (m.length > 0)
_parent.sendPrivateMessage(m, _global.pmUid)
message.text = ""

The sendPrivateMessage() method takes two arguments: the text of the message and the recipient id.

We still have one control in the GUI which we didn't talk about: the "Exit" button. You can press this button at any time to log out of the chat, also we have to handle another less predictable possibility: an unexpected disconnection.

There are many factors that can lead to an abrupt server disconnection like slow network connections, timeouts, server crashes, etc...
Whatever it will happen we have to deal with this problem:

smartfox.onConnectionLost = function()

The onConnectionLost is fired by the client API when the socket connection is closed and the user will be sent back to the login screen. The "EXIT" button is also handled by the above function: when you will click on it a smartfox.disconnect() command will be issued which in turn will close the socket connection. By closing the connection the onConnectionLost handler will be invoked.

Ok, that's almost all about the "Advanced Chat" tutorial. At this point you should be able to start writing your own variations on the "chat" theme as well as add new interesting features to the applications seen so far.

Take your time with the code shown in these pages and try to experiment on your own: it's always one of the best method to learn new things!

In the next chapters we will discuss more advanced topics like "User variables" and we will build a simple Avatar Chat.

Stay tuned.


Name: Marco Lapi, a.k.a Lapo
Location: Fossano, Italy
Age: 34
Flash experience: started out with Flash 4 back in 1999
Job: web designer/developer
Website: http://www.gotoandplay.it/
| Homepage | News | Games | Articles | Multiplayer Central | Reviews | Spotlight | Forums | Info | Links | Contact us | Advertise | Credits |

| www.smartfoxserver.com | www.gotoandplay.biz | www.openspace-engine.com |

gotoAndPlay() v 3.0.0 -- (c)2003-2008 gotoAndPlay() Team -- P.IVA 03121770048