LosaDev Tools: Lost Saga modding tools in the browser
This commit is contained in:
commit
c5e04472fb
105 files changed
+38541
No files matched your search
@@ -0,0 +1,70 @@
|
||||
import { defineConfig } from "vite";
|
||||
|
||||
// The ported desktop modules import node:* modules; in the browser they map to small shims.
|
||||
// Root-relative paths on purpose: an absolute path made "node:fs" a different module URL than the
|
||||
// worker's own "./vfs.js" import, so two vfs instances existed and the ported modules saw no mounts.
|
||||
const nodeShims = {
|
||||
"node:fs": "/src/worker/vfs.js",
|
||||
"node:fs/promises": "/src/worker/shims/fs-promises.js",
|
||||
"node:zlib": "/src/worker/shims/zlib.js",
|
||||
"node:crypto": "/src/worker/shims/crypto.js",
|
||||
"node:path": "path-browserify",
|
||||
path: "path-browserify",
|
||||
"node:os": "/src/worker/shims/os.js",
|
||||
"node:child_process": "/src/worker/shims/child_process.js",
|
||||
electron: "/src/worker/shims/electron.js",
|
||||
};
|
||||
|
||||
// Exact matches only: "node:fs" must not also rewrite "node:fs/promises".
|
||||
const aliases = Object.entries(nodeShims).map(([find, replacement]) => ({ find: new RegExp(`^${find.replace(/[/:]/g, "\\$&")}$`), replacement }));
|
||||
|
||||
// Dev only: /__testgame/<file> serves files from LSTOOLS_TEST_DIR (a COPY of a client folder is
|
||||
// best), used with ?devgame=rs.iop,map.iop to test pages without the native folder picker.
|
||||
const testGame = {
|
||||
name: "losadev-test-game",
|
||||
apply: "serve",
|
||||
configureServer(server) {
|
||||
const dir = process.env.LSTOOLS_TEST_DIR;
|
||||
if (!dir) return;
|
||||
// Range requests: the worker reads the packs piecewise with sync XHR (vfs.remoteFile).
|
||||
server.middlewares.use("/__testgame/", async (req, res) => {
|
||||
const { createReadStream, statSync } = await import("node:fs");
|
||||
const { join, basename } = await import("node:path");
|
||||
const name = basename(decodeURIComponent(req.url.split("?")[0]));
|
||||
const file = join(dir, name);
|
||||
let size;
|
||||
try {
|
||||
size = statSync(file).size;
|
||||
} catch {
|
||||
res.statusCode = 404;
|
||||
return res.end();
|
||||
}
|
||||
res.setHeader("Accept-Ranges", "bytes");
|
||||
res.setHeader("Cache-Control", "no-store");
|
||||
if (req.method === "HEAD") {
|
||||
res.setHeader("Content-Length", size);
|
||||
return res.end();
|
||||
}
|
||||
const m = /bytes=(\d+)-(\d*)/.exec(req.headers.range || "");
|
||||
if (m) {
|
||||
const start = Number(m[1]);
|
||||
const end = Math.min(size - 1, m[2] ? Number(m[2]) : size - 1);
|
||||
res.statusCode = 206;
|
||||
res.setHeader("Content-Range", `bytes ${start}-${end}/${size}`);
|
||||
res.setHeader("Content-Length", end - start + 1);
|
||||
return createReadStream(file, { start, end }).pipe(res);
|
||||
}
|
||||
res.setHeader("Content-Length", size);
|
||||
createReadStream(file).pipe(res);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default defineConfig({
|
||||
server: { port: 4700 },
|
||||
plugins: [testGame],
|
||||
define: { __LEGACY_VER__: JSON.stringify(String(Date.now())) },
|
||||
resolve: { alias: aliases },
|
||||
worker: { format: "es", plugins: () => [] },
|
||||
build: { target: "es2022", sourcemap: true },
|
||||
});
|
||||
Reference in new issue
Block a user