ElectroServer Flex simple chat

I’ve just converted the code from the Simple Chat Tutorial on the ElectroServer wiki into Flex and I thought it may be useful to someone.

Here’s what it looks like, and it’s connecting to an ES4 install with only 20 connections so forgive me if you can’t connect :

Here’s the source:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" applicationComplete="init()" width="450" height="365">
 
<mx:Script>
	<![CDATA[
		import mx.utils.URLUtil;
		import com.electrotank.electroserver4.message.event.PublicMessageEvent;
		import com.electrotank.electroserver4.message.request.PublicMessageRequest;
		import com.electrotank.electroserver4.user.User;
		import com.electrotank.electroserver4.message.request.LoginRequest;
		import com.electrotank.electroserver4.room.Room;
		import com.electrotank.electroserver4.message.event.JoinRoomEvent;
		import com.electrotank.electroserver4.message.event.UserListUpdateEvent;
		import com.electrotank.electroserver4.message.request.CreateRoomRequest;
		import com.electrotank.electroserver4.message.response.LoginResponse;
		import com.electrotank.electroserver4.message.event.ConnectionEvent;
		import com.electrotank.electroserver4.message.MessageType;
		import com.electrotank.electroserver4.ElectroServer;
		import mx.rpc.events.FaultEvent;
		import mx.rpc.events.ResultEvent;
		import mx.controls.Alert;
 
		private var es : ElectroServer; 
		private var serverInfo : Object; 
		private var myRoom : Room; 
		[Bindable]
		private var users : Array; 
 
		public function init():void
		{
			// There MUST be a better way of getting the app's path than this! suggestions welcome. 
 
			var pathelements: Array = Application.application.url.split("/"); 
			pathelements[pathelements.length-1] = settings.url; 
			settings.url = pathelements.join("/"); 
 
			settings.send(); 
			users = []; 
		}
		public function sendMessage() : void
		{
 
			var msg:String = msg_text.text;
	  		if (msg != "") {
	  			msg_text.text = ""; 
				msg_text.setFocus(); 
 
	  			//create the request
	  			var pmr:PublicMessageRequest =new PublicMessageRequest();
	  			pmr.setRoomId(myRoom.getRoomId());
	  			pmr.setZoneId(myRoom.getZone().getZoneId());
	  			pmr.setMessage(msg);
 
	  			//send it
	  			es.send(pmr);
	  		}
 
 
 
		}
 
		public function onPublicMessageEvent(e:PublicMessageEvent):void 
	  	{
	  		var from:String = e.getUserName();
	  		var msg:String = e.getMessage();
 
	  		output(from+": "+msg);
 
	  	}		
 
		public function xmlLoaded(e : ResultEvent) : void
		{
 
			es = new ElectroServer(); 
			serverInfo = []; 
			for each (var lis:XML in e.result.Listener) {
				var protocol:String = lis.@protocol;
				var ip:String = lis.@ip;
				var port:Number = Number(lis.@port);
				serverInfo[protocol] = new Object();
				serverInfo[protocol].ip = ip;
				serverInfo[protocol].port = port;
			}
 
			es.addEventListener(MessageType.ConnectionEvent, "onConnectionEvent", this);
			es.addEventListener(MessageType.LoginResponse, "onLoginResponse", this);
			es.addEventListener(MessageType.JoinRoomEvent, "onJoinRoomEvent", this);
			es.addEventListener(MessageType.PublicMessageEvent, "onPublicMessageEvent", this);
			es.addEventListener(MessageType.UserListUpdateEvent, "onUserListUpdateEvent", this);
 
			//Create the connection
			output("Attempting connection with this ip/port combo: "+serverInfo.text.ip+":"+serverInfo.text.port);
			es.createConnection(serverInfo.text.ip, serverInfo.text.port);
 
		}
 
 
		public function onConnectionEvent(e:ConnectionEvent):void 
		{
			if (e.getAccepted()) {
				output("Connection accepted");
				var name:String = "user"+Math.round(10000*Math.random());
				output("Attempting to login as: "+name);
				//Build the LoginRequest and populate it
				var lr:LoginRequest = new LoginRequest();
				lr.setUserName(name);
				//send it
				es.send(lr);
			} else {
				output("Connection failed: "+e.getEsError().getDescription());
			}
		}
	 	public function onLoginResponse(e:LoginResponse):void 
	  	{
	  		if (e.getAccepted()) {
	  			output("Login accepted.");
	  			output("You are logged in as: "+e.getUserName());
	  			joinRoom();
	  		} else {
	  			output("Login failed: "+e.getEsError().getDescription());
	  		}
		}			
 
		private function joinRoom():void 
		{
		  	//tries to create a room. if it already exists, then you join that room
		  	//create the request
			var crr:CreateRoomRequest = new CreateRoomRequest();
			crr.setRoomName("MyRoom");
			crr.setZoneName("ZoneName");
			//send it
			es.send(crr);
		}	
 
		public function onJoinRoomEvent(e:JoinRoomEvent):void 
		{
			myRoom = e.room;
			showUserList();
		}
		public function onUserListUpdateEvent(e:UserListUpdateEvent) : void
  		{
  			showUserList();
  		}
 
		public function showUserList() : void
		{
			var userobjs : Array = myRoom.getUsers(); 
			users = [];
 
			for each(var user : User in userobjs)
			{
				users.push(user.getUserName()); 
			}
 
		}
 
		public function xmlLoadFailed(e : FaultEvent) : void
		{
			trace("failed"); 
		}
 
		public function output(msg : String) : void
		{
			chat_text.text += msg+"\n"; 
			chat_text.verticalScrollPosition = chat_text.maxVerticalScrollPosition;
		}
	]]>
</mx:Script>
 
	<mx:HTTPService 
	id="settings"
	url="./ServerSettings.xml" 
	resultFormat="e4x"
	result="xmlLoaded(event);"
	fault="xmlLoadFailed(event);"
	/>
 
	<mx:Model id="users_model">
      <users>
 
      </users>
    </mx:Model>
 
	<mx:Button x="386" y="333" label="Send" id="send_button" click="sendMessage()"/>
	<mx:TextInput x="10" y="333" width="368" id="msg_text" enter="sendMessage()"/>
	<mx:TextArea x="10" y="10" width="302" height="316" id="chat_text"/>
	<mx:List x="320" y="8" width="120" id="user_list" dataProvider="{users}" height="318"></mx:List>
 
</mx:Application>

This example also requires a ServerSettings.xml file that contains the server details, which if you’re running ElectroServer locally, should be :

 <Listeners>
       <Listener ip="127.0.0.1" port="9898" protocol="text" />
       <Listener ip="127.0.0.1" port="1935" protocol="rtmp" />
 </Listeners>

Download the MXML source code for the ElectroServer Flex Simple Chat.

I very rarely use Flex so please feel free to comment with improvements!

Particularly with how to load a file with a relative path in an HTTPService. It seems ridiculous that I have to specify a full path name, and the hack I’ve employed to extract the local path from the application URL is equally ridiculous. There must be a simpler method?

Bookmark and Share

Related posts:

  1. Further adventures with ElectroServer
  2. Simple Flash 3D drawing API
  3. Simple real-time easing in Flash & 3D panels
  4. How to set up ASDoc in Flex Builder
  5. Multi-user gaming in Flash – Lunar Lander tests

2 Responses to “ElectroServer Flex simple chat”

  1. Bill Brown says:

    Just want to say that I’m quite enjoying your ElectroServer posts. I tried putting together a multi-user game using Smart Fox Server a couple years ago, but ran into too many frustrating roadblocks to get it deployed over my holiday time. Being a Flash guy, the server-side is out of my comfort zone and I ran into many similar installations issues that you had.
    I appreciate you posting your solutions to all the “gotchas”. You’ve inspired me to get my own project off the back burner.
    Just out of curiosity, would you mind commenting on why you chose ElectroServer over some of the other multi-user offerings?

    • Hi Bill,

      very glad you’re enjoying these, and yes, just like you, I’m finding it challenging but enjoyable being out of my comfort zone :-)

      I have done some work with FMS before and I will also be looking at SmartFox and Red5, but ElectroServer interests me greatly. The best Flash games book I’ve read (and there have been many) is FlashMX Game Design Demysified (years old now) by Jobe Makar. Since I read the book I’ve met Jobe many times and he is now a friend who I respect greatly. It’s his company that makes ElectroServer, so I thought it would be worth checking out. I’m very interested to see how it compares with the other alternatives, so i’ll continue to report my findings.

Leave a Reply

Bad Behavior has blocked 793 access attempts in the last 7 days.