Serious mvd surgery. Interpolation of player position/angle is no longer

done and playerinfo is now written at the proper time, fixing the
"lagged dlights" issue (as Spike puts it:). Hack to fix broken mvds removed
as it should no longer be needed if everybody fixes their mvd servers :)
This commit is contained in:
Bill Currie 2005-04-27 09:54:37 +00:00
parent 616f094369
commit 9dcd2333d9
7 changed files with 65 additions and 172 deletions

View file

@ -38,7 +38,6 @@ struct skin_s;
extern int packet_latency[NET_TIMINGS];
extern int parsecountmod;
extern int player_parsecountmod;
extern double parsecounttime;
extern int cl_playerindex;
extern int cl_flagindex;

View file

@ -53,7 +53,6 @@ typedef struct demo_client_s {
demoinfo_t info;
float sec;
int parsecount;
qboolean fixangle;
vec3_t angle;
float cmdtime;
int flags;
@ -92,8 +91,6 @@ typedef struct demo_s {
client_t recorder;
int stats[MAX_CLIENTS][MAX_CL_STATS]; // ouch!
qboolean fixangle[MAX_CLIENTS];
float fixangletime[MAX_CLIENTS];
demoinfo_t info[MAX_CLIENTS];
demo_frame_t frames[DEMO_FRAMES];
@ -127,6 +124,7 @@ extern struct cvar_s *sv_demotxt;
extern struct cvar_s *serverdemo;
void DemoWrite_Begin (byte type, int to, int size);
void SV_WriteClientToDemo (sizebuf_t *msg, int i, demo_client_t *cl);
void SV_DemoWritePackets (int num);
void SV_Stop (int reason);
void DemoSetMsgBuf (demobuf_t *prev, demobuf_t *cur);

View file

@ -673,7 +673,6 @@ CL_ParsePlayerinfo (void)
Host_Error ("CL_ParsePlayerinfo: bad num");
info = &cl.players[num];
player_parsecountmod = parsecountmod;
state = &cl.frames[parsecountmod].playerstate[num];
state->number = num;

View file

@ -159,7 +159,6 @@ const char *svc_strings[] = {
int oldparsecountmod;
int parsecountmod;
int player_parsecountmod;
double parsecounttime;
int viewentity;
@ -1161,7 +1160,7 @@ CL_MuzzleFlash (void)
if ((unsigned int) (i - 1) >= MAX_CLIENTS)
return;
pl = &cl.frames[player_parsecountmod].playerstate[i - 1];
pl = &cl.frames[parsecountmod].playerstate[i - 1];
dl = R_AllocDlight (i);
if (!dl)
@ -1203,7 +1202,8 @@ CL_ParseServerMessage (void)
if (cl_shownet->int_val == 1)
Con_Printf ("%i ", net_message->message->cursize);
else if (cl_shownet->int_val == 2)
Con_Printf ("------------------\n");
Con_Printf ("------------------ %d\n",
cls.netchan.incoming_acknowledged);
CL_ParseClientdata ();

View file

@ -211,49 +211,71 @@ SV_DemoWriteToDisk (int type, int to, float time)
}
}
/*
SV_DemoWritePackets
Interpolates to get exact players position for current frame
and writes packets to the disk/memory
*/
static float
adjustangle (float current, float ideal, float fraction)
void
SV_WriteClientToDemo (sizebuf_t *msg, int i, demo_client_t *cl)
{
float move;
float *origin, *angles;
int flags;
int j;
demoinfo_t *demoinfo = &demo.info[i];
move = ideal - current;
if (ideal > current) {
origin = cl->info.origin;
angles = cl->info.angles;
if (move >= 180)
move = move - 360;
} else {
if (move <= -180)
move = move + 360;
}
// now write it to buf
flags = cl->flags;
move *= fraction;
for (j = 0; j < 3; j++)
if (origin[j] != demoinfo->origin[j])
flags |= DF_ORIGIN << j;
return (current + move);
for (j = 0; j < 3; j++)
if (angles[j] != demoinfo->angles[j])
flags |= DF_ANGLES << j;
if (cl->info.model != demoinfo->model)
flags |= DF_MODEL;
if (cl->info.effects != demoinfo->effects)
flags |= DF_EFFECTS;
if (cl->info.skinnum != demoinfo->skinnum)
flags |= DF_SKINNUM;
if (cl->info.weaponframe != demoinfo->weaponframe)
flags |= DF_WEAPONFRAME;
MSG_WriteByte (msg, svc_playerinfo);
MSG_WriteByte (msg, i);
MSG_WriteShort (msg, flags);
MSG_WriteByte (msg, cl->frame);
for (j = 0; j < 3; j++)
if (flags & (DF_ORIGIN << j))
MSG_WriteCoord (msg, origin[j]);
for (j = 0; j < 3; j++)
if (flags & (DF_ANGLES << j))
MSG_WriteAngle16 (msg, angles[j]);
if (flags & DF_MODEL)
MSG_WriteByte (msg, cl->info.model);
if (flags & DF_SKINNUM)
MSG_WriteByte (msg, cl->info.skinnum);
if (flags & DF_EFFECTS)
MSG_WriteByte (msg, cl->info.effects);
if (flags & DF_WEAPONFRAME)
MSG_WriteByte (msg, cl->info.weaponframe);
*demoinfo = cl->info;
}
void
SV_DemoWritePackets (int num)
{
demo_frame_t *frame, *nextframe;
demo_client_t *cl, *nextcl = 0;
int i, j, flags;
qboolean valid;
double time, playertime, nexttime;
float f;
vec3_t origin, angles;
sizebuf_t msg;
byte msg_buf[MAX_MSGLEN];
demoinfo_t *demoinfo;
msg.data = msg_buf;
msg.maxsize = sizeof (msg_buf);
demo_frame_t *frame;
double time;
if (num > demo.parsecount - demo.lastwritten + 1)
num = demo.parsecount - demo.lastwritten + 1;
@ -262,122 +284,12 @@ SV_DemoWritePackets (int num)
for (; num; num--, demo.lastwritten++) {
frame = &demo.frames[demo.lastwritten & DEMO_FRAMES_MASK];
time = frame->time;
nextframe = frame;
msg.cursize = 0;
demo.dbuf = &frame->buf;
// find two frames
// one before the exact time (time - msec) and one after,
// then we can interpolate exact position for current frame
for (i = 0, cl = frame->clients, demoinfo = demo.info; i < MAX_CLIENTS;
i++, cl++, demoinfo++) {
if (cl->parsecount != demo.lastwritten)
continue; // not valid
nexttime = playertime = time - cl->sec;
for (j = demo.lastwritten + 1, valid = false;
nexttime < time && j < demo.parsecount; j++) {
nextframe = &demo.frames[j & DEMO_FRAMES_MASK];
nextcl = &nextframe->clients[i];
if (nextcl->parsecount != j)
break; // disconnected?
if (nextcl->fixangle)
break; // respawned, or walked into
// teleport, do not interpolate!
if (!(nextcl->flags & DF_DEAD) && (cl->flags & DF_DEAD))
break; // respawned, do not interpolate
nexttime = nextframe->time - nextcl->sec;
if (nexttime >= time) {
// good, found what we were looking for
valid = true;
break;
}
}
if (valid) {
f = (time - nexttime) / (nexttime - playertime);
for (j = 0; j < 3; j++) {
angles[j] = adjustangle (cl->info.angles[j],
nextcl->info.angles[j], 1.0 + f);
origin[j] = (nextcl->info.origin[j]
+ f * (nextcl->info.origin[j]
- cl->info.origin[j]));
}
} else {
VectorCopy (cl->info.origin, origin);
VectorCopy (cl->info.angles, angles);
}
// now write it to buf
flags = cl->flags;
if (cl->fixangle) {
demo.fixangletime[i] = cl->cmdtime;
}
for (j = 0; j < 3; j++)
if (origin[j] != demoinfo->origin[j])
flags |= DF_ORIGIN << j;
if (cl->fixangle || demo.fixangletime[i] != cl->cmdtime) {
for (j = 0; j < 3; j++)
if (angles[j] != demoinfo->angles[j])
flags |= DF_ANGLES << j;
}
if (cl->info.model != demoinfo->model)
flags |= DF_MODEL;
if (cl->info.effects != demoinfo->effects)
flags |= DF_EFFECTS;
if (cl->info.skinnum != demoinfo->skinnum)
flags |= DF_SKINNUM;
if (cl->info.weaponframe != demoinfo->weaponframe)
flags |= DF_WEAPONFRAME;
MSG_WriteByte (&msg, svc_playerinfo);
MSG_WriteByte (&msg, i);
MSG_WriteShort (&msg, flags);
MSG_WriteByte (&msg, cl->frame);
for (j = 0; j < 3; j++)
if (flags & (DF_ORIGIN << j))
MSG_WriteCoord (&msg, origin[j]);
for (j = 0; j < 3; j++)
if (flags & (DF_ANGLES << j))
MSG_WriteAngle16 (&msg, angles[j]);
if (flags & DF_MODEL)
MSG_WriteByte (&msg, cl->info.model);
if (flags & DF_SKINNUM)
MSG_WriteByte (&msg, cl->info.skinnum);
if (flags & DF_EFFECTS)
MSG_WriteByte (&msg, cl->info.effects);
if (flags & DF_WEAPONFRAME)
MSG_WriteByte (&msg, cl->info.weaponframe);
VectorCopy (cl->info.origin, demoinfo->origin);
VectorCopy (cl->info.angles, demoinfo->angles);
demoinfo->skinnum = cl->info.skinnum;
demoinfo->effects = cl->info.effects;
demoinfo->weaponframe = cl->info.weaponframe;
demoinfo->model = cl->info.model;
}
// this goes first to reduce demo size a bit
SV_DemoWriteToDisk (demo.lasttype, demo.lastto, time);
// SV_DemoWriteToDisk (demo.lasttype, demo.lastto, time);
SV_DemoWriteToDisk (0, 0, time); // now goes the rest
if (msg.cursize)
SV_WriteDemoMessage (&msg, dem_all, 0, time);
}
if (demo.lastwritten > demo.parsecount)

View file

@ -422,9 +422,7 @@ SV_WritePlayersToClient (client_t *client, edict_t *clent, byte *pvs,
dcl->parsecount = demo.parsecount;
VectorCopy (SVvector (ent, origin), dcl->info.origin);
VectorCopy (SVvector (ent, angles), dcl->info.angles);
dcl->info.angles[0] *= -3;
dcl->info.angles[2] = 0; // no roll angle
VectorCopy (cl->lastcmd.angles, dcl->info.angles);
if (SVfloat (ent, health) <= 0) {
// don't show the corpse looking around...
@ -441,13 +439,13 @@ SV_WritePlayersToClient (client_t *client, edict_t *clent, byte *pvs,
dcl->frame = SVfloat (ent, frame);
dcl->flags = 0;
dcl->cmdtime = cl->localtime;
dcl->fixangle = demo.fixangle[j];
demo.fixangle[j] = 0;
if (SVfloat (ent, health) <= 0)
dcl->flags |= DF_DEAD;
if (SVvector (ent, mins)[2] != -24)
dcl->flags |= DF_GIB;
SV_WriteClientToDemo (msg, j, dcl);
continue;
}

View file

@ -522,7 +522,6 @@ SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg)
MSG_WriteByte (msg, svc_setangle);
MSG_WriteAngleV (msg, angles);
SVfloat (ent, fixangle) = 0;
demo.fixangle[clnum] = true;
if (sv.demorecording) {
MSG_WriteByte (&demo.datagram, svc_setangle);
@ -807,7 +806,7 @@ SV_SendClientMessages (void)
void
SV_SendDemoMessage (void)
{
int i, j, cls = 0;
int i, j;
client_t *c;
byte buf[MAX_DATAGRAM];
sizebuf_t msg;
@ -829,21 +828,9 @@ SV_SendDemoMessage (void)
return;
demo.forceFrame = 0;
for (i = 0, c = svs.clients ; i<MAX_CLIENTS ; i++, c++) {
if (c->state != cs_spawned && c->state != cs_server)
continue; // datagrams only go to spawned
cls |= 1 << i;
}
if (!cls) {
SZ_Clear (&demo.datagram);
return;
}
for (i = 0, c = svs.clients; i < MAX_CLIENTS; i++, c++) {
if (c->state != cs_spawned && c->state != cs_server)
continue; // datagrams only go to spawned
continue;
if (c->spectator)
continue;