[SmartFox] Simple chat (part 2)
[ August 10, 2004 ] by Marco Lapi, a.k.a Lapo
Article 4: learn how to build a basic chat application (part 2)

In this second chapter of the "Simple Chat" application I'd like to discuss a little more in detail some aspects of the code created so far. The previous article focused its attention on how to quickly build a simple chat application and we intentionally left out some topics that deserve some extra explanation.


As you have noticed we have taken three main actions in the previous code example:

1) Connect:
At first we try to establish a connection to the server using the its ip address and port.
This is just like knocking at someone's door. You don't enter in the house, you just ask if there's anybody at home.
In case you don't get any responses then you won't be able to ask anything else.

2) Login:
If the server responded you can tell who you are and see if the server accepts you.
In our case you will always be accepted unless you use a user name that is already in use.

3) Join:
Once you're "inside" you will be able to choose which room you want to enter.
This is determined by the "zone" in which you asked to log in. You can think of "zones" as if they were different houses, each of them with its different set of rooms. Some can be very small with a few rooms and others can be huge and with many many rooms.

Once these three steps are taken successfully you're enabled to interact with all the other users.

Below follows a table with the typical request-response pattern that you would normally use to do the connect-login-join:

// Most important thing to do: create an instance of the SmartFoxClient class
server = new SmartFoxClient()
Client Request Event fired by Server
server.connect(ip, port, zone) onConnect()
server.login(name, password) onLogin()
server.joinRoom(roomId) or server.autoJoin() onJoinRoom() or onJoinRoomError()

Two of the most important SmartFoxServer events are called onRoomListUpdate() and onJoinRoom().
What makes them special is the fact the they populate some data structures in the SmartFoxClient object and I'd like to take a deeper look at it.

The following picture represents the SmartFoxServer internal data structure and you have already seen it in the first part of this tutorial:

The server (at the root of the diagram) holds a list of zones, each running a different application.
Each zone contains a list of rooms which in turn contain users.

While the server always sees all this big structure, the client has a smaller perspective as every user is always connected in just one zone at a time. So the SmartFoxClient object is populated with a list of Rooms (those owned by the zone in which we are connected) and every Room will have its own list of users.

The picture below shows this in detail:

The roomList is an array and it is populated with Room objects when the onRoomListUpdate event is fired: each Room object can be accessed using the methods shown under the Room Object.

The userList is an array and it is populated with User objects when the onJoinRoom event is fired: each User object can be accessed using the methods shown under the User Object.

If you go back to the previous article and source code, you will notice that we already used these objects and methods but now you should have a better understanding of what's going on "behind the scenes" and be able to experiment on your own.


One important thing to consider in every project is how to manage unexpected conditions and errors.
Also sometimes it is necessary to stop the normal flow of the application, for example to get some input from the user and we would also like our UI to behave in a different way (i.e. disable certain part of it until the user submits data).

In our "Simple Chat" demo we can get two types of errors:

- a login error, if you try to enter with an already existing user name
- a join error, if you try to join a room that's already full

To test these conditions, try launching two instances of the "Simple Chat" sample and log in with the same name: the second time a dialog window will popup in the middle of the screen and the rest of the application will be grayed out.
The application will restore its state when you will press the "OK" button.

We'll use this simple system quite a lot in all the next tutorials every time we will need a dialog box:

- sending a private message
- entering a password protected room
- creating a new room
- creating a new game room
- showing system and error messages

You can find the code that handles the dialog boxes under the "connect" label in the source fla of the "SimpleChat"
Mainly we use two functions: showWindow(), hideWindow()

function showWindow(linkageName)
_global.isBusy = true
disabler._visible = true
var win = _root.attachMovie(linkageName, linkageName, 9999)
win._x = (stageW / 2) - (win._width / 2)
win._y = (stageH / 2) - (win._height / 2)
return win

The "linkageName" argument is the linkage identifier of the symbol in the library, so if you plan to add you own custom windows always remember to export them for "Actionscript". If you inspect the library in the .FLA you will find a "_windows" folder with all the dialog boxes needed by the application and if you right-click (win) or ctrl-click(mac) on each of them you will notice that they all have a linkage id.

The _global.isBusy boolean is tested everytime a button in the interface is pressed. This way we can disable all buttons in the GUI just by setting this global variable to "true".

The variable called "disabler" refers to a movieclip (check the layer called "disabler") that will cover the entire stage with a semi-transparent black square (this enforces the idea that the main interface has been temporarily "freezed").

The code continues by attaching the dialog box movieclip on stage, then the clip is centered in the screen and a reference to it is returned by the function so you can furtherly manipulate it.

Now double click on the "errorWindow" movieclip in the library and select the "OK" button then open the Actionscript panel (F9).
You will notice that we have just one command, closeMe(), and you will find it's code in the main timeline of the "errorWindow" mc.


This command invokes the hideWindow() function in the parent timeline passing the movieclip instance name as an argument. This way the hideWindow() method can destroy the window and re-enable the GUI controls.

In the next tutorials we will use also input dialog boxes and we will use almost the same approach. The only thing we'll change is that the button will not directly call the closeMe() function, instead it will call a function in the main timeline that will read the input
data and then invoke the hideWindow() method.

See you in the next article.


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/

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