卫戍协议:盟约 web remake — initial import
Online co-op browser remake of Arknights' Stronghold Protocol: Alliance (client-simulated combat, official waves/bonds/items/strategies, 3D board, facing wheel, operator loadout, official emotes, deployment scripts).
This commit is contained in:
commit
01a44cd288
408 files changed
+308986
No files matched your search
@@ -0,0 +1,59 @@
|
||||
// Copies client vendor libraries from node_modules into public/vendor (run by `npm run vendor` / postinstall).
|
||||
//
|
||||
// three.js (the official 3D board scene, DESIGN §15) ships as two ES modules: three.module.js imports
|
||||
// './three.core.js', so both are copied side by side and the renderer imports '/vendor/three.module.js' directly
|
||||
// (no import map, no CDN — LAN play works offline). Optional packages that are not installed are skipped with a
|
||||
// warning instead of failing the install.
|
||||
// Preact's hooks build imports the bare specifier "preact"; it is rewritten to the sibling './preact.module.js' (the
|
||||
// same URL the import map resolves "preact" to, so one Preact instance) — module graphs then load without import-map
|
||||
// support (Safari < 16.4).
|
||||
import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
||||
import { dirname, join } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const root = join(dirname(fileURLToPath(import.meta.url)), '..');
|
||||
const out = join(root, 'public', 'vendor');
|
||||
|
||||
/** Bare specifiers inside vendored ES modules → their sibling vendored file. */
|
||||
export const VENDOR_REWRITES = Object.freeze({ 'hooks.module.js': { preact: './preact.module.js' } });
|
||||
|
||||
/**
|
||||
* Rewrite `from"x"` / `from 'x'` / `import("x")` of the mapped bare specifiers in a vendored module source.
|
||||
* @param {string} src
|
||||
* @param {Record<string, string>} map
|
||||
*/
|
||||
export function rewriteBare(src, map) {
|
||||
let res = src;
|
||||
for (const [bare, rel] of Object.entries(map)) {
|
||||
const esc = bare.replace(/[.*+?^${}()|[\]\\/]/g, '\\$&');
|
||||
res = res.replace(new RegExp(`(\\bfrom\\s*|\\bimport\\s*\\(\\s*|\\bimport\\s*)(["'])${esc}\\2`, 'g'), (_, pre, q) => `${pre}${q}${rel}${q}`);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/** [source under the repo root, file name in public/vendor, optional] */
|
||||
export const VENDOR_FILES = Object.freeze([
|
||||
['node_modules/pixi.js/dist/pixi.min.js', 'pixi.min.js'],
|
||||
['node_modules/pixi-spine/dist/pixi-spine.js', 'pixi-spine.js'],
|
||||
['node_modules/preact/dist/preact.module.js', 'preact.module.js'],
|
||||
['node_modules/preact/hooks/dist/hooks.module.js', 'hooks.module.js'],
|
||||
['node_modules/htm/dist/htm.module.js', 'htm.module.js'],
|
||||
['node_modules/three/build/three.core.js', 'three.core.js', true],
|
||||
['node_modules/three/build/three.module.js', 'three.module.js', true],
|
||||
]);
|
||||
|
||||
export function vendor({ log = console.log, warn = console.warn } = {}) {
|
||||
mkdirSync(out, { recursive: true });
|
||||
const done = [];
|
||||
for (const [src, dst, optional] of VENDOR_FILES) {
|
||||
const from = join(root, src);
|
||||
if (optional && !existsSync(from)) { warn(`vendor: ${dst} skipped (${src} not installed; the 3D board falls back to 2D)`); continue; }
|
||||
if (VENDOR_REWRITES[dst]) writeFileSync(join(out, dst), rewriteBare(readFileSync(from, 'utf8'), VENDOR_REWRITES[dst]));
|
||||
else copyFileSync(from, join(out, dst));
|
||||
done.push(dst);
|
||||
log('vendor:', dst);
|
||||
}
|
||||
return done;
|
||||
}
|
||||
|
||||
if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) vendor();
|
||||
Reference in new issue
Block a user