This repository has been archived on 2024-06-13. You can view files and clone it, but cannot push or open issues or pull requests.
2020-08-04 13:13:01 -04:00

404 lines
14 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 *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