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.

601 lines
18 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Controls the loading, parsing and creation of the entities from the BSP.
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "entitylist.h"
  8. #include "mapentities_shared.h"
  9. #include "soundent.h"
  10. #include "TemplateEntities.h"
  11. #include "point_template.h"
  12. #include "ai_initutils.h"
  13. #include "lights.h"
  14. #include "mapentities.h"
  15. #include "wcedit.h"
  16. #include "stringregistry.h"
  17. #include "datacache/imdlcache.h"
  18. #include "world.h"
  19. #include "toolframework/iserverenginetools.h"
  20. // memdbgon must be the last include file in a .cpp file!!!
  21. #include "tier0/memdbgon.h"
  22. struct HierarchicalSpawnMapData_t
  23. {
  24. const char *m_pMapData;
  25. int m_iMapDataLength;
  26. };
  27. static CStringRegistry *g_pClassnameSpawnPriority = NULL;
  28. extern edict_t *g_pForceAttachEdict;
  29. // creates an entity by string name, but does not spawn it
  30. CBaseEntity *CreateEntityByName( const char *className, int iForceEdictIndex )
  31. {
  32. if ( iForceEdictIndex != -1 )
  33. {
  34. g_pForceAttachEdict = engine->CreateEdict( iForceEdictIndex );
  35. if ( !g_pForceAttachEdict )
  36. Error( "CreateEntityByName( %s, %d ) - CreateEdict failed.", className, iForceEdictIndex );
  37. }
  38. IServerNetworkable *pNetwork = EntityFactoryDictionary()->Create( className );
  39. g_pForceAttachEdict = NULL;
  40. if ( !pNetwork )
  41. return NULL;
  42. CBaseEntity *pEntity = pNetwork->GetBaseEntity();
  43. Assert( pEntity );
  44. return pEntity;
  45. }
  46. CBaseNetworkable *CreateNetworkableByName( const char *className )
  47. {
  48. IServerNetworkable *pNetwork = EntityFactoryDictionary()->Create( className );
  49. if ( !pNetwork )
  50. return NULL;
  51. CBaseNetworkable *pNetworkable = pNetwork->GetBaseNetworkable();
  52. Assert( pNetworkable );
  53. return pNetworkable;
  54. }
  55. void FreeContainingEntity( edict_t *ed )
  56. {
  57. if ( ed )
  58. {
  59. CBaseEntity *ent = GetContainingEntity( ed );
  60. if ( ent )
  61. {
  62. ed->SetEdict( NULL, false );
  63. CBaseEntity::PhysicsRemoveTouchedList( ent );
  64. CBaseEntity::PhysicsRemoveGroundList( ent );
  65. UTIL_RemoveImmediate( ent );
  66. }
  67. }
  68. }
  69. // parent name may have a , in it to include an attachment point
  70. string_t ExtractParentName(string_t parentName)
  71. {
  72. if ( !strchr(STRING(parentName), ',') )
  73. return parentName;
  74. char szToken[256];
  75. nexttoken(szToken, STRING(parentName), ',');
  76. return AllocPooledString(szToken);
  77. }
  78. //-----------------------------------------------------------------------------
  79. // Purpose: Callback function for qsort, used to sort entities by their depth
  80. // in the movement hierarchy.
  81. // Input : pEnt1 -
  82. // pEnt2 -
  83. // Output : Returns -1, 0, or 1 per qsort spec.
  84. //-----------------------------------------------------------------------------
  85. static int __cdecl CompareSpawnOrder(HierarchicalSpawn_t *pEnt1, HierarchicalSpawn_t *pEnt2)
  86. {
  87. if (pEnt1->m_nDepth == pEnt2->m_nDepth)
  88. {
  89. if ( g_pClassnameSpawnPriority )
  90. {
  91. int o1 = pEnt1->m_hEntity ? g_pClassnameSpawnPriority->GetStringID( pEnt1->m_hEntity->GetClassname() ) : -1;
  92. int o2 = pEnt2->m_hEntity ? g_pClassnameSpawnPriority->GetStringID( pEnt2->m_hEntity->GetClassname() ) : -1;
  93. if ( o1 < o2 )
  94. return 1;
  95. if ( o2 < o1 )
  96. return -1;
  97. }
  98. return 0;
  99. }
  100. if (pEnt1->m_nDepth > pEnt2->m_nDepth)
  101. return 1;
  102. return -1;
  103. }
  104. //-----------------------------------------------------------------------------
  105. // Computes the hierarchical depth of the entities to spawn..
  106. //-----------------------------------------------------------------------------
  107. static int ComputeSpawnHierarchyDepth_r( CBaseEntity *pEntity )
  108. {
  109. if ( !pEntity )
  110. return 1;
  111. if (pEntity->m_iParent == NULL_STRING)
  112. return 1;
  113. CBaseEntity *pParent = gEntList.FindEntityByName( NULL, ExtractParentName(pEntity->m_iParent) );
  114. if (!pParent)
  115. return 1;
  116. if (pParent == pEntity)
  117. {
  118. Warning( "LEVEL DESIGN ERROR: Entity %s is parented to itself!\n", pEntity->GetDebugName() );
  119. return 1;
  120. }
  121. return 1 + ComputeSpawnHierarchyDepth_r( pParent );
  122. }
  123. static void ComputeSpawnHierarchyDepth( int nEntities, HierarchicalSpawn_t *pSpawnList )
  124. {
  125. // NOTE: This isn't particularly efficient, but so what? It's at the beginning of time
  126. // I did it this way because it simplified the parent setting in hierarchy (basically
  127. // eliminated questions about whether you should transform origin from global to local or not)
  128. int nEntity;
  129. for (nEntity = 0; nEntity < nEntities; nEntity++)
  130. {
  131. CBaseEntity *pEntity = pSpawnList[nEntity].m_hEntity;
  132. if (pEntity && !pEntity->IsDormant())
  133. {
  134. pSpawnList[nEntity].m_nDepth = ComputeSpawnHierarchyDepth_r( pEntity );
  135. }
  136. else
  137. {
  138. pSpawnList[nEntity].m_nDepth = 1;
  139. }
  140. }
  141. }
  142. static void SortSpawnListByHierarchy( int nEntities, HierarchicalSpawn_t *pSpawnList )
  143. {
  144. MEM_ALLOC_CREDIT();
  145. g_pClassnameSpawnPriority = new CStringRegistry;
  146. // this will cause the entities to be spawned in the indicated order
  147. // Highest string ID spawns first. String ID is spawn priority.
  148. // by default, anything not in this list has priority -1
  149. g_pClassnameSpawnPriority->AddString( "func_wall", 10 );
  150. g_pClassnameSpawnPriority->AddString( "scripted_sequence", 9 );
  151. g_pClassnameSpawnPriority->AddString( "phys_hinge", 8 );
  152. g_pClassnameSpawnPriority->AddString( "phys_ballsocket", 8 );
  153. g_pClassnameSpawnPriority->AddString( "phys_slideconstraint", 8 );
  154. g_pClassnameSpawnPriority->AddString( "phys_constraint", 8 );
  155. g_pClassnameSpawnPriority->AddString( "phys_pulleyconstraint", 8 );
  156. g_pClassnameSpawnPriority->AddString( "phys_lengthconstraint", 8 );
  157. g_pClassnameSpawnPriority->AddString( "phys_ragdollconstraint", 8 );
  158. g_pClassnameSpawnPriority->AddString( "info_mass_center", 8 ); // spawn these before physbox/prop_physics
  159. g_pClassnameSpawnPriority->AddString( "trigger_vphysics_motion", 8 ); // spawn these before physbox/prop_physics
  160. g_pClassnameSpawnPriority->AddString( "prop_physics", 7 );
  161. g_pClassnameSpawnPriority->AddString( "prop_ragdoll", 7 );
  162. // Sort the entities (other than the world) by hierarchy depth, in order to spawn them in
  163. // that order. This insures that each entity's parent spawns before it does so that
  164. // it can properly set up anything that relies on hierarchy.
  165. #ifdef _WIN32
  166. qsort(&pSpawnList[0], nEntities, sizeof(pSpawnList[0]), (int (__cdecl *)(const void *, const void *))CompareSpawnOrder);
  167. #elif POSIX
  168. qsort(&pSpawnList[0], nEntities, sizeof(pSpawnList[0]), (int (*)(const void *, const void *))CompareSpawnOrder);
  169. #endif
  170. delete g_pClassnameSpawnPriority;
  171. g_pClassnameSpawnPriority = NULL;
  172. }
  173. void SetupParentsForSpawnList( int nEntities, HierarchicalSpawn_t *pSpawnList )
  174. {
  175. int nEntity;
  176. for (nEntity = nEntities - 1; nEntity >= 0; nEntity--)
  177. {
  178. CBaseEntity *pEntity = pSpawnList[nEntity].m_hEntity;
  179. if ( pEntity )
  180. {
  181. if ( strchr(STRING(pEntity->m_iParent), ',') )
  182. {
  183. char szToken[256];
  184. const char *pAttachmentName = nexttoken(szToken, STRING(pEntity->m_iParent), ',');
  185. pEntity->m_iParent = AllocPooledString(szToken);
  186. CBaseEntity *pParent = gEntList.FindEntityByName( NULL, pEntity->m_iParent );
  187. // setparent in the spawn pass instead - so the model will have been set & loaded
  188. pSpawnList[nEntity].m_pDeferredParent = pParent;
  189. pSpawnList[nEntity].m_pDeferredParentAttachment = pAttachmentName;
  190. }
  191. else
  192. {
  193. CBaseEntity *pParent = gEntList.FindEntityByName( NULL, pEntity->m_iParent );
  194. if ((pParent != NULL) && (pParent->edict() != NULL))
  195. {
  196. pEntity->SetParent( pParent );
  197. }
  198. }
  199. }
  200. }
  201. }
  202. // this is a hook for edit mode
  203. void RememberInitialEntityPositions( int nEntities, HierarchicalSpawn_t *pSpawnList )
  204. {
  205. for (int nEntity = 0; nEntity < nEntities; nEntity++)
  206. {
  207. CBaseEntity *pEntity = pSpawnList[nEntity].m_hEntity;
  208. if ( pEntity )
  209. {
  210. NWCEdit::RememberEntityPosition( pEntity );
  211. }
  212. }
  213. }
  214. void SpawnAllEntities( int nEntities, HierarchicalSpawn_t *pSpawnList, bool bActivateEntities )
  215. {
  216. int nEntity;
  217. for (nEntity = 0; nEntity < nEntities; nEntity++)
  218. {
  219. VPROF( "MapEntity_ParseAllEntities_Spawn");
  220. CBaseEntity *pEntity = pSpawnList[nEntity].m_hEntity;
  221. if ( pSpawnList[nEntity].m_pDeferredParent )
  222. {
  223. // UNDONE: Promote this up to the root of this function?
  224. MDLCACHE_CRITICAL_SECTION();
  225. CBaseEntity *pParent = pSpawnList[nEntity].m_pDeferredParent;
  226. int iAttachment = -1;
  227. CBaseAnimating *pAnim = pParent->GetBaseAnimating();
  228. if ( pAnim )
  229. {
  230. iAttachment = pAnim->LookupAttachment(pSpawnList[nEntity].m_pDeferredParentAttachment);
  231. }
  232. pEntity->SetParent( pParent, iAttachment );
  233. }
  234. if ( pEntity )
  235. {
  236. if (DispatchSpawn(pEntity) < 0)
  237. {
  238. for ( int i = nEntity+1; i < nEntities; i++ )
  239. {
  240. // this is a child object that will be deleted now
  241. if ( pSpawnList[i].m_hEntity && pSpawnList[i].m_hEntity->IsMarkedForDeletion() )
  242. {
  243. pSpawnList[i].m_hEntity = NULL;
  244. }
  245. }
  246. // Spawn failed.
  247. gEntList.CleanupDeleteList();
  248. // Remove the entity from the spawn list
  249. pSpawnList[nEntity].m_hEntity = NULL;
  250. }
  251. }
  252. }
  253. if ( bActivateEntities )
  254. {
  255. VPROF( "MapEntity_ParseAllEntities_Activate");
  256. bool bAsyncAnims = mdlcache->SetAsyncLoad( MDLCACHE_ANIMBLOCK, false );
  257. for (nEntity = 0; nEntity < nEntities; nEntity++)
  258. {
  259. CBaseEntity *pEntity = pSpawnList[nEntity].m_hEntity;
  260. if ( pEntity )
  261. {
  262. MDLCACHE_CRITICAL_SECTION();
  263. pEntity->Activate();
  264. }
  265. }
  266. mdlcache->SetAsyncLoad( MDLCACHE_ANIMBLOCK, bAsyncAnims );
  267. }
  268. }
  269. //-----------------------------------------------------------------------------
  270. // Purpose: Only called on BSP load. Parses and spawns all the entities in the BSP.
  271. // Input : pMapData - Pointer to the entity data block to parse.
  272. //-----------------------------------------------------------------------------
  273. void MapEntity_ParseAllEntities(const char *pMapData, IMapEntityFilter *pFilter, bool bActivateEntities)
  274. {
  275. VPROF("MapEntity_ParseAllEntities");
  276. HierarchicalSpawnMapData_t *pSpawnMapData = new HierarchicalSpawnMapData_t[NUM_ENT_ENTRIES];
  277. HierarchicalSpawn_t *pSpawnList = new HierarchicalSpawn_t[NUM_ENT_ENTRIES];
  278. CUtlVector< CPointTemplate* > pPointTemplates;
  279. int nEntities = 0;
  280. char szTokenBuffer[MAPKEY_MAXLENGTH];
  281. // Allow the tools to spawn different things
  282. if ( serverenginetools )
  283. {
  284. pMapData = serverenginetools->GetEntityData( pMapData );
  285. }
  286. // Loop through all entities in the map data, creating each.
  287. for ( ; true; pMapData = MapEntity_SkipToNextEntity(pMapData, szTokenBuffer) )
  288. {
  289. //
  290. // Parse the opening brace.
  291. //
  292. char token[MAPKEY_MAXLENGTH];
  293. pMapData = MapEntity_ParseToken( pMapData, token );
  294. //
  295. // Check to see if we've finished or not.
  296. //
  297. if (!pMapData)
  298. break;
  299. if (token[0] != '{')
  300. {
  301. Error( "MapEntity_ParseAllEntities: found %s when expecting {", token);
  302. continue;
  303. }
  304. //
  305. // Parse the entity and add it to the spawn list.
  306. //
  307. CBaseEntity *pEntity;
  308. const char *pCurMapData = pMapData;
  309. pMapData = MapEntity_ParseEntity(pEntity, pMapData, pFilter);
  310. if (pEntity == NULL)
  311. continue;
  312. if (pEntity->IsTemplate())
  313. {
  314. // It's a template entity. Squirrel away its keyvalue text so that we can
  315. // recreate the entity later via a spawner. pMapData points at the '}'
  316. // so we must add one to include it in the string.
  317. Templates_Add(pEntity, pCurMapData, (pMapData - pCurMapData) + 2);
  318. // Remove the template entity so that it does not show up in FindEntityXXX searches.
  319. UTIL_Remove(pEntity);
  320. gEntList.CleanupDeleteList();
  321. continue;
  322. }
  323. // To
  324. if ( dynamic_cast<CWorld*>( pEntity ) )
  325. {
  326. VPROF( "MapEntity_ParseAllEntities_SpawnWorld");
  327. pEntity->m_iParent = NULL_STRING; // don't allow a parent on the first entity (worldspawn)
  328. DispatchSpawn(pEntity);
  329. continue;
  330. }
  331. CNodeEnt *pNode = dynamic_cast<CNodeEnt*>(pEntity);
  332. if ( pNode )
  333. {
  334. VPROF( "MapEntity_ParseAllEntities_SpawnTransients");
  335. // We overflow the max edicts on large maps that have lots of entities.
  336. // Nodes & Lights remove themselves immediately on Spawn(), so dispatch their
  337. // spawn now, to free up the slot inside this loop.
  338. // NOTE: This solution prevents nodes & lights from being used inside point_templates.
  339. //
  340. // NOTE: Nodes spawn other entities (ai_hint) if they need to have a persistent presence.
  341. // To ensure keys are copied over into the new entity, we pass the mapdata into the
  342. // node spawn function.
  343. if ( pNode->Spawn( pCurMapData ) < 0 )
  344. {
  345. gEntList.CleanupDeleteList();
  346. }
  347. continue;
  348. }
  349. if ( dynamic_cast<CLight*>(pEntity) )
  350. {
  351. VPROF( "MapEntity_ParseAllEntities_SpawnTransients");
  352. // We overflow the max edicts on large maps that have lots of entities.
  353. // Nodes & Lights remove themselves immediately on Spawn(), so dispatch their
  354. // spawn now, to free up the slot inside this loop.
  355. // NOTE: This solution prevents nodes & lights from being used inside point_templates.
  356. if (DispatchSpawn(pEntity) < 0)
  357. {
  358. gEntList.CleanupDeleteList();
  359. }
  360. continue;
  361. }
  362. // Build a list of all point_template's so we can spawn them before everything else
  363. CPointTemplate *pTemplate = dynamic_cast< CPointTemplate* >(pEntity);
  364. if ( pTemplate )
  365. {
  366. pPointTemplates.AddToTail( pTemplate );
  367. }
  368. else
  369. {
  370. // Queue up this entity for spawning
  371. pSpawnList[nEntities].m_hEntity = pEntity;
  372. pSpawnList[nEntities].m_nDepth = 0;
  373. pSpawnList[nEntities].m_pDeferredParentAttachment = NULL;
  374. pSpawnList[nEntities].m_pDeferredParent = NULL;
  375. pSpawnMapData[nEntities].m_pMapData = pCurMapData;
  376. pSpawnMapData[nEntities].m_iMapDataLength = (pMapData - pCurMapData) + 2;
  377. nEntities++;
  378. }
  379. }
  380. // Now loop through all our point_template entities and tell them to make templates of everything they're pointing to
  381. int iTemplates = pPointTemplates.Count();
  382. for ( int i = 0; i < iTemplates; i++ )
  383. {
  384. VPROF( "MapEntity_ParseAllEntities_SpawnTemplates");
  385. CPointTemplate *pPointTemplate = pPointTemplates[i];
  386. // First, tell the Point template to Spawn
  387. if ( DispatchSpawn(pPointTemplate) < 0 )
  388. {
  389. UTIL_Remove(pPointTemplate);
  390. gEntList.CleanupDeleteList();
  391. continue;
  392. }
  393. pPointTemplate->StartBuildingTemplates();
  394. // Now go through all it's templates and turn the entities into templates
  395. int iNumTemplates = pPointTemplate->GetNumTemplateEntities();
  396. for ( int iTemplateNum = 0; iTemplateNum < iNumTemplates; iTemplateNum++ )
  397. {
  398. // Find it in the spawn list
  399. CBaseEntity *pEntity = pPointTemplate->GetTemplateEntity( iTemplateNum );
  400. for ( int iEntNum = 0; iEntNum < nEntities; iEntNum++ )
  401. {
  402. if ( pSpawnList[iEntNum].m_hEntity == pEntity )
  403. {
  404. // Give the point_template the mapdata
  405. pPointTemplate->AddTemplate( pEntity, pSpawnMapData[iEntNum].m_pMapData, pSpawnMapData[iEntNum].m_iMapDataLength );
  406. if ( pPointTemplate->ShouldRemoveTemplateEntities() )
  407. {
  408. // Remove the template entity so that it does not show up in FindEntityXXX searches.
  409. UTIL_Remove(pEntity);
  410. gEntList.CleanupDeleteList();
  411. // Remove the entity from the spawn list
  412. pSpawnList[iEntNum].m_hEntity = NULL;
  413. }
  414. break;
  415. }
  416. }
  417. }
  418. pPointTemplate->FinishBuildingTemplates();
  419. }
  420. SpawnHierarchicalList( nEntities, pSpawnList, bActivateEntities );
  421. delete [] pSpawnMapData;
  422. delete [] pSpawnList;
  423. }
  424. void SpawnHierarchicalList( int nEntities, HierarchicalSpawn_t *pSpawnList, bool bActivateEntities )
  425. {
  426. // Compute the hierarchical depth of all entities hierarchically attached
  427. ComputeSpawnHierarchyDepth( nEntities, pSpawnList );
  428. // Sort the entities (other than the world) by hierarchy depth, in order to spawn them in
  429. // that order. This insures that each entity's parent spawns before it does so that
  430. // it can properly set up anything that relies on hierarchy.
  431. SortSpawnListByHierarchy( nEntities, pSpawnList );
  432. // save off entity positions if in edit mode
  433. if ( engine->IsInEditMode() )
  434. {
  435. RememberInitialEntityPositions( nEntities, pSpawnList );
  436. }
  437. // Set up entity movement hierarchy in reverse hierarchy depth order. This allows each entity
  438. // to use its parent's world spawn origin to calculate its local origin.
  439. SetupParentsForSpawnList( nEntities, pSpawnList );
  440. // Spawn all the entities in hierarchy depth order so that parents spawn before their children.
  441. SpawnAllEntities( nEntities, pSpawnList, bActivateEntities );
  442. }
  443. //-----------------------------------------------------------------------------
  444. // Purpose:
  445. // Input : *pEntData -
  446. //-----------------------------------------------------------------------------
  447. void MapEntity_PrecacheEntity( const char *pEntData, int &nStringSize )
  448. {
  449. CEntityMapData entData( (char*)pEntData, nStringSize );
  450. char className[MAPKEY_MAXLENGTH];
  451. if (!entData.ExtractValue("classname", className))
  452. {
  453. Error( "classname missing from entity!\n" );
  454. }
  455. // Construct via the LINK_ENTITY_TO_CLASS factory.
  456. CBaseEntity *pEntity = CreateEntityByName(className);
  457. //
  458. // Set up keyvalues, which can set the model name, which is why we don't just do UTIL_PrecacheOther here...
  459. //
  460. if ( pEntity != NULL )
  461. {
  462. pEntity->ParseMapData(&entData);
  463. pEntity->Precache();
  464. UTIL_RemoveImmediate( pEntity );
  465. }
  466. }
  467. //-----------------------------------------------------------------------------
  468. // Purpose: Takes a block of character data as the input
  469. // Input : pEntity - Receives the newly constructed entity, NULL on failure.
  470. // pEntData - Data block to parse to extract entity keys.
  471. // Output : Returns the current position in the entity data block.
  472. //-----------------------------------------------------------------------------
  473. const char *MapEntity_ParseEntity(CBaseEntity *&pEntity, const char *pEntData, IMapEntityFilter *pFilter)
  474. {
  475. CEntityMapData entData( (char*)pEntData );
  476. char className[MAPKEY_MAXLENGTH];
  477. if (!entData.ExtractValue("classname", className))
  478. {
  479. Error( "classname missing from entity!\n" );
  480. }
  481. pEntity = NULL;
  482. if ( !pFilter || pFilter->ShouldCreateEntity( className ) )
  483. {
  484. //
  485. // Construct via the LINK_ENTITY_TO_CLASS factory.
  486. //
  487. if ( pFilter )
  488. pEntity = pFilter->CreateNextEntity( className );
  489. else
  490. pEntity = CreateEntityByName(className);
  491. //
  492. // Set up keyvalues.
  493. //
  494. if (pEntity != NULL)
  495. {
  496. pEntity->ParseMapData(&entData);
  497. }
  498. else
  499. {
  500. Warning("Can't init %s\n", className);
  501. }
  502. }
  503. else
  504. {
  505. // Just skip past all the keys.
  506. char keyName[MAPKEY_MAXLENGTH];
  507. char value[MAPKEY_MAXLENGTH];
  508. if ( entData.GetFirstKey(keyName, value) )
  509. {
  510. do
  511. {
  512. }
  513. while ( entData.GetNextKey(keyName, value) );
  514. }
  515. }
  516. //
  517. // Return the current parser position in the data block
  518. //
  519. return entData.CurrentBufferPosition();
  520. }