mirror of
https://gitea.wildfiregames.com/0ad/0ad.git
synced 2026-10-13 15:34:37 +00:00
Simplify component deserialization.
Deserialize SYSTEM_ENTITY before any other entities. This makes it safe for Deserialize() methods to access system components (mirroring how Init() can already access system components). Add a Deserialized message, sent after all entities have been deserialized, to help with some other sequencing problems. This was SVN commit r15264.
This commit is contained in:
@@ -21,6 +21,8 @@
|
||||
#include "IComponent.h"
|
||||
#include "ParamNode.h"
|
||||
|
||||
#include "simulation2/MessageTypes.h"
|
||||
|
||||
#include "simulation2/serialization/DebugSerializer.h"
|
||||
#include "simulation2/serialization/HashSerializer.h"
|
||||
#include "simulation2/serialization/StdSerializer.h"
|
||||
@@ -105,6 +107,7 @@ bool CComponentManager::ComputeStateHash(std::string& outHash, bool quick)
|
||||
CHashSerializer serializer(m_ScriptInterface);
|
||||
|
||||
serializer.StringASCII("rng", SerializeRNG(m_RNG), 0, 32);
|
||||
serializer.NumberU32_Unbounded("next entity id", m_NextEntityId);
|
||||
|
||||
std::map<ComponentTypeId, std::map<entity_id_t, IComponent*> >::const_iterator cit = m_ComponentsByTypeId.begin();
|
||||
for (; cit != m_ComponentsByTypeId.end(); ++cit)
|
||||
@@ -151,7 +154,12 @@ bool CComponentManager::ComputeStateHash(std::string& outHash, bool quick)
|
||||
* Simulation state serialization format:
|
||||
*
|
||||
* TODO: Global version number.
|
||||
* Number of (non-empty) component types.
|
||||
* Number of SYSTEM_ENTITY component types
|
||||
* For each SYSTEM_ENTITY component type:
|
||||
* Component type name
|
||||
* TODO: Component type version number.
|
||||
* Component state.
|
||||
* Number of (non-empty, non-SYSTEM_ENTITY-only) component types.
|
||||
* For each component type:
|
||||
* Component type name.
|
||||
* TODO: Component type version number.
|
||||
@@ -182,7 +190,9 @@ bool CComponentManager::SerializeState(std::ostream& stream)
|
||||
|
||||
std::map<ComponentTypeId, std::map<entity_id_t, IComponent*> >::const_iterator cit;
|
||||
|
||||
uint32_t numSystemComponentTypes = 0;
|
||||
uint32_t numComponentTypes = 0;
|
||||
std::set<ComponentTypeId> serializedSystemComponentTypes;
|
||||
std::set<ComponentTypeId> serializedComponentTypes;
|
||||
|
||||
for (cit = m_ComponentsByTypeId.begin(); cit != m_ComponentsByTypeId.end(); ++cit)
|
||||
@@ -191,19 +201,50 @@ bool CComponentManager::SerializeState(std::ostream& stream)
|
||||
bool needsSerialization = false;
|
||||
for (std::map<entity_id_t, IComponent*>::const_iterator eit = cit->second.begin(); eit != cit->second.end(); ++eit)
|
||||
{
|
||||
// Don't serialize local entities
|
||||
if (ENTITY_IS_LOCAL(eit->first))
|
||||
// Don't serialize local entities, and handle SYSTEM_ENTITY separately
|
||||
if (ENTITY_IS_LOCAL(eit->first) || eit->first == SYSTEM_ENTITY)
|
||||
continue;
|
||||
|
||||
needsSerialization = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!needsSerialization)
|
||||
if (needsSerialization)
|
||||
{
|
||||
numComponentTypes++;
|
||||
serializedComponentTypes.insert(cit->first);
|
||||
}
|
||||
|
||||
if (cit->second.find(SYSTEM_ENTITY) != cit->second.end())
|
||||
{
|
||||
numSystemComponentTypes++;
|
||||
serializedSystemComponentTypes.insert(cit->first);
|
||||
}
|
||||
}
|
||||
|
||||
serializer.NumberU32_Unbounded("num system component types", numSystemComponentTypes);
|
||||
|
||||
for (cit = m_ComponentsByTypeId.begin(); cit != m_ComponentsByTypeId.end(); ++cit)
|
||||
{
|
||||
if (serializedSystemComponentTypes.find(cit->first) == serializedSystemComponentTypes.end())
|
||||
continue;
|
||||
|
||||
numComponentTypes++;
|
||||
serializedComponentTypes.insert(cit->first);
|
||||
std::map<ComponentTypeId, ComponentType>::const_iterator ctit = m_ComponentTypesById.find(cit->first);
|
||||
if (ctit == m_ComponentTypesById.end())
|
||||
{
|
||||
debug_warn(L"Invalid ctit"); // this should never happen
|
||||
return false;
|
||||
}
|
||||
|
||||
serializer.StringASCII("name", ctit->second.name, 0, 255);
|
||||
|
||||
std::map<entity_id_t, IComponent*>::const_iterator eit = cit->second.find(SYSTEM_ENTITY);
|
||||
if (eit == cit->second.end())
|
||||
{
|
||||
debug_warn(L"Invalid eit"); // this should never happen
|
||||
return false;
|
||||
}
|
||||
eit->second->Serialize(serializer);
|
||||
}
|
||||
|
||||
serializer.NumberU32_Unbounded("num component types", numComponentTypes);
|
||||
@@ -226,8 +267,8 @@ bool CComponentManager::SerializeState(std::ostream& stream)
|
||||
uint32_t numComponents = 0;
|
||||
for (std::map<entity_id_t, IComponent*>::const_iterator eit = cit->second.begin(); eit != cit->second.end(); ++eit)
|
||||
{
|
||||
// Don't serialize local entities
|
||||
if (ENTITY_IS_LOCAL(eit->first))
|
||||
// Don't serialize local entities or SYSTEM_ENTITY
|
||||
if (ENTITY_IS_LOCAL(eit->first) || eit->first == SYSTEM_ENTITY)
|
||||
continue;
|
||||
|
||||
numComponents++;
|
||||
@@ -239,8 +280,8 @@ bool CComponentManager::SerializeState(std::ostream& stream)
|
||||
// Serialize the components now
|
||||
for (std::map<entity_id_t, IComponent*>::const_iterator eit = cit->second.begin(); eit != cit->second.end(); ++eit)
|
||||
{
|
||||
// Don't serialize local entities
|
||||
if (ENTITY_IS_LOCAL(eit->first))
|
||||
// Don't serialize local entities or SYSTEM_ENTITY
|
||||
if (ENTITY_IS_LOCAL(eit->first) || eit->first == SYSTEM_ENTITY)
|
||||
continue;
|
||||
|
||||
serializer.NumberU32_Unbounded("entity id", eit->first);
|
||||
@@ -256,7 +297,6 @@ bool CComponentManager::DeserializeState(std::istream& stream)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
CStdDeserializer deserializer(m_ScriptInterface, stream);
|
||||
|
||||
ResetState();
|
||||
@@ -268,12 +308,39 @@ bool CComponentManager::DeserializeState(std::istream& stream)
|
||||
|
||||
deserializer.NumberU32_Unbounded("next entity id", m_NextEntityId); // TODO: use sensible bounds
|
||||
|
||||
uint32_t numComponentTypes;
|
||||
deserializer.NumberU32_Unbounded("num component types", numComponentTypes);
|
||||
uint32_t numSystemComponentTypes;
|
||||
deserializer.NumberU32_Unbounded("num system component types", numSystemComponentTypes);
|
||||
|
||||
ICmpTemplateManager* templateManager = NULL;
|
||||
CParamNode noParam;
|
||||
|
||||
for (size_t i = 0; i < numSystemComponentTypes; ++i)
|
||||
{
|
||||
std::string ctname;
|
||||
deserializer.StringASCII("name", ctname, 0, 255);
|
||||
|
||||
ComponentTypeId ctid = LookupCID(ctname);
|
||||
if (ctid == CID__Invalid)
|
||||
{
|
||||
LOGERROR(L"Deserialization saw unrecognised component type '%hs'", ctname.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
IComponent* component = ConstructComponent(m_SystemEntity, ctid);
|
||||
if (!component)
|
||||
return false;
|
||||
|
||||
component->Deserialize(noParam, deserializer);
|
||||
|
||||
// If this was the template manager, remember it so we can use it when
|
||||
// deserializing any further non-system entities
|
||||
if (ctid == CID_TemplateManager)
|
||||
templateManager = static_cast<ICmpTemplateManager*> (component);
|
||||
}
|
||||
|
||||
uint32_t numComponentTypes;
|
||||
deserializer.NumberU32_Unbounded("num component types", numComponentTypes);
|
||||
|
||||
for (size_t i = 0; i < numComponentTypes; ++i)
|
||||
{
|
||||
std::string ctname;
|
||||
@@ -299,7 +366,7 @@ bool CComponentManager::DeserializeState(std::istream& stream)
|
||||
|
||||
// Try to find the template for this entity
|
||||
const CParamNode* entTemplate = NULL;
|
||||
if (templateManager && ent != SYSTEM_ENTITY) // (system entities don't use templates)
|
||||
if (templateManager)
|
||||
entTemplate = templateManager->LoadLatestTemplate(ent);
|
||||
|
||||
// Deserialize, with the appropriate template for this component
|
||||
@@ -307,11 +374,6 @@ bool CComponentManager::DeserializeState(std::istream& stream)
|
||||
component->Deserialize(entTemplate->GetChild(ctname.c_str()), deserializer);
|
||||
else
|
||||
component->Deserialize(noParam, deserializer);
|
||||
|
||||
// If this was the template manager, remember it so we can use it when
|
||||
// deserializing any further non-system entities
|
||||
if (ent == SYSTEM_ENTITY && ctid == CID_TemplateManager)
|
||||
templateManager = static_cast<ICmpTemplateManager*> (component);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,6 +383,10 @@ bool CComponentManager::DeserializeState(std::istream& stream)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Allow components to do some final reinitialisation after everything is loaded
|
||||
CMessageDeserialized msg;
|
||||
BroadcastMessage(msg);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (PSERROR_Deserialize& e)
|
||||
|
||||
Reference in New Issue
Block a user