while (thread != null) { if ((msg = msgParser.getNextMessage()) == null) { thread = null; break; } msg.Action(gdata); try { thread.sleep(GlobalData.ClientMsgHandlerDelay); } catch (Exception e) {} }
Here is a typical content of a data info in the objects.txt :
4@3023&2027&3&20&40#
4 is its message type which is separated to the other data by a '@' character, in
this case, 4 is a door object message.
3023 is its object id, and 2027 is the id of its belong objects. 3 is its direction,
in this case is the west side. 20 is its starting pixel and 40 is its ending pixel.
All intermediate data is separate by & sign, and each object is ended with a # sign.
These separators are defined in Message.java
Map Hierachy
We have seen that every objects has a self id and a belong id, these 2 member
data are defined in the mazeObject.class
which is the super class of every
mazeObject. (block, room, door, item and player) That means every objects has
these 2 member data. Only block has no belong id, which always contains a 0 in its
belong id. The following are the possible relationship between 2 maze objects.
Block --+--- Room +--- Item +--- Player Room ---+--- Door +--- Item +--- Player Player -+--- ItemWhen constructing the map (by MapConstrutor),it is very important that the belonging object arrived before the belonged objects. for example, block has to arrive to the client before the rooms that have a belong id same as that block. Otherwise, the rooms can not be construted into the mapStructre.
The code in CollisionDetector.java
looks like this:
if (gdata.map.needMoreBlock(r,c,-1,0)) { // request the next 3 blocks gdata.reqSender.mapReq(r-1,c-1); gdata.reqSender.mapReq(r-1,c); gdata.reqSender.mapReq(r-1,c+1); // remove the opposite 3 blocks gdata.map.removeBlock(r+2,c-1); gdata.map.removeBlock(r+2,c); gdata.map.removeBlock(r+2,c+1); }
There is little problem with the first 2 URL, however, the loading of the 3rd type of URL is somewhat tricky.
When mapConstructor constructs the item into the map, if the program is in the client side, it will give a request of image for that itme to the IconReader. IconReader is a thread reading these requested icons and put them in the ImageTable. Before the IconReader read the images of that icon, it is displayed as the default image (images/it.gif>, so is that when the image can not be found. (the URL is invalid)
When reading the image, the IconReader will test if the URL is valid by
calling its url.openStream() method. This is important when no one knows if the
specified URL is correct, or still there.
Each client has a CrashReporter thread which
generates a message to the server every 1000 miliseconds. If the server does not
receive this message within the period, it assumes that the client quits and do
the proper things.
The last 2 images have been introduced in the previous topic: Dealing
with URL, this part emphasizes on the System Images.
The system images defines the default images of the moving person, and the default
item images. they are put under the directory "images" with can be specified on
the applet html tag. (We realize later that this is not proper for the client
to change). Every Object has a drawing peer named DrawXXX, for example Room has
DrawRoom, Player has
DrawPlayer.
It is not difficult to guess that DrawPlayer
contains the images files of the default player images.
DrawItem has the image
files of default items.
As to the DrawRoom and
DrawDoor, they do not have
images but they both have a special way to draw themselves.
All of these DrawXXX instance are put in the ImageTable (in
ClientGlobal.java and are used in the drawSelf
method of each objects. For item, if there is no DrawItem instance corresponding
to the id of that item put in the ImageTable, it will just display the default
item image. This could happen if the specified item URL does not exist. (in the
case IconReader can not find it).
The server forks a ClientManager
for each client, which sets up the first 2 message channels (see below),
waiting for a new client connects to. Once the connections are made, the
server forks another ClientManager and wait another new client and so on.
Fail/Stop Model
Fail/Stop is a term in fault tolerant. This program can't tolerate any fault,
especially for the server. But it can detect if there is a crash and does what it
can do. for example, it the client crash or stop due to an unexpected event like
computer crash, network failure... The server can detect this situation and inform
other clients which can then know the quitting of that client. Dealing with Images
There are several kinds of images: Client/Server
To construct a client and server connection is pretty simple in Java due
to the existing
socket package and thread support. The former makes it easy to construct the
connection and the latter makes the server easy to handle mutiple clients at
the same time. There can be theoreticaly unlimited number of clients connecting
to the server at the same time. The only limit is the CPU speed and Network
bandwidth.