mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-22 18:31:27 +00:00
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:
parent
616f094369
commit
9dcd2333d9
7 changed files with 65 additions and 172 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ();
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue