X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=sv_user.c;h=2c148e852d87e1c2d0d538c3c612a420a522de6d;hb=0f3e880c9e2d7f490bfb4e8a1c318bd7428a695b;hp=f251a8bc0c4db2c7ac019596679eccb98a69fb92;hpb=919fbb05eeafd41c867b1f39bb2cc9e5dd61077e;p=xonotic%2Fdarkplaces.git diff --git a/sv_user.c b/sv_user.c index f251a8bc..2c148e85 100644 --- a/sv_user.c +++ b/sv_user.c @@ -21,11 +21,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" -cvar_t sv_edgefriction = {0, "edgefriction", "2"}; -cvar_t sv_deltacompress = {0, "sv_deltacompress", "1"}; -cvar_t sv_idealpitchscale = {0, "sv_idealpitchscale","0.8"}; -cvar_t sv_maxspeed = {CVAR_NOTIFY, "sv_maxspeed", "320"}; -cvar_t sv_accelerate = {0, "sv_accelerate", "10"}; +cvar_t sv_edgefriction = {0, "edgefriction", "2", "how much you slow down when nearing a ledge you might fall off"}; +cvar_t sv_idealpitchscale = {0, "sv_idealpitchscale","0.8", "how much to look up/down slopes and stairs when not using freelook"}; +cvar_t sv_maxspeed = {CVAR_NOTIFY, "sv_maxspeed", "320", "maximum speed a player can accelerate to when on ground (can be exceeded by tricks)"}; +cvar_t sv_maxairspeed = {0, "sv_maxairspeed", "30", "maximum speed a player can accelerate to when airborn (note that it is possible to completely stop by moving the opposite direction)"}; +cvar_t sv_accelerate = {0, "sv_accelerate", "10", "rate at which a player accelerates to sv_maxspeed"}; static usercmd_t cmd; @@ -176,8 +176,8 @@ void SV_AirAccelerate (vec3_t wishveloc) float addspeed, wishspd, accelspeed, currentspeed; wishspd = VectorNormalizeLength (wishveloc); - if (wishspd > 30) - wishspd = 30; + if (wishspd > sv_maxairspeed.value) + wishspd = sv_maxairspeed.value; currentspeed = DotProduct (host_client->edict->fields.server->velocity, wishveloc); addspeed = wishspd - currentspeed; if (addspeed <= 0) @@ -602,16 +602,17 @@ void SV_ClientThink(void) SV_ReadClientMove =================== */ -extern void SV_Physics_Entity (prvm_edict_t *ent, qboolean runmove); -void SV_ApplyClientMove (void); -void SV_ReadClientMove (void) +qboolean SV_ReadClientMove (void) { 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__); @@ -643,14 +644,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 @@ -680,10 +685,20 @@ void SV_ReadClientMove (void) if (!host_client->spawned) memset(move, 0, sizeof(*move)); + else if (move->time > sv.time + 0.01) // 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 + return true; + } else { // apply the latest accepted move to the entity fields - SV_ApplyClientMove(); host_client->movesequence = move->sequence; if (host_client->movesequence) { @@ -692,10 +707,11 @@ void SV_ReadClientMove (void) if (frametime > 0.1) frametime = 0.1; prog->globals.server->frametime = frametime; - SV_Physics_Entity(host_client->edict, true); + SV_Physics_ClientEntity(host_client->edict); prog->globals.server->frametime = oldframetime; } } + return false; } void SV_ApplyClientMove (void) @@ -707,6 +723,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 @@ -729,6 +750,14 @@ void SV_ApplyClientMove (void) if ((val = PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_button6))) val->_float = ((move->buttons >> 5) & 1); if ((val = PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_button7))) val->_float = ((move->buttons >> 6) & 1); if ((val = PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_button8))) val->_float = ((move->buttons >> 7) & 1); + if ((val = PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_button9))) val->_float = ((move->buttons >> 11) & 1); + if ((val = PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_button10))) val->_float = ((move->buttons >> 12) & 1); + if ((val = PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_button11))) val->_float = ((move->buttons >> 13) & 1); + if ((val = PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_button12))) val->_float = ((move->buttons >> 14) & 1); + if ((val = PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_button13))) val->_float = ((move->buttons >> 15) & 1); + if ((val = PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_button14))) val->_float = ((move->buttons >> 16) & 1); + if ((val = PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_button15))) val->_float = ((move->buttons >> 17) & 1); + if ((val = PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_button16))) val->_float = ((move->buttons >> 18) & 1); if ((val = PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_buttonuse))) val->_float = ((move->buttons >> 8) & 1); if ((val = PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_buttonchat))) val->_float = ((move->buttons >> 9) & 1); if ((val = PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_cursor_active))) val->_float = ((move->buttons >> 10) & 1); @@ -841,7 +870,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: @@ -850,7 +881,10 @@ void SV_ReadClientMessage(void) if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__); if (developer_networkentities.integer >= 1) Con_Printf("recv clc_ackframe %i\n", num); - if (host_client->latestframenum < num) + // if the client hasn't progressed through signons yet, + // ignore any clc_ackframes we get (they're probably from the + // previous level) + if (host_client->spawned && host_client->latestframenum < num) { int i; for (i = host_client->latestframenum + 1;i < num;i++)