ElectroServer OverviewDeveloper's BlogElectroServer DownloadsShowcasing ElectroServer contentElectroServer DocumentionElectroServer Support
500 users license
$700
ES3 Basic Chat Tutorial
Author: Jobe Makar & Dimitrios Bendilas

In this tutorial we are going to demonstrate how to build a fully functional Chat from scratch, using ElectroServer. The Chat will feature public and private messaging, a user list, a room list and the ability to create new rooms or join existing ones.

For this tutorial we are going to use AS 2.0.

This tutorial is divided into 4 parts:
Part 1 - Getting started
Part 2 - Creating the basic interface
Part 3 - Connecting to ElectroServer and Logging in
Part 4 - Building the Chat


Part 1 - Getting started

Before we start anything, create a new folder for our project and name it BasicChat. Download this zip file. Unzip the downloaded file into the BasicChat directory.These are class files and are essential for a chat or game to work with ElectroServer. Now, while in the same directory create a new.fla file and name it Chat.fla. The final .swf file produced will be in this directory.

You'll notice a file called ElectroServer.as. This file contains a class called ElectroServer. It is used to allow a Flash client (like a chat or game) talk to ElectroServer easily. It handles creating and parsing XML messages internally so that you don't have to. You'll see how useful it can be later in this tutorial.

Part 2 - Creating the basic interface

Go to flash and create two new keyframes in the main timeline, labeled Loader and ServerSettings. Loader will hold a preloader for our application and ServerSettings will have the code that will get us started with connecting to ElectroServer. When this application is finished, your main timeline look like this:



You may build the whole structure now, or wait and build it gradually as we go along this tutorial. I strongly suggest you create separate layers for different items of your app. Keep the Labels separate from the code(Actions) and the Assets.

NOTE:
Throughout this tutorial, I won't refer to the creation of graphical elements at all. Panels, backgrounds, buttons and every other visual element are up to you to build, according to the needs of the application, of course.


PRELOADER
We are going to create a very simple preloader. It will just show us a "Loading. Please wait" message, until the whole movie is loaded and then it will proceed to the next step in our application, the ServerSettings keyframe.

Type the following code in the first frame, which is labeled Loader:

this.onEnterFrame = function()
if (this.getBytesLoaded()/this.getBytesTotal() >=1) {
delete this.onEnterFrame;
gotoAndStop("ServerSettings");
}
}
stop();


This very simple preloader will take us to the keyframe labeled ServerSettings as soon as the movie is fully loaded. So now we can really start building our application.

SETTING IP AND PORT
When ElectroServer is running it listens for connections on a specific IP and Port. In order to connect to ElectroServer our chat needs to use the same IP and Port. The smart thing is to have these stored somewhere outside the .fla file so that you don't need to recompile it in case you want to connect to a different IP or Port. So, we're going to have these in an XML file, which looks as simple as this:

<ServerSettings>
<IP>192.168.1.20</IP>
<Port>9875</Port>
</ServerSettings>


Just open your favorite editor (Notepad or WordPad will do) and type the above. Note that the values for the IP and the Port have to be the same as those stated in configuration.xml in your ElectroServer installation folder, because this is the IP and Port your server is listening to. Save that file as ServerSettings.xml in the same folder as before.

The first thing now is to parse this XML inside our movie and get the values for IP and Port.

So, go to frame ServerSettings and type the following:

var error:String;

var ip:String; var port:Number;

var serverSettings:XML = new XML();
serverSettings.ignoreWhite = true;
serverSettings.onLoad = settingsLoaded;
serverSettings.load("ServerSettings.xml");


These lines of code will load ServerSettings.xml and run a function called settingsLoaded() as soon as the file is loaded. Also, in these lines we make sure we declare the some useful variables (error, ip and port) that we are going to use in just a moment.

Let's take a look at settingsLoaded():

function settingsLoaded(success:Boolean):Void {
if (success) {
var children:Array = this.firstChild.childNodes;
for (var i:Number=0; i


This function simply parses the loaded XML file and sets the values of ip and port variables, if the file was loaded successfully.

ERROR HANDLING SCHEME
If there is a problem with the XML file, we need to notify the user, so we are going to build a very basic error handling scheme, which will be used throughout this application. As you can see above, if an error occurs, errorFound() will be fired, having an explanatory string passed as a parameter.

Let's see the body of the errorFound() function (this resides in ServerSettings frame):

function errorFound(str:String):Void {
error = str;
gotoAndStop("Error");
}


So, this function sets the previously declared error variable to the value of the passed parameter and moves the clip to another frame labeled Error.

You now have to create a new keyframe called Error. Make sure you have a TextField named error_txt on the stage at frame Error. Add this line of ActionScript to the frame. It handles taking the error message and displaying it in a text field.

error_txt.text = error;



Ok, now we are done forever with the error handling functions, so now we are ready to start the server fun!

Part 3 - Connecting to ElectroServer and Logging in

In this part things start getting more interesting. We are going to see how we connect and login to ElectroServer. Let's expand our main structure a bit, by creating 3 more keyframes, labeled Connect, Login and LoggingIn.

CONNECTING TO ELECTROSERVER
Having the ip and port set from before, we are now going to connect to ElectroServer. This is very easily achieved with only the few following lines. Just type them in the frame labeled Connect:

System.security["loadPolicyFile"]("xmlsocket://"+ip+":"+port);

var es:ElectroServer = ElectroServer.getInstance();

es.setIP(ip);
es.setPort(port);
es.onConnection = onConnection;
es.connect();


The first line of ActionScript may look strange. It is used to make sure that your chat file will have permission to connect to ElectroServer. The Flash player is very strict about letting a SWF file connect to a domain that the SWF is not loaded from. Without this first line of ActionScript you'd have to be extremely careful about where you put the chat file to make sure that it would connect successfully. For now, just trust that it will work.

Next we declare a variable called es, which holds the instance of the ElectroServer class, which is the only class we need to communicate with ElectroServer.

Then, we set the IP and Port in the ElectroServer instance, using those two variables from before (ip and port). Also, we set a callback function called onConnection, to run as soon as we are connected to the server. So, when a connection is established (or rejected) the function called onConnection is executed.

Last, we simply run the es.connect() method. This method attempts to establish a socket connection between our chat application and ElectroServer. Once this connection is established, the chat and ElectroServer will be able to exchanged information quickly.

This is what happens when onConnection is called:

function onConnection(success:Boolean, error:String) {
if (success) {
gotoAndStop("Login");
} else {
foundError(error);
}
}




If the connection is successful the movie will go to frame Login. If not, it will display an error. The error that occurred while a connection to ElectroServer was attempted, comes as a String parameter in the onConnection callback function, so we are able to display a descriptive error message.

LOGIN TO ELECTROSERVER
If everything is ok with the connection, we are taken to frame Login. As you can see this frame contains a very simple form, where the user is prompted to enter a login name and click the login button in order to login.



First, we set the focus on the input textfield (username_txt), so that the user doesn't have to click with the mouse to start typing in the textfield.

Selection.setFocus(username_txt);

In addition to the login button, we are going to create a keyListener, so that the user can press ENTER as an alternative to clicking the login button. Both the ENTER key and the mouse click will trigger the same function, loginClicked().

login_btn.onRelease = loginClicked;
var keyListener:Object = new Object();
keyListener.onKeyDown = function() {
if (Key.isDown(Key.ENTER)) {
loginClicked();
}
}
Key.addListener(keyListener);

function loginClicked() {
var username:String = username_txt.text;
if (username.length > 2 && username.length < 15) {
Key.removeListener(keyListener);

es.loggedIn = loggedIn;
es.login(username);
gotoAndStop("LoggingIn");
}
}


What the loginClicked() function does is take the username typed in the input textfield, perform a basic validation check and if it is valid, login to ElectroServer, using that username. Note that we remove the key listener, now that we don't need it, since we don't want the loginClicked function to fire whenever the user presses ENTER in the rest of the program.
Let's take a look at the last 3 lines of code:
We set a callback function, loggedIn, that will fire as soon as the login process is completed:

es.loggedIn = loggedIn;

We login using the username typed in the input textfield:

es.login(username);

And we tell the movie to go to the LoggingIn frame.

gotoAndStop("LoggingIn");

There, we simply display a "Logging in. Please wait" message, until further notice.



The login method takes the username from the text field and sends it to ElectroServer. ElectroServer makes sure that this name is not already in use by someone else, and makes sure that it does not contain vulgarity, and returns a response. When the response is received by the chat client, the loggedIn callback is fired.
This is the loggedIn function that fires when the login is completed:

function loggedIn(success:Boolean, error:String) {
if (success) {
es.roomJoined = roomJoined;
joinRoom();
} else {
errorFound(error);
}
}


loggedIn() also comes with two parameters, success and error. The former simply shows if the login was successful and if not (true or false), the later explains why. Again, if an error is found, the usual error handling process is followed. Reasons for an unsuccessful login might be an attempt to use a username that already exists in the server (there cannot be two different users logged in with the same username), or a username that contains vulgarity.

JOIN A ROOM
If the login is successful then these two lines are executed, as we saw above:

es.roomJoined = roomJoined;
joinRoom();


We run a function called joinRoom(), after we have set a callback function, roomJoined, that will fire as soon as the user joins a room (or fails joining a room because an error has occurred). A user has to be inside a room before starting having a functional presence in the server (send and receive messages, events etc).
This is the code inside the joinRoom() function:

function joinRoom() {
var roomObj:Object = new Object();
roomObj.roomName = "Lobby";
roomObj.zone = "Chat Area";
es.createRoom(roomObj);
}


As you can see, we are calling an ElectroServer method called createRoom(). This method is slightly more complex than the other ElectroServer methods we've seen so far. It takes only one parameter, an Object here called roomObj, that has multiple properties. In this example we only need two, but there are up to 12 different properties available, which can greatly affect the behavior of the created room. The properties we use here are roomObj.roomName and roomObj.zone. So, we are telling the server we want to create a room called "Lobby", in a zone called "Chat Area". For more information about the structure of the zones and rooms in the server see the documentation. As you know, users connect to the server. A group of users is called a room. A group of rooms is called a zone. Most of the time you will only need one zone.

NOTE:
Now, you may wonder why we actually create a room, when we just said we are going to join a room. Well, in order to join a room it has to exist. But the first time our application is run, there is no room called "Lobby" in a zone called "Chat Area". So someone has to create it. The createRoom function joins the room, after first creating it if it doesn't already exist. ElectroServer also supports the creation of Persistent Rooms, that are created as server starts, even without any user being inside them. The creation of such a room will be covered in another tutorial.


When the joining process is completed, the callback function roomJoined will fire. Let's see what's inside that function:

function roomJoined(result:Object, roomObj:Object) {
if (result.success) {
gotoAndStop("Chat");
} else {
errorFound(results.error);
}
};


The function checks if the room was successfully joined. If not, an error is displayed. The success or failure and the error if one exists, are held in the results parameter. A second parameter, roomObj is an Object containing many information about the room the user just joined. We don't need this for anything here, so we just tell the movie to proceed to frame Chat, if the room was successfully joined.

Part 4 - Building the Chat


Ok, things are going to get pretty wild now! We are about to create a fully functional chat. It may sound a bit intimidating, but it's really pretty easy. Let's start with the simple stuff. Create a new frame called Chat. The rest of the code from now on will go there.
We'll take a look at our interface, which will provide an easy way for the user to interact and will help us display everything related to our chat.
The stage in the Chat frame needs to contain the following assets:

- A big TextArea component, where all public messages will be displayed
- An input text field where the user can type a message to send
- A "send" button
- A user list (List Component)
- A room list (List Component)
- A "new room" button
Something like this:



USER LIST
We have a user list on the stage. We are going to make it functional.

es.userListUpdated = showUsers;

This simple line sets a callback function to fire every time a user enters or leaves the room they are currently in. So, whenever the userListUpdated event is fired, a function we're about to build just now, showUsers(), will be executed.

function showUsers():Void {
var userlist:Array = es.getUserList();
userListBox.dataProvider = userlist;
}


Here we call an ElectroServer method, es.getUserList() which returns an array with all the users in that room. Then, we simply assign that as the dataProvider of our user list component (instance name: userListBox). Simple as that!

To make sure we get the user list when we first join the room, we iclude a direct call to the function, at the top of our code:

showUsers();

If you run the application now and login, you'll see your username in the user list. If you run it twice and login with two different usernames, you'll see both of them appearing in the list and so on.
The user list is ready. How about making the room list as well?

ROOM LIST
It's done using the same concept. First we set a callback function:

es.roomListUpdated = showRooms;

and then we create the callback. Our function is showRooms():

function showRooms():Void {
var roomlist:Array = es.getRoomList();
roomListBox.dataProvider = roomlist;
}


Again, we invoke a method on our ElectroServer instance, es.getRoomList().
This returns an array with all rooms, we set that as the dataProvider of the roomListBox List Component and the room list works like a charm!
To make sure we get the room list when we first join the room, we include a direct call to the function, at the top of our code:

showRooms();

PUBLIC MESSAGING
We are now ready to build the messaging system. The main method we are going to use in order to send a message is es.sendMessage().This is for both public and private messages.
To receive a sent message, we will be using es.messageReceived.
First let's set up the controls we are going to use to type and send a message. As we have already seen, the user will type their message in a text input (msgBox_inp). It's a good thing that we set the focus on that input:

Selection.setFocus(msgBox_inp);

As we did at the Login form, we are going to provide 2 ways of sending the message, a mouse click on the send button and an ENTER key press:

send_btn.onRelease = sendClicked;

var keyListener:Object = new Object();
keyListener.onKeyDown = function() {
if (Key.isDown(Key.ENTER)) {
sendClicked();
}
}
Key.addListener(keyListener);


This is pretty straightforward. As soon as the send button or ENTER key is pressed, a function called sendClicked() will be fired:

function sendClicked():Void {
var msg:String = msgBox_inp.text;
if (msg.length > 0) {
es.sendMessage("public", msg);
msgBox_inp.text = "";
}
}


After we perform a very basic validation (the message cannot be empty), we send a public message, usinges.sendMessage("public", msg). Just stating the type of the message (public) and the message itself. Then we clear the textbox so that we can type a new message. This method takes the text that you typed into the message field, and sends it to ElectroServer as a public message. ElectroServer will then take that message and broadcast it to everyone else in the same room, including you! When that message is received, the messageReceived callback is fired.
A public message is sent to every single user in the same room as you. So everyone, including you, can receive that message and display it on the screen. That's what we are going to do now.
Here is the callback function we have to set in order to receive messages from the server:

function messageReceived(type:String, message:String, from:String):Void {v var msg:String;
switch (type) {

case "public":
msg = "[" + from + "] " + message + newline;
break;

case "private":
msg = "** [" + from + "] ** " + message + newline;
}
chatBox.text += msg;
chatBox.vPosition = chatBox.maxVPosition;
Selection.setFocus(msgBox);
}


Let's go through the parameters of the function first.

- type is a string indicating if this is either a public or a private message
- message is the actual message string
- from is the username of the person that sent the message

NOTE
There is actually a fourth parameter, variables, which is an object the user can send along with the simple message. We are not going to need this for this tutorial, but have in mind that this can help you send some pretty complex messages and gain a lot in functionality. For instance, you could send an object describing the desired format of the message, like font, color and style so that the received message is displayed that way on the receiving user's screen.


As you are able to see on the messageReceived function above, we are performing a check to see if the received message is of public or private type. Then we display the message on the chatBox TextArea, with private messages being displayed slightly different than the public ones. We haven't built the functionality for sending a private message yet, but we are going to do that really soon. The code for receiving and handling a private message is ready though.



If you run your application now you'll see that you can type and send a message and this will be received and displayed in the TextArea.

ADDING FUNCTIONALITY - POP-UP WINDOW
We have plenty of things yet to implement. In order to provide a usable interface, we are going to create a new pop-up movieclip that will be shown and hidden whenever needed. This is what the movieclip's timeline will look like in the end:



For now, create a new movieclip, place it on the stage at the upper left corner, name the instance "popup" and create the structure that you see in the image above.
Go to the first frame of the popup movieclip and type the following code:

stop();

function close() {
delete infoObj;
gotoAndStop(1);
}


Function close() will be used later on throughout the popup movieclip to make the clip invisible.

We now need a function that takes the popup to the desired state. Here it is (this code is placed on the main timeline, frame Chat):

function showPopUp(action:String, obj:Object) {v if (action == "JoinRoom" && obj.attributes.IsPasswordProtected) {
action = "JoinProtectedRoom";
}
popup.infoObj = obj;
popup.gotoAndStop(action);
}


showPopUp() takes two parameters, an action string and an obj object. action is used in a pop.gotoAndStop(action) method, which is going to take the popup movieclip at a frame labeled as the value of action. Obj is assigned to a custom property of popup, popup.infoObj. So, when calling the showPopUp() method, you are telling the popup movie to go to a specific frame, having along infoObj, which contains useful data. This is the same infoObj we saw in delete infoObj;, inside the close() function in the popup movieclip; we just make sure we delete the object after we have used it, so that there are is no unwanted data hanging around.

PRIVATE MESSAGING
We are now ready to implement the private messaging. First we need a control that the user should use in order to send a private message to a specific user. A single click on a username on the user list is the simplest and effective way. Let's set that up (code placed on the main timeline):

var userClickListenerObject:Object = new Object();
userClickListenerObject.change = function(eventObj:Object) {
var user:Object = eventObj.target.value;
showPopUp("PrivateMessage", user);
}
userListBox.addEventListener("change", userClickListenerObject);


userListBox.addEventListener("change", userClickListenerObject);
We create an event listener for the userListBox List Component and make sure the showPopUp() function is fired every time the user clicks on a specific username on that list. We pass along two parameters, a "PrivateMessage" string and a user object.
Let's go now to the popup clip and the PrivateMessage frame in particular. This is what we need on the stage:



A panel with an input text (message_inp) where the user can type their message, an OK and a CANCEL button. We also display the username of the person the message will go.
Let's write some code to make it work:

Selection.setFocus(message_inp);

username_txt.text = infoObj.Name.value;

ok_btn.onRelease = ok;
cancel_btn.onRelease = close;

function ok() {
var msg:String = message_inp.text;
if (msg.length > 0) {
_parent.es.sendMessage("private", msg, [username_txt.text]);
close();
}
}


We first set the focus on the input text and display the target username. Then we initiate our controls. The CANCEL button calls close(), which as you remember resides in the first frame of the popup movieclip, while the OK button calls a function named ok().
The ok() function validates the typed string and uses the ElectroServer sendMessage() method to send a private message. You'll notice that the 3rd parameter passed in sendMessage() is an array with one element:

[username_txt.text]

The reason the username is passed as an array is because sendMessage() can send a private message to many users at once. So you could actually have an array with more than one username and send a private message to all of them, with one sendMessage() call.
Note that we call the sendMessage() method on _parent.es, since the above code is in the popup movieclip. As soon as the method is called, the popup window hides again, by invoking the close() method.vThat's all you need for private messaging. We already have set up the messageReceived() function to handle private messages, so now your private messaging system should be working.



CREATE A ROOM
We are now moving to room-related features. We'll see how you can create a new room. First go to the main timeline and make sure the NEW ROOM button instance name is newRoom_btn. Then go to the Chat frame and type the following lines, so that we can make something happen when the button is clicked:

newRoom_btn.onRelease = function() {
showPopUp("NewRoom");
}


In the popup movieclip now, this is what the NewRoom frame should look like:



The user has to enter a name for the room to be created. Password and description are optional. As soon as OK is pressed, a new room will be created. Here's the code for the NewRoom frame:

Selection.setFocus(roomName_inp);

ok_btn.onRelease = ok;
cancel_btn.onRelease = close;

function ok() {
if (roomName_inp.text.length == 0) return;
makeRoom();
close();
}

function makeRoom() {
var roomObj:Object = new Object();
roomObj.roomName = roomName_inp.text;
roomObj.Description = description_inp.text;
roomObj.password = password_inp.text;
_parent.es.createRoom(roomObj);
}


As always, we set focus on the first input text and initialize the two buttons, OK and CANCEL. The later hides the popup as usual. The ok() function, fires when the OK button is fired and calls the makeRoom() function, if the room name is not an empty string.

The createRoom() method is used to create the new room, just like before when we first created the Lobby. Now we are creating two extra properties, Description and password, on the roomObj object. There is no need to define a zone property. If you don't specify a zone in the room object, the room will be created in the current zone. If you want to, you could have an extra input text, where the user would enter the name of the zone to be created.

As soon as you press the OK button, the room is created and you automatically join it. If you have set a password, then only users that know this password can join the room.
One last thing. As soon as the room is created, the ElectroServer event roomJoined will be fired. We already have set up a callback function called roomJoined at the step of Login, but that was for the first room we ever joined, the Lobby. So, we want to make sure we set a brand new roomJoined function to take over after we have joined the Lobby and we are trying to join other rooms.
The function is again very simple. Just checking if the room was successfully joined. If not, an error is displayed, else it does absolutely nothing. This is added to the ActionScript on the Chat frame on the main timeline:

function roomJoined(result:Object) {
if (result.success) {
//successfully joined room
} else {
showPopUp("Error", result.error);
}
}


We are almost done here! We learned how to create a new room. Let's see now how to join an existing room - a much simpler task.

JOIN AN EXISTING ROOM
Like we did with the private messages and the user list, it's very convenient to perform the action of joining a room, when we actually click on the room name on the room list. We are going to use a similar event handler for the roomListBox List Component (code goes on the main timeline):

var roomClickListenerObject:Object = new Object();
roomClickListenerObject.change = function(eventObj:Object) {
var room:Object = eventObj.target.value;
showPopUp("JoinRoom", room);
}


Notice the room:Object variable we pass to showPopUp(). We'll see that again in a moment.
Let's take a look again at the showPopUp() function (resides on Chat frame, main timeline):

function showPopUp(action:String, obj:Object) {

function showPopUp(action:String, obj:Object) {
if (action == "JoinRoom" && obj.attributes.IsPasswordProtected) {
action = "JoinProtectedRoom";
}
popup.infoObj = obj;
popup.gotoAndStop(action);
}


The room variable passed in the function is the parameter called obj inside the function. If you notice the first two lines of code, you'll see that we are checking weather the room we are about to join is protected by a password or not. So, if the room isn't password protected the popup will go to frame JoinRoom, else it will go to JoinProtectedRoom.

This is what those two frames should look like:



Their only difference is the password input text (password_inp) in JoinProtectedRoom.
As you may expect, the code for both of them is almost identical. Let's take a look on frame JoinRoom first:

var roomName:String = infoObj.Name.value;
roomName_txt.text = roomName;

ok_btn.onRelease = ok;
cancel_btn.onRelease = close;

function ok() {
_parent.es.joinRoom(roomName);
close();
}


We get the name of the room we want to join from the infoObj that was passed on the popup movieclip with the showPopUp() function. We set the OK and CANCEL buttons and create an ok() function to fire when OK is pressed.

ok() calls es.joinRoom(), passing roomName as the only parameter. This will tell ElectroServer to join a room named after the value of roomName, which is in the same zone as the room you are currently in, since no zone is specified. If you wanted to join a room in a different zone you should have used:

_parent.es.joinRoom(roomName, "" , zoneName);

where the second parameter "" is the password. Since we are talking about a not-protected room, we leave the password blank.
As for the password protected rooms, this is the slightly altered code:

Selection.setFocus(password_inp);

var roomName:String = infoObj.Name.value;
roomName_txt.text = roomName;

ok_btn.onRelease = ok;
cancel_btn.onRelease = close;

function ok() {
_parent.es.joinRoom(roomName, password_inp.text);
close();
}


As you see, it's exactly the same as above, but now we are passing a second parameter into es.joinRoom(), the value of the password input text. If the password we provide is incorrect, we won't be able to join the room and an error message will appear.