Add support for sv_antilag (from fteqw).

I'm not 100% certain it actually works, but it doesn't seem to have broken
anything :)
This commit is contained in:
Bill Currie 2012-06-28 16:03:56 +09:00
parent 40da338674
commit 276b6f9662
7 changed files with 175 additions and 30 deletions

View file

@ -32,6 +32,11 @@
#include "QF/mathlib.h"
#include "QF/model.h"
typedef struct {
qboolean present;
vec3_t laggedpos;
} laggedentinfo_t;
typedef enum {
tr_point,
tr_box,

View file

@ -36,6 +36,8 @@
#include "QF/quakeio.h"
#include "QF/sizebuf.h"
#include "world.h"
#include "host.h"
#include "netchan.h"
#include "qw/bothdefs.h"
@ -86,6 +88,11 @@ typedef struct {
byte *pvs, *phs; // fully expanded and decompressed
//antilag
float lagentsfrac;
laggedentinfo_t *lagents;
unsigned maxlagents;
// added to every client's unreliable buffer each frame, then cleared
sizebuf_t datagram;
byte datagram_buf[MAX_DATAGRAM];
@ -133,6 +140,8 @@ typedef struct {
// reply
double senttime;
float ping_time;
vec3_t playerpositions[MAX_CLIENTS];
qboolean playerpresent[MAX_CLIENTS];
packet_entities_t entities;
packet_players_t players;
} client_frame_t;
@ -215,6 +224,11 @@ typedef struct client_s {
double connection_started; // or time of disconnect for zombies
qboolean send_message; // set on frames a datagram arived on
//antilag stuff
laggedentinfo_t laggedents[MAX_CLIENTS];
unsigned laggedents_count;
float laggedents_frac;
// spawn parms are carried from level to level
float spawn_parms[NUM_SPAWN_PARMS];
@ -369,21 +383,22 @@ typedef enum {
#define DAMAGE_AIM 2
// edict->flags
#define FL_FLY 1
#define FL_SWIM 2
#define FL_GLIMPSE 4
#define FL_CLIENT 8
#define FL_INWATER 16
#define FL_MONSTER 32
#define FL_GODMODE 64
#define FL_NOTARGET 128
#define FL_ITEM 256
#define FL_ONGROUND 512
#define FL_PARTIALGROUND 1024 // not all corners are valid
#define FL_WATERJUMP 2048 // player jumping out of water
#define FL_FLY (1<<0)
#define FL_SWIM (1<<1)
#define FL_GLIMPSE (1<<2)
#define FL_CLIENT (1<<3)
#define FL_INWATER (1<<4)
#define FL_MONSTER (1<<5)
#define FL_GODMODE (1<<6)
#define FL_NOTARGET (1<<7)
#define FL_ITEM (1<<8)
#define FL_ONGROUND (1<<9)
#define FL_PARTIALGROUND (1<<10) // not all corners are valid
#define FL_WATERJUMP (1<<11) // player jumping out of water
// 4096 used by quakec
#define FL_FINALIZED 8192
#define FL_FINDABLE_NONSOLID 16384
#define FL_FINALIZED (1<<13)
#define FL_FINDABLE_NONSOLID (1<<14)
#define FLQW_LAGGEDMOVE (1<<16)
// entity effects
@ -531,7 +546,8 @@ void SV_RunNewmis (void);
void SV_SetMoveVars(void);
struct trace_s;
int SV_FlyMove (struct edict_s *ent, float time, struct trace_s *steptrace);
struct trace_s SV_PushEntity (struct edict_s *ent, vec3_t push);
struct trace_s SV_PushEntity (struct edict_s *ent, vec3_t push,
unsigned traceflags);
int SV_EntCanSupportJump (struct edict_s *ent);
//
@ -609,6 +625,8 @@ void SV_WriteEntitiesToClient (delta_t *delta, sizebuf_t *msg);
void Cvar_Info (struct cvar_s *var);
extern struct cvar_s *sv_antilag;
extern struct cvar_s *sv_antilag_frac;
extern struct cvar_s *sv_timecheck_fuzz;
extern struct cvar_s *sv_timecheck_decay;
extern struct cvar_s *sv_maxrate;

View file

@ -377,7 +377,7 @@ SV_FinishGravity (edict_t *ent, vec3_t move)
Does not change the entities velocity at all
*/
trace_t
SV_PushEntity (edict_t *ent, vec3_t push)
SV_PushEntity (edict_t *ent, vec3_t push, unsigned traceflags)
{
trace_t trace;
vec3_t end;
@ -392,13 +392,17 @@ SV_PushEntity (edict_t *ent, vec3_t push)
VectorAdd (e_origin, push, end);
if ((int) SVfloat (ent, flags) & FLQW_LAGGEDMOVE)
traceflags |= MOVE_LAGGED;
if (e_movetype == MOVETYPE_FLYMISSILE)
trace = SV_Move (e_origin, e_mins, e_maxs, end, MOVE_MISSILE, ent);
traceflags |= MOVE_MISSILE;
else if (e_solid == SOLID_TRIGGER || e_solid == SOLID_NOT)
// clip against only bmodels
trace = SV_Move (e_origin, e_mins, e_maxs, end, MOVE_NOMONSTERS, ent);
traceflags |= MOVE_NOMONSTERS;
else
trace = SV_Move (e_origin, e_mins, e_maxs, end, MOVE_NORMAL, ent);
traceflags |= MOVE_NORMAL;
trace = SV_Move (e_origin, e_mins, e_maxs, end, traceflags, ent);
VectorCopy (trace.endpos, e_origin);
SV_LinkEdict (ent, true);
@ -511,7 +515,7 @@ SV_Push (edict_t *pusher, const vec3_t tmove, const vec3_t amove)
// try moving the contacted entity
solid_save = SVfloat (pusher, solid);
SVfloat (pusher, solid) = SOLID_NOT;
SV_PushEntity (check, move);
SV_PushEntity (check, move, MOVE_NORMAL);
SVfloat (pusher, solid) = solid_save;
block = SV_TestEntityPosition (check);
@ -691,6 +695,7 @@ SV_Physics_Toss (edict_t *ent)
float backoff;
trace_t trace;
vec3_t move;
int fl;
// regular thinking
if (!SV_RunThink (ent))
@ -720,7 +725,11 @@ SV_Physics_Toss (edict_t *ent)
SVdata (ent)->add_grav = false;
SV_FinishGravity (ent, move);
}
trace = SV_PushEntity (ent, move);
fl = 0;
if (sv_antilag->int_val == 2)
fl |= MOVE_LAGGED;
trace = SV_PushEntity (ent, move, fl);
if (trace.fraction == 1)
return;
if (ent->free)

View file

@ -387,6 +387,9 @@ PF_traceline (progs_t *pr)
nomonsters = P_FLOAT (pr, 2);
ent = P_EDICT (pr, 3);
if (sv_antilag->int_val == 2)
nomonsters |= MOVE_LAGGED;
trace = SV_Move (v1, vec3_origin, vec3_origin, v2, nomonsters, ent);
*sv_globals.trace_allsolid = trace.allsolid;

View file

@ -750,6 +750,9 @@ CPQW_traceline (progs_t *pr)
nomonsters = TL_ANY_SOLID;
nomonsters = tl_to_move[nomonsters];
if (sv_antilag->int_val == 2)
nomonsters |= MOVE_LAGGED;
trace = SV_Move (v1, vec3_origin, vec3_origin, v2, nomonsters, ent);
*sv_globals.trace_allsolid = trace.allsolid;

View file

@ -79,6 +79,9 @@ edict_t *sv_player;
usercmd_t cmd;
cvar_t *sv_antilag;
cvar_t *sv_antilag_frac;
cvar_t *sv_accelerate;
cvar_t *sv_airaccelerate;
cvar_t *sv_maxspeed;
@ -1869,6 +1872,21 @@ SV_ExecuteClientMessage (client_t *cl)
frame = &cl->delta.frames[cl->delta.cur_frame];
frame->ping_time = realtime - frame->senttime;
cl->laggedents_count = 0;
if (sv_antilag->int_val) {
int i;
for (i = 0; i < MAX_CLIENTS; i++) {
cl->laggedents[i].present = frame->playerpresent[i];
if (cl->laggedents[i].present) {
VectorCopy(frame->playerpositions[i],
cl->laggedents[i].laggedpos);
}
}
cl->laggedents_count = MAX_CLIENTS;
cl->laggedents_frac = sv_antilag_frac->value;
}
// save time for ping calculations
cl->delta.frames[cl->delta.out_frame].senttime = realtime;
cl->delta.frames[cl->delta.out_frame].ping_time = -1;
@ -2001,6 +2019,15 @@ SV_UserInit (void)
cl_rollangle = Cvar_Get ("cl_rollangle", "2", CVAR_NONE, NULL, "How much "
"a player's screen tilts when strafing");
sv_antilag = Cvar_Get ("sv_antilag", "1", CVAR_SERVERINFO, Cvar_Info,
"Attempt to backdate impacts to compensate for "
"lag. 0=completely off. 1=mod-controlled. "
"2=forced, which might break certain uses of "
"traceline.");
sv_antilag_frac = Cvar_Get ("sv_antilag_frac", "1", CVAR_SERVERINFO,
Cvar_Info,
"FIXME something to do with sv_antilag");
sv_allowfake = Cvar_Get ("sv_allowfake", "2", CVAR_NONE, NULL, "Allow 'fake' messages (FuhQuake $\\). 1 = "
"always, 2 = only say_team");
sv_spectalk = Cvar_Get ("sv_spectalk", "1", CVAR_NONE, NULL, "Toggles "

View file

@ -717,16 +717,18 @@ ctl_pretest_other (edict_t *touch, moveclip_t *clip)
}
static inline int
ctl_touch_test (edict_t *touch, moveclip_t *clip)
ctl_pretest_lagged (edict_t *touch, moveclip_t *clip)
{
if (clip->boxmins[0] > SVvector (touch, absmax)[0]
|| clip->boxmins[1] > SVvector (touch, absmax)[1]
|| clip->boxmins[2] > SVvector (touch, absmax)[2]
|| clip->boxmaxs[0] < SVvector (touch, absmin)[0]
|| clip->boxmaxs[1] < SVvector (touch, absmin)[1]
|| clip->boxmaxs[2] < SVvector (touch, absmin)[2])
return 0;
if (clip->type & MOVE_LAGGED)
if ((unsigned) (touch->entnum - 1) < sv.maxlagents)
if (sv.lagents[touch->entnum - 1].present)
return 0;
return 1;
}
static inline int
ctl_touch_common (edict_t *touch, moveclip_t *clip)
{
if (clip->passedict && SVvector (clip->passedict, size)[0]
&& !SVvector (touch, size)[0])
return 0; // points never interact
@ -743,6 +745,34 @@ ctl_touch_test (edict_t *touch, moveclip_t *clip)
return 1;
}
static inline int
ctl_touch_test (edict_t *touch, moveclip_t *clip)
{
if (clip->boxmins[0] > SVvector (touch, absmax)[0]
|| clip->boxmins[1] > SVvector (touch, absmax)[1]
|| clip->boxmins[2] > SVvector (touch, absmax)[2]
|| clip->boxmaxs[0] < SVvector (touch, absmin)[0]
|| clip->boxmaxs[1] < SVvector (touch, absmin)[1]
|| clip->boxmaxs[2] < SVvector (touch, absmin)[2])
return 0;
return ctl_touch_common (touch, clip);
}
static inline int
ctl_touch_test_origin (edict_t *touch, const vec3_t origin, moveclip_t *clip)
{
if (clip->boxmins[0] > origin[0] + SVvector (touch, maxs)[0]
|| clip->boxmins[1] > origin[1] + SVvector (touch, maxs)[1]
|| clip->boxmins[2] > origin[2] + SVvector (touch, maxs)[2]
|| clip->boxmaxs[0] < origin[0] + SVvector (touch, mins)[0]
|| clip->boxmaxs[1] < origin[1] + SVvector (touch, mins)[1]
|| clip->boxmaxs[2] < origin[2] + SVvector (touch, mins)[2])
return 0;
return ctl_touch_common (touch, clip);
}
static void
ctl_do_clip (edict_t *touch, moveclip_t *clip, trace_t *trace)
{
@ -793,6 +823,8 @@ SV_ClipToLinks (areanode_t *node, moveclip_t *clip)
return;
if (!ctl_pretest_everything (touch, clip))
continue;
if (!ctl_pretest_lagged (touch, clip))
continue;
if (!ctl_touch_test (touch, clip))
continue;
ctl_do_clip (touch, clip, &trace);
@ -806,6 +838,8 @@ SV_ClipToLinks (areanode_t *node, moveclip_t *clip)
return;
if (!ctl_pretest_triggers (touch, clip))
continue;
if (!ctl_pretest_lagged (touch, clip))
continue;
if (!ctl_touch_test (touch, clip))
continue;
ctl_do_clip (touch, clip, &trace);
@ -820,6 +854,8 @@ SV_ClipToLinks (areanode_t *node, moveclip_t *clip)
return;
if (!ctl_pretest_other (touch, clip))
continue;
if (!ctl_pretest_lagged (touch, clip))
continue;
if (!ctl_touch_test (touch, clip))
continue;
ctl_do_clip (touch, clip, &trace);
@ -892,7 +928,51 @@ SV_Move (const vec3_t start, const vec3_t mins, const vec3_t maxs,
clip.boxmaxs);
// clip to entities
SV_ClipToLinks (sv_areanodes, &clip);
if (clip.type & MOVE_LAGGED) {
clip.type &= ~MOVE_LAGGED;
if (passedict->entnum && passedict->entnum <= MAX_CLIENTS) {
client_t *cl = &svs.clients[passedict->entnum - 1];
clip.type |= MOVE_LAGGED;
sv.lagents = cl->laggedents;
sv.maxlagents = cl->laggedents_count;
sv.lagentsfrac = cl->laggedents_frac;
} else if (PROG_TO_EDICT (&sv_pr_state, SVentity (passedict, owner))) {
edict_t *owner;
owner = PROG_TO_EDICT (&sv_pr_state, SVentity (passedict, owner));
if (owner->entnum && owner->entnum <= MAX_CLIENTS) {
client_t *cl = &svs.clients[passedict->entnum - 1];
clip.type |= MOVE_LAGGED;
sv.lagents = cl->laggedents;
sv.maxlagents = cl->laggedents_count;
sv.lagentsfrac = cl->laggedents_frac;
}
}
}
if (clip.type & MOVE_LAGGED) {
trace_t trace;
edict_t *touch;
vec3_t lp;
unsigned li;
SV_ClipToLinks (sv_areanodes, &clip);
for (li = 0; li < sv.maxlagents; li++) {
if (!sv.lagents[li].present)
continue;
if (clip.trace.allsolid)
break;
touch = EDICT_NUM (&sv_pr_state, li + 1);
if (!ctl_pretest_other (touch, &clip))
continue;
VectorBlend (SVvector(touch, origin), sv.lagents[li].laggedpos,
sv.lagentsfrac, lp);
if (!ctl_touch_test_origin (touch, lp, &clip))
continue;
ctl_do_clip (touch, &clip, &trace);
}
} else {
SV_ClipToLinks (sv_areanodes, &clip);
}
return clip.trace;
}