X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=sv_user.c;h=6d9a39d103bea67b4dbb088581d4827044d8db63;hp=decd9e54cd25999535308dfb9463f7dbbec966fc;hb=980ac035e70ad26a44913dabebe4be5726f966ac;hpb=545926ff9670b675714b3b2d8acbfe19e08483f3 diff --git a/sv_user.c b/sv_user.c index decd9e54..6d9a39d1 100644 --- a/sv_user.c +++ b/sv_user.c @@ -20,9 +20,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // 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; /* =============== @@ -56,7 +58,7 @@ void SV_SetIdealPitch (void) bottom[1] = top[1]; bottom[2] = top[2] - 160; - tr = SV_Move (top, vec3_origin, vec3_origin, bottom, MOVE_NOMONSTERS, host_client->edict, SUPERCONTENTS_SOLID); + tr = SV_TraceLine(top, bottom, MOVE_NOMONSTERS, host_client->edict, SUPERCONTENTS_SOLID); // if looking at a wall, leave ideal the way is was if (tr.startsolid) return; @@ -122,7 +124,7 @@ void SV_UserFriction (void) start[2] = host_client->edict->fields.server->origin[2] + host_client->edict->fields.server->mins[2]; stop[2] = start[2] - 34; - trace = SV_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, host_client->edict, SV_GenericHitSuperContentsMask(host_client->edict)); + trace = SV_TraceLine(start, stop, MOVE_NOMONSTERS, host_client->edict, SV_GenericHitSuperContentsMask(host_client->edict)); if (trace.fraction == 1.0) friction = sv_friction.value*sv_edgefriction.value; @@ -163,6 +165,7 @@ void SV_Accelerate (void) host_client->edict->fields.server->velocity[i] += accelspeed*wishdir[i]; } +extern cvar_t sv_gameplayfix_q2airaccelerate; void SV_AirAccelerate (vec3_t wishveloc) { int i; @@ -175,7 +178,7 @@ void SV_AirAccelerate (vec3_t wishveloc) addspeed = wishspd - currentspeed; if (addspeed <= 0) return; - accelspeed = (sv_airaccelerate.value < 0 ? sv_accelerate.value : sv_airaccelerate.value)*wishspeed * sv.frametime; + accelspeed = (sv_airaccelerate.value < 0 ? sv_accelerate.value : sv_airaccelerate.value)*(sv_gameplayfix_q2airaccelerate.integer ? wishspd : wishspeed) * sv.frametime; if (accelspeed > addspeed) accelspeed = addspeed; @@ -347,7 +350,7 @@ void SV_AirMove (void) // 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 (); @@ -371,6 +374,8 @@ void SV_ClientThink (void) { 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); @@ -388,7 +393,7 @@ void SV_ClientThink (void) if (host_client->edict->fields.server->movetype == MOVETYPE_NONE) return; - onground = (int)host_client->edict->fields.server->flags & FL_ONGROUND; + onground = ((int)host_client->edict->fields.server->flags & FL_ONGROUND) != 0; DropPunchAngle (); @@ -457,7 +462,7 @@ void SV_ReadClientMove (void) // 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; @@ -563,7 +568,7 @@ void SV_ExecuteClientMoves(void) if (ceil(max(sv_readmoves[sv_numreadmoves-1].receivetime - sv_readmoves[sv_numreadmoves-1].time, 0) * 1000.0) < sv_clmovement_minping.integer) host_client->clmovement_disabletimeout = realtime + sv_clmovement_minping_disabletime.value / 1000.0; // several conditions govern whether clientside movement prediction is allowed - if (sv_readmoves[sv_numreadmoves-1].sequence && sv_clmovement_enable.integer && sv_clmovement_waitforinput.integer > 0 && host_client->clmovement_disabletimeout <= realtime && host_client->edict->fields.server->movetype == MOVETYPE_WALK && (!(val = PRVM_EDICTFIELDVALUE(host_client->edict, prog->fieldoffsets.disableclientprediction)) || !val->_float)) + if (sv_readmoves[sv_numreadmoves-1].sequence && sv_clmovement_enable.integer && sv_clmovement_inputtimeout.value > 0 && host_client->clmovement_disabletimeout <= realtime && host_client->edict->fields.server->movetype == MOVETYPE_WALK && (!(val = PRVM_EDICTFIELDVALUE(host_client->edict, prog->fieldoffsets.disableclientprediction)) || !val->_float)) { // process the moves in order and ignore old ones // but always trust the latest move @@ -579,7 +584,16 @@ void SV_ExecuteClientMoves(void) 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 - moveframetime = bound(0, move->time - host_client->cmd.time, 0.1); + 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, min(0.1, sv_clmovement_inputtimeout.value)); + + // discard (treat like lost) moves with too low distance from + // the previous one to prevent hacks using float inaccuracy + // clients will see this as packet loss in the netgraph + if(moveframetime < 0.0005) + continue; + //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; @@ -589,7 +603,7 @@ void SV_ExecuteClientMoves(void) // (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) + // determined by the sv_clmovement_inputtimeout cvar) if (moveframetime <= 0) continue; oldframetime = prog->globals.server->frametime; @@ -607,7 +621,7 @@ void SV_ExecuteClientMoves(void) SV_Physics_ClientMove(); sv.frametime = oldframetime2; prog->globals.server->frametime = oldframetime; - host_client->clmovement_skipphysicsframes = sv_clmovement_waitforinput.integer; + host_client->clmovement_inputtimeout = sv_clmovement_inputtimeout.value; } } } @@ -627,15 +641,21 @@ void SV_ExecuteClientMoves(void) } // 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; + host_client->clmovement_inputtimeout = 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]; @@ -694,7 +714,10 @@ void SV_ApplyClientMove (void) void SV_FrameLost(int framenum) { if (host_client->entitydatabase5) + { EntityFrame5_LostFrame(host_client->entitydatabase5, framenum); + EntityFrameCSQC_LostFrame(host_client, framenum); + } } void SV_FrameAck(int framenum) @@ -719,6 +742,9 @@ void SV_ReadClientMessage(void) 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; @@ -836,13 +862,13 @@ clc_stringcmd_invalid: int crc; unsigned char *temp; FS_Seek(host_client->download_file, 0, SEEK_SET); - temp = Mem_Alloc(tempmempool, size); + temp = (unsigned char *) Mem_Alloc(tempmempool, size); FS_Read(host_client->download_file, temp, size); crc = CRC_Block(temp, size); Mem_Free(temp); // calculated crc, send the file info to the client // (so that it can verify the data) - Host_ClientCommands(va("\ncl_downloadfinished %i %i %s\n", size, crc, host_client->download_name)); + Host_ClientCommands("\ncl_downloadfinished %i %i %s\n", size, crc, host_client->download_name); Con_DPrintf("Download of %s by %s has finished\n", host_client->download_name, host_client->name); FS_Close(host_client->download_file); host_client->download_file = NULL;