+ if (!host_client->spawned)
+ return;
+ if (sv_readmoves[sv_numreadmoves-1].sequence && sv_clmovement_enable.integer && sv_clmovement_waitforinput.integer > 0)
+ {
+ // process the moves in order and ignore old ones
+ // but always trust the latest move
+ // (this deals with bogus initial move sequences after level change,
+ // where the client will eventually catch up with the level change
+ // and reset its move sequence)
+ for (moveindex = 0;moveindex < sv_numreadmoves;moveindex++)
+ {
+ usercmd_t *move = sv_readmoves + moveindex;
+ if (host_client->cmd.sequence < move->sequence || moveindex == sv_numreadmoves - 1)
+ {
+ // this is a new move
+ moveframetime = bound(0, move->time - host_client->cmd.time, 0.1);
+ //Con_Printf("movesequence = %i (%i lost), moveframetime = %f\n", move->sequence, move->sequence ? move->sequence - host_client->movesequence - 1 : 0, moveframetime);
+ host_client->cmd = *move;
+ host_client->movesequence = move->sequence;
+
+ // if using prediction, we need to perform moves when packets are
+ // received, even if multiple occur in one frame
+ // (they can't go beyond the current time so there is no cheat issue
+ // with this approach, and if they don't send input for a while they
+ // start moving anyway, so the longest 'lagaport' possible is
+ // determined by the sv_clmovement_waitforinput cvar)
+ if (moveframetime <= 0)
+ continue;
+ oldframetime = prog->globals.server->frametime;
+ oldframetime2 = sv.frametime;
+ // update ping time for qc to see while executing this move
+ host_client->ping = host_client->cmd.receivetime - host_client->cmd.time;
+ // the server and qc frametime values must be changed temporarily
+ sv.frametime = moveframetime;
+ prog->globals.server->frametime = moveframetime;
+ SV_Physics_ClientEntity(host_client->edict);
+ sv.frametime = oldframetime2;
+ prog->globals.server->frametime = oldframetime;
+ host_client->clmovement_skipphysicsframes = sv_clmovement_waitforinput.integer;
+ }
+ }
+ }
+ else