Avoid slightly-expensive QueryInterface() calls

Add CEntityHandle which wraps an entity_id_t and also has a pointer to a
per-entity array of IComponents. QueryInterface/CmpPtr on a handle just
involve a couple of pointer dereferences instead of a map lookup.

This requires sizeof(void*) per registered interface type per entity,
which is currently ~0.5KB per entity, which shouldn't be a problem.

This was SVN commit r13825.
This commit is contained in:
Ykkrosh 2013-09-11 20:41:53 +00:00
parent 87753bf3fd
commit 05422ad545
35 changed files with 530 additions and 264 deletions

View File

@ -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);
}
}

View File

@ -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<ICmpRangeManager> cmpRangeManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpRangeManager> cmpRangeManager(GetSystemEntity());
if (cmpRangeManager)
cmpRangeManager->SetLosRevealAll(player, true);
}
@ -976,7 +976,7 @@ public:
{
ScriptInterface& scriptInterface = GetSimContext().GetScriptInterface();
// load the technology templates
CmpPtr<ICmpTechnologyTemplateManager> cmpTechTemplateManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpTechnologyTemplateManager> cmpTechTemplateManager(GetSystemEntity());
ENSURE(cmpTechTemplateManager);
// Get the game state from AIInterface
@ -990,7 +990,7 @@ public:
{
ScriptInterface& scriptInterface = GetSimContext().GetScriptInterface();
CmpPtr<ICmpAIInterface> cmpAIInterface(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpAIInterface> cmpAIInterface(GetSystemEntity());
ENSURE(cmpAIInterface);
// Get the game state from AIInterface
@ -999,7 +999,7 @@ public:
// Get the passability data
Grid<u16> dummyGrid;
const Grid<u16>* passabilityMap = &dummyGrid;
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpPathfinder> 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<u8> dummyGrid2;
const Grid<u8>* territoryMap = &dummyGrid2;
CmpPtr<ICmpTerritoryManager> cmpTerritoryManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpTerritoryManager> cmpTerritoryManager(GetSystemEntity());
if (cmpTerritoryManager && cmpTerritoryManager->NeedUpdate(&m_TerritoriesDirtyID))
{
territoryMap = &cmpTerritoryManager->GetTerritoryGrid();
@ -1029,7 +1029,7 @@ public:
if (m_Worker.getPlayerSize() == 0)
return;
CmpPtr<ICmpAIInterface> cmpAIInterface(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpAIInterface> cmpAIInterface(GetSystemEntity());
ENSURE(cmpAIInterface);
// Get the game state from AIInterface
@ -1038,7 +1038,7 @@ public:
// Get the passability data
Grid<u16> dummyGrid;
const Grid<u16>* passabilityMap = &dummyGrid;
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity());
if (cmpPathfinder)
passabilityMap = &cmpPathfinder->GetPassabilityGrid();
@ -1047,7 +1047,7 @@ public:
bool territoryMapDirty = false;
Grid<u8> dummyGrid2;
const Grid<u8>* territoryMap = &dummyGrid2;
CmpPtr<ICmpTerritoryManager> cmpTerritoryManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpTerritoryManager> cmpTerritoryManager(GetSystemEntity());
if (cmpTerritoryManager && cmpTerritoryManager->NeedUpdate(&m_TerritoriesDirtyID))
{
territoryMap = &cmpTerritoryManager->GetTerritoryGrid();
@ -1066,7 +1066,7 @@ public:
std::vector<CAIWorker::SCommandSets> commands;
m_Worker.GetCommands(commands);
CmpPtr<ICmpCommandQueue> cmpCommandQueue(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpCommandQueue> cmpCommandQueue(GetSystemEntity());
if (!cmpCommandQueue)
return;
@ -1088,7 +1088,7 @@ private:
void StartLoadEntityTemplates()
{
CmpPtr<ICmpTemplateManager> cmpTemplateManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpTemplateManager> cmpTemplateManager(GetSystemEntity());
ENSURE(cmpTemplateManager);
m_TemplateNames = cmpTemplateManager->FindAllTemplates(false);
@ -1102,7 +1102,7 @@ private:
if (m_TemplateLoadedIdx >= m_TemplateNames.size())
return false;
CmpPtr<ICmpTemplateManager> cmpTemplateManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpTemplateManager> cmpTemplateManager(GetSystemEntity());
ENSURE(cmpTemplateManager);
const CParamNode* node = cmpTemplateManager->GetTemplateWithoutValidation(m_TemplateNames[m_TemplateLoadedIdx]);
@ -1127,7 +1127,7 @@ private:
void LoadPathfinderClasses(CScriptVal state)
{
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity());
if (!cmpPathfinder)
return;

View File

@ -136,7 +136,7 @@ public:
const CMessageInterpolate& msgData = static_cast<const CMessageInterpolate&> (msg);
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
CmpPtr<ICmpPosition> 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<ICmpVisual> cmpVisual(GetSimContext(), GetEntityId());
CmpPtr<ICmpVisual> cmpVisual(GetEntityHandle());
if (cmpVisual)
{
CBoundingBoxAligned bound = cmpVisual->GetBounds();
@ -163,7 +163,7 @@ public:
CFixedVector3D pos = cmpPosition->GetPosition();
CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpTerrain> cmpTerrain(GetSystemEntity());
if (cmpTerrain)
{
fixed ground = cmpTerrain->GetGroundLevel(pos.X, pos.Z);

View File

@ -130,11 +130,11 @@ public:
const CFixedVector3D error(fixed::FromInt(-1), fixed::FromInt(-1), fixed::FromInt(-1));
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
if (!cmpPosition || !cmpPosition->IsInWorld())
return error;
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
if (!cmpObstructionManager)
return error;
@ -155,7 +155,7 @@ public:
return error;
ICmpPathfinder::pass_class_t spawnedPass = cmpUnitMotion->GetPassabilityClass();
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity());
if (!cmpPathfinder)
return error;

View File

@ -169,7 +169,7 @@ public:
break;
// Find the new player's colour
CmpPtr<ICmpPlayerManager> cmpPlayerManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpPlayerManager> cmpPlayerManager(GetSystemEntity());
if (!cmpPlayerManager)
break;
CmpPtr<ICmpPlayer> cmpPlayer(GetSimContext(), cmpPlayerManager->GetPlayerByID(msgData.to));

View File

@ -84,7 +84,7 @@ public:
void CCmpMotionBall::Move(fixed dt)
{
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
if (!cmpPosition)
return;

View File

@ -292,7 +292,7 @@ public:
if (!data.inWorld && !m_Tag.valid())
break; // nothing needs to change
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
if (!cmpObstructionManager)
break; // error
@ -336,7 +336,7 @@ public:
{
if (m_Tag.valid())
{
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
if (!cmpObstructionManager)
break; // error
@ -358,11 +358,11 @@ public:
// Construct the obstruction shape
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
if (!cmpObstructionManager)
return; // error
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
if (!cmpPosition)
return; // error
@ -389,7 +389,7 @@ public:
// TODO: code duplication from message handlers
if (m_Tag.valid())
{
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
if (!cmpObstructionManager)
return; // error
@ -444,11 +444,11 @@ public:
virtual bool GetObstructionSquare(ICmpObstructionManager::ObstructionSquare& out)
{
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
if (!cmpPosition)
return false; // error
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
if (!cmpObstructionManager)
return false; // error
@ -485,7 +485,7 @@ public:
virtual EFoundationCheck CheckFoundation(std::string className, bool onlyCenterPoint)
{
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
if (!cmpPosition)
return FOUNDATION_CHECK_FAIL_ERROR; // error
@ -494,7 +494,7 @@ public:
CFixedVector2D pos = cmpPosition->GetPosition2D();
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity());
if (!cmpPathfinder)
return FOUNDATION_CHECK_FAIL_ERROR; // error
@ -522,7 +522,7 @@ public:
virtual bool CheckDuplicateFoundation()
{
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
if (!cmpPosition)
return false; // error
@ -531,7 +531,7 @@ public:
CFixedVector2D pos = cmpPosition->GetPosition2D();
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
if (!cmpObstructionManager)
return false; // error
@ -556,7 +556,7 @@ public:
{
std::vector<entity_id_t> ret;
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
if (!cmpPosition)
return ret; // error
@ -565,7 +565,7 @@ public:
CFixedVector2D pos = cmpPosition->GetPosition2D();
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
if (!cmpObstructionManager)
return ret; // error
@ -620,7 +620,7 @@ public:
if (m_Tag.valid() && m_Type == UNIT)
{
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
if (cmpObstructionManager)
cmpObstructionManager->SetUnitMovingFlag(m_Tag, m_Moving);
}
@ -652,7 +652,7 @@ public:
{
if (m_Tag.valid())
{
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
if (cmpObstructionManager)
{
if (m_Type == UNIT)
@ -680,11 +680,11 @@ public:
if (m_Type == UNIT)
return;
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
if (!cmpObstructionManager)
return;
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
CmpPtr<ICmpPosition> 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<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
if (!cmpObstructionManager)
return; // error
@ -776,7 +776,7 @@ protected:
inline void RemoveClusterShapes()
{
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
if (!cmpObstructionManager)
return; // error

View File

@ -123,7 +123,7 @@ public:
}
// Disable rendering of the unit if it has no position
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
if (!cmpPosition || !cmpPosition->IsInWorld())
{
m_Enabled = false;

View File

@ -306,7 +306,7 @@ const Grid<u16>& CCmpPathfinder::GetPassabilityGrid()
void CCmpPathfinder::UpdateGrid()
{
CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpTerrain> cmpTerrain(GetSystemEntity());
if (!cmpTerrain)
return; // error
@ -326,7 +326,7 @@ void CCmpPathfinder::UpdateGrid()
m_ObstructionGrid = new Grid<u8>(m_MapSize, m_MapSize);
}
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpObstructionManager> 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<ICmpWaterManager> cmpWaterManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpWaterManager> 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<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpObstructionManager> 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<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
if (!cmpObstructionManager)
return ICmpObstruction::FOUNDATION_CHECK_FAIL_ERROR;

View File

@ -580,7 +580,7 @@ void CCmpPathfinder::ComputeShortPath(const IObstructionTestFilter& filter,
}
// Find all the obstruction squares that might affect us
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
std::vector<ICmpObstructionManager::ObstructionSquare> 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<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
if (!cmpObstructionManager)
return false;

View File

@ -304,13 +304,13 @@ public:
entity_pos_t baseY;
if (m_RelativeToGround)
{
CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpTerrain> cmpTerrain(GetSystemEntity());
if (cmpTerrain)
baseY = cmpTerrain->GetGroundLevel(m_X, m_Z);
if (m_Floating)
{
CmpPtr<ICmpWaterManager> cmpWaterManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpWaterManager> 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<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpTerrain> cmpTerrain(GetSystemEntity());
if (cmpTerrain)
baseY = cmpTerrain->GetGroundLevel(m_PrevX, m_PrevZ);
if (m_Floating)
{
CmpPtr<ICmpWaterManager> cmpWaterMan(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpWaterManager> 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<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpTerrain> cmpTerrain(GetSystemEntity());
if (cmpTerrain)
baseY = cmpTerrain->GetExactGroundLevel(x, z);
if (m_Floating || forceFloating)
{
CmpPtr<ICmpWaterManager> cmpWaterManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpWaterManager> cmpWaterManager(GetSystemEntity());
if (cmpWaterManager)
baseY = std::max(baseY, cmpWaterManager->GetExactWaterLevel(x, z));
}
@ -575,7 +575,7 @@ private:
return;
}
CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpTerrain> cmpTerrain(GetSystemEntity());
if (!cmpTerrain || !cmpTerrain->IsLoaded())
{
// try again when terrain is loaded

View File

@ -235,7 +235,7 @@ void CCmpProjectileManager::AdvanceProjectile(Projectile& projectile, float dt)
// carry on until we reach solid land
if (projectile.time >= projectile.timeHit)
{
CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpTerrain> 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<ICmpRangeManager> cmpRangeManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpRangeManager> cmpRangeManager(GetSystemEntity());
int player = GetSimContext().GetCurrentDisplayedPlayer();
ICmpRangeManager::CLosQuerier los (cmpRangeManager->GetLosQuerier(player));
bool losRevealAll = cmpRangeManager->GetLosRevealAll(player);

View File

@ -500,14 +500,14 @@ void CCmpRallyPointRenderer::UpdateMarkers()
}
// set rally point flag selection based on player civilization
CmpPtr<ICmpOwnership> cmpOwnership(GetSimContext(), GetEntityId());
CmpPtr<ICmpOwnership> cmpOwnership(GetEntityHandle());
if (cmpOwnership)
{
player_id_t ownerId = cmpOwnership->GetOwner();
if (ownerId != INVALID_PLAYER && (ownerId != previousOwner || m_LastMarkerCount < i))
{
m_LastOwner = ownerId;
CmpPtr<ICmpPlayerManager> cmpPlayerManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpPlayerManager> 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<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
CmpPtr<ICmpPosition> 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<ICmpFootprint> cmpFootprint(GetSimContext(), GetEntityId());
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpFootprint> cmpFootprint(GetEntityHandle());
CmpPtr<ICmpPathfinder> 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<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
CmpPtr<ICmpPosition> 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<ICmpFootprint> cmpFootprint(GetSimContext(), GetEntityId());
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpFootprint> cmpFootprint(GetEntityHandle());
CmpPtr<ICmpPathfinder> 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<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpTerrain> 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<SVisibilitySegment>::const_iterator it = m_VisibilitySegments[index].begin(); it != m_VisibilitySegments[index].end(); ++it)
@ -984,9 +984,9 @@ void CCmpRallyPointRenderer::FixFootprintWaypoints(std::vector<CVector2D>& coord
void CCmpRallyPointRenderer::ReduceSegmentsByVisibility(std::vector<CVector2D>& coords, unsigned maxSegmentLinks, bool floating)
{
CmpPtr<ICmpPathfinder> cmpPathFinder(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpWaterManager> cmpWaterManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpPathfinder> cmpPathFinder(GetSystemEntity());
CmpPtr<ICmpTerrain> cmpTerrain(GetSystemEntity());
CmpPtr<ICmpWaterManager> cmpWaterManager(GetSystemEntity());
ENSURE(cmpPathFinder && cmpTerrain && cmpWaterManager);
if (coords.size() < 3)
@ -1083,7 +1083,7 @@ void CCmpRallyPointRenderer::GetVisibilitySegments(std::deque<SVisibilitySegment
if (m_Path[index].size() < 2)
return;
CmpPtr<ICmpRangeManager> cmpRangeMgr(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpRangeManager> cmpRangeMgr(GetSystemEntity());
player_id_t currentPlayer = GetSimContext().GetCurrentDisplayedPlayer();
CLosQuerier losQuerier(cmpRangeMgr->GetLosQuerier(currentPlayer));

View File

@ -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<typename S>
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<SerializeU32_Unbounded>()(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<SerializeU32_Unbounded, SerializeQuery>()(serialize, "queries", m_Queries);
SerializeMap<SerializeU32_Unbounded, SerializeQuery>()(serialize, "queries", m_Queries, GetSimContext());
SerializeMap<SerializeU32_Unbounded, SerializeEntityData>()(serialize, "entity data", m_EntityData);
SerializeMap<SerializeI32_Unbounded, SerializeBool>()(serialize, "los reveal all", m_LosRevealAll);
@ -720,7 +737,7 @@ public:
std::vector<entity_id_t> r;
CmpPtr<ICmpPosition> cmpSourcePosition(GetSimContext(), q.source);
CmpPtr<ICmpPosition> 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<ICmpPosition> cmpSourcePosition(GetSimContext(), q.source);
CmpPtr<ICmpPosition> 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<ICmpPosition> cmpSourcePosition(GetSimContext(), q.source);
CmpPtr<ICmpPosition> 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<entity_id_t>& r)
{
CmpPtr<ICmpPosition> cmpSourcePosition(GetSimContext(), q.source);
CmpPtr<ICmpPosition> cmpSourcePosition(q.source);
if (!cmpSourcePosition || !cmpSourcePosition->IsInWorld())
return;
CFixedVector2D pos = cmpSourcePosition->GetPosition2D();
@ -1006,8 +1023,8 @@ public:
std::vector<entity_pos_t> r;
CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpWaterManager> cmpWaterManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpTerrain> cmpTerrain(GetSystemEntity());
CmpPtr<ICmpWaterManager> 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<ICmpPosition> cmpSourcePosition(GetSimContext(), q.source);
CmpPtr<ICmpPosition> cmpSourcePosition(q.source);
if (!cmpSourcePosition || !cmpSourcePosition->IsInWorld())
continue;
CFixedVector2D pos = cmpSourcePosition->GetPosition2D();
@ -1151,9 +1168,9 @@ public:
std::vector<entity_pos_t> 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<ICmpPosition> cmpPosition(GetSimContext(), ent);
if (ent.GetId() == INVALID_ENTITY)
return VIS_HIDDEN;
CmpPtr<ICmpPosition> 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<ICmpVision> cmpVision(GetSimContext(), ent);
CmpPtr<ICmpVision> 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<ICmpTerritoryManager> cmpTerritoryManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpTerritoryManager> cmpTerritoryManager(GetSystemEntity());
if (!cmpTerritoryManager || !cmpTerritoryManager->NeedUpdate(&m_TerritoriesDirtyID))
return;

View File

@ -306,7 +306,7 @@ void CCmpSelectable::HandleMessage(const CMessage& msg, bool UNUSED(global))
break;
// update the selection highlight color
CmpPtr<ICmpPlayerManager> cmpPlayerManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpPlayerManager> cmpPlayerManager(GetSystemEntity());
if (!cmpPlayerManager)
break;
@ -352,13 +352,12 @@ void CCmpSelectable::UpdateStaticOverlay()
if (!CRenderer::IsInitialised())
return;
entity_id_t entityId = GetEntityId();
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), entityId);
CmpPtr<ICmpFootprint> cmpFootprint(GetSimContext(), entityId);
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
CmpPtr<ICmpFootprint> cmpFootprint(GetEntityHandle());
if (!cmpFootprint || !cmpPosition || !cmpPosition->IsInWorld())
return;
CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpTerrain> 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<ICmpPosition> cmpPosition(GetSimContext(), entityId);
CmpPtr<ICmpFootprint> cmpFootprint(GetSimContext(), entityId);
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
CmpPtr<ICmpFootprint> 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<ICmpWaterManager> cmpWaterManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpWaterManager> cmpWaterManager(GetSystemEntity());
CmpPtr<ICmpTerrain> 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<ICmpOwnership> cmpOwnership(GetSimContext(), GetEntityId());
CmpPtr<ICmpOwnership> 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<ICmpPlayerManager> cmpPlayerManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpPlayerManager> 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<ICmpVisual> cmpVisual(GetSimContext(), GetEntityId());
CmpPtr<ICmpVisual> cmpVisual(GetEntityHandle());
if (cmpVisual)
{
SimRender::ConstructBoxOutline(cmpVisual->GetBounds(), *m_DebugBoundingBoxOverlay);

View File

@ -65,7 +65,7 @@ public:
if ( ! g_SoundManager || (source == INVALID_ENTITY) )
return;
CmpPtr<ICmpRangeManager> cmpRangeManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpRangeManager> cmpRangeManager(GetSystemEntity());
int currentPlayer = GetSimContext().GetCurrentDisplayedPlayer();
if ( !cmpRangeManager ||

View File

@ -118,7 +118,7 @@ public:
u16 tiles = GetTilesPerSide();
u16 vertices = GetVerticesPerSide();
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpObstructionManager> 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<ICmpRangeManager> cmpRangeManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpRangeManager> cmpRangeManager(GetSystemEntity());
if (cmpRangeManager)
{
cmpRangeManager->SetBounds(entity_pos_t::Zero(), entity_pos_t::Zero(),

View File

@ -103,10 +103,10 @@ public:
{
u32 newRadius = m_Radius;
CmpPtr<ICmpOwnership> cmpOwnership(GetSimContext(), GetEntityId());
CmpPtr<ICmpOwnership> cmpOwnership(GetEntityHandle());
if (cmpOwnership && cmpOwnership->GetOwner() != INVALID_PLAYER)
{
CmpPtr<ICmpPlayerManager> cmpPlayerManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpPlayerManager> cmpPlayerManager(GetSystemEntity());
entity_id_t playerEnt = cmpPlayerManager->GetPlayerByID(cmpOwnership->GetOwner());
if (playerEnt != INVALID_ENTITY)

View File

@ -336,7 +336,7 @@ void CCmpTerritoryManager::CalculateTerritories()
PROFILE("CalculateTerritories");
CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpTerrain> 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<u8> influenceGrid(tilesW, tilesH);
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpPathfinder> 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<ICmpPlayerManager> cmpPlayerManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpPlayerManager> cmpPlayerManager(GetSystemEntity());
if (!cmpPlayerManager)
return;

View File

@ -294,14 +294,14 @@ public:
m_RunSpeed = m_WalkSpeed;
}
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity());
if (cmpPathfinder)
{
m_PassClass = cmpPathfinder->GetPassabilityClass(paramNode.GetChild("PassabilityClass").ToUTF8());
m_CostClass = cmpPathfinder->GetCostClass(paramNode.GetChild("CostClass").ToUTF8());
}
CmpPtr<ICmpObstruction> cmpObstruction(GetSimContext(), GetEntityId());
CmpPtr<ICmpObstruction> 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<ICmpObstruction> cmpObstruction(GetSimContext(), GetEntityId());
CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle());
if (cmpObstruction)
cmpObstruction->SetMovingFlag(false);
@ -484,7 +484,7 @@ private:
{
StopMoving();
CmpPtr<ICmpObstruction> cmpObstruction(GetSimContext(), GetEntityId());
CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle());
if (cmpObstruction)
cmpObstruction->SetMovingFlag(false);
@ -502,7 +502,7 @@ private:
{
m_Moving = false;
CmpPtr<ICmpObstruction> cmpObstruction(GetSimContext(), GetEntityId());
CmpPtr<ICmpObstruction> 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<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
if (!cmpPosition || !cmpPosition->IsInWorld())
{
StartFailed();
@ -658,7 +658,7 @@ void CCmpUnitMotion::PathResult(u32 ticket, const ICmpPathfinder::Path& path)
}
}
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
CmpPtr<ICmpPosition> 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<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
CmpPtr<ICmpPosition> 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<ICmpPathfinder> cmpPathfinder (GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity());
if (!cmpPathfinder)
return;
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
CmpPtr<ICmpPosition> 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<ICmpPathfinder> cmpPathfinder (GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpPathfinder> 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<ICmpOwnership> cmpOwnership(GetSimContext(), GetEntityId());
CmpPtr<ICmpOwnership> cmpOwnership(GetEntityHandle());
if (cmpOwnership)
{
CmpPtr<ICmpRangeManager> cmpRangeManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpRangeManager> 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<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
CmpPtr<ICmpPosition> 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<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
CmpPtr<ICmpPosition> 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<ICmpObstruction> cmpObstruction(GetSimContext(), GetEntityId());
CmpPtr<ICmpObstruction> 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<ICmpPathfinder> cmpPathfinder(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpPathfinder> 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<ICmpPathfinder> cmpPathfinder(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity());
if (!cmpPathfinder)
return;
@ -1242,7 +1242,7 @@ bool CCmpUnitMotion::PickNextLongWaypoint(const CFixedVector2D& pos, bool avoidM
goal.z = targetZ;
}
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpPathfinder> 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<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
CmpPtr<ICmpPosition> 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<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpObstructionManager> 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<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
if (!cmpPosition || !cmpPosition->IsInWorld())
return false;
CFixedVector2D pos = cmpPosition->GetPosition2D();
bool hasObstruction = false;
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpObstructionManager> 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<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
if (!cmpPosition || !cmpPosition->IsInWorld())
return false;
CFixedVector2D pos = cmpPosition->GetPosition2D();
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpObstructionManager> 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<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
if (!cmpPosition || !cmpPosition->IsInWorld())
return false;
CFixedVector2D pos = cmpPosition->GetPosition2D();
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpObstructionManager> 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<SOverlayLine>& lines, CColor color)
{
bool floating = false;
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
if (cmpPosition)
floating = cmpPosition->IsFloating();

View File

@ -85,13 +85,13 @@ public:
const CMessageTechnologyModification& msgData = static_cast<const CMessageTechnologyModification&> (msg);
if (msgData.component == L"Vision")
{
CmpPtr<ICmpOwnership> cmpOwnership(GetSimContext(), GetEntityId());
CmpPtr<ICmpOwnership> cmpOwnership(GetEntityHandle());
if (cmpOwnership)
{
player_id_t owner = cmpOwnership->GetOwner();
if (owner != INVALID_PLAYER && owner == msgData.player)
{
CmpPtr<ICmpPlayerManager> cmpPlayerManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpPlayerManager> cmpPlayerManager(GetSystemEntity());
entity_id_t playerEnt = cmpPlayerManager->GetPlayerByID(owner);
CmpPtr<ICmpTechnologyManager> cmpTechnologyManager(GetSimContext(), playerEnt);
if (playerEnt != INVALID_ENTITY && cmpTechnologyManager)

View File

@ -261,7 +261,7 @@ public:
if (m_Unit)
{
CmpPtr<ICmpOwnership> cmpOwnership(GetSimContext(), GetEntityId());
CmpPtr<ICmpOwnership> 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<ICmpVision> cmpVision(GetSimContext(), GetEntityId());
CmpPtr<ICmpVision> 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<ICmpFootprint> cmpFootprint(GetSimContext(), GetEntityId());
CmpPtr<ICmpFootprint> 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<ICmpTemplateManager> cmpTemplateManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpTemplateManager> 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<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
if (!cmpPosition || !cmpPosition->IsInWorld())
return;
CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), GetEntityId());
CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetEntityHandle());
if (!cmpUnitMotion)
return;
@ -712,23 +712,23 @@ void CCmpVisualActor::Update(fixed UNUSED(turnLength))
void CCmpVisualActor::UpdateVisibility()
{
ICmpRangeManager::ELosVisibility oldVisibility = m_Visibility;
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
CmpPtr<ICmpPosition> 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<ICmpVision> cmpVision(GetSimContext(), GetEntityId());
CmpPtr<ICmpVision> cmpVision(GetEntityHandle());
if (cmpVision && cmpVision->GetAlwaysVisible())
m_Visibility = ICmpRangeManager::VIS_VISIBLE;
else
{
CmpPtr<ICmpRangeManager> cmpRangeManager(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpRangeManager> 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<ICmpSelectable> cmpSelectable(GetSimContext(), GetEntityId());
CmpPtr<ICmpSelectable> 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<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
CmpPtr<ICmpPosition> 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<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
CmpPtr<ICmpTerrain> cmpTerrain(GetSystemEntity());
if (floating && cmpTerrain)
{
CVector3D pos = transform.GetTranslation();

View File

@ -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;
/**

View File

@ -43,16 +43,17 @@ std::vector<entity_id_t> 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<ICmpSelectable*>(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<ICmpVisual> cmpVisual(simulation.GetSimContext(), ent);
CmpPtr<ICmpVisual> cmpVisual(handle);
if (!cmpVisual)
continue;
@ -121,17 +122,18 @@ std::vector<entity_id_t> 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<ICmpSelectable*>(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<ICmpOwnership> cmpOwnership(simulation.GetSimContext(), ent);
CmpPtr<ICmpOwnership> cmpOwnership(handle);
if (owner != INVALID_PLAYER && (!cmpOwnership || cmpOwnership->GetOwner() != owner))
continue;
@ -139,7 +141,7 @@ std::vector<entity_id_t> 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<ICmpVisual> cmpVisual(simulation.GetSimContext(), ent);
CmpPtr<ICmpVisual> cmpVisual(handle);
if (!cmpVisual)
continue;
@ -175,6 +177,7 @@ std::vector<entity_id_t> 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<ICmpSelectable*>(it->second)->IsEditorOnly() && !allowEditorSelectables)
@ -192,7 +195,7 @@ std::vector<entity_id_t> 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'

View File

@ -68,6 +68,18 @@ struct SerializeMap
}
}
template<typename K, typename V, typename C>
void operator()(ISerializer& serialize, const char* UNUSED(name), std::map<K, V>& value, C& context)
{
size_t len = value.size();
serialize.NumberU32_Unbounded("length", (u32)len);
for (typename std::map<K, V>::iterator it = value.begin(); it != value.end(); ++it)
{
KS()(serialize, "key", it->first);
VS()(serialize, "value", it->second, context);
}
}
template<typename M>
void operator()(IDeserializer& deserialize, const char* UNUSED(name), M& value)
{
@ -85,6 +97,24 @@ struct SerializeMap
value.insert(std::make_pair(k, v));
}
}
template<typename M, typename C>
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

View File

@ -74,6 +74,15 @@ public:
m = static_cast<T*>(QueryInterface(simulation, ent, T::GetInterfaceId()));
}
CmpPtr(CEntityHandle ent)
{
SEntityComponentCache* cache = ent.GetComponentCache();
if (cache != NULL && T::GetInterfaceId() < (int)cache->numInterfaces)
m = static_cast<T*>(cache->interfaces[T::GetInterfaceId()]);
else
m = NULL;
}
T* operator->() { return m; }
operator bool_type() const

View File

@ -468,6 +468,13 @@ void CComponentManager::ResetState()
m_ComponentsByTypeId.clear();
// Delete all SEntityComponentCaches
std::map<entity_id_t, SEntityComponentCache*>::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<ComponentTypeId, ComponentType>::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<entity_id_t, IComponent*>& 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<entity_id_t, IComponent*>& 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<entity_id_t, SEntityComponentCache*>::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<entity_id_t>::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<boost::unordered_map<entity_id_t, IComponent*> >::iterator ifcit = m_ComponentsByInterface.begin();
for (; ifcit != m_ComponentsByInterface.end(); ++ifcit)

View File

@ -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<MessageTypeId, std::string> m_MessageTypeNamesById;
std::map<std::string, InterfaceId> m_InterfaceIdsByName;
std::map<entity_id_t, SEntityComponentCache*> m_ComponentCaches;
// TODO: maintaining both ComponentsBy* is nasty; can we get rid of one,
// while keeping QueryInterface and PostMessage sufficiently efficient?

View File

@ -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;

View File

@ -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, ("<test>" + xml + "</test>").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<T*> (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);

View File

@ -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

View File

@ -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;
};

View File

@ -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;
};

View File

@ -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<ICmpTemplateManager*> (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<ICmpTemplateManager*> (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<ICmpTemplateManager*> (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<ICmpTemplateManager*> (man.QueryInterface(ent1, IID_TemplateManager));
TS_ASSERT(tempMan != NULL);

View File

@ -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, "<x>1234</x>"), 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<ICmpTest1*> (man.QueryInterface(ent1, IID_Test1))->GetX(), 11000);
TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (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<ICmpTest1*> (man.QueryInterface(ent1, IID_Test1))->GetX(), 11000);
TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (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<ICmpTest1*> (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<ICmpTest1*> (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<ICmpTest1*> (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<ICmpTest1*> (man.QueryInterface(ent1, IID_Test1))->GetX(), (int)ent1);
TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (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<ICmpTest1*> (man.QueryInterface(ent1, IID_Test1))->GetX(), 400);
TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (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<ICmpTest1*> (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<ICmpTest1*> (man.QueryInterface(ent1, IID_Test1))->GetX(), 100);
TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (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, "<node><x>1</x><y>1<z w='100'><a>1000</a></z>0</y></node>"), 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<ICmpTest1*> (man.QueryInterface(ent1, IID_Test1))->GetX(), 100);
TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (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, "<x>100</x>"), 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<ICmpTest1*> (man.QueryInterface(ent1, IID_Test1))->GetX(), 102);
TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (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, "<x>100</x>"), 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<ICmpTest1*> (man.QueryInterface(ent1, IID_Test1))->GetX(), 100);
TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (man.QueryInterface(ent2, IID_Test1))->GetX(), 200);
@ -549,8 +584,8 @@ public:
TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (man.QueryInterface(ent1, IID_Test1))->GetX(), 1000);
TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (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<ICmpTest1*> (man.QueryInterface(ent3, IID_Test1))->GetX(), 1000);
TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (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, "<x>1234</x>"), 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<ICmpTest1*> (man.QueryInterface(ent1, IID_Test1))->GetX(), 11000);
TS_ASSERT_EQUALS(static_cast<ICmpTest2*> (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, "<x>1234</x>"), 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<ICmpTest1*> (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<ICmpTemplateManager*> (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<ICmpTest1*> (man.QueryInterface(ent2, IID_Test1))->GetX(), 12347);