mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-22 12:01:25 +00:00
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:
parent
8b4a282c47
commit
f810be4830
6 changed files with 103 additions and 83 deletions
|
@ -906,40 +906,10 @@ void CL_PredictEntityMovement(entity_state_t *estate, float age)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
CL_PredictMove
|
||||
==============
|
||||
*/
|
||||
void CL_PredictMovePNum (int seat)
|
||||
float CL_GetPredictionRealtime(playerview_t *pv)
|
||||
{
|
||||
//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;
|
||||
|
||||
//these are to make svc_viewentity work better
|
||||
float simtime;
|
||||
//these are to make svc_viewentity work better
|
||||
float netfps = cl_netfps.value;
|
||||
|
||||
if (!netfps)
|
||||
|
@ -978,6 +948,43 @@ void CL_PredictMovePNum (int seat)
|
|||
simtime -= cls.latency; //push back when playing demos.
|
||||
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);
|
||||
|
||||
if (!pv->spectator && (pv->cam_state != CAM_FREECAM || pv->cam_spec_track != -1)) //just in case
|
||||
|
|
|
@ -3941,6 +3941,8 @@ static void cs_get_input_state (usercmd_t *cmd)
|
|||
cmd->fservertime = *csqcg.input_servertime;
|
||||
cmd->servertime = *csqcg.input_servertime*1000;
|
||||
}
|
||||
if (csqcg.input_clienttime)
|
||||
cmd->fclienttime = *csqcg.input_clienttime;
|
||||
|
||||
if (csqcg.input_cursor_screen)
|
||||
Vector2Copy(csqcg.input_cursor_screen, cmd->cursor_screen);
|
||||
|
|
|
@ -1454,21 +1454,21 @@ void MSGFTE_WriteDeltaUsercmd (sizebuf_t *buf, const usercmd_t *from, const user
|
|||
if (bits & UC_FORWARD)
|
||||
{
|
||||
if (bits & UC_BIGMOVES)
|
||||
MSG_WriteShort(buf, cmd->forwardmove);
|
||||
MSG_WriteInt64(buf, cmd->forwardmove);
|
||||
else
|
||||
MSG_WriteChar(buf, cmd->forwardmove/5);
|
||||
}
|
||||
if (bits & UC_RIGHT)
|
||||
{
|
||||
if (bits & UC_BIGMOVES)
|
||||
MSG_WriteShort(buf, cmd->sidemove);
|
||||
MSG_WriteInt64(buf, cmd->sidemove);
|
||||
else
|
||||
MSG_WriteChar(buf, cmd->sidemove/5);
|
||||
}
|
||||
if (bits & UC_UP)
|
||||
{
|
||||
if (bits & UC_BIGMOVES)
|
||||
MSG_WriteShort(buf, cmd->upmove);
|
||||
MSG_WriteInt64(buf, cmd->upmove);
|
||||
else
|
||||
MSG_WriteChar(buf, cmd->upmove/5);
|
||||
}
|
||||
|
@ -1548,6 +1548,7 @@ void MSGFTE_ReadDeltaUsercmd (const usercmd_t *from, usercmd_t *cmd)
|
|||
}
|
||||
*cmd = *from;
|
||||
cmd->servertime = from->servertime+MSG_ReadUInt64();
|
||||
cmd->fservertime = cmd->servertime/1000.0;
|
||||
for (i = 0; i < 3; 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_BIGMOVES)
|
||||
cmd->forwardmove = MSG_ReadShort();
|
||||
cmd->forwardmove = MSG_ReadInt64();
|
||||
else
|
||||
cmd->forwardmove = MSG_ReadChar()*5;
|
||||
}
|
||||
if (bits & UC_RIGHT)
|
||||
{
|
||||
if (bits & UC_BIGMOVES)
|
||||
cmd->sidemove = MSG_ReadShort();
|
||||
cmd->sidemove = MSG_ReadInt64();
|
||||
else
|
||||
cmd->sidemove = MSG_ReadChar()*5;
|
||||
}
|
||||
if (bits & UC_UP)
|
||||
{
|
||||
if (bits & UC_BIGMOVES)
|
||||
cmd->upmove = MSG_ReadShort();
|
||||
cmd->upmove = MSG_ReadInt64();
|
||||
else
|
||||
cmd->upmove = MSG_ReadChar()*5;
|
||||
}
|
||||
|
|
|
@ -1008,6 +1008,7 @@ void PR_LoadGlabalStruct(qboolean muted)
|
|||
globalvec (false, input_right_angles) \
|
||||
globalvec (false, input_right_velocity) \
|
||||
globalvec (false, input_right_avelocity) \
|
||||
globalfloat (false, input_servertime) \
|
||||
\
|
||||
globalint (false, serverid) \
|
||||
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)[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)
|
||||
pr_global_struct->input_buttons = ucmd->buttons;
|
||||
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
|
||||
pr_global_struct->time = sv.time;
|
||||
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, client->edict);
|
||||
PR_ExecuteProgram (svprogfuncs, pr_global_struct->PlayerPreThink);
|
||||
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},
|
||||
|
||||
{"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_angles", "vector", QW|NQ, D("+x=DOWN")},
|
||||
{"input_movevalues", "vector", QW|NQ},
|
||||
|
|
|
@ -104,6 +104,8 @@ typedef struct nqglobalvars_s
|
|||
pvec_t *physics_mode;
|
||||
|
||||
pvec_t *clientcommandframe;
|
||||
pvec_t *input_servertime;
|
||||
pvec_t *input_clienttime;
|
||||
pvec_t *input_timelength;
|
||||
pvec_t *input_impulse;
|
||||
pvec3_t *input_angles;
|
||||
|
|
|
@ -7946,56 +7946,54 @@ void SV_ExecuteClientMessage (client_t *cl)
|
|||
qbyte checksum, calculatedChecksum;
|
||||
int seq_hash;
|
||||
|
||||
// calc ping time
|
||||
if (cl->frameunion.frames)
|
||||
{ //split screen doesn't always have frames.
|
||||
frame = &cl->frameunion.frames[cl->netchan.incoming_acknowledged & UPDATE_MASK];
|
||||
|
||||
if (cl->lastsequence_acknowledged + UPDATE_BACKUP > cl->netchan.incoming_acknowledged)
|
||||
{
|
||||
/*note that if there is packetloss, we can change a single frame's ping_time multiple times
|
||||
this means that the 'ping' is more latency than ping times*/
|
||||
if (frame->ping_time == -1 || !sv_ping_ignorepl.ival)
|
||||
frame->ping_time = realtime - frame->senttime; //no more phenomanally low pings please
|
||||
|
||||
if (cl->spectator)
|
||||
cl->delay = 0;
|
||||
else
|
||||
{
|
||||
float diff = frame->ping_time*1000 - sv_minping.value;
|
||||
if (fabs(diff) > 1)
|
||||
{
|
||||
//FIXME: we should use actual arrival times instead, so we don't get so much noise and seesawing.
|
||||
diff = bound(-25, diff, 25); //don't swing wildly
|
||||
cl->delay -= 0.001*(diff/25); //scale towards the ideal value
|
||||
cl->delay = bound(0, cl->delay, 1); //but make sure things don't go crazy
|
||||
}
|
||||
}
|
||||
if (cl->penalties & BAN_LAGGED)
|
||||
if (cl->delay < 0.2)
|
||||
cl->delay = 0.2;
|
||||
}
|
||||
|
||||
if (sv_antilag.ival || !*sv_antilag.string)
|
||||
{
|
||||
#ifdef warningmsg
|
||||
#pragma warningmsg("FIXME: make antilag optionally support non-player ents too")
|
||||
#endif
|
||||
cl->laggedents_count = sv.allocated_client_slots;
|
||||
memcpy(cl->laggedents, frame->laggedplayer, sizeof(*cl->laggedents)*cl->laggedents_count);
|
||||
cl->laggedents_time = frame->laggedtime;
|
||||
cl->laggedents_frac = !*sv_antilag_frac.string?1:sv_antilag_frac.value;
|
||||
}
|
||||
else
|
||||
cl->laggedents_count = 0;
|
||||
}
|
||||
else
|
||||
if (!cl->frameunion.frames)
|
||||
{
|
||||
Con_Printf("Server bug: No frames!\n");
|
||||
cl->send_message = false;
|
||||
return; //shouldn't happen...
|
||||
}
|
||||
|
||||
// calc ping time
|
||||
frame = &cl->frameunion.frames[cl->netchan.incoming_acknowledged & UPDATE_MASK];
|
||||
|
||||
if (cl->lastsequence_acknowledged + UPDATE_BACKUP > cl->netchan.incoming_acknowledged)
|
||||
{
|
||||
/*note that if there is packetloss, we can change a single frame's ping_time multiple times
|
||||
this means that the 'ping' is more latency than ping times*/
|
||||
if (frame->ping_time == -1 || !sv_ping_ignorepl.ival)
|
||||
frame->ping_time = realtime - frame->senttime; //no more phenomanally low pings please
|
||||
|
||||
if (cl->spectator)
|
||||
cl->delay = 0;
|
||||
else
|
||||
{
|
||||
float diff = frame->ping_time*1000 - sv_minping.value;
|
||||
if (fabs(diff) > 1)
|
||||
{
|
||||
//FIXME: we should use actual arrival times instead, so we don't get so much noise and seesawing.
|
||||
diff = bound(-25, diff, 25); //don't swing wildly
|
||||
cl->delay -= 0.001*(diff/25); //scale towards the ideal value
|
||||
cl->delay = bound(0, cl->delay, 1); //but make sure things don't go crazy
|
||||
}
|
||||
}
|
||||
if (cl->penalties & BAN_LAGGED)
|
||||
if (cl->delay < 0.2)
|
||||
cl->delay = 0.2;
|
||||
}
|
||||
|
||||
if (sv_antilag.ival || !*sv_antilag.string)
|
||||
{
|
||||
#ifdef warningmsg
|
||||
#pragma warningmsg("FIXME: make antilag optionally support non-player ents too")
|
||||
#endif
|
||||
cl->laggedents_count = sv.allocated_client_slots;
|
||||
memcpy(cl->laggedents, frame->laggedplayer, sizeof(*cl->laggedents)*cl->laggedents_count);
|
||||
cl->laggedents_time = frame->laggedtime;
|
||||
cl->laggedents_frac = !*sv_antilag_frac.string?1:sv_antilag_frac.value;
|
||||
}
|
||||
else
|
||||
cl->laggedents_count = 0;
|
||||
|
||||
// make sure the reply sequence number matches the incoming
|
||||
// sequence number
|
||||
if (cl->netchan.incoming_sequence >= cl->netchan.outgoing_sequence)
|
||||
|
@ -8076,6 +8074,8 @@ void SV_ExecuteClientMessage (client_t *cl)
|
|||
else
|
||||
{
|
||||
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);
|
||||
VectorCopy(split->lastcmd.cursor_start, oldest.cursor_start);
|
||||
VectorCopy(split->lastcmd.cursor_impact, oldest.cursor_impact);
|
||||
|
|
Loading…
Reference in a new issue