refactor(maps): pyramid.yaml per piràmide amb merge a sala
This commit is contained in:
1 parent
5f206e03c8
commit
125cdd0c74
45 files changed
+331
-1085
No files matched your search
@@ -6,6 +6,7 @@
|
||||
#include "core/resources/resource_helper.hpp"
|
||||
#include "game/entities/entity.hpp"
|
||||
#include "game/entities/entity_factory.hpp"
|
||||
#include "game/map/room_yaml.hpp"
|
||||
#include "utils/defaults.hpp"
|
||||
|
||||
namespace EntityLoader {
|
||||
@@ -44,13 +45,7 @@ namespace EntityLoader {
|
||||
}
|
||||
|
||||
auto readSpawns(const std::string& level_yaml_path) -> std::vector<fkyaml::node> {
|
||||
auto bytes = Resource::Helper::loadFile(level_yaml_path);
|
||||
if (bytes.empty()) {
|
||||
throw std::runtime_error("EntityLoader: no s'ha pogut obrir " + level_yaml_path);
|
||||
}
|
||||
const auto* begin = reinterpret_cast<const char*>(bytes.data());
|
||||
const auto* end = begin + bytes.size();
|
||||
fkyaml::node root = fkyaml::node::deserialize(begin, end);
|
||||
fkyaml::node root = RoomYaml::loadMerged(level_yaml_path);
|
||||
std::vector<fkyaml::node> spawns;
|
||||
if (!root.contains("entities")) { return spawns; }
|
||||
const auto& list = root["entities"];
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
#include <stdexcept>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "core/resources/resource_helper.hpp"
|
||||
#include "external/fkyaml_node.hpp"
|
||||
#include "game/map/room_yaml.hpp"
|
||||
#include "utils/defaults.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
@@ -157,13 +157,7 @@ namespace Map {
|
||||
}
|
||||
|
||||
void loadFrom(const std::string& yaml_path) {
|
||||
auto bytes = Resource::Helper::loadFile(yaml_path);
|
||||
if (bytes.empty()) {
|
||||
throw std::runtime_error("Map: no s'ha pogut obrir " + yaml_path);
|
||||
}
|
||||
const auto* begin = reinterpret_cast<const char*>(bytes.data());
|
||||
const auto* end = begin + bytes.size();
|
||||
auto yaml = fkyaml::node::deserialize(begin, end);
|
||||
auto yaml = RoomYaml::loadMerged(yaml_path);
|
||||
if (!yaml.contains("geometry")) {
|
||||
throw std::runtime_error("Map: manca bloc `geometry:` a " + yaml_path);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
#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
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "external/fkyaml_node.hpp"
|
||||
|
||||
// Carregador de YAMLs de sala amb fusió per piràmide. Cada piràmide pot
|
||||
// tenir un `pyramid.yaml` germà al directori de sala que aporta camps
|
||||
// compartits (tileset, lighting, push_factor, paint_tiles...); el YAML
|
||||
// de sala només declara el que canvia (data, entities, geometry, room).
|
||||
//
|
||||
// Regles de fusió:
|
||||
// - mapes: fusió recursiva, claus de la sala guanyen
|
||||
// - sequences i escalars: la sala substitueix sencer
|
||||
//
|
||||
// Si no hi ha `pyramid.yaml` al directori, retorna només el YAML de sala
|
||||
// sense modificacions — així rutes externes (tests, mapes solts) segueixen
|
||||
// funcionant igual.
|
||||
namespace RoomYaml {
|
||||
|
||||
auto loadMerged(const std::string& room_yaml_path) -> fkyaml::node;
|
||||
|
||||
} // namespace RoomYaml
|
||||
@@ -9,8 +9,8 @@
|
||||
#include "core/rendering/screen.hpp"
|
||||
#include "core/rendering/surface.hpp"
|
||||
#include "core/resources/resource_cache.hpp"
|
||||
#include "core/resources/resource_helper.hpp"
|
||||
#include "external/fkyaml_node.hpp"
|
||||
#include "game/map/room_yaml.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
#ifdef _DEBUG
|
||||
@@ -41,13 +41,7 @@ namespace {
|
||||
} // namespace
|
||||
|
||||
Tilemap::Tilemap(const std::string& yaml_path) {
|
||||
auto bytes = Resource::Helper::loadFile(yaml_path);
|
||||
if (bytes.empty()) {
|
||||
throw std::runtime_error("Tilemap: no s'ha pogut obrir " + yaml_path);
|
||||
}
|
||||
const auto* begin = reinterpret_cast<const char*>(bytes.data());
|
||||
const auto* end = begin + bytes.size();
|
||||
auto yaml = fkyaml::node::deserialize(begin, end);
|
||||
auto yaml = RoomYaml::loadMerged(yaml_path);
|
||||
|
||||
tileset_path_ = yaml["tileset"].get_value<std::string>();
|
||||
tile_size_ = yaml["tile_size"].get_value<int>();
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "game/gameplay_config.hpp"
|
||||
#include "game/levels/level_manager.hpp"
|
||||
#include "game/map/map.hpp"
|
||||
#include "game/map/room_yaml.hpp"
|
||||
#include "game/options.hpp"
|
||||
#include "game/scenes/scene_flow.hpp"
|
||||
#include "game/scenes/start_input.hpp"
|
||||
@@ -65,21 +66,13 @@ namespace {
|
||||
// pinta amb l'índex declarat al mapa, i un mapa sense aquests camps
|
||||
// simplement no deixa rastre visual.
|
||||
auto readOptionalInt(const std::string& yaml_path, const std::string& key, int fallback = -1) -> int {
|
||||
auto bytes = Resource::Helper::loadFile(yaml_path);
|
||||
if (bytes.empty()) { return fallback; }
|
||||
const auto* begin = reinterpret_cast<const char*>(bytes.data());
|
||||
const auto* end = begin + bytes.size();
|
||||
auto yaml = fkyaml::node::deserialize(begin, end);
|
||||
auto yaml = RoomYaml::loadMerged(yaml_path);
|
||||
if (!yaml.contains(key)) { return fallback; }
|
||||
return yaml[key].get_value<int>();
|
||||
}
|
||||
|
||||
auto readOptionalFloat(const std::string& yaml_path, const std::string& key, float fallback) -> float {
|
||||
auto bytes = Resource::Helper::loadFile(yaml_path);
|
||||
if (bytes.empty()) { return fallback; }
|
||||
const auto* begin = reinterpret_cast<const char*>(bytes.data());
|
||||
const auto* end = begin + bytes.size();
|
||||
auto yaml = fkyaml::node::deserialize(begin, end);
|
||||
auto yaml = RoomYaml::loadMerged(yaml_path);
|
||||
if (!yaml.contains(key)) { return fallback; }
|
||||
return yaml[key].get_value<float>();
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user