#include "../game/q_shared.h"
#include "qcommon.h"
Include dependency graph for msg.c:

Go to the source code of this file.
Data Structures | |
| struct | netField_t |
Defines | |
| #define | CM_ANGLE1 (1<<0) |
| #define | CM_ANGLE2 (1<<1) |
| #define | CM_ANGLE3 (1<<2) |
| #define | CM_BUTTONS (1<<6) |
| #define | CM_FORWARD (1<<3) |
| #define | CM_SIDE (1<<4) |
| #define | CM_UP (1<<5) |
| #define | CM_WEAPON (1<<7) |
| #define | FLOAT_INT_BIAS (1<<(FLOAT_INT_BITS-1)) |
| #define | FLOAT_INT_BITS 13 |
| #define | LOG(x) if( cl_shownet->integer == 4 ) { Com_Printf("%s ", x ); }; |
| #define | NETF(x) #x,(int)&((entityState_t*)0)->x |
| #define | PSF(x) #x,(int)&((playerState_t*)0)->x |
Functions | |
| void | MSG_BeginReading (msg_t *msg) |
| void | MSG_BeginReadingOOB (msg_t *msg) |
| void | MSG_Bitstream (msg_t *buf) |
| void | MSG_Clear (msg_t *buf) |
| void | MSG_Copy (msg_t *buf, byte *data, int length, msg_t *src) |
| void | MSG_Init (msg_t *buf, byte *data, int length) |
| void | MSG_initHuffman () |
| void | MSG_InitOOB (msg_t *buf, byte *data, int length) |
| float | MSG_ReadAngle16 (msg_t *msg) |
| char * | MSG_ReadBigString (msg_t *msg) |
| int | MSG_ReadBits (msg_t *msg, int bits) |
| int | MSG_ReadByte (msg_t *msg) |
| int | MSG_ReadChar (msg_t *msg) |
| void | MSG_ReadData (msg_t *msg, void *data, int len) |
| int | MSG_ReadDelta (msg_t *msg, int oldV, int bits) |
| void | MSG_ReadDeltaEntity (msg_t *msg, entityState_t *from, entityState_t *to, int number) |
| float | MSG_ReadDeltaFloat (msg_t *msg, float oldV) |
| int | MSG_ReadDeltaKey (msg_t *msg, int key, int oldV, int bits) |
| float | MSG_ReadDeltaKeyFloat (msg_t *msg, int key, float oldV) |
| void | MSG_ReadDeltaPlayerstate (msg_t *msg, playerState_t *from, playerState_t *to) |
| void | MSG_ReadDeltaUsercmd (msg_t *msg, usercmd_t *from, usercmd_t *to) |
| void | MSG_ReadDeltaUsercmdKey (msg_t *msg, int key, usercmd_t *from, usercmd_t *to) |
| float | MSG_ReadFloat (msg_t *msg) |
| int | MSG_ReadLong (msg_t *msg) |
| int | MSG_ReadShort (msg_t *msg) |
| char * | MSG_ReadString (msg_t *msg) |
| char * | MSG_ReadStringLine (msg_t *msg) |
| void | MSG_ReportChangeVectors_f (void) |
| void | MSG_WriteAngle (msg_t *sb, float f) |
| void | MSG_WriteAngle16 (msg_t *sb, float f) |
| void | MSG_WriteBigString (msg_t *sb, const char *s) |
| void | MSG_WriteBits (msg_t *msg, int value, int bits) |
| void | MSG_WriteByte (msg_t *sb, int c) |
| void | MSG_WriteChar (msg_t *sb, int c) |
| void | MSG_WriteData (msg_t *buf, const void *data, int length) |
| void | MSG_WriteDelta (msg_t *msg, int oldV, int newV, int bits) |
| void | MSG_WriteDeltaEntity (msg_t *msg, struct entityState_s *from, struct entityState_s *to, qboolean force) |
| void | MSG_WriteDeltaFloat (msg_t *msg, float oldV, float newV) |
| void | MSG_WriteDeltaKey (msg_t *msg, int key, int oldV, int newV, int bits) |
| void | MSG_WriteDeltaKeyFloat (msg_t *msg, int key, float oldV, float newV) |
| void | MSG_WriteDeltaPlayerstate (msg_t *msg, struct playerState_s *from, struct playerState_s *to) |
| void | MSG_WriteDeltaUsercmd (msg_t *msg, usercmd_t *from, usercmd_t *to) |
| void | MSG_WriteDeltaUsercmdKey (msg_t *msg, int key, usercmd_t *from, usercmd_t *to) |
| void | MSG_WriteFloat (msg_t *sb, float f) |
| void | MSG_WriteLong (msg_t *sb, int c) |
| void | MSG_WriteShort (msg_t *sb, int c) |
| void | MSG_WriteString (msg_t *sb, const char *s) |
Variables | |
| cvar_t * | cl_shownet |
| netField_t | entityStateFields [] |
| int | kbitmask [32] |
| int | msg_hData [256] |
| huffman_t | msgHuff |
| qboolean | msgInit = qfalse |
| int | oldsize = 0 |
| int | overflows |
| int | pcount [256] |
| netField_t | playerStateFields [] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Definition at line 845 of file msg.c. Referenced by MSG_WriteDeltaEntity(), and MSG_WriteDeltaPlayerstate(). |
|
|
Definition at line 844 of file msg.c. Referenced by MSG_ReadDeltaEntity(), MSG_ReadDeltaPlayerstate(), MSG_WriteDeltaEntity(), and MSG_WriteDeltaPlayerstate(). |
|
|
Definition at line 527 of file msg.c. Referenced by main(), and MSG_ReadDeltaPlayerstate(). |
|
|
|
|
|
|
|
|
Definition at line 74 of file msg.c. References msg_t::bit, msg_t::oob, and msg_t::readcount.
|
|
|
Definition at line 80 of file msg.c. References msg_t::bit, msg_t::oob, and msg_t::readcount. Referenced by CL_ConnectionlessPacket(), Netchan_Process(), SV_ConnectionlessPacket(), and SV_PacketEvent().
|
|
|
Definition at line 70 of file msg.c. References msg_t::oob. Referenced by CL_ParseServerMessage(), CL_Record_f(), CL_WritePacket(), and SV_ExecuteClientMessage(). 00070 {
00071 buf->oob = qfalse;
00072 }
|
|
|
Definition at line 63 of file msg.c. References msg_t::bit, msg_t::cursize, and msg_t::overflowed. Referenced by SV_SendClientSnapshot(). 00063 {
00064 buf->cursize = 0;
00065 buf->overflowed = qfalse;
00066 buf->bit = 0; //<- in bits
00067 }
|
|
||||||||||||||||||||
|
Definition at line 86 of file msg.c. References byte, Com_Error(), Com_Memcpy(), msg_t::data, ERR_DROP, length(), and src. Referenced by SV_Netchan_Transmit(). 00087 {
00088 if (length<src->cursize) {
00089 Com_Error( ERR_DROP, "MSG_Copy: can't copy into a smaller msg_t buffer");
00090 }
00091 Com_Memcpy(buf, src, sizeof(msg_t));
00092 buf->data = data;
00093 Com_Memcpy(buf->data, src->data, src->cursize);
00094 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 44 of file msg.c. References byte, Com_Memset(), and MSG_initHuffman(). Referenced by CL_ReadDemoMessage(), CL_Record_f(), CL_WritePacket(), Com_EventLoop(), SV_SendClientGameState(), SV_SendClientSnapshot(), and Sys_GetEvent(). 00044 {
00045 if (!msgInit) {
00046 MSG_initHuffman();
00047 }
00048 Com_Memset (buf, 0, sizeof(*buf));
00049 buf->data = data;
00050 buf->maxsize = length;
00051 }
|
Here is the call graph for this function:

|
|
Definition at line 1709 of file msg.c. References byte, huffman_t::compressor, huffman_t::decompressor, Huff_addRef(), Huff_Init(), i, j, msg_hData, msgHuff, and msgInit. Referenced by MSG_Init(), and MSG_InitOOB(). 01709 {
01710 int i,j;
01711
01712 msgInit = qtrue;
01713 Huff_Init(&msgHuff);
01714 for(i=0;i<256;i++) {
01715 for (j=0;j<msg_hData[i];j++) {
01716 Huff_addRef(&msgHuff.compressor, (byte)i); // Do update
01717 Huff_addRef(&msgHuff.decompressor, (byte)i); // Do update
01718 }
01719 }
01720 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 53 of file msg.c. References byte, Com_Memset(), and MSG_initHuffman(). Referenced by Netchan_Transmit(), and Netchan_TransmitNextFragment(). 00053 {
00054 if (!msgInit) {
00055 MSG_initHuffman();
00056 }
00057 Com_Memset (buf, 0, sizeof(*buf));
00058 buf->data = data;
00059 buf->maxsize = length;
00060 buf->oob = qtrue;
00061 }
|
Here is the call graph for this function:

|
|
Definition at line 504 of file msg.c. References MSG_ReadShort(), and SHORT2ANGLE. 00504 {
00505 return SHORT2ANGLE(MSG_ReadShort(msg));
00506 }
|
Here is the call graph for this function:

|
|
Definition at line 457 of file msg.c. References c, l, MSG_ReadByte(), and string(). Referenced by CL_ParseGamestate(). 00457 {
00458 static char string[BIG_INFO_STRING];
00459 int l,c;
00460
00461 l = 0;
00462 do {
00463 c = MSG_ReadByte(msg); // use ReadByte so -1 is out of bounds
00464 if ( c == -1 || c == 0 ) {
00465 break;
00466 }
00467 // translate all fmt spec to avoid crash bugs
00468 if ( c == '%' ) {
00469 c = '.';
00470 }
00471
00472 string[l] = c;
00473 l++;
00474 } while (l < sizeof(string)-1);
00475
00476 string[l] = 0;
00477
00478 return string;
00479 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 184 of file msg.c. References msg_t::bit, bits, Com_Error(), msg_t::data, huffman_t::decompressor, ERR_DROP, Huff_getBit(), Huff_offsetReceive(), i, LittleLong(), LittleShort(), msgHuff, msg_t::oob, qboolean, msg_t::readcount, huff_t::tree, and value. Referenced by CL_ParseGamestate(), CL_ParsePacketEntities(), MSG_ReadByte(), MSG_ReadChar(), MSG_ReadDelta(), MSG_ReadDeltaEntity(), MSG_ReadDeltaFloat(), MSG_ReadDeltaKey(), MSG_ReadDeltaKeyFloat(), MSG_ReadDeltaPlayerstate(), MSG_ReadDeltaUsercmd(), MSG_ReadDeltaUsercmdKey(), MSG_ReadFloat(), MSG_ReadLong(), and MSG_ReadShort(). 00184 {
00185 int value;
00186 int get;
00187 qboolean sgn;
00188 int i, nbits;
00189 // FILE* fp;
00190
00191 value = 0;
00192
00193 if ( bits < 0 ) {
00194 bits = -bits;
00195 sgn = qtrue;
00196 } else {
00197 sgn = qfalse;
00198 }
00199
00200 if (msg->oob) {
00201 if (bits==8) {
00202 value = msg->data[msg->readcount];
00203 msg->readcount += 1;
00204 msg->bit += 8;
00205 } else if (bits==16) {
00206 unsigned short *sp = (unsigned short *)&msg->data[msg->readcount];
00207 value = LittleShort(*sp);
00208 msg->readcount += 2;
00209 msg->bit += 16;
00210 } else if (bits==32) {
00211 unsigned int *ip = (unsigned int *)&msg->data[msg->readcount];
00212 value = LittleLong(*ip);
00213 msg->readcount += 4;
00214 msg->bit += 32;
00215 } else {
00216 Com_Error(ERR_DROP, "can't read %d bits\n", bits);
00217 }
00218 } else {
00219 nbits = 0;
00220 if (bits&7) {
00221 nbits = bits&7;
00222 for(i=0;i<nbits;i++) {
00223 value |= (Huff_getBit(msg->data, &msg->bit)<<i);
00224 }
00225 bits = bits - nbits;
00226 }
00227 if (bits) {
00228 // fp = fopen("c:\\netchan.bin", "a");
00229 for(i=0;i<bits;i+=8) {
00230 Huff_offsetReceive (msgHuff.decompressor.tree, &get, msg->data, &msg->bit);
00231 // fwrite(&get, 1, 1, fp);
00232 value |= (get<<(i+nbits));
00233 }
00234 // fclose(fp);
00235 }
00236 msg->readcount = (msg->bit>>3)+1;
00237 }
00238 if ( sgn ) {
00239 if ( value & ( 1 << ( bits - 1 ) ) ) {
00240 value |= -1 ^ ( ( 1 << bits ) - 1 );
00241 }
00242 }
00243
00244 return value;
00245 }
|
Here is the call graph for this function:

|
|
Definition at line 382 of file msg.c. References c, msg_t::cursize, MSG_ReadBits(), and msg_t::readcount. Referenced by CL_ParseGamestate(), CL_ParseServerMessage(), CL_ParseSnapshot(), MSG_ReadBigString(), MSG_ReadData(), MSG_ReadDeltaEntity(), MSG_ReadDeltaPlayerstate(), MSG_ReadString(), MSG_ReadStringLine(), SV_ExecuteClientMessage(), and SV_UserMove(). 00382 {
00383 int c;
00384
00385 c = (unsigned char)MSG_ReadBits( msg, 8 );
00386 if ( msg->readcount > msg->cursize ) {
00387 c = -1;
00388 }
00389 return c;
00390 }
|
Here is the call graph for this function:

|
|
Definition at line 371 of file msg.c. References c, msg_t::cursize, MSG_ReadBits(), and msg_t::readcount. 00371 {
00372 int c;
00373
00374 c = (signed char)MSG_ReadBits( msg, 8 );
00375 if ( msg->readcount > msg->cursize ) {
00376 c = -1;
00377 }
00378
00379 return c;
00380 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 508 of file msg.c. References byte, i, and MSG_ReadByte(). Referenced by CL_ParseDownload(), and CL_ParseSnapshot(). 00508 {
00509 int i;
00510
00511 for (i=0 ; i<len ; i++) {
00512 ((byte *)data)[i] = MSG_ReadByte (msg);
00513 }
00514 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 538 of file msg.c. References bits, and MSG_ReadBits(). Referenced by MSG_ReadDeltaUsercmd(). 00538 {
00539 if ( MSG_ReadBits( msg, 1 ) ) {
00540 return MSG_ReadBits( msg, bits );
00541 }
00542 return oldV;
00543 }
|
Here is the call graph for this function:

|
||||||||||||||||||||
|
Definition at line 977 of file msg.c. References msg_t::bit, byte, cl_shownet, Com_Error(), Com_Memset(), Com_Printf(), entityState_t, entityStateFields, ERR_DROP, field(), FLOAT_INT_BITS, i, cvar_s::integer, MAX_GENTITIES, MSG_ReadBits(), MSG_ReadByte(), number, entityState_s::number, print(), and msg_t::readcount. Referenced by CL_DeltaEntity(), and CL_ParseGamestate(). 00978 {
00979 int i, lc;
00980 int numFields;
00981 netField_t *field;
00982 int *fromF, *toF;
00983 int print;
00984 int trunc;
00985 int startBit, endBit;
00986
00987 if ( number < 0 || number >= MAX_GENTITIES) {
00988 Com_Error( ERR_DROP, "Bad delta entity number: %i", number );
00989 }
00990
00991 if ( msg->bit == 0 ) {
00992 startBit = msg->readcount * 8 - GENTITYNUM_BITS;
00993 } else {
00994 startBit = ( msg->readcount - 1 ) * 8 + msg->bit - GENTITYNUM_BITS;
00995 }
00996
00997 // check for a remove
00998 if ( MSG_ReadBits( msg, 1 ) == 1 ) {
00999 Com_Memset( to, 0, sizeof( *to ) );
01000 to->number = MAX_GENTITIES - 1;
01001 if ( cl_shownet->integer >= 2 || cl_shownet->integer == -1 ) {
01002 Com_Printf( "%3i: #%-3i remove\n", msg->readcount, number );
01003 }
01004 return;
01005 }
01006
01007 // check for no delta
01008 if ( MSG_ReadBits( msg, 1 ) == 0 ) {
01009 *to = *from;
01010 to->number = number;
01011 return;
01012 }
01013
01014 numFields = sizeof(entityStateFields)/sizeof(entityStateFields[0]);
01015 lc = MSG_ReadByte(msg);
01016
01017 // shownet 2/3 will interleave with other printed info, -1 will
01018 // just print the delta records`
01019 if ( cl_shownet->integer >= 2 || cl_shownet->integer == -1 ) {
01020 print = 1;
01021 Com_Printf( "%3i: #%-3i ", msg->readcount, to->number );
01022 } else {
01023 print = 0;
01024 }
01025
01026 to->number = number;
01027
01028 for ( i = 0, field = entityStateFields ; i < lc ; i++, field++ ) {
01029 fromF = (int *)( (byte *)from + field->offset );
01030 toF = (int *)( (byte *)to + field->offset );
01031
01032 if ( ! MSG_ReadBits( msg, 1 ) ) {
01033 // no change
01034 *toF = *fromF;
01035 } else {
01036 if ( field->bits == 0 ) {
01037 // float
01038 if ( MSG_ReadBits( msg, 1 ) == 0 ) {
01039 *(float *)toF = 0.0f;
01040 } else {
01041 if ( MSG_ReadBits( msg, 1 ) == 0 ) {
01042 // integral float
01043 trunc = MSG_ReadBits( msg, FLOAT_INT_BITS );
01044 // bias to allow equal parts positive and negative
01045 trunc -= FLOAT_INT_BIAS;
01046 *(float *)toF = trunc;
01047 if ( print ) {
01048 Com_Printf( "%s:%i ", field->name, trunc );
01049 }
01050 } else {
01051 // full floating point value
01052 *toF = MSG_ReadBits( msg, 32 );
01053 if ( print ) {
01054 Com_Printf( "%s:%f ", field->name, *(float *)toF );
01055 }
01056 }
01057 }
01058 } else {
01059 if ( MSG_ReadBits( msg, 1 ) == 0 ) {
01060 *toF = 0;
01061 } else {
01062 // integer
01063 *toF = MSG_ReadBits( msg, field->bits );
01064 if ( print ) {
01065 Com_Printf( "%s:%i ", field->name, *toF );
01066 }
01067 }
01068 }
01069 // pcount[i]++;
01070 }
01071 }
01072 for ( i = lc, field = &entityStateFields[lc] ; i < numFields ; i++, field++ ) {
01073 fromF = (int *)( (byte *)from + field->offset );
01074 toF = (int *)( (byte *)to + field->offset );
01075 // no change
01076 *toF = *fromF;
01077 }
01078
01079 if ( print ) {
01080 if ( msg->bit == 0 ) {
01081 endBit = msg->readcount * 8 - GENTITYNUM_BITS;
01082 } else {
01083 endBit = ( msg->readcount - 1 ) * 8 + msg->bit - GENTITYNUM_BITS;
01084 }
01085 Com_Printf( " (%i bits)\n", endBit - startBit );
01086 }
01087 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 554 of file msg.c. References MSG_ReadBits(). 00554 {
00555 if ( MSG_ReadBits( msg, 1 ) ) {
00556 float newV;
00557
00558 *(int *)&newV = MSG_ReadBits( msg, 32 );
00559 return newV;
00560 }
00561 return oldV;
00562 }
|
Here is the call graph for this function:

|
||||||||||||||||||||
|
Definition at line 592 of file msg.c. References bits, kbitmask, and MSG_ReadBits(). Referenced by MSG_ReadDeltaUsercmdKey(). 00592 {
00593 if ( MSG_ReadBits( msg, 1 ) ) {
00594 return MSG_ReadBits( msg, bits ) ^ (key & kbitmask[bits]);
00595 }
00596 return oldV;
00597 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 608 of file msg.c. References MSG_ReadBits(). 00608 {
00609 if ( MSG_ReadBits( msg, 1 ) ) {
00610 float newV;
00611
00612 *(int *)&newV = MSG_ReadBits( msg, 32 ) ^ key;
00613 return newV;
00614 }
00615 return oldV;
00616 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 1315 of file msg.c. References playerState_s::ammo, msg_t::bit, bits, byte, cl_shownet, Com_Memset(), Com_Printf(), field(), FLOAT_INT_BITS, i, cvar_s::integer, LOG, MSG_ReadBits(), MSG_ReadByte(), MSG_ReadLong(), MSG_ReadShort(), playerState_s::persistant, playerState_t, playerStateFields, playerState_s::powerups, print(), msg_t::readcount, and playerState_s::stats. 01315 {
01316 int i, lc;
01317 int bits;
01318 netField_t *field;
01319 int numFields;
01320 int startBit, endBit;
01321 int print;
01322 int *fromF, *toF;
01323 int trunc;
01324 playerState_t dummy;
01325
01326 if ( !from ) {
01327 from = &dummy;
01328 Com_Memset( &dummy, 0, sizeof( dummy ) );
01329 }
01330 *to = *from;
01331
01332 if ( msg->bit == 0 ) {
01333 startBit = msg->readcount * 8 - GENTITYNUM_BITS;
01334 } else {
01335 startBit = ( msg->readcount - 1 ) * 8 + msg->bit - GENTITYNUM_BITS;
01336 }
01337
01338 // shownet 2/3 will interleave with other printed info, -2 will
01339 // just print the delta records
01340 if ( cl_shownet->integer >= 2 || cl_shownet->integer == -2 ) {
01341 print = 1;
01342 Com_Printf( "%3i: playerstate ", msg->readcount );
01343 } else {
01344 print = 0;
01345 }
01346
01347 numFields = sizeof( playerStateFields ) / sizeof( playerStateFields[0] );
01348 lc = MSG_ReadByte(msg);
01349
01350 for ( i = 0, field = playerStateFields ; i < lc ; i++, field++ ) {
01351 fromF = (int *)( (byte *)from + field->offset );
01352 toF = (int *)( (byte *)to + field->offset );
01353
01354 if ( ! MSG_ReadBits( msg, 1 ) ) {
01355 // no change
01356 *toF = *fromF;
01357 } else {
01358 if ( field->bits == 0 ) {
01359 // float
01360 if ( MSG_ReadBits( msg, 1 ) == 0 ) {
01361 // integral float
01362 trunc = MSG_ReadBits( msg, FLOAT_INT_BITS );
01363 // bias to allow equal parts positive and negative
01364 trunc -= FLOAT_INT_BIAS;
01365 *(float *)toF = trunc;
01366 if ( print ) {
01367 Com_Printf( "%s:%i ", field->name, trunc );
01368 }
01369 } else {
01370 // full floating point value
01371 *toF = MSG_ReadBits( msg, 32 );
01372 if ( print ) {
01373 Com_Printf( "%s:%f ", field->name, *(float *)toF );
01374 }
01375 }
01376 } else {
01377 // integer
01378 *toF = MSG_ReadBits( msg, field->bits );
01379 if ( print ) {
01380 Com_Printf( "%s:%i ", field->name, *toF );
01381 }
01382 }
01383 }
01384 }
01385 for ( i=lc,field = &playerStateFields[lc];i<numFields; i++, field++) {
01386 fromF = (int *)( (byte *)from + field->offset );
01387 toF = (int *)( (byte *)to + field->offset );
01388 // no change
01389 *toF = *fromF;
01390 }
01391
01392
01393 // read the arrays
01394 if (MSG_ReadBits( msg, 1 ) ) {
01395 // parse stats
01396 if ( MSG_ReadBits( msg, 1 ) ) {
01397 LOG("PS_STATS");
01398 bits = MSG_ReadShort (msg);
01399 for (i=0 ; i<16 ; i++) {
01400 if (bits & (1<<i) ) {
01401 to->stats[i] = MSG_ReadShort(msg);
01402 }
01403 }
01404 }
01405
01406 // parse persistant stats
01407 if ( MSG_ReadBits( msg, 1 ) ) {
01408 LOG("PS_PERSISTANT");
01409 bits = MSG_ReadShort (msg);
01410 for (i=0 ; i<16 ; i++) {
01411 if (bits & (1<<i) ) {
01412 to->persistant[i] = MSG_ReadShort(msg);
01413 }
01414 }
01415 }
01416
01417 // parse ammo
01418 if ( MSG_ReadBits( msg, 1 ) ) {
01419 LOG("PS_AMMO");
01420 bits = MSG_ReadShort (msg);
01421 for (i=0 ; i<16 ; i++) {
01422 if (bits & (1<<i) ) {
01423 to->ammo[i] = MSG_ReadShort(msg);
01424 }
01425 }
01426 }
01427
01428 // parse powerups
01429 if ( MSG_ReadBits( msg, 1 ) ) {
01430 LOG("PS_POWERUPS");
01431 bits = |