diff --git a/engine/server/server.h b/engine/server/server.h index e9465d3e..614b7f54 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -395,6 +395,8 @@ extern convar_t sv_instancedbaseline; extern convar_t sv_background_freeze; extern convar_t sv_minupdaterate; extern convar_t sv_maxupdaterate; +extern convar_t sv_minrate; +extern convar_t sv_maxrate; extern convar_t sv_downloadurl; extern convar_t sv_newunit; extern convar_t sv_clienttrace; diff --git a/engine/server/sv_client.c b/engine/server/sv_client.c index ab8264b2..3455257a 100644 --- a/engine/server/sv_client.c +++ b/engine/server/sv_client.c @@ -1751,7 +1751,7 @@ void SV_UserinfoChanged( sv_client_t *cl ) // rate command val = Info_ValueForKey( cl->userinfo, "rate" ); if( COM_CheckString( val ) ) - cl->netchan.rate = bound( MIN_RATE, Q_atoi( val ), MAX_RATE ); + cl->netchan.rate = bound( sv_minrate.value, Q_atoi( val ), sv_maxrate.value ); else cl->netchan.rate = DEFAULT_RATE; // movement prediction @@ -1775,8 +1775,7 @@ void SV_UserinfoChanged( sv_client_t *cl ) { if( Q_atoi( val ) != 0 ) { - int i = bound( 10, Q_atoi( val ), 300 ); - cl->cl_updaterate = 1.0 / i; + cl->cl_updaterate = 1.0 / bound( sv_minupdaterate.value, Q_atoi( val ), sv_maxupdaterate.value ); } else cl->cl_updaterate = 0.0; } diff --git a/engine/server/sv_frame.c b/engine/server/sv_frame.c index 8c8d1406..06576b1e 100644 --- a/engine/server/sv_frame.c +++ b/engine/server/sv_frame.c @@ -838,8 +838,10 @@ SV_SendClientMessages */ void SV_SendClientMessages( void ) { - sv_client_t *cl; - int i; + sv_client_t *cl; + int i; + double updaterate_time; + double time_until_next_message; if( sv.state == ss_dead ) return; @@ -865,7 +867,14 @@ void SV_SendClientMessages( void ) if( cl->state == cs_spawned ) { - if(( host.realtime + sv.frametime ) >= cl->next_messagetime ) + // Try to send a message as soon as we can. + // If the target time for sending is within the next frame interval ( based on last frame ), + // trigger the send now. Note that in single player, + // FCL_SEND_NET_MESSAGE flag is also set any time a packet arrives from the client. + time_until_next_message = cl->next_messagetime - ( host.realtime + sv.frametime ); + if( time_until_next_message <= 0.0 ) + SetBits( cl->flags, FCL_SEND_NET_MESSAGE ); + else if( time_until_next_message > 2.0 ) // something got hosed SetBits( cl->flags, FCL_SEND_NET_MESSAGE ); } @@ -901,7 +910,9 @@ void SV_SendClientMessages( void ) } // now that we were able to send, reset timer to point to next possible send time. - cl->next_messagetime = host.realtime + sv.frametime + cl->cl_updaterate; + // check here also because sv_max/minupdaterate could been changed in runtime + updaterate_time = bound( 1.0 / sv_maxupdaterate.value, cl->cl_updaterate, 1.0 / sv_minupdaterate.value ); + cl->next_messagetime = host.realtime + sv.frametime + updaterate_time; ClearBits( cl->flags, FCL_SEND_NET_MESSAGE ); // NOTE: we should send frame even if server is not simulated to prevent overflow diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 7641591f..a748a0fc 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -32,10 +32,10 @@ CVAR_DEFINE_AUTO( sv_filterban, "1", 0, "filter banned users" ); CVAR_DEFINE_AUTO( sv_cheats, "0", FCVAR_SERVER, "allow cheats on server" ); CVAR_DEFINE_AUTO( sv_instancedbaseline, "1", 0, "allow to use instanced baselines to saves network overhead" ); CVAR_DEFINE_AUTO( sv_contact, "", FCVAR_ARCHIVE|FCVAR_SERVER, "server techincal support contact address or web-page" ); -CVAR_DEFINE_AUTO( sv_minupdaterate, "10.0", FCVAR_ARCHIVE, "minimal value for 'cl_updaterate' window" ); -CVAR_DEFINE_AUTO( sv_maxupdaterate, "30.0", FCVAR_ARCHIVE, "maximal value for 'cl_updaterate' window" ); -CVAR_DEFINE_AUTO( sv_minrate, "0", FCVAR_SERVER, "min bandwidth rate allowed on server, 0 == unlimited" ); -CVAR_DEFINE_AUTO( sv_maxrate, "0", FCVAR_SERVER, "max bandwidth rate allowed on server, 0 == unlimited" ); +CVAR_DEFINE_AUTO( sv_minupdaterate, "25.0", FCVAR_ARCHIVE, "minimal value for 'cl_updaterate' window" ); +CVAR_DEFINE_AUTO( sv_maxupdaterate, "60.0", FCVAR_ARCHIVE, "maximal value for 'cl_updaterate' window" ); +CVAR_DEFINE_AUTO( sv_minrate, "5000", FCVAR_SERVER, "min bandwidth rate allowed on server, 0 == unlimited" ); +CVAR_DEFINE_AUTO( sv_maxrate, "50000", FCVAR_SERVER, "max bandwidth rate allowed on server, 0 == unlimited" ); CVAR_DEFINE_AUTO( sv_logrelay, "0", FCVAR_ARCHIVE, "allow log messages from remote machines to be logged on this server" ); CVAR_DEFINE_AUTO( sv_newunit, "0", 0, "clear level-saves from previous SP game chapter to help keep .sav file size as minimum" ); CVAR_DEFINE_AUTO( sv_clienttrace, "1", FCVAR_SERVER, "0 = big box(Quake), 0.5 = halfsize, 1 = normal (100%), otherwise it's a scaling factor" ); @@ -866,6 +866,10 @@ void SV_Init( void ) Cvar_RegisterVariable( &sv_skyname ); Cvar_RegisterVariable( &sv_footsteps ); Cvar_RegisterVariable( &sv_wateralpha ); + Cvar_RegisterVariable( &sv_minupdaterate ); + Cvar_RegisterVariable( &sv_maxupdaterate ); + Cvar_RegisterVariable( &sv_minrate ); + Cvar_RegisterVariable( &sv_maxrate ); Cvar_RegisterVariable( &sv_cheats ); Cvar_RegisterVariable( &sv_airmove ); Cvar_RegisterVariable( &sv_fps );