diff --git a/source/ps/XML/XMLWriter.cpp b/source/ps/XML/XMLWriter.cpp index b9623a0a70..7026102dc9 100644 --- a/source/ps/XML/XMLWriter.cpp +++ b/source/ps/XML/XMLWriter.cpp @@ -259,6 +259,19 @@ template <> void XMLWriter_File::ElementAttribute(const char* name, const { ElementAttribute(name, value.c_str(), newelement); } +template <> void XMLWriter_File::ElementAttribute(const char* name, const std::string& value, bool newelement) +{ + ElementAttribute(name, value.c_str(), newelement); +} +// Encode Unicode strings as UTF-8 +template <> void XMLWriter_File::ElementAttribute(const char* name, const CStrW& value, bool newelement) +{ + ElementAttribute(name, value.ToUTF8(), newelement); +} +template <> void XMLWriter_File::ElementAttribute(const char* name, const std::wstring& value, bool newelement) +{ + ElementAttribute(name, utf8_from_wstring(value).c_str(), newelement); +} // Use CStr's conversion for most types: #define TYPE2(ID_T, ARG_T) \ @@ -272,13 +285,3 @@ TYPE(int) TYPE(unsigned int) TYPE(float) TYPE(double) - -// Encode Unicode strings as UTF-8 -template <> void XMLWriter_File::ElementAttribute(const char* name, const CStrW& value, bool newelement) -{ - ElementAttribute(name, value.ToUTF8(), newelement); -} -template <> void XMLWriter_File::ElementAttribute(const char* name, const std::wstring& value, bool newelement) -{ - ElementAttribute(name, utf8_from_wstring(value).c_str(), newelement); -} diff --git a/source/simulation2/components/CCmpTemplateManager.cpp b/source/simulation2/components/CCmpTemplateManager.cpp index 7629c3626a..9d640e255a 100644 --- a/source/simulation2/components/CCmpTemplateManager.cpp +++ b/source/simulation2/components/CCmpTemplateManager.cpp @@ -61,7 +61,7 @@ public: { size_t count = 0; - for (std::map::const_iterator it = m_LatestTemplates.begin(); it != m_LatestTemplates.end(); ++it) + for (std::map::const_iterator it = m_LatestTemplates.begin(); it != m_LatestTemplates.end(); ++it) { if (ENTITY_IS_LOCAL(it->first)) continue; @@ -69,13 +69,14 @@ public: } serialize.NumberU32_Unbounded("num entities", (u32)count); - for (std::map::const_iterator it = m_LatestTemplates.begin(); it != m_LatestTemplates.end(); ++it) + for (std::map::const_iterator it = m_LatestTemplates.begin(); it != m_LatestTemplates.end(); ++it) { if (ENTITY_IS_LOCAL(it->first)) continue; serialize.NumberU32_Unbounded("id", it->first); - serialize.String("template", it->second, 0, 256); + serialize.StringASCII("template", it->second, 0, 256); } + // TODO: maybe we should do some kind of interning thing instead of printing so many strings? // TODO: will need to serialize techs too, because we need to be giving out // template data before other components (like the tech components) have been deserialized @@ -90,9 +91,9 @@ public: for (u32 i = 0; i < numEntities; ++i) { entity_id_t ent; - std::wstring templateName; + std::string templateName; deserialize.NumberU32_Unbounded(ent); - deserialize.String(templateName, 0, 256); + deserialize.StringASCII(templateName, 0, 256); m_LatestTemplates[ent] = templateName; } } @@ -113,13 +114,13 @@ public: } } - virtual const CParamNode* LoadTemplate(entity_id_t ent, const std::wstring& templateName, int playerID); + virtual const CParamNode* LoadTemplate(entity_id_t ent, const std::string& templateName, int playerID); - virtual const CParamNode* GetTemplate(std::wstring templateName); + virtual const CParamNode* GetTemplate(std::string templateName); virtual const CParamNode* LoadLatestTemplate(entity_id_t ent); - virtual std::wstring GetCurrentTemplateName(entity_id_t ent); + virtual std::string GetCurrentTemplateName(entity_id_t ent); virtual std::vector FindAllTemplates(); @@ -131,26 +132,26 @@ private: // loaded non-broken template data. This includes files that will fail schema validation. // (Failed loads won't remove existing entries under the same name, so we behave more nicely // when hotloading broken files) - std::map m_TemplateFileData; + std::map m_TemplateFileData; // Map from template name to schema validation status. // (Some files, e.g. inherited parent templates, may not be valid themselves but we still need to load // them and use them; we only reject invalid templates that were requested directly by GetTemplate/etc) - std::map m_TemplateSchemaValidity; + std::map m_TemplateSchemaValidity; // Remember the template used by each entity, so we can return them // again for deserialization. // TODO: should store player ID etc. - std::map m_LatestTemplates; + std::map m_LatestTemplates; // (Re)loads the given template, regardless of whether it exists already, // and saves into m_TemplateFileData. Also loads any parents that are not yet // loaded. Returns false on error. // @param templateName XML filename to load (not a |-separated string) - bool LoadTemplateFile(const std::wstring& templateName, int depth); + bool LoadTemplateFile(const std::string& templateName, int depth); // Constructs a standard static-decorative-object template for the given actor - void ConstructTemplateActor(const std::wstring& actorName, CParamNode& out); + void ConstructTemplateActor(const std::string& actorName, CParamNode& out); // Copy the non-interactive components of an entity template (position, actor, etc) into // a new entity template @@ -163,7 +164,7 @@ private: REGISTER_COMPONENT_TYPE(TemplateManager) -const CParamNode* CCmpTemplateManager::LoadTemplate(entity_id_t ent, const std::wstring& templateName, int UNUSED(playerID)) +const CParamNode* CCmpTemplateManager::LoadTemplate(entity_id_t ent, const std::string& templateName, int UNUSED(playerID)) { m_LatestTemplates[ent] = templateName; @@ -176,18 +177,18 @@ const CParamNode* CCmpTemplateManager::LoadTemplate(entity_id_t ent, const std:: return templateRoot; } -const CParamNode* CCmpTemplateManager::GetTemplate(std::wstring templateName) +const CParamNode* CCmpTemplateManager::GetTemplate(std::string templateName) { // Load the template if necessary if (!LoadTemplateFile(templateName, 0)) { - LOGERROR(L"Failed to load entity template '%ls'", templateName.c_str()); + LOGERROR(L"Failed to load entity template '%hs'", templateName.c_str()); return NULL; } // Compute validity, if it's not computed before if (m_TemplateSchemaValidity.find(templateName) == m_TemplateSchemaValidity.end()) - m_TemplateSchemaValidity[templateName] = m_Validator.Validate(templateName, m_TemplateFileData[templateName].ToXML()); + m_TemplateSchemaValidity[templateName] = m_Validator.Validate(CStrW(templateName), m_TemplateFileData[templateName].ToXML()); // Refuse to return invalid templates if (!m_TemplateSchemaValidity[templateName]) return NULL; @@ -195,7 +196,7 @@ const CParamNode* CCmpTemplateManager::GetTemplate(std::wstring templateName) const CParamNode& templateRoot = m_TemplateFileData[templateName].GetChild("Entity"); if (!templateRoot.IsOk()) { - LOGERROR(L"Invalid root element in entity template '%ls'", templateName.c_str()); + LOGERROR(L"Invalid root element in entity template '%hs'", templateName.c_str()); return NULL; } // TODO: the template ought to be validated with some schema, so we don't @@ -206,21 +207,21 @@ const CParamNode* CCmpTemplateManager::GetTemplate(std::wstring templateName) const CParamNode* CCmpTemplateManager::LoadLatestTemplate(entity_id_t ent) { - std::map::const_iterator it = m_LatestTemplates.find(ent); + std::map::const_iterator it = m_LatestTemplates.find(ent); if (it == m_LatestTemplates.end()) return NULL; return LoadTemplate(ent, it->second, -1); } -std::wstring CCmpTemplateManager::GetCurrentTemplateName(entity_id_t ent) +std::string CCmpTemplateManager::GetCurrentTemplateName(entity_id_t ent) { - std::map::const_iterator it = m_LatestTemplates.find(ent); + std::map::const_iterator it = m_LatestTemplates.find(ent); if (it == m_LatestTemplates.end()) - return L""; + return ""; return it->second; } -bool CCmpTemplateManager::LoadTemplateFile(const std::wstring& templateName, int depth) +bool CCmpTemplateManager::LoadTemplateFile(const std::string& templateName, int depth) { // If this file was already loaded, we don't need to do anything if (m_TemplateFileData.find(templateName) != m_TemplateFileData.end()) @@ -229,25 +230,25 @@ bool CCmpTemplateManager::LoadTemplateFile(const std::wstring& templateName, int // Handle infinite loops more gracefully than running out of stack space and crashing if (depth > 100) { - LOGERROR(L"Probable infinite inheritance loop in entity template '%ls'", templateName.c_str()); + LOGERROR(L"Probable infinite inheritance loop in entity template '%hs'", templateName.c_str()); return false; } // Handle special case "actor|foo" - if (templateName.find(L"actor|") == 0) + if (templateName.find("actor|") == 0) { ConstructTemplateActor(templateName.substr(6), m_TemplateFileData[templateName]); return true; } // Handle special case "preview|foo" - if (templateName.find(L"preview|") == 0) + if (templateName.find("preview|") == 0) { // Load the base entity template, if it wasn't already loaded - std::wstring baseName = templateName.substr(8); + std::string baseName = templateName.substr(8); if (!LoadTemplateFile(baseName, depth+1)) { - LOGERROR(L"Failed to load entity template '%ls'", baseName.c_str()); + LOGERROR(L"Failed to load entity template '%hs'", baseName.c_str()); return false; } // Copy a subset to the requested template @@ -256,13 +257,13 @@ bool CCmpTemplateManager::LoadTemplateFile(const std::wstring& templateName, int } // Handle special case "foundation|foo" - if (templateName.find(L"foundation|") == 0) + if (templateName.find("foundation|") == 0) { // Load the base entity template, if it wasn't already loaded - std::wstring baseName = templateName.substr(11); + std::string baseName = templateName.substr(11); if (!LoadTemplateFile(baseName, depth+1)) { - LOGERROR(L"Failed to load entity template '%ls'", baseName.c_str()); + LOGERROR(L"Failed to load entity template '%hs'", baseName.c_str()); return false; } // Copy a subset to the requested template @@ -272,7 +273,7 @@ bool CCmpTemplateManager::LoadTemplateFile(const std::wstring& templateName, int // Normal case: templateName is an XML file: - VfsPath path = VfsPath(TEMPLATE_ROOT) / (templateName + L".xml"); + VfsPath path = VfsPath(TEMPLATE_ROOT) / (std::wstring)CStrW(templateName + ".xml"); CXeromyces xero; PSRETURN ok = xero.Load(path); if (ok != PSRETURN_OK) @@ -282,19 +283,19 @@ bool CCmpTemplateManager::LoadTemplateFile(const std::wstring& templateName, int utf16string parentStr = xero.GetRoot().GetAttributes().GetNamedItem(attr_parent); if (!parentStr.empty()) { - std::wstring parentName(parentStr.begin(), parentStr.end()); + std::string parentName(parentStr.begin(), parentStr.end()); // To prevent needless complexity in template design, we don't allow |-separated strings as parents if (parentName.find('|') != parentName.npos) { - LOGERROR(L"Invalid parent '%ls' in entity template '%ls'", parentName.c_str(), templateName.c_str()); + LOGERROR(L"Invalid parent '%hs' in entity template '%hs'", parentName.c_str(), templateName.c_str()); return false; } // Ensure the parent is loaded if (!LoadTemplateFile(parentName, depth+1)) { - LOGERROR(L"Failed to load parent '%ls' of entity template '%ls'", parentName.c_str(), templateName.c_str()); + LOGERROR(L"Failed to load parent '%hs' of entity template '%hs'", parentName.c_str(), templateName.c_str()); return false; } @@ -310,9 +311,9 @@ bool CCmpTemplateManager::LoadTemplateFile(const std::wstring& templateName, int return true; } -void CCmpTemplateManager::ConstructTemplateActor(const std::wstring& actorName, CParamNode& out) +void CCmpTemplateManager::ConstructTemplateActor(const std::string& actorName, CParamNode& out) { - std::string name = utf8_from_wstring(CParamNode::EscapeXMLString(actorName)); + std::string name = utf8_from_wstring(CParamNode::EscapeXMLString(CStrW(actorName))); std::string xml = "" "" "" diff --git a/source/simulation2/components/ICmpTemplateManager.cpp b/source/simulation2/components/ICmpTemplateManager.cpp index 32bab84ed8..c8c46e853a 100644 --- a/source/simulation2/components/ICmpTemplateManager.cpp +++ b/source/simulation2/components/ICmpTemplateManager.cpp @@ -22,7 +22,7 @@ #include "simulation2/system/InterfaceScripted.h" BEGIN_INTERFACE_WRAPPER(TemplateManager) -DEFINE_INTERFACE_METHOD_1("GetTemplate", const CParamNode*, ICmpTemplateManager, GetTemplate, std::wstring) -DEFINE_INTERFACE_METHOD_1("GetCurrentTemplateName", std::wstring, ICmpTemplateManager, GetCurrentTemplateName, entity_id_t) +DEFINE_INTERFACE_METHOD_1("GetTemplate", const CParamNode*, ICmpTemplateManager, GetTemplate, std::string) +DEFINE_INTERFACE_METHOD_1("GetCurrentTemplateName", std::string, ICmpTemplateManager, GetCurrentTemplateName, entity_id_t) DEFINE_INTERFACE_METHOD_0("FindAllTemplates", std::vector, ICmpTemplateManager, FindAllTemplates) END_INTERFACE_WRAPPER(TemplateManager) diff --git a/source/simulation2/components/ICmpTemplateManager.h b/source/simulation2/components/ICmpTemplateManager.h index cb28bad367..e6e0085426 100644 --- a/source/simulation2/components/ICmpTemplateManager.h +++ b/source/simulation2/components/ICmpTemplateManager.h @@ -25,6 +25,10 @@ /** * Template manager: Handles the loading of entity template files for the initialisation * and deserialization of entity components. + * + * Template names are intentionally restricted to ASCII strings for storage/serialization + * efficiency (we have a lot of strings so this is significant); + * they correspond to filenames so they shouldn't contain non-ASCII anyway. */ class ICmpTemplateManager : public IComponent { @@ -49,7 +53,7 @@ public: * * @return NULL on error */ - virtual const CParamNode* LoadTemplate(entity_id_t ent, const std::wstring& templateName, int playerID) = 0; + virtual const CParamNode* LoadTemplate(entity_id_t ent, const std::string& templateName, int playerID) = 0; /** * Loads the template XML file identified by 'templateName' (including inheritance @@ -57,7 +61,7 @@ public: * * @return NULL on error */ - virtual const CParamNode* GetTemplate(std::wstring templateName) = 0; + virtual const CParamNode* GetTemplate(std::string templateName) = 0; /** * Returns the template most recently specified for the entity 'ent'. @@ -70,7 +74,7 @@ public: /** * Returns the name of the template most recently specified for the entity 'ent'. */ - virtual std::wstring GetCurrentTemplateName(entity_id_t ent) = 0; + virtual std::string GetCurrentTemplateName(entity_id_t ent) = 0; /** * Returns a list of strings that could be validly passed as @c templateName to LoadTemplate. diff --git a/source/simulation2/system/ComponentManager.cpp b/source/simulation2/system/ComponentManager.cpp index b40f2f0d0f..6d3ead0016 100644 --- a/source/simulation2/system/ComponentManager.cpp +++ b/source/simulation2/system/ComponentManager.cpp @@ -559,7 +559,7 @@ entity_id_t CComponentManager::AddEntity(const std::wstring& templateName, entit // TODO: should assert that ent doesn't exist - const CParamNode* tmpl = tempMan->LoadTemplate(ent, templateName, -1); + const CParamNode* tmpl = tempMan->LoadTemplate(ent, CStr8(templateName), -1); if (!tmpl) return INVALID_ENTITY; // LoadTemplate will have reported the error diff --git a/source/simulation2/tests/test_CmpTemplateManager.h b/source/simulation2/tests/test_CmpTemplateManager.h index dfd82979cf..a6efccab77 100644 --- a/source/simulation2/tests/test_CmpTemplateManager.h +++ b/source/simulation2/tests/test_CmpTemplateManager.h @@ -63,31 +63,31 @@ public: ICmpTemplateManager* tempMan = static_cast (man.QueryInterface(ent1, IID_TemplateManager)); TS_ASSERT(tempMan != NULL); - const CParamNode* basic = tempMan->LoadTemplate(ent2, L"basic", -1); + const CParamNode* basic = tempMan->LoadTemplate(ent2, "basic", -1); TS_ASSERT(basic != NULL); TS_ASSERT_WSTR_EQUALS(basic->ToXML(), L"12345"); - const CParamNode* inherit2 = tempMan->LoadTemplate(ent2, L"inherit2", -1); + const CParamNode* inherit2 = tempMan->LoadTemplate(ent2, "inherit2", -1); TS_ASSERT(inherit2 != NULL); TS_ASSERT_WSTR_EQUALS(inherit2->ToXML(), L"d2e1f1g2"); - const CParamNode* inherit1 = tempMan->LoadTemplate(ent2, L"inherit1", -1); + const CParamNode* inherit1 = tempMan->LoadTemplate(ent2, "inherit1", -1); TS_ASSERT(inherit1 != NULL); TS_ASSERT_WSTR_EQUALS(inherit1->ToXML(), L"d1e1f1"); - const CParamNode* actor = tempMan->LoadTemplate(ent2, L"actor|example1", -1); + const CParamNode* actor = tempMan->LoadTemplate(ent2, "actor|example1", -1); TS_ASSERT(actor != NULL); TS_ASSERT_WSTR_EQUALS(actor->ToXML(), L"0uprightfalseexample1"); - const CParamNode* preview = tempMan->LoadTemplate(ent2, L"preview|unit", -1); + const CParamNode* preview = tempMan->LoadTemplate(ent2, "preview|unit", -1); TS_ASSERT(preview != NULL); TS_ASSERT_WSTR_EQUALS(preview->ToXML(), L"0uprightfalseexample"); - const CParamNode* previewobstruct = tempMan->LoadTemplate(ent2, L"preview|unitobstruct", -1); + const CParamNode* previewobstruct = tempMan->LoadTemplate(ent2, "preview|unitobstruct", -1); TS_ASSERT(previewobstruct != NULL); TS_ASSERT_WSTR_EQUALS(previewobstruct->ToXML(), L"1.00uprightfalseexample"); - const CParamNode* previewactor = tempMan->LoadTemplate(ent2, L"preview|actor|example2", -1); + const CParamNode* previewactor = tempMan->LoadTemplate(ent2, "preview|actor|example2", -1); TS_ASSERT(previewactor != NULL); TS_ASSERT_WSTR_EQUALS(previewactor->ToXML(), L"0uprightfalseexample2"); } @@ -108,19 +108,19 @@ public: TestLogger logger; - TS_ASSERT(tempMan->LoadTemplate(ent2, L"illformed", -1) == NULL); + TS_ASSERT(tempMan->LoadTemplate(ent2, "illformed", -1) == NULL); - TS_ASSERT(tempMan->LoadTemplate(ent2, L"invalid", -1) == NULL); + TS_ASSERT(tempMan->LoadTemplate(ent2, "invalid", -1) == NULL); - TS_ASSERT(tempMan->LoadTemplate(ent2, L"nonexistent", -1) == NULL); + TS_ASSERT(tempMan->LoadTemplate(ent2, "nonexistent", -1) == NULL); - TS_ASSERT(tempMan->LoadTemplate(ent2, L"inherit-loop", -1) == NULL); + TS_ASSERT(tempMan->LoadTemplate(ent2, "inherit-loop", -1) == NULL); - TS_ASSERT(tempMan->LoadTemplate(ent2, L"inherit-broken", -1) == NULL); + TS_ASSERT(tempMan->LoadTemplate(ent2, "inherit-broken", -1) == NULL); - TS_ASSERT(tempMan->LoadTemplate(ent2, L"inherit-special", -1) == NULL); + TS_ASSERT(tempMan->LoadTemplate(ent2, "inherit-special", -1) == NULL); - TS_ASSERT(tempMan->LoadTemplate(ent2, L"preview|nonexistent", -1) == NULL); + TS_ASSERT(tempMan->LoadTemplate(ent2, "preview|nonexistent", -1) == NULL); } void test_LoadTemplate_multiple() @@ -137,28 +137,28 @@ public: ICmpTemplateManager* tempMan = static_cast (man.QueryInterface(ent1, IID_TemplateManager)); TS_ASSERT(tempMan != NULL); - const CParamNode* basicA = tempMan->LoadTemplate(ent2, L"basic", -1); + const CParamNode* basicA = tempMan->LoadTemplate(ent2, "basic", -1); TS_ASSERT(basicA != NULL); - const CParamNode* basicB = tempMan->LoadTemplate(ent2, L"basic", -1); + const CParamNode* basicB = tempMan->LoadTemplate(ent2, "basic", -1); TS_ASSERT(basicA == basicB); - const CParamNode* inherit2A = tempMan->LoadTemplate(ent2, L"inherit2", -1); + const CParamNode* inherit2A = tempMan->LoadTemplate(ent2, "inherit2", -1); TS_ASSERT(inherit2A != NULL); - const CParamNode* inherit2B = tempMan->LoadTemplate(ent2, L"inherit2", -1); + const CParamNode* inherit2B = tempMan->LoadTemplate(ent2, "inherit2", -1); TS_ASSERT(inherit2A == inherit2B); TestLogger logger; - TS_ASSERT(tempMan->LoadTemplate(ent2, L"nonexistent", -1) == NULL); - TS_ASSERT(tempMan->LoadTemplate(ent2, L"nonexistent", -1) == NULL); + TS_ASSERT(tempMan->LoadTemplate(ent2, "nonexistent", -1) == NULL); + TS_ASSERT(tempMan->LoadTemplate(ent2, "nonexistent", -1) == NULL); - TS_ASSERT(tempMan->LoadTemplate(ent2, L"inherit-loop", -1) == NULL); - TS_ASSERT(tempMan->LoadTemplate(ent2, L"inherit-loop", -1) == NULL); + TS_ASSERT(tempMan->LoadTemplate(ent2, "inherit-loop", -1) == NULL); + TS_ASSERT(tempMan->LoadTemplate(ent2, "inherit-loop", -1) == NULL); - TS_ASSERT(tempMan->LoadTemplate(ent2, L"inherit-broken", -1) == NULL); - TS_ASSERT(tempMan->LoadTemplate(ent2, L"inherit-broken", -1) == NULL); + TS_ASSERT(tempMan->LoadTemplate(ent2, "inherit-broken", -1) == NULL); + TS_ASSERT(tempMan->LoadTemplate(ent2, "inherit-broken", -1) == NULL); } }; @@ -196,7 +196,7 @@ public: { std::wstring name = templates[i]; printf("# %ls\n", name.c_str()); - const CParamNode* p = cmpTempMan->GetTemplate(name); + const CParamNode* p = cmpTempMan->GetTemplate(CStr8(name)); TS_ASSERT(p != NULL); } } diff --git a/source/simulation2/tests/test_ComponentManager.h b/source/simulation2/tests/test_ComponentManager.h index 30bea11485..ab0a7b8a9c 100644 --- a/source/simulation2/tests/test_ComponentManager.h +++ b/source/simulation2/tests/test_ComponentManager.h @@ -725,7 +725,7 @@ public: TS_ASSERT(man.AddComponent(SYSTEM_ENTITY, CID_TemplateManager, noParam)); ICmpTemplateManager* tempMan = static_cast (man.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager)); - const CParamNode* testParam = tempMan->LoadTemplate(ent2, L"template-serialize", -1); + const CParamNode* testParam = tempMan->LoadTemplate(ent2, "template-serialize", -1); man.AddComponent(ent2, man.LookupCID("TestScript1_consts"), testParam->GetChild("TestScript1_consts")); diff --git a/source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp b/source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp index 685e866936..14ffa40234 100644 --- a/source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp +++ b/source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp @@ -591,7 +591,7 @@ BEGIN_COMMAND(DeleteObject) { // Saved copy of the important aspects of a unit, to allow undo entity_id_t m_EntityID; - std::wstring m_TemplateName; + std::string m_TemplateName; int32_t m_Owner; CFixedVector3D m_Pos; CFixedVector3D m_Rot; @@ -633,9 +633,9 @@ BEGIN_COMMAND(DeleteObject) void Undo() { CSimulation2& sim = *g_Game->GetSimulation2(); - entity_id_t ent = sim.AddEntity(m_TemplateName, m_EntityID); + entity_id_t ent = sim.AddEntity(CStrW(m_TemplateName), m_EntityID); if (ent == INVALID_ENTITY) - LOGERROR(L"Failed to load entity template '%ls'", m_TemplateName.c_str()); + LOGERROR(L"Failed to load entity template '%hs'", m_TemplateName.c_str()); else { CmpPtr cmpPosition(sim, m_EntityID);