entity_id_t CComponentManager::AddEntity(const std::wstring& templateName, entity_id_t ent) { ICmpTemplateManager *cmpTemplateManager = static_cast<ICmpTemplateManager*> (QueryInterface(SYSTEM_ENTITY, IID_TemplateManager)); if (!cmpTemplateManager) { debug_warn(L"No ICmpTemplateManager loaded"); return INVALID_ENTITY; } // TODO: should assert that ent doesn't exist const CParamNode* tmpl = cmpTemplateManager->LoadTemplate(ent, utf8_from_wstring(templateName), -1); 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) { // Ignore attributes on the root element if (it->first.length() && it->first[0] == '@') continue; CComponentManager::ComponentTypeId cid = LookupCID(it->first); if (cid == CID__Invalid) { LOGERROR(L"Unrecognised component type name '%hs' in entity template '%ls'", it->first.c_str(), templateName.c_str()); return INVALID_ENTITY; } 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? } CMessageCreate msg(ent); PostMessage(ent, msg); return ent; }
bool CComponentManager::DeserializeState(std::istream& stream) { CStdDeserializer deserializer(m_ScriptInterface, stream); ResetState(); std::string rng; deserializer.StringASCII("rng", rng, 0, 32); DeserializeRNG(rng, m_RNG); deserializer.NumberU32_Unbounded("next entity id", m_NextEntityId); // TODO: use sensible bounds uint32_t numComponentTypes; deserializer.NumberU32_Unbounded("num component types", numComponentTypes); ICmpTemplateManager* templateManager = NULL; CParamNode noParam; for (size_t i = 0; i < numComponentTypes; ++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; } uint32_t numComponents; deserializer.NumberU32_Unbounded("num components", numComponents); for (size_t j = 0; j < numComponents; ++j) { entity_id_t ent; deserializer.NumberU32_Unbounded("entity id", ent); IComponent* component = ConstructComponent(ent, ctid); if (!component) return false; // Try to find the template for this entity const CParamNode* entTemplate = NULL; if (templateManager && ent != SYSTEM_ENTITY) // (system entities don't use templates) entTemplate = templateManager->LoadLatestTemplate(ent); // Deserialize, with the appropriate template for this component if (entTemplate) 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); } } if (stream.peek() != EOF) { LOGERROR(L"Deserialization didn't reach EOF"); return false; } // TODO: catch exceptions return true; }