X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=sv_user.c;h=23a98966a07ccb2842698a8ef539d7586e6e1dbd;hb=658d44cb461c2c60ce86ab48efa918f242c33196;hp=6bdd8ba9d90eca5d987d6bc8e437fadbbfa504ff;hpb=5a13189621f6a615dc7d0e79420907bf64b63ebb;p=xonotic%2Fdarkplaces.git diff --git a/sv_user.c b/sv_user.c index 6bdd8ba9..23a98966 100644 --- a/sv_user.c +++ b/sv_user.c @@ -38,12 +38,12 @@ SV_SetIdealPitch #define MAX_FORWARD 6 void SV_SetIdealPitch (void) { - float angleval, sinval, cosval; + float angleval, sinval, cosval, step, dir; trace_t tr; vec3_t top, bottom; float z[MAX_FORWARD]; int i, j; - int step, dir, steps; + int steps; if (!((int)host_client->edict->fields.server->flags & FL_ONGROUND)) return; @@ -602,14 +602,22 @@ void SV_ClientThink(void) SV_ReadClientMove =================== */ -void SV_ReadClientMove (void) +qboolean SV_ReadClientMove (void) { + qboolean kickplayer = false; int i; double oldmovetime; +#ifdef NUM_PING_TIMES + double total; +#endif usercmd_t *move = &host_client->cmd; oldmovetime = move->time; + // if this move has been applied, clear it, and start accumulating new data + if (move->applied) + memset(move, 0, sizeof(*move)); + if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__); // read ping time @@ -619,6 +627,16 @@ void SV_ReadClientMove (void) if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__); move->receivetime = sv.time; + // calculate average ping time + host_client->ping = move->receivetime - move->time; +#ifdef NUM_PING_TIMES + host_client->ping_times[host_client->num_pings % NUM_PING_TIMES] = move->receivetime - move->time; + host_client->num_pings++; + for (i=0, total = 0;i < NUM_PING_TIMES;i++) + total += host_client->ping_times[i]; + host_client->ping = total / NUM_PING_TIMES; +#endif + // read current angles for (i = 0;i < 3;i++) { @@ -681,50 +699,57 @@ void SV_ReadClientMove (void) if (!host_client->spawned) memset(move, 0, sizeof(*move)); + else if (move->time > (float)sv.time + 0.001f) // add a little fuzz factor due to float precision issues + { + Con_DPrintf("client move->time %f > sv.time %f, kicking\n", move->time, sv.time); + // if the client is lying about time, we have definitively detected a + // speed cheat attempt of the worst sort, and we can immediately kick + // the offending player off. + // this fixes the timestamp to prevent a speed cheat from working + move->time = sv.time; + // but we kick the player for good measure + kickplayer = true; + } else { // apply the latest accepted move to the entity fields host_client->movesequence = move->sequence; if (host_client->movesequence) { - double frametime = move->time - oldmovetime; + double frametime = bound(0, move->time - oldmovetime, 0.1); double oldframetime = prog->globals.server->frametime; - if (frametime > 0.1) - frametime = 0.1; + //if (move->time - oldmovetime >= 0.1001) + // Con_DPrintf("client move exceeds 100ms! (time %f -> time %f)\n", oldmovetime, move->time); prog->globals.server->frametime = frametime; SV_Physics_ClientEntity(host_client->edict); prog->globals.server->frametime = oldframetime; } } + return kickplayer; } void SV_ApplyClientMove (void) { -#ifdef NUM_PING_TIMES - int i; - float total; -#endif prvm_eval_t *val; usercmd_t *move = &host_client->cmd; if (!move->receivetime) return; - // calculate average ping time - host_client->ping = move->receivetime - move->time; -#ifdef NUM_PING_TIMES - host_client->ping_times[host_client->num_pings % NUM_PING_TIMES] = move->receivetime - move->time; - host_client->num_pings++; - for (i=0, total = 0;i < NUM_PING_TIMES;i++) - total += host_client->ping_times[i]; - host_client->ping = total / NUM_PING_TIMES; -#endif + // note: a move can be applied multiple times if the client packets are + // not coming as often as the physics is executed, and the move must be + // applied before running qc each time because the id1 qc had a bug where + // it clears self.button2 in PlayerJump, causing pogostick behavior if + // moves are not applied every time before calling qc + move->applied = true; // set the edict fields host_client->edict->fields.server->button0 = move->buttons & 1; host_client->edict->fields.server->button2 = (move->buttons & 2)>>1; if (move->impulse) host_client->edict->fields.server->impulse = move->impulse; + // only send the impulse to qc once + move->impulse = 0; VectorCopy(move->viewangles, host_client->edict->fields.server->v_angle); if ((val = PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_button3))) val->_float = ((move->buttons >> 2) & 1); if ((val = PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_button4))) val->_float = ((move->buttons >> 3) & 1); @@ -749,8 +774,6 @@ void SV_ApplyClientMove (void) if ((val = PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_cursor_trace_endpos))) VectorCopy(move->cursor_impact, val->vector); if ((val = PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_cursor_trace_ent))) val->edict = PRVM_EDICT_TO_PROG(PRVM_EDICT_NUM(move->cursor_entitynumber)); if ((val = PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_ping))) val->_float = host_client->ping * 1000.0; - - memset(move, 0, sizeof(*move)); } void SV_FrameLost(int framenum) @@ -798,7 +821,7 @@ void SV_ReadClientMessage(void) return; } - cmd = MSG_ReadChar (); + cmd = MSG_ReadByte (); if (cmd == -1) { // end of message @@ -854,7 +877,9 @@ void SV_ReadClientMessage(void) return; case clc_move: - SV_ReadClientMove (); + // if ReadClientMove returns true, the client tried to speed cheat + if (SV_ReadClientMove ()) + SV_DropClient (false); break; case clc_ackframe: