2007年12月06日
Hello World Chat Part 1
Hi!
In this article we will implement a simple chat app with input, user list and chatroom list. It’s a semi large project so I will split it into two parts. This article will cover most of the server-side code and the second part will cover the client-side code.
Shown below is my humble chat interface. I’m not an expert on swing so feel free to touch up the interface. You can download the source here hello-world chat source.
Last time we lightly touched upon the DObject and it’s inner workings. In this lesson we are going to use those DObjects to help us send chat messages and user information to other people. In addition to this I will be using MVC model view component pattern to create the application. Although this sounds complicated the OOO libraries supplies us with something called the crowd framework. The crowd framework builds upon the narya library providing a MVC framework to help structure the game code.
We’ll start by setting up our environment.
Get a copy of OOO gardens library and run distall to build the library if you haven’t yet. This is all explained in my previous article. Next, create a new folder. For the sake of simplicity I will call it “helloworld“. After that copy all the created files in “gardens/dist/lib” to “helloworld/lib“. Now you have all the libraries needed to use the Crowd framework. Next we have to configure a build file. This isn’t an Ant tutorial so I’m going to borrow and modify a build file from the gardens folder. Copy the “gardens/projects/games/jreversi/build.xml” to “helloworld“. Finally create these folders “src/java/net/tutorial/client/” and “src/java/net/tutorial/server/“. Your final workspace structure should look like this.
helloworld/
build.xml
lib/
activation.jar
ant.jar
commons-beanutils.jar
....
....
src/
java/
net/
tutorial/
client/
data/
server/
Now we have to modify a few things inside build.xml so we can use it for our project.
<project name="helloworld" default="compile" basedir="."> <– change “jreversi” to “helloworld”
<property name=”app.name” value=”helloworld”/> <– change “jreversi” to “helloworld”
<!– declare our classpath –>
<path id=”classpath”>
<fileset dir=”lib” includes=”**/*.jar”/> <– change “../lib” to “lib”
<pathelement location=”${deploy.dir}/classes”/>
</path>
Modify the prepare task to look like this
<!-- prepares the application directories -->
<target name="prepare">
<mkdir dir="${deploy.dir}"/>
<mkdir dir="${deploy.dir}/classes"/>
</target>
Finally add these two tasks
<!-- a target for running a game client -->
<target name="client">
<java classname="net.tutorial.client.HelloWorld" fork="true">
<classpath refid="classpath"/>
</java>
</target>
<!-- a target for running the game server -->
<target name="server">
<java classname="net.tutorial.server.HelloWorldServer" fork="true">
<classpath refid="classpath"/>
</java>
</target>
Now that we setup our environment we can use these ant commands
- dist: compile and create our jar file
- server: start our server
- client: start an instance of the client
- gendobj: generate dobject (I will explain this later)
Before we start coding I want to lay out our tentative plan of attack is as follows.
- Create our server.
- Setup the server ports and connections.
- Create a special client that can hold our chatroom data.
- Implement code to create chat rooms that can be used by the clients.
- Create a manager to handle the chat rooms.
- Create our client.
- Setup our credentials and logon code.
- Initialize our managers which handle server messages.
- Implement code to connect to the chat rooms.
- Implement code to send chats to other clients and move rooms.
So let’s start coding!
First let’s create our server. Create a new class that extends com.threerings.crowd.server.CrowdServer and call it “HelloWorldServer.java”. First we need to define a static main entry point.
public class HelloWorldServer extends CrowdServer {
public static void main(String[] args) {
HelloWorldServer server = new HelloWorldServer();
try {
server.init();
server.run();
} catch (Exception e) {
Log.warning("Unable to initialize server.");
Log.logStackTrace(e);
}
}
This is the most basic server you can create using the CrowdServer. This will let the client connect and that is about it. server.init() and server.run() basically create the managers like the DObject manager and begin the server sending and receiving threads.
Our next step is create our custom client. What I mean by custom client is a DObject that represents a client. When the client connects to the server it creates a new DObject called ClientObject. This DObject holds basic client information. Then it is sent back to the client. So when the object is modified by the server the client will know. The crowd framework extends this object with something called BodyObject. The BodyObject holds more information like username and status which help shape a more concrete user. In our game we will need one more bit of information which is a list of chat rooms that the client can enter.
We will do this using three specific steps.
- Extend the BodyObject class with our own class called ChatUserObject and add in our needed members.
- Run an ant task called gendobj to auto generate code for the DObject
- Override the ClientResolver function which is in charge of creating client objects.
First, create a class called ChatUserObject that extends com.threerings.crowd.data.BodyObject and add one public String array member called roomIds. roomIds will store the ids of the chat rooms that the player can choose to move into.
public class ChatUserObject extends BodyObject {
public String[] roomIds;
}
Save the file and then call ant gendobj from the console. The gendobj ant task reads in your file and produces specific static strings and functions that the DObject uses to send your data.
In the next step we need to tell the server to use our ChatRoomUser besides BodyObject. The way to do this is create a new ClientFactory and override the functions which are responsible for creating the Client DObject. The CrowdServer instance that you extended contains one static member called clmgr. This is the client manager. The client manager is responsible for creating and deleting clients and uses the ClientFactory to create a client resolver. The ClientFactory uses the ClientResolver to create the actual DObject. At this point it’s not necessary to know all the details, just that you know who creates the DObject that represents the client. Basically all you have to do is pass your class that extends the ClientFactory into setClientFactory and implement the abstract methods createClient and createClientResolver. Inside of createClientResolver we have to create a new class that extends CrowdClientResolver and overrides createClientObject. Inside of createClientObject is where we will return our custom ChatUserObject. Rather that creating many files I just created a bunch of anonymous classes. We can override the CrowdServers init function and place the code in there.
@Override
public void init() throws Exception {
super.init();
// configure the client manager to use our bits
clmgr.setClientFactory(new ClientFactory() {
public PresentsClient createClient(AuthRequest areq) {
return new CrowdClient();
}
public ClientResolver createClientResolver(Name username) {
return new CrowdClientResolver() {
@Override
public ClientObject createClientObject() {
// create our custom client
return new PlayerObject();
}
};
}
});
.....
Now that we have our custom client object we need some chatrooms for our chat user. Creating a new room takes some steps
- Create a PlaceView (view) that will be used for the clients interface.
- Create a PlaceController that will be used to controll the panel (view)
- Create a PlaceConfig that encapsulates the information to configure our Controller.
- Create room instances on the server side using place registry.
You can see that we have a view and controller. The model is the data stored inside our ChatUserObject and one more object called the PlaceObject. The PlaceObject is also a DObject which stores shared information between the clients which can be used to update and modify the view.
In the next article I will cover implementing new rooms and the sending chat messages. See you next time!
- Posted by brian on 15:42 filed in Threerings, English
- パーマリンク


Leave a Comment
Trackbacked