Counter Strike : Global Offensive Source Code
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.

217 lines
5.6 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #ifndef BASEHANDLE_H
  7. #define BASEHANDLE_H
  8. #ifdef _WIN32
  9. #pragma once
  10. #endif
  11. #include "const.h"
  12. #include "tier0/platform.h"
  13. #include "tier0/dbg.h"
  14. class IHandleEntity;
  15. // -------------------------------------------------------------------------------------------------- //
  16. // CBaseHandle.
  17. // -------------------------------------------------------------------------------------------------- //
  18. enum INVALID_EHANDLE_tag
  19. {
  20. INVALID_EHANDLE
  21. };
  22. class CBaseHandle
  23. {
  24. friend class CBaseEntityList;
  25. public:
  26. CBaseHandle();
  27. CBaseHandle( INVALID_EHANDLE_tag );
  28. CBaseHandle( const CBaseHandle &other );
  29. explicit CBaseHandle( IHandleEntity* pHandleObj );
  30. CBaseHandle( int iEntry, int iSerialNumber );
  31. // NOTE: The following constructor is not type-safe, and can allow creating an
  32. // arbitrary CBaseHandle that doesn't necessarily point to an actual object.
  33. //
  34. // It is your responsibility to ensure that the target of the handle actually points
  35. // to the object you think it does. Generally, the argument to this function should
  36. // have been obtained from CBaseHandle::ToInt() on a valid handle.
  37. static CBaseHandle UnsafeFromIndex( int index );
  38. void Init( int iEntry, int iSerialNumber );
  39. void Term();
  40. // Even if this returns true, Get() still can return return a non-null value.
  41. // This just tells if the handle has been initted with any values.
  42. bool IsValid() const;
  43. int GetEntryIndex() const;
  44. int GetSerialNumber() const;
  45. int ToInt() const;
  46. bool operator !=( const CBaseHandle &other ) const;
  47. bool operator ==( const CBaseHandle &other ) const;
  48. bool operator ==( const IHandleEntity* pEnt ) const;
  49. bool operator !=( const IHandleEntity* pEnt ) const;
  50. bool operator <( const CBaseHandle &other ) const;
  51. bool operator <( const IHandleEntity* pEnt ) const;
  52. // Assign a value to the handle.
  53. const CBaseHandle& operator=( const IHandleEntity *pEntity );
  54. const CBaseHandle& Set( const IHandleEntity *pEntity );
  55. // Use this to dereference the handle.
  56. // Note: this is implemented in game code (ehandle.h)
  57. IHandleEntity* Get() const;
  58. protected:
  59. // The low NUM_SERIAL_BITS hold the index. If this value is less than MAX_EDICTS, then the entity is networkable.
  60. // The high NUM_SERIAL_NUM_BITS bits are the serial number.
  61. uint32 m_Index;
  62. };
  63. #include "ihandleentity.h"
  64. inline CBaseHandle::CBaseHandle()
  65. {
  66. m_Index = INVALID_EHANDLE_INDEX;
  67. }
  68. inline CBaseHandle::CBaseHandle( INVALID_EHANDLE_tag )
  69. {
  70. m_Index = INVALID_EHANDLE_INDEX;
  71. }
  72. inline CBaseHandle::CBaseHandle( const CBaseHandle &other )
  73. {
  74. m_Index = other.m_Index;
  75. }
  76. inline CBaseHandle::CBaseHandle( IHandleEntity* pEntity )
  77. {
  78. Set( pEntity );
  79. }
  80. inline CBaseHandle::CBaseHandle( int iEntry, int iSerialNumber )
  81. {
  82. Init( iEntry, iSerialNumber );
  83. }
  84. inline CBaseHandle CBaseHandle::UnsafeFromIndex( int index )
  85. {
  86. CBaseHandle ret;
  87. ret.m_Index = index;
  88. return ret;
  89. }
  90. inline void CBaseHandle::Init( int iEntry, int iSerialNumber )
  91. {
  92. Assert( iEntry >= 0 && (iEntry & ENT_ENTRY_MASK) == iEntry);
  93. Assert( iSerialNumber >= 0 && iSerialNumber < (1 << NUM_SERIAL_NUM_BITS) );
  94. m_Index = iEntry | (iSerialNumber << NUM_SERIAL_NUM_SHIFT_BITS);
  95. }
  96. inline void CBaseHandle::Term()
  97. {
  98. m_Index = INVALID_EHANDLE_INDEX;
  99. }
  100. inline bool CBaseHandle::IsValid() const
  101. {
  102. return m_Index != INVALID_EHANDLE_INDEX;
  103. }
  104. inline int CBaseHandle::GetEntryIndex() const
  105. {
  106. // There is a hack here: due to a bug in the original implementation of the
  107. // entity handle system, an attempt to look up an invalid entity index in
  108. // certain cirumstances might fall through to the the mask operation below.
  109. // This would mask an invalid index to be in fact a lookup of entity number
  110. // NUM_ENT_ENTRIES, so invalid ent indexes end up actually looking up the
  111. // last slot in the entities array. Since this slot is always empty, the
  112. // lookup returns NULL and the expected behavior occurs through this unexpected
  113. // route.
  114. // A lot of code actually depends on this behavior, and the bug was only exposed
  115. // after a change to NUM_SERIAL_NUM_BITS increased the number of allowable
  116. // static props in the world. So the if-stanza below detects this case and
  117. // retains the prior (bug-submarining) behavior.
  118. if ( !IsValid() )
  119. return NUM_ENT_ENTRIES-1;
  120. return m_Index & ENT_ENTRY_MASK;
  121. }
  122. inline int CBaseHandle::GetSerialNumber() const
  123. {
  124. return m_Index >> NUM_SERIAL_NUM_SHIFT_BITS;
  125. }
  126. inline int CBaseHandle::ToInt() const
  127. {
  128. return (int)m_Index;
  129. }
  130. inline bool CBaseHandle::operator !=( const CBaseHandle &other ) const
  131. {
  132. return m_Index != other.m_Index;
  133. }
  134. inline bool CBaseHandle::operator ==( const CBaseHandle &other ) const
  135. {
  136. return m_Index == other.m_Index;
  137. }
  138. inline bool CBaseHandle::operator ==( const IHandleEntity* pEnt ) const
  139. {
  140. return Get() == pEnt;
  141. }
  142. inline bool CBaseHandle::operator !=( const IHandleEntity* pEnt ) const
  143. {
  144. return Get() != pEnt;
  145. }
  146. inline bool CBaseHandle::operator <( const CBaseHandle &other ) const
  147. {
  148. return m_Index < other.m_Index;
  149. }
  150. inline bool CBaseHandle::operator <( const IHandleEntity *pEntity ) const
  151. {
  152. uint32 otherIndex = (pEntity) ? pEntity->GetRefEHandle().m_Index : INVALID_EHANDLE_INDEX;
  153. return m_Index < otherIndex;
  154. }
  155. inline const CBaseHandle& CBaseHandle::operator=( const IHandleEntity *pEntity )
  156. {
  157. return Set( pEntity );
  158. }
  159. inline const CBaseHandle& CBaseHandle::Set( const IHandleEntity *pEntity )
  160. {
  161. if ( pEntity )
  162. {
  163. *this = pEntity->GetRefEHandle();
  164. }
  165. else
  166. {
  167. m_Index = INVALID_EHANDLE_INDEX;
  168. }
  169. return *this;
  170. }
  171. #endif // BASEHANDLE_H