source-engine/game/server/entitylist.h
2022-03-01 23:00:42 +03:00

365 lines
12 KiB
C++

//========= 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 *FindEntityByNetname( CBaseEntity *pStartEntity, const char *szModelName );
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 &params ) = 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