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.

297 lines
7.3 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $Workfile: $
  6. // $Date: $
  7. //
  8. //-----------------------------------------------------------------------------
  9. // $Log: $
  10. //
  11. // $NoKeywords: $
  12. //=============================================================================//
  13. #include "quakedef.h"
  14. #include <stddef.h>
  15. #include "vengineserver_impl.h"
  16. #include "server.h"
  17. #include "pr_edict.h"
  18. #include "world.h"
  19. #include "ispatialpartition.h"
  20. #include "utllinkedlist.h"
  21. #include "framesnapshot.h"
  22. #include "tier0/cache_hints.h"
  23. // memdbgon must be the last include file in a .cpp file!!!
  24. #include "tier0/memdbgon.h"
  25. // Edicts won't get reallocated for this many seconds after being freed.
  26. #define EDICT_FREETIME 1.0
  27. static ConVar sv_useexplicitdelete( "sv_useexplicitdelete", "1", FCVAR_DEVELOPMENTONLY, "Explicitly delete dormant client entities caused by AllowImmediateReuse()." );
  28. static float g_EdictFreeTime[MAX_EDICTS];
  29. static int g_nLowestFreeEdict = 0;
  30. void ED_ClearTimes()
  31. {
  32. V_memset( g_EdictFreeTime, 0, sizeof(g_EdictFreeTime) );
  33. g_nLowestFreeEdict = 0;
  34. }
  35. /*
  36. =================
  37. ED_ClearEdict
  38. Sets everything to NULL, done when new entity is allocated for game.dll
  39. =================
  40. */
  41. void ED_ClearEdict (edict_t *e)
  42. {
  43. e->ClearFree();
  44. e->ClearStateChanged();
  45. serverGameEnts->FreeContainingEntity(e);
  46. InitializeEntityDLLFields(e);
  47. e->m_NetworkSerialNumber = -1; // must be filled by game.dll
  48. }
  49. /*
  50. =================
  51. ED_Alloc
  52. Either finds a free edict, or allocates a new one.
  53. Try to avoid reusing an entity that was recently freed, because it
  54. can cause the client to think the entity morphed into something else
  55. instead of being removed and recreated, which can cause interpolated
  56. angles and bad trails.
  57. =================
  58. */
  59. edict_t *ED_Alloc( int iForceEdictIndex )
  60. {
  61. if ( iForceEdictIndex >= 0 )
  62. {
  63. if ( iForceEdictIndex >= sv.num_edicts )
  64. {
  65. Warning( "ED_Alloc( %d ) - invalid edict index specified.", iForceEdictIndex );
  66. return NULL;
  67. }
  68. edict_t *e = &sv.edicts[iForceEdictIndex];
  69. if ( e->IsFree() )
  70. {
  71. ED_ClearEdict( e );
  72. return e;
  73. }
  74. else
  75. {
  76. return NULL;
  77. }
  78. }
  79. // Check the free list first.
  80. int nFirstIndex = sv.GetMaxClients() + 1;
  81. #if _DEBUG
  82. for ( int i = nFirstIndex; i < g_nLowestFreeEdict; i++ )
  83. {
  84. if ( sv.edicts[i].IsFree() )
  85. {
  86. Assert(0);
  87. DebuggerBreakIfDebugging();
  88. }
  89. }
  90. #endif
  91. nFirstIndex = imax( nFirstIndex, g_nLowestFreeEdict );
  92. edict_t *pEdict = sv.edicts + nFirstIndex;
  93. // This misses cache a lot because it has to touch the entire table (32KB in the worst case)
  94. // We could use a free list here!!! For now, try to prefetch it and keep an "lowest free" index to help
  95. #if defined(_GAMECONSOLE)
  96. int nPrefetchCount = sv.num_edicts - nFirstIndex;
  97. nPrefetchCount = imin( nPrefetchCount, 8 );
  98. int nLastPrefetch = sv.num_edicts - 8;
  99. for ( int i = 0; i < nPrefetchCount; i++ )
  100. {
  101. PREFETCH_128( ( (byte *)pEdict ) + i * 128, 0 );
  102. }
  103. #endif
  104. g_nLowestFreeEdict = sv.num_edicts;
  105. for ( int i = nFirstIndex; i < sv.num_edicts; i++ )
  106. {
  107. #if defined(_GAMECONSOLE)
  108. if ( !(i & 7) && i < nLastPrefetch )
  109. {
  110. PREFETCH_128( ( (byte *)pEdict ) + 128, 0 );
  111. }
  112. #endif
  113. if ( pEdict->IsFree() )
  114. {
  115. g_nLowestFreeEdict = imin( i, g_nLowestFreeEdict );
  116. if ( (g_EdictFreeTime[i] < 2 || sv.GetTime() - g_EdictFreeTime[i] >= EDICT_FREETIME) )
  117. {
  118. // If we have no freetime, we've had AllowImmediateReuse() called. We need
  119. // to explicitly delete this old entity.
  120. if ( g_EdictFreeTime[i] == 0 && sv_useexplicitdelete.GetBool() )
  121. {
  122. //Warning("ADDING SLOT to snapshot: %d\n", i );
  123. framesnapshotmanager->AddExplicitDelete( i );
  124. }
  125. ED_ClearEdict( pEdict );
  126. return pEdict;
  127. }
  128. }
  129. pEdict++;
  130. }
  131. // Allocate a new edict.
  132. if ( sv.num_edicts >= sv.max_edicts )
  133. {
  134. if ( sv.max_edicts != 0 )
  135. {
  136. // We don't have any available edicts that are newer than
  137. // EDICT_FREETIME. Rather than crash try to find an edict that
  138. // was deleted less than EDICT_FREETIME ago. This will protect us
  139. // against potential server hacks like those used to crash
  140. // dota2 servers.
  141. pEdict = sv.edicts + nFirstIndex;
  142. for ( int i = nFirstIndex; i < sv.num_edicts; i++ )
  143. {
  144. if ( pEdict->IsFree() )
  145. {
  146. ED_ClearEdict( pEdict );
  147. return pEdict;
  148. }
  149. pEdict++;
  150. }
  151. }
  152. AssertMsg( 0, "Can't allocate edict" );
  153. if ( sv.max_edicts == 0 )
  154. Sys_Error( "ED_Alloc: No edicts yet" );
  155. Sys_Error ("ED_Alloc: no free edicts");
  156. }
  157. // Do this before clearing since clear now needs to call back into the edict to deduce the index so can get the changeinfo data in the parallel structure
  158. sv.num_edicts++;
  159. ED_ClearEdict( pEdict );
  160. return pEdict;
  161. }
  162. void ED_AllowImmediateReuse()
  163. {
  164. edict_t *pEdict = sv.edicts + sv.GetMaxClients() + 1;
  165. for ( int i=sv.GetMaxClients()+1; i < sv.num_edicts; i++ )
  166. {
  167. if ( pEdict->IsFree() )
  168. {
  169. g_EdictFreeTime[i] = 0;
  170. }
  171. pEdict++;
  172. }
  173. }
  174. /*
  175. =================
  176. ED_Free
  177. Marks the edict as free
  178. FIXME: walk all entities and NULL out references to this entity
  179. =================
  180. */
  181. void ED_Free (edict_t *ed)
  182. {
  183. if ( !sv.edicts )
  184. {
  185. // During l4d2 ship cycle we crashed in this code, being called from CleanupDeleteList on the server for a single entity
  186. // We don't know what was causing the entity to persist after sv.edicts was shut down, so hopefully this guard will let
  187. // us catch it in the debugger if we ever see it again.
  188. Warning( "ED_Free(0x%p) called after sv.edicts == NULL\n", ed );
  189. if ( !IsX360() )
  190. {
  191. DebuggerBreak();
  192. }
  193. return;
  194. }
  195. if (ed->IsFree())
  196. {
  197. #ifdef _DEBUG
  198. // ConDMsg("duplicate free on '%s'\n", pr_strings + ed->classname );
  199. #endif
  200. return;
  201. }
  202. // don't free player edicts
  203. int edictIndex = ed - sv.edicts;
  204. if ( edictIndex >= 1 && edictIndex <= sv.GetMaxClients() )
  205. return;
  206. g_nLowestFreeEdict = imin( g_nLowestFreeEdict, edictIndex );
  207. // release the DLL entity that's attached to this edict, if any
  208. serverGameEnts->FreeContainingEntity( ed );
  209. ed->SetFree();
  210. g_EdictFreeTime[edictIndex] = sv.GetTime();
  211. // Increment the serial number so it knows to send explicit deletes the clients.
  212. ed->m_NetworkSerialNumber++;
  213. }
  214. //
  215. // serverGameEnts->FreeContainingEntity( pEdict ) frees up memory associated with a DLL entity.
  216. // InitializeEntityDLLFields clears out fields to NULL or UNKNOWN.
  217. // Release is for terminating a DLL entity. Initialize is for initializing one.
  218. //
  219. void InitializeEntityDLLFields( edict_t *pEdict )
  220. {
  221. // clear all the game variables
  222. size_t sz = offsetof( edict_t, m_pUnk ) + sizeof( void* );
  223. memset( ((byte*)pEdict) + sz, 0, sizeof(edict_t) - sz );
  224. int edictIndex = pEdict - sv.edicts;
  225. g_EdictFreeTime[edictIndex] = 0;
  226. }
  227. edict_t *EDICT_NUM(int n)
  228. {
  229. Assert( n >= 0 && n < sv.max_edicts );
  230. return &sv.edicts[n];
  231. }
  232. int NUM_FOR_EDICT(const edict_t *e)
  233. {
  234. int b = e - sv.edicts;
  235. Assert( b >= 0 && b < sv.num_edicts );
  236. return b;
  237. }
  238. // Special version which allows accessing unused sv.edictchangeinfo slots
  239. int NUM_FOR_EDICTINFO( const edict_t * e )
  240. {
  241. int b = e - sv.edicts;
  242. Assert( b >= 0 && b < sv.max_edicts );
  243. return b;
  244. }
  245. IChangeInfoAccessor *CBaseEdict::GetChangeAccessor()
  246. {
  247. int idx = NUM_FOR_EDICTINFO( (const edict_t * )this );
  248. return &sv.edictchangeinfo[ idx ];
  249. }
  250. const IChangeInfoAccessor *CBaseEdict::GetChangeAccessor() const
  251. {
  252. int idx = NUM_FOR_EDICTINFO( (const edict_t * )this );
  253. return &sv.edictchangeinfo[ idx ];
  254. }