Changeset View
Changeset View
Standalone View
Standalone View
source/simulation2/system/ComponentManagerSerialization.cpp
Show First 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
CDebugSerializer serializer(m_ScriptInterface, stream, includeDebugInfo); | CDebugSerializer serializer(m_ScriptInterface, stream, includeDebugInfo); | ||||
serializer.StringASCII("rng", SerializeRNG(m_RNG), 0, 32); | serializer.StringASCII("rng", SerializeRNG(m_RNG), 0, 32); | ||||
serializer.TextLine("entities:"); | serializer.TextLine("entities:"); | ||||
// We want the output to be grouped by entity ID, so invert the CComponentManager data structures | // We want the output to be grouped by entity ID, so invert the CComponentManager data structures | ||||
std::map<entity_id_t, std::map<ComponentTypeId, IComponent*> > components; | DualFlatMap<entity_id_t, SparseFlatMap<ComponentTypeId, IComponent*>, FIRST_LOCAL_ENTITY> components; | ||||
//std::map<ComponentTypeId, std::string> names; | for (size_t cid = 1; cid < m_ComponentsByTypeId.size(); ++cid) | ||||
for (const std::pair<entity_id_t, IComponent*>& entComp : m_ComponentsByTypeId[cid]) | |||||
components[entComp.first][cid] = entComp.second; | |||||
std::map<ComponentTypeId, std::map<entity_id_t, IComponent*> >::const_iterator ctit = m_ComponentsByTypeId.begin(); | for (const std::pair<entity_id_t, SparseFlatMap<ComponentTypeId, IComponent*> >& ents : components) | ||||
for (; ctit != m_ComponentsByTypeId.end(); ++ctit) | |||||
{ | |||||
std::map<entity_id_t, IComponent*>::const_iterator eit = ctit->second.begin(); | |||||
for (; eit != ctit->second.end(); ++eit) | |||||
{ | |||||
components[eit->first][ctit->first] = eit->second; | |||||
} | |||||
} | |||||
std::map<entity_id_t, std::map<ComponentTypeId, IComponent*> >::const_iterator cit = components.begin(); | |||||
for (; cit != components.end(); ++cit) | |||||
{ | { | ||||
std::stringstream n; | std::stringstream n; | ||||
n << "- id: " << cit->first; | n << "- id: " << ents.first; | ||||
serializer.TextLine(n.str()); | serializer.TextLine(n.str()); | ||||
if (ENTITY_IS_LOCAL(cit->first)) | if (ENTITY_IS_LOCAL(ents.first)) | ||||
serializer.TextLine(" type: local"); | serializer.TextLine(" type: local"); | ||||
std::map<ComponentTypeId, IComponent*>::const_iterator ctit = cit->second.begin(); | for (const std::pair<ComponentTypeId, IComponent*>& comp : ents.second) | ||||
for (; ctit != cit->second.end(); ++ctit) | |||||
{ | { | ||||
std::stringstream n; | std::stringstream n; | ||||
n << " " << LookupComponentTypeName(ctit->first) << ":"; | n << " " << LookupComponentTypeName(comp.first) << ":"; | ||||
serializer.TextLine(n.str()); | serializer.TextLine(n.str()); | ||||
serializer.Indent(4); | serializer.Indent(4); | ||||
ctit->second->Serialize(serializer); | comp.second->Serialize(serializer); | ||||
serializer.Dedent(4); | serializer.Dedent(4); | ||||
} | } | ||||
serializer.TextLine(""); | serializer.TextLine(""); | ||||
} | } | ||||
// TODO: catch exceptions | // TODO: catch exceptions | ||||
return true; | return true; | ||||
} | } | ||||
bool CComponentManager::ComputeStateHash(std::string& outHash, bool quick) const | bool CComponentManager::ComputeStateHash(std::string& outHash, bool quick) const | ||||
{ | { | ||||
// Hash serialization: this includes the minimal data necessary to detect | // Hash serialization: this includes the minimal data necessary to detect | ||||
// differences in the state, and ignores things like counts and names | // differences in the state, and ignores things like counts and names | ||||
// If 'quick' is set, this checks even fewer things, so that it will | // If 'quick' is set, this checks even fewer things, so that it will | ||||
// be fast enough to run every turn but will typically detect any | // be fast enough to run every turn but will typically detect any | ||||
// out-of-syncs fairly soon | // out-of-syncs fairly soon | ||||
CHashSerializer serializer(m_ScriptInterface); | CHashSerializer serializer(m_ScriptInterface); | ||||
serializer.StringASCII("rng", SerializeRNG(m_RNG), 0, 32); | serializer.StringASCII("rng", SerializeRNG(m_RNG), 0, 32); | ||||
serializer.NumberU32_Unbounded("next entity id", m_NextEntityId); | serializer.NumberU32_Unbounded("next entity id", m_NextEntityId); | ||||
std::map<ComponentTypeId, std::map<entity_id_t, IComponent*> >::const_iterator cit = m_ComponentsByTypeId.begin(); | for (size_t cid = 1; cid < m_ComponentsByTypeId.size(); ++cid) | ||||
for (; cit != m_ComponentsByTypeId.end(); ++cit) | |||||
{ | { | ||||
// In quick mode, only check unit positions | // In quick mode, only check unit positions | ||||
if (quick && !(cit->first == CID_Position)) | if (quick && !(cid == CID_Position)) | ||||
continue; | continue; | ||||
// Only emit component types if they have a component that will be serialized | // Only emit component types if they have a component that will be serialized | ||||
bool needsSerialization = false; | bool needsSerialization = false; | ||||
for (std::map<entity_id_t, IComponent*>::const_iterator eit = cit->second.begin(); eit != cit->second.end(); ++eit) | for (const std::pair<entity_id_t, IComponent*>& entComp : m_ComponentsByTypeId[cid]) | ||||
{ | { | ||||
// Don't serialize local entities | // Don't serialize local entities | ||||
if (ENTITY_IS_LOCAL(eit->first)) | if (ENTITY_IS_LOCAL(entComp.first)) | ||||
continue; | continue; | ||||
needsSerialization = true; | needsSerialization = true; | ||||
break; | break; | ||||
} | } | ||||
if (!needsSerialization) | if (!needsSerialization) | ||||
continue; | continue; | ||||
serializer.NumberI32_Unbounded("component type id", cit->first); | serializer.NumberI32_Unbounded("component type id", cid); | ||||
for (std::map<entity_id_t, IComponent*>::const_iterator eit = cit->second.begin(); eit != cit->second.end(); ++eit) | for (const std::pair<entity_id_t, IComponent*>& entComp : m_ComponentsByTypeId[cid]) | ||||
{ | { | ||||
// Don't serialize local entities | // Don't serialize local entities | ||||
if (ENTITY_IS_LOCAL(eit->first)) | if (ENTITY_IS_LOCAL(entComp.first)) | ||||
continue; | continue; | ||||
serializer.NumberU32_Unbounded("entity id", eit->first); | serializer.NumberU32_Unbounded("entity id", entComp.first); | ||||
eit->second->Serialize(serializer); | entComp.second->Serialize(serializer); | ||||
} | } | ||||
} | } | ||||
outHash = std::string((const char*)serializer.ComputeHash(), serializer.GetHashLength()); | outHash = std::string((const char*)serializer.ComputeHash(), serializer.GetHashLength()); | ||||
// TODO: catch exceptions | // TODO: catch exceptions | ||||
return true; | return true; | ||||
} | } | ||||
Show All 31 Lines | bool CComponentManager::SerializeState(std::ostream& stream) const | ||||
// We don't serialize the destruction queue, since we'd have to be careful to skip local entities etc | // We don't serialize the destruction queue, since we'd have to be careful to skip local entities etc | ||||
// and it's (hopefully) easier to just expect callers to flush the queue before serializing | // and it's (hopefully) easier to just expect callers to flush the queue before serializing | ||||
ENSURE(m_DestructionQueue.empty()); | ENSURE(m_DestructionQueue.empty()); | ||||
serializer.StringASCII("rng", SerializeRNG(m_RNG), 0, 32); | serializer.StringASCII("rng", SerializeRNG(m_RNG), 0, 32); | ||||
serializer.NumberU32_Unbounded("next entity id", m_NextEntityId); | serializer.NumberU32_Unbounded("next entity id", m_NextEntityId); | ||||
std::map<ComponentTypeId, std::map<entity_id_t, IComponent*> >::const_iterator cit; | |||||
uint32_t numSystemComponentTypes = 0; | uint32_t numSystemComponentTypes = 0; | ||||
uint32_t numComponentTypes = 0; | uint32_t numComponentTypes = 0; | ||||
std::set<ComponentTypeId> serializedSystemComponentTypes; | std::set<ComponentTypeId> serializedSystemComponentTypes; | ||||
std::set<ComponentTypeId> serializedComponentTypes; | std::set<ComponentTypeId> serializedComponentTypes; | ||||
for (cit = m_ComponentsByTypeId.begin(); cit != m_ComponentsByTypeId.end(); ++cit) | for (size_t cid = 1; cid < m_ComponentsByTypeId.size(); ++cid) | ||||
{ | { | ||||
// Only emit component types if they have a component that will be serialized | // Only emit component types if they have a component that will be serialized | ||||
bool needsSerialization = false; | bool needsSerialization = false; | ||||
for (std::map<entity_id_t, IComponent*>::const_iterator eit = cit->second.begin(); eit != cit->second.end(); ++eit) | for (const std::pair<entity_id_t, IComponent*>& entComp : m_ComponentsByTypeId[cid]) | ||||
{ | { | ||||
// Don't serialize local entities, and handle SYSTEM_ENTITY separately | // Don't serialize local entities, and handle SYSTEM_ENTITY separately | ||||
if (ENTITY_IS_LOCAL(eit->first) || eit->first == SYSTEM_ENTITY) | if (ENTITY_IS_LOCAL(entComp.first) || entComp.first == SYSTEM_ENTITY) | ||||
continue; | continue; | ||||
needsSerialization = true; | needsSerialization = true; | ||||
break; | break; | ||||
} | } | ||||
if (needsSerialization) | if (needsSerialization) | ||||
{ | { | ||||
numComponentTypes++; | numComponentTypes++; | ||||
serializedComponentTypes.insert(cit->first); | serializedComponentTypes.insert(cid); | ||||
} | } | ||||
if (cit->second.find(SYSTEM_ENTITY) != cit->second.end()) | if (m_ComponentsByTypeId[cid].find(SYSTEM_ENTITY) != m_ComponentsByTypeId[cid].end()) | ||||
{ | { | ||||
numSystemComponentTypes++; | numSystemComponentTypes++; | ||||
serializedSystemComponentTypes.insert(cit->first); | serializedSystemComponentTypes.insert(cid); | ||||
} | } | ||||
} | } | ||||
serializer.NumberU32_Unbounded("num system component types", numSystemComponentTypes); | serializer.NumberU32_Unbounded("num system component types", numSystemComponentTypes); | ||||
for (cit = m_ComponentsByTypeId.begin(); cit != m_ComponentsByTypeId.end(); ++cit) | for (size_t cid = 1; cid < m_ComponentsByTypeId.size(); ++cid) | ||||
{ | { | ||||
if (serializedSystemComponentTypes.find(cit->first) == serializedSystemComponentTypes.end()) | if (serializedSystemComponentTypes.find(cid) == serializedSystemComponentTypes.end()) | ||||
continue; | continue; | ||||
std::map<ComponentTypeId, ComponentType>::const_iterator ctit = m_ComponentTypesById.find(cit->first); | std::map<ComponentTypeId, ComponentType>::const_iterator ctit = m_ComponentTypesById.find(cid); | ||||
if (ctit == m_ComponentTypesById.end()) | if (ctit == m_ComponentTypesById.end()) | ||||
{ | { | ||||
debug_warn(L"Invalid ctit"); // this should never happen | debug_warn(L"Invalid ctit"); // this should never happen | ||||
return false; | return false; | ||||
} | } | ||||
serializer.StringASCII("name", ctit->second.name, 0, 255); | serializer.StringASCII("name", ctit->second.name, 0, 255); | ||||
std::map<entity_id_t, IComponent*>::const_iterator eit = cit->second.find(SYSTEM_ENTITY); | EntCompMap::const_iterator eit = m_ComponentsByTypeId[cid].find(SYSTEM_ENTITY); | ||||
if (eit == cit->second.end()) | if (eit == m_ComponentsByTypeId[cid].end()) | ||||
{ | { | ||||
debug_warn(L"Invalid eit"); // this should never happen | debug_warn(L"Invalid eit"); // this should never happen | ||||
return false; | return false; | ||||
} | } | ||||
eit->second->Serialize(serializer); | eit->second->Serialize(serializer); | ||||
} | } | ||||
serializer.NumberU32_Unbounded("num component types", numComponentTypes); | serializer.NumberU32_Unbounded("num component types", numComponentTypes); | ||||
for (cit = m_ComponentsByTypeId.begin(); cit != m_ComponentsByTypeId.end(); ++cit) | for (size_t cid = 1; cid < m_ComponentsByTypeId.size(); ++cid) | ||||
{ | { | ||||
if (serializedComponentTypes.find(cit->first) == serializedComponentTypes.end()) | if (serializedComponentTypes.find(cid) == serializedComponentTypes.end()) | ||||
continue; | continue; | ||||
std::map<ComponentTypeId, ComponentType>::const_iterator ctit = m_ComponentTypesById.find(cit->first); | std::map<ComponentTypeId, ComponentType>::const_iterator ctit = m_ComponentTypesById.find(cid); | ||||
if (ctit == m_ComponentTypesById.end()) | if (ctit == m_ComponentTypesById.end()) | ||||
{ | { | ||||
debug_warn(L"Invalid ctit"); // this should never happen | debug_warn(L"Invalid ctit"); // this should never happen | ||||
return false; | return false; | ||||
} | } | ||||
serializer.StringASCII("name", ctit->second.name, 0, 255); | serializer.StringASCII("name", ctit->second.name, 0, 255); | ||||
// Count the components before serializing any of them | // Count the components before serializing any of them | ||||
uint32_t numComponents = 0; | uint32_t numComponents = 0; | ||||
for (std::map<entity_id_t, IComponent*>::const_iterator eit = cit->second.begin(); eit != cit->second.end(); ++eit) | for (const std::pair<entity_id_t, IComponent*>& entComp : m_ComponentsByTypeId[cid]) | ||||
{ | { | ||||
// Don't serialize local entities or SYSTEM_ENTITY | // Don't serialize local entities or SYSTEM_ENTITY | ||||
if (ENTITY_IS_LOCAL(eit->first) || eit->first == SYSTEM_ENTITY) | if (ENTITY_IS_LOCAL(entComp.first) || entComp.first == SYSTEM_ENTITY) | ||||
continue; | continue; | ||||
numComponents++; | numComponents++; | ||||
} | } | ||||
// Emit the count | // Emit the count | ||||
serializer.NumberU32_Unbounded("num components", numComponents); | serializer.NumberU32_Unbounded("num components", numComponents); | ||||
// Serialize the components now | // Serialize the components now | ||||
for (std::map<entity_id_t, IComponent*>::const_iterator eit = cit->second.begin(); eit != cit->second.end(); ++eit) | for (const std::pair<entity_id_t, IComponent*>& entComp : m_ComponentsByTypeId[cid]) | ||||
{ | { | ||||
// Don't serialize local entities or SYSTEM_ENTITY | // Don't serialize local entities or SYSTEM_ENTITY | ||||
if (ENTITY_IS_LOCAL(eit->first) || eit->first == SYSTEM_ENTITY) | if (ENTITY_IS_LOCAL(entComp.first) || entComp.first == SYSTEM_ENTITY) | ||||
continue; | continue; | ||||
serializer.NumberU32_Unbounded("entity id", eit->first); | serializer.NumberU32_Unbounded("entity id", entComp.first); | ||||
eit->second->Serialize(serializer); | entComp.second->Serialize(serializer); | ||||
} | } | ||||
} | } | ||||
// TODO: catch exceptions | // TODO: catch exceptions | ||||
return true; | return true; | ||||
} | } | ||||
bool CComponentManager::DeserializeState(std::istream& stream) | bool CComponentManager::DeserializeState(std::istream& stream) | ||||
▲ Show 20 Lines • Show All 101 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator