Index: binaries/data/mods/public/maps/scenarios/units_demo.js =================================================================== --- binaries/data/mods/public/maps/scenarios/units_demo.js +++ binaries/data/mods/public/maps/scenarios/units_demo.js @@ -31,7 +31,7 @@ let gap = 14; let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); -for (let template of cmpTemplateManager.FindAllTemplates(actors)) +for (let template of cmpTemplateManager.FindTemplatesWithRootName(actors, "Entity")) { print(template + "...\n"); Index: binaries/data/mods/public/maps/scripts/CaptureTheRelic.js =================================================================== --- binaries/data/mods/public/maps/scripts/CaptureTheRelic.js +++ binaries/data/mods/public/maps/scripts/CaptureTheRelic.js @@ -1,7 +1,7 @@ Trigger.prototype.InitCaptureTheRelic = function() { let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); - let catafalqueTemplates = shuffleArray(cmpTemplateManager.FindAllTemplates(false).filter( + let catafalqueTemplates = shuffleArray(cmpTemplateManager.FindTemplatesWithRootName(false, "Entity").filter( name => GetIdentityClasses(cmpTemplateManager.GetTemplate(name).Identity || {}).indexOf("Relic") != -1)); let potentialSpawnPoints = TriggerHelper.GetLandSpawnPoints(); Index: binaries/data/mods/public/maps/scripts/Regicide.js =================================================================== --- binaries/data/mods/public/maps/scripts/Regicide.js +++ binaries/data/mods/public/maps/scripts/Regicide.js @@ -10,7 +10,7 @@ // Get all hero templates of these civs let heroTemplates = {}; let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); - for (let templateName of cmpTemplateManager.FindAllTemplates(false)) + for (let templateName of cmpTemplateManager.FindTemplatesWithRootName(false, "Entity")) { if (!templateName.startsWith("units/")) continue; Index: source/ps/TemplateLoader.h =================================================================== --- source/ps/TemplateLoader.h +++ source/ps/TemplateLoader.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -69,9 +69,9 @@ /** * Returns a list of strings that could validly be passed as @c templateName to LoadTemplateFile. - * Not ignoring any special directories. + * Only returns templates with the specified root name. */ - std::vector FindTemplatesUnrestricted(const std::string& path, bool includeSubdirectories) const; + std::vector FindTemplatesWithRootName(const std::string& path, bool includeSubdirectories, ETemplatesType templatesType, const std::string& rootName) const; private: /** Index: source/ps/TemplateLoader.cpp =================================================================== --- source/ps/TemplateLoader.cpp +++ source/ps/TemplateLoader.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -159,15 +159,19 @@ return templates; } -std::vector CTemplateLoader::FindTemplatesUnrestricted(const std::string& path, bool includeSubdirectories) const +std::vector CTemplateLoader::FindTemplatesWithRootName(const std::string& path, bool includeSubdirectories, ETemplatesType templatesType, const std::string& rootName) const { - std::vector templates; - - size_t flags = includeSubdirectories ? vfs::DIR_RECURSIVE : 0; + std::vector templates = FindTemplates(path, includeSubdirectories, templateTypes); + std::vector templatesWithCorrectRootName; - WARN_IF_ERR(vfs::ForEachFile(g_VFS, VfsPath(TEMPLATE_ROOT) / path, AddToTemplatesUnrestricted, (uintptr_t)&templates, L"*.xml", flags)); + for (const std::string& templateName : templates) + { + const CParamNode& templateData = GetTemplateFileData(templateName); + if (templateData.GetNodeName() === rootName) + templatesWithCorrectRootName.push_back(templateName); + } - return templates; + return templatesWithCorrectRootName; } const CParamNode& CTemplateLoader::GetTemplateFileData(const std::string& templateName) Index: source/simulation2/components/CCmpTemplateManager.cpp =================================================================== --- source/simulation2/components/CCmpTemplateManager.cpp +++ source/simulation2/components/CCmpTemplateManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -217,11 +217,17 @@ return m_templateLoader.FindTemplates("", true, templatesType); } +std::vector CCmpTemplateManager::FindTemplatesWithRootName(bool includeActors, const std::string rootName) const +{ + ETemplatesType templatesType = includeActors ? ALL_TEMPLATES : SIMULATION_TEMPLATES; + return m_templateLoader.FindTemplatesWithRootName("", true, templatesType, rootName); +} + std::vector> CCmpTemplateManager::GetCivData() { std::vector> data; - std::vector names = m_templateLoader.FindTemplatesUnrestricted("special/players/", false); + std::vector names = m_templateLoader.FindTemplatesWithRootName("", true, SIMULATION_TEMPLATES, "Player"); data.reserve(names.size()); for (const std::string& name : names) { Index: source/simulation2/components/ICmpTemplateManager.h =================================================================== --- source/simulation2/components/ICmpTemplateManager.h +++ source/simulation2/components/ICmpTemplateManager.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -104,6 +104,13 @@ virtual std::vector FindAllTemplates(bool includeActors) const = 0; /** + * Returns a list of strings that could be validly passed as @c templateName to LoadTemplate. + * (Filters to only return templates with the correct root name.) + * This is likely to be quite slow. + */ + virtual std::vector FindTemplatesWithRootName(bool includeActors, const std::string& rootName) const = 0; + + /** * Returns some data of the civs from the templates. * Intended for use by the map editor. */ Index: source/simulation2/components/ICmpTemplateManager.cpp =================================================================== --- source/simulation2/components/ICmpTemplateManager.cpp +++ source/simulation2/components/ICmpTemplateManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -27,6 +27,7 @@ DEFINE_INTERFACE_METHOD("TemplateExists", ICmpTemplateManager, TemplateExists) DEFINE_INTERFACE_METHOD("GetCurrentTemplateName", ICmpTemplateManager, GetCurrentTemplateName) DEFINE_INTERFACE_METHOD("FindAllTemplates", ICmpTemplateManager, FindAllTemplates) +DEFINE_INTERFACE_METHOD("FindTemplatesWithRootName", ICmpTemplateManager, FindTemplatesWithRootName) DEFINE_INTERFACE_METHOD("GetCivData", ICmpTemplateManager, GetCivData) DEFINE_INTERFACE_METHOD("GetEntitiesUsingTemplate", ICmpTemplateManager, GetEntitiesUsingTemplate) END_INTERFACE_WRAPPER(TemplateManager) Index: source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp =================================================================== --- source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp +++ source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -95,7 +95,7 @@ CmpPtr cmpTemplateManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY); if (cmpTemplateManager) { - std::vector names = cmpTemplateManager->FindAllTemplates(true); + std::vector names = cmpTemplateManager->FindTemplatesWithRootName(true, "Entity"); for (std::vector::iterator it = names.begin(); it != names.end(); ++it) {