Files

67 lines
2.6 KiB
C++

#include "game/map/room_yaml.hpp"
#include <stdexcept>
#include "core/resources/resource_helper.hpp"
namespace RoomYaml {
namespace {
// Fusiona `overlay` damunt `base` in-place. Recursió només per a
// mapes; per a la resta (escalars, sequences) la `overlay` substitueix
// l'entrada de `base`. Manté l'ordre de claus de `base` per a les
// que ja hi eren; les noves s'afegeixen al final.
void deepMerge(fkyaml::node& base, const fkyaml::node& overlay) {
if (!overlay.is_mapping()) { return; }
for (const auto& kv : overlay.as_map()) {
const auto KEY = kv.first.get_value<std::string>();
const auto& val = kv.second;
if (base.contains(KEY) && base[KEY].is_mapping() && val.is_mapping()) {
deepMerge(base[KEY], val);
} else {
base[KEY] = val;
}
}
}
auto deserializeFile(const std::string& path) -> fkyaml::node {
auto bytes = Resource::Helper::loadFile(path);
if (bytes.empty()) {
throw std::runtime_error("RoomYaml: no s'ha pogut obrir " + path);
}
const auto* begin = reinterpret_cast<const char*>(bytes.data());
const auto* end = begin + bytes.size();
return fkyaml::node::deserialize(begin, end);
}
// Retorna el directori del path (sense barra final). Si no hi ha
// separador, retorna cadena buida.
auto dirOf(const std::string& path) -> std::string {
const auto POS = path.find_last_of('/');
if (POS == std::string::npos) { return ""; }
return path.substr(0, POS);
}
} // namespace
auto loadMerged(const std::string& room_yaml_path) -> fkyaml::node {
const auto DIR = dirOf(room_yaml_path);
const auto PYRAMID_PATH = DIR.empty() ? std::string{"pyramid.yaml"} : (DIR + "/pyramid.yaml");
// El pyramid.yaml és opcional: si Resource::Helper::loadFile el
// troba (disc o pack), el fem servir com a base; si no, només
// retornem el YAML de sala tal qual.
auto pyramid_bytes = Resource::Helper::loadFile(PYRAMID_PATH);
auto room = deserializeFile(room_yaml_path);
if (pyramid_bytes.empty()) { return room; }
const auto* begin = reinterpret_cast<const char*>(pyramid_bytes.data());
const auto* end = begin + pyramid_bytes.size();
auto merged = fkyaml::node::deserialize(begin, end);
deepMerge(merged, room);
return merged;
}
} // namespace RoomYaml