- fixed net_packetlog to use Con_Printf when there's no logfile open,

rather than a stdout hack (which had problems with buffering)
- actually parse net_deltapacketentities
- print offset within net_{,delta}packetentities blocks for each
  entity
- fix indenting in Log_Delta
- fix off-by-one for packet offset printing
- fix a miss-parsing of svc_deltapacketentities
  (MAX_PACKET_ENTITIES does NOT include U_REMOVE entities)
- remove "full update" handling for CL_ParseDeltaPacketEntities, since
  that only happens with svc_packetentities
This commit is contained in:
Adam Olsen 2001-10-29 00:32:16 +00:00
parent 3ce8029f74
commit 36b8256b3a
4 changed files with 151 additions and 145 deletions

View file

@ -185,15 +185,17 @@ typedef struct net_svc_delta_s
typedef struct net_svc_packetentities_s typedef struct net_svc_packetentities_s
{ {
int num; int numwords, numdeltas;
net_svc_delta_t vars[MAX_PACKET_ENTITIES + 1]; unsigned short words[MAX_EDICTS];
entity_state_t deltas[MAX_PACKET_ENTITIES];
} net_svc_packetentities_t; } net_svc_packetentities_t;
typedef struct net_svc_deltapacketentities_s typedef struct net_svc_deltapacketentities_s
{ {
int num; int numwords, numdeltas;
byte from; byte from;
net_svc_delta_t vars[MAX_PACKET_ENTITIES + 1]; unsigned short words[MAX_EDICTS];
entity_state_t deltas[MAX_PACKET_ENTITIES];
} net_svc_deltapacketentities_t; } net_svc_deltapacketentities_t;
qboolean NET_SVC_Print_Parse (net_svc_print_t *block, msg_t *msg); qboolean NET_SVC_Print_Parse (net_svc_print_t *block, msg_t *msg);

View file

@ -194,11 +194,11 @@ CL_ParsePacketEntities (void)
return; return;
} }
for (index = 0; block.vars[index].word; index++) { for (index = 0; block.words[index]; index++) {
if (block.vars[index].word & U_REMOVE) { if (block.words[index] & U_REMOVE) {
cl.validsequence = 0; cl.validsequence = 0;
Host_NetError ("CL_ParsePacketEntities: WARNING: U_REMOVE " Host_NetError ("CL_ParsePacketEntities: U_REMOVE on full "
"on full update\n"); "update\n");
return; return;
} }
@ -208,11 +208,11 @@ CL_ParsePacketEntities (void)
return; return;
} }
newp->entities[index] = cl_baselines[block.vars[index].word & 511]; newp->entities[index] = cl_baselines[block.words[index] & 511];
CL_EntityState_Copy (&block.vars[index].state, CL_EntityState_Copy (&block.deltas[index],
&newp->entities[index], &newp->entities[index],
block.vars[index].state.flags); block.deltas[index].flags);
newp->entities[index].number = block.vars[index].state.number; newp->entities[index].number = block.deltas[index].number;
if (newp->entities[index].modelindex >= MAX_MODELS) { if (newp->entities[index].modelindex >= MAX_MODELS) {
Host_NetError ("CL_ParsePacketEntities: modelindex %i >= " Host_NetError ("CL_ParsePacketEntities: modelindex %i >= "
"MAX_MODELS", newp->entities[index].modelindex); "MAX_MODELS", newp->entities[index].modelindex);
@ -233,11 +233,11 @@ CL_ParsePacketEntities (void)
void void
CL_ParseDeltaPacketEntities () CL_ParseDeltaPacketEntities ()
{ {
int i; int oldindex = 0, newindex = 0;
byte from; int wordindex = 0, deltaindex = 0;
int oldindex, newindex, newnum, oldnum, oldpacket, newpacket; int oldnum, newnum;
packet_entities_t *oldp, *newp, dummy; int oldpacket, newpacket;
qboolean full = false; packet_entities_t *oldp, *newp;
net_svc_deltapacketentities_t block; net_svc_deltapacketentities_t block;
if (NET_SVC_DeltaPacketEntities_Parse (&block, net_message)) { if (NET_SVC_DeltaPacketEntities_Parse (&block, net_message)) {
@ -249,14 +249,16 @@ CL_ParseDeltaPacketEntities ()
newp = &cl.frames[newpacket].packet_entities; newp = &cl.frames[newpacket].packet_entities;
cl.frames[newpacket].invalid = false; cl.frames[newpacket].invalid = false;
from = block.from;
oldpacket = cl.frames[newpacket].delta_sequence; oldpacket = cl.frames[newpacket].delta_sequence;
if (oldpacket == -1) {
Host_NetError ("Cl_ParseDeltaPacketEntities: invalid "
"delta_sequence\n");
return;
}
if ((from & UPDATE_MASK) != (oldpacket & UPDATE_MASK)) if ((block.from & UPDATE_MASK) != (oldpacket & UPDATE_MASK))
Con_DPrintf ("CL_ParseDeltaPacketEntities: WARNING: from mismatch\n"); Con_DPrintf ("CL_ParseDeltaPacketEntities: WARNING: from mismatch\n");
if (oldpacket != -1) {
if (cls.netchan.outgoing_sequence - oldpacket >= UPDATE_BACKUP - 1) { if (cls.netchan.outgoing_sequence - oldpacket >= UPDATE_BACKUP - 1) {
// we can't use this, it is too old // we can't use this, it is too old
Con_DPrintf ("FlushEntityPacket\n"); Con_DPrintf ("FlushEntityPacket\n");
@ -265,36 +267,20 @@ CL_ParseDeltaPacketEntities ()
} }
cl.validsequence = cls.netchan.incoming_sequence; cl.validsequence = cls.netchan.incoming_sequence;
oldp = &cl.frames[oldpacket & UPDATE_MASK].packet_entities; oldp = &cl.frames[oldpacket & UPDATE_MASK].packet_entities;
} else { // a full update that we can start delta compressing from now
oldp = &dummy;
dummy.num_entities = 0;
cl.validsequence = cls.netchan.incoming_sequence;
full = true;
Host_NetError ("Full update in CL_ParseDeltaPacketEntities\n");
return;
}
oldindex = 0;
newindex = 0;
newp->num_entities = 0; newp->num_entities = 0;
for (i = 0; block.vars[i].word; i++) { for (; block.words[wordindex];) {
newnum = block.vars[i].word & 511; newnum = block.words[wordindex] & 511;
oldnum = oldindex >= oldp->num_entities ? 9999 : oldnum = oldindex >= oldp->num_entities ? 9999 :
oldp->entities[oldindex].number; oldp->entities[oldindex].number;
while (newnum > oldnum) { while (newnum > oldnum) { // copy one of the old entities
// if (newnum > oldnum) { // over to the new packet unchanged
if (full) {
Con_Printf ("CL_ParseDeltaPacketEntities: WARNING: "
"oldcopy on full update");
return;
}
// Con_Printf ("copy %i\n", oldnum); // Con_Printf ("copy %i\n", oldnum);
// copy one of the old entities over to the new packet unchanged
if (newindex >= MAX_PACKET_ENTITIES) { if (newindex >= MAX_PACKET_ENTITIES) {
Host_NetError ("CL_ParseDeltaPacketEntities: newindex >= " Host_NetError ("CL_ParseDeltaPacketEntities: newindex >= "
"MAX_PACKET_ENTITIES (2nd)"); "MAX_PACKET_ENTITIES (1st)");
return; return;
} }
newp->entities[newindex] = oldp->entities[oldindex]; newp->entities[newindex] = oldp->entities[oldindex];
@ -306,53 +292,48 @@ CL_ParseDeltaPacketEntities ()
if (newnum < oldnum) { // new from baseline if (newnum < oldnum) { // new from baseline
// Con_Printf ("baseline %i\n", newnum); // Con_Printf ("baseline %i\n", newnum);
if (block.vars[i].word & U_REMOVE) { if (block.words[wordindex] & U_REMOVE) {
if (full) { wordindex++;
cl.validsequence = 0;
Host_NetError ("CL_ParseDeltaPacketEntities: "
"U_REMOVE on full update\n");
return;
}
continue; continue;
} }
if (newindex >= MAX_PACKET_ENTITIES) { if (newindex >= MAX_PACKET_ENTITIES) {
Host_NetError ("CL_ParseDeltaPacketEntities: newindex >= " Host_NetError ("CL_ParseDeltaPacketEntities: newindex >= "
"MAX_PACKET_ENTITIES (3rd)"); "MAX_PACKET_ENTITIES (2nd)");
return; return;
} }
newp->entities[newindex] = cl_baselines[newnum]; newp->entities[newindex] = cl_baselines[newnum];
CL_EntityState_Copy (&block.vars[i].state, CL_EntityState_Copy (&block.deltas[deltaindex],
&newp->entities[newindex], &newp->entities[newindex],
block.vars[i].state.flags); block.deltas[deltaindex].flags);
newp->entities[newindex].number = block.vars[i].state.number; newp->entities[newindex].number
= block.deltas[deltaindex].number;
if (newp->entities[newindex].modelindex >= MAX_MODELS) { if (newp->entities[newindex].modelindex >= MAX_MODELS) {
Host_NetError ("CL_ParsePacketEntities: modelindex %i >= " Host_NetError ("CL_ParsePacketEntities: modelindex %i >= "
"MAX_MODELS", "MAX_MODELS",
newp->entities[newindex].modelindex); newp->entities[newindex].modelindex);
return; return;
} }
wordindex++;
deltaindex++;
newindex++; newindex++;
continue; continue;
} }
if (newnum == oldnum) { // delta from previous if (newnum == oldnum) { // delta from previous
if (full) { // Con_Printf ("delta %i\n", newnum);
cl.validsequence = 0; if (block.words[wordindex] & U_REMOVE) { // Clear the entity
Con_Printf ("WARNING: delta on full update"); memset (&cl_packet_ents[newnum], 0, sizeof (entity_t));
} wordindex++;
if (block.vars[i].word & U_REMOVE) { // Clear the entity
entity_t *ent = &cl_packet_ents[newnum];
memset (ent, 0, sizeof (entity_t));
oldindex++; oldindex++;
continue; continue;
} }
// Con_Printf ("delta %i\n", newnum);
newp->entities[newindex] = oldp->entities[oldindex]; newp->entities[newindex] = oldp->entities[oldindex];
CL_EntityState_Copy (&block.vars[i].state, CL_EntityState_Copy (&block.deltas[deltaindex],
&newp->entities[newindex], &newp->entities[newindex],
block.vars[i].state.flags); block.deltas[deltaindex].flags);
newp->entities[newindex].number = block.vars[i].state.number; newp->entities[newindex].number
= block.deltas[deltaindex].number;
if (newp->entities[newindex].modelindex >= MAX_MODELS) { if (newp->entities[newindex].modelindex >= MAX_MODELS) {
Host_NetError ("CL_ParsePacketEntities: modelindex %i >= " Host_NetError ("CL_ParsePacketEntities: modelindex %i >= "
"MAX_MODELS", "MAX_MODELS",
@ -360,6 +341,8 @@ CL_ParseDeltaPacketEntities ()
return; return;
} }
wordindex++;
deltaindex++;
newindex++; newindex++;
oldindex++; oldindex++;
} }

View file

@ -171,7 +171,6 @@ const char *clc_string[] = {
#define svc_particle 18 // [vec3] <variable> #define svc_particle 18 // [vec3] <variable>
#define svc_signonnum 25 // [byte] used for the signon #define svc_signonnum 25 // [byte] used for the signon
// sequence // sequence
static VFile *_stdout;
static VFile *Net_PacketLog; static VFile *Net_PacketLog;
static const char **Net_sound_precache; static const char **Net_sound_precache;
static sizebuf_t _packet; static sizebuf_t _packet;
@ -193,12 +192,11 @@ Net_LogPrintf (char *fmt, ...)
vsnprintf (text, sizeof (text), fmt, argptr); vsnprintf (text, sizeof (text), fmt, argptr);
va_end (argptr); va_end (argptr);
if (!Net_PacketLog) if (Net_PacketLog) {
Net_PacketLog = _stdout;
Qprintf (Net_PacketLog, "%s", text); Qprintf (Net_PacketLog, "%s", text);
Qflush (Net_PacketLog); Qflush (Net_PacketLog);
if (Net_PacketLog == _stdout) } else
Net_PacketLog = NULL; Con_Printf ("%s", text);
} }
int int
@ -308,30 +306,43 @@ Log_Outgoing_Packet (const char *p, int len)
return; return;
} }
void qboolean
Log_Delta(int bits) Log_Delta(int bits)
{ {
entity_state_t to; entity_state_t to;
int i; int i;
Net_LogPrintf ("\n\t"); Net_LogPrintf ("\n\t<%06x> ", MSG_GetReadCount (&packet) - 2);
if (!bits) {
Net_LogPrintf ("End");
return 1;
}
// set everything to the state we are delta'ing from // set everything to the state we are delta'ing from
to.number = bits & 511; to.number = bits & 511;
bits &= ~511; bits &= ~511;
Net_LogPrintf ("Ent: %d", to.number);
if (bits & U_REMOVE)
Net_LogPrintf (" U_REMOVE");
if (bits & U_MOREBITS) { // read in the low order bits if (bits & U_MOREBITS) { // read in the low order bits
i = MSG_ReadByte (&packet); i = MSG_ReadByte (&packet);
bits |= i; bits |= i;
Net_LogPrintf (" U_MOREBITS");
} }
// LordHavoc: Endy neglected to mark this as being part of the QSG // LordHavoc: Endy neglected to mark this as being part of the QSG
// version 2 stuff... // version 2 stuff...
if (bits & U_EXTEND1) { if (bits & U_EXTEND1) {
bits |= MSG_ReadByte (&packet) << 16; bits |= MSG_ReadByte (&packet) << 16;
if (bits & U_EXTEND2) Net_LogPrintf (" U_EXTEND1");
if (bits & U_EXTEND2) {
bits |= MSG_ReadByte (&packet) << 24; bits |= MSG_ReadByte (&packet) << 24;
Net_LogPrintf (" U_EXTEND2");
}
} }
to.flags = bits; to.flags = bits;
@ -390,7 +401,7 @@ Log_Delta(int bits)
Net_LogPrintf(" Uframe2: %d", ((to.frame & 0xFF) | (MSG_ReadByte (&packet) << 8))); Net_LogPrintf(" Uframe2: %d", ((to.frame & 0xFF) | (MSG_ReadByte (&packet) << 8)));
// Ender (QSG - End) // Ender (QSG - End)
return; return 0;
} }
@ -438,7 +449,8 @@ Parse_Server_Packet ()
if (c == -1) if (c == -1)
break; break;
// Net_LogPrintf("\n<%ld,%ld> ",seq1 & 0x7FFFFFFF,seq2 & 0x7FFFFFFF); // Net_LogPrintf("\n<%ld,%ld> ",seq1 & 0x7FFFFFFF,seq2 & 0x7FFFFFFF);
Net_LogPrintf ("<%06x> [0x%02x] ", MSG_GetReadCount (&packet), c); Net_LogPrintf ("<%06x> [0x%02x] ",
MSG_GetReadCount (&packet) - 1, c);
if (c < 53) if (c < 53)
Net_LogPrintf ("%s: ", svc_string[c]); Net_LogPrintf ("%s: ", svc_string[c]);
@ -794,21 +806,19 @@ Parse_Server_Packet ()
else else
Net_LogPrintf ("\n\t*End of sound list*"); Net_LogPrintf ("\n\t*End of sound list*");
break; break;
case svc_deltapacketentities:
Net_LogPrintf ("from: %d", MSG_ReadByte (&packet));
// intentional fallthrough
case svc_packetentities: case svc_packetentities:
while (1) { while (1) {
mask1 = (unsigned short) MSG_ReadShort(&packet); mask1 = (unsigned short) MSG_ReadShort(&packet);
if (packet.badread) { if (packet.badread) {
Net_LogPrintf ("Badread\n"); Net_LogPrintf (" Badread\n");
return; return;
} }
if (!mask1) break; if (Log_Delta(mask1))
if (mask1 & U_REMOVE) Net_LogPrintf("UREMOVE ");
Log_Delta(mask1);
}
break; break;
case svc_deltapacketentities: }
Net_LogPrintf ("idx: %d", MSG_ReadByte (&packet));
return;
break; break;
case svc_maxspeed: case svc_maxspeed:
Net_LogPrintf ("%f", MSG_ReadFloat (&packet)); Net_LogPrintf ("%f", MSG_ReadFloat (&packet));
@ -958,7 +968,7 @@ Net_PacketLog_f (cvar_t *var)
void void
Net_PacketLog_Zap_f (void) Net_PacketLog_Zap_f (void)
{ {
if (Net_PacketLog && Net_PacketLog != _stdout) { if (Net_PacketLog) {
Con_Printf ("truncating packet logfile: %s\n", "qfpacket.log"); Con_Printf ("truncating packet logfile: %s\n", "qfpacket.log");
Qseek (Net_PacketLog, 0, 0); Qseek (Net_PacketLog, 0, 0);
Qwrite (Net_PacketLog, 0, 0); Qwrite (Net_PacketLog, 0, 0);
@ -976,8 +986,6 @@ Net_Log_Init (const char **sound_precache)
{ {
Net_sound_precache = sound_precache; Net_sound_precache = sound_precache;
_stdout = Qdopen (1, "wt"); // create a QFile of stdout
net_packetlog = Cvar_Get ("net_packetlog", "0", CVAR_NONE, Net_PacketLog_f, net_packetlog = Cvar_Get ("net_packetlog", "0", CVAR_NONE, Net_PacketLog_f,
"enable/disable packet logging"); "enable/disable packet logging");

View file

@ -405,22 +405,13 @@ NET_SVC_Soundlist_Parse (net_svc_soundlist_t *block, msg_t *msg)
} }
// this is a sub-block, not a real block // this is a sub-block, not a real block
qboolean void
NET_SVC_Delta_Parse (net_svc_delta_t *subblock, msg_t *msg) NET_SVC_Delta_Parse (entity_state_t *es, unsigned int bits, msg_t *msg)
{ {
unsigned int bits; // bytes of bits: [EXT2][EXT1][ORIG][MORE] // bytes of bits: [EXT2][EXT1][ORIG][MORE]
entity_state_t *es;
subblock->word = bits = (unsigned short) MSG_ReadShort (msg);
if (!bits || msg->badread)
return true;
es = &subblock->state;
es->number = bits & 511; es->number = bits & 511;
bits &= ~511; bits &= ~511;
// if (bits & U_REMOVE)
// return false;
es->frame = 0; es->frame = 0;
es->effects = 0; es->effects = 0;
@ -484,22 +475,32 @@ NET_SVC_Delta_Parse (net_svc_delta_t *subblock, msg_t *msg)
if (bits & U_SOLID) { if (bits & U_SOLID) {
// FIXME // FIXME
} }
return false;
} }
qboolean qboolean
NET_SVC_PacketEntities_Parse (net_svc_packetentities_t *block, msg_t *msg) NET_SVC_PacketEntities_Parse (net_svc_packetentities_t *block, msg_t *msg)
{ {
int i; int word, delta;
unsigned short bits;
for (i = 0; i < MAX_PACKET_ENTITIES; i++) for (word = 0, delta = 0; !msg->badread; word++) {
if (NET_SVC_Delta_Parse (&block->vars[i], msg)) if (word >= MAX_EDICTS)
return 1; // FIXME: differentiate from short packet
bits = (unsigned short) MSG_ReadShort (msg);
block->words[word] = bits;
if (!bits)
break; break;
if (!(bits & U_REMOVE)) {
if (delta >= MAX_PACKET_ENTITIES)
return 1;
NET_SVC_Delta_Parse (&block->deltas[delta], bits, msg);
delta++;
}
}
block->vars[i].word = 0; block->numwords = word;
block->num = i; block->numdeltas = delta;
return msg->badread; return msg->badread;
} }
@ -508,15 +509,27 @@ qboolean
NET_SVC_DeltaPacketEntities_Parse (net_svc_deltapacketentities_t *block, NET_SVC_DeltaPacketEntities_Parse (net_svc_deltapacketentities_t *block,
msg_t *msg) msg_t *msg)
{ {
int i; int word, delta;
unsigned short bits;
block->from = MSG_ReadByte (msg); block->from = MSG_ReadByte (msg);
for (i = 0; i < MAX_PACKET_ENTITIES; i++) for (word = 0, delta = 0; !msg->badread; word++) {
if (NET_SVC_Delta_Parse (&block->vars[i], msg)) if (word >= MAX_EDICTS)
return 1; // FIXME: differentiate from short packet
bits = (unsigned short) MSG_ReadShort (msg);
block->words[word] = bits;
if (!bits)
break; break;
if (!(bits & U_REMOVE)) {
if (delta >= MAX_PACKET_ENTITIES)
return 1;
NET_SVC_Delta_Parse (&block->deltas[delta], bits, msg);
delta++;
}
}
block->vars[i].word = 0; block->numwords = word;
block->num = i; block->numdeltas = delta;
return msg->badread; return msg->badread;
} }