NFC Flash Chat
While I am not a big "chatter," building a chat application was a nice way to play with some of the new Flash 5 features and prototype some new ideas I've had about designing applications with Flash. This framework can be used to build other real-time, multiuser Flash applications. I'm interested to hear what you think of all this and am happy to answer questions. Send email to alon@ajdigital.com.
Overview
This is a Flash chat client for the Java chat server NFC Chat, located at http://nfcchat.sourceforge.net. It is available for you to download, pull apart and use. There are three main pieces to this Flash application:
- the chat engine
The file nfcEngine.fla provides all the functionality needed to send a recieve messages with the chat server using XML socket communication (Flash 5 only). There are no visual elements to this implementation. You can do what you want with this file, but you can use it as is to implement your own chat interface. You should load nfcEngine.swf in to your own Flash movie that provides all your interface elements.
- the interface
The file nfcUI.fla is an implementation of an interface that uses the chat engine. It supports most but not all of the messages that you can send and receive. Feel free to modify and use this file to create your own interface.
- the chat server
The chat server is running NFC Chat (http://nfcchat.sourceforge.net) with some additional code to support sending and receiving XML messages.
Using the ChatEngine
You should load nfcEngine.swf in to your own Flash movie that provides all your interface elements. It does not matter where you load this movie as it will set a variable _root._ChatEngine when it loads that points to itself. The interface should only reference the engine through this variable, as in _root._ChatEngine.sendSignOn(username,password);
Likewise, your interface file should set a variable at the root that points to the location of the Handler clip:
_root._ChatInterface = this;
The chat engine uses this variable to communicate with the interface. nfcUI.fla does this on the first frame of the movie.
Sending messages
When you call a function in the chat engine to send a message, the engine builds the appropriate message format, creates an XML document object and sends it through the socket it has opened with the server. None of these functions have return values. All messages sent back from the server must be received and processed using the available handlers. You just need to call the functions:
- _root._ChatEngine.sendSignon(username, password)
- Connect and login in to the server. Password not required.
- _root._ChatEngine.sendSignoff()
- Log off.
- _root._ChatEngine.sendStats()
- Request server stats
- _root._ChatEngine.sendGetRoomsList()
- Request list of all rooms
- _root._ChatEngine.sendJoinRoom(room)
- Request to join a room
- _root._ChatEngine.sendUserInfo(username)
- Request user stats
- _root._ChatEngine.sendGetUserList()
- Request list of all users
- _root._ChatEngine.sendRoomMessage(room,message)
- Send message to a room
- _root._ChatEngine.sendRequestUsersInRoom(room)
- Request list of users in a room
- _root._ChatEngine.sendPartRoom(room)
- Leave a room
- _root._ChatEngine.sendSayToUserMessage()
- Send a private message to a user
- _root._ChatEngine.sendEmoteToRoomMessage()
- Emote to a room
- _root._ChatEngine.sendEmoteToUserMessage()
- Emote privately to a user
- _root._ChatEngine.sendHelpMessage(command)
- Not very useful - request help info on an NFCChat command
- _root._ChatEngine.sendVersionMessage(version)
- Not very useful but nice to do - tell the server what kind of client you are
- _root._ChatEngine.sendKillMessage(user,message)
- Kill a user - not sure what this actually does
- _root._ChatEngine.sendIgnoreMessage(username)
- Tell server to not send messages from a specifc user to us
- _root._ChatEngine.sendUnIgnoreMessage(username)
- Tell server to start sending messages from a specifc user
Receiving messages
The server sends messages to the chat client, sometimes in response to messages you have sent, and sometimes because of other users' actions (like saying something to a room). When server messages come in, they are received by the chat engine, parsed and processed before the engine calls these functions in the interface. These are the functions you will need to use or tweak to build the interface:
- _root._ChatInterface.Handler.handleConnect()
- Connected successfully to the chat server
- _root._ChatInterface.Handler.handleFailedConnect()
- Failed connecting to the chat server
- _root._ChatInterface.Handler.handleClose()
- Connection to the chat server is shut down
- _root._ChatInterface.Handler.handleSignon()
- Acknowledgement of successful logon
- _root._ChatInterface.Handler.handleError(error)
- Something went wrong
- _root._ChatInterface.Handler.handleUnknown(array)
- We received a message type we did not recognize, input is an array
- _root._ChatInterface.Handler.handleNoAction(message)
- We received a message with no action (server & user stats)
- _root._ChatInterface.Handler.handleRoomJoin(room)
- Acknowledgement of successful room join
- _root._ChatInterface.Handler.handleRoomMsg(sender, room, message)
- Received a message from a sender to a room
- _root._ChatInterface.Handler.handleRoomUserDiff(room, diff, username)
- A user left or joined a room, diff = + or -
- _root._ChatInterface.Handler.handleServerUserList(users)
- Receive a list of all users
- _root._ChatInterface.Handler.handleServerRoomList(rooms)
- Receive a list of all rooms with number of users in each, as in
(room1, 2, room2, 4, room3, 0)
- _root._ChatInterface.Handler.handleRoomUserList(room, users)
- Receive list of users in a room
- _root._ChatInterface.Handler.handlePartRoom(room)
- Acknowledgement of leaving a room
- _root._ChatInterface.Handler.handlePrivateMsg(sender, message)
- Receive private message from a sender
- _root._ChatInterface.Handler.handleRoomEmote(sender, room, message)
- Receive a message emoted to a room
- _root._ChatInterface.Handler.handleUserEmote(sender, msg)
- Receive private message emoted from a sender
- _root._ChatInterface.Handler.handleKill(killer, msg)
- Handle being killed by a user who also sends a message, I haven't seent this happen yet
- _root._ChatInterface.Handler.handleUserDiff(username, diff)
- Handle a user arriving or leaving the chat
- _root._ChatInterface.Handler.handleRoomDiff(room, diff)
- Handle a room being added or removed
- _root._ChatInterface.Handler.handleShutdown()
- Server shut down
Thoughts
What's this about?
I had a couple goals in initiating this project:
- To play with and learn some of the new Flash 5 features
- To prototype ways to build Flash apps so that funcionality is independent of interface
- To build reusable interface components that can be used by a range of applications
I feel somewhat successful with the first two. Your efforts to use this implementation to tweak or create new interfaces will be a good test of number 2. The third has not been a high priority on this project and therefore I haven't done much with it. The lists in the interface I provide are a start with this.
Simplify
While the nfcUI.fla interface is pretty full featured. The chat engine could be used to make a much simpler chat that only takes a login and has just one room. All you need to do is send and recieve the messages you want to use and ignore everything else. If I get a chance, I'd like to put together a sample of this.
Add Chat to All Your Flash
Because the chat engine and interface create their own references by which they communicate, you can create a chat program to load in to your other Flash apps. It would be cool to be playing a Flash game and be able to send messages to all the other players. You can do that with this implementation.
Debugging
To debug while authoring, I use trace a lot. In fact, if you load and use the nfcEngine.swf file while testing your movie, you will see a lot of stuff written to output. I try to use trace messages that look like:
trace(this + ": whatever you want to say");
"this" resolves to the path to the movie clip creating the trace message so that it's easy to see where it's coming from. Messages from the nfcEngine will have a movie clip path dependent on where you load the movie. To hide these messages or reduce the size of the .swf created, select to remove trace actions in your publish settings.
Bugs
As with all works in progress, there are a few bugs. I'm not concerned with interface bugs but more with bugs in the handling of communication with the chat server. I'll list known problems here and fix them when I can.
The Chat Server
I have a chat server running at www.ajdigital.com. This server is only for development and testing. I will not guarantee it's stability or reliability, but you are welcome to test against it.
The chat server is called NFC Chat and is an open source Java chat server. More information and source code is available at http://nfcchat.sourceforge.net.
I chose this server because it is open source, well designed, full of features, and easy to extend. You can add new message types, tweak the code, or, as I did, look at how it is implemented and add your own code to it.
Made "Flashable"
I extended the chat server to change the format in which it sends messages. Flash requires that all socket messages are sent and received in XML format. I just wrapped the default NFC messages in simple XML. Essentially, instead of sending and receiving messages that look like:
/saytoroom chatroom hi, guys!
The messages now look like:
<message value="/saytoroom chatroom hi, guys!" />
These changes I made require no modifications to the source provided on SourceForge - they simply extend the existing application with new functionality.
They are in SourceForge CVS in web/flash/ if you want to grab them there and will be available in the build following release 1.0.6-rc2.
License
I am distributing the chat engine under the GNU General Public License (GPL) which pretty means you can do anything with this stuff except sell it to someone else without getting my permission. You can do absolutely anything you want with the interface. If you want to use this stuff in your own work and/or sell it as part of your work, all you need to do is ask.