isle-portable/ISLE/emscripten/filesystem.cpp
Christian Semmler 3d7bbdf0ae
Add third person camera extension
Introduces a third person camera system with orbit camera, input handling
(mouse/keyboard/touch/gamepad), display actor cloning, and camera-relative
movement. Includes shared character utilities (animator, cloner, customizer)
and an IExtraAnimHandler interface for optional animation extensions.
Also includes generic base game fixes and extension system improvements.
2026-03-29 08:20:57 -07:00

139 lines
3.9 KiB
C++

#include "filesystem.h"
#include "events.h"
#include "extensions/siloader.h"
#include "extensions/textureloader.h"
#include "legogamestate.h"
#include "misc.h"
#include "mxmain.h"
#include <SDL3/SDL_filesystem.h>
#include <SDL3/SDL_log.h>
#include <emscripten.h>
#include <emscripten/wasmfs.h>
static backend_t opfs = nullptr;
static backend_t fetchfs = nullptr;
extern const char* g_files[46];
extern const char* g_textures[120];
bool Emscripten_OPFSDisabled()
{
return MAIN_THREAD_EM_ASM_INT({return !!Module["disableOpfs"]});
}
bool Emscripten_SetupConfig(const char* p_iniConfig)
{
if (Emscripten_OPFSDisabled()) {
SDL_Log("OPFS is disabled; ignoring .ini path");
return false;
}
opfs = wasmfs_create_opfs_backend();
MxString iniConfig = p_iniConfig;
char* parse = iniConfig.GetData();
while ((parse = SDL_strchr(++parse, '/'))) {
*parse = '\0';
wasmfs_create_directory(iniConfig.GetData(), 0644, opfs);
*parse = '/';
}
return true;
}
void Emscripten_SetupFilesystem()
{
fetchfs = wasmfs_create_fetch_backend((MxString(Emscripten_streamHost) + "/LEGO").GetData(), 512 * 1024);
wasmfs_create_directory("/LEGO", 0644, fetchfs);
wasmfs_create_directory("/LEGO/Scripts", 0644, fetchfs);
wasmfs_create_directory("/LEGO/Scripts/Act2", 0644, fetchfs);
wasmfs_create_directory("/LEGO/Scripts/Act3", 0644, fetchfs);
wasmfs_create_directory("/LEGO/Scripts/Build", 0644, fetchfs);
wasmfs_create_directory("/LEGO/Scripts/Garage", 0644, fetchfs);
wasmfs_create_directory("/LEGO/Scripts/Hospital", 0644, fetchfs);
wasmfs_create_directory("/LEGO/Scripts/Infocntr", 0644, fetchfs);
wasmfs_create_directory("/LEGO/Scripts/Isle", 0644, fetchfs);
wasmfs_create_directory("/LEGO/Scripts/Police", 0644, fetchfs);
wasmfs_create_directory("/LEGO/Scripts/Race", 0644, fetchfs);
wasmfs_create_directory("/LEGO/data", 0644, fetchfs);
const auto registerFile = [](const char* p_path) {
MxString path = MxString(Emscripten_bundledPath) + MxString(p_path);
path.MapPathToFilesystem();
if (SDL_GetPathInfo(path.GetData(), NULL)) {
SDL_Log("File %s is bundled and won't be streamed", p_path);
}
else {
wasmfs_create_file(p_path, 0644, fetchfs);
MxOmni::GetCDFiles().emplace_back(p_path);
SDL_Log("File %s set up for streaming", p_path);
}
};
const auto preloadFile = [](const char* p_path) -> bool {
size_t length = 0;
void* data = SDL_LoadFile(p_path, &length);
if (data) {
SDL_free(data);
}
return length > 0;
};
for (const char* file : g_files) {
registerFile(file);
}
#ifdef EXTENSIONS
if (Extensions::TextureLoaderExt::enabled) {
MxString directory =
MxString("/LEGO") + Extensions::TextureLoaderExt::options["texture loader:texture path"].c_str();
Extensions::TextureLoaderExt::options["texture loader:texture path"] = directory.GetData();
wasmfs_create_directory(directory.GetData(), 0644, fetchfs);
MxU32 i = 0;
Emscripten_SendExtensionProgress("HD Textures", 0);
for (const char* file : g_textures) {
MxString path = directory + "/" + file + ".bmp";
registerFile(path.GetData());
if (!preloadFile(path.GetData())) {
Extensions::TextureLoaderExt::AddExcludedFile(file);
}
Emscripten_SendExtensionProgress("HD Textures", (++i * 100) / sizeOfArray(g_textures));
}
}
if (Extensions::SiLoaderExt::enabled) {
wasmfs_create_directory("/LEGO/extra", 0644, fetchfs);
for (const auto& file : Extensions::SiLoaderExt::GetFiles()) {
registerFile(file.c_str());
}
}
#endif
if (GameState()->GetSavePath() && *GameState()->GetSavePath() && !Emscripten_OPFSDisabled()) {
if (!opfs) {
opfs = wasmfs_create_opfs_backend();
}
MxString savePath = GameState()->GetSavePath();
if (savePath.GetData()[savePath.GetLength() - 1] != '/') {
savePath += "/";
}
char* parse = savePath.GetData();
while ((parse = SDL_strchr(++parse, '/'))) {
*parse = '\0';
wasmfs_create_directory(savePath.GetData(), 0644, opfs);
*parse = '/';
}
}
}