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 ); AddVar( &m_angRotation, &m_iv_angRotation, LATCH_SIMULATION_VAR );
// Needed for lag compensation // Needed for lag compensation
AddVar( &m_flInterpolatedSimulationTime, &m_iv_flSimulationTime, LATCH_SIMULATION_VAR ); 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. // Removing this until we figure out why velocity introduces view hitching.
// One possible fix is removing the player->ResetLatched() call in CGameMovement::FinishDuck(), // 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 // 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 anglesChanged = ( m_vecOldAngRotation != GetLocalAngles() ) ? true : false;
bool simTimeChanged = ( m_flSimulationTime != m_flOldSimulationTime ) ? 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 // Detect simulation changes
bool simulationChanged = originChanged || anglesChanged || simTimeChanged; bool simulationChanged = originChanged || anglesChanged || simTimeChanged;
bool bPredictable = GetPredictable(); 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 // For non-predicted and non-client only ents, we need to latch network values into the interpolation histories
if ( !bPredictable && !IsClientCreated() ) if ( !bPredictable && !IsClientCreated() )
{ {

View file

@ -13,6 +13,7 @@
#include "cbase.h" #include "cbase.h"
// memdbgon must be the last include file in a .cpp file!!! // memdbgon must be the last include file in a .cpp file!!!
#include "const.h"
#include "tier0/memdbgon.h" #include "tier0/memdbgon.h"
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -23,6 +24,9 @@
static CClientEntityList s_EntityList; 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 list to engine
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CClientEntityList, IClientEntityList, VCLIENTENTITYLIST_INTERFACE_VERSION, s_EntityList ); EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CClientEntityList, IClientEntityList, VCLIENTENTITYLIST_INTERFACE_VERSION, s_EntityList );
@ -503,3 +507,29 @@ C_BaseEntity* C_BaseEntityIterator::Next()
return NULL; 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: $ // $Date: $
// $NoKeywords: $ // $NoKeywords: $
//===========================================================================// //===========================================================================//
#include "const.h"
#if !defined( CLIENTENTITYLIST_H ) #if !defined( CLIENTENTITYLIST_H )
#define CLIENTENTITYLIST_H #define CLIENTENTITYLIST_H
#ifdef _WIN32 #ifdef _WIN32
@ -303,6 +304,19 @@ public:
virtual void OnEntityDeleted( C_BaseEntity *pEntity ) {}; 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 #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, float StandardGlowBlend( const pixelvis_queryparams_t &params, pixelvis_handle_t *queryHandle,
int rendermode, int renderfx, int alpha, float *pscale ); int rendermode, int renderfx, int alpha, float *pscale );
// Interface from engine to tools for manipulating entities // Interface from engine to tools for manipulating entities
class CClientTools : public IClientTools, public IClientEntityListener 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(); m_EntityGroundContact.RemoveAll();
#endif #endif
// Let the compiler auto-vectorize this.
for ( int i = 0; i < MAX_EDICTS; i++ ) for ( int i = 0; i < MAX_EDICTS; i++ )
{ {
cmd->simulationdata[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. // Send interpolated simulation time for lag compensation, let it also auto-vectorize this.
for ( int i = 0; i < MAX_EDICTS; i++ ) for ( int i = 0; i < MAX_EDICTS; i++ )
{ {
const auto pEntity = ClientEntityList().GetEnt( i ); auto pEntity = g_pFastEntityLookUp->entities[i];
if ( !pEntity ) if ( !pEntity )
{ {
continue; continue;
} }
if ( pEntity->ShouldPredict() ) cmd->simulationdata[i].sim_time = pEntity->m_flInterpolatedSimulationTime;
{ cmd->simulationdata[i].anim_time = pEntity->m_flInterpolatedAnimTime;
continue;
}
cmd->simulationdata[pEntity->index].sim_time = pEntity->m_flInterpolatedSimulationTime;
cmd->simulationdata[pEntity->index].anim_time = pEntity->m_flAnimTime;
} }
#ifdef CSTRIKE_DLL #ifdef CSTRIKE_DLL

View file

@ -40,7 +40,7 @@ struct SimulationData
{ {
// TODO_ENHANCED: // TODO_ENHANCED:
// For now we send the last received update for animations. // 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 sim_time;
float anim_time; float anim_time;
}; };

View file

@ -1032,7 +1032,7 @@ float CountdownTimer::Now( void ) const
#ifdef CLIENT_DLL #ifdef CLIENT_DLL
CBasePlayer* UTIL_PlayerByIndex( int entindex ) CBasePlayer* UTIL_PlayerByIndex( int entindex )
{ {
return ToBasePlayer( ClientEntityList().GetEnt( entindex ) ); return ToBasePlayer( g_pFastEntityLookUp->entities[entindex] );
} }
//============================================================================= //=============================================================================
@ -1278,9 +1278,9 @@ CBaseEntity *UTIL_FindEntityProcedural( const char *szName, CBaseEntity *pSearch
*/ */
CBaseEntity* UTIL_FindEntityByName(const char* szName) 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) if (!pClientEntity)
{ {