1528 lines
66 KiB
Plaintext
1528 lines
66 KiB
Plaintext
Updated $Date: 2009-01-19 00:07:11 -0500 (Mon, 19 Jan 2009) $ by $Author: lalo $:
|
|
|
|
Outline:
|
|
|
|
This section contains a brief outline of the document.
|
|
|
|
Background: List some of the background for client/server, and current state
|
|
of affairs.
|
|
General Socket Notes: How sockets are presently used.
|
|
Protocol: Commands that are sent back and forth.
|
|
Example Session: A brief example of what protocol commands would be sent
|
|
back and forth.
|
|
Programming notes: A few notes that can be useful for people writing clients
|
|
are extending the server.
|
|
Todo: Things to do in the future.
|
|
|
|
Note: each section is separated by a line of dashes. This should make finding
|
|
a specific section easier.
|
|
|
|
In order to make things a little for people doing porting, I have
|
|
added SUMMARY comments in some of the sections. These contain a very
|
|
brief summary of some aspect that is needed for writing the code. A more
|
|
detailed explanation of the SUMMARY can be determined by reading the
|
|
section.
|
|
|
|
------------------------------------------------------------------------------
|
|
Background:
|
|
|
|
Originally, the communications plan was set to be a text based system.
|
|
These messages are what is originally detailed below (now removed). It was
|
|
up to the server and client to parse these messages and determine what to
|
|
do. These messages were assumed to be 1 line per message.
|
|
|
|
At a reasonably early stage of development, Eric Anderson wrote a fairly
|
|
(but not totally) complete client/server that used his eutl package. This
|
|
package pretty much set up packets with subpackets - these subpackets would
|
|
have a tag for the data type, then the data itself. Thus, you could any many
|
|
types, and after transmission, the other end could decode these commands.
|
|
|
|
This works fairly well, but I think the creation of numerous sub packets has
|
|
some performance hit. Also, the eutl was not especially well documented,
|
|
so writing a client for a different platform became more difficult (you
|
|
needed to first port over eutl.) An example such of this is the Java client
|
|
currently in production. Also, Eric left to work on other products shortly
|
|
after writing his client, which didn't really leave anyone with a full
|
|
understanding.
|
|
|
|
I have decided to remove the eutl dependency. At least one advantage is
|
|
that having this network related code directly in the client and server
|
|
makes error handling a bit easier/cleaner.
|
|
|
|
However, instead of a straight text method, the outside packet method is:
|
|
<size (2 bytes)><data (size bytes)> The <size> is the size of the data
|
|
packet, the 2 byte size for the size information is not included here.
|
|
|
|
Eutl originally used 4 bytes for the size - to me, 2 bytes seems plenty (gives
|
|
a maximum packet of 32767 - I can't see ever going beyond a few thousand,
|
|
simply because in a fast action game, transmission size of such a packet would
|
|
probably not make things playable.) While saving 2 bytes might not be much,
|
|
it makes a least some sense.
|
|
|
|
The actual data is something of the nature of the commands listed below. It
|
|
is a text command, followed by possible other data. The remaining data can
|
|
be binary - it is up to the client and server to decode what it sent.
|
|
|
|
The commands as described below is just the data portion of the packet. If
|
|
writing a new client, remember that you must take into account the size of
|
|
the packet. there is no termination of packets, other than knowing how long
|
|
it should be.
|
|
|
|
For now, most everything that is sent is text. This is more or less how
|
|
things worked under eutl, except it packed the ints into 4 bytes in a known
|
|
order. In some cases, we handle ints as strings, in others, they are
|
|
sent as binary information. How any command handles it is detailed
|
|
below in the command description.
|
|
|
|
The S and C represent the direction of the data (S->C represents something
|
|
the server sends to the client, C->S represents something the client sends
|
|
to the server.)
|
|
|
|
In terms of all binary values, we use MSB order (same as eutl used). This
|
|
includes the initial length information, as well as any ints or shorts that
|
|
get sent inside the packets. All packets are defined to have at least one
|
|
word of text, followed by a space, then followed by optional data (which can
|
|
be binary.)
|
|
|
|
Side note: Generally, the data the client sends to the server is text,
|
|
but a fair amount of data the server sends to the client is binary. This
|
|
has somewhat to do with who wrote what code, and also has to do that the
|
|
S->C bandwidth is going to more the more serious limitation - the client
|
|
generally won't be sending so much data that the its flow is much problem.
|
|
|
|
Note that all the commands as detailed below are up to date descriptions
|
|
I removed a lot of the old notes on this file, because they were
|
|
out of date, and while might be good ideas, were not all that relevant to
|
|
how things currently work.
|
|
|
|
Summary: Packets sent back and forth have a 2 byte header (MSB order)
|
|
which contains the length of the rest of the packet.
|
|
|
|
------------------------------------------------------------------------------
|
|
General socket notes:
|
|
|
|
We are using a TCP/IP socket. Other methods could be used, but the
|
|
present protocol does not make very good provisions for missing data, so
|
|
it needs to be something that corrects errors/does resends automatically
|
|
(or just doesn't get errors in the first place.)
|
|
|
|
For now, we set non blocking output on the server side. This means we don't
|
|
have to worry about internal buffering.
|
|
|
|
If the connection is lost (which will also happen if the output buffer
|
|
overflowing), it looks like we just terminate the connection without saving
|
|
(meaning last save takes effect.) This can certainly be abused the same way
|
|
that currently killing the server (ie, go to treasure chamber, get all the
|
|
treasure, kill server, wait for map to reset, play again, with you starting
|
|
in the treasure chamber.)
|
|
|
|
I don't know if there is a really good way to handle it. The other method
|
|
would be to save the player back in town. But this then gets the situation
|
|
of 'oops, I'm trapped', lose connection, start back in town.
|
|
|
|
This is probably preferable - all you really gained there is a word of
|
|
recall spell/scroll. Also, it doesn't really hurt the honest players who
|
|
lost their connection for various reasons (and in fact, could be a disadvantage
|
|
if they can't connect again until after the map resets, and they lost all
|
|
the loot they were working on..)
|
|
|
|
The server only reads data from the socket if the player has an action.
|
|
This isn't really good, since many of the commands below might not be actual
|
|
commands for the player. The alternative is to look at the data, and if it
|
|
is a player command and there isn't time, store it away to be processed later.
|
|
But this increases complexity, in that the server must start buffering the
|
|
commands. Fortunately, for now, there are few such client commands.
|
|
|
|
If it becomes a case where the client is requesting images/sounds, dual
|
|
channels could probably be used, since requesting that data is not related
|
|
to the actual playing of the game (or a special daemon that serves those
|
|
requests could also be done.)
|
|
|
|
SUMMARY: TCP/IP sockets are used for exchange data. Server uses non
|
|
blocking i/o when writing to the socket, and the server only reads from the
|
|
socket when the player actually has time for an action.
|
|
|
|
------------------------------------------------------------------------------
|
|
Protocol:
|
|
|
|
Object tags: Many of the commands below refer to 'object tags'. Whenever
|
|
the server creates an object, it creates a unique tag for that object
|
|
(starting at 1 when the server is first run, and ever increasing.) Tags
|
|
are unique, but are not consistent between runs. Thus, the client can
|
|
not store tags when it exits and hope to re-use them when it joins the
|
|
server at a later time - tags are only valid for the current connection.
|
|
|
|
I have decided to break the protocol into various sections which based
|
|
somewhat on what the commands are for (ie, item related commands,
|
|
map commands, image commands, etc.)
|
|
|
|
******************************************************************************
|
|
COMMANDS RELATING TO ESTABLISHING THE INITIAL CONNECTION AND CLOSING THE
|
|
CONNECTION
|
|
|
|
C->S: version <csval> [scval [vinfo]]
|
|
S->C: version <csval> [scval [vinfo]]
|
|
Through the version command, the client and server exchange what
|
|
version of the protocol they understand. Neither send this
|
|
in response to the other - they should both send this
|
|
shortly after a connection is established.
|
|
|
|
csval is the version level of C->S communications.
|
|
scval is the version level of S->C communications.
|
|
vinfo is a string that is purely for informative that general
|
|
client/server info (ie, javaclient, x11client, winclient, sinix server,
|
|
etc). It is purely of interest of server admins who can see what
|
|
type of clients people are using.
|
|
|
|
If a new command is added to the protocol in the C->S direction, then
|
|
the version number in csval will get increased. Likewise, the same
|
|
is true for the scval.
|
|
|
|
As far as the client is concerned, its scval must be at least equal
|
|
to the server, and its csval should not be newer than the server.
|
|
|
|
The server does not care about the version command it receives right
|
|
now - all it currently does is log mismatches. In theory, the
|
|
server should keep track of what the client has, and adjust the
|
|
commands it sends respectively in the S->C direction. The server is
|
|
resilant enough that it won't crash with a version mistmach
|
|
(however, client may end up sending commands that the server just
|
|
ignores). It is really up to the client to enforce versioning and
|
|
quit if the versions don't match.
|
|
|
|
scval and vinfo was added starting in 1020. Before that version,
|
|
there was only one version sent in the version command.
|
|
|
|
The version are currently integers, in the form ABCD.
|
|
A = 1, and will likely for quite a while. This will only really change
|
|
if needed from rollover of B.
|
|
|
|
B represents major protocol changes - if B mismatches, the clients
|
|
will be totally unusable. Such an example would be change of map or
|
|
item sending commands (either new commands or new format.)
|
|
|
|
C represents more minor but still significant changes - clients might
|
|
still work together, but some features that used to work may now fail
|
|
due to the mismatch. An example may be a change in the meaning
|
|
of some field in some command - providing the field is the same size,
|
|
it still should be decoded properly, but the meaning won't be processed
|
|
properly.
|
|
|
|
D represents very minor changes or new commands. Things should work no
|
|
worse if D does not match, however if they do match, some new features
|
|
might be included. An example of the would be the C->S mark command
|
|
to mark items. Server not understanding this just means that the
|
|
server can not process it, and will ignore it.
|
|
|
|
Note: Since all 'packets' have the length as the first 2 bytes, all
|
|
that either the client or server needs to be able to do is look at
|
|
the first string and see if it understands it. If not, it knows how
|
|
many bytes it can skip. As such, exact version matches should not
|
|
be necessary for proper operation - however, both the client and
|
|
server needs to be coded to handle such cases.
|
|
|
|
Note 2: For the most part, this has been obsoleted by the
|
|
setup command which always return status and whether it
|
|
understood the command or not. However there are still some cases
|
|
where using this versioning is useful - an example it the
|
|
addition of the requestinfo/replyinfo commands - the client
|
|
wants to wait for acknowledge of all the replyinfo commands
|
|
it has issued before sending the addme command. However, if the
|
|
server doesn't understand these options, the client will never
|
|
get a response. With the versioning, the client can look at
|
|
the version and know if it should wait for a response or if
|
|
the server will never send back.
|
|
|
|
C->S: addme
|
|
Tells the server that it should add me (the client) to the game.
|
|
Generally, the client will always send this command, but I suppose there
|
|
can be actions the client wants to do before being added.
|
|
|
|
S->C: addme_failed
|
|
S->C: addme_success
|
|
|
|
This are responses to the last addme command. I really think these
|
|
should be discontinued, as they are one of the few messages which is
|
|
just a confirmation of a previous messsage. The addme_failed should
|
|
really be replaced with a terminate type of of message (player quits
|
|
game, server could inform us nicely and exit out). addme_success is
|
|
really of no use - client just throws it away.
|
|
|
|
S->C: goodbye (Added in SC protocol version 1022)
|
|
Informs the client that the server has finished transmitting data
|
|
to the client. This is a bit cleaner than the client detecting
|
|
a read error. In theory, a C->S of the same type could be done,
|
|
but I don't think it would make a big difference for the server (is
|
|
going to do the same thing regardless of a clean connection drop
|
|
or a bad one).
|
|
|
|
Also see the setfacemode command below.
|
|
|
|
******************************************************************************
|
|
COMMANDS RELATING TO PLAYER INPUT AND OUTPUT IN THE INFO WINDOW
|
|
|
|
C->S: ncom <packet> <repeat> <command>
|
|
(ncom = new command)
|
|
Client sends a command to the server. Ordinary commands (ie, north,
|
|
west, apply, maps, etc), might be sent, commands with options may be sent
|
|
(ie, 'invoke create food of booze', 'cast medium fireball'). There are a
|
|
few special commands that can also be sent.
|
|
|
|
Packet is a 16 bit arbitrary value the server will send back through comc
|
|
to inform the client of execution end.
|
|
|
|
repeat is a 32 bit value and is the repeat value, or a count value used
|
|
for instance for dropping.
|
|
|
|
command is the actual command data (north, whatever).
|
|
|
|
'fire' command is a special case. The server will handle repeat firing.
|
|
|
|
'fire_stop' will be sent to inform the server to stop firing. A
|
|
different command name has been chosen to make things easier on the
|
|
server ('fire_stop' should be a 0 time command, with the rest of the
|
|
fire commands actually taking some time.) In some cases, 'fire_stop'
|
|
may be sent almost immediately after the first fire (in cases where the
|
|
player only wants to fire once).
|
|
|
|
S->C: comc <packet> <time>
|
|
(comc = completed command)
|
|
This is used in the window of the ncom command above. packet is
|
|
the command number we just executed (16 bit binary), and time
|
|
is a 32 bit value represent how many milliseconds the player is
|
|
currently taking to execute commands. This information can be
|
|
used by the client to do some throttling.
|
|
|
|
C->S: reply <text>
|
|
Sends <text> as a reply to the last query command sent.
|
|
|
|
S->C: drawinfo <color> <text>
|
|
Tell the client to draw whatever text in color. Color are specified
|
|
in newclient.h, and is sent as a string. The client is free to do
|
|
whatever it wants with the color information (which may very well
|
|
mean ignore it.)
|
|
|
|
S->C: query <flags> [text]
|
|
Asks the client program for input. This is only used in a few places -
|
|
mostly in creating a character and login, but in fact anyplace in the
|
|
server that changes the input state (pl->contr->state, ST_*), should
|
|
send a query.
|
|
|
|
<flags> are detailed in the <newclient.h> file, which is common to both
|
|
the client and server. The flags of relevance to this command are the
|
|
CS_QUERY flags. <flags> are sent in plaintext form.
|
|
|
|
The client is free to ignore the flags. However, if the server just
|
|
wants a single character as a reply, that is all it uses, even if the
|
|
client sends a long string (Server will use the first character.)
|
|
|
|
[text] is the question/prompt that should be printed. Right now, it is
|
|
typically just a ':'. Client should display it no matter what is is,
|
|
however. Text is an optional field. Note - as of 0.94.2, text may
|
|
be multi line, delimited by newlines. Client should handle this
|
|
appropriately.
|
|
|
|
C->S: toggleextendedtext <type>...
|
|
Ask the server to send extended text information for a given type.
|
|
type is a list of decimal integers.
|
|
Currently supported/reserved values for types are described in drawextinfo
|
|
|
|
S->C: ExtendedTextSet <type1> <type2> .... <typen>
|
|
Tell client what actually are the extended infos server may
|
|
send to the client when this is needed. All those infos will
|
|
be related to the map and send through mapextended command.
|
|
Each string represent an info which is enabled. Look
|
|
at toggleextendedinfos and drawextinfo for details.
|
|
|
|
S->C: drawextinfo <color> <type> <subtype> message
|
|
Tell the client to draw specific text. Color are specified
|
|
in newclient.h, and is sent as a string. The client is free to do
|
|
whatever it wants with the color information (it may very well ignore it.)
|
|
|
|
color same as color info from S->C drawinfo
|
|
type is an int in decimal representation, giving the type of message
|
|
subtype is an int in decimal representation, giving subtype
|
|
(flavor) of message.
|
|
message is a string representation of textual message. content of message may
|
|
very well vary depending on the type.
|
|
|
|
The server will never send a message to a client with a message type not
|
|
requested at setup by a toggleextendedinfo. Client is however encouraged to handle
|
|
those case to catch bugs in protocols which may arise in future.
|
|
|
|
It is possible a client handles a given message type but not a given subtype.
|
|
The server does not care about the client subtype (flavors) and, so, client
|
|
should have a 'generic representation' for each supported type, which will be
|
|
used when a given subtype is not supported. The type are made a way subtypes
|
|
can be considered as just visual variations (eg a scroll,a card, a letter
|
|
and a book will share the same type)
|
|
|
|
Values for types and description:
|
|
0 reserved
|
|
1 books
|
|
books contains media tags in their body (see doc/mediaTags)
|
|
message has the form <title>\n<body>
|
|
subtype represent the style of book.
|
|
MSG_TYPE_BOOK_CLASP_1 1
|
|
MSG_TYPE_BOOK_CLASP_2 2
|
|
MSG_TYPE_BOOK_ELEGANT_1 3
|
|
MSG_TYPE_BOOK_ELEGANT_2 4
|
|
MSG_TYPE_BOOK_QUARTO_1 5
|
|
MSG_TYPE_BOOK_QUARTO_2 6
|
|
MSG_TYPE_BOOK_SPELL_EVOKER 8
|
|
MSG_TYPE_BOOK_SPELL_PRAYER 9
|
|
MSG_TYPE_BOOK_SPELL_PYRO 10
|
|
MSG_TYPE_BOOK_SPELL_SORCERER 11
|
|
MSG_TYPE_BOOK_SPELL_SUMMONER 12
|
|
2 cards
|
|
3 papers
|
|
4 signs
|
|
5 monuments
|
|
6 scripted dialogs
|
|
7 motd
|
|
no subtype, content of message is the media tag enabled motd
|
|
8 admin
|
|
9 shop
|
|
10 command
|
|
Responses to commands, eg, who.
|
|
11 attribute
|
|
Changes to attributes (stats, resistances, etc).
|
|
12 skill
|
|
Messages related to using skills.
|
|
13 apply
|
|
Applying objects.
|
|
14 attack
|
|
Attack related messages.
|
|
15 communication
|
|
Communication between players.
|
|
16 spell
|
|
Spell related info.
|
|
17 item
|
|
Item related information.
|
|
18 misc
|
|
Messages that don't go anyplace else.
|
|
19 victim
|
|
Something bad is happening to the player.
|
|
|
|
******************************************************************************
|
|
ITEM MANIPULATION RELATED COMMANDS
|
|
|
|
Client requests to server:
|
|
|
|
C->S: move <to> <tag> <nrof>
|
|
All parameters are integers sent in string format. <to> is where to move
|
|
the object to, tag is the object tag, nrof is how many to move. This
|
|
command is used to pickup/drop objects. If <to> or <tag> is zero, the
|
|
object is being moved from/to the ground. This command is used to move
|
|
items from a container into inventory and vice versa. if nrof
|
|
is zero, all objects will be moved.
|
|
|
|
C->S: examine <val>
|
|
Tells the server that I want to examine object <val>, where <val> is a
|
|
text string that represents that objects tag. Objects tags are unique
|
|
for each object.
|
|
|
|
C->S: apply <val>
|
|
Tells the server that I want to apply the object <val>. Like examine,
|
|
<val> is a text representation of an integer tag.
|
|
|
|
C->S: lock <val><tag>
|
|
Tells to server to set the inventory lock flag of item tag to val.
|
|
val of 1 means that the item should be locked, 0 means unlocked.
|
|
val is 1 byte binary, tag is 4 byte binary. The server should send
|
|
and upditem command with new flags to reflect this change.
|
|
|
|
C->S: mark <tag>
|
|
'marks' and item for secondary usage. Some actions in crossfire
|
|
require an action that uses another item (improvement scrolls, flint
|
|
& steel). In order not to rely on inventory ordering or other
|
|
gimmicks, this 'marked' item is used. Only one item can be marked
|
|
at a time - server will only keep track of the latest mark sent.
|
|
<tag> is a 4 byte binary value. The server will generally send a
|
|
drawinfo command informing the player, but there is no especially
|
|
easy way for the client to know what the marked item is (although,
|
|
client knowing this is not strictly needed)
|
|
|
|
C->S: inscribe 0 <tag1> <tag2>
|
|
Player wants to write spell 'tag1' on scroll 'tag2'. This is roughly equivalent
|
|
of manually marking an item, readying the spell, and using the inscription skill.
|
|
'0' should be one byte, tags should be 4 byte integers.
|
|
|
|
Server updates to client:
|
|
|
|
S->C: item2 <location><tag1><flags1><weight1><face1><name1><anim1>
|
|
<animspeed1><nrof1><type1><object2....>
|
|
|
|
Sends item information to the client. All parameters are sent as 4
|
|
byte ints, except for name, anim, animspeed and type.
|
|
|
|
location is where the object is located (0=ground, any other value
|
|
means is the tag of the object (either player or container)). This
|
|
value is sent as 4 bytes.
|
|
|
|
tag is the item tag - unique for each item (however, a tag might
|
|
be resend, to tell the client to update some object.)
|
|
|
|
flags are various flags on the item (curse, applied, etc). They are
|
|
detailed in newclient.h It is 4 bytes
|
|
|
|
weight is the weight of single one of these objects (in grams).
|
|
The client will need to figure the total weight on its own.
|
|
|
|
face is the face number. These are not guaranteed to be the same
|
|
across different runs of the game (however, in reality, they will
|
|
only change on the one server if they make changes to the archetypes
|
|
and rebuild.) Some face information will be sent from the server
|
|
to the client before actually sending a face number.
|
|
|
|
name is the name of the object. The first byte of this field is the
|
|
text length of the name. Starting at SC 1024, this name is two
|
|
strings, with a null separation. The first byte (length) is the
|
|
length for both of these strings. This name information is just
|
|
the information of what the object is called. It does not include
|
|
how many of the items there are.
|
|
|
|
anim: This is the animation sequence id to use. It is 2 bytes.
|
|
The server will send an 'anim' command for this before sending an
|
|
item1 command with this anim command.
|
|
|
|
animspeed: How often the object should be animated. This is 1
|
|
byte, and is the number of ticks that should pass between each
|
|
animation (a value of 1 means it should be animated every tick.)
|
|
1 byte limits this to once every 255 ticks - I can't see anything
|
|
being animated slower than that.
|
|
|
|
nrof: How many objects comprise this item. This is used for
|
|
the name field and calculating total weight. It is 4 bytes.
|
|
|
|
type: A numeric type id for the item. The only meaning of this
|
|
value is really for sorting - all armors will have type values
|
|
the same or near that each other. The client is free to ignore
|
|
this. This value is 2 bytes.
|
|
|
|
S->C: upditem <flags><tag><vals>+
|
|
|
|
This updates some item (of tag) with new values. flags determines
|
|
what values are sent and to be updated (for a definition of the flag
|
|
values, see the UPD_ flags in newclient.h file.) The order of the
|
|
vals is the same as in the item command - however, as additional
|
|
values are added (and the <flags> extended), the order will remain
|
|
the LSB order of the flags - that is, the value associated with bit
|
|
1 set is sent first, then bit 2, etc.
|
|
|
|
The format of the values is same as the item command above.
|
|
|
|
Only one item can be updated with the upditem command. An item
|
|
command should have been sent by the server before an upditem
|
|
command is set.
|
|
|
|
S->C: delitem <tag1><tag2>...
|
|
Tells the client to delete items with the tag values.
|
|
|
|
S->C delinv <tag>
|
|
Tells the client to delete items carried in/by the object <tag>.
|
|
<tag> is sent as plaintext numbers. Tag of 0 means to delete
|
|
all items on the space tech character is standing on. This command
|
|
only affects the inventory of the object. To fully delete a
|
|
container object, a delinv followed by a delitem should be issued.
|
|
|
|
S->C addspell <tag1> <level1> <casting time1> <mana1> <grace1> <damage1> <skill>
|
|
<path1> <name1> <display name1> <message1> <spell2 ....>
|
|
Tells the client to add the spell(s) listed to the list of spells
|
|
the client knows about. This will be sent at login, and again whenever
|
|
new spells are sent.
|
|
|
|
The fields are;
|
|
<tag> - (4 bytes - int) The ID number for the spell item. This is
|
|
going to be unique, for each spell and will be used to refer
|
|
to it henceforth. The string form of this should also be
|
|
appended to the cast/invoke commands in order to cast the spell.
|
|
|
|
<level> (2 bytes, signed int)
|
|
The level of the spell.
|
|
|
|
<casting time> (2 bytes, signed int)
|
|
The time it will take to cast the spell, in server ticks.
|
|
|
|
<mana> (2 bytes, signed int)
|
|
The mana cost to cast the spell (may be zero)
|
|
|
|
<grace> (2 bytes, signed int)
|
|
The grace cost to cast the spell (may be zero)
|
|
|
|
<damage> (2 bytes, signed int)
|
|
The current damage done by the spell. Note that the meaning of
|
|
this number is to a large part spell dependent, what damage it
|
|
actually does will depend on how the spell works.
|
|
|
|
<skill> (1 byte, unsigned int)
|
|
The skill that the spell uses to be cast, if zero, no skill is
|
|
used in the casting of this spell.
|
|
The numbers are the same as for request_info skill_info
|
|
|
|
<path> (4 bytes, unsigned integer)
|
|
The path that the spell belongs to.
|
|
The client should determine the effect of this by comparing
|
|
these values to both the spell_paths request_info data and the
|
|
stats info concerning attunement/repulsion, etc.
|
|
|
|
<face> (4 bytes, signed int)
|
|
The number of the face that corresponds to the spell, the client
|
|
can request this facenumber if they want to show a graphical spell
|
|
representation.
|
|
|
|
<name> (1 (non-zero) length byte, followed by that many bytes of ASCII text)
|
|
This is a name to identify the spell, which the client can use
|
|
for display purposes, it should /NOT/ be used with the 'cast'
|
|
command, whilst it might work, no such guarantee is made by the
|
|
server. - Use tag instead.
|
|
|
|
<message> (2 length bytes (which may be zero) followed by that many
|
|
bytes of ASCII text)
|
|
The description of the spell. Note that this has an extra length
|
|
byte because the messages may well be longer than 256 bytes in
|
|
length.
|
|
|
|
S->C updspell <flags><tag><vals>+
|
|
|
|
This updates some spell (of tag) with new values. The flags are 1 byte
|
|
and determine which values have been updated, and should be re-read.
|
|
Not all fields may be updated by this command, only those that can be
|
|
changed.
|
|
|
|
If new fields are added in future, they will extend the flags bitmask
|
|
and the order will remain the LSB order of the flags - that is, the
|
|
value associated with bit 1 set is sent first, then bit 2, etc.
|
|
|
|
The format of the values is same as the addspell command above.
|
|
|
|
Only one spell can be updated with the updspell command. A spell
|
|
command should have been sent by the server before an updspell
|
|
command is set.
|
|
|
|
S->C delspell <tag>
|
|
Tells the client to remove its information about the spell Tag is a 4
|
|
byte value, the same as the one sent when the spell was added.
|
|
|
|
******************************************************************************
|
|
COMMANDS RELATING TO THE PLAYER OBJECT/STATS
|
|
|
|
S->C: player <tag><weight><face><name>
|
|
All fields are the same as described in item above. The only
|
|
difference is that player tells the client that this is the central
|
|
object it needs to care about.
|
|
|
|
S->C: stats <stat1><val1><stat2><val2>...
|
|
This is a server message that tells the client values of the various
|
|
stats. All values are binary. that <stat> values are listed in the
|
|
newclient.h file and are sent as 8bits. All the values sent are
|
|
16 bits with these exceptions:
|
|
-weight limit:
|
|
data is 32 bits.
|
|
-speed, weapon_sp is converted to an int first by multiply by
|
|
FLOAT_MULTI (as defined in newclient.h) and then sent as
|
|
32 bits.
|
|
-range, title are sent as strings with their length preceded. The
|
|
length is 1 byte.
|
|
-experience: If the client uses the 'exp64' setup flag, this is sent
|
|
as 64 bit data, otherwise, 32 bit data (with appropriate loss of
|
|
information. To make tracking of this easier, a different stat
|
|
type is used for 64 bit data (CS_STAT_EXP64) compared to 32 bit -
|
|
thus, the client can know what to do based on stat type. However,
|
|
for the run of the session, either CS_STAT_EXP64 of CS_STAT_EXP will
|
|
get used, never both.
|
|
|
|
-skill experience: this is only set if exp64 is set. This is sent
|
|
as the skill level, followed by the skill exp (thus, 9 bytes +
|
|
the stat type byte)
|
|
|
|
-spell paths: if spellmon is set in setup, the bitmask of attuned,
|
|
repelled and denied paths is sent. These are all 32bits
|
|
|
|
******************************************************************************
|
|
COMMANDS RELATING TO IMAGE INFORMATION TRANSMISSION
|
|
|
|
S->C: anim <num><flags><face1><face2>...
|
|
Informs the client of an animation sequence. The client is responsible
|
|
for animating the objects in the inventory window, and upditem
|
|
and other items command will refer to the animation number with
|
|
num above. All values are 2 byte binary values.
|
|
|
|
<num> is the animation number we are defining. The server will only
|
|
send the anim command for a particular <num> once per run - the
|
|
client needs to keep track what has been sent. On new runs,
|
|
anim commands will be resent.
|
|
|
|
<flags> is currently unused, but is included because I think there
|
|
may end up being cases were more about the animation than just the
|
|
num and faces are needed.
|
|
|
|
<face1>... is the various faces that comprise the animation
|
|
sequence. The number of faces can be determined by checking the
|
|
length of the packet. These values correspond in the same
|
|
way as all references to face do.
|
|
|
|
Note that how fast the object is animated is contained in the
|
|
item commands.
|
|
|
|
S->C: image2 <face><set><len><data>
|
|
Sends a png version of an image to the client. <face> is the face
|
|
number (4 bytes), <set> the faceset the image is part of,
|
|
<len> the length of data (4 bytes), data is the png data used to
|
|
the image.
|
|
|
|
S->C: face2 <num><setnum><checksum><name>
|
|
Informs the client that image <num> (binary short) of faceset <setnum>
|
|
(A byte) is associated with <name>. This is used when the client is
|
|
caching images. In normal
|
|
operation, when the server runs across a face that it hasn't sent
|
|
the client, it sends a png for that face. If the face
|
|
mode is none, the server then sends this command. The client can
|
|
then check to see if it might have cached this face, and if not,
|
|
should then request it from the server. Note that the num to name
|
|
mappings can change between server and different runs of the
|
|
server. For this reason, this data needs to be sent each
|
|
time run. The client should be able to load/determine what face
|
|
to load via the name.
|
|
|
|
C->S: setfacemode <val>
|
|
This tells the server what type of display mode the client is using.
|
|
<val> is a plaintext integer. 0=no faces, 1=bitmap, 2=xpm (pixmap).
|
|
3=png (added in CS version 1022)
|
|
If the 5'th bit is true (ie, 0x10 & val is true), that then informs
|
|
the server that client is caching the images, and only send image
|
|
names.
|
|
This command is depreciated, as the only type of images currently
|
|
supported is PNG. The client should instead use the setup command
|
|
to request if it wants to cache images or not.
|
|
|
|
C->S: askface <num>
|
|
Requests that the server send the client face <num>. It will rely
|
|
on the previous set facemode to determine what facetype to send.
|
|
num is a plaintext integer.
|
|
|
|
S->C: smooth <facenbr><smoothpic>
|
|
All parameters are short int in binary form (2 bytes each)
|
|
This command informs the client on how to smooth a face, when it will need it.
|
|
Following are the facenbr of the picture involved in the
|
|
smoothing algorithm. See doc on smoothing on how to use them.
|
|
This info may be send automatically from server if client has
|
|
smoothing enabled but may also be requested by client using
|
|
the asksmooth command below
|
|
C->S: asksmooth <facenbr>
|
|
Parameters is a plain text integer.
|
|
Ask server to send a smooth sequence. Server will respond with a smooth command.
|
|
<facenbr> is an integer telling server which face we want smooth information on.
|
|
|
|
******************************************************************************
|
|
MAP UPDATE COMMANDS
|
|
|
|
S->C: map2 <coord1><len1/type1><data1><len2/type2><data2>...<coord2>
|
|
|
|
This is an update of the map1 commands above [removed]. It is meant to be
|
|
extensible. It is also meant to incorporate the ideas of the
|
|
extended map info command.
|
|
|
|
All data is in standard binary form.
|
|
|
|
The coord value is 16 bits.
|
|
|
|
the coord values are length + x + y values.
|
|
The data represented looks like this:
|
|
|
|
first 6 bits: The x coordinate (0-63)
|
|
next 6 bits: the y coordinate (0-63)
|
|
LSB 0-3: Has the following meaning:
|
|
0: Normal coordinate
|
|
1: Use this coordinate for scroll information and not
|
|
an actual coordinate. This removes the need for the
|
|
mapscroll command. Note that coordinate are still
|
|
modified with the MAP2_COORD_OFFSET as described below -
|
|
as an example, if 14, 14 is passed, that means effective
|
|
scroll of -1, -1. This should only be set in the first
|
|
coordinate value. Another (real) coordinate pair
|
|
will immediately follow this coordinate pair.
|
|
2-15: Unused/reserved.
|
|
|
|
|
|
The x & y coordinates are offset by MAP2_COORD_OFFSET (15).
|
|
This is necessary because there may be effects noticeable to the
|
|
player (light sources) that to the left/above the visible map.
|
|
By using this offset, we can use a coordinate like
|
|
10, 27 to denote that something is 5 spaces above the top
|
|
of the map.
|
|
|
|
<len/type> This is a single byte of data.
|
|
This describes the data that is to follow. If this byte is 255,
|
|
then this is a coordinate termination byte - this means a 7+
|
|
length field of type 1f is not possible.
|
|
|
|
The top 3 bits (len) denote the number of bytes that follow - it is
|
|
possible that this is zero, to denote all the relevant information is
|
|
included in the type. If this is 7 (all bits set) then the following
|
|
byte is an additive length value. Currently, nothing has a 7+
|
|
bit length.
|
|
|
|
The bottom 5 bits is the type of data - this allows for 31 different
|
|
types of data (0-31/0x0-0x1f). The meaning of the data itself depends
|
|
on what the type is. List of various types:
|
|
|
|
0x0: Denotes this space should be cleared. Length in this case should
|
|
also be zero, as there is no data that follows. Clear in this
|
|
context means that all data associated with the space should
|
|
be purged, eg, images, sound, darkness, whatever.
|
|
|
|
0x1: Darkness information - a single byte follows on how light/dark
|
|
the space is. 0 is completely dark, 255 is full bright.
|
|
Note that 0 will never be sent - if the space is completely
|
|
dark, players won't be able to see it.
|
|
|
|
0x2: Sound?
|
|
|
|
0x3: Light sources?
|
|
0x4 - 0xf: Unused
|
|
|
|
0x10-0x19: Image information. Layer 0x10 is the lowest, 0x19 is the
|
|
highest. There are several forms of this data depending on the
|
|
length:
|
|
|
|
2 bytes: This is only the face number.
|
|
3 bytes: <face num>[<smooth>|<animspeed>]
|
|
4 bytes: <face num><animspeed><smooth>
|
|
|
|
smooth is a single byte for smoothing information.
|
|
if face_num has the high bit set, then this object is
|
|
an animation, and the byte after the animation is animation
|
|
speed (see below for more details). Smooth information
|
|
may still be sent for animations, and that would follow
|
|
the animspeed.
|
|
|
|
If face is 0, that means that the face (or animation)
|
|
is no longer visible, and smooth information should also be
|
|
cleared.
|
|
|
|
For animations:
|
|
face will have the high bit set to denote it is not a
|
|
face but an animation id.
|
|
|
|
MSB-1, MSB-2: These are used to denote type of animation:
|
|
0: Normal animation - start at first phase, etc.
|
|
1: Randomize - randomize the animation phase & timing.
|
|
2: Synchronize - this animation should be in the same phase
|
|
as other animations with the same id. Used for things
|
|
like oceans.
|
|
|
|
Like the itemcmd, the server will send information for
|
|
the animation to the client before using the animation
|
|
id.
|
|
|
|
Animations have an extra byte after the animation id -
|
|
this is the animation speed. Like the itemcmd, it is
|
|
how long, in ticks, between animations. 1 means it should
|
|
be animated every tick.
|
|
|
|
Some notes:
|
|
|
|
Coordinates outside the viewable map may be sent. In these cases, it
|
|
means that a big image that extends onto the viewable map is on that
|
|
space. For big images, only the bottom right coordinate is sent -
|
|
this is why it may be off the viewable coordinates. For such spaces,
|
|
only the actual big image itself will be sent for that space.
|
|
|
|
Note that all operations are considered updates to the space (eg, new
|
|
image, new light level, etc). The exception would be the clear
|
|
command, which means clear all data with the space.
|
|
|
|
Note that while not used now, order of these subpackets is important.
|
|
A clear (0x00) followed by other data should be parsed in that order -
|
|
clear the data, then process the data. In contrast, sending
|
|
data followed by a clear byte makes no sense. This functionality
|
|
will likely be used in the future - for example, if 6 layers need
|
|
to be cleared and the other 2 remain the same, it will be more
|
|
efficient to send that clear byte followed by the 2 layers to
|
|
redisplay instead of sending 6 layers with an empty face..
|
|
|
|
Relative to the map1/map1a commands, this is more bandwidth intensive -
|
|
basically, an additional byte is needed for each piece of data sent.
|
|
Thus, on a 25x25 map, if we presume 1.5 objects/space, this is
|
|
an extra 940 bytes to send. OTOH, typically the entire map
|
|
is not being sent - only those bits that change, so this may not
|
|
be as costly as that.
|
|
|
|
If the player is using smoothing, this may actually save bytes,
|
|
as the redundant coordinates and type/length information
|
|
does not need to be sent. With the map2 command, the mapextend
|
|
command is deprecated and is not used.
|
|
|
|
General design notes: For data types that vary in length because
|
|
of optional data, the required data should be sent first, followed
|
|
by optional data if appropriate. An example of this is the face
|
|
information - we send the 2 face bytes first, then follow that
|
|
with optional data (smoothing and/or animation data). This makes
|
|
parsing on the client easier - basically, the client should be
|
|
able to parse the data a byte (or pairing at a time).
|
|
|
|
S->C: tick <tickno>
|
|
<tickno> is an unsigned 32 bit binary value.
|
|
This just tells the client what the current tick is. Right now,
|
|
the client only uses this to know when to animate the images that
|
|
the client is responsible for animating. This will only be sent
|
|
if negotiated with the setup command.
|
|
|
|
S->C: map_scroll <dx> <dy>
|
|
This tells the client to scroll the map dx and dy direction. dx and
|
|
dy will typically be -1, 0, or 1, depending on how the player moved.
|
|
<dx> and <dy> are sent as plaintext. positive values are down and to
|
|
the right respectively, negative values are opposite.
|
|
|
|
C->S: mapredraw
|
|
Requests that the server resend the entire map to the client -
|
|
can be useful if the client or client player knows that the map
|
|
is out of date/corrupted.
|
|
|
|
S->C: newmap
|
|
This tells the client to clear the map state. This command will be sent
|
|
only if negotiated by the newmapcmd option.
|
|
|
|
S->C: magicmap <width> <height> <px> <py> <data>
|
|
This gives the client information from a magic map command.
|
|
<width> <height> are ASCII integers of the size. <px> <py> is
|
|
the player's location (ASCII), and data is binary data of the
|
|
appropriate color. It is 1 byte per space, with the low
|
|
nibble containing the color information, and the high nibble
|
|
containing extra flags, like the existence of walls and floors.
|
|
See the FACE_FLOOR and FACE_WALL values.
|
|
The string of data represents the space from left to right,
|
|
then up to down.
|
|
|
|
C->S: toggleextendedinfos <string1> <string2> .... <stringn>
|
|
Ask the server to send some additional information about the map.
|
|
This command is followed by 1 or more strings. String are separated
|
|
with spaces. Each string toggle an info. The server will respond
|
|
with the command ExtendedInfoSet telling client what actual
|
|
extended infos will be send to the client.
|
|
Valid extended infos are as follow:
|
|
smooth
|
|
send smoothlevel information to the client.
|
|
|
|
S->C: ExtendedInfoSet <string1> <string2> .... <stringn>
|
|
Tell client what actually are the extended infos server may
|
|
send to the client when this is needed. All those infos will
|
|
be related to the map and send through mapextended command.
|
|
Each string represent an info which is enabled. Look
|
|
at toggleextendedinfos and mapextended for details.
|
|
|
|
******************************************************************************
|
|
SOUND RELATED COMMANDS:
|
|
|
|
C->S: setsound <val>
|
|
Obsolete command, should not be used, will be removed at some point.
|
|
|
|
S->C: sound <x><y><num><type>
|
|
Obsolete, will never be sent.
|
|
|
|
S->C: sound2 <x><y><dir><volume><type><len of subtype>subtype<len of name>name
|
|
Plays a sound. See the 'sound' document for more information.
|
|
'x' and 'y' are bytes, position of the sound relative to the player.
|
|
'dir' is a byte from 0 to 8, the direction the sound is moving to.
|
|
'volume' is a byte from 1 to 100, arbitrary intensity of the sound.
|
|
'type' is a byte, the major sound type.
|
|
'len of action' is a byte, length of action.
|
|
'action' is a string, the actual sound name to play.
|
|
'len of name' is a byte, length of name.
|
|
'name' is the name of the sound emitter, that can be used to find a specific sound.
|
|
|
|
S->C: music <string>
|
|
Change background music. Server will send NONE as the string to stop any
|
|
music from playing. (Due to someone forgetting to update this file when
|
|
he/she implemented the command, it is unknown what exactly should be done
|
|
with the string parameter, is it a filename? If yes: relative what?)
|
|
|
|
******************************************************************************
|
|
MISC COMMANDS:
|
|
|
|
C->S: lookat <dx> <dy>
|
|
Client (player) is looking at space dx,dy. dx and dy are delta
|
|
offsets from the player (client doesn't know where the player is
|
|
on the map, so this is the only real way to deal with it.) dx
|
|
and dy plaintext integers. This is only a request to the
|
|
server - a response will typically come back in drawinfo commands.
|
|
|
|
C->S
|
|
S->C: setup <option1> <value1> <option2> <value2>
|
|
Client first sends a setup command to the server to request a change
|
|
in some value (option1).
|
|
|
|
The following options are supported:
|
|
(please keep this alphabetized to make it easier to see different
|
|
options)
|
|
|
|
bot (0/1 value):
|
|
If set to 1, the client will not be considered a player when
|
|
updating information to the metaserver. This is to avoid having
|
|
a server with many bots appear more crowded than others.
|
|
|
|
darkness (0/1 value):
|
|
If set to 1 (default), the server will send darkness information
|
|
in the map protocol commands. If 0, the server will not
|
|
include darkness, thus saving a minor amount of bandwidth.
|
|
Since the client is free to ignore the darkness information,
|
|
this does not allow the client to cheat. In the case of the
|
|
old 'map' protocol command, turning darkness off will result
|
|
in the masking faces not getting sent to the client.
|
|
|
|
exp64: If true, client can handle the 64 bit exp values that
|
|
are now used. Otherwise, values are sent as 32 bit. Setting
|
|
this flag also means that skill exp will be sent, and it will
|
|
be sent in revised method as described in the stats command.
|
|
Value is an integer in string format.
|
|
This is always the default on servers with protocol version >=1028.
|
|
|
|
extendedMapInfos (0/1)
|
|
Toggle sending from server of extended map informations.
|
|
What lies in this extended info depended on what extended
|
|
infos the client asked. See toggleextendedinfos command for
|
|
details.
|
|
|
|
extendedTextInfos (0/1)
|
|
Toggle sending from server of extended text informations.
|
|
What lies in this extended info depended on what extended
|
|
infos the client asked. See toggleextendedtext command for details.
|
|
|
|
facecache (0/1)
|
|
Determines if the client is caching images (1) or wants the
|
|
images sent to it without caching them (0). Default is 0. This
|
|
replaces the setfacemode command.
|
|
|
|
faceset (8 bit)
|
|
Faceset the client wishes to use. If the faceset is not
|
|
valid, the server returns the faceset the client will be
|
|
using (default 0).
|
|
|
|
inscribe (0/1):
|
|
Client will probably always send 1. Server will reply with 1 if it
|
|
supports the 'inscribe' command, 0 else.
|
|
|
|
map2cmd: (1)
|
|
This indicates client support for the map2 protocol command.
|
|
See the map2 protocol details above for the main differences.
|
|
Note that if map2 protocol is used, the following setup commands
|
|
have no effect, either as being redundant or not applicable:
|
|
|
|
mapsize x X y
|
|
Sets the map size to x X y. Note the spaces here are only for
|
|
clarity - there should be no spaces when actually sent (it
|
|
should be 11x11 or 25x25). The default map size unless changed
|
|
is 11x11. The minimum map size the server will allow is 9x9
|
|
(no technical reason this could be smaller, but I don't think
|
|
the game would be smaller). The maximum map size supported in the
|
|
current protocol is 63x63. However, each server can have its
|
|
maximum map size sent to most any value.
|
|
|
|
If the client sends a mapsize command out of valid range, the
|
|
server will respond with a mapsize with the maximum size
|
|
the server supports. Thus, if the client wants to know the maximum
|
|
map size, it can just do a 'mapsize 0x0' and it will get the
|
|
maximum size back.
|
|
|
|
The server will only set the mapsize for the client if both x & y values
|
|
are valid. For example, if the maximum map size is 25x25, and the
|
|
client sends a 31x23 mapsize request, the mapsize will remain at
|
|
11x11 (default) and the server will send back a mapsize 25x25
|
|
setup command.
|
|
|
|
When the values are valid, the server will send back a mapsize
|
|
XxY setup command. Note that this is from its parsed values,
|
|
so it may not match stringwise with what the client sent, but will
|
|
match 0 wise. For example, the client may send a 'mapsize 025X025'
|
|
command, in which case the server will respond with a
|
|
'mapsize 25x25' command - the data is functionally the same.
|
|
|
|
While the server in theory supports non square viewing regions,
|
|
this has not be tested.
|
|
|
|
newmapcmd (0/1)
|
|
This tells the server if the client understands the newmap
|
|
protocol command. This is used by the client in the fog
|
|
of war mode to receive newmap commands from the server each time
|
|
the player changes maps.
|
|
|
|
num_look_objects (int value)
|
|
The maximum number of objects shown in the ground view. If more
|
|
objects are present, fake objects are created for selecting the
|
|
previous/next group of items. Defaults to 50 if not set. The server
|
|
may adjust the given value to a suitable one; this applies to both
|
|
the lower and the upper limit. Returned is the number of items
|
|
actually used; this value can differ from the given one if it has
|
|
been adjusted.
|
|
|
|
Note: the requested int value is the total number of objects
|
|
including fake objects (prev/next group and transport icons). The
|
|
intention for this option is to enable clients to use a fixed
|
|
number of slots for displaying ground view objects.
|
|
|
|
sound (bitmask)
|
|
Obsolete, server will return FALSE.
|
|
|
|
sound2 (bitmask)
|
|
New sound support. Check above for more information.
|
|
1=send sound effects
|
|
2=send music
|
|
64=mute sound; same as "sound" ncom command
|
|
|
|
spellmon (0/1)
|
|
If set to 1 the client has indicated that it wishes to be
|
|
sent the spell list and updated when it changes.
|
|
|
|
tick (0/1)
|
|
If set, the client want tick commands so it knows animation
|
|
timing.
|
|
|
|
want_pickup (0/1)
|
|
If set, the client wants pickup mode to be sent when player
|
|
correctly logs in (to synchronize interface).
|
|
Note that this flag only sends at login, not when mode changes.
|
|
|
|
All data in the setup command is in ASCII text form. options and
|
|
values can not have whitepace - the client and server use whitspace
|
|
to split the options and values.
|
|
|
|
Currently (2001-05-28), the server only sends a setup in response to
|
|
client first having sent a setup command.
|
|
|
|
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
This section describes the requestinfo and replyinfo commands.
|
|
Because these commands may handle different types of data with different
|
|
return formats, this section is formatted a bit differently to make
|
|
it easier to read the different structures.
|
|
|
|
C->S: requestinfo <info_type>[options]
|
|
S->C: replyinfo <info_type>[options]<data>
|
|
|
|
The requestinfo command is a general purpose way for the client to request
|
|
some piece of data the server may have. The server still needs to be
|
|
coded to respond to the specific info_type, but if the passed info_type is
|
|
not supported, the server will still respond with the replyinfo, but with
|
|
an empty data list.
|
|
|
|
This mechanism allows the client to send requests for data and not need to
|
|
do complicated checking if the server would understand the specific
|
|
request - if the server understands it, the data gets sent back. If the
|
|
server doesn't understand it, the client gets no data, but does get the
|
|
replyinfo so that it knows that the server does not support that
|
|
particular aspect.
|
|
|
|
Only one info_type is allowed for each requestinfo. If the client
|
|
requests many pieces of information (say image sets available, spell
|
|
listings, etc), it should send multiple requestinfos.
|
|
|
|
[options] is specific to the info_type - it could be a range of values, or
|
|
empty.
|
|
|
|
Requestinfo requests will not change any data on the server - the setup
|
|
command should be used for that. The requestinfo just requests data.
|
|
Note that since the requests can be made before a player logs in, the
|
|
requestinfo command will not generally support getting information related
|
|
to the player object.
|
|
|
|
The following info_types are supported:
|
|
|
|
image_info:
|
|
'image_info' (no options):
|
|
|
|
Request basic image information the server has. The data is sent in
|
|
text format - the replyinfo is newline terminated. Since the packet
|
|
length is sent in the header, that is used to figure out the length of
|
|
returned data.
|
|
|
|
Line 1: The last image number the server has. Note that there is
|
|
no image 0, so this also amounts to the number of images
|
|
if you start counting from one.
|
|
|
|
Line 2: checksum of all the image name information. This can
|
|
basically be used to determine if the number to name mapping is
|
|
the same, eg, if on server 1 the total is 123456, and the player
|
|
goes to server 2 and the total is the same, we can say with a high
|
|
degree of confidence that the name to number mappings are the name.
|
|
If instead the numbers differ, we know we can't rely on using the
|
|
same mappings.
|
|
|
|
Line 3+:The image set information the client has. The format
|
|
is the same as the format in the image_info file, sans comments.
|
|
The server will ignore any parameters the client sends.
|
|
|
|
An examply response:
|
|
|
|
replyinfo image_info
|
|
3512
|
|
1169234
|
|
0:base:standard:0:32x32:none:The standard image set.
|
|
1:clsc:classic:0:32x32:none:Classic and new styling.
|
|
|
|
|
|
image_sums <start> <stop>
|
|
|
|
Request the image number to name (and checksum) values - in this way,
|
|
the client can build all images before play starts and also request
|
|
any missing images. The returned data is
|
|
|
|
image_sums <start> <stop> <imagenum><checksum><faceset><namelength><name>
|
|
|
|
There is an initial space after the stop value, but no spaces after
|
|
that point. The <start> and <stop> values are ASCII text (same
|
|
format as it is sent to the server in). The start and stop
|
|
values are inclusive - thus, if the start is 0 and the stop
|
|
is 100, 101 checksums will be set.
|
|
|
|
imagenum is 16 bit binary data.
|
|
checksum is 32 bit binary data. It contains the checksum for
|
|
the image in the current selected set, and will use whatever
|
|
fallback logic the imagesets specify.
|
|
faceset is 8 bit binary data. It contains the actually selected
|
|
faceset.
|
|
namelength is 8 bit binary data. It is the length of the
|
|
name field below, including the null terminator.
|
|
name is character data. It is null terminated to make processing
|
|
easier - in this way, the client doesn't need to copy the data
|
|
to make it null terminated.
|
|
|
|
Note that due to possible OS system constraints on the maximum single
|
|
write supported to a socket, the complete set can not be requested at
|
|
once - instead, the images information should be requested in blocks
|
|
of less than 1000. The server will not process a block larger than
|
|
1000 at a time. Smaller blocks may be desired if the client wants to
|
|
try to reduce the potential lag caused.
|
|
|
|
Multiple requests for all the information can be sent at once, as the
|
|
server will buffer the response data, but constraints prevent the
|
|
server from sending the entire data back in one replyinfo (one being
|
|
that the data would be beyond 65535 bytes, so the length information
|
|
in the packet would not be accurate.)
|
|
|
|
If the client sends invalid data (stop is less than start, missing
|
|
stop paremeter, stop is beyond the number of images, or asking for
|
|
more than 1000 at a time), the reply will just be an empty list.
|
|
|
|
Note that the server will track that it has sent the face
|
|
information for the requested images, and thus will not send
|
|
it again (unless requested via requestinfo). Thus, this
|
|
request should always do the right thing with the
|
|
returned information.
|
|
|
|
exp_table (no parameters)
|
|
This requests the experience table (what exp is needed for each
|
|
level) from the server. With this data, the client can easily
|
|
display how much experience is needed for the different skills
|
|
or total exp value for next level. Data format:
|
|
|
|
<num_levels>: uint16 - max level/how many exp values follow.
|
|
<level1> ... <level num_levels>: uint64 - amount of exp needed
|
|
for the level.
|
|
|
|
Note that num_levels and the actual exp values are transmitted
|
|
as binary values.
|
|
|
|
skill_info (no parameters)
|
|
This returns the skill number to skill name mappings. In this
|
|
way, new skills can be added in the server, and the client
|
|
can use this new skill information with no changes to the code.
|
|
|
|
All data below is in text format. Format is:
|
|
|
|
stat number:skill name
|
|
|
|
Where stat number is the number that will be used to send
|
|
that skill information. Example:
|
|
141:lockpicking
|
|
142:hiding
|
|
143:smithery
|
|
|
|
spell_paths (no parameters)
|
|
This returns a list of all spell paths in the game, along with the
|
|
number associated with them. This should be used to parse spell_path
|
|
data in the stats command. The number is a bitmask but is sent as a
|
|
decimal value.
|
|
|
|
All data is sent in text format. Format is:
|
|
|
|
number:name
|
|
|
|
eg
|
|
|
|
16:missiles
|
|
|
|
race_list (no parameters)
|
|
Returns the races players can choose.
|
|
The names can be used to request more information with race_info.
|
|
Reply format is: replyinfo race_list |race1|race2|...|racen
|
|
|
|
race_info <race name>
|
|
Returns information about specified race.
|
|
(work in progress)
|
|
|
|
class_list (no parameters)
|
|
Returns the classes players can choose.
|
|
The names can be used to request more information with class_info.
|
|
Reply format is: replyinfo class_list |class1|class2|...|classn
|
|
|
|
class_info <class name>
|
|
Returns information about specified class.
|
|
(work in progress)
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
Example Session:
|
|
|
|
The client first opens a connection to the server.
|
|
|
|
S->C: version 1001
|
|
C->S: version 1001
|
|
|
|
The client/server are exchanging version information, to verify that
|
|
they can both properly communicate with each other. If there is
|
|
a mismatch, one or both of the sides might close the connection.
|
|
|
|
|
|
C->S: setfacemode 2
|
|
|
|
The client is informing the server that is wants to use XPM images. Note
|
|
that setfacemode is an optional command - if the client wants to live with
|
|
the default (XPM) mode, it doesn't need to send this.
|
|
|
|
C->S: addme
|
|
S->C: addme_success
|
|
|
|
Client is informing the server it wants to be added to the game. Server
|
|
is telling client that the command has succeeded, and it will then
|
|
be added.
|
|
|
|
NOTE: I am not sure if this is the exact order of the next few commands,
|
|
since a whole bunch of stuff is being done at once.
|
|
|
|
S->C: pixmap (All that the map command uses will be sent.)
|
|
S->C: map (display starting town map.)
|
|
S->C: stats (display default character stats)
|
|
S->C: drawinfo (display motd)
|
|
S->C: query (get player name)
|
|
C->S: reply (return player name)
|
|
S->C: drawinfo (inform player to enter password)
|
|
S->C: query (request password)
|
|
C->S: reply (return player password.)
|
|
|
|
At this point, things could deviate two ways - player could be
|
|
starting a new character, in which case, numerous draw infos, query's
|
|
(stat rolling), replys, stats (change stats that were just
|
|
rolled), map updates (player changing class) could be sent. However,
|
|
we will assume that the player actually entered the proper password
|
|
and an existing character is rejoining the game.
|
|
|
|
Once again, I am not positive this is the correct order or not.
|
|
|
|
S->C: player (send player object.)
|
|
S->C: stats (send player stats)
|
|
S->C: pixmap (assuming on different map and we haven't sent some of
|
|
the images before)
|
|
S->C: map (map player was saved on)
|
|
S->C: pixmap (assuming we have not sent image for item before)
|
|
S->C: item (item in players inventory or where he is standing)
|
|
|
|
|
|
After that is established, a loop is established that typically will result
|
|
in these commands being sent at various times:
|
|
|
|
S->C: stats - to inform the client when stats go up or down.
|
|
S->C: map_scroll (when the player moves)
|
|
S->C: map (update after map_scroll, or when player changes maps.)
|
|
S->C: pixmap/bitmap (with maps commands) to update faces.
|
|
S->C: drawinfo (Tell about hitting creatures, applying, etc.)
|
|
S->C: item (tell what objects are in players inventory, or space he is standing
|
|
on.
|
|
C->S: command (general commands, like north, fire, cast, etc.)
|
|
C->S: apply (applying and object.)
|
|
C->S: move (moving and object)
|
|
C->S: examine (examine an object.)
|
|
|
|
S->C: query (keypress for shop listing, some other areas)
|
|
C->S: reply (from last query)
|
|
|
|
------------------------------------------------------------------------------
|
|
Programming Notes:
|
|
|
|
These are a few quick notes on how things work. Note that they really
|
|
only apply to the code in the standard distribution, most of the direct
|
|
i/o is handled by functions that are talked about. If writing a client
|
|
from scratch, you will need to port this over (or write your own - it
|
|
isn't very complicated.)
|
|
|
|
For the server and the C client, a SockList structure is used for basic
|
|
data handling. Basically, this is just a structure that has an unsigned
|
|
character buffer and a length field (which contains the length of data in
|
|
the buffer, not the actual buffer length.)
|
|
|
|
As a side note, when sending a packet, you can supply the length of the
|
|
data and the sending routines will take care of sending the 2 bytes of
|
|
length information.
|
|
|
|
When getting a packet, these 2 bytes are at the start of the buffer and
|
|
not removed.
|
|
|
|
There is a file called newsocket.c - this file is shared between the`
|
|
client and server distribution, but except for the SockList data type,
|
|
it could probably be used by itself. The newsocket.c file contains
|
|
some routines to pack ints, shorts, and single chars into SockList
|
|
structs, as well as functions for the reverse. It also contains a
|
|
function to send socklists, as well as read them. The Add??? functions
|
|
increase the len field of the socklist, the Get??? functions do not
|
|
change the pointer in anyways. Thus, to get an int and move the buffer,
|
|
you do something like:
|
|
int = GetIntString(data); data+=4
|
|
As a side note, if you malloc the data for the buffer, make sure to free
|
|
it when done.
|
|
|
|
There is also the newclient.h file which is shared between the client and
|
|
server. This file contains the definition of the SockList, as well as
|
|
many defined values for constants of varying means (ie, that in the
|
|
stats command, a stat value of 1 is hit points, etc.) When porting to
|
|
a new system, you will need to grab these constant values for yourself.
|
|
|
|
A few other notes:
|
|
The item command lists the weight for an individual item of that type. It
|
|
thus becomes the responsibility of the client to parse the name to see how
|
|
many there are, and then multiply the weight by that nrof for an accurate
|
|
value. This should probably be changed, with the item command including
|
|
an nrof, with that being removed from the string we send. Also, the client
|
|
is responsible for computing the weight of containers, and thus the player
|
|
itself.
|
|
|
|
------------------------------------------------------------------------------
|
|
Image caching:
|
|
|
|
Image caching has been implemented on the client, with necessary server
|
|
support to handle it. This section will briefly describe how image
|
|
caching works on the protocol level, as well as how the current client does
|
|
it.
|
|
|
|
First, the client checks for an option denoting the image caching
|
|
is desired. If so, we initialize all the images to a default value - this
|
|
means we don't need to put special checks into the drawing code to see if
|
|
we have an image - we just draw the default images (I use a question mark
|
|
pixmap, since that makes it very easy to see what stuff is cached.) We
|
|
also initialize an array which will hold the number to name mapping so
|
|
that when we actually get the image, we know what filename to store it
|
|
as.
|
|
|
|
Second, we request the server to do image caching. This is done
|
|
by oring the cache directive to the image mode we want.
|
|
|
|
C->S: setfacemode 18
|
|
|
|
Then, when the server finds an image number that it has not send to the
|
|
client, it sends us a name command information us the number to name mapping:
|
|
|
|
S->C: face 65 CSword.115
|
|
|
|
Note that this is not exactly how the send - the number is actually send
|
|
in binary form, and there is no space between that the and the name. Such
|
|
formating is difficult here, but the above example illustrates the
|
|
data is sent.
|
|
|
|
The client then checks for the existence of the image locally. Note that it
|
|
is up to the client to apply any extensions based on display type (ie,
|
|
add .xpm or .gif or whatever.) The current client stores images in
|
|
~/.crossfire/images, and then splits them into sub directories based on
|
|
the first 2 letters - in the above example, the file would be
|
|
~/.crossfire/images/CS/CSword.115
|
|
|
|
If the client does not have the image or otherwise needs a copy from the
|
|
server, it then requests it:
|
|
|
|
C->S: askface 65
|
|
|
|
The server will then send the image via the normal bitmap/pixmap
|
|
routines.
|
|
|
|
S->C: pixmap <data>
|
|
|
|
Because the pixmap/bitmap routines do include the image name,
|
|
we must store the name & number mapping someplace before sending the
|
|
askface. I just used an array of character pointers, so then in
|
|
position 65, we do a strdup of the name, store it, then use it when
|
|
the pixmap/bitmap command comes in, and free that data.
|
|
|
|
Also, the client does occasional redraws of all data if it has received
|
|
new images and is running in cached mode. Otherwise, the map can remain
|
|
out of date indefinitely (although, once the player moves, things will get
|
|
redrawn.)
|
|
|
|
This has the effect that first time running in cached mode, performance
|
|
will actually be a little bit worse for the client (after all, it needs
|
|
to still request all the images, but is still doing pretty constant redraws
|
|
of the data.) But times after that, performance is greatly improved.
|
|
|
|
------------------------------------------------------------------------------
|
|
Changes:
|
|
|
|
This area documents changes in the protocol version and what happened between
|
|
them. Note that this is not a complete list, as the setup command
|
|
is used to control many cases.:
|
|
|
|
CS version 1022 -> 1023: just to sync version with server
|
|
|
|
CS version 1021 -> 1022: Client supports sending of verbal image type
|
|
questions.
|
|
|
|
SC version 1022 -> 1023: Server supports sending png images (addition of
|
|
image command).
|
|
|
|
SC version 1023 -> 1024: Server will send two part names (described in
|
|
item command) which contains the singular & plural form of the name)
|
|
|
|
SC version 1024 -> 1025: Support for sending all resistance
|
|
values in the stats command.
|
|
|
|
SC version 1025 -> 1026: Add face1 command that includes the image
|
|
checksum.
|
|
|
|
SC version 1026 -> 1027: Add requestinfo/replyinfo commands - client
|
|
can check this to know if it should expect a replyinfo to its requestinfo.
|
|
|
|
SC version 1027 -> 1028: mostly remove obsolete commands:
|
|
image, face, face1, map, map1, map1a, command
|
|
|
|
------------------------------------------------------------------------------
|
|
Todo:
|
|
|
|
It probably makes more sense to do a more preemptive handling of socket
|
|
events. That is, instead of sleeping 120 ms, then checking all the
|
|
sockets, we do a select on all the file descriptors with an appropriate
|
|
sleep time.
|
|
|
|
If we get input, we handle it at that time if the player has an action. In
|
|
this way, instead of handling all the actions after sleeping for the 120ms,
|
|
we can instead spread them out more. Only when the 120ms expire do we
|
|
then do all the actions like move the monsters, regenerate HP, etc.
|
|
|
|
The only potential problem I see with this right now is that select will
|
|
return immediately if there is data on the socket (player has used up all
|
|
their time, are paralyzed, etc.) This would probably mean that the server
|
|
needs to do internal buffering, which complicates things some. The
|
|
potential advantage with this is that we could peek at the data, and
|
|
if the command is not a player action (ie, maybe requesting an image, or
|
|
a misc command like who), we could still execute it. Actually, we can
|
|
get around the select problem by only adding the file descriptors from
|
|
sockets that actually have time to perform actions.
|
|
|
|
It probably also makes sense to look at the map at the end of each tick
|
|
and determine what needs to be sent (same for the look window.) If a player
|
|
is moving really fast (speed > 1), they could in theory move 2 spaces in
|
|
1 tick - what is the point then of sending a map and the items for the space
|
|
the skip over quickly?
|
|
|
|
However, what might also make more sense (but becomes a bit more complicated)
|
|
is adjust the players speed by these smaller amounts. Thus, if the player
|
|
has speed of 2.0, every (half a tick) we add 1 point or something. What
|
|
might be smarter is if we do set up the sleep system above, then anytime
|
|
we get an event that we see how much time has passed and increase all the
|
|
players speed by that amount. Thus, if a player is running, they will move
|
|
whenever they have proper speed - this may make things feel a bit snappier.
|