]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_input.c
cl_main: Keep old CL_Disconnect for simplicity. Move guts to CL_DisconnectEx
[xonotic/darkplaces.git] / cl_input.c
index a75495cf46ab6f2f2d95cd586139b84b28ce89f4..da3104fdac12ea2f9455a8802c6fde0833cf3561 100644 (file)
@@ -1517,7 +1517,7 @@ void CL_UpdateMoveVars(void)
        else
        {
                cl.moveflags = 0;
-               cl.movevars_ticrate = (cls.demoplayback ? 1.0f : host_timescale.value) / bound(1.0f, cl_netfps.value, 1000.0f);
+               cl.movevars_ticrate = (cls.demoplayback ? 1.0f : host_timescale.value) / bound(10.0f, cl_netfps.value, 1000.0f);
                cl.movevars_timescale = (cls.demoplayback ? 1.0f : host_timescale.value);
                cl.movevars_gravity = sv_gravity.value;
                cl.movevars_stopspeed = cl_movement_stopspeed.value;
@@ -1756,8 +1756,7 @@ void CL_SendMove(void)
        usercmd_t *cmd;
        sizebuf_t buf;
        unsigned char data[1024];
-       double packettime;
-       int msecdelta;
+       float packettime;
        qbool quemove;
        qbool important;
 
@@ -1813,12 +1812,14 @@ void CL_SendMove(void)
        // set viewangles
        VectorCopy(cl.viewangles, cl.cmd.viewangles);
 
-       msecdelta = (int)(floor(cl.cmd.time * 1000) - floor(cl.movecmd[1].time * 1000));
-       cl.cmd.msec = (unsigned char)bound(0, msecdelta, 255);
+       // bones_was_here: previously cl.cmd.frametime was floored to nearest millisec
+       // this meant the smoothest async movement required integer millisec
+       // client and server frame times (eg 125fps)
+       cl.cmd.frametime = bound(0.0, cl.cmd.time - cl.movecmd[1].time, 0.255);
        // ridiculous value rejection (matches qw)
-       if (cl.cmd.msec > 250)
-               cl.cmd.msec = 100;
-       cl.cmd.frametime = cl.cmd.msec * (1.0 / 1000.0);
+       if (cl.cmd.frametime > 0.25)
+               cl.cmd.frametime = 0.1;
+       cl.cmd.msec = (unsigned char)floor(cl.cmd.frametime * 1000);
 
        switch(cls.protocol)
        {
@@ -1828,6 +1829,7 @@ void CL_SendMove(void)
                break;
        case PROTOCOL_DARKPLACES6:
        case PROTOCOL_DARKPLACES7:
+       case PROTOCOL_DARKPLACES8:
                cl.cmd.predicted = cl_movement.integer != 0;
                break;
        default:
@@ -1859,6 +1861,7 @@ void CL_SendMove(void)
                break;
        case PROTOCOL_DARKPLACES6:
        case PROTOCOL_DARKPLACES7:
+       case PROTOCOL_DARKPLACES8:
                // FIXME: cl.cmd.buttons & 16 is +button5, Nexuiz/Xonotic specific
                cl.cmd.crouch = (cl.cmd.buttons & 16) != 0;
                break;
@@ -1870,30 +1873,47 @@ void CL_SendMove(void)
                cl.movecmd[0] = cl.cmd;
 
        // don't predict more than 200fps
-       if (host.realtime >= cl.lastpackettime + 0.005)
+       if (cl.timesincepacket >= 0.005)
                cl.movement_replay = true; // redo the prediction
 
        // now decide whether to actually send this move
        // (otherwise it is only for prediction)
 
+       // do not send 0ms packets because they mess up physics
+       if(cl.cmd.msec == 0 && cl.time > cl.oldtime && (cls.protocol == PROTOCOL_QUAKEWORLD || cls.signon == SIGNONS))
+               return;
+
        // don't send too often or else network connections can get clogged by a
        // high renderer framerate
-       packettime = 1.0 / bound(1, cl_netfps.value, 1000);
+       packettime = 1.0f / bound(10.0f, cl_netfps.value, 1000.0f);
        if (cl.movevars_timescale && cl.movevars_ticrate)
        {
+               // try to ensure at least 1 packet per server frame
+               // and apply soft limit of 2, hard limit < 4 (packettime reduced further below)
                float maxtic = cl.movevars_ticrate / cl.movevars_timescale;
-               packettime = min(packettime, maxtic);
+               packettime = bound(maxtic * 0.5f, packettime, maxtic);
        }
+       // bones_was_here: reduce packettime to (largest multiple of realframetime) <= packettime
+       // prevents packet rates lower than cl_netfps or server frame rate
+       // eg: cl_netfps 60 and cl_maxfps 250 would otherwise send only 50 netfps
+       // with this line that config sends 62.5 netfps
+       // (this causes it to emit packets at a steady beat)
+       packettime = floor(packettime / (float)cl.realframetime) * (float)cl.realframetime;
 
-       // do not send 0ms packets because they mess up physics
-       if(cl.cmd.msec == 0 && cl.time > cl.oldtime && (cls.protocol == PROTOCOL_QUAKEWORLD || cls.signon == SIGNONS))
-               return;
        // always send if buttons changed or an impulse is pending
        // even if it violates the rate limit!
        important = (cl.cmd.impulse || (cl_netimmediatebuttons.integer && cl.cmd.buttons != cl.movecmd[1].buttons));
-       // don't send too often (cl_netfps)
-       if (!important && host.realtime < cl.lastpackettime + packettime)
+
+       // don't send too often (cl_netfps), allowing a small margin for float error
+       // bones_was_here: accumulate realframetime to prevent low packet rates
+       // previously with cl_maxfps == cl_netfps it did not send every frame as
+       // host.realtime - cl.lastpackettime was often well below (or above) packettime
+       if (!important && cl.timesincepacket < packettime * 0.99999f)
+       {
+               cl.timesincepacket += cl.realframetime;
                return;
+       }
+
        // don't choke the connection with packets (obey rate limit)
        // it is important that this check be last, because it adds a new
        // frame to the shownetgraph output and any cancelation after this
@@ -1901,12 +1921,9 @@ void CL_SendMove(void)
        // we also still send if it is important
        if (!NetConn_CanSend(cls.netcon) && !important)
                return;
-       // try to round off the lastpackettime to a multiple of the packet interval
-       // (this causes it to emit packets at a steady beat)
-       if (packettime > 0)
-               cl.lastpackettime = floor(host.realtime / packettime) * packettime;
-       else
-               cl.lastpackettime = host.realtime;
+
+       // reset the packet timing accumulator
+       cl.timesincepacket = cl.realframetime;
 
        buf.maxsize = sizeof(data);
        buf.cursize = 0;
@@ -1923,6 +1940,7 @@ void CL_SendMove(void)
        // PROTOCOL_DARKPLACES5  clc_move = 19 bytes total
        // PROTOCOL_DARKPLACES6  clc_move = 52 bytes total
        // PROTOCOL_DARKPLACES7  clc_move = 56 bytes total per move (can be up to 16 moves)
+       // PROTOCOL_DARKPLACES8  clc_move = 56 bytes total per move (can be up to 16 moves)
        // PROTOCOL_QUAKEWORLD   clc_move = 34 bytes total (typically, but can reach 43 bytes, or even 49 bytes with roll)
 
        // set prydon cursor info
@@ -2024,6 +2042,7 @@ void CL_SendMove(void)
                        MSG_WriteByte (&buf, cl.cmd.impulse);
                case PROTOCOL_DARKPLACES6:
                case PROTOCOL_DARKPLACES7:
+               case PROTOCOL_DARKPLACES8:
                        // set the maxusercmds variable to limit how many should be sent
                        maxusercmds = bound(1, cl_netrepeatinput.integer + 1, min(3, CL_MAX_USERCMDS));
                        // when movement prediction is off, there's not much point in repeating old input as it will just be ignored
@@ -2148,13 +2167,7 @@ void CL_SendMove(void)
        in_impulse = 0;
 
        if (cls.netcon->message.overflowed)
-       {
-               Con_Print("CL_SendMove: lost server connection\n");
-               CL_Disconnect();
-               SV_LockThreadMutex();
-               SV_Shutdown();
-               SV_UnlockThreadMutex();
-       }
+               CL_DisconnectEx(true, "Lost connection to server");
 }
 
 /*