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.
nekohook/modules/source2013/sdk/game/client/cliententitylist.h
2020-08-04 13:13:01 -04:00

287 lines
9.3 KiB
C++

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//===========================================================================//
#if !defined(CLIENTENTITYLIST_H)
#define CLIENTENTITYLIST_H
#ifdef _WIN32
#pragma once
#endif
#include "../../public/icliententitylist.h"
#include "../../public/iclientunknown.h"
#include "../../public/ispatialpartition.h"
#include "../../public/tier0/dbg.h"
#include "../../public/tier1/utllinkedlist.h"
#include "../../public/tier1/utlmap.h"
#include "../../public/tier1/utlvector.h"
#include "../shared/entitylist_base.h"
#include "cdll_util.h"
#include "icliententityinternal.h"
class C_Beam;
class C_BaseViewModel;
class C_BaseEntity;
#define INPVS_YES 0x0001 // The entity thinks it's in the PVS.
#define INPVS_THISFRAME \
0x0002 // Accumulated as different views are rendered during the frame and
// used to notify the entity if it is not in the PVS anymore (at the
// end of the frame).
#define INPVS_NEEDSNOTIFY 0x0004 // The entity thinks it's in the PVS.
class IClientEntityListener;
abstract_class C_BaseEntityClassList {
public:
C_BaseEntityClassList();
~C_BaseEntityClassList();
virtual void LevelShutdown() = 0;
C_BaseEntityClassList *m_pNextClassList;
};
template <class T>
class C_EntityClassList : public C_BaseEntityClassList {
public:
virtual void LevelShutdown() { 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;
};
// Maximum size of entity list
#define INVALID_CLIENTENTITY_HANDLE CBaseHandle(INVALID_EHANDLE_INDEX)
//
// This is the IClientEntityList implemenation. It serves two functions:
//
// 1. It converts server entity indices into IClientNetworkables for the engine.
//
// 2. It provides a place to store IClientUnknowns and gives out
// ClientEntityHandle_t's
// so they can be indexed and retreived. For example, this is how static
// props are referenced by the spatial partition manager - it doesn't know
// what is being inserted, so it's
// given ClientEntityHandle_t's, and the handlers for spatial partition
//callbacks can
// use the client entity list to look them up and check for supported
// interfaces.
//
class CClientEntityList : public CBaseEntityList, public IClientEntityList {
friend class C_BaseEntityIterator;
friend class C_AllBaseEntityIterator;
public:
// Constructor, destructor
CClientEntityList(void);
virtual ~CClientEntityList(void);
void Release(); // clears everything and releases entities
// Implement IClientEntityList
public:
virtual IClientNetworkable *GetClientNetworkable(int entnum);
virtual IClientEntity *GetClientEntity(int entnum);
virtual int NumberOfEntities(bool bIncludeNonNetworkable = false);
virtual IClientUnknown *GetClientUnknownFromHandle(
ClientEntityHandle_t hEnt);
virtual IClientNetworkable *GetClientNetworkableFromHandle(
ClientEntityHandle_t hEnt);
virtual IClientEntity *GetClientEntityFromHandle(ClientEntityHandle_t hEnt);
virtual int GetHighestEntityIndex(void);
virtual void SetMaxEntities(int maxents);
virtual int GetMaxEntities();
// CBaseEntityList overrides.
protected:
virtual void OnAddEntity(IHandleEntity *pEnt, CBaseHandle handle);
virtual void OnRemoveEntity(IHandleEntity *pEnt, CBaseHandle handle);
// Internal to client DLL.
public:
// All methods of accessing specialized IClientUnknown's go through here.
IClientUnknown *GetListedEntity(int entnum);
// Simple wrappers for convenience..
C_BaseEntity *GetBaseEntity(int entnum);
ICollideable *GetCollideable(int entnum);
IClientRenderable *GetClientRenderableFromHandle(ClientEntityHandle_t hEnt);
C_BaseEntity *GetBaseEntityFromHandle(ClientEntityHandle_t hEnt);
ICollideable *GetCollideableFromHandle(ClientEntityHandle_t hEnt);
IClientThinkable *GetClientThinkableFromHandle(ClientEntityHandle_t hEnt);
// Convenience methods to convert between entindex + ClientEntityHandle_t
ClientEntityHandle_t EntIndexToHandle(int entnum);
int HandleToEntIndex(ClientEntityHandle_t handle);
// Is a handle valid?
bool IsHandleValid(ClientEntityHandle_t handle) const;
// For backwards compatibility...
C_BaseEntity *GetEnt(int entnum) { return GetBaseEntity(entnum); }
void RecomputeHighestEntityUsed(void);
// Use this to iterate over all the C_BaseEntities.
C_BaseEntity *FirstBaseEntity() const;
C_BaseEntity *NextBaseEntity(C_BaseEntity *pEnt) const;
class CPVSNotifyInfo {
public:
IPVSNotify *m_pNotify;
IClientRenderable *m_pRenderable;
unsigned char m_InPVSStatus; // Combination of the INPVS_ flags.
unsigned short m_PVSNotifiersLink; // Into m_PVSNotifyInfos.
};
// Get the list of all PVS notifiers.
CUtlLinkedList<CPVSNotifyInfo, unsigned short> &GetPVSNotifiers();
CUtlVector<IClientEntityListener *> m_entityListeners;
// add a class that gets notified of entity events
void AddListenerEntity(IClientEntityListener *pListener);
void RemoveListenerEntity(IClientEntityListener *pListener);
void NotifyCreateEntity(C_BaseEntity *pEnt);
void NotifyRemoveEntity(C_BaseEntity *pEnt);
private:
// Cached info for networked entities.
struct EntityCacheInfo_t {
// Cached off because GetClientNetworkable is called a *lot*
IClientNetworkable *m_pNetworkable;
unsigned short
m_BaseEntitiesIndex; // Index into m_BaseEntities (or
// m_BaseEntities.InvalidIndex() if none).
};
// Current count
int m_iNumServerEnts;
// Max allowed
int m_iMaxServerEnts;
int m_iNumClientNonNetworkable;
// Current last used slot
int m_iMaxUsedServerIndex;
// This holds fast lookups for special edicts.
EntityCacheInfo_t m_EntityCacheInfo[NUM_ENT_ENTRIES];
// For fast iteration.
CUtlLinkedList<C_BaseEntity *, unsigned short> m_BaseEntities;
private:
void AddPVSNotifier(IClientUnknown *pUnknown);
void RemovePVSNotifier(IClientUnknown *pUnknown);
// These entities want to know when they enter and leave the PVS (server
// entities already can get the equivalent notification with
// NotifyShouldTransmit, but client entities have to get it this way).
CUtlLinkedList<CPVSNotifyInfo, unsigned short> m_PVSNotifyInfos;
CUtlMap<IClientUnknown *, unsigned short, unsigned short>
m_PVSNotifierMap; // Maps IClientUnknowns to indices into
// m_PVSNotifyInfos.
};
// Use this to iterate over *all* (even dormant) the C_BaseEntities in the
// client entity list.
class C_AllBaseEntityIterator {
public:
C_AllBaseEntityIterator();
void Restart();
C_BaseEntity *Next(); // keep calling this until it returns null.
private:
unsigned short m_CurBaseEntity;
};
class C_BaseEntityIterator {
public:
C_BaseEntityIterator();
void Restart();
C_BaseEntity *Next(); // keep calling this until it returns null.
private:
unsigned short m_CurBaseEntity;
};
//-----------------------------------------------------------------------------
// Inline methods
//-----------------------------------------------------------------------------
inline bool CClientEntityList::IsHandleValid(
ClientEntityHandle_t handle) const {
return handle.Get() != 0;
}
inline IClientUnknown *CClientEntityList::GetListedEntity(int entnum) {
return (IClientUnknown *)LookupEntityByNetworkIndex(entnum);
}
inline IClientUnknown *CClientEntityList::GetClientUnknownFromHandle(
ClientEntityHandle_t hEnt) {
return (IClientUnknown *)LookupEntity(hEnt);
}
inline CUtlLinkedList<CClientEntityList::CPVSNotifyInfo, unsigned short>
&CClientEntityList::GetPVSNotifiers() {
return m_PVSNotifyInfos;
}
//-----------------------------------------------------------------------------
// Convenience methods to convert between entindex + ClientEntityHandle_t
//-----------------------------------------------------------------------------
inline ClientEntityHandle_t CClientEntityList::EntIndexToHandle(int entnum) {
if (entnum < -1) return INVALID_EHANDLE_INDEX;
IClientUnknown *pUnk = GetListedEntity(entnum);
return pUnk ? pUnk->GetRefEHandle() : INVALID_EHANDLE_INDEX;
}
//-----------------------------------------------------------------------------
// Returns the client entity list
//-----------------------------------------------------------------------------
extern CClientEntityList *cl_entitylist;
inline CClientEntityList &ClientEntityList() { return *cl_entitylist; }
// Implement this class and register with entlist to receive entity
// create/delete notification
class IClientEntityListener {
public:
virtual void OnEntityCreated(C_BaseEntity *pEntity){};
// virtual void OnEntitySpawned( C_BaseEntity *pEntity ) {};
virtual void OnEntityDeleted(C_BaseEntity *pEntity){};
};
#endif // CLIENTENTITYLIST_H