feedback5 WAD: language packs are the first type of content packs — a language is a file in a language folder (public/i18n/<code>.json, optional data/i18n/<code>.json) or a pack folder (packs/<id>/pack.json); the server lists them live at /packs/index.json (server/packs.js), the menu shows every pack, strings fall back pack → base → declared fallback (English) → Chinese, broken placeholders are skipped, plurals follow Intl.PluralRules (English unchanged), English carries a _meta manifest like any pack; tools: i18n.mjs template / check <code>, packs.mjs list / index, build-i18n --lang ja|ko|zh-TW (the official JP / KR / TW clients); the release zip ships packs/ and a generated packs/index.json; golden unchanged
This commit is contained in:
1 parent
f1df0d359d
commit
25b2a87b26
22 files changed
+2222
-241
No files matched your search
+12
-6
@@ -5,7 +5,8 @@
|
||||
// which startServer() options go to net.js / lobby.js, the console logger
|
||||
// http/websocket.js session wiring (SessionRegistry → Lobby → Network) and the WebSocket at /ws (maxPayload 64 KB;
|
||||
// refused at upgrade with 404 / 429 per network / 503)
|
||||
// http/static.js the static mounts (/ → public/, /data/, /shared/, /sim/ `.js` only), the /data.js browser stand-in
|
||||
// http/static.js the static mounts (/ → public/, /data/, /shared/, /sim/ `.js` only), the /data.js browser stand-in,
|
||||
// the content packs (/packs/index.json, /packs/<id>/<file> — the registry is packs.js)
|
||||
// http/media.js /media/bgm/act1 → public/assets/audio/bgm/act1.mp3 (audio addressed without its extension)
|
||||
// http/files.js one file → response: MIME, gzip + memory cache, ETag / Last-Modified / 304, Cache-Control, ranges
|
||||
// http/buildTag.js the build tag of the served browser runtime (/healthz `build`, public/js/ui/buildGuard.js)
|
||||
@@ -24,6 +25,7 @@ import { getData, loadData } from './data.js';
|
||||
import { ROOT, listenAddress, serveDirs, makeLogger, parseTrustProxy } from './http/config.js';
|
||||
import { WS_MAX_PAYLOAD, createSessionStack, attachWebSocket } from './http/websocket.js';
|
||||
import { DATA_SHIM_JS, createStaticHandler } from './http/static.js';
|
||||
import { createPackRegistry } from './packs.js';
|
||||
import { MIME, COMPRESSIBLE, acceptsGzip, parseRange } from './http/files.js';
|
||||
import { BUILD_INPUTS, computeBuildTag, buildTag, resetBuildTag } from './http/buildTag.js';
|
||||
import { createRequestHandler } from './http/routes.js';
|
||||
@@ -40,7 +42,7 @@ export {
|
||||
* Build and start the HTTP + WebSocket server.
|
||||
* @param {{
|
||||
* port?: number, host?: string, quiet?: boolean, log?: object,
|
||||
* publicDir?: string, dataDir?: string, sharedDir?: string,
|
||||
* publicDir?: string, dataDir?: string, sharedDir?: string, packsDir?: string,
|
||||
* MatchClass?: Function, seedFn?: () => number,
|
||||
* lobbyGraceMs?: number, reconnectWindowMs?: number, heartbeatMs?: number, helloTimeoutMs?: number,
|
||||
* ratePerSec?: number, rateBurst?: number, maxConnections?: number, maxRooms?: number,
|
||||
@@ -49,17 +51,21 @@ export {
|
||||
* }} [opts]
|
||||
* @returns {Promise<{ port: number, host: string, url: string, server: http.Server, wss: import('ws').WebSocketServer,
|
||||
* lobby: import('./lobby.js').Lobby, network: import('./net.js').Network,
|
||||
* registry: import('./net.js').SessionRegistry, close: () => Promise<void> }>}
|
||||
* registry: import('./net.js').SessionRegistry, packs: ReturnType<typeof createPackRegistry>,
|
||||
* close: () => Promise<void> }>}
|
||||
*/
|
||||
export async function startServer(opts = {}) {
|
||||
const { port, host } = listenAddress(opts);
|
||||
const log = opts.log || makeLogger(!!opts.quiet);
|
||||
const { publicDir, dataDir, sharedDir } = serveDirs(opts);
|
||||
const { publicDir, dataDir, sharedDir, packsDir } = serveDirs(opts);
|
||||
|
||||
// The process-wide singleton serves the default data dir; a custom dir (tests) gets its own copy.
|
||||
const data = opts.dataDir ? loadData(dataDir, { log }) : getData({ dir: dataDir, log });
|
||||
const { registry, lobby, network } = createSessionStack(opts, { data, log });
|
||||
const serveStatic = createStaticHandler({ publicDir, dataDir, sharedDir, log });
|
||||
// content packs (docs/PACKS.md): scanned now — the start log names them — and again whenever their folders change
|
||||
const packs = createPackRegistry({ publicDir, dataDir, packsDir }, { log });
|
||||
packs.refresh(true);
|
||||
const serveStatic = createStaticHandler({ publicDir, dataDir, sharedDir, packsDir, packs, log });
|
||||
const startedAt = Date.now();
|
||||
// The tag is per process (see buildTag): read the browser runtime once, here, not on every /healthz.
|
||||
resetBuildTag();
|
||||
@@ -103,7 +109,7 @@ export async function startServer(opts = {}) {
|
||||
return closing;
|
||||
}
|
||||
|
||||
return { port: actualPort, host, url, server, wss, lobby, network, registry, close };
|
||||
return { port: actualPort, host, url, server, wss, lobby, network, registry, packs, close };
|
||||
}
|
||||
|
||||
// `node server/index.js` / npm start: listen, print the banner, stop on SIGINT / SIGTERM (http/boot.js).
|
||||
|
||||
Reference in new issue
Block a user