Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

308 lines
8.8 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $Workfile: $
  6. // $Date: $
  7. // $NoKeywords: $
  8. //===========================================================================//
  9. #if !defined( CLIENTENTITYLIST_H )
  10. #define CLIENTENTITYLIST_H
  11. #ifdef _WIN32
  12. #pragma once
  13. #endif
  14. #include "tier0/dbg.h"
  15. #include "icliententitylist.h"
  16. #include "iclientunknown.h"
  17. #include "utllinkedlist.h"
  18. #include "utlvector.h"
  19. #include "icliententityinternal.h"
  20. #include "ispatialpartition.h"
  21. #include "cdll_util.h"
  22. #include "entitylist_base.h"
  23. #include "utlmap.h"
  24. class C_Beam;
  25. class C_BaseViewModel;
  26. class C_BaseEntity;
  27. #define INPVS_YES 0x0001 // The entity thinks it's in the PVS.
  28. #define INPVS_THISFRAME 0x0002 // Accumulated as different views are rendered during the frame and used to notify the entity if
  29. // it is not in the PVS anymore (at the end of the frame).
  30. #define INPVS_NEEDSNOTIFY 0x0004 // The entity thinks it's in the PVS.
  31. class IClientEntityListener;
  32. abstract_class C_BaseEntityClassList
  33. {
  34. public:
  35. C_BaseEntityClassList();
  36. ~C_BaseEntityClassList();
  37. virtual void LevelShutdown() = 0;
  38. C_BaseEntityClassList *m_pNextClassList;
  39. };
  40. template< class T >
  41. class C_EntityClassList : public C_BaseEntityClassList
  42. {
  43. public:
  44. virtual void LevelShutdown() { m_pClassList = NULL; }
  45. void Insert( T *pEntity )
  46. {
  47. pEntity->m_pNext = m_pClassList;
  48. m_pClassList = pEntity;
  49. }
  50. void Remove( T *pEntity )
  51. {
  52. T **pPrev = &m_pClassList;
  53. T *pCur = *pPrev;
  54. while ( pCur )
  55. {
  56. if ( pCur == pEntity )
  57. {
  58. *pPrev = pCur->m_pNext;
  59. return;
  60. }
  61. pPrev = &pCur->m_pNext;
  62. pCur = *pPrev;
  63. }
  64. }
  65. static T *m_pClassList;
  66. };
  67. // Maximum size of entity list
  68. #define INVALID_CLIENTENTITY_HANDLE CBaseHandle( INVALID_EHANDLE_INDEX )
  69. //
  70. // This is the IClientEntityList implemenation. It serves two functions:
  71. //
  72. // 1. It converts server entity indices into IClientNetworkables for the engine.
  73. //
  74. // 2. It provides a place to store IClientUnknowns and gives out ClientEntityHandle_t's
  75. // so they can be indexed and retreived. For example, this is how static props are referenced
  76. // by the spatial partition manager - it doesn't know what is being inserted, so it's
  77. // given ClientEntityHandle_t's, and the handlers for spatial partition callbacks can
  78. // use the client entity list to look them up and check for supported interfaces.
  79. //
  80. class CClientEntityList : public CBaseEntityList, public IClientEntityList
  81. {
  82. friend class C_BaseEntityIterator;
  83. friend class C_AllBaseEntityIterator;
  84. public:
  85. // Constructor, destructor
  86. CClientEntityList( void );
  87. virtual ~CClientEntityList( void );
  88. void Release(); // clears everything and releases entities
  89. // Implement IClientEntityList
  90. public:
  91. virtual IClientNetworkable* GetClientNetworkable( int entnum );
  92. virtual IClientEntity* GetClientEntity( int entnum );
  93. virtual int NumberOfEntities( bool bIncludeNonNetworkable = false );
  94. virtual IClientUnknown* GetClientUnknownFromHandle( ClientEntityHandle_t hEnt );
  95. virtual IClientNetworkable* GetClientNetworkableFromHandle( ClientEntityHandle_t hEnt );
  96. virtual IClientEntity* GetClientEntityFromHandle( ClientEntityHandle_t hEnt );
  97. virtual int GetHighestEntityIndex( void );
  98. virtual void SetMaxEntities( int maxents );
  99. virtual int GetMaxEntities( );
  100. // CBaseEntityList overrides.
  101. protected:
  102. virtual void OnAddEntity( IHandleEntity *pEnt, CBaseHandle handle );
  103. virtual void OnRemoveEntity( IHandleEntity *pEnt, CBaseHandle handle );
  104. // Internal to client DLL.
  105. public:
  106. // All methods of accessing specialized IClientUnknown's go through here.
  107. IClientUnknown* GetListedEntity( int entnum );
  108. // Simple wrappers for convenience..
  109. C_BaseEntity* GetBaseEntity( int entnum );
  110. ICollideable* GetCollideable( int entnum );
  111. IClientRenderable* GetClientRenderableFromHandle( ClientEntityHandle_t hEnt );
  112. C_BaseEntity* GetBaseEntityFromHandle( ClientEntityHandle_t hEnt );
  113. ICollideable* GetCollideableFromHandle( ClientEntityHandle_t hEnt );
  114. IClientThinkable* GetClientThinkableFromHandle( ClientEntityHandle_t hEnt );
  115. // Convenience methods to convert between entindex + ClientEntityHandle_t
  116. ClientEntityHandle_t EntIndexToHandle( int entnum );
  117. int HandleToEntIndex( ClientEntityHandle_t handle );
  118. // Is a handle valid?
  119. bool IsHandleValid( ClientEntityHandle_t handle ) const;
  120. // For backwards compatibility...
  121. C_BaseEntity* GetEnt( int entnum ) { return GetBaseEntity( entnum ); }
  122. void RecomputeHighestEntityUsed( void );
  123. // Use this to iterate over all the C_BaseEntities.
  124. C_BaseEntity* FirstBaseEntity() const;
  125. C_BaseEntity* NextBaseEntity( C_BaseEntity *pEnt ) const;
  126. class CPVSNotifyInfo
  127. {
  128. public:
  129. IPVSNotify *m_pNotify;
  130. IClientRenderable *m_pRenderable;
  131. unsigned char m_InPVSStatus; // Combination of the INPVS_ flags.
  132. unsigned short m_PVSNotifiersLink; // Into m_PVSNotifyInfos.
  133. };
  134. // Get the list of all PVS notifiers.
  135. CUtlLinkedList<CPVSNotifyInfo,unsigned short>& GetPVSNotifiers();
  136. CUtlVector<IClientEntityListener *> m_entityListeners;
  137. // add a class that gets notified of entity events
  138. void AddListenerEntity( IClientEntityListener *pListener );
  139. void RemoveListenerEntity( IClientEntityListener *pListener );
  140. void NotifyCreateEntity( C_BaseEntity *pEnt );
  141. void NotifyRemoveEntity( C_BaseEntity *pEnt );
  142. private:
  143. // Cached info for networked entities.
  144. struct EntityCacheInfo_t
  145. {
  146. // Cached off because GetClientNetworkable is called a *lot*
  147. IClientNetworkable *m_pNetworkable;
  148. unsigned short m_BaseEntitiesIndex; // Index into m_BaseEntities (or m_BaseEntities.InvalidIndex() if none).
  149. };
  150. // Current count
  151. int m_iNumServerEnts;
  152. // Max allowed
  153. int m_iMaxServerEnts;
  154. int m_iNumClientNonNetworkable;
  155. // Current last used slot
  156. int m_iMaxUsedServerIndex;
  157. // This holds fast lookups for special edicts.
  158. EntityCacheInfo_t m_EntityCacheInfo[NUM_ENT_ENTRIES];
  159. // For fast iteration.
  160. CUtlLinkedList<C_BaseEntity*, unsigned short> m_BaseEntities;
  161. private:
  162. void AddPVSNotifier( IClientUnknown *pUnknown );
  163. void RemovePVSNotifier( IClientUnknown *pUnknown );
  164. // These entities want to know when they enter and leave the PVS (server entities
  165. // already can get the equivalent notification with NotifyShouldTransmit, but client
  166. // entities have to get it this way).
  167. CUtlLinkedList<CPVSNotifyInfo,unsigned short> m_PVSNotifyInfos;
  168. CUtlMap<IClientUnknown*,unsigned short,unsigned short> m_PVSNotifierMap; // Maps IClientUnknowns to indices into m_PVSNotifyInfos.
  169. };
  170. // Use this to iterate over *all* (even dormant) the C_BaseEntities in the client entity list.
  171. class C_AllBaseEntityIterator
  172. {
  173. public:
  174. C_AllBaseEntityIterator();
  175. void Restart();
  176. C_BaseEntity* Next(); // keep calling this until it returns null.
  177. private:
  178. unsigned short m_CurBaseEntity;
  179. };
  180. class C_BaseEntityIterator
  181. {
  182. public:
  183. C_BaseEntityIterator();
  184. void Restart();
  185. C_BaseEntity* Next(); // keep calling this until it returns null.
  186. private:
  187. unsigned short m_CurBaseEntity;
  188. };
  189. //-----------------------------------------------------------------------------
  190. // Inline methods
  191. //-----------------------------------------------------------------------------
  192. inline bool CClientEntityList::IsHandleValid( ClientEntityHandle_t handle ) const
  193. {
  194. return handle.Get() != 0;
  195. }
  196. inline IClientUnknown* CClientEntityList::GetListedEntity( int entnum )
  197. {
  198. return (IClientUnknown*)LookupEntityByNetworkIndex( entnum );
  199. }
  200. inline IClientUnknown* CClientEntityList::GetClientUnknownFromHandle( ClientEntityHandle_t hEnt )
  201. {
  202. return (IClientUnknown*)LookupEntity( hEnt );
  203. }
  204. inline CUtlLinkedList<CClientEntityList::CPVSNotifyInfo,unsigned short>& CClientEntityList::GetPVSNotifiers()
  205. {
  206. return m_PVSNotifyInfos;
  207. }
  208. //-----------------------------------------------------------------------------
  209. // Convenience methods to convert between entindex + ClientEntityHandle_t
  210. //-----------------------------------------------------------------------------
  211. inline ClientEntityHandle_t CClientEntityList::EntIndexToHandle( int entnum )
  212. {
  213. if ( entnum < -1 )
  214. return INVALID_EHANDLE_INDEX;
  215. IClientUnknown *pUnk = GetListedEntity( entnum );
  216. return pUnk ? pUnk->GetRefEHandle() : INVALID_EHANDLE_INDEX;
  217. }
  218. //-----------------------------------------------------------------------------
  219. // Returns the client entity list
  220. //-----------------------------------------------------------------------------
  221. extern CClientEntityList *cl_entitylist;
  222. inline CClientEntityList& ClientEntityList()
  223. {
  224. return *cl_entitylist;
  225. }
  226. // Implement this class and register with entlist to receive entity create/delete notification
  227. class IClientEntityListener
  228. {
  229. public:
  230. virtual void OnEntityCreated( C_BaseEntity *pEntity ) {};
  231. //virtual void OnEntitySpawned( C_BaseEntity *pEntity ) {};
  232. virtual void OnEntityDeleted( C_BaseEntity *pEntity ) {};
  233. };
  234. #endif // CLIENTENTITYLIST_H