diff --git a/source/simulation2/Simulation2.cpp b/source/simulation2/Simulation2.cpp index 236303bf23..2e17b393d3 100644 --- a/source/simulation2/Simulation2.cpp +++ b/source/simulation2/Simulation2.cpp @@ -97,19 +97,22 @@ public: CParamNode noParam; CComponentManager::ComponentTypeId cid; - // Add native system components: - componentManager.AddComponent(SYSTEM_ENTITY, CID_TemplateManager, noParam); + componentManager.InitSystemEntity(); + CEntityHandle systemEntity = componentManager.GetSystemEntity(); - componentManager.AddComponent(SYSTEM_ENTITY, CID_CommandQueue, noParam); - componentManager.AddComponent(SYSTEM_ENTITY, CID_ObstructionManager, noParam); - componentManager.AddComponent(SYSTEM_ENTITY, CID_ParticleManager, noParam); - componentManager.AddComponent(SYSTEM_ENTITY, CID_Pathfinder, noParam); - componentManager.AddComponent(SYSTEM_ENTITY, CID_ProjectileManager, noParam); - componentManager.AddComponent(SYSTEM_ENTITY, CID_RangeManager, noParam); - componentManager.AddComponent(SYSTEM_ENTITY, CID_SoundManager, noParam); - componentManager.AddComponent(SYSTEM_ENTITY, CID_Terrain, noParam); - componentManager.AddComponent(SYSTEM_ENTITY, CID_TerritoryManager, noParam); - componentManager.AddComponent(SYSTEM_ENTITY, CID_WaterManager, noParam); + // Add native system components: + componentManager.AddComponent(systemEntity, CID_TemplateManager, noParam); + + componentManager.AddComponent(systemEntity, CID_CommandQueue, noParam); + componentManager.AddComponent(systemEntity, CID_ObstructionManager, noParam); + componentManager.AddComponent(systemEntity, CID_ParticleManager, noParam); + componentManager.AddComponent(systemEntity, CID_Pathfinder, noParam); + componentManager.AddComponent(systemEntity, CID_ProjectileManager, noParam); + componentManager.AddComponent(systemEntity, CID_RangeManager, noParam); + componentManager.AddComponent(systemEntity, CID_SoundManager, noParam); + componentManager.AddComponent(systemEntity, CID_Terrain, noParam); + componentManager.AddComponent(systemEntity, CID_TerritoryManager, noParam); + componentManager.AddComponent(systemEntity, CID_WaterManager, noParam); // Add scripted system components: if (!skipScriptedComponents) @@ -120,7 +123,7 @@ public: cid = componentManager.LookupCID(name); \ if (cid == CID__Invalid) \ LOGERROR(L"Can't find component type " L##name); \ - componentManager.AddComponent(SYSTEM_ENTITY, cid, noParam) + componentManager.AddComponent(systemEntity, cid, noParam) LOAD_SCRIPTED_COMPONENT("AIInterface"); LOAD_SCRIPTED_COMPONENT("Barter"); @@ -134,7 +137,7 @@ public: if (!skipAI) { - componentManager.AddComponent(SYSTEM_ENTITY, CID_AIManager, noParam); + componentManager.AddComponent(systemEntity, CID_AIManager, noParam); } } diff --git a/source/simulation2/components/CCmpAIManager.cpp b/source/simulation2/components/CCmpAIManager.cpp index 84979389ea..2724ec3d0d 100644 --- a/source/simulation2/components/CCmpAIManager.cpp +++ b/source/simulation2/components/CCmpAIManager.cpp @@ -967,7 +967,7 @@ public: // AI players can cheat and see through FoW/SoD, since that greatly simplifies // their implementation. // (TODO: maybe cleverer AIs should be able to optionally retain FoW/SoD) - CmpPtr cmpRangeManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpRangeManager(GetSystemEntity()); if (cmpRangeManager) cmpRangeManager->SetLosRevealAll(player, true); } @@ -976,7 +976,7 @@ public: { ScriptInterface& scriptInterface = GetSimContext().GetScriptInterface(); // load the technology templates - CmpPtr cmpTechTemplateManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpTechTemplateManager(GetSystemEntity()); ENSURE(cmpTechTemplateManager); // Get the game state from AIInterface @@ -990,7 +990,7 @@ public: { ScriptInterface& scriptInterface = GetSimContext().GetScriptInterface(); - CmpPtr cmpAIInterface(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpAIInterface(GetSystemEntity()); ENSURE(cmpAIInterface); // Get the game state from AIInterface @@ -999,7 +999,7 @@ public: // Get the passability data Grid dummyGrid; const Grid* passabilityMap = &dummyGrid; - CmpPtr cmpPathfinder(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpPathfinder(GetSystemEntity()); if (cmpPathfinder) passabilityMap = &cmpPathfinder->GetPassabilityGrid(); @@ -1007,7 +1007,7 @@ public: // Since getting the territory grid can trigger a recalculation, we check NeedUpdate first Grid dummyGrid2; const Grid* territoryMap = &dummyGrid2; - CmpPtr cmpTerritoryManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpTerritoryManager(GetSystemEntity()); if (cmpTerritoryManager && cmpTerritoryManager->NeedUpdate(&m_TerritoriesDirtyID)) { territoryMap = &cmpTerritoryManager->GetTerritoryGrid(); @@ -1029,7 +1029,7 @@ public: if (m_Worker.getPlayerSize() == 0) return; - CmpPtr cmpAIInterface(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpAIInterface(GetSystemEntity()); ENSURE(cmpAIInterface); // Get the game state from AIInterface @@ -1038,7 +1038,7 @@ public: // Get the passability data Grid dummyGrid; const Grid* passabilityMap = &dummyGrid; - CmpPtr cmpPathfinder(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpPathfinder(GetSystemEntity()); if (cmpPathfinder) passabilityMap = &cmpPathfinder->GetPassabilityGrid(); @@ -1047,7 +1047,7 @@ public: bool territoryMapDirty = false; Grid dummyGrid2; const Grid* territoryMap = &dummyGrid2; - CmpPtr cmpTerritoryManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpTerritoryManager(GetSystemEntity()); if (cmpTerritoryManager && cmpTerritoryManager->NeedUpdate(&m_TerritoriesDirtyID)) { territoryMap = &cmpTerritoryManager->GetTerritoryGrid(); @@ -1066,7 +1066,7 @@ public: std::vector commands; m_Worker.GetCommands(commands); - CmpPtr cmpCommandQueue(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpCommandQueue(GetSystemEntity()); if (!cmpCommandQueue) return; @@ -1088,7 +1088,7 @@ private: void StartLoadEntityTemplates() { - CmpPtr cmpTemplateManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpTemplateManager(GetSystemEntity()); ENSURE(cmpTemplateManager); m_TemplateNames = cmpTemplateManager->FindAllTemplates(false); @@ -1102,7 +1102,7 @@ private: if (m_TemplateLoadedIdx >= m_TemplateNames.size()) return false; - CmpPtr cmpTemplateManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpTemplateManager(GetSystemEntity()); ENSURE(cmpTemplateManager); const CParamNode* node = cmpTemplateManager->GetTemplateWithoutValidation(m_TemplateNames[m_TemplateLoadedIdx]); @@ -1127,7 +1127,7 @@ private: void LoadPathfinderClasses(CScriptVal state) { - CmpPtr cmpPathfinder(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpPathfinder(GetSystemEntity()); if (!cmpPathfinder) return; diff --git a/source/simulation2/components/CCmpDecay.cpp b/source/simulation2/components/CCmpDecay.cpp index 309c5a7538..eac41ee9b5 100644 --- a/source/simulation2/components/CCmpDecay.cpp +++ b/source/simulation2/components/CCmpDecay.cpp @@ -136,7 +136,7 @@ public: const CMessageInterpolate& msgData = static_cast (msg); - CmpPtr cmpPosition(GetSimContext(), GetEntityId()); + CmpPtr cmpPosition(GetEntityHandle()); if (!cmpPosition || !cmpPosition->IsInWorld()) { // If there's no position (this usually shouldn't happen), destroy the unit immediately @@ -151,7 +151,7 @@ public: { m_TotalSinkDepth = 1.f; // minimum so we always sink at least a little - CmpPtr cmpVisual(GetSimContext(), GetEntityId()); + CmpPtr cmpVisual(GetEntityHandle()); if (cmpVisual) { CBoundingBoxAligned bound = cmpVisual->GetBounds(); @@ -163,7 +163,7 @@ public: CFixedVector3D pos = cmpPosition->GetPosition(); - CmpPtr cmpTerrain(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpTerrain(GetSystemEntity()); if (cmpTerrain) { fixed ground = cmpTerrain->GetGroundLevel(pos.X, pos.Z); diff --git a/source/simulation2/components/CCmpFootprint.cpp b/source/simulation2/components/CCmpFootprint.cpp index 301c456db4..828415c15e 100644 --- a/source/simulation2/components/CCmpFootprint.cpp +++ b/source/simulation2/components/CCmpFootprint.cpp @@ -130,11 +130,11 @@ public: const CFixedVector3D error(fixed::FromInt(-1), fixed::FromInt(-1), fixed::FromInt(-1)); - CmpPtr cmpPosition(GetSimContext(), GetEntityId()); + CmpPtr cmpPosition(GetEntityHandle()); if (!cmpPosition || !cmpPosition->IsInWorld()) return error; - CmpPtr cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpObstructionManager(GetSystemEntity()); if (!cmpObstructionManager) return error; @@ -155,7 +155,7 @@ public: return error; ICmpPathfinder::pass_class_t spawnedPass = cmpUnitMotion->GetPassabilityClass(); - CmpPtr cmpPathfinder(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpPathfinder(GetSystemEntity()); if (!cmpPathfinder) return error; diff --git a/source/simulation2/components/CCmpMinimap.cpp b/source/simulation2/components/CCmpMinimap.cpp index ac8004d4e0..4549b449e7 100644 --- a/source/simulation2/components/CCmpMinimap.cpp +++ b/source/simulation2/components/CCmpMinimap.cpp @@ -169,7 +169,7 @@ public: break; // Find the new player's colour - CmpPtr cmpPlayerManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpPlayerManager(GetSystemEntity()); if (!cmpPlayerManager) break; CmpPtr cmpPlayer(GetSimContext(), cmpPlayerManager->GetPlayerByID(msgData.to)); diff --git a/source/simulation2/components/CCmpMotionBall.cpp b/source/simulation2/components/CCmpMotionBall.cpp index 66cbb64343..7ff704dcf1 100644 --- a/source/simulation2/components/CCmpMotionBall.cpp +++ b/source/simulation2/components/CCmpMotionBall.cpp @@ -84,7 +84,7 @@ public: void CCmpMotionBall::Move(fixed dt) { - CmpPtr cmpPosition(GetSimContext(), GetEntityId()); + CmpPtr cmpPosition(GetEntityHandle()); if (!cmpPosition) return; diff --git a/source/simulation2/components/CCmpObstruction.cpp b/source/simulation2/components/CCmpObstruction.cpp index a0ab6a72d7..ea22a7c059 100644 --- a/source/simulation2/components/CCmpObstruction.cpp +++ b/source/simulation2/components/CCmpObstruction.cpp @@ -292,7 +292,7 @@ public: if (!data.inWorld && !m_Tag.valid()) break; // nothing needs to change - CmpPtr cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpObstructionManager(GetSystemEntity()); if (!cmpObstructionManager) break; // error @@ -336,7 +336,7 @@ public: { if (m_Tag.valid()) { - CmpPtr cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpObstructionManager(GetSystemEntity()); if (!cmpObstructionManager) break; // error @@ -358,11 +358,11 @@ public: // Construct the obstruction shape - CmpPtr cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpObstructionManager(GetSystemEntity()); if (!cmpObstructionManager) return; // error - CmpPtr cmpPosition(GetSimContext(), GetEntityId()); + CmpPtr cmpPosition(GetEntityHandle()); if (!cmpPosition) return; // error @@ -389,7 +389,7 @@ public: // TODO: code duplication from message handlers if (m_Tag.valid()) { - CmpPtr cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpObstructionManager(GetSystemEntity()); if (!cmpObstructionManager) return; // error @@ -444,11 +444,11 @@ public: virtual bool GetObstructionSquare(ICmpObstructionManager::ObstructionSquare& out) { - CmpPtr cmpPosition(GetSimContext(), GetEntityId()); + CmpPtr cmpPosition(GetEntityHandle()); if (!cmpPosition) return false; // error - CmpPtr cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpObstructionManager(GetSystemEntity()); if (!cmpObstructionManager) return false; // error @@ -485,7 +485,7 @@ public: virtual EFoundationCheck CheckFoundation(std::string className, bool onlyCenterPoint) { - CmpPtr cmpPosition(GetSimContext(), GetEntityId()); + CmpPtr cmpPosition(GetEntityHandle()); if (!cmpPosition) return FOUNDATION_CHECK_FAIL_ERROR; // error @@ -494,7 +494,7 @@ public: CFixedVector2D pos = cmpPosition->GetPosition2D(); - CmpPtr cmpPathfinder(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpPathfinder(GetSystemEntity()); if (!cmpPathfinder) return FOUNDATION_CHECK_FAIL_ERROR; // error @@ -522,7 +522,7 @@ public: virtual bool CheckDuplicateFoundation() { - CmpPtr cmpPosition(GetSimContext(), GetEntityId()); + CmpPtr cmpPosition(GetEntityHandle()); if (!cmpPosition) return false; // error @@ -531,7 +531,7 @@ public: CFixedVector2D pos = cmpPosition->GetPosition2D(); - CmpPtr cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpObstructionManager(GetSystemEntity()); if (!cmpObstructionManager) return false; // error @@ -556,7 +556,7 @@ public: { std::vector ret; - CmpPtr cmpPosition(GetSimContext(), GetEntityId()); + CmpPtr cmpPosition(GetEntityHandle()); if (!cmpPosition) return ret; // error @@ -565,7 +565,7 @@ public: CFixedVector2D pos = cmpPosition->GetPosition2D(); - CmpPtr cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpObstructionManager(GetSystemEntity()); if (!cmpObstructionManager) return ret; // error @@ -620,7 +620,7 @@ public: if (m_Tag.valid() && m_Type == UNIT) { - CmpPtr cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpObstructionManager(GetSystemEntity()); if (cmpObstructionManager) cmpObstructionManager->SetUnitMovingFlag(m_Tag, m_Moving); } @@ -652,7 +652,7 @@ public: { if (m_Tag.valid()) { - CmpPtr cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpObstructionManager(GetSystemEntity()); if (cmpObstructionManager) { if (m_Type == UNIT) @@ -680,11 +680,11 @@ public: if (m_Type == UNIT) return; - CmpPtr cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpObstructionManager(GetSystemEntity()); if (!cmpObstructionManager) return; - CmpPtr cmpPosition(GetSimContext(), GetEntityId()); + CmpPtr cmpPosition(GetEntityHandle()); if (!cmpPosition) return; // error @@ -750,7 +750,7 @@ protected: inline void AddClusterShapes(entity_pos_t x, entity_pos_t z, entity_angle_t a) { - CmpPtr cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpObstructionManager(GetSystemEntity()); if (!cmpObstructionManager) return; // error @@ -776,7 +776,7 @@ protected: inline void RemoveClusterShapes() { - CmpPtr cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpObstructionManager(GetSystemEntity()); if (!cmpObstructionManager) return; // error diff --git a/source/simulation2/components/CCmpOverlayRenderer.cpp b/source/simulation2/components/CCmpOverlayRenderer.cpp index 88f8894747..e4e7d1f674 100644 --- a/source/simulation2/components/CCmpOverlayRenderer.cpp +++ b/source/simulation2/components/CCmpOverlayRenderer.cpp @@ -123,7 +123,7 @@ public: } // Disable rendering of the unit if it has no position - CmpPtr cmpPosition(GetSimContext(), GetEntityId()); + CmpPtr cmpPosition(GetEntityHandle()); if (!cmpPosition || !cmpPosition->IsInWorld()) { m_Enabled = false; diff --git a/source/simulation2/components/CCmpPathfinder.cpp b/source/simulation2/components/CCmpPathfinder.cpp index d7e1091442..59049ae4cb 100644 --- a/source/simulation2/components/CCmpPathfinder.cpp +++ b/source/simulation2/components/CCmpPathfinder.cpp @@ -306,7 +306,7 @@ const Grid& CCmpPathfinder::GetPassabilityGrid() void CCmpPathfinder::UpdateGrid() { - CmpPtr cmpTerrain(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpTerrain(GetSystemEntity()); if (!cmpTerrain) return; // error @@ -326,7 +326,7 @@ void CCmpPathfinder::UpdateGrid() m_ObstructionGrid = new Grid(m_MapSize, m_MapSize); } - CmpPtr cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpObstructionManager(GetSystemEntity()); bool obstructionsDirty = cmpObstructionManager->Rasterise(*m_ObstructionGrid); @@ -372,7 +372,7 @@ void CCmpPathfinder::UpdateGrid() // Obstructions or terrain changed - we need to recompute passability // TODO: only bother recomputing the region that has actually changed - CmpPtr cmpWaterManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpWaterManager(GetSystemEntity()); // TOOD: these bits should come from ICmpTerrain CTerrain& terrain = GetSimContext().GetTerrain(); @@ -666,7 +666,7 @@ ICmpObstruction::EFoundationCheck CCmpPathfinder::CheckUnitPlacement(const IObst entity_pos_t x, entity_pos_t z, entity_pos_t r, pass_class_t passClass, bool onlyCenterPoint) { // Check unit obstruction - CmpPtr cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpObstructionManager(GetSystemEntity()); if (!cmpObstructionManager) return ICmpObstruction::FOUNDATION_CHECK_FAIL_ERROR; @@ -717,7 +717,7 @@ ICmpObstruction::EFoundationCheck CCmpPathfinder::CheckBuildingPlacement(const I entity_pos_t h, entity_id_t id, pass_class_t passClass, bool onlyCenterPoint) { // Check unit obstruction - CmpPtr cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpObstructionManager(GetSystemEntity()); if (!cmpObstructionManager) return ICmpObstruction::FOUNDATION_CHECK_FAIL_ERROR; diff --git a/source/simulation2/components/CCmpPathfinder_Vertex.cpp b/source/simulation2/components/CCmpPathfinder_Vertex.cpp index b2f01712a0..27d61a76b5 100644 --- a/source/simulation2/components/CCmpPathfinder_Vertex.cpp +++ b/source/simulation2/components/CCmpPathfinder_Vertex.cpp @@ -580,7 +580,7 @@ void CCmpPathfinder::ComputeShortPath(const IObstructionTestFilter& filter, } // Find all the obstruction squares that might affect us - CmpPtr cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpObstructionManager(GetSystemEntity()); std::vector squares; cmpObstructionManager->GetObstructionsInRange(filter, rangeXMin - r, rangeZMin - r, rangeXMax + r, rangeZMax + r, squares); @@ -854,7 +854,7 @@ bool CCmpPathfinder::CheckMovement(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1, entity_pos_t r, pass_class_t passClass) { - CmpPtr cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpObstructionManager(GetSystemEntity()); if (!cmpObstructionManager) return false; diff --git a/source/simulation2/components/CCmpPosition.cpp b/source/simulation2/components/CCmpPosition.cpp index 721d6893a1..02a032e83a 100644 --- a/source/simulation2/components/CCmpPosition.cpp +++ b/source/simulation2/components/CCmpPosition.cpp @@ -304,13 +304,13 @@ public: entity_pos_t baseY; if (m_RelativeToGround) { - CmpPtr cmpTerrain(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpTerrain(GetSystemEntity()); if (cmpTerrain) baseY = cmpTerrain->GetGroundLevel(m_X, m_Z); if (m_Floating) { - CmpPtr cmpWaterManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpWaterManager(GetSystemEntity()); if (cmpWaterManager) baseY = std::max(baseY, cmpWaterManager->GetWaterLevel(m_X, m_Z)); } @@ -341,13 +341,13 @@ public: entity_pos_t baseY; if (m_RelativeToGround) { - CmpPtr cmpTerrain(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpTerrain(GetSystemEntity()); if (cmpTerrain) baseY = cmpTerrain->GetGroundLevel(m_PrevX, m_PrevZ); if (m_Floating) { - CmpPtr cmpWaterMan(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpWaterMan(GetSystemEntity()); if (cmpWaterMan) baseY = std::max(baseY, cmpWaterMan->GetWaterLevel(m_PrevX, m_PrevZ)); } @@ -452,13 +452,13 @@ public: float baseY = 0; if (m_RelativeToGround) { - CmpPtr cmpTerrain(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpTerrain(GetSystemEntity()); if (cmpTerrain) baseY = cmpTerrain->GetExactGroundLevel(x, z); if (m_Floating || forceFloating) { - CmpPtr cmpWaterManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpWaterManager(GetSystemEntity()); if (cmpWaterManager) baseY = std::max(baseY, cmpWaterManager->GetExactWaterLevel(x, z)); } @@ -575,7 +575,7 @@ private: return; } - CmpPtr cmpTerrain(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpTerrain(GetSystemEntity()); if (!cmpTerrain || !cmpTerrain->IsLoaded()) { // try again when terrain is loaded diff --git a/source/simulation2/components/CCmpProjectileManager.cpp b/source/simulation2/components/CCmpProjectileManager.cpp index 3b69567feb..3b243a75a6 100644 --- a/source/simulation2/components/CCmpProjectileManager.cpp +++ b/source/simulation2/components/CCmpProjectileManager.cpp @@ -235,7 +235,7 @@ void CCmpProjectileManager::AdvanceProjectile(Projectile& projectile, float dt) // carry on until we reach solid land if (projectile.time >= projectile.timeHit) { - CmpPtr cmpTerrain(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpTerrain(GetSystemEntity()); if (cmpTerrain) { float h = cmpTerrain->GetExactGroundLevel(projectile.pos.X, projectile.pos.Z); @@ -318,7 +318,7 @@ void CCmpProjectileManager::RemoveProjectile(uint32_t id) void CCmpProjectileManager::RenderSubmit(SceneCollector& collector, const CFrustum& frustum, bool culling) { - CmpPtr cmpRangeManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpRangeManager(GetSystemEntity()); int player = GetSimContext().GetCurrentDisplayedPlayer(); ICmpRangeManager::CLosQuerier los (cmpRangeManager->GetLosQuerier(player)); bool losRevealAll = cmpRangeManager->GetLosRevealAll(player); diff --git a/source/simulation2/components/CCmpRallyPointRenderer.cpp b/source/simulation2/components/CCmpRallyPointRenderer.cpp index 8612c1512e..684199dad6 100644 --- a/source/simulation2/components/CCmpRallyPointRenderer.cpp +++ b/source/simulation2/components/CCmpRallyPointRenderer.cpp @@ -500,14 +500,14 @@ void CCmpRallyPointRenderer::UpdateMarkers() } // set rally point flag selection based on player civilization - CmpPtr cmpOwnership(GetSimContext(), GetEntityId()); + CmpPtr cmpOwnership(GetEntityHandle()); if (cmpOwnership) { player_id_t ownerId = cmpOwnership->GetOwner(); if (ownerId != INVALID_PLAYER && (ownerId != previousOwner || m_LastMarkerCount < i)) { m_LastOwner = ownerId; - CmpPtr cmpPlayerManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpPlayerManager(GetSystemEntity()); // cmpPlayerManager should not be null as long as this method is called on-demand instead of at Init() time // (we can't rely on component initialization order in Init()) if (cmpPlayerManager) @@ -542,12 +542,12 @@ void CCmpRallyPointRenderer::RecomputeAllRallyPointPaths() if (!IsSet()) return; // no use computing a path if the rally point isn't set - CmpPtr cmpPosition(GetSimContext(), GetEntityId()); + CmpPtr cmpPosition(GetEntityHandle()); if (!cmpPosition || !cmpPosition->IsInWorld()) return; // no point going on if this entity doesn't have a position or is outside of the world - CmpPtr cmpFootprint(GetSimContext(), GetEntityId()); - CmpPtr cmpPathfinder(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpFootprint(GetEntityHandle()); + CmpPtr cmpPathfinder(GetSystemEntity()); for (size_t i = 0; i < m_RallyPoints.size(); ++i) { @@ -560,12 +560,12 @@ void CCmpRallyPointRenderer::RecomputeRallyPointPath_wrapper(size_t index) if (!IsSet()) return; // no use computing a path if the rally point isn't set - CmpPtr cmpPosition(GetSimContext(), GetEntityId()); + CmpPtr cmpPosition(GetEntityHandle()); if (!cmpPosition || !cmpPosition->IsInWorld()) return; // no point going on if this entity doesn't have a position or is outside of the world - CmpPtr cmpFootprint(GetSimContext(), GetEntityId()); - CmpPtr cmpPathfinder(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpFootprint(GetEntityHandle()); + CmpPtr cmpPathfinder(GetSystemEntity()); RecomputeRallyPointPath(index, cmpPosition, cmpFootprint, cmpPathfinder); } @@ -726,7 +726,7 @@ void CCmpRallyPointRenderer::ConstructOverlayLines(size_t index) if (m_Path[index].size() < 2) return; - CmpPtr cmpTerrain(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpTerrain(GetSystemEntity()); LineCapType dashesLineCapType = SOverlayTexturedLine::LINECAP_ROUND; // line caps to use for the dashed segments (and any other segment's edges that border it) for (std::deque::const_iterator it = m_VisibilitySegments[index].begin(); it != m_VisibilitySegments[index].end(); ++it) @@ -984,9 +984,9 @@ void CCmpRallyPointRenderer::FixFootprintWaypoints(std::vector& coord void CCmpRallyPointRenderer::ReduceSegmentsByVisibility(std::vector& coords, unsigned maxSegmentLinks, bool floating) { - CmpPtr cmpPathFinder(GetSimContext(), SYSTEM_ENTITY); - CmpPtr cmpTerrain(GetSimContext(), SYSTEM_ENTITY); - CmpPtr cmpWaterManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpPathFinder(GetSystemEntity()); + CmpPtr cmpTerrain(GetSystemEntity()); + CmpPtr cmpWaterManager(GetSystemEntity()); ENSURE(cmpPathFinder && cmpTerrain && cmpWaterManager); if (coords.size() < 3) @@ -1083,7 +1083,7 @@ void CCmpRallyPointRenderer::GetVisibilitySegments(std::deque cmpRangeMgr(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpRangeMgr(GetSystemEntity()); player_id_t currentPlayer = GetSimContext().GetCurrentDisplayedPlayer(); CLosQuerier losQuerier(cmpRangeMgr->GetLosQuerier(currentPlayer)); diff --git a/source/simulation2/components/CCmpRangeManager.cpp b/source/simulation2/components/CCmpRangeManager.cpp index d5d0df7c30..64f16bf46b 100644 --- a/source/simulation2/components/CCmpRangeManager.cpp +++ b/source/simulation2/components/CCmpRangeManager.cpp @@ -47,7 +47,7 @@ struct Query { bool enabled; bool parabolic; - entity_id_t source; + CEntityHandle source; // TODO: this could crash if an entity is destroyed while a Query is still referencing it entity_pos_t minRange; entity_pos_t maxRange; entity_pos_t elevationBonus; @@ -145,18 +145,16 @@ struct EntityData cassert(sizeof(EntityData) == 16); - /** * Serialization helper template for Query */ struct SerializeQuery { template - void operator()(S& serialize, const char* UNUSED(name), Query& value) + void Common(S& serialize, const char* UNUSED(name), Query& value) { serialize.Bool("enabled", value.enabled); serialize.Bool("parabolic",value.parabolic); - serialize.NumberU32_Unbounded("source", value.source); serialize.NumberFixed_Unbounded("min range", value.minRange); serialize.NumberFixed_Unbounded("max range", value.maxRange); serialize.NumberFixed_Unbounded("elevation bonus", value.elevationBonus); @@ -165,6 +163,25 @@ struct SerializeQuery SerializeVector()(serialize, "last match", value.lastMatch); serialize.NumberU8_Unbounded("flagsMask", value.flagsMask); } + + void operator()(ISerializer& serialize, const char* name, Query& value, const CSimContext& UNUSED(context)) + { + Common(serialize, name, value); + + uint32_t id = value.source.GetId(); + serialize.NumberU32_Unbounded("source", id); + } + + void operator()(IDeserializer& deserialize, const char* name, Query& value, const CSimContext& context) + { + Common(deserialize, name, value); + + uint32_t id; + deserialize.NumberU32_Unbounded("source", id); + value.source = context.GetComponentManager().LookupEntityHandle(id, true); + // the referenced entity might not have been deserialized yet, + // so tell LookupEntityHandle to allocate the handle if necessary + } }; /** @@ -331,7 +348,7 @@ public: serialize.NumberFixed_Unbounded("world z1", m_WorldZ1); serialize.NumberU32_Unbounded("query next", m_QueryNext); - SerializeMap()(serialize, "queries", m_Queries); + SerializeMap()(serialize, "queries", m_Queries, GetSimContext()); SerializeMap()(serialize, "entity data", m_EntityData); SerializeMap()(serialize, "los reveal all", m_LosRevealAll); @@ -720,7 +737,7 @@ public: std::vector r; - CmpPtr cmpSourcePosition(GetSimContext(), q.source); + CmpPtr cmpSourcePosition(q.source); if (!cmpSourcePosition || !cmpSourcePosition->IsInWorld()) { // If the source doesn't have a position, then the result is just the empty list @@ -752,7 +769,7 @@ public: Query& q = it->second; q.enabled = true; - CmpPtr cmpSourcePosition(GetSimContext(), q.source); + CmpPtr cmpSourcePosition(q.source); if (!cmpSourcePosition || !cmpSourcePosition->IsInWorld()) { // If the source doesn't have a position, then the result is just the empty list @@ -813,7 +830,7 @@ public: if (!q.enabled) continue; - CmpPtr cmpSourcePosition(GetSimContext(), q.source); + CmpPtr cmpSourcePosition(q.source); if (!cmpSourcePosition || !cmpSourcePosition->IsInWorld()) continue; @@ -836,7 +853,7 @@ public: CFixedVector2D pos = cmpSourcePosition->GetPosition2D(); std::stable_sort(added.begin(), added.end(), EntityDistanceOrdering(m_EntityData, pos)); - messages.push_back(std::make_pair(q.source, CMessageRangeUpdate(it->first))); + messages.push_back(std::make_pair(q.source.GetId(), CMessageRangeUpdate(it->first))); messages.back().second.added.swap(added); messages.back().second.removed.swap(removed); @@ -865,7 +882,7 @@ public: return false; // Ignore self - if (id == q.source) + if (id == q.source.GetId()) return false; // Ignore if it's missing the required interface @@ -880,7 +897,7 @@ public: */ void PerformQuery(const Query& q, std::vector& r) { - CmpPtr cmpSourcePosition(GetSimContext(), q.source); + CmpPtr cmpSourcePosition(q.source); if (!cmpSourcePosition || !cmpSourcePosition->IsInWorld()) return; CFixedVector2D pos = cmpSourcePosition->GetPosition2D(); @@ -1006,8 +1023,8 @@ public: std::vector r; - CmpPtr cmpTerrain(GetSimContext(), SYSTEM_ENTITY); - CmpPtr cmpWaterManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpTerrain(GetSystemEntity()); + CmpPtr cmpWaterManager(GetSystemEntity()); entity_pos_t waterLevel = cmpWaterManager->GetWaterLevel(pos.X,pos.Z); entity_pos_t thisHeight = pos.Y > waterLevel ? pos.Y : waterLevel; @@ -1088,7 +1105,7 @@ public: Query q; q.enabled = false; q.parabolic = false; - q.source = source; + q.source = GetSimContext().GetComponentManager().LookupEntityHandle(source); q.minRange = minRange; q.maxRange = maxRange; q.elevationBonus = entity_pos_t::Zero(); @@ -1130,7 +1147,7 @@ public: { Query& q = it->second; - CmpPtr cmpSourcePosition(GetSimContext(), q.source); + CmpPtr cmpSourcePosition(q.source); if (!cmpSourcePosition || !cmpSourcePosition->IsInWorld()) continue; CFixedVector2D pos = cmpSourcePosition->GetPosition2D(); @@ -1151,9 +1168,9 @@ public: std::vector coords; // Get the outline from cache if possible - if (ParabolicRangesOutlines.find(q.source) != ParabolicRangesOutlines.end()) + if (ParabolicRangesOutlines.find(q.source.GetId()) != ParabolicRangesOutlines.end()) { - EntityParabolicRangeOutline e = ParabolicRangesOutlines[q.source]; + EntityParabolicRangeOutline e = ParabolicRangesOutlines[q.source.GetId()]; if (e.position == pos && e.range == q.maxRange) { // outline is cached correctly, use it @@ -1168,7 +1185,7 @@ public: e.outline = coords; e.range = q.maxRange; e.position = pos; - ParabolicRangesOutlines[q.source] = e; + ParabolicRangesOutlines[q.source.GetId()] = e; } } else @@ -1178,11 +1195,11 @@ public: // cache a new outline coords = getParabolicRangeForm(pos,q.maxRange,q.maxRange*2, entity_pos_t::Zero(), entity_pos_t::FromFloat(2.0f*3.14f),70); EntityParabolicRangeOutline e; - e.source = q.source; + e.source = q.source.GetId(); e.range = q.maxRange; e.position = pos; e.outline = coords; - ParabolicRangesOutlines[q.source] = e; + ParabolicRangesOutlines[q.source.GetId()] = e; } CColor thiscolor = q.enabled ? enabledRingColour : disabledRingColour; @@ -1280,12 +1297,14 @@ public: return CLosQuerier(GetSharedLosMask(player), m_LosState, m_TerrainVerticesPerSide); } - virtual ELosVisibility GetLosVisibility(entity_id_t ent, player_id_t player, bool forceRetainInFog) + virtual ELosVisibility GetLosVisibility(CEntityHandle ent, player_id_t player, bool forceRetainInFog) { // (We can't use m_EntityData since this needs to handle LOCAL entities too) // Entities not with positions in the world are never visible - CmpPtr cmpPosition(GetSimContext(), ent); + if (ent.GetId() == INVALID_ENTITY) + return VIS_HIDDEN; + CmpPtr cmpPosition(ent); if (!cmpPosition || !cmpPosition->IsInWorld()) return VIS_HIDDEN; @@ -1312,7 +1331,7 @@ public: // Fogged if the 'retain in fog' flag is set, and in a non-visible explored region if (los.IsExplored(i, j)) { - CmpPtr cmpVision(GetSimContext(), ent); + CmpPtr cmpVision(ent); if (forceRetainInFog || (cmpVision && cmpVision->GetRetainInFog())) return VIS_FOGGED; } @@ -1321,6 +1340,13 @@ public: return VIS_HIDDEN; } + virtual ELosVisibility GetLosVisibility(entity_id_t ent, player_id_t player, bool forceRetainInFog) + { + CEntityHandle handle = GetSimContext().GetComponentManager().LookupEntityHandle(ent); + return GetLosVisibility(handle, player, forceRetainInFog); + } + + virtual void SetLosRevealAll(player_id_t player, bool enabled) { m_LosRevealAll[player] = enabled; @@ -1370,7 +1396,7 @@ public: void UpdateTerritoriesLos() { - CmpPtr cmpTerritoryManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpTerritoryManager(GetSystemEntity()); if (!cmpTerritoryManager || !cmpTerritoryManager->NeedUpdate(&m_TerritoriesDirtyID)) return; diff --git a/source/simulation2/components/CCmpSelectable.cpp b/source/simulation2/components/CCmpSelectable.cpp index 73f4f7bf88..2bb9464bdd 100644 --- a/source/simulation2/components/CCmpSelectable.cpp +++ b/source/simulation2/components/CCmpSelectable.cpp @@ -306,7 +306,7 @@ void CCmpSelectable::HandleMessage(const CMessage& msg, bool UNUSED(global)) break; // update the selection highlight color - CmpPtr cmpPlayerManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpPlayerManager(GetSystemEntity()); if (!cmpPlayerManager) break; @@ -352,13 +352,12 @@ void CCmpSelectable::UpdateStaticOverlay() if (!CRenderer::IsInitialised()) return; - entity_id_t entityId = GetEntityId(); - CmpPtr cmpPosition(GetSimContext(), entityId); - CmpPtr cmpFootprint(GetSimContext(), entityId); + CmpPtr cmpPosition(GetEntityHandle()); + CmpPtr cmpFootprint(GetEntityHandle()); if (!cmpFootprint || !cmpPosition || !cmpPosition->IsInWorld()) return; - CmpPtr cmpTerrain(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpTerrain(GetSystemEntity()); if (!cmpTerrain) return; // should never happen @@ -450,9 +449,8 @@ void CCmpSelectable::UpdateDynamicOverlay(float frameOffset) if (!CRenderer::IsInitialised()) return; - entity_id_t entityId = GetEntityId(); - CmpPtr cmpPosition(GetSimContext(), entityId); - CmpPtr cmpFootprint(GetSimContext(), entityId); + CmpPtr cmpPosition(GetEntityHandle()); + CmpPtr cmpFootprint(GetEntityHandle()); if (!cmpFootprint || !cmpPosition || !cmpPosition->IsInWorld()) return; @@ -460,8 +458,8 @@ void CCmpSelectable::UpdateDynamicOverlay(float frameOffset) CVector2D position; cmpPosition->GetInterpolatedPosition2D(frameOffset, position.X, position.Y, rotY); - CmpPtr cmpWaterManager(GetSimContext(), SYSTEM_ENTITY); - CmpPtr cmpTerrain(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpWaterManager(GetSystemEntity()); + CmpPtr cmpTerrain(GetSystemEntity()); ENSURE(cmpWaterManager && cmpTerrain); CTerrain* terrain = cmpTerrain->GetCTerrain(); @@ -534,7 +532,7 @@ void CCmpSelectable::RenderSubmit(SceneCollector& collector) { // Default to white if there's no owner (e.g. decorative, editor-only actors) CColor color = CColor(1.0, 1.0, 1.0, 1.0); - CmpPtr cmpOwnership(GetSimContext(), GetEntityId()); + CmpPtr cmpOwnership(GetEntityHandle()); if (cmpOwnership) { player_id_t owner = cmpOwnership->GetOwner(); @@ -542,7 +540,7 @@ void CCmpSelectable::RenderSubmit(SceneCollector& collector) return; // Try to initialize m_Color to the owning player's colour. - CmpPtr cmpPlayerManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpPlayerManager(GetSystemEntity()); if (!cmpPlayerManager) return; @@ -588,7 +586,7 @@ void CCmpSelectable::RenderSubmit(SceneCollector& collector) if (!m_DebugBoundingBoxOverlay) m_DebugBoundingBoxOverlay = new SOverlayLine; if (!m_DebugSelectionBoxOverlay) m_DebugSelectionBoxOverlay = new SOverlayLine; - CmpPtr cmpVisual(GetSimContext(), GetEntityId()); + CmpPtr cmpVisual(GetEntityHandle()); if (cmpVisual) { SimRender::ConstructBoxOutline(cmpVisual->GetBounds(), *m_DebugBoundingBoxOverlay); diff --git a/source/simulation2/components/CCmpSoundManager.cpp b/source/simulation2/components/CCmpSoundManager.cpp index 20bb235b82..cc2db102df 100644 --- a/source/simulation2/components/CCmpSoundManager.cpp +++ b/source/simulation2/components/CCmpSoundManager.cpp @@ -65,7 +65,7 @@ public: if ( ! g_SoundManager || (source == INVALID_ENTITY) ) return; - CmpPtr cmpRangeManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpRangeManager(GetSystemEntity()); int currentPlayer = GetSimContext().GetCurrentDisplayedPlayer(); if ( !cmpRangeManager || diff --git a/source/simulation2/components/CCmpTerrain.cpp b/source/simulation2/components/CCmpTerrain.cpp index 2c7cd19a65..58965dd122 100644 --- a/source/simulation2/components/CCmpTerrain.cpp +++ b/source/simulation2/components/CCmpTerrain.cpp @@ -118,7 +118,7 @@ public: u16 tiles = GetTilesPerSide(); u16 vertices = GetVerticesPerSide(); - CmpPtr cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpObstructionManager(GetSystemEntity()); if (cmpObstructionManager) { cmpObstructionManager->SetBounds(entity_pos_t::Zero(), entity_pos_t::Zero(), @@ -126,7 +126,7 @@ public: entity_pos_t::FromInt(tiles*(int)TERRAIN_TILE_SIZE)); } - CmpPtr cmpRangeManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpRangeManager(GetSystemEntity()); if (cmpRangeManager) { cmpRangeManager->SetBounds(entity_pos_t::Zero(), entity_pos_t::Zero(), diff --git a/source/simulation2/components/CCmpTerritoryInfluence.cpp b/source/simulation2/components/CCmpTerritoryInfluence.cpp index dcf50572f5..ca748ff90e 100644 --- a/source/simulation2/components/CCmpTerritoryInfluence.cpp +++ b/source/simulation2/components/CCmpTerritoryInfluence.cpp @@ -103,10 +103,10 @@ public: { u32 newRadius = m_Radius; - CmpPtr cmpOwnership(GetSimContext(), GetEntityId()); + CmpPtr cmpOwnership(GetEntityHandle()); if (cmpOwnership && cmpOwnership->GetOwner() != INVALID_PLAYER) { - CmpPtr cmpPlayerManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpPlayerManager(GetSystemEntity()); entity_id_t playerEnt = cmpPlayerManager->GetPlayerByID(cmpOwnership->GetOwner()); if (playerEnt != INVALID_ENTITY) diff --git a/source/simulation2/components/CCmpTerritoryManager.cpp b/source/simulation2/components/CCmpTerritoryManager.cpp index c8b1ec79c4..a144c57fda 100644 --- a/source/simulation2/components/CCmpTerritoryManager.cpp +++ b/source/simulation2/components/CCmpTerritoryManager.cpp @@ -336,7 +336,7 @@ void CCmpTerritoryManager::CalculateTerritories() PROFILE("CalculateTerritories"); - CmpPtr cmpTerrain(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpTerrain(GetSystemEntity()); // If the terrain hasn't been loaded (e.g. this is called during map initialisation), // abort the computation (and assume callers can cope with m_Territories == NULL) @@ -351,7 +351,7 @@ void CCmpTerritoryManager::CalculateTerritories() // Compute terrain-passability-dependent costs per tile Grid influenceGrid(tilesW, tilesH); - CmpPtr cmpPathfinder(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpPathfinder(GetSystemEntity()); ICmpPathfinder::pass_class_t passClassDefault = cmpPathfinder->GetPassabilityClass("default"); ICmpPathfinder::pass_class_t passClassUnrestricted = cmpPathfinder->GetPassabilityClass("unrestricted"); @@ -628,7 +628,7 @@ void CCmpTerritoryManager::UpdateBoundaryLines() texturePropsMask.SetMaxAnisotropy(2.f); CTexturePtr textureMask = g_Renderer.GetTextureManager().CreateTexture(texturePropsMask); - CmpPtr cmpPlayerManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpPlayerManager(GetSystemEntity()); if (!cmpPlayerManager) return; diff --git a/source/simulation2/components/CCmpUnitMotion.cpp b/source/simulation2/components/CCmpUnitMotion.cpp index 4985e9c407..cc0fa896f4 100644 --- a/source/simulation2/components/CCmpUnitMotion.cpp +++ b/source/simulation2/components/CCmpUnitMotion.cpp @@ -294,14 +294,14 @@ public: m_RunSpeed = m_WalkSpeed; } - CmpPtr cmpPathfinder(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpPathfinder(GetSystemEntity()); if (cmpPathfinder) { m_PassClass = cmpPathfinder->GetPassabilityClass(paramNode.GetChild("PassabilityClass").ToUTF8()); m_CostClass = cmpPathfinder->GetCostClass(paramNode.GetChild("CostClass").ToUTF8()); } - CmpPtr cmpObstruction(GetSimContext(), GetEntityId()); + CmpPtr cmpObstruction(GetEntityHandle()); if (cmpObstruction) m_Radius = cmpObstruction->GetUnitRadius(); @@ -472,7 +472,7 @@ private: StopMoving(); m_State = STATE_IDLE; // don't go through the STOPPING state since we never even started - CmpPtr cmpObstruction(GetSimContext(), GetEntityId()); + CmpPtr cmpObstruction(GetEntityHandle()); if (cmpObstruction) cmpObstruction->SetMovingFlag(false); @@ -484,7 +484,7 @@ private: { StopMoving(); - CmpPtr cmpObstruction(GetSimContext(), GetEntityId()); + CmpPtr cmpObstruction(GetEntityHandle()); if (cmpObstruction) cmpObstruction->SetMovingFlag(false); @@ -502,7 +502,7 @@ private: { m_Moving = false; - CmpPtr cmpObstruction(GetSimContext(), GetEntityId()); + CmpPtr cmpObstruction(GetEntityHandle()); if (cmpObstruction) cmpObstruction->SetMovingFlag(false); @@ -620,7 +620,7 @@ void CCmpUnitMotion::PathResult(u32 ticket, const ICmpPathfinder::Path& path) m_LongPath.m_Waypoints.push_back(wp); } - CmpPtr cmpPosition(GetSimContext(), GetEntityId()); + CmpPtr cmpPosition(GetEntityHandle()); if (!cmpPosition || !cmpPosition->IsInWorld()) { StartFailed(); @@ -658,7 +658,7 @@ void CCmpUnitMotion::PathResult(u32 ticket, const ICmpPathfinder::Path& path) } } - CmpPtr cmpPosition(GetSimContext(), GetEntityId()); + CmpPtr cmpPosition(GetEntityHandle()); if (!cmpPosition || !cmpPosition->IsInWorld()) { StartFailed(); @@ -686,7 +686,7 @@ void CCmpUnitMotion::PathResult(u32 ticket, const ICmpPathfinder::Path& path) m_LongPath.m_Waypoints.push_back(wp); } - CmpPtr cmpPosition(GetSimContext(), GetEntityId()); + CmpPtr cmpPosition(GetEntityHandle()); if (!cmpPosition || !cmpPosition->IsInWorld()) { StopMoving(); @@ -794,11 +794,11 @@ void CCmpUnitMotion::Move(fixed dt) // Maybe we should split the updates into multiple phases to minimise // that problem. - CmpPtr cmpPathfinder (GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpPathfinder(GetSystemEntity()); if (!cmpPathfinder) return; - CmpPtr cmpPosition(GetSimContext(), GetEntityId()); + CmpPtr cmpPosition(GetEntityHandle()); if (!cmpPosition || !cmpPosition->IsInWorld()) return; @@ -1020,7 +1020,7 @@ bool CCmpUnitMotion::TryGoingStraightToTargetEntity(CFixedVector2D from) if ((targetPos - from).CompareLength(DIRECT_PATH_RANGE) > 0) return false; - CmpPtr cmpPathfinder (GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpPathfinder(GetSystemEntity()); if (!cmpPathfinder) return false; @@ -1066,10 +1066,10 @@ bool CCmpUnitMotion::CheckTargetMovement(CFixedVector2D from, entity_pos_t minDe // Fail if the target is no longer visible to this entity's owner // (in which case we'll continue moving to its last known location, // unless it comes back into view before we reach that location) - CmpPtr cmpOwnership(GetSimContext(), GetEntityId()); + CmpPtr cmpOwnership(GetEntityHandle()); if (cmpOwnership) { - CmpPtr cmpRangeManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpRangeManager(GetSystemEntity()); if (cmpRangeManager) { if (cmpRangeManager->GetLosVisibility(m_TargetEntity, cmpOwnership->GetOwner()) == ICmpRangeManager::VIS_HIDDEN) @@ -1111,7 +1111,7 @@ bool CCmpUnitMotion::PathIsShort(const ICmpPathfinder::Path& path, CFixedVector2 void CCmpUnitMotion::FaceTowardsPoint(entity_pos_t x, entity_pos_t z) { - CmpPtr cmpPosition(GetSimContext(), GetEntityId()); + CmpPtr cmpPosition(GetEntityHandle()); if (!cmpPosition || !cmpPosition->IsInWorld()) return; @@ -1127,7 +1127,7 @@ void CCmpUnitMotion::FaceTowardsPointFromPos(CFixedVector2D pos, entity_pos_t x, { entity_angle_t angle = atan2_approx(offset.X, offset.Y); - CmpPtr cmpPosition(GetSimContext(), GetEntityId()); + CmpPtr cmpPosition(GetEntityHandle()); if (!cmpPosition) return; cmpPosition->TurnTo(angle); @@ -1156,7 +1156,7 @@ void CCmpUnitMotion::BeginPathing(CFixedVector2D from, const ICmpPathfinder::Goa m_Moving = true; // Set our 'moving' flag, so other units pathfinding now will ignore us - CmpPtr cmpObstruction(GetSimContext(), GetEntityId()); + CmpPtr cmpObstruction(GetEntityHandle()); if (cmpObstruction) cmpObstruction->SetMovingFlag(true); @@ -1183,7 +1183,7 @@ void CCmpUnitMotion::BeginPathing(CFixedVector2D from, const ICmpPathfinder::Goa void CCmpUnitMotion::RequestLongPath(CFixedVector2D from, const ICmpPathfinder::Goal& goal) { - CmpPtr cmpPathfinder(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpPathfinder(GetSystemEntity()); if (!cmpPathfinder) return; @@ -1194,7 +1194,7 @@ void CCmpUnitMotion::RequestLongPath(CFixedVector2D from, const ICmpPathfinder:: void CCmpUnitMotion::RequestShortPath(CFixedVector2D from, const ICmpPathfinder::Goal& goal, bool avoidMovingUnits) { - CmpPtr cmpPathfinder(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpPathfinder(GetSystemEntity()); if (!cmpPathfinder) return; @@ -1242,7 +1242,7 @@ bool CCmpUnitMotion::PickNextLongWaypoint(const CFixedVector2D& pos, bool avoidM goal.z = targetZ; } - CmpPtr cmpPathfinder(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpPathfinder(GetSystemEntity()); if (!cmpPathfinder) return false; @@ -1256,7 +1256,7 @@ bool CCmpUnitMotion::MoveToPointRange(entity_pos_t x, entity_pos_t z, entity_pos { PROFILE("MoveToPointRange"); - CmpPtr cmpPosition(GetSimContext(), GetEntityId()); + CmpPtr cmpPosition(GetEntityHandle()); if (!cmpPosition || !cmpPosition->IsInWorld()) return false; @@ -1270,7 +1270,7 @@ bool CCmpUnitMotion::MoveToPointRange(entity_pos_t x, entity_pos_t z, entity_pos // Check whether this point is in an obstruction - CmpPtr cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpObstructionManager(GetSystemEntity()); if (!cmpObstructionManager) return false; @@ -1340,14 +1340,14 @@ bool CCmpUnitMotion::MoveToPointRange(entity_pos_t x, entity_pos_t z, entity_pos bool CCmpUnitMotion::IsInPointRange(entity_pos_t x, entity_pos_t z, entity_pos_t minRange, entity_pos_t maxRange) { - CmpPtr cmpPosition(GetSimContext(), GetEntityId()); + CmpPtr cmpPosition(GetEntityHandle()); if (!cmpPosition || !cmpPosition->IsInWorld()) return false; CFixedVector2D pos = cmpPosition->GetPosition2D(); bool hasObstruction = false; - CmpPtr cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpObstructionManager(GetSystemEntity()); ICmpObstructionManager::ObstructionSquare obstruction; if (cmpObstructionManager) hasObstruction = cmpObstructionManager->FindMostImportantObstruction(GetObstructionFilter(true), x, z, m_Radius, obstruction); @@ -1406,13 +1406,13 @@ bool CCmpUnitMotion::MoveToTargetRange(entity_id_t target, entity_pos_t minRange { PROFILE("MoveToTargetRange"); - CmpPtr cmpPosition(GetSimContext(), GetEntityId()); + CmpPtr cmpPosition(GetEntityHandle()); if (!cmpPosition || !cmpPosition->IsInWorld()) return false; CFixedVector2D pos = cmpPosition->GetPosition2D(); - CmpPtr cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpObstructionManager(GetSystemEntity()); if (!cmpObstructionManager) return false; @@ -1551,13 +1551,13 @@ bool CCmpUnitMotion::IsInTargetRange(entity_id_t target, entity_pos_t minRange, // This function closely mirrors MoveToTargetRange - it needs to return true // after that Move has completed - CmpPtr cmpPosition(GetSimContext(), GetEntityId()); + CmpPtr cmpPosition(GetEntityHandle()); if (!cmpPosition || !cmpPosition->IsInWorld()) return false; CFixedVector2D pos = cmpPosition->GetPosition2D(); - CmpPtr cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpObstructionManager(GetSystemEntity()); if (!cmpObstructionManager) return false; @@ -1642,7 +1642,7 @@ void CCmpUnitMotion::MoveToFormationOffset(entity_id_t target, entity_pos_t x, e void CCmpUnitMotion::RenderPath(const ICmpPathfinder::Path& path, std::vector& lines, CColor color) { bool floating = false; - CmpPtr cmpPosition(GetSimContext(), GetEntityId()); + CmpPtr cmpPosition(GetEntityHandle()); if (cmpPosition) floating = cmpPosition->IsFloating(); diff --git a/source/simulation2/components/CCmpVision.cpp b/source/simulation2/components/CCmpVision.cpp index 070ad44d7c..facd023cbf 100644 --- a/source/simulation2/components/CCmpVision.cpp +++ b/source/simulation2/components/CCmpVision.cpp @@ -85,13 +85,13 @@ public: const CMessageTechnologyModification& msgData = static_cast (msg); if (msgData.component == L"Vision") { - CmpPtr cmpOwnership(GetSimContext(), GetEntityId()); + CmpPtr cmpOwnership(GetEntityHandle()); if (cmpOwnership) { player_id_t owner = cmpOwnership->GetOwner(); if (owner != INVALID_PLAYER && owner == msgData.player) { - CmpPtr cmpPlayerManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpPlayerManager(GetSystemEntity()); entity_id_t playerEnt = cmpPlayerManager->GetPlayerByID(owner); CmpPtr cmpTechnologyManager(GetSimContext(), playerEnt); if (playerEnt != INVALID_ENTITY && cmpTechnologyManager) diff --git a/source/simulation2/components/CCmpVisualActor.cpp b/source/simulation2/components/CCmpVisualActor.cpp index f80868b441..da70133b64 100644 --- a/source/simulation2/components/CCmpVisualActor.cpp +++ b/source/simulation2/components/CCmpVisualActor.cpp @@ -261,7 +261,7 @@ public: if (m_Unit) { - CmpPtr cmpOwnership(GetSimContext(), GetEntityId()); + CmpPtr cmpOwnership(GetEntityHandle()); if (cmpOwnership) m_Unit->GetModel().SetPlayerID(cmpOwnership->GetOwner()); } @@ -525,7 +525,7 @@ void CCmpVisualActor::InitModel(const CParamNode& paramNode) if (paramNode.GetChild("SilhouetteOccluder").ToBool()) modelFlags |= MODELFLAG_SILHOUETTE_OCCLUDER; - CmpPtr cmpVision(GetSimContext(), GetEntityId()); + CmpPtr cmpVision(GetEntityHandle()); if (cmpVision && cmpVision->GetAlwaysVisible()) modelFlags |= MODELFLAG_IGNORE_LOS; @@ -566,7 +566,7 @@ void CCmpVisualActor::InitSelectionShapeDescriptor(const CParamNode& paramNode) } else if (shapeNode.GetChild("Footprint").IsOk()) { - CmpPtr cmpFootprint(GetSimContext(), GetEntityId()); + CmpPtr cmpFootprint(GetEntityHandle()); if (cmpFootprint) { ICmpFootprint::EShape fpShape; // fp stands for "footprint" @@ -643,7 +643,7 @@ void CCmpVisualActor::ReloadActor() // HACK: selection shape needs template data, but rather than storing all that data // in the component, we load the template here and pass it into a helper function - CmpPtr cmpTemplateManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpTemplateManager(GetSystemEntity()); const CParamNode* node = cmpTemplateManager->LoadLatestTemplate(GetEntityId()); ENSURE(node && node->GetChild("VisualActor").IsOk()); @@ -673,11 +673,11 @@ void CCmpVisualActor::Update(fixed UNUSED(turnLength)) // If we're in the special movement mode, select an appropriate animation if (!m_AnimRunThreshold.IsZero()) { - CmpPtr cmpPosition(GetSimContext(), GetEntityId()); + CmpPtr cmpPosition(GetEntityHandle()); if (!cmpPosition || !cmpPosition->IsInWorld()) return; - CmpPtr cmpUnitMotion(GetSimContext(), GetEntityId()); + CmpPtr cmpUnitMotion(GetEntityHandle()); if (!cmpUnitMotion) return; @@ -712,23 +712,23 @@ void CCmpVisualActor::Update(fixed UNUSED(turnLength)) void CCmpVisualActor::UpdateVisibility() { ICmpRangeManager::ELosVisibility oldVisibility = m_Visibility; - CmpPtr cmpPosition(GetSimContext(), GetEntityId()); + CmpPtr cmpPosition(GetEntityHandle()); if (cmpPosition && cmpPosition->IsInWorld()) { // The 'always visible' flag means we should always render the unit // (regardless of whether the LOS system thinks it's visible) - CmpPtr cmpVision(GetSimContext(), GetEntityId()); + CmpPtr cmpVision(GetEntityHandle()); if (cmpVision && cmpVision->GetAlwaysVisible()) m_Visibility = ICmpRangeManager::VIS_VISIBLE; else { - CmpPtr cmpRangeManager(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpRangeManager(GetSystemEntity()); // Uncomment the following lines to prevent the models from popping into existence // near the LOS boundary. Is rather resource intensive. //if (cmpVision->GetRetainInFog()) // m_Visibility = ICmpRangeManager::VIS_VISIBLE; //else - m_Visibility = cmpRangeManager->GetLosVisibility(GetEntityId(), + m_Visibility = cmpRangeManager->GetLosVisibility(GetEntityHandle(), GetSimContext().GetCurrentDisplayedPlayer()); } } @@ -738,7 +738,7 @@ void CCmpVisualActor::UpdateVisibility() if (m_Visibility != oldVisibility) { // Change the visibility of the visual actor's selectable if it has one. - CmpPtr cmpSelectable(GetSimContext(), GetEntityId()); + CmpPtr cmpSelectable(GetEntityHandle()); if (cmpSelectable) cmpSelectable->SetVisibility(m_Visibility == ICmpRangeManager::VIS_HIDDEN ? false : true); } @@ -750,7 +750,7 @@ void CCmpVisualActor::Interpolate(float frameTime, float frameOffset) return; // Disable rendering of the unit if it has no position - CmpPtr cmpPosition(GetSimContext(), GetEntityId()); + CmpPtr cmpPosition(GetEntityHandle()); if (!cmpPosition || !cmpPosition->IsInWorld()) return; else if (!m_PreviouslyRendered) @@ -778,7 +778,7 @@ void CCmpVisualActor::Interpolate(float frameTime, float frameOffset) // If this is a floating unit, we want it to start all the way under the terrain, // so find the difference between its current position and the terrain - CmpPtr cmpTerrain(GetSimContext(), SYSTEM_ENTITY); + CmpPtr cmpTerrain(GetSystemEntity()); if (floating && cmpTerrain) { CVector3D pos = transform.GetTranslation(); diff --git a/source/simulation2/components/ICmpRangeManager.h b/source/simulation2/components/ICmpRangeManager.h index 6592794c66..4a891459ab 100644 --- a/source/simulation2/components/ICmpRangeManager.h +++ b/source/simulation2/components/ICmpRangeManager.h @@ -303,6 +303,7 @@ public: * TODO: This is a hack to allow preview entities in FoW to return fogged instead of hidden, * see http://trac.wildfiregames.com/ticket/958 */ + virtual ELosVisibility GetLosVisibility(CEntityHandle ent, player_id_t player, bool forceRetainInFog = false) = 0; virtual ELosVisibility GetLosVisibility(entity_id_t ent, player_id_t player, bool forceRetainInFog = false) = 0; /** diff --git a/source/simulation2/helpers/Selection.cpp b/source/simulation2/helpers/Selection.cpp index 7ab3259afa..b6d0a0ba7c 100644 --- a/source/simulation2/helpers/Selection.cpp +++ b/source/simulation2/helpers/Selection.cpp @@ -43,16 +43,17 @@ std::vector EntitySelection::PickEntitiesAtPoint(CSimulation2& simu for (CSimulation2::InterfaceListUnordered::const_iterator it = ents.begin(); it != ents.end(); ++it) { entity_id_t ent = it->first; + CEntityHandle handle = it->second->GetEntityHandle(); // Check if this entity is only selectable in Atlas if (!allowEditorSelectables && static_cast(it->second)->IsEditorOnly()) continue; // Ignore entities hidden by LOS (or otherwise hidden, e.g. when not IsInWorld) - if (cmpRangeManager->GetLosVisibility(ent, player) == ICmpRangeManager::VIS_HIDDEN) + if (cmpRangeManager->GetLosVisibility(handle, player) == ICmpRangeManager::VIS_HIDDEN) continue; - CmpPtr cmpVisual(simulation.GetSimContext(), ent); + CmpPtr cmpVisual(handle); if (!cmpVisual) continue; @@ -121,17 +122,18 @@ std::vector EntitySelection::PickEntitiesInRect(CSimulation2& simul for (CSimulation2::InterfaceListUnordered::const_iterator it = ents.begin(); it != ents.end(); ++it) { entity_id_t ent = it->first; + CEntityHandle handle = it->second->GetEntityHandle(); // Check if this entity is only selectable in Atlas if (static_cast(it->second)->IsEditorOnly() && !allowEditorSelectables) continue; // Ignore entities hidden by LOS (or otherwise hidden, e.g. when not IsInWorld) - if (cmpRangeManager->GetLosVisibility(ent, owner) == ICmpRangeManager::VIS_HIDDEN) + if (cmpRangeManager->GetLosVisibility(handle, owner) == ICmpRangeManager::VIS_HIDDEN) continue; // Ignore entities not owned by 'owner' - CmpPtr cmpOwnership(simulation.GetSimContext(), ent); + CmpPtr cmpOwnership(handle); if (owner != INVALID_PLAYER && (!cmpOwnership || cmpOwnership->GetOwner() != owner)) continue; @@ -139,7 +141,7 @@ std::vector EntitySelection::PickEntitiesInRect(CSimulation2& simul // (We just use the centre position and not the whole bounding box, because maybe // that's better for users trying to select objects in busy areas) - CmpPtr cmpVisual(simulation.GetSimContext(), ent); + CmpPtr cmpVisual(handle); if (!cmpVisual) continue; @@ -175,6 +177,7 @@ std::vector EntitySelection::PickSimilarEntities(CSimulation2& simu for (CSimulation2::InterfaceListUnordered::const_iterator it = ents.begin(); it != ents.end(); ++it) { entity_id_t ent = it->first; + CEntityHandle handle = it->second->GetEntityHandle(); // Check if this entity is only selectable in Atlas if (static_cast(it->second)->IsEditorOnly() && !allowEditorSelectables) @@ -192,7 +195,7 @@ std::vector EntitySelection::PickSimilarEntities(CSimulation2& simu // Ignore entities hidden by LOS (or otherwise hidden, e.g. when not IsInWorld) // In this case, the checking is done to avoid selecting garrisoned units - if (cmpRangeManager->GetLosVisibility(ent, owner) == ICmpRangeManager::VIS_HIDDEN) + if (cmpRangeManager->GetLosVisibility(handle, owner) == ICmpRangeManager::VIS_HIDDEN) continue; // Ignore entities not owned by 'owner' diff --git a/source/simulation2/serialization/SerializeTemplates.h b/source/simulation2/serialization/SerializeTemplates.h index 44fdf014d1..fcef0acfa8 100644 --- a/source/simulation2/serialization/SerializeTemplates.h +++ b/source/simulation2/serialization/SerializeTemplates.h @@ -68,6 +68,18 @@ struct SerializeMap } } + template + void operator()(ISerializer& serialize, const char* UNUSED(name), std::map& value, C& context) + { + size_t len = value.size(); + serialize.NumberU32_Unbounded("length", (u32)len); + for (typename std::map::iterator it = value.begin(); it != value.end(); ++it) + { + KS()(serialize, "key", it->first); + VS()(serialize, "value", it->second, context); + } + } + template void operator()(IDeserializer& deserialize, const char* UNUSED(name), M& value) { @@ -85,6 +97,24 @@ struct SerializeMap value.insert(std::make_pair(k, v)); } } + + template + void operator()(IDeserializer& deserialize, const char* UNUSED(name), M& value, C& context) + { + typedef typename M::key_type K; + typedef typename M::value_type::second_type V; // M::data_type gives errors with gcc + value.clear(); + u32 len; + deserialize.NumberU32_Unbounded("length", len); + for (size_t i = 0; i < len; ++i) + { + K k; + V v; + KS()(deserialize, "key", k); + VS()(deserialize, "value", v, context); + value.insert(std::make_pair(k, v)); + } + } }; // We have to order the map before serializing to make things consistent diff --git a/source/simulation2/system/CmpPtr.h b/source/simulation2/system/CmpPtr.h index 5ecc8fba95..f0cbcb43b7 100644 --- a/source/simulation2/system/CmpPtr.h +++ b/source/simulation2/system/CmpPtr.h @@ -74,6 +74,15 @@ public: m = static_cast(QueryInterface(simulation, ent, T::GetInterfaceId())); } + CmpPtr(CEntityHandle ent) + { + SEntityComponentCache* cache = ent.GetComponentCache(); + if (cache != NULL && T::GetInterfaceId() < (int)cache->numInterfaces) + m = static_cast(cache->interfaces[T::GetInterfaceId()]); + else + m = NULL; + } + T* operator->() { return m; } operator bool_type() const diff --git a/source/simulation2/system/ComponentManager.cpp b/source/simulation2/system/ComponentManager.cpp index 7a0e519bc7..e83d9898cb 100644 --- a/source/simulation2/system/ComponentManager.cpp +++ b/source/simulation2/system/ComponentManager.cpp @@ -468,6 +468,13 @@ void CComponentManager::ResetState() m_ComponentsByTypeId.clear(); + // Delete all SEntityComponentCaches + std::map::iterator ccit = m_ComponentCaches.begin(); + for (; ccit != m_ComponentCaches.end(); ++ccit) + free(ccit->second); + m_ComponentCaches.clear(); + m_SystemEntity = CEntityHandle(); + m_DestructionQueue.clear(); // Reset IDs @@ -573,7 +580,7 @@ entity_id_t CComponentManager::AllocateNewEntity(entity_id_t preferredId) return id; } -bool CComponentManager::AddComponent(entity_id_t ent, ComponentTypeId cid, const CParamNode& paramNode) +bool CComponentManager::AddComponent(CEntityHandle ent, ComponentTypeId cid, const CParamNode& paramNode) { IComponent* component = ConstructComponent(ent, cid); if (!component) @@ -583,7 +590,7 @@ bool CComponentManager::AddComponent(entity_id_t ent, ComponentTypeId cid, const return true; } -IComponent* CComponentManager::ConstructComponent(entity_id_t ent, ComponentTypeId cid) +IComponent* CComponentManager::ConstructComponent(CEntityHandle ent, ComponentTypeId cid) { std::map::const_iterator it = m_ComponentTypesById.find(cid); if (it == m_ComponentTypesById.end()) @@ -597,7 +604,7 @@ IComponent* CComponentManager::ConstructComponent(entity_id_t ent, ComponentType ENSURE((size_t)ct.iid < m_ComponentsByInterface.size()); boost::unordered_map& emap1 = m_ComponentsByInterface[ct.iid]; - if (emap1.find(ent) != emap1.end()) + if (emap1.find(ent.GetId()) != emap1.end()) { LOGERROR(L"Multiple components for interface %d", ct.iid); return NULL; @@ -621,30 +628,75 @@ IComponent* CComponentManager::ConstructComponent(entity_id_t ent, ComponentType IComponent* component = ct.alloc(m_ScriptInterface, obj); ENSURE(component); - component->SetEntityId(ent); + component->SetEntityHandle(ent); component->SetSimContext(m_SimContext); // Store a reference to the new component - emap1.insert(std::make_pair(ent, component)); - emap2.insert(std::make_pair(ent, component)); + emap1.insert(std::make_pair(ent.GetId(), component)); + emap2.insert(std::make_pair(ent.GetId(), component)); // TODO: We need to more careful about this - if an entity is constructed by a component // while we're iterating over all components, this will invalidate the iterators and everything // will break. // We probably need some kind of delayed addition, so they get pushed onto a queue and then // inserted into the world later on. (Be careful about immediation deletion in that case, too.) + SEntityComponentCache* cache = ent.GetComponentCache(); + ENSURE(cache != NULL && ct.iid < (int)cache->numInterfaces && cache->interfaces[ct.iid] == NULL); + cache->interfaces[ct.iid] = component; + return component; } -void CComponentManager::AddMockComponent(entity_id_t ent, InterfaceId iid, IComponent& component) +void CComponentManager::AddMockComponent(CEntityHandle ent, InterfaceId iid, IComponent& component) { // Just add it into the by-interface map, not the by-component-type map, // so it won't be considered for messages or deletion etc boost::unordered_map& emap1 = m_ComponentsByInterface.at(iid); - if (emap1.find(ent) != emap1.end()) + if (emap1.find(ent.GetId()) != emap1.end()) debug_warn(L"Multiple components for interface"); - emap1.insert(std::make_pair(ent, &component)); + emap1.insert(std::make_pair(ent.GetId(), &component)); + + SEntityComponentCache* cache = ent.GetComponentCache(); + ENSURE(cache != NULL && iid < (int)cache->numInterfaces && cache->interfaces[iid] == NULL); + cache->interfaces[iid] = &component; +} + +CEntityHandle CComponentManager::AllocateEntityHandle(entity_id_t ent) +{ + // Interface IDs start at 1, and SEntityComponentCache is defined with a 1-sized array, + // so we need space for an extra m_InterfaceIdsByName.size() items + SEntityComponentCache* cache = (SEntityComponentCache*)calloc(1, + sizeof(SEntityComponentCache) + sizeof(IComponent*) * m_InterfaceIdsByName.size()); + ENSURE(cache != NULL); + cache->numInterfaces = m_InterfaceIdsByName.size() + 1; + + ENSURE(m_ComponentCaches.find(ent) == m_ComponentCaches.end()); + m_ComponentCaches[ent] = cache; + + return CEntityHandle(ent, cache); +} + +CEntityHandle CComponentManager::LookupEntityHandle(entity_id_t ent, bool allowCreate) +{ + std::map::iterator it; + it = m_ComponentCaches.find(ent); + if (it == m_ComponentCaches.end()) + { + if (allowCreate) + return AllocateEntityHandle(ent); + else + return CEntityHandle(ent, NULL); + } + else + return CEntityHandle(ent, it->second); +} + +void CComponentManager::InitSystemEntity() +{ + ENSURE(m_SystemEntity.GetId() == INVALID_ENTITY); + m_SystemEntity = AllocateEntityHandle(SYSTEM_ENTITY); + m_SimContext.SetSystemEntity(m_SystemEntity); } entity_id_t CComponentManager::AddEntity(const std::wstring& templateName, entity_id_t ent) @@ -662,6 +714,8 @@ entity_id_t CComponentManager::AddEntity(const std::wstring& templateName, entit if (!tmpl) return INVALID_ENTITY; // LoadTemplate will have reported the error + CEntityHandle handle = AllocateEntityHandle(ent); + // Construct a component for each child of the root element const CParamNode::ChildrenMap& tmplChilds = tmpl->GetChildren(); for (CParamNode::ChildrenMap::const_iterator it = tmplChilds.begin(); it != tmplChilds.end(); ++it) @@ -677,12 +731,11 @@ entity_id_t CComponentManager::AddEntity(const std::wstring& templateName, entit return INVALID_ENTITY; } - if (!AddComponent(ent, cid, it->second)) + if (!AddComponent(handle, cid, it->second)) { LOGERROR(L"Failed to construct component type name '%hs' in entity template '%ls'", it->first.c_str(), templateName.c_str()); return INVALID_ENTITY; } - // TODO: maybe we should delete already-constructed components if one of them fails? } @@ -699,7 +752,7 @@ void CComponentManager::DestroyComponentsSoon(entity_id_t ent) void CComponentManager::FlushDestroyedComponents() { - while(!m_DestructionQueue.empty()) + while (!m_DestructionQueue.empty()) { // Make a copy of the destruction queue, so that the iterators won't be invalidated if the // CMessageDestroy handlers try to destroy more entities themselves @@ -709,6 +762,7 @@ void CComponentManager::FlushDestroyedComponents() for (std::vector::iterator it = queue.begin(); it != queue.end(); ++it) { entity_id_t ent = *it; + CEntityHandle handle = LookupEntityHandle(ent); CMessageDestroy msg(ent); PostMessage(ent, msg); @@ -723,9 +777,13 @@ void CComponentManager::FlushDestroyedComponents() eit->second->Deinit(); m_ComponentTypesById[iit->first].dealloc(eit->second); iit->second.erase(ent); + handle.GetComponentCache()->interfaces[m_ComponentTypesById[iit->first].iid] = NULL; } } + free(handle.GetComponentCache()); + m_ComponentCaches.erase(ent); + // Remove from m_ComponentsByInterface std::vector >::iterator ifcit = m_ComponentsByInterface.begin(); for (; ifcit != m_ComponentsByInterface.end(); ++ifcit) diff --git a/source/simulation2/system/ComponentManager.h b/source/simulation2/system/ComponentManager.h index 8e02023116..50846deb99 100644 --- a/source/simulation2/system/ComponentManager.h +++ b/source/simulation2/system/ComponentManager.h @@ -123,6 +123,22 @@ public: */ std::string LookupComponentTypeName(ComponentTypeId cid) const; + /** + * Set up an empty SYSTEM_ENTITY. Must be called after ResetState() and before GetSystemEntity(). + */ + void InitSystemEntity(); + + /** + * Returns a CEntityHandle with id SYSTEM_ENTITY. + */ + CEntityHandle GetSystemEntity() { ASSERT(m_SystemEntity.GetId() == SYSTEM_ENTITY); return m_SystemEntity; } + + /** + * Returns a CEntityHandle with id @p ent. + * If @p allowCreate is true and there is no existing CEntityHandle, a new handle will be allocated. + */ + CEntityHandle LookupEntityHandle(entity_id_t ent, bool allowCreate = false); + /** * Returns a new entity ID that has never been used before. * This affects the simulation state so it must only be called in network-synchronised ways. @@ -148,7 +164,7 @@ public: * * @return true on success; false on failure, and logs an error message */ - bool AddComponent(entity_id_t ent, ComponentTypeId cid, const CParamNode& paramNode); + bool AddComponent(CEntityHandle ent, ComponentTypeId cid, const CParamNode& paramNode); /** * Adds an externally-created component, so that it is returned by QueryInterface @@ -156,14 +172,14 @@ public: * (This is intended for unit tests that need to add mock objects the tested components * expect to exist.) */ - void AddMockComponent(entity_id_t ent, InterfaceId iid, IComponent& component); + void AddMockComponent(CEntityHandle ent, InterfaceId iid, IComponent& component); /** * Allocates a component object of type 'cid', and attaches it to entity 'ent'. * (The component's Init is not called here - either Init or Deserialize must be called * before using the returned object.) */ - IComponent* ConstructComponent(entity_id_t ent, ComponentTypeId cid); + IComponent* ConstructComponent(CEntityHandle ent, ComponentTypeId cid); /** * Constructs an entity based on the given template, and adds it the world with @@ -252,8 +268,12 @@ private: ComponentTypeId GetScriptWrapper(InterfaceId iid); + CEntityHandle AllocateEntityHandle(entity_id_t ent); + ScriptInterface m_ScriptInterface; - const CSimContext& m_SimContext; + CSimContext& m_SimContext; + + CEntityHandle m_SystemEntity; ComponentTypeId m_CurrentComponent; // used when loading component types bool m_CurrentlyHotloading; @@ -269,6 +289,8 @@ private: std::map m_MessageTypeNamesById; std::map m_InterfaceIdsByName; + std::map m_ComponentCaches; + // TODO: maintaining both ComponentsBy* is nasty; can we get rid of one, // while keeping QueryInterface and PostMessage sufficiently efficient? diff --git a/source/simulation2/system/ComponentManagerSerialization.cpp b/source/simulation2/system/ComponentManagerSerialization.cpp index c8c7b9d343..07e397d9de 100644 --- a/source/simulation2/system/ComponentManagerSerialization.cpp +++ b/source/simulation2/system/ComponentManagerSerialization.cpp @@ -260,6 +260,7 @@ bool CComponentManager::DeserializeState(std::istream& stream) CStdDeserializer deserializer(m_ScriptInterface, stream); ResetState(); + InitSystemEntity(); std::string rng; deserializer.StringASCII("rng", rng, 0, 32); @@ -292,7 +293,7 @@ bool CComponentManager::DeserializeState(std::istream& stream) { entity_id_t ent; deserializer.NumberU32_Unbounded("entity id", ent); - IComponent* component = ConstructComponent(ent, ctid); + IComponent* component = ConstructComponent(LookupEntityHandle(ent, true), ctid); if (!component) return false; diff --git a/source/simulation2/system/ComponentTest.h b/source/simulation2/system/ComponentTest.h index f2a0c487c7..a9b86d3966 100644 --- a/source/simulation2/system/ComponentTest.h +++ b/source/simulation2/system/ComponentTest.h @@ -76,9 +76,19 @@ public: { TS_ASSERT(m_Cmp == NULL); + CEntityHandle handle; + if (ent == SYSTEM_ENTITY) + { + m_ComponentManager.InitSystemEntity(); + handle = m_ComponentManager.GetSystemEntity(); + m_Context.SetSystemEntity(handle); + } + else + handle = m_ComponentManager.LookupEntityHandle(ent, true); + m_Cid = cid; TS_ASSERT_EQUALS(CParamNode::LoadXMLString(m_Param, ("" + xml + "").c_str()), PSRETURN_OK); - TS_ASSERT(m_ComponentManager.AddComponent(ent, m_Cid, m_Param.GetChild("test"))); + TS_ASSERT(m_ComponentManager.AddComponent(handle, m_Cid, m_Param.GetChild("test"))); m_Cmp = m_ComponentManager.QueryInterface(ent, T::GetInterfaceId()); TS_ASSERT(m_Cmp != NULL); return static_cast (m_Cmp); @@ -86,7 +96,17 @@ public: void AddMock(entity_id_t ent, EInterfaceId iid, IComponent& component) { - m_ComponentManager.AddMockComponent(ent, iid, component); + CEntityHandle handle; + if (ent == SYSTEM_ENTITY) + { + m_ComponentManager.InitSystemEntity(); + handle = m_ComponentManager.GetSystemEntity(); + m_Context.SetSystemEntity(handle); + } + else + handle = m_ComponentManager.LookupEntityHandle(ent, true); + + m_ComponentManager.AddMockComponent(handle, iid, component); } void HandleMessage(IComponent* cmp, const CMessage& msg, bool global) @@ -101,8 +121,6 @@ public: */ void Roundtrip(bool verbose = false) { - entity_id_t ent = 1; - std::stringstream dbgstr1; CDebugSerializer dbg1(GetScriptInterface(), dbgstr1); m_Cmp->Serialize(dbg1); @@ -121,6 +139,8 @@ public: // (We should never need to add any mock objects etc to test2, since deserialization // mustn't depend on other components already existing) + CEntityHandle ent = test2.m_ComponentManager.LookupEntityHandle(10, true); + CStdDeserializer stdde2(test2.GetScriptInterface(), stdstr1); IComponent* cmp2 = test2.m_ComponentManager.ConstructComponent(ent, m_Cid); diff --git a/source/simulation2/system/Entity.h b/source/simulation2/system/Entity.h index e455b84910..672290296a 100644 --- a/source/simulation2/system/Entity.h +++ b/source/simulation2/system/Entity.h @@ -21,6 +21,8 @@ #include "lib/types.h" +class IComponent; + /** * Entity ID type. * ID numbers are never reused within a simulation run. @@ -58,5 +60,38 @@ const entity_id_t SYSTEM_ENTITY = 1; #define ENTITY_IS_LOCAL(id) (((id) & ENTITY_TAGMASK) == ENTITY_TAGMASK) const entity_id_t FIRST_LOCAL_ENTITY = ENTITY_TAGMASK; +struct SEntityComponentCache +{ + size_t numInterfaces; + IComponent* interfaces[1]; /* variable length array */ +}; + +/** + * Object wrapping an entity_id_t, with a SEntityComponentCache to support fast + * QueryInterface() / CmpPtr<>() calls. + * + * Components can use IComponent::GetSystemEntity() and IComponent::GetEntityHandle() + * to get handles to SYSTEM_ENTITY and themselves, and then pass those handles around. + * + * Be careful not to store a CEntityHandle for longer than the lifetime of the entity + * (listen to MT_Destroy messages to know when to release it) - otherwise the handle will + * contain a dangling pointer and will probably crash. + */ +class CEntityHandle +{ +public: + CEntityHandle() : m_Id(0), m_ComponentCache(NULL) { } + CEntityHandle(entity_id_t id, SEntityComponentCache* componentCache) + : m_Id(id), m_ComponentCache(componentCache) + { + } + + entity_id_t GetId() const { return m_Id; } + SEntityComponentCache* GetComponentCache() const { return m_ComponentCache; } + +private: + entity_id_t m_Id; + SEntityComponentCache* m_ComponentCache; +}; #endif // INCLUDED_SIM2_ENTITY diff --git a/source/simulation2/system/IComponent.h b/source/simulation2/system/IComponent.h index 47c1e122ca..6fcfe0fd6f 100644 --- a/source/simulation2/system/IComponent.h +++ b/source/simulation2/system/IComponent.h @@ -21,11 +21,11 @@ #include "Components.h" #include "Message.h" #include "Entity.h" +#include "SimContext.h" #include "scriptinterface/ScriptTypes.h" class CParamNode; -class CSimContext; class CMessage; class ISerializer; class IDeserializer; @@ -42,8 +42,12 @@ public: virtual void HandleMessage(const CMessage& msg, bool global); - entity_id_t GetEntityId() const { return m_EntityId; } - void SetEntityId(entity_id_t ent) { m_EntityId = ent; } + CEntityHandle GetEntityHandle() const { return m_EntityHandle; } + void SetEntityHandle(CEntityHandle ent) { m_EntityHandle = ent; } + + entity_id_t GetEntityId() const { return m_EntityHandle.GetId(); } + + CEntityHandle GetSystemEntity() const { return m_SimContext->GetSystemEntity(); } const CSimContext& GetSimContext() const { return *m_SimContext; } void SetSimContext(const CSimContext& context) { m_SimContext = &context; } @@ -56,7 +60,7 @@ public: virtual jsval GetJSInstance() const; private: - entity_id_t m_EntityId; + CEntityHandle m_EntityHandle; const CSimContext* m_SimContext; }; diff --git a/source/simulation2/system/SimContext.h b/source/simulation2/system/SimContext.h index 134fdbe71f..c9317b56c9 100644 --- a/source/simulation2/system/SimContext.h +++ b/source/simulation2/system/SimContext.h @@ -18,6 +18,8 @@ #ifndef INCLUDED_SIMCONTEXT #define INCLUDED_SIMCONTEXT +#include "Entity.h" + class CComponentManager; class CUnitManager; class CTerrain; @@ -43,6 +45,9 @@ public: ScriptInterface& GetScriptInterface() const; + void SetSystemEntity(CEntityHandle ent) { m_SystemEntity = ent; } + CEntityHandle GetSystemEntity() const { ASSERT(m_SystemEntity.GetId() == SYSTEM_ENTITY); return m_SystemEntity; } + /** * Returns the player ID that the current display is being rendered for. * Currently relies on g_Game being initialised (evil globals...) @@ -54,6 +59,8 @@ private: CUnitManager* m_UnitManager; CTerrain* m_Terrain; + CEntityHandle m_SystemEntity; + friend class CSimulation2Impl; }; diff --git a/source/simulation2/tests/test_CmpTemplateManager.h b/source/simulation2/tests/test_CmpTemplateManager.h index 9d1fd085e7..822eb26d43 100644 --- a/source/simulation2/tests/test_CmpTemplateManager.h +++ b/source/simulation2/tests/test_CmpTemplateManager.h @@ -56,9 +56,10 @@ public: man.LoadComponentTypes(); entity_id_t ent1 = 1, ent2 = 2; + CEntityHandle hnd1 = man.LookupEntityHandle(ent1, true); CParamNode noParam; - TS_ASSERT(man.AddComponent(ent1, CID_TemplateManager, noParam)); + TS_ASSERT(man.AddComponent(hnd1, CID_TemplateManager, noParam)); ICmpTemplateManager* tempMan = static_cast (man.QueryInterface(ent1, IID_TemplateManager)); TS_ASSERT(tempMan != NULL); @@ -117,9 +118,10 @@ public: man.LoadComponentTypes(); entity_id_t ent1 = 1, ent2 = 2; + CEntityHandle hnd1 = man.LookupEntityHandle(ent1, true); CParamNode noParam; - TS_ASSERT(man.AddComponent(ent1, CID_TemplateManager, noParam)); + TS_ASSERT(man.AddComponent(hnd1, CID_TemplateManager, noParam)); ICmpTemplateManager* tempMan = static_cast (man.QueryInterface(ent1, IID_TemplateManager)); TS_ASSERT(tempMan != NULL); @@ -154,9 +156,10 @@ public: man.LoadComponentTypes(); entity_id_t ent1 = 1, ent2 = 2; + CEntityHandle hnd1 = man.LookupEntityHandle(ent1, true); CParamNode noParam; - TS_ASSERT(man.AddComponent(ent1, CID_TemplateManager, noParam)); + TS_ASSERT(man.AddComponent(hnd1, CID_TemplateManager, noParam)); ICmpTemplateManager* tempMan = static_cast (man.QueryInterface(ent1, IID_TemplateManager)); TS_ASSERT(tempMan != NULL); @@ -185,9 +188,10 @@ public: man.LoadComponentTypes(); entity_id_t ent1 = 1, ent2 = 2; + CEntityHandle hnd1 = man.LookupEntityHandle(ent1, true); CParamNode noParam; - TS_ASSERT(man.AddComponent(ent1, CID_TemplateManager, noParam)); + TS_ASSERT(man.AddComponent(hnd1, CID_TemplateManager, noParam)); ICmpTemplateManager* tempMan = static_cast (man.QueryInterface(ent1, IID_TemplateManager)); TS_ASSERT(tempMan != NULL); diff --git a/source/simulation2/tests/test_ComponentManager.h b/source/simulation2/tests/test_ComponentManager.h index a4e66a7eaf..5fdbdf3901 100644 --- a/source/simulation2/tests/test_ComponentManager.h +++ b/source/simulation2/tests/test_ComponentManager.h @@ -101,19 +101,20 @@ public: CSimContext context; CComponentManager man(context); man.LoadComponentTypes(); + CEntityHandle hnd1 = man.AllocateEntityHandle(1); CParamNode noParam; - TS_ASSERT(man.AddComponent(1, CID_Test1A, noParam)); + TS_ASSERT(man.AddComponent(hnd1, CID_Test1A, noParam)); { TestLogger log; - TS_ASSERT(! man.AddComponent(1, 12345, noParam)); + TS_ASSERT(! man.AddComponent(hnd1, 12345, noParam)); TS_ASSERT_WSTR_CONTAINS(log.GetOutput(), L"ERROR: Invalid component id 12345"); } { TestLogger log; - TS_ASSERT(! man.AddComponent(1, CID_Test1B, noParam)); + TS_ASSERT(! man.AddComponent(hnd1, CID_Test1B, noParam)); TS_ASSERT_WSTR_CONTAINS(log.GetOutput(), L"ERROR: Multiple components for interface "); } } @@ -125,18 +126,20 @@ public: man.LoadComponentTypes(); entity_id_t ent1 = 1, ent2 = 2; + CEntityHandle hnd1 = man.AllocateEntityHandle(ent1); + CEntityHandle hnd2 = man.AllocateEntityHandle(ent2); CParamNode noParam; - man.AddComponent(ent1, CID_Test1A, noParam); + man.AddComponent(hnd1, CID_Test1A, noParam); TS_ASSERT(man.QueryInterface(ent1, IID_Test1) != NULL); TS_ASSERT(man.QueryInterface(ent1, IID_Test2) == NULL); TS_ASSERT(man.QueryInterface(ent2, IID_Test1) == NULL); TS_ASSERT(man.QueryInterface(ent2, IID_Test2) == NULL); - man.AddComponent(ent2, CID_Test1B, noParam); + man.AddComponent(hnd2, CID_Test1B, noParam); TS_ASSERT(man.QueryInterface(ent2, IID_Test1) != NULL); TS_ASSERT(man.QueryInterface(ent2, IID_Test2) == NULL); - man.AddComponent(ent2, CID_Test2A, noParam); + man.AddComponent(hnd2, CID_Test2A, noParam); TS_ASSERT(man.QueryInterface(ent2, IID_Test1) != NULL); TS_ASSERT(man.QueryInterface(ent2, IID_Test2) != NULL); } @@ -148,13 +151,17 @@ public: man.LoadComponentTypes(); entity_id_t ent1 = 1, ent2 = 2, ent3 = 3, ent4 = 4; + CEntityHandle hnd1 = man.AllocateEntityHandle(ent1); + CEntityHandle hnd2 = man.AllocateEntityHandle(ent2); + CEntityHandle hnd3 = man.AllocateEntityHandle(ent3); + CEntityHandle hnd4 = man.AllocateEntityHandle(ent4); CParamNode noParam; - man.AddComponent(ent1, CID_Test1A, noParam); - man.AddComponent(ent2, CID_Test1B, noParam); - man.AddComponent(ent3, CID_Test2A, noParam); - man.AddComponent(ent4, CID_Test1A, noParam); - man.AddComponent(ent4, CID_Test2A, noParam); + man.AddComponent(hnd1, CID_Test1A, noParam); + man.AddComponent(hnd2, CID_Test1B, noParam); + man.AddComponent(hnd3, CID_Test2A, noParam); + man.AddComponent(hnd4, CID_Test1A, noParam); + man.AddComponent(hnd4, CID_Test2A, noParam); CMessageTurnStart msg1; CMessageUpdate msg2(fixed::FromInt(100)); @@ -218,13 +225,15 @@ public: man.LoadComponentTypes(); entity_id_t ent1 = 1, ent2 = 2; + CEntityHandle hnd1 = man.AllocateEntityHandle(ent1); + CEntityHandle hnd2 = man.AllocateEntityHandle(ent2); CParamNode noParam; CParamNode testParam; TS_ASSERT_EQUALS(CParamNode::LoadXMLString(testParam, "1234"), PSRETURN_OK); - man.AddComponent(ent1, CID_Test1A, noParam); - man.AddComponent(ent2, CID_Test1A, testParam); + man.AddComponent(hnd1, CID_Test1A, noParam); + man.AddComponent(hnd2, CID_Test1A, testParam); TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent1, IID_Test1))->GetX(), 11000); TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent2, IID_Test1))->GetX(), 1234); @@ -241,12 +250,15 @@ public: TS_ASSERT_EQUALS(man.LookupCID("TestScript1B"), (int)CID__LastNative+1); entity_id_t ent1 = 1, ent2 = 2, ent3 = 3; + CEntityHandle hnd1 = man.AllocateEntityHandle(ent1); + CEntityHandle hnd2 = man.AllocateEntityHandle(ent2); + CEntityHandle hnd3 = man.AllocateEntityHandle(ent3); CParamNode noParam; - man.AddComponent(ent1, CID_Test1A, noParam); - man.AddComponent(ent2, man.LookupCID("TestScript1A"), noParam); - man.AddComponent(ent3, man.LookupCID("TestScript1B"), noParam); - man.AddComponent(ent3, man.LookupCID("TestScript2A"), noParam); + man.AddComponent(hnd1, CID_Test1A, noParam); + man.AddComponent(hnd2, man.LookupCID("TestScript1A"), noParam); + man.AddComponent(hnd3, man.LookupCID("TestScript1B"), noParam); + man.AddComponent(hnd3, man.LookupCID("TestScript2A"), noParam); TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent1, IID_Test1))->GetX(), 11000); TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent2, IID_Test1))->GetX(), 101000); @@ -280,9 +292,10 @@ public: TS_ASSERT(man.LoadScript(L"simulation/helpers/test-helper.js")); entity_id_t ent1 = 1; + CEntityHandle hnd1 = man.AllocateEntityHandle(ent1); CParamNode noParam; - man.AddComponent(ent1, man.LookupCID("TestScript1_Helper"), noParam); + man.AddComponent(hnd1, man.LookupCID("TestScript1_Helper"), noParam); TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent1, IID_Test1))->GetX(), 3); } @@ -295,9 +308,10 @@ public: TS_ASSERT(man.LoadScript(L"simulation/components/test-global-helper.js")); entity_id_t ent1 = 1; + CEntityHandle hnd1 = man.AllocateEntityHandle(ent1); CParamNode noParam; - man.AddComponent(ent1, man.LookupCID("TestScript1_GlobalHelper"), noParam); + man.AddComponent(hnd1, man.LookupCID("TestScript1_GlobalHelper"), noParam); TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent1, IID_Test1))->GetX(), 2); } @@ -311,10 +325,11 @@ public: TS_ASSERT(man.LoadScript(L"simulation/components/test-interface.js")); entity_id_t ent1 = 1; + CEntityHandle hnd1 = man.AllocateEntityHandle(ent1); CParamNode noParam; - man.AddComponent(ent1, man.LookupCID("TestScript1_Interface"), noParam); - man.AddComponent(ent1, man.LookupCID("TestScript2_Interface"), noParam); + man.AddComponent(hnd1, man.LookupCID("TestScript1_Interface"), noParam); + man.AddComponent(hnd1, man.LookupCID("TestScript2_Interface"), noParam); TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent1, IID_Test1))->GetX(), 1000 + IID__LastNative); } @@ -345,10 +360,12 @@ public: TS_ASSERT(man.LoadScript(L"simulation/components/test-entityid.js")); entity_id_t ent1 = 1, ent2 = 234; + CEntityHandle hnd1 = man.AllocateEntityHandle(ent1); + CEntityHandle hnd2 = man.AllocateEntityHandle(ent2); CParamNode noParam; - man.AddComponent(ent1, man.LookupCID("TestScript1A"), noParam); - man.AddComponent(ent2, man.LookupCID("TestScript1A"), noParam); + man.AddComponent(hnd1, man.LookupCID("TestScript1A"), noParam); + man.AddComponent(hnd2, man.LookupCID("TestScript1A"), noParam); TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent1, IID_Test1))->GetX(), (int)ent1); TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent2, IID_Test1))->GetX(), (int)ent2); @@ -362,12 +379,14 @@ public: TS_ASSERT(man.LoadScript(L"simulation/components/test-query.js")); entity_id_t ent1 = 1, ent2 = 2; + CEntityHandle hnd1 = man.AllocateEntityHandle(ent1); + CEntityHandle hnd2 = man.AllocateEntityHandle(ent2); CParamNode noParam; - man.AddComponent(ent1, man.LookupCID("TestScript1A"), noParam); - man.AddComponent(ent1, man.LookupCID("TestScript2A"), noParam); - man.AddComponent(ent2, man.LookupCID("TestScript1A"), noParam); - man.AddComponent(ent2, CID_Test2A, noParam); + man.AddComponent(hnd1, man.LookupCID("TestScript1A"), noParam); + man.AddComponent(hnd1, man.LookupCID("TestScript2A"), noParam); + man.AddComponent(hnd2, man.LookupCID("TestScript1A"), noParam); + man.AddComponent(hnd2, CID_Test2A, noParam); TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent1, IID_Test1))->GetX(), 400); TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent2, IID_Test1))->GetX(), 21000); @@ -380,14 +399,16 @@ public: man.LoadComponentTypes(); TS_ASSERT(man.LoadScript(L"simulation/components/test-addentity.js")); TS_ASSERT(man.LoadScript(L"simulation/components/addentity/test-addentity.js")); + man.InitSystemEntity(); entity_id_t ent1 = man.AllocateNewEntity(); entity_id_t ent2 = ent1 + 2; + CEntityHandle hnd1 = man.AllocateEntityHandle(ent1); CParamNode noParam; - TS_ASSERT(man.AddComponent(SYSTEM_ENTITY, CID_TemplateManager, noParam)); + TS_ASSERT(man.AddComponent(man.GetSystemEntity(), CID_TemplateManager, noParam)); - TS_ASSERT(man.AddComponent(ent1, man.LookupCID("TestScript1_AddEntity"), noParam)); + TS_ASSERT(man.AddComponent(hnd1, man.LookupCID("TestScript1_AddEntity"), noParam)); TS_ASSERT(man.QueryInterface(ent2, IID_Test1) == NULL); TS_ASSERT(man.QueryInterface(ent2, IID_Test2) == NULL); @@ -411,14 +432,16 @@ public: man.LoadComponentTypes(); TS_ASSERT(man.LoadScript(L"simulation/components/test-addentity.js")); TS_ASSERT(man.LoadScript(L"simulation/components/addentity/test-addentity.js")); + man.InitSystemEntity(); - entity_id_t ent1 = 1; + entity_id_t ent1 = man.AllocateNewEntity(); entity_id_t ent2 = man.AllocateNewLocalEntity() + 2; + CEntityHandle hnd1 = man.AllocateEntityHandle(ent1); CParamNode noParam; - TS_ASSERT(man.AddComponent(SYSTEM_ENTITY, CID_TemplateManager, noParam)); + TS_ASSERT(man.AddComponent(man.GetSystemEntity(), CID_TemplateManager, noParam)); - TS_ASSERT(man.AddComponent(ent1, man.LookupCID("TestScript1_AddLocalEntity"), noParam)); + TS_ASSERT(man.AddComponent(hnd1, man.LookupCID("TestScript1_AddLocalEntity"), noParam)); TS_ASSERT(man.QueryInterface(ent2, IID_Test1) == NULL); TS_ASSERT(man.QueryInterface(ent2, IID_Test2) == NULL); @@ -443,9 +466,10 @@ public: TS_ASSERT(man.LoadScript(L"simulation/components/test-destroyentity.js")); entity_id_t ent1 = 10; + CEntityHandle hnd1 = man.AllocateEntityHandle(ent1); CParamNode noParam; - TS_ASSERT(man.AddComponent(ent1, man.LookupCID("TestScript1_DestroyEntity"), noParam)); + TS_ASSERT(man.AddComponent(hnd1, man.LookupCID("TestScript1_DestroyEntity"), noParam)); TS_ASSERT(man.QueryInterface(ent1, IID_Test1) != NULL); static_cast (man.QueryInterface(ent1, IID_Test1))->GetX(); @@ -462,13 +486,16 @@ public: TS_ASSERT(man.LoadScript(L"simulation/components/test-msg.js")); entity_id_t ent1 = 1, ent2 = 2, ent3 = 3; + CEntityHandle hnd1 = man.AllocateEntityHandle(ent1); + CEntityHandle hnd2 = man.AllocateEntityHandle(ent2); + CEntityHandle hnd3 = man.AllocateEntityHandle(ent3); CParamNode noParam; - man.AddComponent(ent1, man.LookupCID("TestScript1A"), noParam); - man.AddComponent(ent1, man.LookupCID("TestScript2A"), noParam); - man.AddComponent(ent2, man.LookupCID("TestScript1A"), noParam); - man.AddComponent(ent2, CID_Test2A, noParam); - man.AddComponent(ent3, man.LookupCID("TestScript1B"), noParam); + man.AddComponent(hnd1, man.LookupCID("TestScript1A"), noParam); + man.AddComponent(hnd1, man.LookupCID("TestScript2A"), noParam); + man.AddComponent(hnd2, man.LookupCID("TestScript1A"), noParam); + man.AddComponent(hnd2, CID_Test2A, noParam); + man.AddComponent(hnd3, man.LookupCID("TestScript1B"), noParam); TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent1, IID_Test1))->GetX(), 100); TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent2, IID_Test1))->GetX(), 100); @@ -492,13 +519,15 @@ public: TS_ASSERT(man.LoadScript(L"simulation/components/test-param.js")); entity_id_t ent1 = 1, ent2 = 2; + CEntityHandle hnd1 = man.AllocateEntityHandle(ent1); + CEntityHandle hnd2 = man.AllocateEntityHandle(ent2); CParamNode noParam; CParamNode testParam; TS_ASSERT_EQUALS(CParamNode::LoadXMLString(testParam, "1110000"), PSRETURN_OK); - man.AddComponent(ent1, man.LookupCID("TestScript1_Init"), noParam); - man.AddComponent(ent2, man.LookupCID("TestScript1_Init"), testParam.GetChild("node")); + man.AddComponent(hnd1, man.LookupCID("TestScript1_Init"), noParam); + man.AddComponent(hnd2, man.LookupCID("TestScript1_Init"), testParam.GetChild("node")); TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent1, IID_Test1))->GetX(), 100); TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent2, IID_Test1))->GetX(), 1+10+100+1000); @@ -512,13 +541,15 @@ public: TS_ASSERT(man.LoadScript(L"simulation/components/test-param.js")); entity_id_t ent1 = 1, ent2 = 2; + CEntityHandle hnd1 = man.AllocateEntityHandle(ent1); + CEntityHandle hnd2 = man.AllocateEntityHandle(ent2); CParamNode noParam; CParamNode testParam; TS_ASSERT_EQUALS(CParamNode::LoadXMLString(testParam, "100"), PSRETURN_OK); - man.AddComponent(ent1, man.LookupCID("TestScript1_readonly"), testParam); - man.AddComponent(ent2, man.LookupCID("TestScript1_readonly"), testParam); + man.AddComponent(hnd1, man.LookupCID("TestScript1_readonly"), testParam); + man.AddComponent(hnd2, man.LookupCID("TestScript1_readonly"), testParam); TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent1, IID_Test1))->GetX(), 102); TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent2, IID_Test1))->GetX(), 102); @@ -533,13 +564,17 @@ public: TS_ASSERT(man.LoadScript(L"simulation/components/test-hotload1.js")); entity_id_t ent1 = 1, ent2 = 2, ent3 = 3, ent4 = 4; + CEntityHandle hnd1 = man.AllocateEntityHandle(ent1); + CEntityHandle hnd2 = man.AllocateEntityHandle(ent2); + CEntityHandle hnd3 = man.AllocateEntityHandle(ent3); + CEntityHandle hnd4 = man.AllocateEntityHandle(ent4); CParamNode testParam; TS_ASSERT_EQUALS(CParamNode::LoadXMLString(testParam, "100"), PSRETURN_OK); - man.AddComponent(ent1, man.LookupCID("HotloadA"), testParam); - man.AddComponent(ent2, man.LookupCID("HotloadB"), testParam); - man.AddComponent(ent2, man.LookupCID("HotloadC"), testParam); + man.AddComponent(hnd1, man.LookupCID("HotloadA"), testParam); + man.AddComponent(hnd2, man.LookupCID("HotloadB"), testParam); + man.AddComponent(hnd2, man.LookupCID("HotloadC"), testParam); TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent1, IID_Test1))->GetX(), 100); TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent2, IID_Test1))->GetX(), 200); @@ -549,8 +584,8 @@ public: TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent1, IID_Test1))->GetX(), 1000); TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent2, IID_Test1))->GetX(), 200); - man.AddComponent(ent3, man.LookupCID("HotloadA"), testParam); - man.AddComponent(ent4, man.LookupCID("HotloadB"), testParam); + man.AddComponent(hnd3, man.LookupCID("HotloadA"), testParam); + man.AddComponent(hnd4, man.LookupCID("HotloadB"), testParam); TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent3, IID_Test1))->GetX(), 1000); TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent4, IID_Test1))->GetX(), 200); @@ -563,15 +598,18 @@ public: man.LoadComponentTypes(); entity_id_t ent1 = 1, ent2 = 2, ent3 = FIRST_LOCAL_ENTITY; + CEntityHandle hnd1 = man.AllocateEntityHandle(ent1); + CEntityHandle hnd2 = man.AllocateEntityHandle(ent2); + CEntityHandle hnd3 = man.AllocateEntityHandle(ent3); CParamNode noParam; CParamNode testParam; TS_ASSERT_EQUALS(CParamNode::LoadXMLString(testParam, "1234"), PSRETURN_OK); - man.AddComponent(ent1, CID_Test1A, noParam); - man.AddComponent(ent1, CID_Test2A, noParam); - man.AddComponent(ent2, CID_Test1A, testParam); - man.AddComponent(ent3, CID_Test2A, noParam); + man.AddComponent(hnd1, CID_Test1A, noParam); + man.AddComponent(hnd1, CID_Test2A, noParam); + man.AddComponent(hnd2, CID_Test1A, testParam); + man.AddComponent(hnd3, CID_Test2A, noParam); TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent1, IID_Test1))->GetX(), 11000); TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent1, IID_Test2))->GetX(), 21000); @@ -651,15 +689,19 @@ public: TS_ASSERT(man.LoadScript(L"simulation/components/test-serialize.js")); entity_id_t ent1 = 1, ent2 = 2, ent3 = 3, ent4 = 4; + CEntityHandle hnd1 = man.AllocateEntityHandle(ent1); + CEntityHandle hnd2 = man.AllocateEntityHandle(ent2); + CEntityHandle hnd3 = man.AllocateEntityHandle(ent3); + CEntityHandle hnd4 = man.AllocateEntityHandle(ent4); CParamNode noParam; CParamNode testParam; TS_ASSERT_EQUALS(CParamNode::LoadXMLString(testParam, "1234"), PSRETURN_OK); - man.AddComponent(ent1, man.LookupCID("TestScript1_values"), testParam); - man.AddComponent(ent2, man.LookupCID("TestScript1_entity"), testParam); - man.AddComponent(ent3, man.LookupCID("TestScript1_nontree"), testParam); - man.AddComponent(ent4, man.LookupCID("TestScript1_custom"), testParam); + man.AddComponent(hnd1, man.LookupCID("TestScript1_values"), testParam); + man.AddComponent(hnd2, man.LookupCID("TestScript1_entity"), testParam); + man.AddComponent(hnd3, man.LookupCID("TestScript1_nontree"), testParam); + man.AddComponent(hnd4, man.LookupCID("TestScript1_custom"), testParam); TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent1, IID_Test1))->GetX(), 1234); { @@ -734,9 +776,10 @@ public: TS_ASSERT(man.LoadScript(L"simulation/components/test-serialize.js")); entity_id_t ent1 = 1; + CEntityHandle hnd1 = man.AllocateEntityHandle(ent1); CParamNode noParam; - man.AddComponent(ent1, man.LookupCID("TestScript1_getter"), noParam); + man.AddComponent(hnd1, man.LookupCID("TestScript1_getter"), noParam); std::stringstream stateStream; TS_ASSERT(man.SerializeState(stateStream)); @@ -749,18 +792,20 @@ public: CComponentManager man(context); man.LoadComponentTypes(); TS_ASSERT(man.LoadScript(L"simulation/components/test-serialize.js")); + man.InitSystemEntity(); entity_id_t ent2 = 2; + CEntityHandle hnd2 = man.AllocateEntityHandle(ent2); CParamNode noParam; // The template manager takes care of reloading templates on deserialization, // so we need to use it here - TS_ASSERT(man.AddComponent(SYSTEM_ENTITY, CID_TemplateManager, noParam)); + TS_ASSERT(man.AddComponent(man.GetSystemEntity(), CID_TemplateManager, noParam)); ICmpTemplateManager* tempMan = static_cast (man.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager)); const CParamNode* testParam = tempMan->LoadTemplate(ent2, "template-serialize", -1); - man.AddComponent(ent2, man.LookupCID("TestScript1_consts"), testParam->GetChild("TestScript1_consts")); + man.AddComponent(hnd2, man.LookupCID("TestScript1_consts"), testParam->GetChild("TestScript1_consts")); TS_ASSERT_EQUALS(static_cast (man.QueryInterface(ent2, IID_Test1))->GetX(), 12347);