// sv_user.c -- server code for moving users
#include "quakedef.h"
+#include "sv_demo.h"
#define DEBUGMOVES 0
static usercmd_t cmd;
+extern cvar_t sv_autodemo_perclient;
/*
===============
// noclip
VectorCopy (wishvel, host_client->edict->fields.server->velocity);
}
- else if (onground && (!sv_gameplayfix_qwplayerphysics.integer || !host_client->edict->fields.server->button2 || !((int)host_client->edict->fields.server->flags & FL_JUMPRELEASED)))
+ else if (onground)
{
SV_UserFriction ();
SV_Accelerate ();
{
vec3_t v_angle;
+ //Con_Printf("clientthink for %ims\n", (int) (sv.frametime * 1000));
+
SV_ApplyClientMove();
// make sure the velocity is sane (not a NaN)
SV_CheckVelocity(host_client->edict);
// read ping time
if (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE && sv.protocol != PROTOCOL_NEHAHRABJP && sv.protocol != PROTOCOL_NEHAHRABJP2 && sv.protocol != PROTOCOL_NEHAHRABJP3 && sv.protocol != PROTOCOL_DARKPLACES1 && sv.protocol != PROTOCOL_DARKPLACES2 && sv.protocol != PROTOCOL_DARKPLACES3 && sv.protocol != PROTOCOL_DARKPLACES4 && sv.protocol != PROTOCOL_DARKPLACES5 && sv.protocol != PROTOCOL_DARKPLACES6)
move->sequence = MSG_ReadLong ();
- move->time = MSG_ReadFloat ();
+ move->time = move->clienttime = MSG_ReadFloat ();
if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
move->receivetime = (float)sv.time;
Con_Printf("%smove #%i %ims (%ims) %i %i '%i %i %i' '%i %i %i'\n", (move->time - host_client->cmd.time) > sv.frametime * 1.01 ? "^1" : "^2", move->sequence, (int)floor((move->time - host_client->cmd.time) * 1000.0 + 0.5), (int)floor(move->time * 1000.0 + 0.5), move->impulse, move->buttons, (int)move->viewangles[0], (int)move->viewangles[1], (int)move->viewangles[2], (int)move->forwardmove, (int)move->sidemove, (int)move->upmove);
#endif
// this is a new move
+ move->time = bound(sv.time - 1, move->time, sv.time); // prevent slowhack/speedhack combos
move->time = max(move->time, host_client->cmd.time); // prevent backstepping of time
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);
}
// now copy the new move
host_client->cmd = sv_readmoves[sv_numreadmoves-1];
+ host_client->cmd.time = max(host_client->cmd.time, sv.time);
+ // physics will run up to sv.time, so allow no predicted moves
+ // before that otherwise, there is a speedhack by turning
+ // prediction on and off repeatedly on client side because the
+ // engine would run BOTH client and server physics for the same
+ // time
host_client->movesequence = 0;
// make sure that normal physics takes over immediately
host_client->clmovement_skipphysicsframes = 0;
}
// calculate average ping time
- host_client->ping = host_client->cmd.receivetime - host_client->cmd.time;
+ host_client->ping = host_client->cmd.receivetime - host_client->cmd.clienttime;
#ifdef NUM_PING_TIMES
- host_client->ping_times[host_client->num_pings % NUM_PING_TIMES] = host_client->cmd.receivetime - host_client->cmd.time;
+ host_client->ping_times[host_client->num_pings % NUM_PING_TIMES] = host_client->cmd.receivetime - host_client->cmd.clienttime;
host_client->num_pings++;
for (i=0, total = 0;i < NUM_PING_TIMES;i++)
total += host_client->ping_times[i];
int cmd, num, start;
char *s, *p, *q;
+ if(sv_autodemo_perclient.integer >= 2)
+ SV_WriteDemoMessage(host_client, &(host_client->netconnection->message), true);
+
//MSG_BeginReading ();
sv_numreadmoves = 0;