/* Relay -- a tool to record and play Quake2 demos Copyright (C) 2000 Conor Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Conor Davis cedavis@planetquake.com */ #ifndef __DM2_H #define __DM2_H #include #include "block.h" #include "bsp.h" // for MAX_MAP_AREAS #include "pak.h" #include "q2defines.h" #include "shared.h" #define RECORD_NETWORK 0 #define RECORD_CLIENT 1 #define RECORD_SERVER 2 // these are readable only by q2relay #define RECORD_RELAY 0x80 // number of previous states to store for delta referencing #define UPDATE_BACKUP 16 #define UPDATE_MASK (UPDATE_BACKUP-1) #define BASELINES_FRAME 0xffffffff // server-to-client commands #define SVC_BAD 0x00 #define SVC_MUZZLEFLASH 0x01 #define SVC_MUZZLEFLASH2 0x02 #define SVC_TEMP_ENTITY 0x03 #define SVC_LAYOUT 0x04 #define SVC_INVENTORY 0x05 #define SVC_NOP 0x06 #define SVC_DISCONNECT 0x07 #define SVC_RECONNECT 0x08 #define SVC_SOUND 0x09 #define SVC_PRINT 0x0a #define SVC_STUFFTEXT 0x0b #define SVC_SERVERDATA 0x0c #define SVC_CONFIGSTRING 0x0d #define SVC_SPAWNBASELINE 0x0e #define SVC_CENTERPRINT 0x0f #define SVC_DOWNLOAD 0x10 #define SVC_PLAYERINFO 0x11 #define SVC_PACKETENTITIES 0x12 #define SVC_DELTAPACKETENTITIES 0x13 #define SVC_FRAME 0x14 // by default, messages are multicast // if the id byte contains this bit, the message // is unicast #define MSG_UNICAST 0x80 // most of these bits are from a serverrecord sample sent to Tom Vykruta // http://www.stomped.com/demented2/dm2specs.htm // client-to-server commands #define CLC_BAD 0x00 #define CLC_NOP 0x01 #define CLC_MOVE 0x02 #define CLC_USERINFO 0x03 #define CLC_STRINGCMD 0x04 // player_state_t mask bits #define PS_M_TYPE (1<<0) #define PS_M_ORIGIN (1<<1) #define PS_M_VELOCITY (1<<2) #define PS_M_TIME (1<<3) #define PS_M_FLAGS (1<<4) #define PS_M_GRAVITY (1<<5) #define PS_M_DELTA_ANGLES (1<<6) #define PS_VIEWOFFSET (1<<7) #define PS_VIEWANGLES (1<<8) #define PS_KICKANGLES (1<<9) #define PS_BLEND (1<<10) #define PS_FOV (1<<11) #define PS_WEAPONINDEX (1<<12) #define PS_WEAPONFRAME (1<<13) #define PS_RDFLAGS (1<<14) // usercmd_t mask bits // ms and light are allways sent, the others are optional #define CM_ANGLE1 (1<<0) #define CM_ANGLE2 (1<<1) #define CM_ANGLE3 (1<<2) #define CM_FORWARD (1<<3) #define CM_SIDE (1<<4) #define CM_UP (1<<5) #define CM_BUTTONS (1<<6) #define CM_IMPULSE (1<<7) // sound mask bits // a sound without an ent or pos will be a local only sound #define SND_VOLUME (1<<0) // a byte #define SND_ATTENUATION (1<<1) // a byte #define SND_POS (1<<2) // three coordinates #define SND_ENT (1<<3) // a short 0-2: channel, 3-12: entity #define SND_OFFSET (1<<4) // a byte, msec offset from frame start // sound defaults #define DEFAULT_SOUND_PACKET_VOLUME 1.0F #define DEFAULT_SOUND_PACKET_ATTENUATION 1.0F // entity_state_t mask bits // try to pack the common update flags into the first byte #define U_ORIGIN1 (1<<0) #define U_ORIGIN2 (1<<1) #define U_ANGLE2 (1<<2) #define U_ANGLE3 (1<<3) #define U_FRAME8 (1<<4) // frame is a byte #define U_EVENT (1<<5) #define U_REMOVE (1<<6) // REMOVE this entity, don't add it #define U_MOREBITS1 (1<<7) // read one additional byte // second byte #define U_NUMBER16 (1<<8) // NUMBER8 is implicit if not set #define U_ORIGIN3 (1<<9) #define U_ANGLE1 (1<<10) #define U_MODEL (1<<11) #define U_RENDERFX8 (1<<12) // fullbright, etc #define U_EFFECTS8 (1<<14) // autorotate, trails, etc #define U_MOREBITS2 (1<<15) // read one additional byte // third byte #define U_SKIN8 (1<<16) #define U_FRAME16 (1<<17) // frame is a short #define U_RENDERFX16 (1<<18) // 8 + 16 = 32 #define U_EFFECTS16 (1<<19) // 8 + 16 = 32 #define U_MODEL2 (1<<20) // weapons, flags, etc #define U_MODEL3 (1<<21) #define U_MODEL4 (1<<22) #define U_MOREBITS3 (1<<23) // read one additional byte // fourth byte #define U_OLDORIGIN (1<<24) // FIXME: get rid of this #define U_SKIN16 (1<<25) #define U_SOUND (1<<26) #define U_SOLID (1<<27) // dm2 message types typedef struct { short entity; byte value; } muzzleflash_t; typedef struct { byte type; vec3_t origin; vec3_t movedir; vec3_t endpos; vec3_t pos1; vec3_t pos2; vec3_t pos3; vec3_t pos4; short entity; short dest_entity; short count; short style; short plat2flags; short nextid; long wait; } temp_entity_t; typedef struct { byte soundnum; float volume; float attenuation; float timeofs; short entity; byte channel; vec3_t origin; qboolean positioned; } sound_t; typedef struct { byte level; char string[MAX_MSGLEN]; } print_t; typedef struct { long version; short relayversion; long key; byte isdemo; char game[MAX_QPATH]; short player; char mapname[MAX_QPATH]; } serverdata_t; typedef struct { short index; char string[MAX_MSGLEN]; } configstring_t; typedef struct { size_t seq1; size_t seq2; byte area_count; char areas[MAX_MAP_AREAS/8]; byte connected_count; char connected[MAX_CLIENTS/8]; } frame_t; // new, q2relay-specific message types typedef struct { int maxclients; } relayinfo_t; typedef struct { long frame; block_t block; char block_buffer[MAX_MSGLEN]; } delta_t; typedef struct { size_t frame; entity_state_t entities[MAX_EDICTS]; byte active[MAX_EDICTS/8]; byte areas[MAX_MAP_AREAPORTALS/8]; // visible areas in client demos, open areaportals in relay demos // relay-specific data byte connected[MAX_CLIENTS/8]; } state_t; typedef struct { char layout[MAX_MSGLEN]; short inventory[MAX_ITEMS]; player_state_t ps[UPDATE_BACKUP]; } player_t; typedef struct { serverdata_t svd; char configstrings[MAX_CONFIGSTRINGS][64]; state_t baselines; state_t states[UPDATE_BACKUP]; player_t *players; // client demos will have one player, relay will have maxclients int maxclients; // determines size of players array. must be 1 for client demos! size_t current_frame; size_t delta_frame; } dm2_t; extern void DM2_Init(dm2_t *dm2); extern void DM2_FillConfigstrings(char (*configstrings)[64]); extern int DM2_ReadBlock(block_t *block, PFILE *fd); extern int DM2_WriteBlock(block_t *block, PFILE *fd); extern int DM2_ReadGenericString(block_t *block, char *p, size_t len); extern int DM2_WriteGenericString(block_t *block, const char *p); #define DM2_ReadLayout(a,b,c) DM2_ReadGenericString(a,b,c) #define DM2_WriteLayout(a,b) DM2_WriteGenericString(a,b) #define DM2_ReadStufftext(a,b,c) DM2_ReadGenericString(a,b,c) #define DM2_WriteStufftext(a,b) DM2_WriteGenericString(a,b) #define DM2_ReadCenterprint(a,b,c) DM2_ReadGenericString(a,b,c) #define DM2_WriteCenterprint(a,b) DM2_WriteGenericString(a,b) extern int DM2_ReadMuzzleflash(block_t *block, int *entity, int *value); extern int DM2_WriteMuzzleflash(block_t *block, int entity, int value); extern int DM2_ReadTempEntity(block_t *block, const dm2_t *dm2, temp_entity_t *p); extern int DM2_WriteTempEntity(block_t *block, const dm2_t *dm2, const temp_entity_t *p); extern int DM2_ReadInventory(block_t *block, short p[MAX_ITEMS]); extern int DM2_WriteInventory(block_t *block, const short p[MAX_ITEMS]); extern int DM2_ReadSound(block_t *block, int *soundindex, float *volume, float *attenuation, float *timeofs, int *entity, int *channel, vec3_t origin, qboolean *positioned); extern int DM2_WriteSound(block_t *block, int soundindex, float volume, float attenuation, float timeofs, int entity, int channel, vec3_t origin, qboolean positioned); extern int DM2_ReadPrint(block_t *block, int *level, char *string, size_t len); extern int DM2_WritePrint(block_t *block, int level, const char *string); extern int DM2_ReadServerdata(block_t *block, serverdata_t *p); extern int DM2_WriteServerdata(block_t *block, const serverdata_t *p); extern int DM2_ReadConfigstring(block_t *block, int *index, char *string); extern int DM2_WriteConfigstring(block_t *block, int index, const char *string); extern int DM2_ReadFrame(block_t *block, const serverdata_t *svd, int *seq1, int *seq2, int *area_count, byte *areas, int *connected_count, byte *connected); extern int DM2_WriteFrame(block_t *block, const serverdata_t *svd, int seq1, int seq2, int area_count, const byte *areas, int connected_count, const byte *connected); extern int DM2_ReadPS(block_t *block, player_state_t *ps); extern int DM2_WritePS(block_t *block, const player_state_t *to, const player_state_t *from); extern int DM2_ReadEntityMask(block_t *block, int *mask); extern qboolean DM2_ReadEntity(block_t *block, entity_state_t *es, int mask); extern int DM2_ReadPacketEntity(block_t *block, state_t *state, const state_t *baselines); extern int DM2_ReadBaselineEntity(block_t *block, state_t *baselines); extern int DM2_WriteEntity(block_t *block, const entity_state_t *to, const entity_state_t *from, qboolean is_active, qboolean was_active); extern int DM2_WritePacketEntities(block_t *block, const state_t *current, const state_t *delta, const state_t *baselines); extern int DM2_WriteConfigstrings(block_t *block, const char (*configstrings)[64], int start, size_t stopsize); extern int DM2_WriteBaselines(block_t *block, const state_t *baselines, int start, size_t stopsize); extern int DM2_ReadPreFrame(serverdata_t *svd, relayinfo_t *relayinfo, char (*configstrings)[64], state_t *baselines, PFILE *fd); extern int DM2_WritePreFrame(const serverdata_t *svd, const relayinfo_t *relayinfo, const char (*configstrings)[64], const state_t *baselines, PFILE *fd); #endif // __DM2_H