X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=protocol.h;h=3f9e77c612c5a3edd53a303fa15ef1980984aa91;hb=d7981e977a7ce6f1310880fb4bbb42b722a59888;hp=f07830f9cf661356f950cd53dc0251fc75ca9a3e;hpb=eb3d71b9feaefca24fe80b9970eb11d07fd295b5;p=xonotic%2Fdarkplaces.git diff --git a/protocol.h b/protocol.h index f07830f9..3f9e77c6 100644 --- a/protocol.h +++ b/protocol.h @@ -19,9 +19,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // protocol.h -- communications protocols -#define PROTOCOL_VERSION 15 -#define DPPROTOCOL_VERSION1 96 -#define DPPROTOCOL_VERSION2 97 +#ifndef PROTOCOL_H +#define PROTOCOL_H + +#define PROTOCOL_QUAKE 15 +#define PROTOCOL_NEHAHRAMOVIE 250 +#define PROTOCOL_DARKPLACES1 96 +#define PROTOCOL_DARKPLACES2 97 +// LordHavoc: I think the 96-99 range was going to run out too soon... +// so here I jump to 3500 +#define PROTOCOL_DARKPLACES3 3500 +#define PROTOCOL_DARKPLACES4 3501 +#define PROTOCOL_DARKPLACES5 3502 // model effects #define EF_ROCKET 1 // leave a trail @@ -41,14 +50,22 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define EF_ADDITIVE 32 #define EF_BLUE 64 #define EF_RED 128 -#define EF_DELTA 8388608 // LordHavoc: entity is delta compressed to save network bandwidth +#define EF_DELTA 8388608 // LordHavoc: (obsolete) entity is delta compressed to save network bandwidth (no longer used) +#define EF_LOWPRECISION 4194304 // LordHavoc: entity is low precision (integer coordinates) to save network bandwidth // effects/model (can be used as model flags or entity effects) -#define EF_REFLECTIVE 256 // LordHavoc: shiny metal objects :) +#define EF_REFLECTIVE 256 // LordHavoc: shiny metal objects :) (not currently supported) #define EF_FULLBRIGHT 512 // LordHavoc: fullbright #define EF_FLAME 1024 // LordHavoc: on fire +#define EF_STARDUST 2048 // LordHavoc: showering sparks +#define EF_NOSHADOW 4096 // LordHavoc: does not cast a shadow #define EF_STEP 0x80000000 // internal client use only - present on MOVETYPE_STEP entities, not QC accessible (too many bits) +// flags for the pflags field of entities +#define PFLAGS_NOSHADOW 1 +#define PFLAGS_CORONA 2 +#define PFLAGS_FULLDYNAMIC 128 // must be set or the light fields are ignored + // if the high bit of the servercmd is set, the low bits are fast update flags: #define U_MOREBITS (1<<0) #define U_ORIGIN1 (1<<1) @@ -76,7 +93,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define U_ALPHA (1<<17) // 1 byte, 0.0-1.0 maps to 0-255, not sent if exactly 1, and the entity is not sent if <=0 unless it has effects (model effects are checked as well) #define U_SCALE (1<<18) // 1 byte, scale / 16 positive, not sent if 1.0 #define U_EFFECTS2 (1<<19) // 1 byte, this is .effects & 0xFF00 (second byte) -#define U_GLOWSIZE (1<<20) // 1 byte, encoding is float/8.0, signed (negative is darklight), not sent if 0 +#define U_GLOWSIZE (1<<20) // 1 byte, encoding is float/4.0, unsigned, not sent if 0 #define U_GLOWCOLOR (1<<21) // 1 byte, palette index, default is 254 (white), this IS used for darklight (allowing colored darklight), however the particles from a darklight are always black, not sent if default value (even if glowsize or glowtrail is set) // LordHavoc: colormod feature has been removed, because no one used it #define U_COLORMOD (1<<22) // 1 byte, 3 bit red, 3 bit green, 2 bit blue, this lets you tint an object artifically, so you could make a red rocket, or a blue fiend... @@ -111,7 +128,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define SU_PUNCHVEC1 (1<<16) #define SU_PUNCHVEC2 (1<<17) #define SU_PUNCHVEC3 (1<<18) -#define SU_UNUSED19 (1<<19) +#define SU_VIEWZOOM (1<<19) // byte factor (0 = 0.0 (not valid), 255 = 1.0) #define SU_UNUSED20 (1<<20) #define SU_UNUSED21 (1<<21) #define SU_UNUSED22 (1<<22) @@ -130,6 +147,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define SND_VOLUME (1<<0) // a byte #define SND_ATTENUATION (1<<1) // a byte #define SND_LOOPING (1<<2) // a long +#define SND_LARGEENTITY (1<<3) // a short and a byte (instead of a short) +#define SND_LARGESOUND (1<<4) // a short (instead of a byte) // defaults for clientinfo messages @@ -205,7 +224,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // LordHavoc: my svc_ range, 50-59 #define svc_cgame 50 // [short] length [bytes] data -#define svc_fog 51 // unfinished and obsolete +#define svc_unusedlh1 51 #define svc_effect 52 // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate #define svc_effect2 53 // [vector] org [short] modelindex [short] startframe [byte] framecount [byte] framerate #define svc_sound2 54 // short soundindex instead of byte @@ -255,7 +274,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // PGM 01/21/97 #define TE_BEAM 13 // [entity] entity [vector] start [vector] end -// PGM 01/21/97 +// PGM 01/21/97 // Nehahra effects used in the movie (TE_EXPLOSION3 also got written up in a QSG tutorial, hence it's not marked NEH) #define TE_EXPLOSION3 16 // [vector] origin [coord] red [coord] green [coord] blue @@ -274,38 +293,119 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define TE_SUPERSPIKEQUAD 59 // [vector] origin // LordHavoc: block2 - 70-80 #define TE_EXPLOSIONQUAD 70 // [vector] origin -#define TE_BLOOD2 71 // [vector] origin +#define TE_UNUSED1 71 // unused #define TE_SMALLFLASH 72 // [vector] origin #define TE_CUSTOMFLASH 73 // [vector] origin [byte] radius / 8 - 1 [byte] lifetime / 256 - 1 [byte] red [byte] green [byte] blue #define TE_FLAMEJET 74 // [vector] origin [vector] velocity [byte] count #define TE_PLASMABURN 75 // [vector] origin +// LordHavoc: Tei grabbed these codes +#define TE_TEI_G3 76 // [vector] start [vector] end [vector] angles +#define TE_TEI_SMOKE 77 // [vector] origin [vector] dir [byte] count +#define TE_TEI_BIGEXPLOSION 78 // [vector] origin +#define TE_TEI_PLASMAHIT 79 // [vector} origin [vector] dir [byte] count + // these are bits for the 'flags' field of the entity_state_t #define RENDER_STEP 1 #define RENDER_GLOWTRAIL 2 #define RENDER_VIEWMODEL 4 #define RENDER_EXTERIORMODEL 8 +#define RENDER_LOWPRECISION 16 // send as low precision coordinates to save bandwidth +#define RENDER_COLORMAPPED 32 +#define RENDER_SHADOW 64 // cast shadow +#define RENDER_LIGHT 128 // receive light +// this is 80 bytes typedef struct { - double time; // time this state was built - vec3_t origin; - vec3_t angles; - int number; // entity number this state is for - unsigned short active; // true if a valid state - unsigned short modelindex; - unsigned short frame; - unsigned short effects; - byte colormap; - byte skin; - byte alpha; - byte scale; - byte glowsize; - byte glowcolor; - byte flags; + // ! means this is sent to client + double time; // time this state was built (used on client for interpolation) + float origin[3]; // ! + float angles[3]; // ! + int number; // ! entity number this state is for + int effects; // ! + unsigned short modelindex; // ! + unsigned short frame; // ! + unsigned short tagentity; // ! + unsigned short specialvisibilityradius; // larger if it has effects/light + unsigned short viewmodelforclient; + unsigned short exteriormodelforclient; // not shown if first person viewing from this entity, shown in all other cases + unsigned short nodrawtoclient; + unsigned short drawonlytoclient; + unsigned short light[4]; // ! color*256 (0.00 to 255.996), and radius*1 + unsigned char active; // ! true if a valid state + unsigned char lightstyle; // ! + unsigned char lightpflags; // ! + unsigned char colormap; // ! + unsigned char skin; // ! also chooses cubemap for rtlights if lightpflags & LIGHTPFLAGS_FULLDYNAMIC + unsigned char alpha; // ! + unsigned char scale; // ! + unsigned char glowsize; // ! + unsigned char glowcolor; // ! + unsigned char flags; // ! + unsigned char tagindex; // ! + // padding to a multiple of 8 bytes (to align the double time) + unsigned char unused[5]; } entity_state_t; +/* +PROTOCOL_DARKPLACES3 +server updates entities according to some (unmentioned) scheme. + +a frame consists of all visible entities, some of which are up to date, +often some are not up to date. + +these entities are stored in a range (firstentity/endentity) of structs in the +entitydata[] buffer. + +to make a commit the server performs these steps: +1. duplicate oldest frame in database (this is the baseline) as new frame, and + write frame numbers (oldest frame's number, new frame's number) and eye + location to network packet (eye location is obsolete and will be removed in + future revisions) +2. write an entity change to packet and modify new frame accordingly + (this repeats until packet is sufficiently full or new frame is complete) +3. write terminator (0xFFFF) to network packet + (FIXME: this terminator value conflicts with MAX_EDICTS 32768...) + +to read a commit the client performs these steps: +1. reads frame numbers from packet and duplicates baseline frame as new frame, + also reads eye location but does nothing with it (obsolete). +2. delete frames older than the baseline which was used +3. read entity changes from packet until terminator (0xFFFF) is encountered, + each change is applied to entity frame. +4. sends ack framenumber to server as part of input packet + +if server receives ack message in put packet it performs these steps: +1. remove all older frames from database. +*/ + +/* +PROTOCOL_DARKPLACES4 +a frame consists of some visible entities in a range (this is stored as start and end, note that end may be less than start if it wrapped). + +these entities are stored in a range (firstentity/endentity) of structs in the entitydata[] buffer. + +to make a commit the server performs these steps: +1. build an entity_frame_t using appropriate functions, containing (some of) the visible entities, this is passed to the Write function to send it. + +This documention is unfinished! +the Write function performs these steps: +1. check if entity frame is larger than MAX_ENTITYFRAME or is larger than available space in database, if so the baseline is defaults, otherwise it is the current baseline of the database. +2. write differences of an entity compared to selected baseline. +3. add entity to entity update in database. +4. if there are more entities to write and packet is not full, go back to step 2. +5. write terminator (0xFFFF) as entity number. +6. return. + + + + + +server updates entities in looping ranges, a frame consists of a range of visible entities (not always all visible entities), +*/ + typedef struct { double time; @@ -316,7 +416,7 @@ typedef struct entity_frameinfo_t; #define MAX_ENTITY_HISTORY 64 -#define MAX_ENTITY_DATABASE 4096 +#define MAX_ENTITY_DATABASE (MAX_EDICTS * 2) typedef struct { @@ -329,9 +429,13 @@ typedef struct // note: if numframes == 0, insert at start (0 in entitydata) // the only reason this system is used is to avoid copying memory when frames are removed int numframes; - int ackframe; // server only: last acknowledged frame + // server only: last acknowledged frame + int ackframe; + // the current state in the database vec3_t eye; + // table of entities in the entityhistorydata entity_frameinfo_t frames[MAX_ENTITY_HISTORY]; + // entities entity_state_t entitydata[MAX_ENTITY_DATABASE]; } entity_database_t; @@ -342,6 +446,8 @@ typedef struct double time; int framenum; int numentities; + int firstentitynum; + int lastentitynum; vec3_t eye; entity_state_t entitydata[MAX_ENTITY_DATABASE]; } @@ -379,29 +485,46 @@ entity_frame_t; #define E_EFFECTS2 (1<<18) #define E_GLOWSIZE (1<<19) #define E_GLOWCOLOR (1<<20) -#define E_UNUSED1 (1<<21) -#define E_UNUSED2 (1<<22) +#define E_LIGHT (1<<21) +#define E_LIGHTPFLAGS (1<<22) #define E_EXTEND3 (1<<23) #define E_SOUND1 (1<<24) #define E_SOUNDVOL (1<<25) #define E_SOUNDATTEN (1<<26) -#define E_UNUSED4 (1<<27) -#define E_UNUSED5 (1<<28) +#define E_TAGATTACHMENT (1<<27) +#define E_LIGHTSTYLE (1<<28) #define E_UNUSED6 (1<<29) #define E_UNUSED7 (1<<30) #define E_EXTEND4 (1<<31) +// baseline state values +entity_state_t defaultstate; + +// clears a state to baseline values void ClearStateToDefault(entity_state_t *s); +// returns difference between two states as E_ flags +int EntityState_DeltaBits(const entity_state_t *o, const entity_state_t *n); +// write E_ flags to a msg +void EntityState_WriteExtendBits(sizebuf_t *msg, unsigned int bits); +// write values for the E_ flagged fields to a msg +void EntityState_WriteFields(entity_state_t *ent, sizebuf_t *msg, unsigned int bits); +// write entity number and E_ flags and their values, or a remove number, describing the change from delta to ent +void EntityState_WriteUpdate(entity_state_t *ent, sizebuf_t *msg, entity_state_t *delta); +// read E_ flags +int EntityState_ReadExtendBits(void); +// read values for E_ flagged fields and apply them to a state +void EntityState_ReadFields(entity_state_t *e, unsigned int bits); + // (server) clears the database to contain no frames (thus delta compression // compresses against nothing) void EntityFrame_ClearDatabase(entity_database_t *d); // (server and client) removes frames older than 'frame' from database void EntityFrame_AckFrame(entity_database_t *d, int frame); // (server) clears frame, to prepare for adding entities -void EntityFrame_Clear(entity_frame_t *f, vec3_t eye); -// (server) allocates an entity slot in frame, returns NULL if full -entity_state_t *EntityFrame_NewEntity(entity_frame_t *f, int number); +void EntityFrame_Clear(entity_frame_t *f, vec3_t eye, int framenum); +// (server) adds an entity to frame +void EntityFrame_AddEntity(entity_frame_t *f, entity_state_t *s); // (server and client) reads a frame from the database void EntityFrame_FetchFrame(entity_database_t *d, int framenum, entity_frame_t *f); // (server and client) adds a entity_frame to the database, for future @@ -411,12 +534,160 @@ void EntityFrame_AddFrame(entity_database_t *d, entity_frame_t *f); void EntityFrame_Write(entity_database_t *d, entity_frame_t *f, sizebuf_t *msg); // (client) reads a frame from network stream void EntityFrame_Read(entity_database_t *d); -// (client) reads (and interpolates) the eye location from the database, -// given a current time -//int EntityFrame_FetchEye(entity_database_t *d, vec3_t eye, double time); -// (client) fetchs an entity from the frame by index into the entity list -//int EntityFrame_FetchEntityByIndex(entity_frame_t *f, entity_state_t *e, int index); -// (client) fetchs an entity from the frame by entity number -//int EntityFrame_FetchEntityByNumber(entity_frame_t *f, entity_state_t *e, int number); // (client) returns the frame number of the most recent frame recieved int EntityFrame_MostRecentlyRecievedFrameNum(entity_database_t *d); + +typedef struct entity_database4_commit_s +{ + // frame number this commit represents + int framenum; + // number of entities in entity[] array + int numentities; + // maximum number of entities in entity[] array (dynamic resizing) + int maxentities; + entity_state_t *entity; +} +entity_database4_commit_t; + +typedef struct entity_database4_s +{ + // what mempool to use for allocations + mempool_t *mempool; + // reference frame + int referenceframenum; + // reference entities array is resized according to demand + int maxreferenceentities; + // array of states for entities, these are indexable by their entity number (yes there are gaps) + entity_state_t *referenceentity; + // commits waiting to be applied to the reference database when confirmed + // (commit[i]->numentities == 0 means it is empty) + entity_database4_commit_t commit[MAX_ENTITY_HISTORY]; + // (server only) the current commit being worked on + entity_database4_commit_t *currentcommit; + // (server only) if a commit won't fit entirely, continue where it left + // off next frame + int currententitynumber; + // (client only) most recently received frame number to be sent in next + // input update + int ackframenum; +} +entity_database4_t; + +// should-be-private functions that aren't +entity_state_t *EntityFrame4_GetReferenceEntity(entity_database4_t *d, int number); +void EntityFrame4_AddCommitEntity(entity_database4_t *d, entity_state_t *s); + +// allocate a database +entity_database4_t *EntityFrame4_AllocDatabase(mempool_t *pool); +// free a database +void EntityFrame4_FreeDatabase(entity_database4_t *d); +// reset a database (resets compression but does not reallocate anything) +void EntityFrame4_ResetDatabase(entity_database4_t *d); +// updates database to account for a frame-received acknowledgment +int EntityFrame4_AckFrame(entity_database4_t *d, int framenum); + +// write an entity in the frame +// returns false if full +int EntityFrame4_SV_WriteFrame_Entity(entity_database4_t *d, sizebuf_t *msg, int maxbytes, entity_state_t *s); + +// reads a frame from the network stream +void EntityFrame4_CL_ReadFrame(entity_database4_t *d); + +// reset all entity fields (typically used if status changed) +#define E5_FULLUPDATE (1<<0) +// E5_ORIGIN32=0: short[3] = s->origin[0] * 8, s->origin[1] * 8, s->origin[2] * 8 +// E5_ORIGIN32=1: float[3] = s->origin[0], s->origin[1], s->origin[2] +#define E5_ORIGIN (1<<1) +// E5_ANGLES16=0: byte[3] = s->angle[0] * 256 / 360, s->angle[1] * 256 / 360, s->angle[2] * 256 / 360 +// E5_ANGLES16=1: short[3] = s->angle[0] * 65536 / 360, s->angle[1] * 65536 / 360, s->angle[2] * 65536 / 360 +#define E5_ANGLES (1<<2) +// E5_MODEL16=0: byte = s->modelindex +// E5_MODEL16=1: short = s->modelindex +#define E5_MODEL (1<<3) +// E5_FRAME16=0: byte = s->frame +// E5_FRAME16=1: short = s->frame +#define E5_FRAME (1<<4) +// byte = s->skin +#define E5_SKIN (1<<5) +// E5_EFFECTS16=0 && E5_EFFECTS32=0: byte = s->effects +// E5_EFFECTS16=1 && E5_EFFECTS32=0: short = s->effects +// E5_EFFECTS16=0 && E5_EFFECTS32=1: int = s->effects +// E5_EFFECTS16=1 && E5_EFFECTS32=1: int = s->effects +#define E5_EFFECTS (1<<6) +// bits >= (1<<8) +#define E5_EXTEND1 (1<<7) + +// flag +#define E5_ORIGIN32 (1<<9) +// flag +#define E5_ANGLES16 (1<<10) +// flag +#define E5_MODEL16 (1<<11) +// byte = s->renderflags +#define E5_FLAGS (1<<6) +// byte = bound(0, s->alpha * 255, 255) +#define E5_ALPHA (1<<13) +// byte = bound(0, s->scale * 16, 255) +#define E5_SCALE (1<<14) +// bits >= (1<<16) +#define E5_EXTEND2 (1<<15) + +// short = s->tagentity +// byte = s->tagindex +#define E5_ATTACHMENT (1<<16) +// short = s->exteriormodelforentity +#define E5_EXTERIORFORENTITY (1<<17) +// short[4] = s->light[0], s->light[1], s->light[2], s->light[3] +#define E5_LIGHT (1<<18) +// byte = s->colormap +#define E5_COLORMAP (1<<19) +// byte = s->glowsize +// byte = s->glowcolor +#define E5_GLOW (1<<20) +// short = s->effects +#define E5_EFFECTS16 (1<<21) +// int = s->effects +#define E5_EFFECTS32 (1<<22) +// bits >= (1<<24) +#define E5_EXTEND3 (1<<23) + +// flag +#define E5_FRAME16 (1<<24) +// unused +#define E5_UNUSED25 (1<<25) +// unused +#define E5_UNUSED26 (1<<26) +// unused +#define E5_UNUSED27 (1<<27) +// unused +#define E5_UNUSED28 (1<<28) +// unused +#define E5_UNUSED29 (1<<29) +// unused +#define E5_UNUSED30 (1<<30) +// bits2 > 0 +#define E5_EXTEND4 (1<<31) + +typedef struct entity_database5_client_s +{ + qbyte visible[MAX_EDICTS]; + qbyte visibledelta[MAX_EDICTS]; + int statedelta[MAX_EDICTS]; +} +entity_database5_t; + +typedef struct entity_database5_server_s +{ + // temporary working space for client data building + // 0-255 priority level, 0 = don't send + qbyte priorities[MAX_EDICTS]; + // this is the visible entity numbers, sorted by their priority level + int numentitylist; + int entitylist[MAX_EDICTS]; +} +entity_database5_server_t; + +extern cvar_t developer_networkentities; + +#endif +