2023-09-30 14:49:35 +02:00
# ifndef ENTITYSYSTEM_H
# define ENTITYSYSTEM_H
# include "tier0/platform.h"
2023-12-23 20:03:58 +03:00
# include "tier0/threadtools.h"
# include "tier1/generichash.h"
# include "tier1/keyvalues3.h"
2023-09-30 14:49:35 +02:00
# include "tier1/utlmemory.h"
2023-11-15 07:32:36 +03:00
# include "tier1/utlsymbollarge.h"
2023-09-30 14:49:35 +02:00
# include "tier1/utlvector.h"
# include "tier1/utldict.h"
2023-12-23 20:03:58 +03:00
# include "tier1/utlmap.h"
# include "tier1/utlhashtable.h"
2024-01-26 05:11:01 +03:00
# include "tier1/utldelegate.h"
2023-12-23 20:03:58 +03:00
# include "tier1/utlscratchmemory.h"
# include "tier1/utlstring.h"
# include "networksystem/inetworkserializer.h"
# include "vscript/ivscript.h"
2023-09-30 14:49:35 +02:00
# include "eiface.h"
2024-01-26 07:15:55 +03:00
# include "resourcefile/resourcetype.h"
2023-10-13 19:38:47 +03:00
# include "entityhandle.h"
2023-09-30 14:49:35 +02:00
# include "concreteentitylist.h"
# include "entitydatainstantiator.h"
2024-01-26 07:15:55 +03:00
class CKeyValues3Context ;
2023-12-23 20:03:58 +03:00
class CEntityClass ;
class CEntityComponentHelper ;
2023-09-30 14:49:35 +02:00
class CEntityKeyValues ;
2023-12-23 20:03:58 +03:00
class CGameEntitySystem ;
class IEntityIONotify ;
class INetworkFieldChangedEventQueue ;
class INetworkFieldScratchData ;
class IFieldChangeLimitSpew ;
class IEntity2SaveRestore ;
class IEntity2Networkables ;
2023-09-30 14:49:35 +02:00
class IEntityResourceManifest ;
class IEntityPrecacheConfiguration ;
class IEntityResourceManifestBuilder ;
class ISpawnGroupEntityFilter ;
2023-11-15 07:32:36 +03:00
class IHandleEntity ;
2023-12-23 20:03:58 +03:00
struct ComponentUnserializerFieldInfo_t ;
extern CGameEntitySystem * GameEntitySystem ( ) ;
2023-09-30 14:49:35 +02:00
2023-10-07 11:06:14 +03:00
typedef void ( * EntityResourceManifestCreationCallback_t ) ( IEntityResourceManifest * , void * ) ;
2023-09-30 14:49:35 +02:00
2024-10-05 05:11:24 +03:00
struct GameTime_t
{
public :
GameTime_t ( float value = 0.0f ) : m_Value ( value ) { }
float GetTime ( ) const { return m_Value ; }
void SetTime ( float value ) { m_Value = value ; }
private :
float m_Value ;
} ;
2023-12-23 20:03:58 +03:00
enum EntityIOTargetType_t
{
ENTITY_IO_TARGET_INVALID = - 1 ,
ENTITY_IO_TARGET_CLASSNAME = 0 ,
ENTITY_IO_TARGET_CLASSNAME_DERIVES_FROM = 1 ,
ENTITY_IO_TARGET_ENTITYNAME = 2 ,
ENTITY_IO_TARGET_CONTAINS_COMPONENT = 3 ,
ENTITY_IO_TARGET_SPECIAL_ACTIVATOR = 4 ,
ENTITY_IO_TARGET_SPECIAL_CALLER = 5 ,
ENTITY_IO_TARGET_EHANDLE = 6 ,
ENTITY_IO_TARGET_ENTITYNAME_OR_CLASSNAME = 7 ,
} ;
enum EntityIterType_t
{
ENTITY_ITER_OVER_ACTIVE = 0x0 ,
ENTITY_ITER_OVER_DORMANT = 0x1 ,
} ;
2023-09-30 14:49:35 +02:00
enum SpawnGroupEntityFilterType_t
{
SPAWN_GROUP_ENTITY_FILTER_FALLBACK = 0x0 ,
SPAWN_GROUP_ENTITY_FILTER_MOD_SPECIFIC = 0x1 ,
} ;
enum ClearEntityDatabaseMode_t
{
CED_NORMAL = 0x0 ,
CED_NETWORKEDONLY_AND_DONTCLEARSTRINGPOOL = 0x1 ,
} ;
enum ActivateType_t
{
ACTIVATE_TYPE_INITIAL_CREATION = 0x0 ,
ACTIVATE_TYPE_DATAUPDATE_CREATION = 0x1 ,
ACTIVATE_TYPE_ONRESTORE = 0x2 ,
} ;
enum DataUpdateType_t
{
DATA_UPDATE_CREATED = 0x0 ,
DATA_UPDATE_DATATABLE_CHANGED = 0x1 ,
} ;
enum EntityDormancyType_t
{
ENTITY_NOT_DORMANT = 0x0 ,
ENTITY_DORMANT = 0x1 ,
ENTITY_SUSPENDED = 0x2 ,
} ;
2023-12-23 20:03:58 +03:00
// Event queue //
struct EventQueuePrioritizedEvent_t
{
2024-10-05 05:11:24 +03:00
int m_unk001 ;
GameTime_t m_flFireTime ;
2023-12-23 20:03:58 +03:00
EntityIOTargetType_t m_eTargetType ;
CUtlSymbolLarge m_iTarget ;
CUtlSymbolLarge m_iTargetInput ;
CEntityHandle m_pActivator ;
CEntityHandle m_pCaller ;
int m_iOutputID ;
CEntityHandle m_pEntTarget ; // a pointer to the entity to target; overrides m_iTarget
variant_t m_VariantValue ; // variable-type parameter
EventQueuePrioritizedEvent_t * m_pNext ;
EventQueuePrioritizedEvent_t * m_pPrev ;
} ;
class CEventQueue
{
public :
CThreadMutex m_Mutex ;
EventQueuePrioritizedEvent_t m_Events ;
int m_iListCount ;
} ;
2023-11-15 07:32:36 +03:00
// Entity notifications //
2023-09-30 14:49:35 +02:00
struct EntityNotification_t
{
CEntityIdentity * m_pEntity ;
} ;
struct EntityDormancyChange_t : EntityNotification_t
{
EntityDormancyType_t m_nPrevDormancyType ;
EntityDormancyType_t m_nNewDormancyType ;
} ;
struct EntitySpawnInfo_t : EntityNotification_t
{
const CEntityKeyValues * m_pKeyValues ;
2023-10-08 18:55:15 +03:00
uint64 m_Unk1 ;
2023-09-30 14:49:35 +02:00
} ;
struct EntityActivation_t : EntityNotification_t
{
} ;
struct EntityDeletion_t : EntityNotification_t
{
} ;
struct PostDataUpdateInfo_t : EntityNotification_t
{
DataUpdateType_t m_updateType ;
} ;
struct CEntityPrecacheContext
{
const CEntityKeyValues * m_pKeyValues ;
IEntityPrecacheConfiguration * m_pConfig ;
IEntityResourceManifest * m_pManifest ;
} ;
2023-11-15 07:32:36 +03:00
struct SecondaryPrecacheMemberCallback_t
{
void ( CEntityInstance : : * pfnPrecache ) ( ResourceHandle_t hResource , const CEntityPrecacheContext * pContext ) ;
} ;
2023-09-30 14:49:35 +02:00
class IEntityListener
{
public :
2023-10-08 18:55:15 +03:00
virtual void OnEntityCreated ( CEntityInstance * pEntity ) { } ;
virtual void OnEntitySpawned ( CEntityInstance * pEntity ) { } ;
virtual void OnEntityDeleted ( CEntityInstance * pEntity ) { } ;
virtual void OnEntityParentChanged ( CEntityInstance * pEntity , CEntityInstance * pNewParent ) { } ;
2023-09-30 14:49:35 +02:00
} ;
struct CEntityResourceManifestLock
{
IEntityResourceManifestBuilder * m_pBuilder ;
matrix3x4a_t m_vSpawnGroupOffset ;
SpawnGroupHandle_t m_hSpawnGroup ;
IEntityPrecacheConfiguration * m_pConfig ;
IEntityResourceManifest * m_pManifest ;
bool m_bIsLocked ;
bool m_bPrecacheEnable ;
} ;
2023-11-15 07:32:36 +03:00
// Manifest executor //
2023-09-30 14:49:35 +02:00
abstract_class IEntityResourceManifestBuilder
{
public :
2023-11-15 07:32:36 +03:00
virtual void BuildResourceManifest ( SpawnGroupHandle_t hSpawnGroup , int nCount , const EntitySpawnInfo_t * pEntities , const matrix3x4a_t * vWorldOffset , IEntityPrecacheConfiguration * pConfig , IEntityResourceManifest * pResourceManifest ) = 0 ;
virtual void BuildResourceManifest ( SpawnGroupHandle_t hSpawnGroup , int iCount , const CEntityKeyValues * pKeyValues , IEntityPrecacheConfiguration * pConfig , IEntityResourceManifest * pResourceManifest ) = 0 ;
2024-01-26 07:15:55 +03:00
virtual void BuildResourceManifest ( SpawnGroupHandle_t hSpawnGroup , const CUtlVector < const CEntityKeyValues * > * pEntityKeyValues , const char * pFilterName /* Usually, "mapload" and "cs_respawn"/"respawn". See CSpawnGroupEntityFilterRegistrar ctors */ , IEntityPrecacheConfiguration * pConfig , IEntityResourceManifest * pResourceManifest ) = 0 ;
2023-09-30 14:49:35 +02:00
virtual void BuildResourceManifest ( const char * pManifestNameOrGroupName , IEntityPrecacheConfiguration * pConfig , IEntityResourceManifest * pResourceManifest ) = 0 ;
2023-11-15 07:32:36 +03:00
virtual void BuildResourceManifest ( EntityResourceManifestCreationCallback_t callback , void * pContext , IEntityPrecacheConfiguration * pConfig , IEntityResourceManifest * pResourceManifest ) = 0 ;
2024-01-26 07:15:55 +03:00
virtual void BuildResourceManifestForEntity ( const char * pEntityDesignerName , IEntityPrecacheConfiguration * pConfig , IEntityResourceManifest * pResourceManifest , CKeyValues3Context * pEntityAllocator ) = 0 ;
2023-11-15 07:32:36 +03:00
virtual void InvokePrecacheCallback ( ResourceHandle_t hResource , const EntitySpawnInfo_t * info , IEntityPrecacheConfiguration * pConfig , IEntityResourceManifest * pResourceManifest , SecondaryPrecacheMemberCallback_t callback ) = 0 ;
2023-09-30 14:49:35 +02:00
virtual void AddRefKeyValues ( const CEntityKeyValues * pKeyValues ) = 0 ;
virtual void ReleaseKeyValues ( const CEntityKeyValues * pKeyValues ) = 0 ;
virtual void LockResourceManifest ( bool bLock , CEntityResourceManifestLock * const context ) = 0 ;
} ;
class CEntitySystem : public IEntityResourceManifestBuilder
{
2024-10-06 03:59:03 +03:00
private :
2023-12-23 20:03:58 +03:00
enum
{
MAX_ACCESSORS = 32 ,
} ;
struct CreationInfo_t
{
CEntityHandle m_hEnt ;
CEntityInstance * m_pEnt ;
const CEntityKeyValues * m_pKeyValues ;
2024-10-07 01:33:33 +03:00
// AMNOTE: Seems to be checked along side m_pKeyValues before its usage
bool m_bEntityKeyValuesInitialized ;
2023-12-23 20:03:58 +03:00
} ;
struct DestructionInfo_t
{
CEntityIdentity * m_pEnt ;
} ;
struct DormancyChangeInfo_t
{
2024-01-26 05:11:01 +03:00
CEntityHandle m_hEnt ;
bool m_bInPVS ;
2023-12-23 20:03:58 +03:00
} ;
struct MurmurHash2HashFunctor
{
unsigned int operator ( ) ( uint32 n ) const { return MurmurHash2 ( & n , sizeof ( uint32 ) , 0x3501A674 ) ; }
} ;
2024-10-06 03:59:03 +03:00
typedef CUtlDelegate < bool ( IParsingErrorListener * , CEntityInstance * , void * , const ComponentUnserializerFieldInfo_t * , const KeyValues3 * ) > KeyUnserializerDelegate ;
2023-09-30 14:49:35 +02:00
public :
2023-12-23 20:03:58 +03:00
virtual ~ CEntitySystem ( ) = 0 ;
2024-10-05 05:11:24 +03:00
// This function is called in CGameEntitySystem::ProcessEventQueue()
virtual GameTime_t unk_001 ( int ) = 0 ;
2023-12-23 20:03:58 +03:00
virtual void ClearEntityDatabase ( ClearEntityDatabaseMode_t eMode ) = 0 ;
virtual CEntityInstance * FindEntityProcedural ( const char * szName , CEntityInstance * pSearchingEntity = nullptr , CEntityInstance * pActivator = nullptr , CEntityInstance * pCaller = nullptr ) = 0 ;
virtual void OnEntityParentChanged ( CEntityInstance * pEntity , CEntityInstance * pNewParent ) = 0 ; // empty function
virtual void OnAddEntity ( CEntityInstance * pEnt , CEntityHandle handle ) = 0 ; // empty function
virtual void OnRemoveEntity ( CEntityInstance * pEnt , CEntityHandle handle ) = 0 ; // empty function
2024-01-26 05:11:01 +03:00
virtual WorldGroupId_t GetSpawnGroupWorldId ( SpawnGroupHandle_t hSpawnGroup ) = 0 ;
2023-12-23 20:03:58 +03:00
virtual void Spawn ( int nCount , const EntitySpawnInfo_t * pInfo ) = 0 ;
virtual void Activate ( int nCount , const EntityActivation_t * pActivates , ActivateType_t activateType ) = 0 ;
virtual void PostDataUpdate ( int nCount , const PostDataUpdateInfo_t * pInfo ) = 0 ;
virtual void OnSetDormant ( int nCount , const EntityDormancyChange_t * pInfo , bool bNotifyAddedToPVS ) = 0 ;
virtual void UpdateOnRemove ( int nCount , const EntityDeletion_t * pDeletion ) = 0 ;
2023-09-30 14:49:35 +02:00
public :
2023-12-24 14:56:13 +03:00
CEntityIdentity * GetEntityIdentity ( CEntityIndex entnum ) ;
CEntityIdentity * GetEntityIdentity ( const CEntityHandle & hEnt ) ;
2023-12-23 20:03:58 +03:00
2023-12-24 14:56:13 +03:00
inline CEntityInstance * GetEntityInstance ( CEntityIdentity * ident ) { return ident ? ident - > m_pInstance : nullptr ; }
inline CEntityInstance * GetEntityInstance ( CEntityIndex entnum ) { return GetEntityInstance ( GetEntityIdentity ( entnum ) ) ; }
inline CEntityInstance * GetEntityInstance ( const CEntityHandle & hEnt ) { return GetEntityInstance ( GetEntityIdentity ( hEnt ) ) ; }
2023-09-30 14:49:35 +02:00
2023-12-23 20:03:58 +03:00
inline void AddEntityKeyValuesAllocatorRef ( ) { + + m_nEntityKeyValuesAllocatorRefCount ; }
inline void ReleaseEntityKeyValuesAllocatorRef ( )
{
if ( - - m_nEntityKeyValuesAllocatorRefCount = = 0 )
m_EntityKeyValuesAllocator . Clear ( ) ;
}
inline CKeyValues3Context * GetEntityKeyValuesAllocator ( ) { return & m_EntityKeyValuesAllocator ; }
// Search for an entity class by its C++ name, case-insensitive
CEntityClass * FindClassByName ( const char * szClassName ) ;
// Search for an entity class by its designer name, case-insensitive
CEntityClass * FindClassByDesignName ( const char * szClassName ) ;
CEntityHandle FindFirstEntityHandleByName ( const char * szName , WorldGroupId_t hWorldGroupId = WorldGroupId_t ( ) ) ;
CUtlSymbolLarge AllocPooledString ( const char * pString ) ;
CUtlSymbolLarge FindPooledString ( const char * pString ) ;
2023-09-30 14:49:35 +02:00
private :
2024-10-06 03:59:03 +03:00
IEntityResourceManifest * m_pCurrentManifest ;
2023-10-08 18:55:15 +03:00
2023-12-23 20:03:58 +03:00
public :
2024-10-06 03:59:03 +03:00
CConcreteEntityList m_EntityList ;
CUtlString m_sEntSystemName ;
CUtlMap < const char * , CEntityClass * , uint16 , CDefFastCaselessStringLess > m_entClassesByCPPClassname ;
CUtlMap < const char * , CEntityClass * , uint16 , CDefFastCaselessStringLess > m_entClassesByClassname ;
CUtlMap < const char * , CEntityComponentHelper * , uint16 , CDefFastCaselessStringLess > m_entityComponentHelpers ;
CUtlMap < CUtlSymbolLarge , CUtlVector < CEntityHandle > * , uint16 , CDefLess < CUtlSymbolLarge > > m_entityNames ;
CEventQueue m_EventQueue ;
CUtlVectorFixedGrowable < IEntityIONotify * , 2 > m_entityIONotifiers ;
int m_nSuppressDormancyChangeCount ;
NetworkSerializationMode_t m_eNetworkSerializationMode ;
int m_nExecuteQueuedCreationDepth ;
int m_nExecuteQueuedDeletionDepth ;
int m_nSuppressDestroyImmediateCount ;
int m_nSuppressAutoDeletionExecutionCount ;
int m_nEntityKeyValuesAllocatorRefCount ;
float m_flChangeCallbackSpewThreshold ;
bool m_Unk1 ;
bool m_Unk2 ;
bool m_Unk3 ;
bool m_bEnableAutoDeletionExecution ;
bool m_Unk4 ;
bool m_Unk5 ;
bool m_Unk6 ;
CUtlVector < CreationInfo_t > m_queuedCreations ;
CUtlVector < PostDataUpdateInfo_t > m_queuedPostDataUpdates ;
CUtlVector < DestructionInfo_t > m_queuedDeletions ;
CUtlVector < DestructionInfo_t > m_queuedDeferredDeletions ;
CUtlVector < DestructionInfo_t > m_queuedDeallocations ;
CUtlVector < DormancyChangeInfo_t > m_queuedDormancyChanges ;
CUtlDelegate < void ( int , const EntitySpawnInfo_t * ) > m_EntityPostSpawnCallback ;
INetworkFieldChangedEventQueue * m_pNetworkFieldChangedEventQueue ;
INetworkFieldScratchData * m_pNetworkFieldScratchData ;
IFieldChangeLimitSpew * m_pFieldChangeLimitSpew ;
CUtlHashtable < fieldtype_t , KeyUnserializerDelegate , MurmurHash2HashFunctor > m_DataDescKeyUnserializers ;
CUtlScratchMemoryPool m_ComponentUnserializerInfoAllocator ;
CKeyValues3Context m_EntityKeyValuesAllocator ;
CUtlSymbolTableLargeMT_CI m_Symbols ;
SpawnGroupHandle_t m_hActiveSpawnGroup ;
matrix3x4a_t m_vSpawnOriginOffset ;
IEntityDataInstantiator * m_Accessors [ MAX_ACCESSORS ] ;
CUtlHashtable < CUtlString , void * > m_EntityMaterialAttributes ;
2023-09-30 14:49:35 +02:00
} ;
class CGameEntitySystem : public CEntitySystem
{
struct SpawnGroupEntityFilterInfo_t
{
ISpawnGroupEntityFilter * m_pFilter ;
SpawnGroupEntityFilterType_t m_nType ;
} ;
public :
2023-12-23 20:03:58 +03:00
virtual ~ CGameEntitySystem ( ) = 0 ;
2023-09-30 14:49:35 +02:00
2023-10-08 18:55:15 +03:00
void AddListenerEntity ( IEntityListener * pListener ) ;
void RemoveListenerEntity ( IEntityListener * pListener ) ;
2023-09-30 14:49:35 +02:00
public :
2024-10-06 03:59:03 +03:00
int m_iMaxNetworkedEntIndex ;
int m_iNetworkedEntCount ;
int m_iNonNetworkedSavedEntCount ;
CUtlDict < SpawnGroupEntityFilterInfo_t > m_spawnGroupEntityFilters ;
CUtlVector < IEntityListener * > m_entityListeners ;
IEntity2SaveRestore * m_pEntity2SaveRestore ;
IEntity2Networkables * m_pEntity2Networkables ;
2023-12-23 20:03:58 +03:00
} ;
abstract_class IEntityFindFilter
{
public :
virtual bool ShouldFindEntity ( CEntityInstance * pEnt ) = 0 ;
} ;
class EntityInstanceIter_t
{
public :
EntityInstanceIter_t ( IEntityFindFilter * pFilter = nullptr , EntityIterType_t eIterType = ENTITY_ITER_OVER_ACTIVE ) ;
CEntityInstance * First ( ) ;
CEntityInstance * Next ( ) ;
inline void SetWorldGroupId ( WorldGroupId_t hWorldGroupId ) { m_hWorldGroupId = hWorldGroupId ; }
private :
CEntityIdentity * m_pCurrentEnt ;
IEntityFindFilter * m_pFilter ;
EntityIterType_t m_eIterType ;
WorldGroupId_t m_hWorldGroupId ;
} ;
class EntityInstanceByNameIter_t
{
public :
EntityInstanceByNameIter_t ( const char * szName , CEntityInstance * pSearchingEntity = nullptr , CEntityInstance * pActivator = nullptr , CEntityInstance * pCaller = nullptr , IEntityFindFilter * pFilter = nullptr , EntityIterType_t eIterType = ENTITY_ITER_OVER_ACTIVE ) ;
CEntityInstance * First ( ) ;
CEntityInstance * Next ( ) ;
inline void SetWorldGroupId ( WorldGroupId_t hWorldGroupId ) { m_hWorldGroupId = hWorldGroupId ; }
private :
CEntityIdentity * m_pCurrentEnt ;
IEntityFindFilter * m_pFilter ;
EntityIterType_t m_eIterType ;
WorldGroupId_t m_hWorldGroupId ;
const char * m_pszEntityName ;
CUtlVector < CEntityHandle > * m_pEntityHandles ;
int m_nCurEntHandle ;
int m_nNumEntHandles ;
CEntityInstance * m_pProceduralEnt ;
} ;
class EntityInstanceByClassIter_t
{
public :
EntityInstanceByClassIter_t ( const char * szClassName , IEntityFindFilter * pFilter = nullptr , EntityIterType_t eIterType = ENTITY_ITER_OVER_ACTIVE ) ;
2024-02-07 19:40:14 +03:00
EntityInstanceByClassIter_t ( CEntityInstance * pStart , const char * szClassName , IEntityFindFilter * pFilter = nullptr , EntityIterType_t eIterType = ENTITY_ITER_OVER_ACTIVE ) ;
2023-12-23 20:03:58 +03:00
CEntityInstance * First ( ) ;
CEntityInstance * Next ( ) ;
inline void SetWorldGroupId ( WorldGroupId_t hWorldGroupId ) { m_hWorldGroupId = hWorldGroupId ; }
2023-10-08 18:55:15 +03:00
private :
2023-12-23 20:03:58 +03:00
CEntityIdentity * m_pCurrentEnt ;
IEntityFindFilter * m_pFilter ;
EntityIterType_t m_eIterType ;
WorldGroupId_t m_hWorldGroupId ;
const char * m_pszClassName ;
CEntityClass * m_pEntityClass ;
2023-09-30 14:49:35 +02:00
} ;
# endif // ENTITYSYSTEM_H