fix(editor): preferDisk en Debug + reload de sala al entrar i sortir
This commit is contained in:
1 parent
2a78c78e77
commit
d13313503c
4 files changed
+106
-15
No files matched your search
@@ -15,12 +15,18 @@ namespace Resource::Helper {
|
|||||||
Pack g_pack;
|
Pack g_pack;
|
||||||
bool g_pack_loaded = false;
|
bool g_pack_loaded = false;
|
||||||
bool g_fallback_enabled = true;
|
bool g_fallback_enabled = true;
|
||||||
|
// Inverteix la prioritat (disc abans que pack). Activat en Debug
|
||||||
|
// per defecte; veure setPreferDisk al header.
|
||||||
|
bool g_prefer_disk = false;
|
||||||
|
|
||||||
auto readFromDisk(const std::string& filepath) -> std::vector<std::uint8_t> {
|
auto readFromDisk(const std::string& filepath, bool verbose = true) -> std::vector<std::uint8_t> {
|
||||||
const auto FULL = resolve(filepath);
|
const auto FULL = resolve(filepath);
|
||||||
std::ifstream file(FULL, std::ios::binary | std::ios::ate);
|
std::ifstream file(FULL, std::ios::binary | std::ios::ate);
|
||||||
if (!file) {
|
if (!file) {
|
||||||
std::cerr << "Resource::Helper: cannot open " << FULL << '\n';
|
// Silenciem si veníem de prefer_disk: aleshores caurem
|
||||||
|
// al pack i no és cap error real que el fitxer no estigui
|
||||||
|
// al disc.
|
||||||
|
if (verbose) { std::cerr << "Resource::Helper: cannot open " << FULL << '\n'; }
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
std::streamsize size = file.tellg();
|
std::streamsize size = file.tellg();
|
||||||
@@ -37,6 +43,11 @@ namespace Resource::Helper {
|
|||||||
|
|
||||||
auto initializeResourceSystem(const std::string& pack_file, bool enable_fallback) -> bool {
|
auto initializeResourceSystem(const std::string& pack_file, bool enable_fallback) -> bool {
|
||||||
g_fallback_enabled = enable_fallback;
|
g_fallback_enabled = enable_fallback;
|
||||||
|
// En el flux Debug típic (fallback actiu, source tree disponible)
|
||||||
|
// preferim sempre disc: el desenvolupador edita YAML/GIF a `data/`
|
||||||
|
// i ho veu reflectit al següent reload sense re-packejar. En
|
||||||
|
// Release el fallback està desactivat i aquest flag és inert.
|
||||||
|
g_prefer_disk = enable_fallback;
|
||||||
g_pack_loaded = g_pack.loadPack(pack_file);
|
g_pack_loaded = g_pack.loadPack(pack_file);
|
||||||
|
|
||||||
if (g_pack_loaded) {
|
if (g_pack_loaded) {
|
||||||
@@ -76,17 +87,45 @@ namespace Resource::Helper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto loadFile(const std::string& filepath) -> std::vector<std::uint8_t> {
|
auto loadFile(const std::string& filepath) -> std::vector<std::uint8_t> {
|
||||||
if (g_pack_loaded) {
|
// Helper local: lookup al pack normalitzant la clau (els callers
|
||||||
// El pack està indexat relatiu a `data/` (la carpeta que
|
// passen "data/foo.yaml" però l'índex del pack és relatiu a la
|
||||||
// s'empaqueta), però els callers passen "data/foo.yaml" amb
|
// carpeta `data/`).
|
||||||
// prefix. Fem el strip ací perquè no hagin de tenir-ho en compte.
|
const auto FROM_PACK = [&filepath]() -> std::vector<std::uint8_t> {
|
||||||
|
if (!g_pack_loaded) { return {}; }
|
||||||
constexpr std::string_view PREFIX = "data/";
|
constexpr std::string_view PREFIX = "data/";
|
||||||
std::string key = filepath;
|
std::string key = filepath;
|
||||||
if (key.starts_with(PREFIX)) { key.erase(0, PREFIX.size()); }
|
if (key.starts_with(PREFIX)) { key.erase(0, PREFIX.size()); }
|
||||||
if (g_pack.hasResource(key)) { return g_pack.getResource(key); }
|
if (g_pack.hasResource(key)) { return g_pack.getResource(key); }
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
|
||||||
|
if (g_prefer_disk && g_fallback_enabled) {
|
||||||
|
// En Debug volem que el disc guanyi: així les edicions del
|
||||||
|
// editor in-game (i les manuals del repo) es vegen al pròxim
|
||||||
|
// reload sense rebuild del pack. Si el fitxer no és al disc,
|
||||||
|
// caiem al pack — útil per a recursos que només s'han
|
||||||
|
// empaquetat (cas estrany). El silenci a `readFromDisk` evita
|
||||||
|
// emplenar el log amb "cannot open" en aquest camí esperat.
|
||||||
|
auto bytes = readFromDisk(filepath, false);
|
||||||
|
if (!bytes.empty()) { return bytes; }
|
||||||
|
return FROM_PACK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Política original: pack primer; disc com a fallback si el
|
||||||
|
// recurs no està empaquetat (típic d'arrencada en Debug abans
|
||||||
|
// del primer pack).
|
||||||
|
auto packed = FROM_PACK();
|
||||||
|
if (!packed.empty()) { return packed; }
|
||||||
if (g_fallback_enabled) { return readFromDisk(filepath); }
|
if (g_fallback_enabled) { return readFromDisk(filepath); }
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setPreferDisk(bool prefer) {
|
||||||
|
g_prefer_disk = prefer;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto preferDisk() -> bool {
|
||||||
|
return g_prefer_disk;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Resource::Helper
|
} // namespace Resource::Helper
|
||||||
@@ -32,7 +32,17 @@ namespace Resource::Helper {
|
|||||||
// Carrega un recurs pel seu camí relatiu (p.ex. "fonts/hud.gif",
|
// Carrega un recurs pel seu camí relatiu (p.ex. "fonts/hud.gif",
|
||||||
// "input/keys.yaml"). Prova primer el pack; si no hi és i el fallback
|
// "input/keys.yaml"). Prova primer el pack; si no hi és i el fallback
|
||||||
// està actiu, cau a disc (data root + ruta). Retorna vector buit si
|
// està actiu, cau a disc (data root + ruta). Retorna vector buit si
|
||||||
// no el troba.
|
// no el troba. Si `preferDisk()` és true (Debug), inverteix la
|
||||||
|
// prioritat: prova disc abans del pack.
|
||||||
auto loadFile(const std::string& filepath) -> std::vector<std::uint8_t>;
|
auto loadFile(const std::string& filepath) -> std::vector<std::uint8_t>;
|
||||||
|
|
||||||
|
// Inverteix la prioritat de `loadFile` (disc abans que pack). En Debug
|
||||||
|
// s'activa per defecte al `initializeResourceSystem` perquè cada
|
||||||
|
// canvi al YAML/GIF al source tree es vegi sense re-packejar — és el
|
||||||
|
// que necessita l'editor in-game per veure les seues edicions
|
||||||
|
// immediatament al recarregar la sala. En Release no té efecte
|
||||||
|
// (el fallback està desactivat).
|
||||||
|
void setPreferDisk(bool prefer);
|
||||||
|
[[nodiscard]] auto preferDisk() -> bool;
|
||||||
|
|
||||||
} // namespace Resource::Helper
|
} // namespace Resource::Helper
|
||||||
@@ -607,6 +607,30 @@ void GameScene::enterRoomIntro() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
void GameScene::respawnPlayersInstant() {
|
||||||
|
// Variant sense cinemàtica de l'spawn de l'INTRO: per a l'editor
|
||||||
|
// volem que la sala torni a un estat jugable d'immediat (sense
|
||||||
|
// música de sala, sense caiguda aèria). Reusem `computeSpawn` i el
|
||||||
|
// mateix patró de `triggerPlayerSpawn` però cridem `respawn(x, y)`
|
||||||
|
// (teleport instantani) en lloc de `spawnFromAir(x, y)`.
|
||||||
|
const auto SPAWN = computeSpawn();
|
||||||
|
const bool BOTH_ACTIVE = (players_starts_active_[0] && players_starts_active_[1]);
|
||||||
|
const float SINGLE_X = SPAWN.p1_x + static_cast<float>(Map::tile_size);
|
||||||
|
for (std::size_t i = 0; i < players_.size(); ++i) {
|
||||||
|
if (!players_starts_active_[i]) { continue; }
|
||||||
|
float x = SINGLE_X;
|
||||||
|
if (BOTH_ACTIVE) { x = (i == 0) ? SPAWN.p1_x : SPAWN.p2_x; }
|
||||||
|
players_[i]->setSpawnPoint(x, SPAWN.y);
|
||||||
|
players_[i]->respawn(x, SPAWN.y);
|
||||||
|
}
|
||||||
|
state_ = RoomFsm::State::PLAYING;
|
||||||
|
intro_completed_ = true;
|
||||||
|
transition_ = {};
|
||||||
|
std::cout << "[ROOM] post-editor: spawn instantani, estat -> PLAYING\n";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void GameScene::triggerPlayerSpawn(std::size_t slot_index) {
|
void GameScene::triggerPlayerSpawn(std::size_t slot_index) {
|
||||||
if (slot_index >= players_.size()) { return; }
|
if (slot_index >= players_.size()) { return; }
|
||||||
if (!players_starts_active_[slot_index]) { return; }
|
if (!players_starts_active_[slot_index]) { return; }
|
||||||
@@ -1141,17 +1165,28 @@ void GameScene::update(int delta_ms) {
|
|||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
// Toggle de l'editor: només si no hi ha cap transició de pausa ni
|
// Toggle de l'editor: només si no hi ha cap transició de pausa ni
|
||||||
// pausa consolidada. L'editor mateix no consumeix la tecla — la
|
// pausa consolidada. L'editor mateix no consumeix la tecla — la
|
||||||
// llegim ací per decidir la coexistència. Quan se surt del editor,
|
// llegim ací per decidir la coexistència. Tant a l'entrada com a la
|
||||||
// recarreguem les entitats des del YAML perquè el manager torne a
|
// sortida fem `loadRoom` complet per partir sempre del YAML del
|
||||||
// estar sincronitzat amb el que el writer acaba de desar (cada
|
// disc: les entitats tornen a la posició inicial (momies, sarcs),
|
||||||
// sessió d'edició parteix del fitxer, no de l'estat runtime previ).
|
// el paint layer es buida i els jugadors es desactiven. Així
|
||||||
|
// l'editor sempre veu l'estat-base de la sala (no el d'una partida
|
||||||
|
// a meitat) i el joc, en sortir, arrenca fresc amb les edicions ja
|
||||||
|
// persistides al YAML.
|
||||||
if (pause_.state == PauseState::IDLE && detectEditorToggle()) {
|
if (pause_.state == PauseState::IDLE && detectEditorToggle()) {
|
||||||
const bool WAS_ACTIVE = editor_.active();
|
const bool WAS_ACTIVE = editor_.active();
|
||||||
editor_.toggle(tilemap_, entity_manager_);
|
editor_.toggle(tilemap_, entity_manager_);
|
||||||
if (WAS_ACTIVE) {
|
const bool NOW_ACTIVE = editor_.active();
|
||||||
entity_manager_.reload(Levels::LevelManager::get().currentPath());
|
if (!WAS_ACTIVE && NOW_ACTIVE) {
|
||||||
const int ACTIVE_COUNT = std::ranges::count(players_starts_active_, true);
|
// Acabem d'entrar: carreguem fresh des del disc. Els
|
||||||
entity_manager_.setExpectedPlayerCount(ACTIVE_COUNT);
|
// jugadors es queden DISABLED (l'editor no els pinta de
|
||||||
|
// totes maneres) i es reactivaran amb el spawn instantani
|
||||||
|
// a la sortida.
|
||||||
|
loadRoom(Levels::LevelManager::get().currentPath());
|
||||||
|
} else if (WAS_ACTIVE && !NOW_ACTIVE) {
|
||||||
|
// Acabem de sortir: el writer ja ha persistit el YAML.
|
||||||
|
// Carreguem fresh i fem spawn instantani sense cinemàtica.
|
||||||
|
loadRoom(Levels::LevelManager::get().currentPath());
|
||||||
|
respawnPlayersInstant();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -288,6 +288,13 @@ class GameScene : public Scene {
|
|||||||
// Idempotent quan ja s'estava a INTRO — útil per als salts debug.
|
// Idempotent quan ja s'estava a INTRO — útil per als salts debug.
|
||||||
void enterRoomIntro();
|
void enterRoomIntro();
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
// Spawn instantani sense cinemàtica: usat al sortir del editor per
|
||||||
|
// fer un "fresh start" de la sala (jugadors al spawn, sense la
|
||||||
|
// cinemàtica `room_intro.ogg`). Posa l'estat directament a PLAYING.
|
||||||
|
void respawnPlayersInstant();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
// Editor modal del tilemap. Mútuament excloent amb la pausa: si la
|
// Editor modal del tilemap. Mútuament excloent amb la pausa: si la
|
||||||
// pausa no està IDLE la tecla de toggle de l'editor s'ignora, i
|
// pausa no està IDLE la tecla de toggle de l'editor s'ignora, i
|
||||||
|
|||||||
Reference in new issue
Block a user