Add sv_nqplayerphysics cvar for mods that don't want to include SV_RunClientCommand for whatever reason. Set to 0 to force predictable player physics.

This commit is contained in:
Shpoike 2023-07-25 13:37:52 +01:00
parent 039d61dbfa
commit 09a32a91ba
6 changed files with 55 additions and 28 deletions

View file

@ -164,6 +164,8 @@ void SV_Impact (edict_t *e1, edict_t *e2);
void World_AddEntsToPmove(edict_t *ignore, vec3_t boxminmax[2]);
void PMCL_ServerinfoUpdated(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 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)

View file

@ -1987,30 +1987,29 @@ static void PF_both_pmove(edict_t *e)
}
}
cvar_t pm_bunnyspeedcap = {"pm_bunnyspeedcap", "", CVAR_SERVERINFO}; //reduces strafejumps to maxspeed instead of endlessly accelerating
cvar_t pm_bunnyfriction = {"pm_bunnyfriction", "1", CVAR_SERVERINFO}; //forces nq's frame of friction
cvar_t pm_ktjump = {"pm_ktjump", "", CVAR_SERVERINFO};
cvar_t pm_slidefix = {"pm_slidefix", "1", CVAR_SERVERINFO}; //don't bump when going down slopes.
cvar_t pm_airstep = {"pm_airstep", "", CVAR_SERVERINFO}; //allow stepping up stairs when eg jumping
cvar_t pm_pground = {"pm_pground", "", CVAR_SERVERINFO}; //persistent onground state, supposed to be more precise but has gamecode interaction issues.
cvar_t pm_stepdown = {"pm_stepdown", "", CVAR_SERVERINFO}; //glue the player to the ground when going down steps instead of just up. kinda weird.
cvar_t pm_walljump = {"pm_walljump", "", CVAR_SERVERINFO}; //bouncing off the walls.
cvar_t pm_slidyslopes = {"pm_slidyslopes", "", CVAR_SERVERINFO}; //gradually slide down slopes like vanilla nq
cvar_t pm_autobunny = {"pm_autobunny", "", CVAR_SERVERINFO}; //pogostick mode, for lazy noobs
cvar_t pm_watersinkspeed = {"pm_watersinkspeed", "", CVAR_SERVERINFO}; //speed you sink at when idle in water
cvar_t pm_flyfriction = {"pm_flyfriction", "", CVAR_SERVERINFO}; //friction in fly/noclip modes.
cvar_t pm_edgefriction = {"pm_edgefriction", "2",}; //should alias to edgefriction but be listed in the serverinfo as pm_...
cvar_t pm_stepheight = {"pm_stepheight", ""}; //should alias to edgefriction but be listed in the serverinfo as pm_...
static cvar_t pm_bunnyspeedcap = {"pm_bunnyspeedcap", "", CVAR_SERVERINFO}; //reduces strafejumps to maxspeed instead of endlessly accelerating
static cvar_t pm_bunnyfriction = {"pm_bunnyfriction", "1", CVAR_SERVERINFO}; //forces nq's frame of friction
static cvar_t pm_ktjump = {"pm_ktjump", "", CVAR_SERVERINFO};
static cvar_t pm_slidefix = {"pm_slidefix", "1", CVAR_SERVERINFO}; //don't bump when going down slopes.
static cvar_t pm_airstep = {"pm_airstep", "", CVAR_SERVERINFO}; //allow stepping up stairs when eg jumping
static cvar_t pm_pground = {"pm_pground", "", CVAR_SERVERINFO}; //persistent onground state, supposed to be more precise but has gamecode interaction issues.
static cvar_t pm_stepdown = {"pm_stepdown", "", CVAR_SERVERINFO}; //glue the player to the ground when going down steps instead of just up. kinda weird.
static cvar_t pm_walljump = {"pm_walljump", "", CVAR_SERVERINFO}; //bouncing off the walls.
static cvar_t pm_slidyslopes = {"pm_slidyslopes", "", CVAR_SERVERINFO}; //gradually slide down slopes like vanilla nq
static cvar_t pm_autobunny = {"pm_autobunny", "", CVAR_SERVERINFO}; //pogostick mode, for lazy noobs
static cvar_t pm_watersinkspeed = {"pm_watersinkspeed", "", CVAR_SERVERINFO}; //speed you sink at when idle in water
static cvar_t pm_flyfriction = {"pm_flyfriction", "", CVAR_SERVERINFO}; //friction in fly/noclip modes.
static cvar_t pm_edgefriction = {"pm_edgefriction", "2",}; //should alias to edgefriction but be listed in the serverinfo as pm_...
static cvar_t pm_stepheight = {"pm_stepheight", ""}; //should alias to edgefriction but be listed in the serverinfo as pm_...
extern cvar_t sv_maxspeed;
cvar_t sv_spectatormaxspeed = {"sv_spectatormaxspeed", "500"};
extern cvar_t sv_accelerate;
cvar_t sv_airaccelerate = {"sv_airaccelerate", "0.7"};
cvar_t sv_wateraccelerate = {"sv_wateraccelerate", "10"};
cvar_t sv_waterfriction = {"sv_waterfriction", "4"};
extern cvar_t sv_waterfriction;
extern cvar_t sv_friction;
extern cvar_t sv_gravity;
extern cvar_t sv_stopspeed;
static cvar_t sv_airaccelerate = {"sv_airaccelerate", "0.7"};
static cvar_t sv_wateraccelerate = {"sv_wateraccelerate", "10"};
static cvar_t sv_waterfriction = {"sv_waterfriction", "4"};
static cvar_t sv_spectatormaxspeed = {"sv_spectatormaxspeed", "500"};
void PM_Register(void)
{
PM_Init();

View file

@ -206,6 +206,7 @@ typedef struct client_s
int lastacksequence;
int lastmovemessage;
double lastmovetime;
qboolean usingpmove; //using the SV_RunClientCommand entrypoint, or getting pmove thrust upon them serverside (disables sv_user.c+movetype stuff, enables provides pmove hints to the client)
char userinfo[1024]; //spike -- for csqc to (ab)use.
client_voip_t voip; //spike -- for voip

View file

@ -1312,7 +1312,7 @@ invisible:
ents[numents].state.modelindex = 0;
if (ent == clent) //add velocity, but we only care for the local player (should add prediction for other entities some time too).
{
if (qcvm->extfuncs.SV_RunClientCommand)
if (client->usingpmove)
ents[numents].state.pmovetype = ent->v.movetype; //looks like prediction is available. assuming SV_RunClientCommand just calls runstandardplayerphysics then we can predict it with matching clientside stuff.
else
ents[numents].state.pmovetype = 0; //fixme: we don't do prediction, so don't tell the client that it can try
@ -1539,6 +1539,7 @@ void SV_Init (void)
extern cvar_t sv_idealpitchscale;
extern cvar_t sv_aim;
extern cvar_t sv_altnoclip; //johnfitz
extern cvar_t sv_nqplayerphysics; //spike
extern cvar_t sv_public; //spike
extern cvar_t sv_reportheartbeats; //spike
extern cvar_t com_protocolname; //spike
@ -1567,6 +1568,7 @@ void SV_Init (void)
Cvar_RegisterVariable (&sv_gameplayfix_setmodelrealbox);
Cvar_RegisterVariable (&pr_checkextension);
Cvar_RegisterVariable (&sv_altnoclip); //johnfitz
Cvar_RegisterVariable (&sv_nqplayerphysics); //spike
Cvar_RegisterVariable (&sv_sound_watersplash); //spike
Cvar_RegisterVariable (&sv_sound_land); //spike

View file

@ -1202,7 +1202,7 @@ void SV_Physics_Client (edict_t *ent, int num)
if ( ! svs.clients[num-1].active )
return; // unconnected slot
if (qcvm->extfuncs.SV_RunClientCommand)
if (svs.clients[num-1].usingpmove)
return; //we're doing independant player physics with this mod, so clientside prediction can do its thing.
if (!svs.clients[num-1].knowntoqc && sv_gameplayfix_spawnbeforethinks.value)
return; //don't spam prethinks before we called putclientinserver.

View file

@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// sv_user.c -- server code for moving users
#include "quakedef.h"
#include "pmove.h"
edict_t *sv_player;
@ -42,6 +43,7 @@ usercmd_t cmd;
cvar_t sv_idealpitchscale = {"sv_idealpitchscale","0.8",CVAR_NONE};
cvar_t sv_altnoclip = {"sv_altnoclip","1",CVAR_ARCHIVE}; //johnfitz
cvar_t sv_nqplayerphysics = {"sv_nqplayerphysics", "1", CVAR_ARCHIVE}; //spike. set to 0 for prediction to work. name comes from fte.
qboolean SV_RunThink (edict_t *ent);
@ -392,8 +394,6 @@ void SV_ClientThink (void)
if (sv_player->v.movetype == MOVETYPE_NONE)
return;
if (qcvm->extfuncs.SV_RunClientCommand)
return; //this stuff is handled on inputs. don't corrupt anything.
onground = (int)sv_player->v.flags & FL_ONGROUND;
@ -402,6 +402,9 @@ void SV_ClientThink (void)
DropPunchAngle ();
if (host_client->usingpmove)
return; //this stuff is handled on inputs. don't corrupt anything.
//
// if dead, behave differently
//
@ -462,6 +465,7 @@ void SV_ReadClientMove (usercmd_t *move)
vec3_t movevalues;
int sequence;
eval_t *val;
vec3_t savedvel;
if (host_client->protocol_pext2 & PEXT2_PREDINFO)
{
@ -554,10 +558,11 @@ void SV_ReadClientMove (usercmd_t *move)
eval->vector[2] = move->upmove;
}
//FIXME: attempt to apply physics command now, if the mod has custom physics+csqc-prediction
//decide if we're going independant or not
host_client->usingpmove = !!qcvm->extfuncs.SV_RunClientCommand || (!sv_nqplayerphysics.value && (*sv_nqplayerphysics.string||deathmatch.value));
if (qcvm->extfuncs.SV_RunClientCommand && host_client->knowntoqc)
//and give them their independance here.
if (host_client->usingpmove && host_client->knowntoqc)
{
if (timestamp > qcvm->time)
timestamp = qcvm->time; //don't let the client exceed the current time
@ -592,14 +597,32 @@ void SV_ReadClientMove (usercmd_t *move)
if (qcvm->extglobals.input_cursor_entitynumber)
*qcvm->extglobals.input_cursor_entitynumber = curs_entity;
VectorCopy(host_client->edict->v.velocity, savedvel);
pr_global_struct->self = EDICT_TO_PROG(host_client->edict);
PR_ExecuteProgram(pr_global_struct->PlayerPreThink);
if (!qcvm->extfuncs.SV_RunClientCommand)
{
//Undo damage caused by unaware mods... in vanilla this includes:
// PlayerJump has 4 velocity changes that might mess with prediction
// WaterMove imposes some additional drag that breaks things
// CheckWaterJump is entirely redundant.
//(it should be noted that the (cs)qc should still track jumps for sounds, and landings for fall damage, and water for drowning, just not any of the velocity changes)
VectorCopy(savedvel, host_client->edict->v.velocity);
}
if (!SV_RunThink (host_client->edict))
return; //ent was removed? o.O
if (qcvm->extfuncs.SV_RunClientCommand)
{
pr_global_struct->self = EDICT_TO_PROG(host_client->edict);
PR_ExecuteProgram(qcvm->extfuncs.SV_RunClientCommand);
}
else
{ //the qc ain't helping us here. go direct to the runstandardplayerphysics builtin.
G_INT(OFS_PARM0) = EDICT_TO_PROG(host_client->edict);
PF_sv_pmove();
}
pr_global_struct->self = EDICT_TO_PROG(host_client->edict);
PR_ExecuteProgram(pr_global_struct->PlayerPostThink);