mirror of
https://github.com/Shpoike/Quakespasm.git
synced 2025-03-12 04:41:42 +00:00
Add clientside prediction without needing csqc.
This commit is contained in:
parent
09a32a91ba
commit
89d027979a
6 changed files with 147 additions and 13 deletions
106
Quake/cl_main.c
106
Quake/cl_main.c
|
@ -41,6 +41,7 @@ cvar_t cl_bottomcolor = {"bottomcolor", "", CVAR_ARCHIVE | CVAR_USERINFO};
|
|||
|
||||
cvar_t cl_shownet = {"cl_shownet","0",CVAR_NONE}; // can be 0, 1, or 2
|
||||
cvar_t cl_nolerp = {"cl_nolerp","0",CVAR_NONE};
|
||||
cvar_t cl_nopred = {"cl_nopred", "0", CVAR_ARCHIVE}; //name comes from quakeworld.
|
||||
|
||||
cvar_t cfg_unbindall = {"cfg_unbindall", "1", CVAR_ARCHIVE};
|
||||
|
||||
|
@ -493,6 +494,108 @@ static qboolean CL_LerpEntity(entity_t *ent, vec3_t org, vec3_t ang, float frac)
|
|||
int j;
|
||||
vec3_t delta;
|
||||
qboolean teleported = false;
|
||||
|
||||
if (ent->netstate.pmovetype && ent-cl.entities==cl.viewentity && qcvm->worldmodel && !cl_nopred.value)
|
||||
{ //note: V_CalcRefdef will copy from cl.entities[viewent] to get its origin, so doing it here is the proper place anyway.
|
||||
static struct
|
||||
{
|
||||
int seq;
|
||||
float waterjumptime;
|
||||
} propagate[countof(cl.movecmds)];
|
||||
vec3_t bounds[2];
|
||||
|
||||
// memset(&pmove, 0xff, sizeof(pmove));
|
||||
#ifdef VALGRIND_MAKE_MEM_UNDEFINED
|
||||
VALGRIND_MAKE_MEM_UNDEFINED(&pmove, sizeof(pmove));
|
||||
#endif
|
||||
PMCL_SetMoveVars();
|
||||
|
||||
if (ent->netstate.solidsize)
|
||||
{
|
||||
pmove.player_maxs[0] = pmove.player_maxs[1] = ent->netstate.solidsize & 255;
|
||||
pmove.player_mins[0] = pmove.player_mins[1] = -pmove.player_maxs[0];
|
||||
pmove.player_mins[2] = -(int)((ent->netstate.solidsize >>8) & 255);
|
||||
pmove.player_maxs[2] = (int)((ent->netstate.solidsize>>16) & 65535) - 32768;
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorClear(pmove.player_mins);
|
||||
VectorClear(pmove.player_maxs);
|
||||
}
|
||||
pmove.safeorigin_known = false;
|
||||
VectorCopy(ent->msg_origins[0], pmove.origin);
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
pmove.velocity[j] = ent->netstate.velocity[j]*1.0/8;
|
||||
bounds[0][j] = pmove.origin[j] + pmove.player_mins[j] - 256;
|
||||
bounds[1][j] = pmove.origin[j] + pmove.player_maxs[j] + 256;
|
||||
}
|
||||
VectorClear(pmove.gravitydir);
|
||||
|
||||
pmove.waterjumptime = 0;//FIXME: needs propagation. (e->v.teleport_time>qcvm->time)?e->v.teleport_time - qcvm->time:0;
|
||||
pmove.jump_held = !!(ent->netstate.pmovetype&0x40);
|
||||
pmove.onladder = false;//!!(fl&PMF_LADDER);
|
||||
pmove.jump_secs = 0; //has been 0 since Z_EXT_PM_TYPE instead of imposing a delay on rejumps.
|
||||
pmove.onground = !!(ent->netstate.pmovetype&0x80); //in case we're using pm_pground
|
||||
|
||||
switch(ent->netstate.pmovetype&63)
|
||||
{
|
||||
case MOVETYPE_WALK: pmove.pm_type = PM_NORMAL; break;
|
||||
case MOVETYPE_TOSS: //pmove.pm_type = PM_DEAD; break;
|
||||
case MOVETYPE_BOUNCE: pmove.pm_type = PM_DEAD; break;
|
||||
case MOVETYPE_FLY: pmove.pm_type = PM_FLY; break;
|
||||
case MOVETYPE_NOCLIP: pmove.pm_type = PM_SPECTATOR; break;
|
||||
|
||||
case MOVETYPE_NONE:
|
||||
case MOVETYPE_STEP:
|
||||
case MOVETYPE_PUSH:
|
||||
case MOVETYPE_FLYMISSILE:
|
||||
case MOVETYPE_EXT_BOUNCEMISSILE:
|
||||
case MOVETYPE_EXT_FOLLOW:
|
||||
default: pmove.pm_type = PM_NONE; break;
|
||||
}
|
||||
|
||||
pmove.skipent = -(int)(ent-cl.entities);
|
||||
World_AddEntsToPmove(NULL, bounds);
|
||||
|
||||
j = cl.ackedmovemessages+1;
|
||||
if (j < cl.movemessages-countof(cl.movecmds))
|
||||
j = cl.movemessages-countof(cl.movecmds); //don't corrupt things, lost is lost.
|
||||
|
||||
if (propagate[j%countof(cl.movecmds)].seq == j)
|
||||
{ //some things can only be known thanks to propagation.
|
||||
pmove.waterjumptime = propagate[j%countof(cl.movecmds)].waterjumptime;
|
||||
}
|
||||
// else Con_Printf("propagation not available\n"); //just do without
|
||||
|
||||
for (; j < cl.movemessages; j++)
|
||||
{
|
||||
pmove.cmd = cl.movecmds[j%countof(cl.movecmds)];
|
||||
PM_PlayerMove(1);
|
||||
|
||||
propagate[(j+1)%countof(cl.movecmds)].seq = j+1;
|
||||
propagate[(j+1)%countof(cl.movecmds)].waterjumptime = pmove.waterjumptime;
|
||||
}
|
||||
|
||||
//and run the partial too, to keep things smooth
|
||||
pmove.cmd = cl.pendingcmd;
|
||||
PM_PlayerMove(1);
|
||||
|
||||
VectorCopy (pmove.origin, org);
|
||||
VectorCopy (pmove.cmd.viewangles, ang);
|
||||
ang[0] *= -1.0/3; //FIXME: STUPID STUPID BUG
|
||||
|
||||
//for bob+calcrefdef stuff, mostly.
|
||||
VectorCopy (pmove.velocity, cl.velocity);
|
||||
cl.onground = pmove.onground;
|
||||
cl.inwater = pmove.waterlevel>=2;
|
||||
|
||||
//FIXME: add stair-smoothing support
|
||||
//FIXME: add error correction
|
||||
|
||||
return true; //if we're predicting, don't let its old position linger as interpolation. should be less laggy that way, or something.
|
||||
}
|
||||
|
||||
//figure out the pos+angles of the parent
|
||||
if (ent->forcelink)
|
||||
{ // the entity was not updated in the last message
|
||||
|
@ -1145,8 +1248,10 @@ int CL_ReadFromServer (void)
|
|||
if (cl_shownet.value)
|
||||
Con_Printf ("\n");
|
||||
|
||||
PR_SwitchQCVM(&cl.qcvm);
|
||||
CL_RelinkEntities ();
|
||||
CL_UpdateTEnts ();
|
||||
PR_SwitchQCVM(NULL);
|
||||
|
||||
//johnfitz -- devstats
|
||||
|
||||
|
@ -1570,6 +1675,7 @@ void CL_Init (void)
|
|||
Cvar_RegisterVariable (&cl_anglespeedkey);
|
||||
Cvar_RegisterVariable (&cl_shownet);
|
||||
Cvar_RegisterVariable (&cl_nolerp);
|
||||
Cvar_RegisterVariable (&cl_nopred);
|
||||
Cvar_RegisterVariable (&lookspring);
|
||||
Cvar_RegisterVariable (&lookstrafe);
|
||||
Cvar_RegisterVariable (&sensitivity);
|
||||
|
|
13
Quake/host.c
13
Quake/host.c
|
@ -766,13 +766,13 @@ static void CL_LoadCSProgs(void)
|
|||
qboolean fullcsqc = false;
|
||||
int i;
|
||||
PR_ClearProgs(&cl.qcvm);
|
||||
PR_SwitchQCVM(&cl.qcvm);
|
||||
if (pr_checkextension.value && !cl_nocsqc.value)
|
||||
{ //only try to use csqc if qc extensions are enabled.
|
||||
char versionedname[MAX_QPATH];
|
||||
unsigned int csqchash;
|
||||
size_t csqcsize;
|
||||
const char *val;
|
||||
PR_SwitchQCVM(&cl.qcvm);
|
||||
val = Info_GetKey(cl.serverinfo, "*csprogs", versionedname, sizeof(versionedname));
|
||||
csqchash = (unsigned int)strtoul(val, NULL, 0);
|
||||
if (*val)
|
||||
|
@ -863,9 +863,18 @@ static void CL_LoadCSProgs(void)
|
|||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PR_ClearProgs(qcvm);
|
||||
PR_SwitchQCVM(NULL);
|
||||
qcvm->worldmodel = cl.worldmodel;
|
||||
SV_ClearWorld();
|
||||
}
|
||||
}
|
||||
else
|
||||
{ //always initialsing at least part of it, allowing us to share some state with prediction.
|
||||
qcvm->worldmodel = cl.worldmodel;
|
||||
SV_ClearWorld();
|
||||
}
|
||||
PR_SwitchQCVM(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -163,9 +163,11 @@ int SV_HullPointContents (hull_t *hull, int num, vec3_t p);
|
|||
void SV_Impact (edict_t *e1, edict_t *e2);
|
||||
void World_AddEntsToPmove(edict_t *ignore, vec3_t boxminmax[2]);
|
||||
void PMCL_ServerinfoUpdated(void);
|
||||
void PMCL_SetMoveVars(void);
|
||||
void PMSV_SetMoveStats(edict_t *plent, float *fstat, int *istat); //so client has the right movevars as stats.
|
||||
void PMSV_UpdateMovevars(void);
|
||||
void PF_sv_pmove(void);
|
||||
void PMSV_UpdateMovevars(void);
|
||||
void PM_Register(void);
|
||||
#define VectorClear(v) ((v)[0] = (v)[1] = (v)[2] = 0)
|
||||
#define VectorSet(r,x,y,z) do{(r)[0] = x; (r)[1] = y;(r)[2] = z;}while(0)
|
||||
|
|
|
@ -1886,7 +1886,10 @@ static void PF_both_pmove(edict_t *e)
|
|||
eval_t *pmflags = GetEdictFieldValue(e, qcvm->extfields.pmove_flags);
|
||||
unsigned int fl = (pmflags && pmflags->_float)?pmflags->_float:0;
|
||||
|
||||
memset(&pmove, 0, sizeof(pmove));
|
||||
// memset(&pmove, 0xff, sizeof(pmove));
|
||||
#ifdef VALGRIND_MAKE_MEM_UNDEFINED
|
||||
VALGRIND_MAKE_MEM_UNDEFINED(&pmove, sizeof(pmove));
|
||||
#endif
|
||||
VectorCopy(e->v.mins, pmove.player_mins);
|
||||
VectorCopy(e->v.maxs, pmove.player_maxs);
|
||||
VectorCopy(e->v.oldorigin, pmove.safeorigin); pmove.safeorigin_known = (qcvm==&sv.qcvm); //where we revert to when stuck. only consider this valid for ssqc.
|
||||
|
@ -2066,7 +2069,7 @@ void PMSV_UpdateMovevars(void)
|
|||
svmovevars.maxairspeed = 30;
|
||||
svmovevars.flags = MOVEFLAG_VALID|MOVEFLAG_NOGRAVITYONGROUND|(*pm_edgefriction.string?0:MOVEFLAG_QWEDGEBOX);
|
||||
};
|
||||
static void PF_sv_pmove(void)
|
||||
void PF_sv_pmove(void)
|
||||
{
|
||||
edict_t *e = G_EDICT(OFS_PARM0);
|
||||
movevars = svmovevars;
|
||||
|
@ -2136,10 +2139,8 @@ void PMCL_ServerinfoUpdated(void)
|
|||
clmovevars.jumpspeed = 270;
|
||||
clmovevars.maxairspeed = 30;
|
||||
};
|
||||
static void PF_cs_pmove(void)
|
||||
void PMCL_SetMoveVars(void)
|
||||
{
|
||||
edict_t *e = G_EDICT(OFS_PARM0);
|
||||
|
||||
movevars = clmovevars;
|
||||
if (cl.protocol_pext2 & PEXT2_PREDINFO)
|
||||
{ //protocol provides movevars as stats...
|
||||
|
@ -2161,7 +2162,11 @@ static void PF_cs_pmove(void)
|
|||
movevars.jumpspeed = fstat[STAT_MOVEVARS_JUMPVELOCITY];
|
||||
movevars.maxairspeed = fstat[STAT_MOVEVARS_MAXAIRSPEED];
|
||||
}
|
||||
|
||||
}
|
||||
static void PF_cs_pmove(void)
|
||||
{
|
||||
edict_t *e = G_EDICT(OFS_PARM0);
|
||||
PMCL_SetMoveVars();
|
||||
PF_both_pmove(e);
|
||||
}
|
||||
|
||||
|
|
|
@ -286,10 +286,13 @@ World_AreaAddEntsToPmove ( edict_t *ignore, areanode_t *node, vec3_t boxminmax[2
|
|||
|| boxminmax[1][2] < other->v.absmin[2] )
|
||||
continue;
|
||||
|
||||
if (PROG_TO_EDICT(other->v.owner) == ignore)
|
||||
continue; // don't clip against own missiles
|
||||
if (PROG_TO_EDICT(ignore->v.owner) == other)
|
||||
continue; // don't clip against owner
|
||||
if (ignore)
|
||||
{
|
||||
if (PROG_TO_EDICT(other->v.owner) == ignore)
|
||||
continue; // don't clip against own missiles
|
||||
if (PROG_TO_EDICT(ignore->v.owner) == other)
|
||||
continue; // don't clip against owner
|
||||
}
|
||||
|
||||
if (pmove.numphysent == countof(pmove.physents))
|
||||
return; //too many... ooer.
|
||||
|
@ -327,8 +330,13 @@ World_AreaAddEntsToPmove ( edict_t *ignore, areanode_t *node, vec3_t boxminmax[2
|
|||
}
|
||||
void World_AddEntsToPmove(edict_t *ignore, vec3_t boxminmax[2])
|
||||
{
|
||||
pmove.skipent = NUM_FOR_EDICT(ignore);
|
||||
if (ignore)
|
||||
pmove.skipent = NUM_FOR_EDICT(ignore);
|
||||
pmove.physents[0].model = qcvm->worldmodel;
|
||||
VectorClear(pmove.physents[0].origin);
|
||||
VectorClear(pmove.physents[0].angles);
|
||||
pmove.physents[0].forcecontentsmask = 0;
|
||||
pmove.physents[0].info = 0;
|
||||
pmove.numphysent = 1;
|
||||
World_AreaAddEntsToPmove (ignore, qcvm->areanodes, boxminmax);
|
||||
|
||||
|
|
|
@ -89,6 +89,10 @@ Zone block
|
|||
|
||||
*/
|
||||
|
||||
#ifdef __linux__
|
||||
//#include <valgrind/memcheck.h>
|
||||
#endif
|
||||
|
||||
void Memory_Init (void *buf, int size);
|
||||
|
||||
void Z_Free (void *ptr);
|
||||
|
|
Loading…
Reference in a new issue