1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249 |
- #include "../game/q_shared.h"
- #include "qcommon.h"
- #include "../server/server.h"
- /*
- ==============================================================================
- MESSAGE IO FUNCTIONS
- Handles byte ordering and avoids alignment errors
- ==============================================================================
- */
- void MSG_Init( msg_t *buf, byte *data, int length ) {
- memset (buf, 0, sizeof(*buf));
- buf->data = data;
- buf->maxsize = length;
- }
- void MSG_Clear( msg_t *buf ) {
- buf->cursize = 0;
- buf->overflowed = qfalse;
- buf->bit = 0;
- }
- void MSG_BeginReading( msg_t *msg ) {
- msg->readcount = 0;
- msg->bit = 0;
- }
- void MSG_ReadByteAlign( msg_t *buf ) {
- // round up to the next byte
- if ( buf->bit ) {
- buf->bit = 0;
- buf->readcount++;
- }
- }
- void *MSG_GetSpace( msg_t *buf, int length ) {
- void *data;
- // round up to the next byte
- if ( buf->bit ) {
- buf->bit = 0;
- buf->cursize++;
- }
- if ( buf->cursize + length > buf->maxsize ) {
- if ( !buf->allowoverflow ) {
- Com_Error (ERR_FATAL, "MSG_GetSpace: overflow without allowoverflow set");
- }
- if ( length > buf->maxsize ) {
- Com_Error (ERR_FATAL, "MSG_GetSpace: %i is > full buffer size", length);
- }
- Com_Printf ("MSG_GetSpace: overflow\n");
- MSG_Clear (buf);
- buf->overflowed = qtrue;
- }
- data = buf->data + buf->cursize;
- buf->cursize += length;
-
- return data;
- }
- void MSG_WriteData( msg_t *buf, const void *data, int length ) {
- memcpy (MSG_GetSpace(buf,length),data,length);
- }
- /*
- =============================================================================
- bit functions
-
- =============================================================================
- */
- int overflows;
- // negative bit values include signs
- void MSG_WriteBits( msg_t *msg, int value, int bits ) {
- int put;
- int fraction;
- // this isn't an exact overflow check, but close enough
- if ( msg->maxsize - msg->cursize < 4 ) {
- msg->overflowed = qtrue;
- #ifndef FINAL_BUILD
- Com_Printf (S_COLOR_RED"MSG_WriteBits: buffer Full writing %d in %d bits\n", value, bits);
- #endif
- return;
- }
- if ( bits == 0 || bits < -31 || bits > 32 ) {
- Com_Error( ERR_DROP, "MSG_WriteBits: bad bits %i", bits );
- }
- // check for overflows
- if ( bits != 32 ) {
- if ( bits > 0 ) {
- if ( value > ( ( 1 << bits ) - 1 ) || value < 0 ) {
- overflows++;
- #ifndef FINAL_BUILD
- #ifdef _DEBUG
- Com_Printf (S_COLOR_RED"MSG_WriteBits: overflow writing %d in %d bits\n", value, bits);
- #endif
- #endif
- }
- } else {
- int r;
- r = 1 << (bits-1);
- if ( value > r - 1 || value < -r ) {
- overflows++;
- #ifndef FINAL_BUILD
- #ifdef _DEBUG
- Com_Printf (S_COLOR_RED"MSG_WriteBits: overflow writing %d in %d bits\n", value, bits);
- #endif
- #endif
- }
- }
- }
- if ( bits < 0 ) {
- bits = -bits;
- }
- while ( bits ) {
- if ( msg->bit == 0 ) {
- msg->data[msg->cursize] = 0;
- msg->cursize++;
- }
- put = 8 - msg->bit;
- if ( put > bits ) {
- put = bits;
- }
- fraction = value & ( ( 1 << put ) - 1 );
- msg->data[msg->cursize - 1] |= fraction << msg->bit;
- bits -= put;
- value >>= put;
- msg->bit = ( msg->bit + put ) & 7;
- }
- }
- int MSG_ReadBits( msg_t *msg, int bits ) {
- int value;
- int valueBits;
- int get;
- int fraction;
- qboolean sgn;
- value = 0;
- valueBits = 0;
- if ( bits < 0 ) {
- bits = -bits;
- sgn = qtrue;
- } else {
- sgn = qfalse;
- }
- while ( valueBits < bits ) {
- if ( msg->bit == 0 ) {
- msg->readcount++;
- assert (msg->readcount <= msg->cursize);
- }
- get = 8 - msg->bit;
- if ( get > (bits - valueBits) ) {
- get = (bits - valueBits);
- }
- fraction = msg->data[msg->readcount - 1];
- fraction >>= msg->bit;
- fraction &= ( 1 << get ) - 1;
- value |= fraction << valueBits;
- valueBits += get;
- msg->bit = ( msg->bit + get ) & 7;
- }
- if ( sgn ) {
- if ( value & ( 1 << ( bits - 1 ) ) ) {
- value |= -1 ^ ( ( 1 << bits ) - 1 );
- }
- }
- return value;
- }
- //================================================================================
- //
- // writing functions
- //
- void MSG_WriteByte( msg_t *sb, int c ) {
- #ifdef PARANOID
- if (c < 0 || c > 255)
- Com_Error (ERR_FATAL, "MSG_WriteByte: range error");
- #endif
- MSG_WriteBits( sb, c, 8 );
- }
- void MSG_WriteShort( msg_t *sb, int c ) {
- #ifdef PARANOID
- if (c < ((short)0x8000) || c > (short)0x7fff)
- Com_Error (ERR_FATAL, "MSG_WriteShort: range error");
- #endif
- MSG_WriteBits( sb, c, 16 );
- }
- static void MSG_WriteSShort( msg_t *sb, int c ) {
- MSG_WriteBits( sb, c, -16 );
- }
- void MSG_WriteLong( msg_t *sb, int c ) {
- MSG_WriteBits( sb, c, 32 );
- }
- void MSG_WriteString( msg_t *sb, const char *s ) {
- if ( !s ) {
- MSG_WriteData (sb, "", 1);
- } else {
- int l, i;
- char string[MAX_STRING_CHARS];
- l = strlen( s );
- if ( l >= MAX_STRING_CHARS ) {
- Com_Printf( "MSG_WriteString: MAX_STRING_CHARS" );
- MSG_WriteData (sb, "", 1);
- return;
- }
- Q_strncpyz( string, s, sizeof( string ) );
- // get rid of 0xff chars, because old clients don't like them
- for ( i = 0 ; i < l ; i++ ) {
- if ( ((byte *)string)[i] > 127 ) {
- string[i] = '.';
- }
- }
- MSG_WriteData (sb, string, l+1);
- }
- }
- //============================================================
- //
- // reading functions
- //
- // returns -1 if no more characters are available
- int MSG_ReadByte( msg_t *msg ) {
- int c;
-
- if ( msg->readcount+1 > msg->cursize ) {
- c = -1;
- } else {
- c = (unsigned char)MSG_ReadBits( msg, 8 );
- }
-
- return c;
- }
- int MSG_ReadShort( msg_t *msg ) {
- int c;
-
- if ( msg->readcount+2 > msg->cursize ) {
- c = -1;
- } else {
- c = MSG_ReadBits( msg, 16 );
- }
- return c;
- }
- static int MSG_ReadSShort( msg_t *msg ) {
- int c;
-
- if ( msg->readcount+2 > msg->cursize ) {
- c = -1;
- } else {
- c = MSG_ReadBits( msg, -16 );
- }
- return c;
- }
- int MSG_ReadLong( msg_t *msg ) {
- int c;
-
- if ( msg->readcount+4 > msg->cursize ) {
- c = -1;
- } else {
- c = MSG_ReadBits( msg, 32 );
- }
-
- return c;
- }
- char *MSG_ReadString( msg_t *msg ) {
- static char string[MAX_STRING_CHARS];
- int l,c;
-
- MSG_ReadByteAlign( msg );
- l = 0;
- do {
- c = MSG_ReadByte(msg); // use ReadByte so -1 is out of bounds
- if ( c == -1 || c == 0 ) {
- break;
- }
- // translate all fmt spec to avoid crash bugs
- if ( c == '%' ) {
- c = '.';
- }
- string[l] = c;
- l++;
- } while (l < sizeof(string)-1);
-
- string[l] = 0;
-
- return string;
- }
- char *MSG_ReadStringLine( msg_t *msg ) {
- static char string[MAX_STRING_CHARS];
- int l,c;
- MSG_ReadByteAlign( msg );
- l = 0;
- do {
- c = MSG_ReadByte(msg); // use ReadByte so -1 is out of bounds
- if (c == -1 || c == 0 || c == '\n') {
- break;
- }
- // translate all fmt spec to avoid crash bugs
- if ( c == '%' ) {
- c = '.';
- }
- string[l] = c;
- l++;
- } while (l < sizeof(string)-1);
-
- string[l] = 0;
-
- return string;
- }
- void MSG_ReadData( msg_t *msg, void *data, int len ) {
- int i;
- MSG_ReadByteAlign( msg );
- for (i=0 ; i<len ; i++) {
- ((byte *)data)[i] = MSG_ReadByte (msg);
- }
- }
- /*
- =============================================================================
- delta functions
-
- =============================================================================
- */
- extern cvar_t *cl_shownet;
- #define LOG(x) if( cl_shownet->integer == 4 ) { Com_Printf("%s ", x ); };
- void MSG_WriteDelta( msg_t *msg, int oldV, int newV, int bits ) {
- if ( oldV == newV ) {
- MSG_WriteBits( msg, 0, 1 );
- return;
- }
- MSG_WriteBits( msg, 1, 1 );
- MSG_WriteBits( msg, newV, bits );
- }
- int MSG_ReadDelta( msg_t *msg, int oldV, int bits ) {
- if ( MSG_ReadBits( msg, 1 ) ) {
- return MSG_ReadBits( msg, bits );
- }
- return oldV;
- }
- void MSG_WriteDeltaFloat( msg_t *msg, float oldV, float newV ) {
- if ( oldV == newV ) {
- MSG_WriteBits( msg, 0, 1 );
- return;
- }
- MSG_WriteBits( msg, 1, 1 );
- MSG_WriteBits( msg, *(int *)&newV, 32 );
- }
- float MSG_ReadDeltaFloat( msg_t *msg, float oldV ) {
- if ( MSG_ReadBits( msg, 1 ) ) {
- float newV;
- *(int *)&newV = MSG_ReadBits( msg, 32 );
- return newV;
- }
- return oldV;
- }
- /*
- ============================================================================
- usercmd_t communication
- ============================================================================
- */
- // ms is 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_WEAPON (1<<7)
- /*
- =====================
- MSG_WriteDeltaUsercmd
- =====================
- */
- void MSG_WriteDeltaUsercmd( msg_t *msg, usercmd_t *from, usercmd_t *to ) {
- MSG_WriteDelta( msg, from->serverTime, to->serverTime, 32 );
- MSG_WriteDelta( msg, from->angles[0], to->angles[0], 16 );
- MSG_WriteDelta( msg, from->angles[1], to->angles[1], 16 );
- MSG_WriteDelta( msg, from->angles[2], to->angles[2], 16 );
- MSG_WriteDelta( msg, from->forwardmove, to->forwardmove, -8 );
- MSG_WriteDelta( msg, from->rightmove, to->rightmove, -8 );
- MSG_WriteDelta( msg, from->upmove, to->upmove, -8 );
- MSG_WriteDelta( msg, from->buttons, to->buttons, 16 );//FIXME: We're only really using 9 bits...can this be changed to that?
- MSG_WriteDelta( msg, from->weapon, to->weapon, 8 );
- MSG_WriteDelta( msg, from->generic_cmd, to->generic_cmd, 8 );
- }
- /*
- =====================
- MSG_ReadDeltaUsercmd
- =====================
- */
- void MSG_ReadDeltaUsercmd( msg_t *msg, usercmd_t *from, usercmd_t *to ) {
- to->serverTime = MSG_ReadDelta( msg, from->serverTime, 32);
- to->angles[0] = MSG_ReadDelta( msg, from->angles[0], 16);
- to->angles[1] = MSG_ReadDelta( msg, from->angles[1], 16);
- to->angles[2] = MSG_ReadDelta( msg, from->angles[2], 16);
- to->forwardmove = MSG_ReadDelta( msg, from->forwardmove, -8);
- to->rightmove = MSG_ReadDelta( msg, from->rightmove, -8);
- to->upmove = MSG_ReadDelta( msg, from->upmove, -8);
- to->buttons = MSG_ReadDelta( msg, from->buttons, 16);//FIXME: We're only really using 9 bits...can this be changed to that?
- to->weapon = MSG_ReadDelta( msg, from->weapon, 8);
- to->generic_cmd = MSG_ReadDelta( msg, from->generic_cmd, 8);
- }
- /*
- =============================================================================
- entityState_t communication
-
- =============================================================================
- */
- typedef struct {
- char *name;
- int offset;
- int bits; // 0 = float
- } netField_t;
- // using the stringizing operator to save typing...
- #define NETF(x) #x,(int)&((entityState_t*)0)->x
- #if 0 // Removed by BTO (VV)
- const netField_t entityStateFields[] =
- {
- { NETF(eType), 8 },
- { NETF(eFlags), 32 },
- { NETF(pos.trType), 8 },
- { NETF(pos.trTime), 32 },
- { NETF(pos.trDuration), 32 },
- { NETF(pos.trBase[0]), 0 },
- { NETF(pos.trBase[1]), 0 },
- { NETF(pos.trBase[2]), 0 },
- { NETF(pos.trDelta[0]), 0 },
- { NETF(pos.trDelta[1]), 0 },
- { NETF(pos.trDelta[2]), 0 },
- { NETF(apos.trType), 8 },
- { NETF(apos.trTime), 32 },
- { NETF(apos.trDuration), 32 },
- { NETF(apos.trBase[0]), 0 },
- { NETF(apos.trBase[1]), 0 },
- { NETF(apos.trBase[2]), 0 },
- { NETF(apos.trDelta[0]), 0 },
- { NETF(apos.trDelta[1]), 0 },
- { NETF(apos.trDelta[2]), 0 },
- { NETF(time), 32 },
- { NETF(time2), 32 },
- { NETF(origin[0]), 0 },
- { NETF(origin[1]), 0 },
- { NETF(origin[2]), 0 },
- { NETF(origin2[0]), 0 },
- { NETF(origin2[1]), 0 },
- { NETF(origin2[2]), 0 },
- { NETF(angles[0]), 0 },
- { NETF(angles[1]), 0 },
- { NETF(angles[2]), 0 },
- { NETF(angles2[0]), 0 },
- { NETF(angles2[1]), 0 },
- { NETF(angles2[2]), 0 },
- { NETF(otherEntityNum), GENTITYNUM_BITS },
- //{ NETF(otherEntityNum2), GENTITYNUM_BITS },
- { NETF(groundEntityNum), GENTITYNUM_BITS },
- { NETF(constantLight), 32 },
- { NETF(loopSound), 16 },
- { NETF(modelindex), 9 }, //0 to 511
- { NETF(modelindex2), 8 },
- { NETF(modelindex3), 8 },
- { NETF(clientNum), 32 },
- { NETF(frame), 16 },
- { NETF(solid), 24 },
- { NETF(event), 10 },
- { NETF(eventParm), 16 },
- { NETF(powerups), 16 },
- { NETF(weapon), 8 },
- { NETF(legsAnim), 16 },
- { NETF(legsAnimTimer), 8 },
- { NETF(torsoAnim), 16 },
- { NETF(torsoAnimTimer), 8 },
- { NETF(scale), 8 },
- { NETF(saberInFlight), 4 },
- { NETF(saberActive), 4 },
- { NETF(vehicleArmor), 32 },
- { NETF(vehicleAngles[0]), 0 },
- { NETF(vehicleAngles[1]), 0 },
- { NETF(vehicleAngles[2]), 0 },
- { NETF(m_iVehicleNum), 32 },
- /*
- Ghoul2 Insert Start
- */
- { NETF(modelScale[0]), 0 },
- { NETF(modelScale[1]), 0 },
- { NETF(modelScale[2]), 0 },
- { NETF(radius), 16 },
- { NETF(boltInfo), 32 },
- //{ NETF(ghoul2), 32 },
- { NETF(isPortalEnt), 1 },
- };
- #endif
- // if (int)f == f and (int)f + ( 1<<(FLOAT_INT_BITS-1) ) < ( 1 << FLOAT_INT_BITS )
- // the float will be sent with FLOAT_INT_BITS, otherwise all 32 bits will be sent
- #define FLOAT_INT_BITS 13
- #define FLOAT_INT_BIAS (1<<(FLOAT_INT_BITS-1))
- void MSG_WriteField (msg_t *msg, const int *toF, const netField_t *field)
- {
- int trunc;
- float fullFloat;
- if ( field->bits == -1)
- { // a -1 in the bits field means it's a float that's always between -1 and 1
- int temp = *(float *)toF * 32767;
- MSG_WriteBits( msg, temp, -16 );
- }
- else
- if ( field->bits == 0 ) {
- // float
- fullFloat = *(float *)toF;
- trunc = (int)fullFloat;
- if (fullFloat == 0.0f) {
- MSG_WriteBits( msg, 0, 1 ); //it's a zero
- } else {
- MSG_WriteBits( msg, 1, 1 ); //not a zero
- if ( trunc == fullFloat && trunc + FLOAT_INT_BIAS >= 0 &&
- trunc + FLOAT_INT_BIAS < ( 1 << FLOAT_INT_BITS ) ) {
- // send as small integer
- MSG_WriteBits( msg, 0, 1 );
- MSG_WriteBits( msg, trunc + FLOAT_INT_BIAS, FLOAT_INT_BITS );
- } else {
- // send as full floating point value
- MSG_WriteBits( msg, 1, 1 );
- MSG_WriteBits( msg, *toF, 32 );
- }
- }
- } else {
- if (*toF == 0) {
- MSG_WriteBits( msg, 0, 1 ); //it's a zero
- } else {
- MSG_WriteBits( msg, 1, 1 ); //not a zero
- // integer
- MSG_WriteBits( msg, *toF, field->bits );
- }
- }
- }
- void MSG_ReadField (msg_t *msg, int *toF, const netField_t *field, int print)
- {
- int trunc;
- if ( field->bits == -1)
- { // a -1 in the bits field means it's a float that's always between -1 and 1
- int temp = MSG_ReadBits( msg, -16);
- *(float *)toF = (float)temp / 32767;
- }
- else
- if ( field->bits == 0 ) {
- // float
- if ( MSG_ReadBits( msg, 1 ) == 0 ) {
- *(float *)toF = 0.0f;
- } else {
- if ( MSG_ReadBits( msg, 1 ) == 0 ) {
- // integral float
- trunc = MSG_ReadBits( msg, FLOAT_INT_BITS );
- // bias to allow equal parts positive and negative
- trunc -= FLOAT_INT_BIAS;
- *(float *)toF = trunc;
- if ( print ) {
- Com_Printf( "%s:%i ", field->name, trunc );
- }
- } else {
- // full floating point value
- *toF = MSG_ReadBits( msg, 32 );
- if ( print ) {
- Com_Printf( "%s:%f ", field->name, *(float *)toF );
- }
- }
- }
- } else {
- if ( MSG_ReadBits( msg, 1 ) == 0 ) {
- *toF = 0;
- } else {
- // integer
- *toF = MSG_ReadBits( msg, field->bits );
- if ( print ) {
- Com_Printf( "%s:%i ", field->name, *toF );
- }
- }
- }
- }
- /*
- ==================
- MSG_WriteDeltaEntity
- GENTITYNUM_BITS 1 : remove this entity
- GENTITYNUM_BITS 0 1 SMALL_VECTOR_BITS <data>
- GENTITYNUM_BITS 0 0 LARGE_VECTOR_BITS >data>
- Writes part of a packetentities message, including the entity number.
- Can delta from either a baseline or a previous packet_entity
- If to is NULL, a remove entity update will be sent
- If force is not set, then nothing at all will be generated if the entity is
- identical, under the assumption that the in-order delta code will catch it.
- ==================
- */
- #if 0 // Removed by BTO (VV)
- void MSG_WriteDeltaEntity( msg_t *msg, struct entityState_s *from, struct entityState_s *to,
- qboolean force ) {
- int c;
- int i;
- const netField_t *field;
- int *fromF, *toF;
- int blah;
- bool stuffChanged = false;
- const int numFields = sizeof(entityStateFields)/sizeof(entityStateFields[0]);
- byte changeVector[(numFields/8) + 1];
- // all fields should be 32 bits to avoid any compiler packing issues
- // the "number" field is not part of the field list
- // if this assert fails, someone added a field to the entityState_t
- // struct without updating the message fields
- blah = sizeof( *from );
- assert( numFields + 1 == blah/4);
- c = msg->cursize;
- // a NULL to is a delta remove message
- if ( to == NULL ) {
- if ( from == NULL ) {
- return;
- }
- MSG_WriteBits( msg, from->number, GENTITYNUM_BITS );
- MSG_WriteBits( msg, 1, 1 );
- return;
- }
- if ( to->number < 0 || to->number >= MAX_GENTITIES ) {
- Com_Error (ERR_FATAL, "MSG_WriteDeltaEntity: Bad entity number: %i", to->number );
- }
- memset(changeVector, 0, sizeof(changeVector));
- // build the change vector as bytes so it is endien independent
- for ( i = 0, field = entityStateFields ; i < numFields ; i++, field++ ) {
- fromF = (int *)( (byte *)from + field->offset );
- toF = (int *)( (byte *)to + field->offset );
- if ( *fromF != *toF ) {
- changeVector[ i>>3 ] |= 1 << ( i & 7 );
- stuffChanged = true;
- }
- }
-
- if ( stuffChanged )
- {
- MSG_WriteBits( msg, to->number, GENTITYNUM_BITS );
- MSG_WriteBits( msg, 0, 1 ); // not removed
- MSG_WriteBits( msg, 1, 1 ); // we have a delta
- // we need to write the entire delta
- for ( i = 0 ; i + 8 <= numFields ; i += 8 ) {
- MSG_WriteByte( msg, changeVector[i>>3] );
- }
- if ( numFields & 7 ) {
- MSG_WriteBits( msg, changeVector[i>>3], numFields & 7 );
- }
- for ( i = 0, field = entityStateFields ; i < numFields ; i++, field++ ) {
- fromF = (int *)( (byte *)from + field->offset );
- toF = (int *)( (byte *)to + field->offset );
- if ( *fromF == *toF ) {
- continue;
- }
- MSG_WriteField(msg, toF, field);
- }
- }
- else
- {
- // nothing at all changed
- // write two bits for no change
- MSG_WriteBits( msg, to->number, GENTITYNUM_BITS );
- MSG_WriteBits( msg, 0, 1 ); // not removed
- MSG_WriteBits( msg, 0, 1 ); // no delta
- }
- c = msg->cursize - c;
- }
- #endif
- extern serverStatic_t svs;
- void MSG_WriteEntity( msg_t *msg, struct entityState_s *to, int removeNum)
- {
- if ( to == NULL ) {
- MSG_WriteBits(msg, removeNum, GENTITYNUM_BITS);
- MSG_WriteBits(msg, 1, 1); //removed
- return;
- } else {
- MSG_WriteBits(msg, to->number, GENTITYNUM_BITS);
- MSG_WriteBits(msg, 0, 1); //not removed
- }
- assert(( to - svs.snapshotEntities ) >= 0 && ( to - svs.snapshotEntities ) < 512);
- MSG_WriteLong(msg, to - svs.snapshotEntities);
- }
- void MSG_ReadEntity( msg_t *msg, entityState_t *to)
- {
- // check for a remove
- if ( MSG_ReadBits( msg, 1 ) == 1 ) {
- memset( to, 0, sizeof( *to ) );
- to->number = MAX_GENTITIES - 1;
- return;
- }
- //No remove, read data
- int index;
- index = MSG_ReadLong(msg);
- assert(index >= 0 && index < svs.numSnapshotEntities);
- *to = svs.snapshotEntities[index];
- }
- /*
- ==================
- MSG_ReadDeltaEntity
- The entity number has already been read from the message, which
- is how the from state is identified.
- If the delta removes the entity, entityState_t->number will be set to MAX_GENTITIES-1
- Can go from either a baseline or a previous packet_entity
- ==================
- */
- extern cvar_t *cl_shownet;
- #if 0 // Removed by BTO (VV)
- void MSG_ReadDeltaEntity( msg_t *msg, entityState_t *from, entityState_t *to, int number)
- {
- int i;
- const netField_t *field;
- int *fromF, *toF;
- int print = 0;
- int startBit, endBit;
- const int numFields = sizeof(entityStateFields)/sizeof(entityStateFields[0]);
- byte expandedVector[(numFields/8) + 1];
- if ( number < 0 || number >= MAX_GENTITIES) {
- Com_Error( ERR_DROP, "Bad delta entity number: %i", number );
- }
- if ( msg->bit == 0 ) {
- startBit = msg->readcount * 8 - GENTITYNUM_BITS;
- } else {
- startBit = ( msg->readcount - 1 ) * 8 + msg->bit - GENTITYNUM_BITS;
- }
- // check for a remove
- if ( MSG_ReadBits( msg, 1 ) == 1 ) {
- memset( to, 0, sizeof( *to ) );
- to->number = MAX_GENTITIES - 1;
- if ( cl_shownet->integer >= 2 || cl_shownet->integer == -1 ) {
- Com_Printf( "%3i: #%-3i remove\n", msg->readcount, number );
- }
- return;
- }
- // check for no delta
- if ( MSG_ReadBits( msg, 1 ) != 0 )
- {
- const int numFields = sizeof(entityStateFields)/sizeof(entityStateFields[0]);
- // shownet 2/3 will interleave with other printed info, -1 will
- // just print the delta records`
- if ( cl_shownet->integer >= 2 || cl_shownet->integer == -1 ) {
- print = 1;
- Com_Printf( "%3i: #%-3i ", msg->readcount, to->number );
- } else {
- print = 0;
- }
- // we need to write the entire delta
- for ( i = 0 ; i + 8 <= numFields ; i += 8 ) {
- expandedVector[i>>3] = MSG_ReadByte( msg );
- }
- if ( numFields & 7 ) {
- expandedVector[i>>3] = MSG_ReadBits( msg, numFields & 7 );
- }
- to->number = number;
- for ( i = 0, field = entityStateFields ; i < numFields ; i++, field++ ) {
- fromF = (int *)( (byte *)from + field->offset );
- toF = (int *)( (byte *)to + field->offset );
- if ( ! ( expandedVector[ i >> 3 ] & ( 1 << ( i & 7 ) ) ) ) {
- // no change
- *toF = *fromF;
- } else {
- MSG_ReadField(msg, toF, field, print);
- }
- }
- }
- else
- {
- memcpy(to, from,sizeof(entityState_t));
- to->number = number;
- }
- if ( print ) {
- if ( msg->bit == 0 ) {
- endBit = msg->readcount * 8 - GENTITYNUM_BITS;
- } else {
- endBit = ( msg->readcount - 1 ) * 8 + msg->bit - GENTITYNUM_BITS;
- }
- Com_Printf( " (%i bits)\n", endBit - startBit );
- }
- }
- #endif
- /*
- Ghoul2 Insert End
- */
- /*
- ============================================================================
- plyer_state_t communication
- ============================================================================
- */
- // using the stringizing operator to save typing...
- #define PSF(x) #x,(int)&((playerState_t*)0)->x
- static const netField_t playerStateFields[] =
- {
- { PSF(commandTime), 32 },
- { PSF(pm_type), 8 },
- { PSF(bobCycle), 8 },
- { PSF(pm_flags), 32 },
- { PSF(pm_time), -16 },
- { PSF(origin[0]), 0 },
- { PSF(origin[1]), 0 },
- { PSF(origin[2]), 0 },
- { PSF(velocity[0]), 0 },
- { PSF(velocity[1]), 0 },
- { PSF(velocity[2]), 0 },
- { PSF(weaponTime), -16 },
- { PSF(weaponChargeTime), 32 }, //? really need 32 bits??
- { PSF(gravity), 16 },
- { PSF(leanofs), -8 },
- { PSF(friction), 16 },
- { PSF(speed), 16 },
- { PSF(delta_angles[0]), 16 },
- { PSF(delta_angles[1]), 16 },
- { PSF(delta_angles[2]), 16 },
- { PSF(groundEntityNum), GENTITYNUM_BITS },
- //{ PSF(animationTimer), 16 },
- { PSF(legsAnim), 16 },
- { PSF(torsoAnim), 16 },
- { PSF(movementDir), 4 },
- { PSF(eFlags), 32 },
- { PSF(eventSequence), 16 },
- { PSF(events[0]), 8 },
- { PSF(events[1]), 8 },
- { PSF(eventParms[0]), -9 },
- { PSF(eventParms[1]), -9 },
- { PSF(externalEvent), 8 },
- { PSF(externalEventParm), 8 },
- { PSF(clientNum), 32 },
- { PSF(weapon), 5 },
- { PSF(weaponstate), 4 },
- { PSF(batteryCharge), 16 },
- { PSF(viewangles[0]), 0 },
- { PSF(viewangles[1]), 0 },
- { PSF(viewangles[2]), 0 },
- { PSF(viewheight), -8 },
- { PSF(damageEvent), 8 },
- { PSF(damageYaw), 8 },
- { PSF(damagePitch), -8 },
- { PSF(damageCount), 8 },
- //{ PSF(saberColor), 8 },
- //{ PSF(saberActive), 8 },
- //{ PSF(saberLength), 32 },
- //{ PSF(saberLengthMax), 32 },
- { PSF(forcePowersActive), 32},
- { PSF(saberInFlight), 8 },
- /*{ PSF(vehicleIndex), 32 }, // WOAH, what do we do with this stuff???
- { PSF(vehicleArmor), 32 },
- { PSF(vehicleAngles[0]), 0 },
- { PSF(vehicleAngles[1]), 0 },
- { PSF(vehicleAngles[2]), 0 },*/
- { PSF(viewEntity), 32 },
- { PSF(serverViewOrg[0]), 0 },
- { PSF(serverViewOrg[1]), 0 },
- { PSF(serverViewOrg[2]), 0 },
- };
- /*
- =============
- MSG_WriteDeltaPlayerstate
- =============
- */
- void MSG_WriteDeltaPlayerstate( msg_t *msg, struct playerState_s *from, struct playerState_s *to ) {
- int i;
- playerState_t dummy;
- int statsbits;
- int persistantbits;
- int ammobits;
- int powerupbits;
- int numFields;
- int c;
- const netField_t *field;
- int *fromF, *toF;
- if (!from) {
- from = &dummy;
- memset (&dummy, 0, sizeof(dummy));
- }
- c = msg->cursize;
- numFields = sizeof( playerStateFields ) / sizeof( playerStateFields[0] );
- for ( i = 0, field = playerStateFields ; i < numFields ; i++, field++ ) {
- fromF = (int *)( (byte *)from + field->offset );
- toF = (int *)( (byte *)to + field->offset );
- if ( *fromF == *toF ) {
- MSG_WriteBits( msg, 0, 1 ); // no change
- continue;
- }
- MSG_WriteBits( msg, 1, 1 ); // changed
- MSG_WriteField (msg, toF, field);
- }
- c = msg->cursize - c;
- //
- // send the arrays
- //
- statsbits = 0;
- for (i=0 ; i<MAX_STATS ; i++) {
- if (to->stats[i] != from->stats[i]) {
- statsbits |= 1<<i;
- }
- }
- if ( statsbits ) {
- MSG_WriteBits( msg, 1, 1 ); // changed
- MSG_WriteShort( msg, statsbits );
- for (i=0 ; i<MAX_STATS ; i++)
- if (statsbits & (1<<i) )
- MSG_WriteBits(msg, to->stats[i], 32);
- } else {
- MSG_WriteBits( msg, 0, 1 ); // no change
- }
- persistantbits = 0;
- for (i=0 ; i<MAX_PERSISTANT ; i++) {
- if (to->persistant[i] != from->persistant[i]) {
- persistantbits |= 1<<i;
- }
- }
- if ( persistantbits ) {
- MSG_WriteBits( msg, 1, 1 ); // changed
- MSG_WriteShort( msg, persistantbits );
- for (i=0 ; i<MAX_PERSISTANT ; i++)
- if (persistantbits & (1<<i) )
- MSG_WriteSShort (msg, to->persistant[i]);
- } else {
- MSG_WriteBits( msg, 0, 1 ); // no change
- }
- ammobits = 0;
- for (i=0 ; i<MAX_AMMO ; i++) {
- if (to->ammo[i] != from->ammo[i]) {
- ammobits |= 1<<i;
- }
- }
- if ( ammobits ) {
- MSG_WriteBits( msg, 1, 1 ); // changed
- MSG_WriteShort( msg, ammobits );
- for (i=0 ; i<MAX_AMMO ; i++)
- if (ammobits & (1<<i) )
- MSG_WriteSShort (msg, to->ammo[i]);
- } else {
- MSG_WriteBits( msg, 0, 1 ); // no change
- }
- powerupbits = 0;
- for (i=0 ; i<MAX_POWERUPS ; i++) {
- if (to->powerups[i] != from->powerups[i]) {
- powerupbits |= 1<<i;
- }
- }
- if ( powerupbits ) {
- MSG_WriteBits( msg, 1, 1 ); // changed
- MSG_WriteShort( msg, powerupbits );
- for (i=0 ; i<MAX_POWERUPS ; i++)
- if (powerupbits & (1<<i) )
- MSG_WriteLong( msg, to->powerups[i] );
- } else {
- MSG_WriteBits( msg, 0, 1 ); // no change
- }
- statsbits = 0;
- for (i=0 ; i<MAX_INVENTORY ; i++)
- {
- if (to->inventory[i] != from->inventory[i])
- {
- statsbits |= 1<<i;
- }
- }
- if ( statsbits )
- {
- MSG_WriteBits( msg, 1, 1 ); // changed
- MSG_WriteShort( msg, statsbits );
- for (i=0 ; i<MAX_INVENTORY ; i++)
- {
- if (statsbits & (1<<i) )
- {
- MSG_WriteShort (msg, to->inventory[i]);
- }
- }
- }
- else
- {
- MSG_WriteBits( msg, 0, 1 ); // no change
- }
- }
- /*
- ===================
- MSG_ReadDeltaPlayerstate
- ===================
- */
- void MSG_ReadDeltaPlayerstate (msg_t *msg, playerState_t *from, playerState_t *to ) {
- int i;
- int bits;
- const netField_t *field;
- int numFields;
- int startBit, endBit;
- int print;
- int *fromF, *toF;
- playerState_t dummy;
- if ( !from ) {
- from = &dummy;
- memset( &dummy, 0, sizeof( dummy ) );
- }
- *to = *from;
- if ( msg->bit == 0 ) {
- startBit = msg->readcount * 8 - GENTITYNUM_BITS;
- } else {
- startBit = ( msg->readcount - 1 ) * 8 + msg->bit - GENTITYNUM_BITS;
- }
- // shownet 2/3 will interleave with other printed info, -2 will
- // just print the delta records
- if ( cl_shownet->integer >= 2 || cl_shownet->integer == -2 ) {
- print = 1;
- Com_Printf( "%3i: playerstate ", msg->readcount );
- } else {
- print = 0;
- }
- numFields = sizeof( playerStateFields ) / sizeof( playerStateFields[0] );
- for ( i = 0, field = playerStateFields ; i < numFields ; i++, field++ ) {
- fromF = (int *)( (byte *)from + field->offset );
- toF = (int *)( (byte *)to + field->offset );
- if ( ! MSG_ReadBits( msg, 1 ) ) {
- // no change
- *toF = *fromF;
- } else {
- MSG_ReadField( msg, toF, field, print);
- }
- }
- // read the arrays
- // parse stats
- if ( MSG_ReadBits( msg, 1 ) ) {
- LOG("PS_STATS");
- bits = MSG_ReadShort (msg);
- for (i=0 ; i<MAX_STATS ; i++) {
- if (bits & (1<<i) ) {
- to->stats[i] = MSG_ReadBits(msg,32);
- }
- }
- }
- // parse persistant stats
- if ( MSG_ReadBits( msg, 1 ) ) {
- LOG("PS_PERSISTANT");
- bits = MSG_ReadShort (msg);
- for (i=0 ; i<MAX_PERSISTANT ; i++) {
- if (bits & (1<<i) ) {
- to->persistant[i] = MSG_ReadSShort(msg);
- }
- }
- }
- // parse ammo
- if ( MSG_ReadBits( msg, 1 ) ) {
- LOG("PS_AMMO");
- bits = MSG_ReadShort (msg);
- for (i=0 ; i<MAX_AMMO ; i++) {
- if (bits & (1<<i) ) {
- to->ammo[i] = MSG_ReadSShort(msg);
- }
- }
- }
- // parse powerups
- if ( MSG_ReadBits( msg, 1 ) ) {
- LOG("PS_POWERUPS");
- bits = MSG_ReadShort (msg);
- for (i=0 ; i<MAX_POWERUPS ; i++) {
- if (bits & (1<<i) ) {
- to->powerups[i] = MSG_ReadLong(msg);
- }
- }
- }
- // parse inventory
- if ( MSG_ReadBits( msg, 1 ) ) {
- LOG("PS_INVENTORY");
- bits = MSG_ReadShort (msg);
- for (i=0 ; i<MAX_INVENTORY ; i++) {
- if (bits & (1<<i) ) {
- to->inventory[i] = MSG_ReadShort(msg);
- }
- }
- }
- if ( print ) {
- if ( msg->bit == 0 ) {
- endBit = msg->readcount * 8 - GENTITYNUM_BITS;
- } else {
- endBit = ( msg->readcount - 1 ) * 8 + msg->bit - GENTITYNUM_BITS;
- }
- Com_Printf( " (%i bits)\n", endBit - startBit );
- }
- }
- //===========================================================================
|