Optimized entity look ups

This commit is contained in:
Kamay Xutax 2024-09-04 21:18:45 +02:00
parent 4b2b5e7388
commit e12b3581e2
7 changed files with 70 additions and 22 deletions

View file

@ -846,7 +846,9 @@ C_BaseEntity::C_BaseEntity() :
AddVar( &m_angRotation, &m_iv_angRotation, LATCH_SIMULATION_VAR );
// Needed for lag compensation
AddVar( &m_flInterpolatedSimulationTime, &m_iv_flSimulationTime, LATCH_SIMULATION_VAR );
AddVar( &m_flInterpolatedAnimTime, &m_iv_flAnimTime, LATCH_ANIMATION_VAR );
// TODO_ENHANCED: For now, animations aren't interpolated!
// AddVar( &m_flInterpolatedAnimTime, &m_iv_flAnimTime, LATCH_ANIMATION_VAR );
// Removing this until we figure out why velocity introduces view hitching.
// One possible fix is removing the player->ResetLatched() call in CGameMovement::FinishDuck(),
// but that re-introduces a third-person hitching bug. One possible cause is the abrupt change
@ -2504,15 +2506,22 @@ void C_BaseEntity::PostDataUpdate( DataUpdateType_t updateType )
bool anglesChanged = ( m_vecOldAngRotation != GetLocalAngles() ) ? true : false;
bool simTimeChanged = ( m_flSimulationTime != m_flOldSimulationTime ) ? true : false;
// Store simulation time for lag compensation.
m_flInterpolatedSimulationTime = m_flSimulationTime;
m_flInterpolatedAnimTime = m_flAnimTime;
// Detect simulation changes
bool simulationChanged = originChanged || anglesChanged || simTimeChanged;
bool bPredictable = GetPredictable();
if ( !bPredictable )
{
// Store simulation time for lag compensation.
// These should be only set if it's not created by client or isn't a predictable,
// Otherwise createmove will send these values without caring and potentially
// make the client and server framerate less efficient including prediction errors.
// TODO_ENHANCED: apparently IsClientCreated doesn't behave as it should do ...
m_flInterpolatedSimulationTime = m_flSimulationTime;
m_flInterpolatedAnimTime = m_flAnimTime;
}
// For non-predicted and non-client only ents, we need to latch network values into the interpolation histories
if ( !bPredictable && !IsClientCreated() )
{

View file

@ -13,6 +13,7 @@
#include "cbase.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "const.h"
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
@ -21,7 +22,10 @@
// Create interface
static CClientEntityList s_EntityList;
CBaseEntityList *g_pEntityList = &s_EntityList;
CBaseEntityList* g_pEntityList = &s_EntityList;
static CFastEntityLookUp g_FastEntityLookUp;
CFastEntityLookUp* g_pFastEntityLookUp = &g_FastEntityLookUp;
// Expose list to engine
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CClientEntityList, IClientEntityList, VCLIENTENTITYLIST_INTERFACE_VERSION, s_EntityList );
@ -502,4 +506,30 @@ C_BaseEntity* C_BaseEntityIterator::Next()
}
return NULL;
}
CFastEntityLookUp::CFastEntityLookUp()
{
for ( int i = 0; i < MAX_EDICTS; i++ )
{
entities[i] = NULL;
}
cl_entitylist->AddListenerEntity( this );
}
void CFastEntityLookUp::OnEntityCreated( C_BaseEntity* pEntity )
{
if ( pEntity->index > 0 && pEntity->index < MAX_EDICTS )
{
entities[pEntity->index] = pEntity;
}
}
void CFastEntityLookUp::OnEntityDeleted( C_BaseEntity* pEntity )
{
if ( pEntity->index > 0 && pEntity->index < MAX_EDICTS )
{
entities[pEntity->index] = NULL;
}
}

View file

@ -6,6 +6,7 @@
// $Date: $
// $NoKeywords: $
//===========================================================================//
#include "const.h"
#if !defined( CLIENTENTITYLIST_H )
#define CLIENTENTITYLIST_H
#ifdef _WIN32
@ -303,6 +304,19 @@ public:
virtual void OnEntityDeleted( C_BaseEntity *pEntity ) {};
};
class CFastEntityLookUp : public IClientEntityListener
{
public:
CFastEntityLookUp();
virtual void OnEntityCreated( C_BaseEntity* pEntity );
virtual void OnEntityDeleted( C_BaseEntity* pEntity );
// Let have a chance to let the CPU autovectorize these!
CBaseEntity* entities[MAX_EDICTS];
};
extern CFastEntityLookUp* g_pFastEntityLookUp;
#endif // CLIENTENTITYLIST_H

View file

@ -28,7 +28,6 @@ void DrawSpriteModel( IClientEntity *baseentity, CEngineSprite *psprite,
float StandardGlowBlend( const pixelvis_queryparams_t &params, pixelvis_handle_t *queryHandle,
int rendermode, int renderfx, int alpha, float *pscale );
// Interface from engine to tools for manipulating entities
class CClientTools : public IClientTools, public IClientEntityListener
{

View file

@ -1304,6 +1304,7 @@ void CInput::CreateMove ( int sequence_number, float input_sample_frametime, boo
m_EntityGroundContact.RemoveAll();
#endif
// Let the compiler auto-vectorize this.
for ( int i = 0; i < MAX_EDICTS; i++ )
{
cmd->simulationdata[i] = {};
@ -1312,20 +1313,15 @@ void CInput::CreateMove ( int sequence_number, float input_sample_frametime, boo
// Send interpolated simulation time for lag compensation, let it also auto-vectorize this.
for ( int i = 0; i < MAX_EDICTS; i++ )
{
const auto pEntity = ClientEntityList().GetEnt( i );
auto pEntity = g_pFastEntityLookUp->entities[i];
if ( !pEntity )
{
continue;
}
if ( pEntity->ShouldPredict() )
{
continue;
}
cmd->simulationdata[pEntity->index].sim_time = pEntity->m_flInterpolatedSimulationTime;
cmd->simulationdata[pEntity->index].anim_time = pEntity->m_flAnimTime;
cmd->simulationdata[i].sim_time = pEntity->m_flInterpolatedSimulationTime;
cmd->simulationdata[i].anim_time = pEntity->m_flInterpolatedAnimTime;
}
#ifdef CSTRIKE_DLL

View file

@ -40,7 +40,7 @@ struct SimulationData
{
// TODO_ENHANCED:
// For now we send the last received update for animations.
// anim time is unreliable on low fps.
// We might optimize this by sending a base counter and round the other entities values to it.
float sim_time;
float anim_time;
};

View file

@ -1030,10 +1030,10 @@ float CountdownTimer::Now( void ) const
#ifdef CLIENT_DLL
CBasePlayer *UTIL_PlayerByIndex( int entindex )
{
return ToBasePlayer( ClientEntityList().GetEnt( entindex ) );
}
CBasePlayer* UTIL_PlayerByIndex( int entindex )
{
return ToBasePlayer( g_pFastEntityLookUp->entities[entindex] );
}
//=============================================================================
// HPE_BEGIN:
@ -1278,9 +1278,9 @@ CBaseEntity *UTIL_FindEntityProcedural( const char *szName, CBaseEntity *pSearch
*/
CBaseEntity* UTIL_FindEntityByName(const char* szName)
{
for (int i = 0; i < cl_entitylist->GetHighestEntityIndex(); ++i)
for (int i = 0; i < MAX_EDICTS; ++i)
{
IClientEntity* pClientEntity = cl_entitylist->GetClientEntity( i );
IClientEntity* pClientEntity = g_pFastEntityLookUp->entities[i];
if (!pClientEntity)
{