diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index f79a592a..b2808f5d 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -1620,6 +1620,7 @@ static void CL_AccumlateInput(int plnum, float frametime/*extra contribution*/, float nscale = framemsecs?framemsecs / (framemsecs+cmd->msec):0; float oscale = 1 - nscale; + unsigned int st; CL_BaseMove (newmoves, plnum); @@ -1651,6 +1652,16 @@ static void CL_AccumlateInput(int plnum, float frametime/*extra contribution*/, } cmd->msec = framemsecs; + if (cl.movesequence >= 1) + { //fix up the servertime value to make sure our msecs are actually correct. + st = cl.outframes[(cl.movesequence-1)&UPDATE_MASK].cmd[plnum].servertime + (cmd->msec); //round it. + if (abs((int)st-(int)cmd->servertime) < 50) + { + cmd->servertime = st; + cmd->fservertime = (double)st/1000.0; + } + } + // if we are spectator, try autocam // if (cl.spectator) Cam_Track(&cl.playerview[plnum], &cl_pendingcmd[plnum]); diff --git a/engine/common/common.c b/engine/common/common.c index e4e4f63a..58b4ed85 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -1500,6 +1500,7 @@ void MSGQ2_WriteDeltaUsercmd (sizebuf_t *buf, const usercmd_t *from, const userc #define UC_RIGHT (1<<4) #define UC_BUTTONS (1<<5) #define UC_IMPULSE (1<<6) + #define UC_UP (1<<7) //split from forward/right because its rare, and this avoids sending an extra byte. #define UC_ABSANG (1<<8) //angle values are shorts #define UC_BIGMOVES (1<<9) //fwd/left/up are shorts, rather than a fith. @@ -1507,13 +1508,15 @@ void MSGQ2_WriteDeltaUsercmd (sizebuf_t *buf, const usercmd_t *from, const userc #define UC_CURSORFLDS (1<<11) //lots of data in one. #define UC_LIGHTLEV (1<<12) #define UC_VR_HEAD (1<<13) + #define UC_VR_RIGHT (1<<14) #define UC_VR_LEFT (1<<15) //#define UC_UNUSED (1<<16) //#define UC_UNUSED (1<<17) -//#define UC_UNUSED (1<<18) +#define UC_MSEC_DEBUG (1<<18) //FIXME: temporary //#define UC_UNUSED (1<<19) //#define UC_UNUSED (1<<20) + //#define UC_UNUSED (1<<21) //#define UC_UNUSED (1<<22) //#define UC_UNUSED (1<<23) @@ -1521,11 +1524,12 @@ void MSGQ2_WriteDeltaUsercmd (sizebuf_t *buf, const usercmd_t *from, const userc //#define UC_UNUSED (1<<25) //#define UC_UNUSED (1<<26) //#define UC_UNUSED (1<<27) + //#define UC_UNUSED (1<<28) //#define UC_UNUSED (1<<29) //#define UC_UNUSED (1<<30) //#define UC_UNUSED (1<<31) -#define UC_UNSUPPORTED (~(UC_ANGLE1 | UC_ANGLE2 | UC_ANGLE3 | UC_FORWARD | UC_RIGHT | UC_BUTTONS | UC_IMPULSE | UC_UP | UC_ABSANG | UC_BIGMOVES | UC_WEAPON | UC_CURSORFLDS | UC_LIGHTLEV | UC_VR_HEAD | UC_VR_RIGHT | UC_VR_LEFT)) +#define UC_UNSUPPORTED (~(UC_ANGLE1 | UC_ANGLE2 | UC_ANGLE3 | UC_FORWARD | UC_RIGHT | UC_BUTTONS | UC_IMPULSE | UC_UP | UC_ABSANG | UC_BIGMOVES | UC_WEAPON | UC_CURSORFLDS | UC_LIGHTLEV | UC_VR_HEAD | UC_VR_RIGHT | UC_VR_LEFT | UC_MSEC_DEBUG)) #define UC_VR_STATUS (1<<0) #define UC_VR_ANG (1<<1) @@ -1651,10 +1655,17 @@ void MSGFTE_WriteDeltaUsercmd (sizebuf_t *buf, const short baseangles[3], const if (MSG_CompareVR(VRDEV_LEFT, from, cmd)) bits |= UC_VR_LEFT; +#ifdef _DEBUG + if (developer.ival) + bits |= UC_MSEC_DEBUG; +#endif + //NOTE: WriteUInt64 actually uses some length coding, so its not quite as bloated as it looks. MSG_WriteUInt64(buf, bits); MSG_WriteUInt64(buf, cmd->servertime-from->servertime); + if (bits & UC_MSEC_DEBUG) + MSG_WriteUInt64(buf, cmd->msec); for (i = 0; i < 3; i++) { if (bits & (UC_ANGLE1<servertime = from->servertime+MSG_ReadUInt64(); cmd->fservertime = cmd->servertime/1000.0; + if (bits & UC_MSEC_DEBUG) + cmd->msec = MSG_ReadUInt64(); //for debugging only. only sent when developer 1, for now. + else + cmd->msec = 0; //no info... for (i = 0; i < 3; i++) { if (bits & (UC_ANGLE1<isindependant = !(sv_nqplayerphysics.ival || split->state < cs_spawned || SV_PlayerPhysicsQC || sv.paused || !sv.world.worldmodel || sv.world.worldmodel->loadstate != MLS_LOADED); ran = false; - old = nullcmd; + oldcmd = nullcmd; + dropsequence = split->lastcmd.sequence; for (frame = 0; frame < frames; frame++) { - MSGFTE_ReadDeltaUsercmd(&old, &split->lastcmd); - split->lastcmd.sequence = controller->netchan.outgoing_sequence - (frames-frame-1); - old = split->lastcmd; + MSGFTE_ReadDeltaUsercmd(&oldcmd, &newcmd); + newcmd.sequence = controller->netchan.outgoing_sequence - (frames-frame-1); + oldcmd = newcmd; + + if (newcmd.sequence <= dropsequence) + continue; //this one is a dupe. + + newcmd.msec = newcmd.servertime - split->lastcmd.servertime; + + if (oldcmd.msec && newcmd.msec != oldcmd.msec) + if (sv_showpredloss.ival) + Con_Printf("%s: %g -> %g\n", split->name, newcmd.msec, oldcmd.msec); + + split->lastcmd = newcmd; split->lastcmd.angles[0] += split->baseangles[0]; split->lastcmd.angles[1] += split->baseangles[1]; split->lastcmd.angles[2] += split->baseangles[2]; @@ -8054,10 +8067,6 @@ static double SVFTE_ExecuteClientMove(client_t *controller) if (split->state == cs_spawned) { - //handle impulse here, doing it later might mean it got skipped entirely (nq physics often skips frames). - if (split->lastcmd.impulse) - split->edict->v->impulse = split->lastcmd.impulse; - if (split->isindependant) { //this protocol uses bigger timestamps instead of msecs unsigned int curtime = sv.time*1000; @@ -8082,13 +8091,16 @@ static double SVFTE_ExecuteClientMove(client_t *controller) ran=true; } - split->lastcmd.msec = split->lastcmd.servertime - split->lastruncmd; SV_RunCmd (&split->lastcmd, false); split->lastruncmd = split->lastcmd.servertime; } } else { + //handle impulse here, doing it later might mean it got skipped entirely (nq physics often skips frames). + if (split->lastcmd.impulse) + split->edict->v->impulse = split->lastcmd.impulse; + SV_SetEntityButtons(split->edict, split->lastcmd.buttons); split->lastcmd.buttons = 0; }