A WWII browser shooter with bots, split-screen and LAN multiplayer for up to 16 players. The upgraded client uses Babylon.js with WebGPU/WebGL2, a TypeScript/Vite build, and a 60 Hz simulation clock. Dawnville and all 23 firearm models load directly into Babylon. The four showcase weapons also have articulated prototype hands, sleeves and visible reload ammunition. Soldier bodies and helmets are native procedural Babylon geometry. Movement, stance, collision, hitscan and aim math run in the shared gameplay core; supplemental scene controls and effects still use the transition layer. The classic renderer remains available.
The eight detailed production plans prioritize the Dawnville showcase. This is still an implementation in progress: final authored animation, measured COD2 handling, the other maps' art and dedicated server authority are not complete. The current execution record lists delivered work, verification evidence and remaining acceptance boundaries.
All project commands and start.bat cap owned child processes to the same six CPU cores
on Windows/Linux, with compiler/Blender worker counts capped as well. Run expensive jobs
sequentially. npm run test:check runs the serial CPU integration checks; npm run audit:production
verifies recorded asset integrity and reports the remaining release gates.
Install Node.js 22.12 or newer (Node 20.19+ is also supported).
Double-click start.bat (it installs dependencies on first run, builds the client when
needed, starts the server, and opens the game) — or run npm install once and then npm start. Then press
START HOSTING.
Solo play works too — pick a map and bots from the menu; friends can join an in-progress match. Choose DAWNVILLE to play the rebuilt map. New map, weapon and prop art is enabled by default; no special launch URL is required.
Run npm run build and publish the contents of dist/ to GitHub Pages or another static host.
The build uses relative URLs, so project subpaths work. The existing source-only Pages
configuration still serves the classic client until you switch publishing to the build output.
The build contains the normal client at index.html, the original script client at
legacy/index.html, and the Blender gallery at assets/preview.html.
Limitation: LAN/hosted multiplayer does not work from Pages — HOST/JOIN needs the WebSocket
relay in server.js, and Pages only serves static files. For multiplayer, run the game locally
with start.bat / npm start as described below.
One browser is the authoritative host (whoever presses START HOSTING). Everyone else connects
to that PC. The server (server.js) can run on any machine the others can reach — usually the host
runs both.
- LAN (same network): the server prints
http://<your-lan-ip>:8666lines on startup. Friends open one of those addresses in a browser and press JOIN. - Internet: friends outside your network need a path in. Forward TCP port 8666 on your
router to the host PC, then share
http://<your-public-ip>:8666. (Find your public IP at any "what is my IP" site.) This is the only setup needed — there is no separate relay or account.
Notes:
- Traffic is plain HTTP/WebSocket (no encryption) — fine for a game shared with friends; don't use it for anything sensitive.
- The cap is 16 total (host + clients + bots); bots backfill empty slots up to the cap.
- Change the port with the
PORTenv var (e.g.PORT=9000 npm start); forward/share that port instead.
src/main.ts starts the modern client. src/rendering/babylon-renderer.ts owns Babylon GPU
rendering; src/rendering/native-assets.ts handles native asset ownership and lifecycle.
packages/game-core/ provides engine-independent timing and random primitives.
vite.config.mts bundles the remaining classic scripts into one shared lexical scope while
their responsibilities are extracted. The raw index.html still supports the classic path.
The existing gameplay files retain this load order:
| File | Contents |
|---|---|
js/00-config.js |
tunables (CFG) + the in-page self-test harness (window.__cod2) |
js/01-logic.js |
pure, unit-tested gameplay logic + WEAPONS table + settings (S) |
js/02-engine.js |
renderer, sky/lights, procedural textures & materials |
js/03-world.js |
map-building toolkit + the MAPS builders |
js/04-modes.js |
CTF / Headquarters / Search & Destroy |
js/05-viewmodels.js |
first-person gun models |
js/05a-assets.js |
default Blender weapon/prop imports, world-weapon mounting and authored-map routing with safe fallbacks |
js/06-fighters.js |
soldier models, spawning, nav grid + A* pathfinding |
js/07-combat.js |
movement/physics, raycasts, shooting, damage |
js/08-botai.js |
bot decision-making |
js/09-fx-audio.js |
particles, decals, synthesized audio |
js/10-players.js |
local players, weapon actions, HUD |
js/11-flow.js |
match flow, loadout screens, menu wiring |
js/12-net.js |
LAN multiplayer (host/client over the relay) |
js/13-main.js |
input + main loop + boot |
Load-order rule: code that runs at load time may only call things defined in the same or an earlier file (function declarations don't hoist across script files).
cod2_normandy.html (the game's previous single-file home) is kept as a redirect to index.html.
The asset library now contains 26 original assets: all 23 firearms, a rebuilt Dawnville
map, a wooden supply crate and a steel obstacle. The approved M1 Garand remains unchanged;
22 additional guns cover the rest of the roster. Every asset has an editable .blend
source and a self-contained .glb export. See
assets/README.md for previews, rebuilding and import instructions.
With the server running, open /assets/preview.html to inspect all 26 assets and download
their Blender sources or GLBs. The gallery redraws on interaction, not continuously.
Weapons load lazily for first-person and soldier/world views. A failed download keeps its
procedural fallback; ?assets=procedural restores the old art for comparison.
Dawnville's authored architecture loads through Babylon's native glTF path, bypassing the Three-to-Babylon geometry bridge. Weapons and props still use that bridge, and the map keeps its existing gameplay collision/navigation layout. These are first-pass rigid models: the current hands and whole-weapon reload motion remain, with authored animation clips, LODs and final artist review still to come.
npm test— relay routing unit tests (server.test.js).npm run test:launcher— eight Windows startup checks without opening a browser, including missing Node paths, port conflicts and visible error handling.npm run test:mp— built enhanced client, two low-resolution hardware browsers and the real relay; do not run alongside Blender/browser stress tests.npm run test:static— built/legacy file serving, local model/WASM delivery and malformed-path regression checks with one temporary server.npm run typecheck— TypeScript interfaces and engine adapter.npm run test:core— fixed-step replay, timing and seeded randomness.npm run test:rendering— 10 native-asset lifecycle, stale-load and ownership checks without a browser.npm run test:logic— existing pure gameplay checks without a browser; reports integration exclusions.npm run test:handling— local/client/host shot parity and remote pose replication.npm run test:assets— Khronos glTF validation and Blender export-contract checks.npm run test:town-layout— rebuilt Dawnville's collision, spawn, objective and supply-crate preservation.npm run test:presentation— lazy weapon initialization, muzzle flashes and asynchronous shadow settings.node tools/verify/asset_defaults_test.cjs— 28 catalog/style/socket, clone, fallback and map-import contract checks, including explicit procedural opt-out.node tools/verify/trigger_test.js— fire-discipline logic (extracted fromjs/01-logic.js).- In-page suite: open
index.html?selftest=1(or drive it headlessly withtools/verify/cdp.js, seetools/verify/README.md) → expectALL PASS: <N>.
npm run test:modern checks the built client in one hardware-rendered Chromium browser,
including gameplay, default asset imports and split-screen. Set CHROME_BIN if Edge is not installed
at the default Windows path. -- --all-maps --all-modes adds map/mode smoke coverage;
-- --all-weapons checks the full imported firearm roster;
-- --tour --gallery captures Town viewpoints and checks the asset workshop;
-- --webgpu --high checks high-quality WebGPU; -- --selftest runs the full in-page suite;
-- --default-start checks the plain launch URL with automatic graphics and default assets;
-- --legacy checks the modern build's classic rendering path. Image checks reject black
world output, including each split-screen view. These are short smoke checks,
not 16-player performance or full-match acceptance tests.
See the phase ledger and the full plan. The full firearm roster and one rebuilt map now have first-pass authored assets. Remaining maps, final weapon/environment detail, hands and authored animations, LODs, exact reference handling, dedicated server authority and production performance gates are still pending. An implemented import path or a passing contract test is not final visual acceptance; see the ledger for the latest browser results and outstanding review gates.
?renderer=legacy: classic rendering in the modern build.?backend=webgl: Babylon WebGL2 instead of automatic WebGPU selection.- New Blender models are enabled by default;
?assets=proceduralrestores the original art. Existing?assets=blenderlinks still work. npm run dev: local development client onhttp://localhost:5173(LAN relay proxies to port 8666).COD2_CLIENT=legacy: environment option to serve raw classic sources from the Node server.