X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=sv_user.c;h=966c0551366c965cbe14d2089912485f51449531;hb=b84125ed0d5fc6922a9ea18b7762b489e377175d;hp=77fc45dab8ea0ab833531c732d053dbfc20d5500;hpb=5bac5aa50dedaa328126189009d8e56fc9b4d178;p=xonotic%2Fdarkplaces.git diff --git a/sv_user.c b/sv_user.c index 77fc45da..966c0551 100644 --- a/sv_user.c +++ b/sv_user.c @@ -602,15 +602,18 @@ void SV_ClientThink(void) SV_ReadClientMove =================== */ -void SV_ApplyClientMove (void); -void SV_ReadClientMove (void) +qboolean SV_ReadClientMove (void) { + qboolean kickplayer = false; int i; double oldmovetime; usercmd_t *move = &host_client->cmd; oldmovetime = move->time; - memset(move, 0, sizeof(usercmd_t)); + + // 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__); @@ -642,14 +645,18 @@ void SV_ReadClientMove (void) if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__); // read buttons + // be sure to bitwise OR them into the move->buttons because we want to + // accumulate button presses from multiple packets per actual move if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5) - move->buttons = MSG_ReadByte (); + move->buttons |= MSG_ReadByte (); else - move->buttons = MSG_ReadLong (); + move->buttons |= MSG_ReadLong (); if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__); // read impulse - move->impulse = MSG_ReadByte (); + i = MSG_ReadByte (); + if (i) + move->impulse = i; if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__); // PRYDON_CLIENTCURSOR @@ -679,22 +686,33 @@ 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 - SV_ApplyClientMove(); 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) @@ -706,6 +724,11 @@ void SV_ApplyClientMove (void) prvm_eval_t *val; usercmd_t *move = &host_client->cmd; + if (!move->receivetime || move->applied) + return; + + move->applied = true; + // calculate average ping time host_client->ping = move->receivetime - move->time; #ifdef NUM_PING_TIMES @@ -848,7 +871,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: