Make input_servertime available to ssqc too, so it can guage the player's latency more accurately.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5908 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2021-06-21 13:46:52 +00:00
parent 8b4a282c47
commit f810be4830
6 changed files with 103 additions and 83 deletions

View file

@ -906,39 +906,9 @@ void CL_PredictEntityMovement(entity_state_t *estate, float age)
} }
} }
/* float CL_GetPredictionRealtime(playerview_t *pv)
==============
CL_PredictMove
==============
*/
void CL_PredictMovePNum (int seat)
{ {
//when this is called, the entity states have been interpolated. float simtime;
//interpolation state should be updated to match prediction state, so entities move correctly in mirrors/portals.
//this entire function is pure convolouted bollocks.
struct {
int frame;
double time;
player_state_t *state;
usercmd_t *cmd;
} from, to;
playerview_t *pv = &cl.playerview[seat];
int i;
float f;
outframe_t *backdate;
player_state_t framebuf[2]; //need two framebufs so we can interpolate between two states.
static player_state_t nullstate;
int oldphysent;
double simtime; //this is server time if nopred is set (lerp-only), and local time if we're predicting
extern cvar_t cl_netfps;
lerpents_t *le;
qboolean nopred;
qboolean lerpangles = false;
int trackent;
qboolean cam_nowlocked = false;
usercmd_t indcmd;
//these are to make svc_viewentity work better //these are to make svc_viewentity work better
float netfps = cl_netfps.value; float netfps = cl_netfps.value;
@ -978,6 +948,43 @@ void CL_PredictMovePNum (int seat)
simtime -= cls.latency; //push back when playing demos. simtime -= cls.latency; //push back when playing demos.
simtime += bound(-0.5, cl_predict_timenudge.value, 0.5); simtime += bound(-0.5, cl_predict_timenudge.value, 0.5);
return simtime;
}
/*
==============
CL_PredictMove
==============
*/
void CL_PredictMovePNum (int seat)
{
//when this is called, the entity states have been interpolated.
//interpolation state should be updated to match prediction state, so entities move correctly in mirrors/portals.
//this entire function is pure convolouted bollocks.
struct {
int frame;
double time;
player_state_t *state;
usercmd_t *cmd;
} from, to;
playerview_t *pv = &cl.playerview[seat];
int i;
float f;
outframe_t *backdate;
player_state_t framebuf[2]; //need two framebufs so we can interpolate between two states.
static player_state_t nullstate;
int oldphysent;
double simtime; //this is server time if nopred is set (lerp-only), and local time if we're predicting
extern cvar_t cl_netfps;
lerpents_t *le;
qboolean nopred;
qboolean lerpangles = false;
int trackent;
qboolean cam_nowlocked = false;
usercmd_t indcmd;
simtime = CL_GetPredictionRealtime(pv);
pv->nolocalplayer = !!(cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) || (cls.protocol != CP_QUAKEWORLD); pv->nolocalplayer = !!(cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) || (cls.protocol != CP_QUAKEWORLD);
if (!pv->spectator && (pv->cam_state != CAM_FREECAM || pv->cam_spec_track != -1)) //just in case if (!pv->spectator && (pv->cam_state != CAM_FREECAM || pv->cam_spec_track != -1)) //just in case

View file

@ -3941,6 +3941,8 @@ static void cs_get_input_state (usercmd_t *cmd)
cmd->fservertime = *csqcg.input_servertime; cmd->fservertime = *csqcg.input_servertime;
cmd->servertime = *csqcg.input_servertime*1000; cmd->servertime = *csqcg.input_servertime*1000;
} }
if (csqcg.input_clienttime)
cmd->fclienttime = *csqcg.input_clienttime;
if (csqcg.input_cursor_screen) if (csqcg.input_cursor_screen)
Vector2Copy(csqcg.input_cursor_screen, cmd->cursor_screen); Vector2Copy(csqcg.input_cursor_screen, cmd->cursor_screen);

View file

@ -1454,21 +1454,21 @@ void MSGFTE_WriteDeltaUsercmd (sizebuf_t *buf, const usercmd_t *from, const user
if (bits & UC_FORWARD) if (bits & UC_FORWARD)
{ {
if (bits & UC_BIGMOVES) if (bits & UC_BIGMOVES)
MSG_WriteShort(buf, cmd->forwardmove); MSG_WriteInt64(buf, cmd->forwardmove);
else else
MSG_WriteChar(buf, cmd->forwardmove/5); MSG_WriteChar(buf, cmd->forwardmove/5);
} }
if (bits & UC_RIGHT) if (bits & UC_RIGHT)
{ {
if (bits & UC_BIGMOVES) if (bits & UC_BIGMOVES)
MSG_WriteShort(buf, cmd->sidemove); MSG_WriteInt64(buf, cmd->sidemove);
else else
MSG_WriteChar(buf, cmd->sidemove/5); MSG_WriteChar(buf, cmd->sidemove/5);
} }
if (bits & UC_UP) if (bits & UC_UP)
{ {
if (bits & UC_BIGMOVES) if (bits & UC_BIGMOVES)
MSG_WriteShort(buf, cmd->upmove); MSG_WriteInt64(buf, cmd->upmove);
else else
MSG_WriteChar(buf, cmd->upmove/5); MSG_WriteChar(buf, cmd->upmove/5);
} }
@ -1548,6 +1548,7 @@ void MSGFTE_ReadDeltaUsercmd (const usercmd_t *from, usercmd_t *cmd)
} }
*cmd = *from; *cmd = *from;
cmd->servertime = from->servertime+MSG_ReadUInt64(); cmd->servertime = from->servertime+MSG_ReadUInt64();
cmd->fservertime = cmd->servertime/1000.0;
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
{ {
if (bits & (UC_ANGLE1<<i)) if (bits & (UC_ANGLE1<<i))
@ -1561,21 +1562,21 @@ void MSGFTE_ReadDeltaUsercmd (const usercmd_t *from, usercmd_t *cmd)
if (bits & UC_FORWARD) if (bits & UC_FORWARD)
{ {
if (bits & UC_BIGMOVES) if (bits & UC_BIGMOVES)
cmd->forwardmove = MSG_ReadShort(); cmd->forwardmove = MSG_ReadInt64();
else else
cmd->forwardmove = MSG_ReadChar()*5; cmd->forwardmove = MSG_ReadChar()*5;
} }
if (bits & UC_RIGHT) if (bits & UC_RIGHT)
{ {
if (bits & UC_BIGMOVES) if (bits & UC_BIGMOVES)
cmd->sidemove = MSG_ReadShort(); cmd->sidemove = MSG_ReadInt64();
else else
cmd->sidemove = MSG_ReadChar()*5; cmd->sidemove = MSG_ReadChar()*5;
} }
if (bits & UC_UP) if (bits & UC_UP)
{ {
if (bits & UC_BIGMOVES) if (bits & UC_BIGMOVES)
cmd->upmove = MSG_ReadShort(); cmd->upmove = MSG_ReadInt64();
else else
cmd->upmove = MSG_ReadChar()*5; cmd->upmove = MSG_ReadChar()*5;
} }

View file

@ -1008,6 +1008,7 @@ void PR_LoadGlabalStruct(qboolean muted)
globalvec (false, input_right_angles) \ globalvec (false, input_right_angles) \
globalvec (false, input_right_velocity) \ globalvec (false, input_right_velocity) \
globalvec (false, input_right_avelocity) \ globalvec (false, input_right_avelocity) \
globalfloat (false, input_servertime) \
\ \
globalint (false, serverid) \ globalint (false, serverid) \
globalvec (false, global_gravitydir) \ globalvec (false, global_gravitydir) \
@ -10321,6 +10322,10 @@ static void SV_SetSSQCInputs(usercmd_t *ucmd)
(pr_global_struct->input_movevalues)[1] = ucmd->sidemove; (pr_global_struct->input_movevalues)[1] = ucmd->sidemove;
(pr_global_struct->input_movevalues)[2] = ucmd->upmove; (pr_global_struct->input_movevalues)[2] = ucmd->upmove;
} }
if (pr_global_ptrs->input_servertime)
pr_global_struct->input_servertime = ucmd->fservertime;
if (pr_global_ptrs->input_clienttime)
pr_global_struct->input_clienttime = ucmd->fclienttime;
if (pr_global_ptrs->input_buttons) if (pr_global_ptrs->input_buttons)
pr_global_struct->input_buttons = ucmd->buttons; pr_global_struct->input_buttons = ucmd->buttons;
if (pr_global_ptrs->input_weapon) if (pr_global_ptrs->input_weapon)
@ -10462,6 +10467,7 @@ qboolean SV_RunFullQCMovement(client_t *client, usercmd_t *ucmd)
} }
//prethink should be consistant with what the engine normally does //prethink should be consistant with what the engine normally does
pr_global_struct->time = sv.time;
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, client->edict); pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, client->edict);
PR_ExecuteProgram (svprogfuncs, pr_global_struct->PlayerPreThink); PR_ExecuteProgram (svprogfuncs, pr_global_struct->PlayerPreThink);
WPhys_RunThink (&sv.world, (wedict_t*)client->edict); WPhys_RunThink (&sv.world, (wedict_t*)client->edict);
@ -12706,6 +12712,8 @@ void PR_DumpPlatform_f(void)
{"end_sys_fields", "void", QW|NQ|CS|MENU}, {"end_sys_fields", "void", QW|NQ|CS|MENU},
{"time", "float", MENU, D("The current local time. Increases while paused.")}, {"time", "float", MENU, D("The current local time. Increases while paused.")},
{"input_servertime", "float", QW|NQ|CS, D("Server's timestamp of the client's interpolation state.")},
// {"input_clienttime", "float", QW|NQ|CS, D("This is the timestamp that player prediction is simulating.")},
{"input_timelength", "float", QW|NQ}, {"input_timelength", "float", QW|NQ},
{"input_angles", "vector", QW|NQ, D("+x=DOWN")}, {"input_angles", "vector", QW|NQ, D("+x=DOWN")},
{"input_movevalues", "vector", QW|NQ}, {"input_movevalues", "vector", QW|NQ},

View file

@ -104,6 +104,8 @@ typedef struct nqglobalvars_s
pvec_t *physics_mode; pvec_t *physics_mode;
pvec_t *clientcommandframe; pvec_t *clientcommandframe;
pvec_t *input_servertime;
pvec_t *input_clienttime;
pvec_t *input_timelength; pvec_t *input_timelength;
pvec_t *input_impulse; pvec_t *input_impulse;
pvec3_t *input_angles; pvec3_t *input_angles;

View file

@ -7946,9 +7946,14 @@ void SV_ExecuteClientMessage (client_t *cl)
qbyte checksum, calculatedChecksum; qbyte checksum, calculatedChecksum;
int seq_hash; int seq_hash;
if (!cl->frameunion.frames)
{
Con_Printf("Server bug: No frames!\n");
cl->send_message = false;
return; //shouldn't happen...
}
// calc ping time // calc ping time
if (cl->frameunion.frames)
{ //split screen doesn't always have frames.
frame = &cl->frameunion.frames[cl->netchan.incoming_acknowledged & UPDATE_MASK]; frame = &cl->frameunion.frames[cl->netchan.incoming_acknowledged & UPDATE_MASK];
if (cl->lastsequence_acknowledged + UPDATE_BACKUP > cl->netchan.incoming_acknowledged) if (cl->lastsequence_acknowledged + UPDATE_BACKUP > cl->netchan.incoming_acknowledged)
@ -7988,13 +7993,6 @@ void SV_ExecuteClientMessage (client_t *cl)
} }
else else
cl->laggedents_count = 0; cl->laggedents_count = 0;
}
else
{
Con_Printf("Server bug: No frames!\n");
cl->send_message = false;
return; //shouldn't happen...
}
// make sure the reply sequence number matches the incoming // make sure the reply sequence number matches the incoming
// sequence number // sequence number
@ -8076,6 +8074,8 @@ void SV_ExecuteClientMessage (client_t *cl)
else else
{ {
MSGQW_ReadDeltaUsercmd (&nullcmd, &oldest, PROTOCOL_VERSION_QW); MSGQW_ReadDeltaUsercmd (&nullcmd, &oldest, PROTOCOL_VERSION_QW);
oldest.fservertime = frame->laggedtime; //not very accurate, but our best guess.
oldest.servertime = frame->laggedtime*1000; //not very accurate
Vector2Copy(split->lastcmd.cursor_screen, oldest.cursor_screen); Vector2Copy(split->lastcmd.cursor_screen, oldest.cursor_screen);
VectorCopy(split->lastcmd.cursor_start, oldest.cursor_start); VectorCopy(split->lastcmd.cursor_start, oldest.cursor_start);
VectorCopy(split->lastcmd.cursor_impact, oldest.cursor_impact); VectorCopy(split->lastcmd.cursor_impact, oldest.cursor_impact);