#include "core/jail/jfile.hpp" #include #include #include #include #include #include #include #ifndef _WIN32 #include #endif namespace { struct keyvalue { std::string key; std::string value; }; std::vector config; std::string resource_folder; std::string config_folder; void load_config_values() { config.clear(); const std::string config_file = config_folder + "/config.txt"; std::ifstream fi(config_file); if (!fi.is_open()) { return; } std::string line; while (std::getline(fi, line)) { const auto eq = line.find('='); if (eq == std::string::npos) { continue; } config.push_back({line.substr(0, eq), line.substr(eq + 1)}); } } void save_config_values() { const std::string config_file = config_folder + "/config.txt"; std::ofstream fo(config_file); if (!fo.is_open()) { return; } for (const auto& pair : config) { fo << pair.key << '=' << pair.value << '\n'; } } } // namespace void file_setresourcefolder(const char* str) { resource_folder = str; } auto file_getresourcefolder() -> const char* { return resource_folder.c_str(); } // Crea la carpeta del sistema on guardar les dades. // Accepta rutes amb subdirectoris (ex: "jailgames/aee") i crea tota la jerarquia. void file_setconfigfolder(const char* foldername) { #ifdef _WIN32 const char* base = getenv("APPDATA"); if (!base) base = "C:/"; config_folder = std::string(base) + "/" + foldername; #elif __APPLE__ struct passwd* pw = getpwuid(getuid()); const char* homedir = (pw && pw->pw_dir) ? pw->pw_dir : nullptr; if (!homedir) homedir = getenv("HOME"); if (!homedir) homedir = "/tmp"; config_folder = std::string(homedir) + "/Library/Application Support/" + foldername; #elif __linux__ // Nota emscripten: `__linux__` també està definit, però `getpwuid` pot // retornar nullptr (sense /etc/passwd al MEMFS) o un passwd amb pw_dir // buit. Amb els fallbacks HOME → /tmp evitem crashejar al primer // arranque dins del navegador. La config no persistirà entre recàrregues // (MEMFS és volàtil); caldria IDBFS si volguéssem persistència a web. struct passwd* pw = getpwuid(getuid()); const char* homedir = ((pw != nullptr) && (pw->pw_dir != nullptr) && (pw->pw_dir[0] != 0)) ? pw->pw_dir : nullptr; if ((homedir == nullptr) || (homedir[0] == 0)) { homedir = getenv("HOME"); } if ((homedir == nullptr) || (homedir[0] == 0)) { homedir = "/tmp"; } config_folder = std::string(homedir) + "/.config/" + foldername; #else config_folder = std::string("/tmp/jailgames_config/") + foldername; #endif std::error_code ec; std::filesystem::create_directories(config_folder, ec); // A emscripten/MEMFS create_directories pot fallar (p.ex. parent // read-only o libc++ amb path empty-check estricte). La config és // volàtil al navegador de totes formes: ignorem l'error i continuem. } auto file_getconfigfolder() -> const char* { thread_local std::string folder; folder = config_folder + "/"; return folder.c_str(); } auto file_getconfigvalue(const char* key) -> const char* { if (config.empty()) { load_config_values(); } const auto it = std::find_if(config.begin(), config.end(), [key](const keyvalue& pair) { return pair.key == key; }); if (it != config.end()) { thread_local std::string value_cache; value_cache = it->value; return value_cache.c_str(); } return nullptr; } void file_setconfigvalue(const char* key, const char* value) { if (config.empty()) { load_config_values(); } const auto it = std::find_if(config.begin(), config.end(), [key](const keyvalue& pair) { return pair.key == key; }); if (it != config.end()) { it->value = value; save_config_values(); return; } config.push_back({std::string(key), std::string(value)}); save_config_values(); }