67 lines
2.6 KiB
C++
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
|