The easiest way to explain a message is to give a short
C like program fragment to parse such a message. Each message can be
described by its ID or its name.
ID0x00
Something is bad. This message should never appear.
none
ID0x01
No operation.
none
ID0x02
Disconnect from the server. Stops the game.
none
ID0x03
Updates directly any values in the player state.
long index;is the index in the playerstate
array.
Possible indices are:
Normal DEM files use index 11 to 14 only.
index variable 0 health1 ??? (not used) 2 weaponmodel3 currentammo4 armorvalue5 weaponframe6 ammo_shells7 ammo_nails8 ammo_rockets9 ammo_cells10 weapon11 total_secrets12 total_monsters13 found_secrets14 found_monsters15 ??? . . . 31 ???
long value;is the new value.
long playerstate[32];is the array to describe the player state. Many other messages change (indirectly) some values in it.
index = ReadByte;
if (index > 0x1F) {
error("svc_updatestat: %i is invalid", index);
}
value = ReadLong;
playerstate[index] = value;
ID0x04
This message defines the version of the server. I never found such a message in
a DEM file. It may be absorbed by the serverinfo message.
long serverprotocol;is the version number of the
server. It should be 0x0F.
serverprotocol = ReadLong;
if (serverprotocol != 0x0F) {
error("CL_ParseServerMessage: Server is protocol %i instead of %i\n",
serverprotocol, 0x0F);
}
ID0x05
Sets the camera position to the origin of this entity.
long entity;is the entity with the camera.
entity = ReadShort;
ID0x06
This message starts the play of a sound at a specific point.
long mask;is a bitmask to reduce the amount of data.
float vol;is the volume of the sound (0.0 off, 1.0 max)
float attenuation;is the attenuation of the sound. Possible values (for all kind of sounds) are:
value QuakeC purpose 0 ATTN_NONE i. e. player's death sound doesn't get an attenuation 1 ATTN_NORM the normal attenuation 2 ATTN_IDLE idle monsters get this attenuation 3 ATTN_STATIC spawnstaticsound messages get this attenuation
long channel;is the sound channel. There are 8 possible sound channels in Quake but the game uses 5 only. Possible values are:
value QuakeC purpose 0 CHAN_AUTO big powerups 1 CHAN_WEAPON weapon use sounds 2 CHAN_VOICE pain calls 3 CHAN_ITEM item get sounds 4 CHAN_BODY jump and fall sounds
long entity;is the entity which caused the sound.
long soundnum;is the sound number in the sound-table.
ve3_t origin;is the origin of the sound.
long entity_channel; // combined variable
mask = ReadByte;
vol = mask & 0x01 ? (float) ReadByte / 255.0 : 1.0;
attenuation = mask & 0x02 ? (float) ReadByte / 64.0 : 1.0;
entity_channel = ReadShort;
channel = entity_channel & 0x07;
entity = (entity_channel >> 3) & 0x1FFF;
soundnum = ReadByte;
for (i=0 ; i<3 ; i++) origin[i] = ReadCoord;
ID0x07
This is the time stamp of a block of messages. A time message should appear in every block.
float time;is the time in seconds from the beginning of the current level (not of the recording).
time = ReadFloat;
ID0x08
The client prints the text in the top left corner of the screen. The text appears on the console as well.
char* text;is the text to be displayed. The text contains something like ``You get 5 shells''. There are special non-printable characters in the text: ``\n'' means new line and ``\002'' changes the color of the following text. The value 2 may be a color number but I'm not sure about this.
text = ReadString;
ID0x09
The client transfers the text to the console and runs it.
char* text;is the command, which the client has to execute. These are commands like ``bf\n'' to make a flash after you take something.
text = ReadString;
ID0x0A
This message set the camera orientation.
vec3_t angles;is the new camera orientation.
for (i=0 ; i<3 ; i++) angles[i] = ReadAngle;
ID0x0B
This message is usually one of the first messages after a level start. It loads model and sound files.
long serverversion;is the version of the server.
It should be the same as the version of the client. Up to now this version was
always 0x0F.
long maxclients;is the maximum number of clients in this
recording. It is 1 in single player recordings or the number after the
-listen command line parameter.
long multi;is 0 in single player recordings and 1 in multi player recordings. It actually toggles the ranking screen at the end of a level.
char* mapname;is the name of the level.
char* precache_models[256];is the model-table. It will be filled up with model names. Many other messages contain an index in this array. The first used index is 1.
long nummodels;is the number of models in the model-table.
char* precache_sounds[256];is the sound-table. It will be filled up with sound names. Many other messages contain an index in this array. The first used index is 1.
long numsounds;is the number of sounds in the sound-table.
serverversion = ReadLong;
if (serverversion != 0x0F) {
error("Server returned version %i, not %i", serverversion, 0x0F);
}
maxclients = ReadByte;
multi = ReadByte;
mapname = ReadString;
nummodels = 0;
do {
if (++nummodels > 255) error("Server sent too many model_precache");
precache_models[nummodels] = ReadString;
} while (*precache_models[nummodels]);
numsounds = 0;
do {
if (++numsounds > 255) error("Server sent too many sound_precache");
precache_sounds[numsounds] = ReadString;
} while (*precache_sounds[numsounds]);
ID0x0C
This message defines a light style.
long style;is the light style number.
char* string;is a string of letters ``a'' .. ``z'', where ``a'' means black and ``z'' white. All known effects from nervous flashing: ``az'' to slow dimming: ``zyxwvu ... edcba'' can so be described.
style = ReadByte;
string = ReadString;
ID0x0D
This message sets the player name.
variables
long player;is the internal player number (client 1 is player number 0).
char* netname;is the new player name.
player = ReadByte;
netname = ReadString;
ID0x0E
This message updates the frag count of a specific player.
long player;is the internal player number (client 1 is player number 0).
long frags;is the new frag count for this player.
player = ReadByte;
frags = ReadShort;
ID0x0F
This message updates the status line and the camera coordinates.
long mask;is a bitmask to show which values are coming.
float view_ofs_z;is an additional view offset because the camera is at the origin of the entitiy and not at the eyes (is -8 if the player is death).
float ang_ofs_1;is an additional offset of the first angle.
vec3_t angles;indicates the camera direction change.
vec3_t vel;indicates the camera velocity.
long items;contains a bit mask for the inventory:
| bit | value | QuakeC | purpose |
| 0 | 0x00000001 | IT_SHOTGUN | Shotgun (should be always 1) |
| 1 | 0x00000002 | IT_SUPER_SHOTGUN | Double-barrelled Shotgun |
| 2 | 0x00000004 | IT_NAILGUN | Nailgun |
| 3 | 0x00000008 | IT_SUPER_NAILGUN | Supernailgun |
| 4 | 0x00000010 | IT_GRENADE_LAUNCHER | Grenade Launcher |
| 5 | 0x00000020 | IT_ROCKET_LAUNCHER | Rocket Launcher |
| 6 | 0x00000040 | IT_LIGHTNING | Thunderbolt |
| 7 | 0x00000080 | IT_EXTRA_WEAPON | extra weapon (there is no extra weapon) |
| 8 | 0x00000100 | IT_SHELLS | Shells are active |
| 9 | 0x00000200 | IT_NAILS | Flechettes are active |
| 10 | 0x00000400 | IT_ROCKETS | Grenades are active |
| 11 | 0x00000800 | IT_CELLS | Cells are active |
| 12 | 0x00001000 | IT_AXE | Axe (should be always 1) |
| 13 | 0x00002000 | IT_ARMOR1 | green Armor |
| 14 | 0x00004000 | IT_ARMOR2 | yellow Armor |
| 15 | 0x00008000 | IT_ARMOR3 | red Armor |
| 16 | 0x00010000 | IT_SUPERHEALTH | Megahealth |
| 17 | 0x00020000 | IT_KEY1 | silver (keycard or runekey or key) |
| 18 | 0x00040000 | IT_KEY2 | gold (keycard or runekey or key) |
| 19 | 0x00080000 | IT_INVISIBILITY | Ring of Shadows |
| 20 | 0x00100000 | IT_INVULNERABILITY | Pentagram of Protection |
| 21 | 0x00200000 | IT_SUIT | Biosuit |
| 22 | 0x00400000 | IT_QUAD | Quad Damage |
| 23 | 0x00800000 | unknown | unknown (is 0) |
| 24 | 0x01000000 | unknown | unknown (is 0) |
| 25 | 0x02000000 | unknown | unknown (is 0) |
| 26 | 0x04000000 | unknown | unknown (is 0) |
| 27 | 0x08000000 | unknown | unknown (is 0) |
| 28 | 0x10000000 | unknown | Rune 1 |
| 29 | 0x20000000 | unknown | Rune 2 |
| 30 | 0x40000000 | unknwon | Rune 3 |
| 31 | 0x80000000 | unknown | Rune 4 |
items in the parse routine:
0x4001. It looks like a programmer's mistake because this means
Shotgun any yellow Armor. It should be 0x1001: Shotgun and Axe.
long weaponframe;is the frame of the weapon model.
long armorvalue;is the current armor.
long weaponmodel;is the model number of the weapon in the model-table.
long health;is the current health.
long currentammo;is the current number of the current ammunition.
long ammo_shells;is the current number of shells.
long ammo_nails;is the current number of nails.
long ammo_rockets;is the current number of rockets.
long ammo_cells;is the current number of cells.
long weapon;contains a bit mask for the current weapon:
bit value QuakeC weapon ? 0x00not available Axe 0 0x01IT_SHOTGUN Shotgun 1 0x02IT_SUPER_SHOTGUN Double-barrelled Shotgun 2 0x04IT_NAILGUN Nailgun 3 0x08IT_SUPER_NAILGUN Supernailgun 4 0x10IT_GRENADE_LAUNCHER Grenade Launcher 5 0x20IT_ROCKET_LAUNCHER Rocket Launcher 6 0x40IT_LIGHTNING Thunderbolt 7 0x80IT_EXTRA_WEAPON extra weapon (there is no extra weapon)
long uk_bit_b10, uk_bit_b11; // unknown (unused ??)
mask = ReadShort;
view_ofs_z = mask & 0x0001 ? (float) ReadChar : 22.0;
ang_ofs_1 = mask & 0x0002 ? (float) ReadChar : 0.0;
angles[0] = mask & 0x0004 ? (vec_t) ReadChar : 0.0;
vel[0] = mask & 0x0020 ? (vec_t) ReadChar : 0.0;
angles[1] = mask & 0x0008 ? (vec_t) ReadChar : 0.0;
vel[1] = mask & 0x0040 ? (vec_t) ReadChar : 0.0;
angles[2] = mask & 0x0010 ? (vec_t) ReadChar : 0.0;
vel[2] = mask & 0x0080 ? (vec_t) ReadChar : 0.0;
items = mask & 0x0200 ? ReadLong : 0x4001;
uk_bit_b10 = mask & 0x0400 ? 1 : 0; // bit 10
uk_bit_b11 = mask & 0x0800 ? 1 : 0; // bit 11
weaponframe = mask & 0x1000 ? ReadByte : 0;
armorvalue = mask & 0x2000 ? ReadByte : 0;
weaponmodel = mask & 0x4000 ? ReadByte : 0;
health = ReadShort;
currentammo = ReadByte;
ammo_shells = ReadByte;
ammo_nails = ReadByte;
ammo_rockets = ReadByte;
ammo_cells = ReadByte;
weapon = ReadByte;
ID0x10
Stops a sound. I never found such a message in a DEM file.
long uk_short; // unknown (an index??)
uk_short = ReadShort;
ID0x11
Updates the colors of the specified player.
long player;is the internal player number (client 1 is player 0).
long colors;is the combined color of this player.
long shirtcolor;is the color of the shirt
(0 <= shirtcolor <= 3).
long pantscolor;is the color of the pants
(0 <= pantscolor <= 3).
player = ReadByte;
colors = ReadByte;
shirtcolor = (colors>>4) & 0x0F;
pantscolor = colors & 0x0F;
ID0x12
This starts particles flying around. This happens, if a barrel explodes or blood particles fly after being hit by an axe, shells or nails.
vec3_t origin;is the origin of the particles.
vec3_t vel;is the velocity of the particles.
long color;is the color of the particles (blood is 73).
long count;is the number of the particles
for (i=0 ; i<3 ; i++) origin[i] = ReadCoord;
for (i=0 ; i<3 ; i++) vel[i] = (vec_t) ReadChar * 0.0625;
color = ReadByte;
count = ReadByte;
ID0x13
Tells how severe was a hit and from which points it came.
long save;will be subtracted from the current armor.
long take;will be subtracted from the current health.
vec3_t origin;is the origin of the hit. It points to the weapon of a monster or player (not the origin of the monster entity) or it is (0,0,0) if the damage was caused by drowning or burning.
save = ReadByte;
take = ReadByte;
for (i=0 ; i<3 ; i++) origin[i] = ReadCoord;
ID0x14
This message creates a static entity and sets the internal default values.
long StaticEntityCount;is the number of already started static entities. The maximum number is 127.
long default_modelindex;is the model number in the model-table.
long default_frame;is the frame number of the model.
long default_colormap;is the colormap number to display the model.
long default_skin;is the skin number of the model. This is used for things with different skins (like players or armors).
vec3_t default_origin;is the origin of the entity.
vec3_t default_angles;is the orientation of the entity.
if (StaticEntityCount > 127) error("Too many static entities");
StaticEntityCount++;
default_modelindex = ReadByte;
default_frame = ReadByte;
default_colormap = ReadByte;
default_skin = ReadByte;
for (i=0 ; i<3 ; i++) {
default_origin[i] = ReadCoord;
default_angles[i] = ReadAngle;
}
ID0x15
This is OBSOLETE. It should never occur in DEM files.
error ("CL_ParseServerMessage: Illegible server message\n");
ID0x16
This message creates a dynamic entity and sets the internal default values.
long entity;is the number of the entity.
long default_modelindex;is the model number in the model-table.
long default_frame;is the frame number of the model.
long default_colormap;is the colormap number to display the model.
long default_skin;is the skin number of the model. This is used for things with different skins (like players or armors).
vec3_t default_origin;is the origin of the entity.
vec3_t default_angles;is the orientation of the entity.
entity = ReadShort;
if (entity > 449) error("CL_EntityNum: %i is an invalid number", entity);
default_modelindex = ReadByte;
default_frame = ReadByte;
default_colormap = ReadByte;
default_skin = ReadByte;
for (i=0 ; i<3 ; i++) {
default_origin[i] = ReadCoord;
default_angles[i] = ReadAngle;
}
ID0x17
This message creates a temporary entity.
long entitytype;is the type of the temporary entity. There are two kinds of temporary entities:
is a small point like entity.
| value | QuakeC | purpose |
| 0 | TE_SPIKE | unknown |
| 1 | TE_SUPERSPIKE | superspike hits (spike traps) |
| 2 | TE_GUNSHOT | hit on the wall (Axe, Shotgun) |
| 3 | TE_EXPLOSION | grenade/missile explosion |
| 4 | TE_TAREXPLOSION | explosion of a tarbaby |
| 7 | TE_WIZSPIKE | wizard's hit |
| 8 | TE_KNIGHTSPIKE | hell knight's shot hit |
| 10 | TE_LAVASPLASH | Chthon awakes and falls dead |
| 11 | TE_TELEPORT | teleport end |
is a 2 dimensional entity.
value QuakeC purpose 5 TE_LIGHTNING1 flash of the Shambler 6 TE_LIGHTNING2 flash of the Thunderbolt 9 TE_LIGHTNING3 flash in e1m7 to kill Chthon
long entity;is the entity which created the temporary entity.
vec3_t origin;is the origin of the entity.
vec3_t trace_endpos;is the destination of the large temporary entity.
entitytype = ReadByte;
if (entitytype > 11)
error("CL_ParserTEnt: bad type");
switch (entitytype) {
case 0,1,2,3,4,7,8,10,11:
for (i=0 ; i<3 ; i++) org[i] = ReadCoord;
break;
case 5,6,9:
entity = ReadEntity;
for (i=0 ; i<3 ; i++) origin[i] = ReadCoord;
for (i=0 ; i<3 ; i++) trace_endpos[i] = ReadCoord;
break;
}
ID0x18
Set the pause state. The time stands still but all entities get their update messages.
long pausestate;is 1 to start the pause and 0 to stop it.
pausestate = ReadByte;
if (pausestate) {
// pause is on
}
else {
// pause is off
}
ID0x19
This message selects the client state.
is the client state. The possible values are:
value purpose 1 after model/sound precache, start spawning entities (``prespawn'') 2 start initializing light effects 3 start 3D rendering
signon = ReadByte;
ID0x1A
Prints the specified text at the center of the screen.
char* text;is the text to be displayed.
text = ReadString;
ID0x1B
This message indicates the death of a monster.
long killed_monsters;is the number of killed monsters.
It may be displayed with the console command showscores.
killed_mosters++;
ID0x1C
This message receives a client, if the player enters a secret area.
It comes usually with a print message.
long found_secrets;is the number of found secrets. It may
be displayed with the console command showscores.
found_secrets++;
ID0x1D
This message starts a static (ambient) sound not connected to an entity but to a position.
vec3_t origin;is the origin of the sound.
long soundnum;is the sound number in the sound-table.
float vol;is the volume (0.0 off, 1.0 max)
float attenuation;is the attenuation of the sound. Possible values (for all kind of sounds) are:
value QuakeC purpose 0 ATTN_NONE i. e. player's death sound doesn't get an attenuation 1 ATTN_NORM the normal attenuation 2 ATTN_IDLE idle monsters get this attenuation 3 ATTN_STATIC all spawnstaticsound messages get thisattenuation
for (i=0 ; i<3 ; i++) origin[i] = ReadCoord;
soundnum = ReadByte;
vol = (float) ReadByte / 255.0;
attenuation = (float) ReadByte / 64.0;
ID0x1E
Displays the level end screen. Depending on the multi command in
the serverinfo message this is either the single player summary screen or the
multi player ranking screen.
none
ID0x1F
Displays the episode end screen and some text.
char* text;is the episode end text.
text = ReadString;
ID0x20
This message selects the audio CD track numbers.
long fromtrack;is the start track.
long totrack;is the last track. Both values are equal at the start of a game but become 2 and 3 at the end of an episode.
fromtrack = ReadByte;
totrack = ReadByte;
ID0x21
Displays the help and sell screen.
none
ID>=0x80
This is the general entity update message. For every entity (potentially) in sight the server sends such a message. The message contains only the values, which changed since the creation (or spawning) of the entity (with spawnstatic, spawnbaseline).
long mask;is a bit mask to reduce the amount of data to be sent. Only the changed parts get their bit and their values.
long entity;is the entity number.
long modelindex;is the model number in the model-table.
long frame;is the frame number of the model.
long colormap;is the colormap number to display the model.
long skin;is the skin number of the model. This is used for things with different skins (like players or armors).
long attack_state;shows how the entity attacks. I'm not really sure about the explanation because I found only the values 0 and 2 in DEM files. The possible values are:
value QuakeC purpose 0 none don't attack 1 AS_STRAIGHT straight shot 2 AS_SLIDING move to a side 3 AS_MELEE single combat (dog, ogre) 4 AS_MISSILE shooting attack
vec3_t origin;is the origin of the entity.
vec3_t angles;is the orientation of the entity.
long new;is 1 if the entity gets some really new values (modelindex etc.)
mask = ID & 0x07F;
if (mask & 0x0001) mask |= (ReadByte) << 8;
entity = mask & 0x4000 ? ReadShort : ReadByte;
modelindex = mask & 0x0400 ? ReadByte : default_modelindex;
frame = mask & 0x0040 ? ReadByte : default_frame;
colormap = mask & 0x0800 ? ReadByte : default_colormap;
skin = mask & 0x1000 ? ReadByte : default_skin;
attack_state = mask & 0x2000 ? ReadByte : default_attack_state;
origin[0] = mask & 0x0002 ? ReadCoord : default_origin[0];
angles[0] = mask & 0x0100 ? ReadAngle : default_angles[0];
origin[1] = mask & 0x0004 ? ReadCoord : default_origin[1];
angles[1] = mask & 0x0010 ? ReadAngle : default_angles[1];
origin[2] = mask & 0x0008 ? ReadCoord : default_origin[2];
angles[2] = mask & 0x0200 ? ReadAngle : default_angles[2];
new = mask & 0x0020 ? 1 : 0;