ATCP Documentation
Version 1.0 - June 1, 2007
Transport
This protocol needed to be compliant and invisible to existing TELNET standards because the primary client of choice is still simply a TELNET-compatible one. So, the following format was designed.
Enabling the Transport
The transport layer must be enabled. This involves using standard TELNET sub-option negotiation to determine if the server (and/or client) is capable of ATCP communication. RFC 855 describes the process of sub-option negotiation. We provide a very brief summary here. The server asks the client whether it is capable of supporting ATCP (a 3 unsigned-byte sequence):
IAC DO ATCP (255 253 200)
Note, that the byte 200 is an arbitrary value chosen by Iron Realms, it is not endorsed by any TELNET standards. It was chosen because it did not interfere with any other registered TELNET options. The client then responds with another 3 unsigned-byte code:
IAC WILL ATCP (255 251 200)
From this point on, the server knows that the client is ATCP capable (and is expecting to receive ATCP messages).
Sending Messages
Once the ATCP option has been been enabled, a message may be sent to the client or server using standard TELNET sub-option markers. For example, IAC SB ATCP IAC SE. The start and stop marker byte sequences are defined as follows.
| Char Sequence | Numeric Version | Description |
| IAC SB ATCP | 255 250 200 | Start sequence |
| IAC SE | 255 240 | Stop sequence |
The text between the two markers includes the entire ATCP message body, and can be any text you desire (except, of course, the end marker sequence). However, to build a consistent and modular messaging protocol, we define a common message format.
Message Format
The transport alone is not interesting. To provide useful functionality, we define a set of messages and an informal protocol that can be sent on this new piggy-backing transport.
We define a message to be a single block of text embedded in an ATCP begin/end sequence. The entire block of text is used as the message, with the following characteristics:
- Messages going to the server must be less than 2048 bytes in length.
- Lines are terminated with a single newline character ('\n')
- The first line is the "header" of the message.
- The first word (contiguous, non-whitespace) is the message type.
- Extra text may also be placed after the message type, and as long as it does not contain a newline, it is still considered part of the header.
-
- All following lines (if any) are the message "content"
To support flexibility and evolution of the standard, messages are grouped into "modules" which define what messages can be sent, what they mean, and what (if any) responses are defined for those messages. Each module is like a little "mini" protocol.
Message Module Negotiation
To facilitate the flexible messaging protocol, we define a single message that is "outside" the module system and is provided to allow the client to tell the server about what modules it supports. This should be the very first message the client sends. (Note: currently there is no way to tell the -client- what features the server does, but this could easily be added by simply filtering the list and providing the last step in the negotiation.)
hello <client "key"> <client version> \n <supported module list>
Tell the server about the client including a "key", its version, and what modules it supports. The key is simply a single-word (congituous non-whitespace) describing the client, for instance "Nexus" or "MySuperCoolClient". The version is informational only, but needs to also be a single word (e.g. "1.2.3").
The module list is simply each module that the client supports, along with a version for that module (since modules themselves may change over time), one per line. The version of a module should be a simple integer value, starting with 1. So, an example message might be:
hello Nexus 3.0.0
composer 1
keepalive 1
filestore 2
buddylist 5
Modules
These are the various negotiable bits of functionality. To ease readability, the messages below are color-coded based on who sends them.
| A server sent message: | A client sent message: |
ThisIsAServerSentMessage <blah>
An example of a message sent by the server.
|
ThisIsAClientSentMessage <blah>
An example of a message sent by the client.
|
auth 1
Auth.Request CH \n <challenge seed>
Auth.Request ON|OFF
As of June 1, 2007, this is being made optional and auth requests may be safely ignored (no response sent)
- CH (i.e. Challenge)
- This is sent to the client so that trusted communication can
begin. The client is expected to perform an authorization
function based on that seed, and then respond to the server
with the results of that function (and including the client
name and version).
- ON|OFF
- Enable or disable 'authenticated mode' on the client. Send an
ON after the client has given a proper response to the auth
challenge, (or just send it regardless if you don't care about
authenticated clients). Send an OFF to inform the client that
the server now considers it an untrusted client.
auth <challenge response> <client "key"> <client version>
Provide the authorization that was previously requested. The client key and version should be the same as in the original hello message.
composer 1
Client.Compose <title> \n <initial text to edit>
This causes the client to open a text editing window (if the
option is enabled) so that lines of text can be edited using the
local machine's native widget set. The initial text (if provided)
will be in the editing window to start with. The editing window
also has two buttons: "Save" and "Cancel". The save button causes
the lines of text to be written to the server, followed by a *s
by itself. A cancel results in two normal telnet commands (not atcp messages)
being sent: *q followed by "no" to cancel out of the Achaea composer
without saving changes. Obviously this is really only sent when
entering the Achaea composer and it detects that the user is using an ATCP compatible client. The <title> option will set the title of the composer window.
The above behavior of save/cancel is a remnant of an old implementation that
hasn't been updated. It should use an ATCP message back to the server to tell it
of a status code.
olesetbuf \n <text>
This is sent prior to saving the contents of the composer using *s.
keepalive 1
keepalive
A very simple do-nothing command that tells the server that it should not close the connection on the user because he's really doing something (for instance, editing a lengthy article/post in an external editor). Obviously, the timing and requirements for ditching inactive players varies from game to game.
char_name 1
Char.Name <short 'unique' name> \n <full title>
This should be sent whenever a player's name changes (and once
upon logging the character in. It tells the client what the
player's name in the game is.
char_vitals 1
Char.Vitals \n <encoded vitals>
This is a sequence sent informing the client of the character's
vital information (hp, mana, etc). They are encoded as follows:
<vital code>:<current>/<max>. (For example, "H:45/100") Multiple
items are separated by spaces. The defined codes we have are:
H = hp, M = mana, W = willpower, E = endurance.
filestore 1 (requires: char_name 1)
This module is intentionally undocumented as it should not be used by third parties.
File.Content <file name> \n <File contents>
This is the response to a request from the client to retrieve the
contents of a file.
topvote 1
Client.VoteReminder [<labelid>] [ \n <vote url>]
An optional reminder that will that should hopefully
spur the user to vote using a button in the client.
If the optional url is sent, then it will set the VOTEURL resource in the client to a new value before enabling/showing the vote button, otherwise it's expected
that the url was specified elsewhere (packaging, etc).
voted
After clicking the vote button, this should be sent back to the server to let it know the click occurred. Note this doesn't actually mean they clicked-through on whatever vote page, just that they clicked in the client.
room_brief 1
Room.Brief <brief desc>
Give the client information about the brief description of this room.
room_exits 1
Room.Exits <exit list>
Tell the client about any obvious exits from the user's current room.
The list is encoded in a comma separated short form (e.g."n,w,o,x").
It's expected that the client will update whatever status information
it may currently have displayed (light up icons, etc). The valid exits are:
n - north,
e - east,
s - south,
w - west,
ne - northeast,
nw - northwest,
se - southeast,
sw - southwest,
u - up,
d - down,
i - in,
o - out,
x - special exit(s) (e.g. "mirror" ,"portal", etc)
Note, status conditions in the game may limit the exits that are visible,
so this shouldn't be relied upon for something like world building.
mediapak 1
MediaPak.Def \n <pakdef> \n <pakdef>\n...
This will define a Media Pak to the client. The definition includes
the following:
- id
- The single-word unique identifier for the pak (all resources
and files are referenced using this id). E.g. for "{foo}/bar",
the id would be "foo".
- src
- This is the URL for the pak so the client can download it
if necessary. If it does not begin with "http://" then it's
assumed relative to the codebase of the client.
- req (Optional)
- If present, it may be 0 or 1. A 1 indicates that it
is high priority and will be required shortly. "required" paks
are downloaded before non-required paks.
- size (Optional)
- If present, this indicates the expected size of the
file pointed to by the 'src' parameter (mostly used by the
client's caching system).
- date (Optional)
- If present, this is the last modification date of
the file pointed to by the 'src' paramter (mostly used by the
client's caching system).
The parameters are chained together in key=value form separated by commas.
For instance:
"id=charcreate_core,src=media/characreate_core.mpak"
Once the client encounters a pak definition, it sets it to download in the
background. This can be used to safely pre-load any extra media that may
not be necessary while the user is busy doing other things. The race
portraits are loaded this way. The Wiz system supplies a method for
specifying a required set of media paks, but they must have been defined
using this message beforehand (see Wiz page definitions, 'mediapaks'
attribute).
MediaPak.WaitFor <id>[,<id>...]
Tell the client to force all the paks specified in the comma-separated
list to load. Not usually necessary.
wiz 1 (requires: mediapak 1)
wiz <instanceId> changed <widgetId> \n <value>
wiz <instanceId> clicked <widgetId>
These are sent by the Wiz framework when widgets either change value or have been interacted with. Full documentation of the Wiz system is beyond the scope of this document, but these are the two primary 'drivers' of that functionality.
java 2
Client.JavaEnv
Send a request to the client that it report back its java environment
variables (system properties). It should respond with an appropriate
"javaenv" ATCP reply.
javaenv \n <environment text>
Send a listing back to the server of the current user's Java environment (useful in tracking down bugs).
feedback \n <text>
When a significant error occurs in the client, it can send the server a dump of information describing it (such as a backtrace or other informational message). Generally the server logs this to a file to be looked at later.
ping 1
ping <current average ping>
Do two things: request a Client.Ping response be sent back to the client (so the time can be measured), and provide the server with an average value of the ping thus far. It's up to the server to do with as it pleases (possibly nothing) but can be useful in identifying users that have a slow connection.
Client.Ping
Send a ping response to the client. This does nothing except allows the
client to measure the time it takes to receive it (after sending a request).
unclassified/implicit
These are old messages that were never assigned a module. They have no messages being sent from the client, and may be safely ignored if the client doesn't support this type of functionality.
Client.OpenURL [<window>] \n <url>
This tells the client that we want it to open a browser window
to the given url. The window tag is for named windows (just like
the javascript window.open() popup style creation).
Client.Goodbye <text>
This is sent right before the server terminates a connection. It's
meant to give a _short_ user-friendly reason why the link is being
severed so that the client can inform the user.