#include "game/entities/entity_loader.hpp" #include #include #include #include "game/entities/entity.hpp" #include "game/entities/entity_factory.hpp" namespace EntityLoader { namespace { // Cache de plantilles parsejades. La primera crida llegeix disc; // les següents reben una còpia del node cacheat. fkyaml::node és // cost-barat de copiar (vector de shared_ptr internament). auto templateCache() -> std::unordered_map& { static std::unordered_map k_cache_; return k_cache_; } auto templatePath(const std::string& name) -> std::string { return "data/entities/" + name + "/" + name + ".yaml"; } } // namespace auto loadTemplate(const std::string& name) -> fkyaml::node { auto& cache = templateCache(); auto it = cache.find(name); if (it != cache.end()) { return it->second; } const std::string PATH = templatePath(name); std::ifstream file(PATH); if (!file.is_open()) { throw std::runtime_error("EntityLoader: no s'ha pogut obrir " + PATH); } fkyaml::node node = fkyaml::node::deserialize(file); cache.emplace(name, node); return node; } auto readSpawns(const std::string& level_yaml_path) -> std::vector { std::ifstream file(level_yaml_path); if (!file.is_open()) { throw std::runtime_error("EntityLoader: no s'ha pogut obrir " + level_yaml_path); } fkyaml::node root = fkyaml::node::deserialize(file); std::vector spawns; if (!root.contains("entities")) { return spawns; } const auto& list = root["entities"]; if (!list.is_sequence()) { return spawns; } spawns.reserve(list.size()); // cppcheck-suppress useStlAlgorithm for (const auto& item : list) { spawns.push_back(item); } return spawns; } auto createByType(const std::string& type) -> std::unique_ptr { try { fkyaml::node tmpl = loadTemplate(type); return EntityFactory::instance().create(type, tmpl); } catch (const std::exception&) { return nullptr; } } } // namespace EntityLoader