LosaDev Tools: Lost Saga modding tools in the browser

This commit is contained in:
LosaDev committed 2026-11-07 23:08:43 +07:00
commit c5e04472fb
105 files changed
+38541

No files matched your search

+12
View File
@@ -0,0 +1,12 @@
// "node:child_process": a browser cannot start programs. Features that run an external exe
// are left out of the web version; this only makes a clear error.
function unavailable() {
throw new Error("Running external programs is not possible in the browser (use the desktop LS Tools for this).");
}
export const spawn = unavailable;
export const spawnSync = unavailable;
export const execFile = unavailable;
export const execFileSync = unavailable;
export const exec = unavailable;
export const execSync = unavailable;
export default { spawn, spawnSync, execFile, execFileSync, exec, execSync };
+12
View File
@@ -0,0 +1,12 @@
// node:crypto subset used by the desktop modules.
export function randomBytes(n) {
const b = Buffer.alloc(n);
crypto.getRandomValues(b);
return b;
}
export function randomUUID() {
return crypto.randomUUID();
}
export default { randomBytes, randomUUID };
+21
View File
@@ -0,0 +1,21 @@
// "electron" for the ported main-process modules. Only app.getPath is used outside the dialogs
// (which the browser answers in src/legacy/bridge.js). userData is a virtual folder kept in the
// browser's IndexedDB (see vfs.takePersisted / restore).
const PATHS = { userData: "/userdata", temp: "/tmp", downloads: "/out", documents: "/out", desktop: "/out", home: "/out" };
export const app = {
getPath: (name) => PATHS[name] || `/userdata/${name}`,
getVersion: () => "web",
isPackaged: true,
};
const unavailable = (what) => () => {
throw new Error(`${what} is not available in the browser`);
};
export const dialog = { showOpenDialog: unavailable("dialog"), showSaveDialog: unavailable("dialog"), showMessageBox: unavailable("dialog") };
export const shell = { openPath: async () => "", showItemInFolder: () => {}, openExternal: async () => {} };
export const ipcMain = { handle: () => {}, on: () => {} };
export const BrowserWindow = class {};
export default { app, dialog, shell, ipcMain, BrowserWindow };
+9
View File
@@ -0,0 +1,9 @@
// node:fs/promises subset. Only Pack.optimize() uses it, which belongs to the removed
// IOP Manager; kept so the module loads, and fails clearly if anything calls it.
export async function open() {
const e = new Error("Writing new files is not available in the web version");
e.code = "EROFS";
throw e;
}
export default { open };
+7
View File
@@ -0,0 +1,7 @@
// "node:os" subset for the ported modules.
export const tmpdir = () => "/tmp";
export const homedir = () => "/out";
export const platform = () => "win32";
export const EOL = "\r\n";
export const cpus = () => [{}];
export default { tmpdir, homedir, platform, EOL, cpus };
+29
View File
@@ -0,0 +1,29 @@
// node:zlib subset used by the desktop modules, on fflate.
import { inflateSync, deflateSync } from "fflate";
const TABLE = (() => {
const t = new Uint32Array(256);
for (let n = 0; n < 256; n++) {
let c = n;
for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
t[n] = c >>> 0;
}
return t;
})();
export function crc32(buf, prev = 0) {
let c = ~prev >>> 0;
for (let i = 0; i < buf.length; i++) c = TABLE[(c ^ buf[i]) & 0xff] ^ (c >>> 8);
return ~c >>> 0;
}
export function inflateRawSync(buf) {
return Buffer.from(inflateSync(buf instanceof Uint8Array ? buf : new Uint8Array(buf)));
}
export function deflateRawSync(buf, opts = {}) {
const level = opts.level === undefined ? 6 : opts.level;
return Buffer.from(deflateSync(buf instanceof Uint8Array ? buf : new Uint8Array(buf), { level }));
}
export default { crc32, inflateRawSync, deflateRawSync };