X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=protocol.h;h=211043b4f360feed8e9f017629e9a83b7b652292;hp=9ec2011421bde66d3da630676deb2807529e561f;hb=f9d8bc7ea04ff91fcbd90fe50a299b37724b349b;hpb=a0338ffd578afdaf693aee96bc6f948afb5b1844 diff --git a/protocol.h b/protocol.h index 9ec20114..211043b4 100644 --- a/protocol.h +++ b/protocol.h @@ -22,13 +22,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifndef PROTOCOL_H #define PROTOCOL_H -#define PROTOCOL_VERSION 15 -#define DPPROTOCOL_VERSION1 96 -#define DPPROTOCOL_VERSION2 97 -// LordHavoc: I think the 96-99 range was going to run out too soon... -// so here I jump to 3500 -#define DPPROTOCOL_VERSION3 3500 -#define DPPROTOCOL_VERSION4 3501 +// protocolversion_t is defined in common.h + +protocolversion_t Protocol_EnumForName(const char *s); +const char *Protocol_NameForEnum(protocolversion_t p); +protocolversion_t Protocol_EnumForNumber(int n); +int Protocol_NumberForEnum(protocolversion_t p); +void Protocol_Names(char *buffer, size_t buffersize); // model effects #define EF_ROCKET 1 // leave a trail @@ -56,9 +56,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #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_NODEPTHTEST 8192 // LordHavoc: shows through walls +#define EF_SELECTABLE 16384 // LordHavoc: highlights when PRYDON_CLIENTCURSOR mouse is over it #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) @@ -86,9 +93,8 @@ 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... #define U_EXTEND2 (1<<23) // another byte to follow // LordHavoc: second extend byte @@ -217,10 +223,11 @@ 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_unusedlh1 51 +#define svc_updatestatubyte 51 // [byte] stat [byte] value #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 +#define svc_sound2 54 // (obsolete in DP6 and later) short soundindex instead of byte +#define svc_precache 54 // [short] precacheindex [string] filename, precacheindex is + 0 for modelindex and +32768 for soundindex #define svc_spawnbaseline2 55 // short modelindex instead of byte #define svc_spawnstatic2 56 // short modelindex instead of byte #define svc_entities 57 // [int] deltaframe [int] thisframe [float vector] eye [variable length] entitydata @@ -237,7 +244,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define clc_stringcmd 4 // [string] message // LordHavoc: my clc_ range, 50-59 -#define clc_ackentities 50 // [int] framenumber +#define clc_ackframe 50 // [int] framenumber #define clc_unusedlh1 51 #define clc_unusedlh2 52 #define clc_unusedlh3 53 @@ -305,37 +312,57 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #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_SHADOW 65536 // cast shadow +#define RENDER_LIGHT 131072 // receive light +#define RENDER_TRANSPARENT 262144 // can't light during opaque stage -typedef struct +// this is 80 bytes +typedef struct entity_state_s { - double time; // time this state was built - vec3_t origin; - vec3_t angles; + // ! means this is not 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 - unsigned short active; // true if a valid state + int effects; unsigned short modelindex; unsigned short frame; - unsigned short effects; unsigned short tagentity; - unsigned short specialvisibilityradius; - unsigned short viewmodelforclient; - unsigned short exteriormodelforclient; - unsigned short nodrawtoclient; - unsigned short drawonlytoclient; - qbyte colormap; - qbyte skin; - qbyte alpha; - qbyte scale; - qbyte glowsize; - qbyte glowcolor; - qbyte flags; - qbyte tagindex; + 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; + unsigned char colormod[3]; + // padding to a multiple of 8 bytes (to align the double time) + unsigned char unused[2]; } entity_state_t; +// baseline state values +extern entity_state_t defaultstate; +// reads a quake entity from the network stream +void EntityFrameQuake_ReadEntity(int bits); +// writes a list of quake entities to the network stream +// (or as many will fit) +void EntityFrameQuake_WriteFrame(sizebuf_t *msg, int numstates, const entity_state_t *states); +// cleans up dead entities each frame after ReadEntity (which doesn't clear unused entities) +void EntityFrameQuake_ISeeDeadEntities(void); + /* -DPPROTOCOL_VERSION3 +PROTOCOL_DARKPLACES3 server updates entities according to some (unmentioned) scheme. a frame consists of all visible entities, some of which are up to date, @@ -367,7 +394,7 @@ if server receives ack message in put packet it performs these steps: */ /* -DPPROTOCOL_VERSION4 +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. @@ -391,7 +418,7 @@ the Write function performs these steps: server updates entities in looping ranges, a frame consists of a range of visible entities (not always all visible entities), */ -typedef struct +typedef struct entity_frameinfo_s { double time; int framenum; @@ -403,7 +430,7 @@ entity_frameinfo_t; #define MAX_ENTITY_HISTORY 64 #define MAX_ENTITY_DATABASE (MAX_EDICTS * 2) -typedef struct +typedef struct entityframe_database_s { // note: these can be far out of range, modulo with MAX_ENTITY_DATABASE to get a valid range (which may wrap) // start and end of used area, when adding a new update to database, store at endpos, and increment endpos @@ -414,8 +441,10 @@ 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; + // server only: last sent frame + int latestframenum; // server only: last acknowledged frame - int ackframe; + int ackframenum; // the current state in the database vec3_t eye; // table of entities in the entityhistorydata @@ -423,10 +452,10 @@ typedef struct // entities entity_state_t entitydata[MAX_ENTITY_DATABASE]; } -entity_database_t; +entityframe_database_t; // build entity data in this, to pass to entity read/write functions -typedef struct +typedef struct entity_frame_s { double time; int framenum; @@ -470,44 +499,54 @@ 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_TAGATTACHMENT (1<<27) -#define E_UNUSED5 (1<<28) +#define E_LIGHTSTYLE (1<<28) #define E_UNUSED6 (1<<29) #define E_UNUSED7 (1<<30) #define E_EXTEND4 (1<<31) -// clears a state to baseline values -void ClearStateToDefault(entity_state_t *s); -// used by some of the DP protocols -void EntityState_Write(entity_state_t *ent, sizebuf_t *msg, entity_state_t *delta); - +// 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(const 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(const entity_state_t *ent, sizebuf_t *msg, const 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); + +// (client and server) allocates a new empty database +entityframe_database_t *EntityFrame_AllocDatabase(mempool_t *mempool); +// (client and server) frees the database +void EntityFrame_FreeDatabase(entityframe_database_t *d); // (server) clears the database to contain no frames (thus delta compression // compresses against nothing) -void EntityFrame_ClearDatabase(entity_database_t *d); +void EntityFrame_ClearDatabase(entityframe_database_t *d); // (server and client) removes frames older than 'frame' from database -void EntityFrame_AckFrame(entity_database_t *d, int frame); +void EntityFrame_AckFrame(entityframe_database_t *d, int frame); // (server) clears frame, to prepare for adding entities 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); +void EntityFrame_FetchFrame(entityframe_database_t *d, int framenum, entity_frame_t *f); // (server and client) adds a entity_frame to the database, for future // reference -void EntityFrame_AddFrame(entity_database_t *d, entity_frame_t *f); +void EntityFrame_AddFrame(entityframe_database_t *d, vec3_t eye, int framenum, int numentities, const entity_state_t *entitydata); // (server) writes a frame to network stream -void EntityFrame_Write(entity_database_t *d, entity_frame_t *f, sizebuf_t *msg); +void EntityFrame_WriteFrame(sizebuf_t *msg, entityframe_database_t *d, int numstates, const entity_state_t *states, int viewentnum); // (client) reads a frame from network stream -void EntityFrame_Read(entity_database_t *d); +void EntityFrame_CL_ReadFrame(void); // (client) returns the frame number of the most recent frame recieved -int EntityFrame_MostRecentlyRecievedFrameNum(entity_database_t *d); +int EntityFrame_MostRecentlyRecievedFrameNum(entityframe_database_t *d); typedef struct entity_database4_commit_s { @@ -539,36 +578,184 @@ typedef struct entity_database4_s // (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; + // (server only) + int latestframenumber; } -entity_database4_t; +entityframe4_database_t; // should-be-private functions that aren't -int EntityFrame4_SV_ChooseCommitToReplace(entity_database4_t *d); -entity_state_t *EntityFrame4_GetReferenceEntity(entity_database4_t *d, int number); -void EntityFrame4_AddCommitEntity(entity_database4_t *d, entity_state_t *s); +entity_state_t *EntityFrame4_GetReferenceEntity(entityframe4_database_t *d, int number); +void EntityFrame4_AddCommitEntity(entityframe4_database_t *d, const entity_state_t *s); // allocate a database -entity_database4_t *EntityFrame4_AllocDatabase(mempool_t *pool); +entityframe4_database_t *EntityFrame4_AllocDatabase(mempool_t *pool); // free a database -void EntityFrame4_FreeDatabase(entity_database4_t *d); +void EntityFrame4_FreeDatabase(entityframe4_database_t *d); // reset a database (resets compression but does not reallocate anything) -void EntityFrame4_ResetDatabase(entity_database4_t *d); +void EntityFrame4_ResetDatabase(entityframe4_database_t *d); // updates database to account for a frame-received acknowledgment -void EntityFrame4_AckFrame(entity_database4_t *d, int framenum); +int EntityFrame4_AckFrame(entityframe4_database_t *d, int framenum, int servermode); +// writes a frame to the network stream +void EntityFrame4_WriteFrame(sizebuf_t *msg, entityframe4_database_t *d, int numstates, const entity_state_t *states); +// reads a frame from the network stream +void EntityFrame4_CL_ReadFrame(void); + +// 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) + +// byte = s->renderflags +#define E5_FLAGS (1<<8) +// byte = bound(0, s->alpha * 255, 255) +#define E5_ALPHA (1<<9) +// byte = bound(0, s->scale * 16, 255) +#define E5_SCALE (1<<10) +// flag +#define E5_ORIGIN32 (1<<11) +// flag +#define E5_ANGLES16 (1<<12) +// flag +#define E5_MODEL16 (1<<13) +// byte = s->colormap +#define E5_COLORMAP (1<<14) +// bits >= (1<<16) +#define E5_EXTEND2 (1<<15) + +// short = s->tagentity +// byte = s->tagindex +#define E5_ATTACHMENT (1<<16) +// short[4] = s->light[0], s->light[1], s->light[2], s->light[3] +// byte = s->lightstyle +// byte = s->lightpflags +#define E5_LIGHT (1<<17) +// byte = s->glowsize +// byte = s->glowcolor +#define E5_GLOW (1<<18) +// short = s->effects +#define E5_EFFECTS16 (1<<19) +// int = s->effects +#define E5_EFFECTS32 (1<<20) +// flag +#define E5_FRAME16 (1<<21) +// byte[3] = s->colormod[0], s->colormod[1], s->colormod[2] +#define E5_COLORMOD (1<<22) +// bits >= (1<<24) +#define E5_EXTEND3 (1<<23) + +// unused +#define E5_UNUSED24 (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) + +#define ENTITYFRAME5_MAXPACKETLOGS 64 +#define ENTITYFRAME5_MAXSTATES 1024 + +typedef struct entityframe5_changestate_s +{ + unsigned int number; + unsigned int bits; +} +entityframe5_changestate_t; -// begin writing a frame -void EntityFrame4_SV_WriteFrame_Begin(entity_database4_t *d, sizebuf_t *msg, 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); -// end writing a frame -void EntityFrame4_SV_WriteFrame_End(entity_database4_t *d, sizebuf_t *msg); +typedef struct entityframe5_packetlog_s +{ + int packetnumber; + int numstates; + entityframe5_changestate_t states[ENTITYFRAME5_MAXSTATES]; + qbyte statsdeltabits[(MAX_CL_STATS+7)/8]; +} +entityframe5_packetlog_t; -// reads a frame from the network stream -void EntityFrame4_CL_ReadFrame(entity_database4_t *d); +typedef struct entityframe5_database_s +{ + // number of the latest message sent to client + int latestframenum; + // updated by WriteFrame for internal use + int viewentnum; + + // logs of all recently sent messages (between acked and latest) + entityframe5_packetlog_t packetlog[ENTITYFRAME5_MAXPACKETLOGS]; + + // this goes up as needed and causes all the arrays to be reallocated + int maxedicts; + + // which properties of each entity have changed since last send + int *deltabits; // [maxedicts] + // priorities of entities (updated whenever deltabits change) + // (derived from deltabits) + qbyte *priorities; // [maxedicts] + // last frame this entity was sent on, for prioritzation + int *updateframenum; // [maxedicts] + + // database of current status of all entities + entity_state_t *states; // [maxedicts] + // which entities are currently active + // (duplicate of the active bit of every state in states[]) + // (derived from states) + qbyte *visiblebits; // [(maxedicts+7)/8] + + // delta compression of stats + qbyte statsdeltabits[(MAX_CL_STATS+7)/8]; + int stats[MAX_CL_STATS]; + + // old notes + + // this is used to decide which changestates to set each frame + //int numvisiblestates; + //entity_state_t visiblestates[MAX_EDICTS]; + + // sorted changing states that need to be sent to the client + // kept sorted in lowest to highest priority order, because this allows + // the numchangestates to simply be decremented whenever an state is sent, + // rather than a memmove to remove them from the start. + //int numchangestates; + //entityframe5_changestate_t changestates[MAX_EDICTS]; +} +entityframe5_database_t; + +entityframe5_database_t *EntityFrame5_AllocDatabase(mempool_t *pool); +void EntityFrame5_FreeDatabase(entityframe5_database_t *d); +void EntityFrame5_ResetDatabase(entityframe5_database_t *d); +void EntityState5_WriteUpdate(int number, const entity_state_t *s, int changedbits, sizebuf_t *msg); +int EntityState5_DeltaBitsForState(entity_state_t *o, entity_state_t *n); +void EntityFrame5_CL_ReadFrame(void); +void EntityFrame5_LostFrame(entityframe5_database_t *d, int framenum); +void EntityFrame5_AckFrame(entityframe5_database_t *d, int framenum); +void EntityFrame5_WriteFrame(sizebuf_t *msg, entityframe5_database_t *d, int numstates, const entity_state_t *states, int viewentnum, int *stats, int movesequence); + +extern cvar_t developer_networkentities; #endif