1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
|
Protocol used by xtris, xtserv and xtbot
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The server listens to a TCP port and keeps an internal list of clients
as well as some state information. Each client connects to the server,
identifies itself, gets some information back, and waits for the
beginning of a game. Clients stay connected until they quit, not just
until the end of a game.
Any commands that affect all connected users (such as a user clicking on
the 'start game' button, changing the game speed, pausing the game, etc)
are sent to the server first, which relays them to all clients including
the one that sent it. Only then should the client take the command into
account.
Each client manages its local game, and sends information about it
(squares to draw or clear, lines to clear or grow, etc) to the server,
which broadcasts it to all other connected clients. The server and
clients trust each other with the timing as well as with the choice of
pieces.
A client leaves the game simply by closing the connection; the server
will deal with this even in the middle of a game, and will pass the
information to the remaining clients.
Each client is assigned a number (starting at 1) by the server, and
informed of this number upon connection. Afterwards, all protocol
commands sent by the server to clients include the number of the client
from which the command originated, or 0 if it originated from the
server itself (such as when the server restarts a game).
Each protocol command is a binary packet made of:
. command length in bytes, not counting this field
(4-byte long in network order, always < 256)
. originator's number (char)
. opcode (char)
. arguments, if any
Clients must ignore any opcode that they don't understand.
In protocol commands from the client to the server, the originator's
number is ignored.
In protocol commands from the server to the client, the originator's
number if set to 0 if the command originates from the server itself,
and to the number of a client if the command refers to or comes from
one specific client.
Opcode list:
. OP_NICK = 1 (char n[])
Sent by clients upon connection, as well as when the user changes
nicknames. A client gets fully registered and its existence propagated
to all other clients when it sends its first OP_NICK.
Sent by the server to all other clients when a user changes its
nickname, or declares its first nickname.
The argument is a string of chars, and is not null-terminated.
. OP_PLAY = 2 (no arguments)
Sent by the client when the user requests a new game, without taking any
other action.
Sent by the server to all clients when one of the clients requested it,
or when everyone (save one player) lost. When a client gets this
command, it must drop any current game and start a new one (using an
OP_CLEAR to clear the board).
. OP_FALL = 3 (char l[])
Sent by the client to inform other clients that it has completed some
lines. The arguments are the line numbers, from low to high (i.e from
the top to the bottom of the pit!).
Sent by the server to all clients except the one originating the command.
It's up the each client to make lines flash before clearing them, when
they receive an OP_FALL.
. OP_DRAW = 4 (char x, char y, char color, ...)
Sent by the client to give update information about its own screen. The
arguments are any number of triplets (x, y, color), where x and y are
pit positions (from 0 to 9, 0 to 19 respectively) and color is the color
number (from 0 to 8 respectively, with 7 meaning an empty position).
Clients MUST use OP_GROW, OP_FALL and OP_CLEAR whenever they grow a line,
fall a line or clear the screen; they should not do these with a long
string of OP_DRAWs.
Sent by the server to all clients except the one originating the command.
. OP_LOST = 5 (no arguments)
Sent by the client when it has lost.
Sent by the server to all clients but the originator to inform them that
the originator has lost.
It's up to each client to draw a curtain on a user's pit when the user
has lost.
. OP_GONE = 6 (no arguments)
Sent by the server to inform all clients that a given client has
disconnected.
. OP_CLEAR = 7 (no arguments)
Sent by the client to the server to inform all other clients that it's
clearing the pit.
Sent by the server to all clients except the one the command came from.
. OP_NEW = 8 (unsigned short n)
Sent by the server to all clients to introduce a new player. This is
the only server command in which the originator number is not one of a
previously introduced client or 0.
A newly connected client gets a string of OP_NEWs (and OP_NICKs) to
inform it of all previously connected clients.
The parameter is optional: clients must be able to understand the
command with or without it; if it is not sent, clients must understand
it to be 0. The parameter specifies the number of games that the client
has already won, and is sent as a 16-bit short in network order.
Clients should not check or depend on the argument list being limited to
2 bytes; this command may be extended to pass additional information
about clients.
. OP_LINES = 9 (char n)
Sent by the client after doing n lines. This is used by the server to
re-distribute lines to the client's victim, so clients must NOT send
this command when they do only one line in normal mode. Also, this is
the actual number of lines made, not the number of lines by which the
victim's screen will grow.
Sent by the server to a client when the originator sends n lines to the
client. It's up to the client to translate this into the number of
lines by which the screen will grow (or a square), partially fill these
lines, and send the corresponding update codes back (OP_GROW, OP_DRAW).
. OP_GROW = 10 (no arguments)
Sent by the client to inform other clients that it's inserting a new
empty line at the bottom of the pit. Usually followed by OP_DRAW
commands to partially fill the line.
Sent by the server to all clients except the one originating the command.
. OP_MODE = 11 (char m)
Sent by the client when the user requests a mode change; m is 0 for
normal mode and 1 for fun mode.
Sent by the server to all clients when a user requests it, and also to
each new connecting client if the current mode is not 0. Clients must
change the mode when they get this command from the server, but not when
they send it.
. OP_LEVEL = 12 (char l)
Sent by the client when the user requests a level change; l is the
level, between 0 and 9.
Sent by the server to all clients when a user requests it, and also to
each new connecting client if the current level is not 5. Clients must
change the level when they get this command from the server, but not when
they send it. They must default to level 5 on startup.
. OP_BOT = 13 (no arguments)
Sent by the client immediately after connecting, to declare itself as
a bot.
. OP_KILL = 14 (char n)
Sent by a client, requesting to kill the client n. Ignored by the
server if the given client is not a bot.
. OP_PAUSE = 15 (no arguments)
Sent by the client when the user requests a pause.
Sent by the server to all clients when a user requests it. Clients must
pause the game when they get this command from the server, but not when
they send it.
. OP_CONT = 16 (no arguments)
Sent by the client when the user requests to continue a paused game.
Sent by the server to all clients when a user requests it. Clients must
continue the game when they get this command from the server, but not
when they send it.
. OP_VERSION = 17 (char a, char b, char c)
Sent by the client upon connection. The server compares the version
numbers to its own, and if they are incompatible sends an OP_BADVERS
back and drops the client.
The rule for matching version numbers is that the first two (major
version, minor version) must be equal, while the third (revision) can be
arbitrary. Future versions of the protocol will increment the revision
number if they stay compatible, and one of the version numbers if not.
. OP_BADVERS = 18 (char a, char b, char c)
Sent by the server to a client when the protocol version numbers do not
match; the arguments are the server's version. The client gets its
connection closed just after this, so it's reasonable for the client to
just print an error message and exit.
. OP_MSG = 19 (char msg[])
Sent by the client to send a text message (typed by the user) to all
other clients.
Sent by the server to all clients except the originator.
. OP_YOUARE = 20 (char n)
Sent by the server to the client at the beginning of the connection to
inform it of its own number.
. OP_LINESTO = 21 (char n, char to)
Sent by the server to inform all clients except 'to' that the originator
is sending n lines to 'to'.
. OP_WON = 22 (no arguments)
Sent by the server when it considers that the client has 'won' a game,
i.e when the client has lost but was the last one playing, or when the
client is the only one left playing and the server is about to
auto-restart a new game. Clients that keep track of the number of games
each user won use this to increase the counters.
. OP_ZERO = 23 (no arguments)
Sent by the client when the user requests to reset the game counters.
The client must not reset the counters until it gets the same command
back from the server.
Sent by the server to all clients when a user has requested to reset the
game counters.
A typical sequence of commands would be:
(initialization, in just about any order)
server->client: OP_YOUARE
client->server: OP_NICK
server->client: a number of OP_NEWs, OP_NICKs, and possibly an OP_LEVEL and
an OP_MODE
client->server: OP_BOT (if the client is a bot)
client->server: OP_VERSION
(the client is not yet playing)
client->server & server->client: any number of OP_LEVEL, OP_NICK, OP_KILL,
OP_PLAY, ... and other commands that
do not require that the client is
already playing
(the game starts)
server->client: OP_PLAY
(the client is playing)
(in just about any order)
server->client & client->server: any number of general mode commands
client->server: OP_DRAW, OP_CLEAR, OP_GROW, etc.. commands
[ ... ]
client->server: OP_LOST
|