diff options
Diffstat (limited to 'game/server/entitylist.h')
| -rw-r--r-- | game/server/entitylist.h | 363 |
1 files changed, 363 insertions, 0 deletions
diff --git a/game/server/entitylist.h b/game/server/entitylist.h new file mode 100644 index 0000000..540e2d5 --- /dev/null +++ b/game/server/entitylist.h @@ -0,0 +1,363 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +#ifndef ENTITYLIST_H +#define ENTITYLIST_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "baseentity.h" + +class IEntityListener; + +abstract_class CBaseEntityClassList +{ +public: + CBaseEntityClassList(); + ~CBaseEntityClassList(); + virtual void LevelShutdownPostEntity() = 0; + + CBaseEntityClassList *m_pNextClassList; +}; + +template< class T > +class CEntityClassList : public CBaseEntityClassList +{ +public: + virtual void LevelShutdownPostEntity() { m_pClassList = NULL; } + + void Insert( T *pEntity ) + { + pEntity->m_pNext = m_pClassList; + m_pClassList = pEntity; + } + + void Remove( T *pEntity ) + { + T **pPrev = &m_pClassList; + T *pCur = *pPrev; + while ( pCur ) + { + if ( pCur == pEntity ) + { + *pPrev = pCur->m_pNext; + return; + } + pPrev = &pCur->m_pNext; + pCur = *pPrev; + } + } + + static T *m_pClassList; +}; + +// Derive a class from this if you want to filter entity list searches +abstract_class IEntityFindFilter +{ +public: + virtual bool ShouldFindEntity( CBaseEntity *pEntity ) = 0; + virtual CBaseEntity *GetFilterResult( void ) = 0; +}; + +//----------------------------------------------------------------------------- +// Purpose: a global list of all the entities in the game. All iteration through +// entities is done through this object. +//----------------------------------------------------------------------------- +class CGlobalEntityList : public CBaseEntityList +{ +public: +private: + int m_iHighestEnt; // the topmost used array index + int m_iNumEnts; + int m_iNumEdicts; + + bool m_bClearingEntities; + CUtlVector<IEntityListener *> m_entityListeners; + +public: + IServerNetworkable* GetServerNetworkable( CBaseHandle hEnt ) const; + CBaseNetworkable* GetBaseNetworkable( CBaseHandle hEnt ) const; + CBaseEntity* GetBaseEntity( CBaseHandle hEnt ) const; + edict_t* GetEdict( CBaseHandle hEnt ) const; + + int NumberOfEntities( void ); + int NumberOfEdicts( void ); + + // mark an entity as deleted + void AddToDeleteList( IServerNetworkable *ent ); + // call this before and after each frame to delete all of the marked entities. + void CleanupDeleteList( void ); + int ResetDeleteList( void ); + + // frees all entities in the game + void Clear( void ); + + // Returns true while in the Clear() call. + bool IsClearingEntities() {return m_bClearingEntities;} + + // add a class that gets notified of entity events + void AddListenerEntity( IEntityListener *pListener ); + void RemoveListenerEntity( IEntityListener *pListener ); + + void ReportEntityFlagsChanged( CBaseEntity *pEntity, unsigned int flagsOld, unsigned int flagsNow ); + + // entity is about to be removed, notify the listeners + void NotifyCreateEntity( CBaseEntity *pEnt ); + void NotifySpawn( CBaseEntity *pEnt ); + void NotifyRemoveEntity( CBaseHandle hEnt ); + // iteration functions + + // returns the next entity after pCurrentEnt; if pCurrentEnt is NULL, return the first entity + CBaseEntity *NextEnt( CBaseEntity *pCurrentEnt ); + CBaseEntity *FirstEnt() { return NextEnt(NULL); } + + // returns the next entity of the specified class, using RTTI + template< class T > + T *NextEntByClass( T *start ) + { + for ( CBaseEntity *x = NextEnt( start ); x; x = NextEnt( x ) ) + { + start = dynamic_cast<T*>( x ); + if ( start ) + return start; + } + return NULL; + } + + // search functions + bool IsEntityPtr( void *pTest ); + CBaseEntity *FindEntityByClassname( CBaseEntity *pStartEntity, const char *szName ); + CBaseEntity *FindEntityByName( CBaseEntity *pStartEntity, const char *szName, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL, IEntityFindFilter *pFilter = NULL ); + CBaseEntity *FindEntityByName( CBaseEntity *pStartEntity, string_t iszName, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL, IEntityFindFilter *pFilter = NULL ) + { + return FindEntityByName( pStartEntity, STRING(iszName), pSearchingEntity, pActivator, pCaller, pFilter ); + } + CBaseEntity *FindEntityInSphere( CBaseEntity *pStartEntity, const Vector &vecCenter, float flRadius ); + CBaseEntity *FindEntityByTarget( CBaseEntity *pStartEntity, const char *szName ); + CBaseEntity *FindEntityByModel( CBaseEntity *pStartEntity, const char *szModelName ); + + CBaseEntity *FindEntityByNameNearest( const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL ); + CBaseEntity *FindEntityByNameWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL ); + CBaseEntity *FindEntityByClassnameNearest( const char *szName, const Vector &vecSrc, float flRadius ); + CBaseEntity *FindEntityByClassnameWithin( CBaseEntity *pStartEntity , const char *szName, const Vector &vecSrc, float flRadius ); + CBaseEntity *FindEntityByClassnameWithin( CBaseEntity *pStartEntity , const char *szName, const Vector &vecMins, const Vector &vecMaxs ); + + CBaseEntity *FindEntityGeneric( CBaseEntity *pStartEntity, const char *szName, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL ); + CBaseEntity *FindEntityGenericWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL ); + CBaseEntity *FindEntityGenericNearest( const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL ); + + CBaseEntity *FindEntityNearestFacing( const Vector &origin, const Vector &facing, float threshold); + CBaseEntity *FindEntityClassNearestFacing( const Vector &origin, const Vector &facing, float threshold, char *classname); + + CBaseEntity *FindEntityProcedural( const char *szName, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL ); + + CGlobalEntityList(); + +// CBaseEntityList overrides. +protected: + + virtual void OnAddEntity( IHandleEntity *pEnt, CBaseHandle handle ); + virtual void OnRemoveEntity( IHandleEntity *pEnt, CBaseHandle handle ); + +}; + +extern CGlobalEntityList gEntList; + + +//----------------------------------------------------------------------------- +// Inlines. +//----------------------------------------------------------------------------- +inline edict_t* CGlobalEntityList::GetEdict( CBaseHandle hEnt ) const +{ + IServerUnknown *pUnk = static_cast<IServerUnknown*>(LookupEntity( hEnt )); + if ( pUnk ) + return pUnk->GetNetworkable()->GetEdict(); + else + return NULL; +} + +inline CBaseNetworkable* CGlobalEntityList::GetBaseNetworkable( CBaseHandle hEnt ) const +{ + IServerUnknown *pUnk = static_cast<IServerUnknown*>(LookupEntity( hEnt )); + if ( pUnk ) + return pUnk->GetNetworkable()->GetBaseNetworkable(); + else + return NULL; +} + +inline IServerNetworkable* CGlobalEntityList::GetServerNetworkable( CBaseHandle hEnt ) const +{ + IServerUnknown *pUnk = static_cast<IServerUnknown*>(LookupEntity( hEnt )); + if ( pUnk ) + return pUnk->GetNetworkable(); + else + return NULL; +} + +inline CBaseEntity* CGlobalEntityList::GetBaseEntity( CBaseHandle hEnt ) const +{ + IServerUnknown *pUnk = static_cast<IServerUnknown*>(LookupEntity( hEnt )); + if ( pUnk ) + return pUnk->GetBaseEntity(); + else + return NULL; +} + + +//----------------------------------------------------------------------------- +// Common finds +#if 0 + +template <class ENT_TYPE> +inline bool FindEntityByName( const char *pszName, ENT_TYPE **ppResult) +{ + CBaseEntity *pBaseEntity = gEntList.FindEntityByName( NULL, pszName ); + + if ( pBaseEntity ) + *ppResult = dynamic_cast<ENT_TYPE *>( pBaseEntity ); + else + *ppResult = NULL; + + return ( *ppResult != NULL ); +} + +template <> +inline bool FindEntityByName<CBaseEntity>( const char *pszName, CBaseEntity **ppResult) +{ + *ppResult = gEntList.FindEntityByName( NULL, pszName ); + return ( *ppResult != NULL ); +} + +template <> +inline bool FindEntityByName<CAI_BaseNPC>( const char *pszName, CAI_BaseNPC **ppResult) +{ + CBaseEntity *pBaseEntity = gEntList.FindEntityByName( NULL, pszName ); + + if ( pBaseEntity ) + *ppResult = pBaseEntity->MyNPCPointer(); + else + *ppResult = NULL; + + return ( *ppResult != NULL ); +} +#endif +//----------------------------------------------------------------------------- +// Purpose: Simple object for storing a list of objects +//----------------------------------------------------------------------------- +struct entitem_t +{ + EHANDLE hEnt; + struct entitem_t *pNext; + + // uses pool memory + static void* operator new( size_t stAllocateBlock ); + static void *operator new( size_t stAllocateBlock, int nBlockUse, const char *pFileName, int nLine ); + static void operator delete( void *pMem ); + static void operator delete( void *pMem, int nBlockUse, const char *pFileName, int nLine ) { operator delete( pMem ); } +}; + +class CEntityList +{ +public: + CEntityList(); + ~CEntityList(); + + int m_iNumItems; + entitem_t *m_pItemList; // null terminated singly-linked list + + void AddEntity( CBaseEntity * ); + void DeleteEntity( CBaseEntity * ); +}; + +enum notify_system_event_t +{ + NOTIFY_EVENT_TELEPORT = 0, + NOTIFY_EVENT_DESTROY, +}; + +struct notify_teleport_params_t +{ + Vector prevOrigin; + QAngle prevAngles; + bool physicsRotate; +}; + +struct notify_destroy_params_t +{ +}; + +struct notify_system_event_params_t +{ + union + { + const notify_teleport_params_t *pTeleport; + const notify_destroy_params_t *pDestroy; + }; + notify_system_event_params_t( const notify_teleport_params_t *pInTeleport ) { pTeleport = pInTeleport; } + notify_system_event_params_t( const notify_destroy_params_t *pInDestroy ) { pDestroy = pInDestroy; } +}; + + +abstract_class INotify +{ +public: + // Add notification for an entity + virtual void AddEntity( CBaseEntity *pNotify, CBaseEntity *pWatched ) = 0; + + // Remove notification for an entity + virtual void RemoveEntity( CBaseEntity *pNotify, CBaseEntity *pWatched ) = 0; + + // Call the named input in each entity who is watching pEvent's status + virtual void ReportNamedEvent( CBaseEntity *pEntity, const char *pEventName ) = 0; + + // System events don't make sense as inputs, so are handled through a generic notify function + virtual void ReportSystemEvent( CBaseEntity *pEntity, notify_system_event_t eventType, const notify_system_event_params_t ¶ms ) = 0; + + inline void ReportDestroyEvent( CBaseEntity *pEntity ) + { + notify_destroy_params_t destroy; + ReportSystemEvent( pEntity, NOTIFY_EVENT_DESTROY, notify_system_event_params_t(&destroy) ); + } + + inline void ReportTeleportEvent( CBaseEntity *pEntity, const Vector &prevOrigin, const QAngle &prevAngles, bool physicsRotate ) + { + notify_teleport_params_t teleport; + teleport.prevOrigin = prevOrigin; + teleport.prevAngles = prevAngles; + teleport.physicsRotate = physicsRotate; + ReportSystemEvent( pEntity, NOTIFY_EVENT_TELEPORT, notify_system_event_params_t(&teleport) ); + } + + // Remove this entity from the notify list + virtual void ClearEntity( CBaseEntity *pNotify ) = 0; +}; + +// Implement this class and register with gEntList to receive entity create/delete notification +class IEntityListener +{ +public: + virtual void OnEntityCreated( CBaseEntity *pEntity ) {}; + virtual void OnEntitySpawned( CBaseEntity *pEntity ) {}; + virtual void OnEntityDeleted( CBaseEntity *pEntity ) {}; +}; + +// singleton +extern INotify *g_pNotify; + +void EntityTouch_Add( CBaseEntity *pEntity ); +int AimTarget_ListCount(); +int AimTarget_ListCopy( CBaseEntity *pList[], int listMax ); +void AimTarget_ForceRepopulateList(); + +void SimThink_EntityChanged( CBaseEntity *pEntity ); +int SimThink_ListCount(); +int SimThink_ListCopy( CBaseEntity *pList[], int listMax ); + +#endif // ENTITYLIST_H |