20 Apr 2018

This commit is contained in:
g-cont 2018-04-20 00:00:00 +03:00 committed by Alibek Omarov
parent 1c46e861d7
commit 21a4165b4a
15 changed files with 134 additions and 139 deletions

View File

@ -25,6 +25,5 @@ GNU General Public License for more details.
#define ENGINE_COMPENSATE_QUAKE_BUG (1<<5) // compensate stupid quake bug (inverse pitch) for mods where this bug is fixed
// reserved
#define ENGINE_COMPUTE_STUDIO_LERP (1<<7) // enable MOVETYPE_STEP lerping back in engine
#define ENGINE_FIXED_FRAMERATE (1<<8) // keep constant rate for client and server (but don't clamp renderer calls)
#endif//FEATURES_H

View File

@ -410,8 +410,8 @@ int CL_InterpolateModel( cl_entity_t *e )
if( cls.timedemo || !e->model )
return 1;
if( cl.maxclients <= 1 && !FBitSet( host.features, ENGINE_FIXED_FRAMERATE ))
return 1;
if( fabs( cl_serverframetime() - cl_clientframetime()) < 0.0001f )
return 1; // interpolation disabled
if( e->model->type == mod_brush && !cl_bmodelinterp->value )
return 1;
@ -419,10 +419,8 @@ int CL_InterpolateModel( cl_entity_t *e )
if( cl.local.moving && cl.local.onground == e->index )
return 1;
if( cl.maxclients <= 1 && FBitSet( host.features, ENGINE_FIXED_FRAMERATE ))
t = cl.time - cl_serverframetime();
else t = cl.time - cl_interp->value;
// t = cl.time - cl_serverframetime();
t = cl.time - cl_interp->value;
CL_FindInterpolationUpdates( e, t, &ph0, &ph1 );
if( ph0 == NULL || ph1 == NULL )

View File

@ -250,7 +250,7 @@ static float CL_LerpPoint( void )
return 1.0f;
}
if( cl_interp->value > 0.001f && !FBitSet( host.features, ENGINE_FIXED_FRAMERATE ))
if( cl_interp->value > 0.001f )
{
// manual lerp value (goldsrc mode)
frac = ( cl.time - cl.mtime[0] ) / cl_interp->value;
@ -439,12 +439,11 @@ void CL_FindInterpolatedAddAngle( float t, float *frac, pred_viewangle_t **prev,
void CL_ApplyAddAngle( void )
{
float curtime = cl.time - cl_serverframetime();
pred_viewangle_t *prev = NULL, *next = NULL;
float addangletotal = 0.0f;
float amove, frac = 0.0f;
CL_FindInterpolatedAddAngle( curtime, &frac, &prev, &next );
CL_FindInterpolatedAddAngle( cl.time, &frac, &prev, &next );
if( prev && next )
addangletotal = prev->total + frac * ( next->total - prev->total );
@ -616,7 +615,6 @@ void CL_CreateCmd( void )
pcmd->receivedtime = -1.0;
pcmd->heldback = false;
pcmd->sendsize = 0;
CL_ApplyAddAngle();
}
active = (( cls.signon == SIGNONS ) && !cl.paused && !cls.demoplayback );
@ -1591,6 +1589,9 @@ void CL_ParseStatusMessage( netadr_t from, sizebuf_t *msg )
CL_FixupColorStringsForInfoString( s, infostring );
if( !COM_CheckString( Info_ValueForKey( infostring, "gamedir" )))
return; // unsupported proto
// more info about servers
Con_Printf( "Server: %s, Game: %s\n", NET_AdrToString( from ), Info_ValueForKey( infostring, "gamedir" ));
@ -2051,6 +2052,8 @@ void CL_ReadPackets( void )
cls.demotime += host.frametime;
CL_ReadNetMessage();
CL_ApplyAddAngle();
#if 0
// keep cheat cvars are unchanged
if( cl.maxclients > 1 && cls.state == ca_active && !host_developer.value )

View File

@ -1448,13 +1448,10 @@ void CL_ParseAddAngle( sizebuf_t *msg )
float delta_yaw;
delta_yaw = MSG_ReadBitAngle( msg, 16 );
if( cl.maxclients <= 1 && !FBitSet( host.features, ENGINE_FIXED_FRAMERATE ))
{
cl.viewangles[YAW] += delta_yaw;
return;
}
#if 0
cl.viewangles[YAW] += delta_yaw;
return;
#endif
// update running counter
cl.addangletotal += delta_yaw;

View File

@ -248,7 +248,7 @@ void CL_CheckPredictionError( void )
// save for error interpolation
VectorCopy( delta, cl.local.prediction_error );
if(( dist > MIN_CORRECTION_DISTANCE ) && (( cl.maxclients > 1 ) || FBitSet( host.features, ENGINE_FIXED_FRAMERATE )))
if( dist > MIN_CORRECTION_DISTANCE )
cls.correction_time = cl_smoothtime->value;
}
}

View File

@ -1244,15 +1244,16 @@ COM_CheckParm
*/
int COM_CheckParm( char *parm, char **ppnext )
{
static char str[64];
int i = Sys_CheckParm( parm );
if( Sys_GetParmFromCmdLine( parm, str ))
if( ppnext )
{
// get the pointer on cmdline param
if( ppnext ) *ppnext = str;
return 1;
if( i != 0 && i < host.argc - 1 )
*ppnext = (char *)host.argv[i + 1];
else *ppnext = NULL;
}
return 0;
return i;
}
/*

View File

@ -128,7 +128,7 @@ typedef enum
// PERFORMANCE INFO
#define MIN_FPS 20.0 // host minimum fps value for maxfps.
#define MAX_FPS 200.0 // upper limit for maxfps.
#define HOST_FPS 72.0 // multiplayer games typical fps
#define HOST_FPS 100.0 // multiplayer games typical fps
#define MAX_FRAMETIME 0.25
#define MIN_FRAMETIME 0.0001

View File

@ -78,9 +78,6 @@ void Host_PrintEngineFeatures( void )
if( FBitSet( host.features, ENGINE_COMPENSATE_QUAKE_BUG ))
MsgDev( D_REPORT, "^3EXT:^7 Compensate quake bug enabled\n" );
if( FBitSet( host.features, ENGINE_FIXED_FRAMERATE ))
MsgDev( D_REPORT, "^3EXT:^7 runnung server at constant fps\n" );
}
/*
@ -133,7 +130,7 @@ void Host_CheckSleep( void )
if( host.type == HOST_DEDICATED )
{
// let the dedicated server some sleep
Sys_Sleep( 1 );
// Sys_Sleep( 1 );
}
else
{
@ -645,7 +642,8 @@ void Host_InitCommon( const char *hostname, qboolean bChangeGame )
host.mempool = Mem_AllocPool( "Zone Engine" );
if( Sys_CheckParm( "-console" ))
// HACKHACK: Quake console is always allowed
if( Sys_CheckParm( "-console" ) || !Q_stricmp( progname, "id1" ))
host.allow_console = true;
if( Sys_CheckParm( "-dev" ))
@ -789,7 +787,7 @@ int EXPORT Host_Main( const char *progname, int bChangeGame, pfnChangeGame func
Cmd_AddCommand ( "crash", Host_Crash_f, "a way to force a bus error for development reasons");
}
host_maxfps = Cvar_Get( "fps_max", "72", FCVAR_ARCHIVE, "host fps upper limit" );
host_maxfps = Cvar_Get( "fps_max", "100", FCVAR_ARCHIVE, "host fps upper limit" );
host_framerate = Cvar_Get( "host_framerate", "0", 0, "locks frame timing to this value in seconds" );
host_gameloaded = Cvar_Get( "host_gameloaded", "0", FCVAR_READ_ONLY, "inidcates a loaded game.dll" );
host_clientloaded = Cvar_Get( "host_clientloaded", "0", FCVAR_READ_ONLY, "inidcates a loaded client.dll" );

View File

@ -314,7 +314,9 @@ int Sys_CheckParm( const char *parm )
for( i = 1; i < host.argc; i++ )
{
if( !host.argv[i] ) continue;
if( !host.argv[i] )
continue;
if( !Q_stricmp( parm, host.argv[i] ))
return i;
}

View File

@ -195,8 +195,8 @@ typedef struct server_s
model_t *worldmodel; // pointer to world
qboolean simulating;
qboolean playersonly;
qboolean simulating; // physics is running
qboolean paused;
// statistics
@ -237,7 +237,6 @@ typedef struct sv_client_s
double next_sendinfotime; // time to send info about all players
double cl_updaterate; // client requested updaterate
double timebase; // client timebase
double lastservertime; // check if server time was not changed so no resaon to send update
double connection_started;
char hashedcdkey[34]; // MD5 hash is 32 hex #'s, plus trailing 0

View File

@ -380,7 +380,6 @@ void SV_ConnectClient( netadr_t from )
#endif
newcl->next_messagetime = host.realtime + newcl->cl_updaterate;
newcl->next_sendinfotime = 0.0;
newcl->lastservertime = -1.0;
newcl->ignored_ents = 0;
newcl->chokecount = 0;

View File

@ -652,20 +652,11 @@ void SV_SendClientDatagram( sv_client_t *cl )
byte msg_buf[MAX_DATAGRAM];
sizebuf_t msg;
// if we running server with fixed fps so no reason
// to send updates too fast: time just not changed
if( FBitSet( host.features, ENGINE_FIXED_FRAMERATE ))
{
if( sv.simulating && cl->lastservertime == sv.time )
return;
}
MSG_Init( &msg, "Datagram", msg_buf, sizeof( msg_buf ));
// always send servertime at new frame
MSG_BeginServerCmd( &msg, svc_time );
MSG_WriteFloat( &msg, sv.time );
cl->lastservertime = sv.time;
SV_WriteClientdataToMessage( cl, &msg );
SV_WriteEntitiesToClient( cl, &msg );
@ -825,11 +816,8 @@ void SV_SendClientMessages( void )
continue;
}
if( !FBitSet( host.features, ENGINE_FIXED_FRAMERATE ))
{
if( !host_limitlocal->value && NET_IsLocalAddress( cl->netchan.remote_address ))
SetBits( cl->flags, FCL_SEND_NET_MESSAGE );
}
if( !host_limitlocal->value && NET_IsLocalAddress( cl->netchan.remote_address ))
SetBits( cl->flags, FCL_SEND_NET_MESSAGE );
if( cl->state == cs_spawned )
{

View File

@ -4848,8 +4848,7 @@ qboolean SV_LoadProgs( const char *name )
{
Con_Printf( S_WARN "SV_LoadProgs: couldn't get physics API\n" );
}
// TESTTEST
//host.features |= ENGINE_FIXED_FRAMERATE;
// grab function SV_SaveGameComment
SV_InitSaveRestore ();

View File

@ -96,6 +96,7 @@ CVAR_DEFINE_AUTO( showtriggers, "0", FCVAR_LATCH, "debug cvar shows triggers" );
CVAR_DEFINE_AUTO( sv_airmove, "1", FCVAR_SERVER, "obsolete, compatibility issues" );
CVAR_DEFINE_AUTO( sv_version, "", FCVAR_READ_ONLY, "engine version string" );
CVAR_DEFINE_AUTO( hostname, "", FCVAR_SERVER|FCVAR_PRINTABLEONLY, "name of current host" );
CVAR_DEFINE_AUTO( sv_fps, "0.0", FCVAR_SERVER, "server framerate" );
// gore-related cvars
CVAR_DEFINE_AUTO( violence_hblood, "1", 0, "draw human blood" );
@ -217,6 +218,15 @@ void SV_CheckCmdTimes( void )
float diff;
int i;
if( sv_fps.value != 0.0f )
{
if( sv_fps.value < MIN_FPS )
Cvar_SetValue( "sv_fps", MIN_FPS );
if( sv_fps.value > MAX_FPS )
Cvar_SetValue( "sv_fps", MAX_FPS );
}
if( Host_IsLocalGame( ))
return;
@ -544,32 +554,37 @@ SV_RunGameFrame
SV_RunGameFrame
=================
*/
void SV_RunGameFrame( void )
qboolean SV_RunGameFrame( void )
{
int numFrames = 0; // debug
sv.simulating = SV_IsSimulating();
if(!( sv.simulating = SV_IsSimulating( )))
return;
if( !sv.simulating )
return true;
if( FBitSet( host.features, ENGINE_FIXED_FRAMERATE ))
if( sv_fps.value != 0.0f )
{
sv.time_residual += host.frametime;
double fps = (1.0 / (double)( sv_fps.value - 0.01 )); // FP issues
int numFrames = 0;
static double oldtime;
if( sv.time_residual >= sv.frametime )
while( sv.time_residual >= fps )
{
sv.frametime = fps;
SV_Physics();
sv.time_residual -= sv.frametime;
sv.time += sv.frametime;
sv.time_residual -= fps;
sv.time += fps;
numFrames++;
}
return (numFrames != 0);
}
else
{
SV_Physics();
sv.time += sv.frametime;
numFrames++;
return true;
}
}
@ -584,10 +599,11 @@ void Host_ServerFrame( void )
// if server is not active, do nothing
if( !svs.initialized ) return;
if( FBitSet( host.features, ENGINE_FIXED_FRAMERATE ))
sv.frametime = ( 1.0 / (double)GAME_FPS );
else sv.frametime = host.frametime; // GoldSrc style
if( sv.simulating || sv.state != ss_active )
sv.time_residual += host.frametime;
if( sv_fps.value == 0.0f )
sv.frametime = host.frametime;
svgame.globals->frametime = sv.frametime;
// check clients timewindow
@ -596,9 +612,6 @@ void Host_ServerFrame( void )
// read packets from clients
SV_ReadPackets ();
// let everything in the world think and move
SV_RunGameFrame ();
// refresh physic movevars on the client side
SV_UpdateMovevars ( false );
@ -607,6 +620,9 @@ void Host_ServerFrame( void )
// check timeouts
SV_CheckTimeouts ();
// let everything in the world think and move
if( !SV_RunGameFrame ()) return;
// send messages back to the clients that had packets read this frame
SV_SendClientMessages ();
@ -770,7 +786,7 @@ void SV_Init( void )
Cvar_RegisterVariable (&sv_wateralpha);
Cvar_RegisterVariable (&sv_cheats);
Cvar_RegisterVariable (&sv_airmove);
Cvar_RegisterVariable (&sv_fps);
Cvar_RegisterVariable (&showtriggers);
Cvar_RegisterVariable (&sv_aim);
Cvar_RegisterVariable (&motdfile);

View File

@ -67,19 +67,19 @@ qboolean SV_CopyEdictToPhysEnt( physent_t *pe, edict_t *ed )
VectorCopy( ed->v.origin, pe->origin );
VectorCopy( ed->v.angles, pe->angles );
if( ed->v.flags & FL_CLIENT )
{
// client
SV_GetTrueOrigin( &svs.clients[pe->info - 1], (pe->info - 1), pe->origin );
Q_strncpy( pe->name, "player", sizeof( pe->name ));
pe->player = pe->info;
}
else if( ed->v.flags & FL_FAKECLIENT && ed->v.solid != MOVETYPE_PUSH )
if( FBitSet( ed->v.flags, FL_FAKECLIENT ))
{
// bot
Q_strncpy( pe->name, "bot", sizeof( pe->name ));
pe->player = pe->info;
}
else if( FBitSet( ed->v.flags, FL_CLIENT ))
{
// client
SV_GetTrueOrigin( &svs.clients[pe->info - 1], pe->info, pe->origin );
Q_strncpy( pe->name, "player", sizeof( pe->name ));
pe->player = pe->info;
}
else
{
// otherwise copy the classname
@ -148,39 +148,51 @@ qboolean SV_CopyEdictToPhysEnt( physent_t *pe, edict_t *ed )
return true;
}
qboolean SV_ShouldUnlagForPlayer( sv_client_t *cl )
{
// can't unlag in singleplayer
if( svs.maxclients <= 1 )
return false;
// unlag disabled globally
if( !svgame.dllFuncs.pfnAllowLagCompensation() || !sv_unlag.value )
return false;
if( !FBitSet( cl->flags, FCL_LAG_COMPENSATION ))
return false;
// player not ready
if( cl->state != cs_spawned )
return false;
return true;
}
void SV_GetTrueOrigin( sv_client_t *cl, int edictnum, vec3_t origin )
{
// don't allow unlag in singleplayer
if( svs.maxclients <= 1 ) return;
if( cl->state < cs_connected || edictnum < 0 || edictnum >= svs.maxclients )
if( !SV_ShouldUnlagForPlayer( cl ))
return;
if( !FBitSet( cl->flags, FCL_LAG_COMPENSATION ) || !sv_unlag.value )
if( edictnum < 1 || edictnum > svs.maxclients )
return;
if( !svgame.interp[edictnum].active || !svgame.interp[edictnum].moving )
return;
VectorCopy( svgame.interp[edictnum].newpos, origin );
if( svgame.interp[edictnum-1].active && svgame.interp[edictnum-1].moving )
VectorCopy( svgame.interp[edictnum-1].newpos, origin );
}
void SV_GetTrueMinMax( sv_client_t *cl, int edictnum, vec3_t mins, vec3_t maxs )
{
// don't allow unlag in singleplayer
if( svs.maxclients <= 1 ) return;
if( cl->state < cs_connected || edictnum < 0 || edictnum >= svs.maxclients )
if( !SV_ShouldUnlagForPlayer( cl ))
return;
if( !FBitSet( cl->flags, FCL_LAG_COMPENSATION ) || !sv_unlag.value )
if( edictnum < 1 || edictnum > svs.maxclients )
return;
if( !svgame.interp[edictnum].active || !svgame.interp[edictnum].moving )
return;
VectorCopy( svgame.interp[edictnum].mins, mins );
VectorCopy( svgame.interp[edictnum].maxs, maxs );
if( svgame.interp[edictnum-1].active && svgame.interp[edictnum-1].moving )
{
VectorCopy( svgame.interp[edictnum-1].mins, mins );
VectorCopy( svgame.interp[edictnum-1].maxs, maxs );
}
}
/*
@ -247,12 +259,13 @@ void SV_AddLinksToPmove( areanode_t *node, const vec3_t pmove_mins, const vec3_t
VectorCopy( check->v.absmin, mins );
VectorCopy( check->v.absmax, maxs );
if( FBitSet( check->v.flags, FL_CLIENT ))
if( FBitSet( check->v.flags, FL_CLIENT ) && !FBitSet( check->v.flags, FL_FAKECLIENT ))
{
int e = NUM_FOR_EDICT( check ) - 1;
// trying to get interpolated values
SV_GetTrueMinMax( &svs.clients[e], e, mins, maxs );
if( sv.current_client )
{
// trying to get interpolated values
SV_GetTrueMinMax( sv.current_client, NUM_FOR_EDICT( check ), mins, maxs );
}
}
if( !BoundsIntersect( pmove_mins, pmove_maxs, mins, maxs ))
@ -807,16 +820,7 @@ void SV_SetupMoveInterpolant( sv_client_t *cl )
memset( svgame.interp, 0, sizeof( svgame.interp ));
has_update = false;
// don't allow unlag in singleplayer
if( svs.maxclients <= 1 || cl->state != cs_spawned )
return;
// unlag disabled by game request
if( !svgame.dllFuncs.pfnAllowLagCompensation() || !sv_unlag.value )
return;
// unlag disabled for current client
if( !FBitSet( cl->flags, FCL_LAG_COMPENSATION ))
if( !SV_ShouldUnlagForPlayer( cl ))
return;
has_update = true;
@ -834,17 +838,13 @@ void SV_SetupMoveInterpolant( sv_client_t *cl )
lerp->active = true;
}
if( cl->latency > 1.5f )
latency = 1.5f;
else latency = cl->latency;
latency = Q_min( cl->latency, 1.5f );
if( sv_maxunlag.value != 0.0f )
{
if (sv_maxunlag.value < 0.0f )
Cvar_SetValue( "sv_maxunlag", 0.0f );
if( latency >= sv_maxunlag.value )
latency = sv_maxunlag.value;
latency = Q_min( latency, sv_maxunlag.value );
}
lerp_msec = cl->lastcmd.lerp_msec * 0.001f;
@ -856,9 +856,9 @@ void SV_SetupMoveInterpolant( sv_client_t *cl )
finalpush = ( host.realtime - latency - lerp_msec ) + sv_unlagpush.value;
if( finalpush > host.realtime ) finalpush = host.realtime; // pushed too much ?
frame = NULL;
frame = frame2 = NULL;
for( frame2 = NULL, i = 0; i < SV_UPDATE_BACKUP; i++, frame2 = frame )
for( i = 0; i < SV_UPDATE_BACKUP; i++, frame2 = frame )
{
frame = &cl->frames[(cl->netchan.outgoing_sequence - (i + 1)) & SV_UPDATE_MASK];
@ -866,19 +866,24 @@ void SV_SetupMoveInterpolant( sv_client_t *cl )
{
state = &svs.packet_entities[(frame->first_entity+j)%svs.num_client_entities];
if( state->number <= 0 || state->number >= svs.maxclients )
if( state->number < 1 || state->number > svs.maxclients )
continue;
lerp = &svgame.interp[state->number-1];
if( lerp->nointerp ) continue;
if( state->health <= 0 || ( state->effects & EF_NOINTERP ))
if( state->health <= 0 || FBitSet( state->effects, EF_NOINTERP ))
lerp->nointerp = true;
if( !lerp->firstframe )
if( lerp->firstframe )
{
if( SV_UnlagCheckTeleport( state->origin, lerp->finalpos ))
lerp->nointerp = true;
}
else
{
lerp->firstframe = true;
else if( SV_UnlagCheckTeleport( state->origin, lerp->finalpos ))
lerp->nointerp = true;
}
VectorCopy( state->origin, lerp->finalpos );
}
@ -916,7 +921,7 @@ void SV_SetupMoveInterpolant( sv_client_t *cl )
{
state = &svs.packet_entities[(frame->first_entity+i)%svs.num_client_entities];
if( state->number <= 0 || state->number >= svs.maxclients )
if( state->number < 1 || state->number > svs.maxclients )
continue;
clientnum = state->number - 1;
@ -966,16 +971,7 @@ void SV_RestoreMoveInterpolant( sv_client_t *cl )
return;
}
// don't allow unlag in singleplayer
if( svs.maxclients <= 1 || cl->state != cs_spawned )
return;
// unlag disabled by game request
if( !svgame.dllFuncs.pfnAllowLagCompensation() || !sv_unlag.value )
return;
// unlag disabled for current client
if( !FBitSet( cl->flags, FCL_LAG_COMPENSATION ))
if( !SV_ShouldUnlagForPlayer( cl ))
return;
for( i = 0, check = svs.clients; i < svs.maxclients; i++, check++ )
@ -985,11 +981,11 @@ void SV_RestoreMoveInterpolant( sv_client_t *cl )
oldlerp = &svgame.interp[i];
if( VectorCompare( oldlerp->oldpos, oldlerp->newpos ))
if( VectorCompare( oldlerp->oldpos, oldlerp->newpos ) || !oldlerp->moving )
continue; // they didn't actually move.
if( !oldlerp->moving || !oldlerp->active )
return;
if( !oldlerp->active )
continue;
if( VectorCompare( oldlerp->curpos, check->edict->v.origin ))
{