04 Apr 2010

This commit is contained in:
g-cont 2010-04-04 00:00:00 +04:00 committed by Alibek Omarov
parent 0915c8647b
commit 9f0fb3da32
14 changed files with 128 additions and 47 deletions

View File

@ -260,6 +260,63 @@ void HUD_UpdateEntityVars( edict_t *ent, const entity_state_t *state, const enti
ent->v.rendercolor[i] = LerpPoint( prev->rendercolor[i], state->rendercolor[i], m_fLerp );
}
if( ent->v.movetype == MOVETYPE_STEP )
{
float f = 0;
float d;
// don't do it if the goalstarttime hasn't updated in a while.
// NOTE: Because we need to interpolate multiplayer characters, the interpolation time limit
// was increased to 1.0 s., which is 2x the max lag we are accounting for.
if(( gpGlobals->time < state->animtime + 1.0f ) && ( state->animtime != prev->animtime ))
{
f = (gpGlobals->time - state->animtime) / (state->animtime - prev->animtime);
//ALERT( at_console, "%4.2f %.2f %.2f\n", f, state->animtime, gpGlobals->time );
}
if(!( ent->v.flags & EF_NOINTERP ))
{
// ugly hack to interpolate angle, position.
// current is reached 0.1 seconds after being set
f = f - 1.0;
}
else
{
f = 0;
}
for( i = 0; i < 3; i++ )
{
ent->v.origin[i] += (ent->v.origin[i] - prev->origin[i]) * f;
}
// NOTE: Because multiplayer lag can be relatively large, we don't want to cap
// f at 1.5 anymore.
//if( f > -1.0 && f < 1.5 ) {}
for( i = 0; i < 3; i++ )
{
float ang1, ang2;
ang1 = ent->v.angles[i];
ang2 = prev->angles[i];
d = ang1 - ang2;
if( d > 180 )
{
d -= 360;
}
else if( d < -180 )
{
d += 360;
}
ent->v.angles[i] += d * f;
}
//ALERT( at_console, "%.3f \n", f );
}
// interpolate scale, renderamount etc
ent->v.renderamt = LerpPoint( prev->renderamt, state->renderamt, m_fLerp );
ent->v.scale = LerpPoint( prev->scale, state->scale, m_fLerp );
@ -272,7 +329,7 @@ void HUD_UpdateEntityVars( edict_t *ent, const entity_state_t *state, const enti
if( ent->v.animtime )
{
if( ent->v.effects & EF_NOINTERP )
if(!( ent->v.effects & EF_NOINTERP ))
{
// adjust lerping values if animation restarted
if( lerpTime < 0 ) prevframe = 1.001;

View File

@ -246,7 +246,7 @@ void CL_DeleteDemo_f( void )
{
if( Cmd_Argc() != 2 )
{
Msg( "Usage: deldemo <name>\n" );
Msg( "Usage: killdemo <name>\n" );
return;
}

View File

@ -1044,7 +1044,7 @@ void CL_InitLocal( void )
Cmd_AddCommand ("disconnect", CL_Disconnect_f, "disconnect from server" );
Cmd_AddCommand ("record", CL_Record_f, "record a demo" );
Cmd_AddCommand ("playdemo", CL_PlayDemo_f, "playing a demo" );
Cmd_AddCommand ("deldemo", CL_DeleteDemo_f, "delete a specified demo file and demoshot" );
Cmd_AddCommand ("killdemo", CL_DeleteDemo_f, "delete a specified demo file and demoshot" );
Cmd_AddCommand ("startdemos", CL_StartDemos_f, "start playing back the selected demos sequentially" );
Cmd_AddCommand ("demos", CL_Demos_f, "restart looping demos defined by the last startdemos command" );
Cmd_AddCommand ("movie", CL_PlayVideo_f, "playing a movie" );

View File

@ -290,7 +290,7 @@ extern byte net_message_buffer[MAX_MSGLEN];
#define PORT_CLIENT 27901
#define PORT_SERVER 27910
#define MULTIPLAYER_BACKUP 64 // how many data slots to use when in multiplayer (must be power of 2)
#define SINGLEPLAYER_BACKUP 8 // same for single player
#define SINGLEPLAYER_BACKUP 16 // same for single player
#define MAX_FLAGS 32 // 32 bits == 32 flags
#define MASK_FLAGS (MAX_FLAGS - 1)

View File

@ -98,6 +98,7 @@ typedef struct sv_client_s
char userinfo[MAX_INFO_STRING]; // name, etc (received from client)
char physinfo[MAX_INFO_STRING]; // set on server (transmit to client)
bool physinfo_modified; // transmit at next opportunity
bool send_message;
bool sendmovevars;
bool sendinfo;
@ -390,6 +391,7 @@ void SV_WriteFrameToClient( sv_client_t *client, sizebuf_t *msg );
void SV_BuildClientFrame( sv_client_t *client );
void SV_UpdateEntityState( const edict_t *ent, bool baseline );
void SV_InactivateClients( void );
void SV_SendMessagesToAll( void );
//
// sv_game.c

View File

@ -1467,7 +1467,8 @@ void SV_ExecuteClientMessage( sv_client_t *cl, sizebuf_t *msg )
// make sure the reply sequence number matches the incoming sequence number
if( cl->netchan.incoming_sequence >= cl->netchan.outgoing_sequence )
cl->netchan.outgoing_sequence = cl->netchan.incoming_sequence;
else cl->send_message = false; // don't reply, sequences have slipped
// read optional clientCommand strings
while( cl->state != cs_zombie )
{

View File

@ -585,8 +585,12 @@ void SV_SendClientMessages( void )
MSG_Clear( &cl->datagram );
SV_BroadcastPrintf( PRINT_HIGH, "%s overflowed\n", cl->name );
SV_DropClient( cl );
cl->send_message = true;
}
// only send messages if the client has sent one
if( !cl->send_message ) continue;
if( cl->state == cs_spawned )
{
// don't overrun bandwidth
@ -595,13 +599,36 @@ void SV_SendClientMessages( void )
}
else
{
// just update reliable if needed
// just update reliable
if( cl->netchan.message.cursize || svs.realtime - cl->netchan.last_sent > 1000 )
Netchan_Transmit( &cl->netchan, 0, NULL );
}
// yes, message really sended
cl->send_message = false;
}
}
/*
=======================
SV_SendMessagesToAll
e.g. before changing level
=======================
*/
void SV_SendMessagesToAll( void )
{
int i;
sv_client_t *cl;
for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
{
if( cl->state >= cs_connected )
cl->send_message = true;
}
SV_SendClientMessages();
}
/*
=======================
SV_InactivateClients

View File

@ -1151,14 +1151,14 @@ free edict private mem, unlink physics etc
*/
void pfnRemoveEntity( edict_t* e )
{
if( !e || e->free )
if( !SV_IsValidEdict( e ))
{
MsgDev( D_ERROR, "SV_RemoveEntity: entity already freed\n" );
return;
}
// never free client or world entity
if(( NUM_FOR_EDICT( e ) - 1 ) < svgame.globals->maxClients )
if( e->serialnumber < ( svgame.globals->maxClients + 1 ))
{
MsgDev( D_ERROR, "SV_RemoveEntity: can't delete %s\n", (e == EDICT_NUM( 0 )) ? "world" : "client" );
return;

View File

@ -258,8 +258,11 @@ void SV_ReadPackets( void )
MsgDev( D_INFO, "SV_ReadPackets: fixing up a translated port\n");
cl->netchan.remote_address.port = net_from.port;
}
if( Netchan_Process( &cl->netchan, &net_message ))
{
cl->send_message = true; // reply at end of frame
// this is a valid, sequenced packet, so process it
if( cl->state != cs_zombie )
{
@ -357,8 +360,13 @@ void SV_PrepWorldFrame( void )
{
ent = EDICT_NUM( i );
if( ent->free ) continue;
ent->pvServerData->s.ed_flags = 0;
ent->v.effects &= ~EF_MUZZLEFLASH;
// clear NOINTERP flag automatically only for alive creatures
if( ent->v.flags & ( FL_MONSTER|FL_CLIENT|FL_FAKECLIENT ) && ent->v.health > 0.0f )
ent->v.effects &= ~EF_NOINTERP;
}
}
@ -391,14 +399,14 @@ SV_RunGameFrame
*/
void SV_RunGameFrame( void )
{
if( !SV_HasActivePlayers()) return;
// we always need to bump framenum, even if we
// don't run the world, otherwise the delta
// compression can get confused when a client
// has the "current" frame
sv.framenum++;
if( !SV_HasActivePlayers()) return;
// don't run if paused or not in game
if( !sv.paused && CL_IsInGame( ))
SV_Physics();

View File

@ -650,11 +650,10 @@ void SV_RunCmd( sv_client_t *cl, usercmd_t *ucmd )
if(!( clent->v.flags & FL_SPECTATOR ))
{
svgame.globals->time = sv.time * 0.001f;
svgame.globals->frametime = 0.0f;
svgame.dllFuncs.pfnPlayerPreThink( clent );
svgame.globals->frametime = ucmd->msec * 0.001f;
svgame.dllFuncs.pfnPlayerPreThink( clent );
SV_RunThink( clent );
SV_RunThink( clent ); // clients cannot be deleted from map
// If conveyor, or think, set basevelocity, then send to client asap too.
if( VectorLength( clent->v.basevelocity ) > 0.0f )
@ -711,21 +710,15 @@ void SV_PostRunCmd( sv_client_t *cl )
clent = cl->edict;
if( !clent || clent->free ) return;
svgame.pmove->runfuncs = false; // all next calls ignore footstep sounds
svgame.pmove->runfuncs = false; // all next calls ignore footstep sounds
svgame.globals->frametime = 0.0f; // PlayerPostThink uses it
svgame.globals->time = sv.time * 0.001f;
// run post-think
if(!( clent->v.flags & FL_SPECTATOR ))
{
svgame.globals->time = sv.time * 0.001f;
svgame.globals->frametime = 0;
svgame.dllFuncs.pfnPlayerPostThink( clent );
}
else
{
svgame.globals->time = sv.time * 0.001f;
svgame.globals->frametime = 0;
if( clent->v.flags & FL_SPECTATOR )
svgame.dllFuncs.pfnSpectatorThink( clent );
}
else svgame.dllFuncs.pfnPlayerPostThink( clent );
// restore frametime
svgame.globals->frametime = sv.frametime * 0.001f;

View File

@ -174,21 +174,21 @@ bool SV_RunThink( edict_t *ent )
int i;
float newtime;
newtime = (sv.time + sv.frametime) * 0.001f;
newtime = (sv.time * 0.001f) + (sv.frametime * 0.001f);
// don't let things stay in the past.
// it is possible to start that way by a trigger with a local time.
if( ent->v.nextthink <= 0.0f || ent->v.nextthink > newtime )
return true;
for( i = 0; i < 128 && !ent->free; i++ )
for( i = 0; i < SV_UPDATE_BACKUP && !ent->free; i++ )
{
svgame.globals->time = max( (sv.time * 0.001f), ent->v.nextthink );
svgame.globals->time = max(( sv.time * 0.001f ), ent->v.nextthink );
ent->v.nextthink = 0.0f;
svgame.dllFuncs.pfnThink( ent );
newtime = (sv.time + sv.frametime) * 0.001f;
newtime = (sv.time * 0.001f) + (sv.frametime * 0.001f);
// mods often set nextthink to time to cause a think every frame,
// we don't want to loop in that case, so exit if the new nextthink is
@ -1063,6 +1063,7 @@ void SV_PushMove( edict_t *pusher, float movetime )
// if the pusher has a "blocked" function, call it
// otherwise, just stay in place until the obstacle is gone
svgame.globals->time = (sv.time * 0.001f);
svgame.dllFuncs.pfnBlocked( pusher, check );
break;
}
@ -1209,6 +1210,7 @@ bool SV_PushAngles( edict_t *pusher, vec3_t move, vec3_t amove )
}
MsgDev( D_INFO, "Pusher hit %s\n", SV_ClassName( check ));
svgame.globals->time = (sv.time * 0.001f);
svgame.dllFuncs.pfnBlocked( pusher, check );
// move back any entities we already moved
@ -1907,10 +1909,7 @@ void SV_Physics_Step_RunTimestep( edict_t *ent, float timestep )
void SV_Physics_Step( edict_t *ent )
{
svgame.globals->time = sv.time * 0.001f;
SV_Physics_Step_RunTimestep( ent, svgame.globals->frametime );
if( !SV_RunThink( ent )) return;
SV_CheckWaterTransition( ent );
}
@ -2008,7 +2007,7 @@ void SV_Physics_None( edict_t *ent )
{
float newtime;
newtime = (sv.time + sv.frametime) * 0.001f;
newtime = (sv.time * 0.001f) + svgame.globals->frametime;
if( ent->v.nextthink > 0.0f && ent->v.nextthink <= newtime )
SV_RunThink( ent );
}
@ -2093,8 +2092,8 @@ SV_Physics
*/
void SV_Physics( void )
{
edict_t *ent;
int i;
edict_t *ent;
// let the progs know that a new frame has started
svgame.globals->time = sv.time * 0.001f;
@ -2135,6 +2134,5 @@ void SV_Physics( void )
svgame.dllFuncs.pfnEndFrame();
if( !sv_playersonly->integer )
sv.time += sv.frametime;
if( !sv_playersonly->integer ) sv.time += sv.frametime;
}

View File

@ -756,6 +756,8 @@ void PlayerPostThink( edict_t *pEntity )
// use the old frametime, even if the engine has reset it
gpGlobals->frametime = cached_frametime;
PhysicsPostFrame();
}
void BuildLevelList( void )
@ -958,13 +960,11 @@ void StartFrame( void )
}
ServerPostActivate(); // called once
PhysicsPostFrame();
PhysicsFrame();
}
void EndFrame( void )
{
PhysicsFrame();
}
/*
@ -1206,9 +1206,6 @@ void UpdateEntityState( entity_state_t *to, edict_t *from, int baseline )
if( pNet->pev->fov < 0.0 ) pNet->pev->fov = 0.0;
if( pNet->pev->fov > 160 ) pNet->pev->fov = 160;
to->fov = pNet->pev->fov;
// clear EF_NOINTERP flag each frame for client
pNet->pev->effects &= ~EF_NOINTERP;
}
else if( to->ed_type == ED_AMBIENT )
{

View File

@ -1174,9 +1174,6 @@ void UpdateEntityState( entity_state_t *to, edict_t *from, int baseline )
if( pNet->pev->fov < 0.0 ) pNet->pev->fov = 0.0;
if( pNet->pev->fov > 160 ) pNet->pev->fov = 160;
to->fov = pNet->pev->fov;
// clear EF_NOINTERP flag each frame for client
pNet->pev->effects &= ~EF_NOINTERP;
}
else if( to->ed_type == ED_AMBIENT )
{

View File

@ -26,7 +26,8 @@ Xash 0.71 Beta 05.05.10
2. fix sky changelevel bug
3. complete lights.shader
4. revision server physic
5. revision monster moving
5. revision monster moving OK
6. fix save\restore global state OK
7. rewrite WalkMove OK
8. tune UPDATE_BACKUP value for singleplayer
8. tune UPDATE_BACKUP value for singleplayer OK
9. fix monsters interpolation