From 7f14f85a7c33e861d57032518c7a32915a089b68 Mon Sep 17 00:00:00 2001 From: havoc Date: Sat, 11 Jun 2005 16:42:02 +0000 Subject: [PATCH] split CL_ClientMovement into CL_ClientMovement_Input (called each input packet) and CL_ClientMovement_Replay (called each frame) functions to cure a feedback loop that could freeze up a client with a full prediction queue (prediction became slower with each queue item, and the server was not affected by the slowness of the replay, so it could keep the client busy with an endless packet stream and the client would never catch up) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@5423 d7cf8633-e32d-0410-b094-e92efae38249 --- cl_input.c | 91 +++++++++++++++++++++++++++++++----------------------- cl_main.c | 2 ++ client.h | 2 ++ 3 files changed, 56 insertions(+), 39 deletions(-) diff --git a/cl_input.c b/cl_input.c index 3cea0ef2..03421328 100644 --- a/cl_input.c +++ b/cl_input.c @@ -492,37 +492,10 @@ void CL_UpdatePrydonCursor(void) //CL_SparkShower(cl.cmd.cursor_impact, cl.cmd.cursor_normal, 5, 0); } -void CL_ClientMovement(qboolean buttonjump, qboolean buttoncrouch) +void CL_ClientMovement_Input(qboolean buttonjump, qboolean buttoncrouch) { int i; int n; - int bump; - int contents; - int crouch; - int onground; - double edgefriction; - double frametime; - double t; - vec_t wishspeed; - vec_t addspeed; - vec_t accelspeed; - vec_t f; - vec_t *playermins; - vec_t *playermaxs; - vec3_t currentorigin; - vec3_t currentvelocity; - vec3_t forward; - vec3_t right; - vec3_t up; - vec3_t wishvel; - vec3_t wishdir; - vec3_t neworigin; - vec3_t currentorigin2; - vec3_t neworigin2; - vec3_t yawangles; - trace_t trace; - trace_t trace2; - trace_t trace3; // remove stale queue items n = cl.movement_numqueue; cl.movement_numqueue = 0; @@ -554,26 +527,66 @@ void CL_ClientMovement(qboolean buttonjump, qboolean buttoncrouch) cl.movement_queue[cl.movement_numqueue].crouch = buttoncrouch; cl.movement_numqueue++; } + cl.movement = cl_movement.integer && cl.stats[STAT_HEALTH] > 0 && !cls.demoplayback && !cl.intermission; + // clear queue if client movement is disabled + if (!cl.movement) + cl.movement_numqueue = 0; + cl.movement_replay = true; +} + +void CL_ClientMovement_Replay(void) +{ + int i; + int bump; + int contents; + int crouch; + int onground; + double edgefriction; + double frametime; + double t; + vec_t wishspeed; + vec_t addspeed; + vec_t accelspeed; + vec_t f; + vec_t *playermins; + vec_t *playermaxs; + vec3_t currentorigin; + vec3_t currentvelocity; + vec3_t forward; + vec3_t right; + vec3_t up; + vec3_t wishvel; + vec3_t wishdir; + vec3_t neworigin; + vec3_t currentorigin2; + vec3_t neworigin2; + vec3_t yawangles; + trace_t trace; + trace_t trace2; + trace_t trace3; + if (!cl.movement_replay) + return; + cl.movement_replay = false; + // fetch current starting values VectorCopy(cl_entities[cl.playerentity].state_current.origin, currentorigin); VectorCopy(cl.mvelocity[0], currentvelocity); - // check if onground - VectorSet(currentorigin2, currentorigin[0], currentorigin[1], currentorigin[2] + 1); - VectorSet(neworigin2, currentorigin[0], currentorigin[1], currentorigin[2] - 1); - trace = CL_TraceBox(currentorigin2, cl_playercrouchmins, cl_playercrouchmaxs, neworigin2, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_PLAYERCLIP, true); - onground = trace.fraction < 1 && trace.plane.normal[2] > 0.7; // FIXME: try minor nudges in various directions if startsolid to find a // safe place to start the walk (due to network compression in some // protocols this starts in solid) //currentorigin[2] += (1.0 / 32.0); // slight nudge to get out of the floor crouch = false; // this will be updated on first move + + // check if onground + VectorSet(currentorigin2, currentorigin[0], currentorigin[1], currentorigin[2] + 1); + VectorSet(neworigin2, currentorigin[0], currentorigin[1], currentorigin[2] - 1); + trace = CL_TraceBox(currentorigin2, cl_playercrouchmins, cl_playercrouchmaxs, neworigin2, true, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_PLAYERCLIP, true); + onground = trace.fraction < 1 && trace.plane.normal[2] > 0.7; //Con_Printf("%f: ", cl.mtime[0]); - // replay input queue, and remove any stale queue items + + // replay the input queue to predict current location // note: this relies on the fact there's always one queue item at the end - // abort if client movement is disabled - cl.movement = cl_movement.integer && cl.stats[STAT_HEALTH] > 0 && !cls.demoplayback && !cl.intermission; - if (!cl.movement) - cl.movement_numqueue = 0; + for (i = 0;i < cl.movement_numqueue;i++) { client_movementqueue_t *q = cl.movement_queue + bound(0, i, cl.movement_numqueue - 1); @@ -956,7 +969,7 @@ void CL_SendMove(void) return; // FIXME: bits & 16 is +button5, Nexuiz specific - CL_ClientMovement((bits & 2) != 0, (bits & 16) != 0); + CL_ClientMovement_Input((bits & 2) != 0, (bits & 16) != 0); if (NetConn_SendUnreliableMessage(cls.netcon, &buf) == -1) { diff --git a/cl_main.c b/cl_main.c index 268a05fa..5e4a52c1 100644 --- a/cl_main.c +++ b/cl_main.c @@ -1247,6 +1247,7 @@ CL_ReadFromServer Read all incoming data from the server =============== */ +extern void CL_ClientMovement_Replay(); int CL_ReadFromServer(void) { CL_ReadDemoMessage(); @@ -1267,6 +1268,7 @@ int CL_ReadFromServer(void) V_FadeViewFlashs(); // relink network entities (note: this sets up the view!) + CL_ClientMovement_Replay(); CL_RelinkNetworkEntities(); // move particles diff --git a/client.h b/client.h index c5343650..8b69151c 100644 --- a/client.h +++ b/client.h @@ -526,6 +526,8 @@ typedef struct // client movement simulation // these fields are only updated by CL_ClientMovement (called by CL_SendMove after parsing each network packet) qboolean movement; + // indicates the queue has been updated and should be replayed + qboolean movement_replay; // simulated data (this is valid even if cl.movement is false) vec3_t movement_origin; vec3_t movement_oldorigin; -- 2.39.2