132 lines
4.9 KiB
C++
132 lines
4.9 KiB
C++
#include "core/resources/resource_helper.hpp"
|
|
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <string_view>
|
|
|
|
#include "core/resources/resource_pack.hpp"
|
|
|
|
namespace Resource::Helper {
|
|
|
|
namespace {
|
|
|
|
std::string g_data_root;
|
|
Pack g_pack;
|
|
bool g_pack_loaded = false;
|
|
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, bool verbose = true) -> std::vector<std::uint8_t> {
|
|
const auto FULL = resolve(filepath);
|
|
std::ifstream file(FULL, std::ios::binary | std::ios::ate);
|
|
if (!file) {
|
|
// 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 {};
|
|
}
|
|
std::streamsize size = file.tellg();
|
|
file.seekg(0, std::ios::beg);
|
|
std::vector<std::uint8_t> data(static_cast<std::size_t>(size));
|
|
if (!file.read(reinterpret_cast<char*>(data.data()), size)) {
|
|
std::cerr << "Resource::Helper: failed to read " << FULL << '\n';
|
|
return {};
|
|
}
|
|
return data;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
auto initializeResourceSystem(const std::string& pack_file, bool enable_fallback) -> bool {
|
|
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);
|
|
|
|
if (g_pack_loaded) {
|
|
std::cout << "Resource::Helper: pack loaded (" << g_pack.getResourceCount()
|
|
<< " entries) from " << pack_file << '\n';
|
|
} else if (enable_fallback) {
|
|
std::cout << "Resource::Helper: no pack at " << pack_file
|
|
<< " — using filesystem fallback\n";
|
|
} else {
|
|
std::cerr << "Resource::Helper: FATAL — no pack at " << pack_file
|
|
<< " and fallback disabled\n";
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void shutdownResourceSystem() {
|
|
g_pack.clear();
|
|
g_pack_loaded = false;
|
|
}
|
|
|
|
auto hasPack() -> bool {
|
|
return g_pack_loaded;
|
|
}
|
|
|
|
void setDataRoot(const std::string& absolute_path) {
|
|
g_data_root = absolute_path;
|
|
if (!g_data_root.empty() && g_data_root.back() != '/') {
|
|
g_data_root += '/';
|
|
}
|
|
}
|
|
|
|
auto resolve(const std::string& filepath) -> std::string {
|
|
if (filepath.empty() || filepath.front() == '/') { return filepath; }
|
|
if (g_data_root.empty()) { return filepath; }
|
|
return g_data_root + filepath;
|
|
}
|
|
|
|
auto loadFile(const std::string& filepath) -> std::vector<std::uint8_t> {
|
|
// Helper local: lookup al pack normalitzant la clau (els callers
|
|
// passen "data/foo.yaml" però l'índex del pack és relatiu a la
|
|
// carpeta `data/`).
|
|
const auto FROM_PACK = [&filepath]() -> std::vector<std::uint8_t> {
|
|
if (!g_pack_loaded) { return {}; }
|
|
constexpr std::string_view PREFIX = "data/";
|
|
std::string key = filepath;
|
|
if (key.starts_with(PREFIX)) { key.erase(0, PREFIX.size()); }
|
|
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); }
|
|
return {};
|
|
}
|
|
|
|
void setPreferDisk(bool prefer) {
|
|
g_prefer_disk = prefer;
|
|
}
|
|
|
|
auto preferDisk() -> bool {
|
|
return g_prefer_disk;
|
|
}
|
|
|
|
} // namespace Resource::Helper
|