diff --git a/emscripten/deps.js b/emscripten/deps.js new file mode 100644 index 0000000000..21110acdb0 --- /dev/null +++ b/emscripten/deps.js @@ -0,0 +1,82 @@ + +var EmscriptenDeps = { + ExportPersistantData: () => + { + if (!window.JSZip) + { + alert("JSZip library not found. Aborting"); + return; + } + const zipFolder = (folder) => + { + let zip = new JSZip(); + const processFolder = (name) => { + let contents; + try { + contents = Module.FS.readdir(name); + } catch(e) { + return; + } + contents.forEach((entry) => { + if ([".", ".."].includes(entry)) return; + try { + Module.FS.readFile(name + entry); + processFile(name + entry); + } catch(e) { + processFolder(name + entry + "/"); + } + }) + } + const processFile = (name) => { + zip.file(name, Module.FS.readFile(name)); + } + processFolder(folder); + return zip; + } + const zip = zipFolder("/persistant/"); + zip.generateAsync({type: "blob"}).then(blob => { + const a = document.createElement("a"); + + a.href = URL.createObjectURL(blob); + a.download = "OpenRCT2-emscripten.zip"; + a.click(); + setTimeout(() => URL.revokeObjectURL(a.href), 1000); + }) + }, + ImportPersistantData: () => + { + if (!window.JSZip) + { + alert("JSZip library not found. Aborting"); + return; + } + if (!confirm("Are you sure? This will wipe all current data.")) return; + alert("Select a zip file"); + const input = document.createElement("input"); + input.type = "file"; + input.addEventListener("change", async (e) => { + let zip = new JSZip(); + try { + zip = await zip.loadAsync(e.target.files[0]); + } catch(e) { + alert("Not a zip file!"); + return; + } + await clearDatabase("/persistant/"); + for (const k in zip.files) { + const entry = zip.files[k]; + if (entry.dir) { + try { + Module.FS.mkdir("/"+k); + } catch(e) {} + } else { + Module.FS.writeFile("/"+k, await entry.async("uint8array")); + } + } + console.log("Database restored"); + }) + input.click(); + } +}; + +mergeInto(LibraryManager.library, EmscriptenDeps); diff --git a/emscripten/static/index.js b/emscripten/static/index.js index 44823e8c17..b0215dbbaa 100644 --- a/emscripten/static/index.js +++ b/emscripten/static/index.js @@ -39,49 +39,6 @@ { console.log("loading", fileName); return fileName; - }, - funcs: { - export: () => - { - const zip = zipFolder("/persistant/"); - zip.generateAsync({type: "blob"}).then(blob => { - const a = document.createElement("a"); - - a.href = URL.createObjectURL(blob); - a.download = "OpenRCT2-emscripten.zip"; - a.click(); - setTimeout(() => URL.revokeObjectURL(a.href), 1000); - }) - }, - import: () => - { - if (!confirm("Are you sure? This will wipe all current data.")) return; - alert("Select a zip file"); - const input = document.createElement("input"); - input.type = "file"; - input.addEventListener("change", async (e) => { - let zip = new JSZip(); - try { - zip = await zip.loadAsync(e.target.files[0]); - } catch(e) { - alert("Not a zip file!"); - return; - } - await clearDatabase("/persistant/"); - for (const k in zip.files) { - const entry = zip.files[k]; - if (entry.dir) { - try { - Module.FS.mkdir("/"+k); - } catch(e) {} - } else { - Module.FS.writeFile("/"+k, await entry.async("uint8array")); - } - } - console.log("Database restored"); - }) - input.click(); - } } }); @@ -247,31 +204,6 @@ async function clearDatabase(dir) { processFolder(dir); await new Promise(res => Module.FS.syncfs(false, res)); } -function zipFolder(folder) { - let zip = new JSZip(); - const processFolder = (name) => { - let contents; - try { - contents = Module.FS.readdir(name); - } catch(e) { - return; - } - contents.forEach((entry) => { - if ([".", ".."].includes(entry)) return; - try { - Module.FS.readFile(name + entry); - processFile(name + entry); - } catch(e) { - processFolder(name + entry + "/"); - } - }) - } - const processFile = (name) => { - zip.file(name, Module.FS.readFile(name)); - } - processFolder(folder); - return zip; -} function fileExists(path) { try { Module.FS.readFile(path); diff --git a/src/openrct2-ui/CMakeLists.txt b/src/openrct2-ui/CMakeLists.txt index 14ec176c33..dc94b9dcab 100644 --- a/src/openrct2-ui/CMakeLists.txt +++ b/src/openrct2-ui/CMakeLists.txt @@ -18,7 +18,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Emscripten") endif () set(SHARED_FLAGS "-fexceptions") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${USE_FLAGS} ${SHARED_FLAGS}") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${EMSCRIPTEN_LDFLAGS} --bind ${SHARED_FLAGS} -s EXPORTED_FUNCTIONS=_GetVersion,_main") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${EMSCRIPTEN_LDFLAGS} --bind ${SHARED_FLAGS} -s EXPORTED_FUNCTIONS=_GetVersion,_main --js-library ${ROOT_DIR}/emscripten/deps.js") find_package(SpeexDSP REQUIRED) elseif (MSVC) find_package(SDL2 REQUIRED) diff --git a/src/openrct2-ui/windows/Options.cpp b/src/openrct2-ui/windows/Options.cpp index b40f50d85a..0ca04608cc 100644 --- a/src/openrct2-ui/windows/Options.cpp +++ b/src/openrct2-ui/windows/Options.cpp @@ -48,6 +48,10 @@ #ifdef __EMSCRIPTEN__ #include + extern "C" { + extern void ExportPersistantData(); + extern void ImportPersistantData(); + } #endif using namespace OpenRCT2; @@ -1987,10 +1991,10 @@ namespace OpenRCT2::Ui::Windows break; #ifdef __EMSCRIPTEN__ case WIDX_EXPORT_EMSCRIPTEN_DATA: - MAIN_THREAD_EM_ASM({ Module.funcs.export(); }); + ExportPersistantData(); break; case WIDX_IMPORT_EMSCRIPTEN_DATA: - MAIN_THREAD_EM_ASM({ Module.funcs.import(); }); + ImportPersistantData(); break; #endif } diff --git a/src/openrct2/CMakeLists.txt b/src/openrct2/CMakeLists.txt index 0d3b2e19ee..9b206087e8 100644 --- a/src/openrct2/CMakeLists.txt +++ b/src/openrct2/CMakeLists.txt @@ -122,7 +122,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Emscripten") endif () set(SHARED_FLAGS "-fexceptions") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${USE_FLAGS} ${SHARED_FLAGS}") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${EMSCRIPTEN_LDFLAGS} --bind ${SHARED_FLAGS}") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${EMSCRIPTEN_LDFLAGS} --bind ${SHARED_FLAGS} --js-library ${ROOT_DIR}/emscripten/deps.js") find_package(SpeexDSP REQUIRED) elseif (MSVC) find_package(png 1.6 REQUIRED)