diff --git a/Quake/cl_input.c b/Quake/cl_input.c index 35ba5d20..1860262e 100644 --- a/Quake/cl_input.c +++ b/Quake/cl_input.c @@ -311,8 +311,6 @@ void CL_BaseMove (usercmd_t *cmd) if (cls.signon != SIGNONS) return; - CL_AdjustAngles (); - Q_memset (cmd, 0, sizeof(*cmd)); if (in_strafe.state & 1) diff --git a/Quake/cl_main.c b/Quake/cl_main.c index e51fa89a..fa50183e 100644 --- a/Quake/cl_main.c +++ b/Quake/cl_main.c @@ -67,6 +67,7 @@ int cl_maxvisedicts; entity_t **cl_visedicts; extern cvar_t r_lerpmodels, r_lerpmove; //johnfitz +extern float host_netinterval; //Spike void CL_ClearTrailStates(void) { @@ -413,7 +414,7 @@ float CL_LerpPoint (void) f = cl.mtime[0] - cl.mtime[1]; - if (!f || cls.timedemo || sv.active) + if (!f || cls.timedemo || (sv.active && !host_netinterval)) { cl.time = cl.mtime[0]; return 1; @@ -1119,6 +1120,25 @@ int CL_ReadFromServer (void) return 0; } +/* +================= +CL_UpdateViewAngles + +Spike: split from CL_SendCmd, to do clientside viewangle changes separately from outgoing packets. +================= +*/ +void CL_AccumulateCmd (void) +{ + if (cls.signon == SIGNONS) + { + //basic keyboard looking + CL_AdjustAngles (); + + //accumulate movement from other devices + IN_Move (&cl.pendingcmd); + } +} + /* ================= CL_SendCmd @@ -1137,13 +1157,16 @@ void CL_SendCmd (void) CL_BaseMove (&cmd); // allow mice or other external controllers to add to the move - IN_Move (&cmd); + cmd.forwardmove += cl.pendingcmd.forwardmove; + cmd.sidemove += cl.pendingcmd.sidemove; + cmd.upmove += cl.pendingcmd.upmove; // send the unreliable message CL_SendMove (&cmd); } else CL_SendMove (NULL); + memset(&cl.pendingcmd, 0, sizeof(cl.pendingcmd)); if (cls.demoplayback) { diff --git a/Quake/client.h b/Quake/client.h index 4db7ad01..d4a0cc97 100644 --- a/Quake/client.h +++ b/Quake/client.h @@ -159,6 +159,7 @@ typedef struct // doesn't accidentally do something the // first frame usercmd_t cmd; // last command sent to the server + usercmd_t pendingcmd; // accumulated state from mice+joysticks. // information for local display int stats[MAX_CL_STATS]; // health, etc @@ -379,9 +380,11 @@ extern kbutton_t in_strafe; extern kbutton_t in_speed; void CL_InitInput (void); +void CL_AccumulateCmd (void); void CL_SendCmd (void); void CL_SendMove (const usercmd_t *cmd); int CL_ReadFromServer (void); +void CL_AdjustAngles (void); void CL_BaseMove (usercmd_t *cmd); void CL_Download_Data(void); diff --git a/Quake/cmd.c b/Quake/cmd.c index 0e5ed5b1..45f1eb19 100644 --- a/Quake/cmd.c +++ b/Quake/cmd.c @@ -149,9 +149,17 @@ void Cbuf_InsertText (const char *text) } } +//Spike: for renderer/server isolation +void Cbuf_Waited(void) +{ + cmd_wait = false; +} + /* ============ Cbuf_Execute + +Spike: reworked 'wait' for renderer/server rate independance ============ */ void Cbuf_Execute (void) @@ -161,7 +169,7 @@ void Cbuf_Execute (void) char line[1024]; int quotes, comment; - while (cmd_text.cursize) + while (cmd_text.cursize && !cmd_wait) { // find a \n or ; line break text = (char *)cmd_text.data; @@ -206,13 +214,6 @@ void Cbuf_Execute (void) // execute the command line Cmd_ExecuteString (line, src_command); - - if (cmd_wait) - { // skip out while text still remains in buffer, leaving it - // for next frame - cmd_wait = false; - break; - } } } diff --git a/Quake/cmd.h b/Quake/cmd.h index 71b8daf3..3fc672f4 100644 --- a/Quake/cmd.h +++ b/Quake/cmd.h @@ -58,6 +58,13 @@ void Cbuf_Execute (void); // Normally called once per frame, but may be explicitly invoked. // Do not call inside a command function! +void Cbuf_Waited (void); +//In vanilla, the 'wait' command is used by both input configs and servers. +//mods do hacky stuff like syncing waits to StartFrame calls. +//thankfully, c2s packets and server logic can both happen at the same intervals. +//so wait sets a flag to inhibit execution of more commands, and we only clear it once we've run a network frame. +//so this function lets the cbuf know when to clear the flag again (instead of part of cbuf_execute). + //=========================================================================== /* diff --git a/Quake/host.c b/Quake/host.c index b1a045d1..e38a5c58 100644 --- a/Quake/host.c +++ b/Quake/host.c @@ -56,7 +56,7 @@ client_t *host_client; // current client jmp_buf host_abortserver; byte *host_colormap; - +float host_netinterval; cvar_t host_framerate = {"host_framerate","0",CVAR_NONE}; // set for slow motion cvar_t host_speeds = {"host_speeds","0",CVAR_NONE}; // set for running times cvar_t host_maxfps = {"host_maxfps", "72", CVAR_ARCHIVE}; //johnfitz @@ -106,8 +106,21 @@ Max_Fps_f -- ericw */ static void Max_Fps_f (cvar_t *var) { - if (var->value > 72) - Con_Warning ("host_maxfps above 72 breaks physics.\n"); + if (var->value > 72 || var->value <= 0) + { + if (!host_netinterval) + Con_Printf ("Using renderer/network isolation.\n"); + host_netinterval = 1.0/72; + } + else + { + if (host_netinterval) + Con_Printf ("Disabling renderer/network isolation.\n"); + host_netinterval = 0; + + if (var->value > 72) + Con_Warning ("host_maxfps above 72 breaks physics.\n"); + } } /* @@ -607,7 +620,7 @@ qboolean Host_FilterTime (float time) else if (host_framerate.value > 0) host_frametime = host_framerate.value; else if (host_maxfps.value)// don't allow really long or short frames - host_frametime = CLAMP (0.001, host_frametime, 0.1); //johnfitz -- use CLAMP + host_frametime = CLAMP (0.0001, host_frametime, 0.1); //johnfitz -- use CLAMP return true; } @@ -697,8 +710,9 @@ Host_Frame Runs all active servers ================== */ -void _Host_Frame (float time) +void _Host_Frame (double time) { + static double accumtime = 0; static double time1 = 0; static double time2 = 0; static double time3 = 0; @@ -711,6 +725,7 @@ void _Host_Frame (float time) rand (); // decide the simulation time + accumtime += host_netinterval?CLAMP(0, time, 0.2):0; //for renderer/server isolation if (!Host_FilterTime (time)) return; // don't run too fast, or packets will flood out @@ -722,6 +737,9 @@ void _Host_Frame (float time) // allow mice or other external controllers to add commands IN_Commands (); +//check the stdin for commands (dedicated servers) + Host_GetConsoleCommands (); + // process console commands Cbuf_Execute (); @@ -779,36 +797,31 @@ void _Host_Frame (float time) MSG_WriteByte (&cls.message, clc_nop); } -// if running the server locally, make intentions now - if (sv.active) - CL_SendCmd (); + CL_AccumulateCmd (); -//------------------- -// -// server operations -// -//------------------- - -// check for commands typed to the host - Host_GetConsoleCommands (); - - if (sv.active) + //Run the server+networking (client->server->client), at a different rate from everyt + if (accumtime >= host_netinterval) { - PR_SwitchQCVM(&sv.qcvm); - Host_ServerFrame (); - PR_SwitchQCVM(NULL); - } - -//------------------- -// -// client operations -// -//------------------- - -// if running the server remotely, send intentions now after -// the incoming messages have been read - if (!sv.active) + float realframetime = host_frametime; + accumtime -= host_netinterval; + if (host_netinterval) + { + host_frametime = host_netinterval; + if (host_timescale.value > 0) + host_frametime *= host_timescale.value; + else if (host_framerate.value) + host_frametime = host_framerate.value; + } CL_SendCmd (); + if (sv.active) + { + PR_SwitchQCVM(&sv.qcvm); + Host_ServerFrame (); + PR_SwitchQCVM(NULL); + } + host_frametime = realframetime; + Cbuf_Waited(); + } // fetch results from server if (cls.state == ca_connected) @@ -851,7 +864,7 @@ void _Host_Frame (float time) } -void Host_Frame (float time) +void Host_Frame (double time) { double time1, time2; static double timetotal; diff --git a/Quake/quakedef.h b/Quake/quakedef.h index 15b8a906..908eabde 100644 --- a/Quake/quakedef.h +++ b/Quake/quakedef.h @@ -335,7 +335,7 @@ FUNC_NORETURN void Host_EndGame (const char *message, ...) FUNC_PRINTF(1,2); #pragma aux Host_Error aborts; #pragma aux Host_EndGame aborts; #endif -void Host_Frame (float time); +void Host_Frame (double time); void Host_Quit_f (void); void Host_ClientCommands (const char *fmt, ...) FUNC_PRINTF(1,2); void Host_ShutdownServer (qboolean crash);