Public: anyone can read this; the crew can change it.
forked from trevato/cs
Physics moves into the engine and takes its tuning as data #7
`src/engine/physics.ts` now moves any body through any set of boxes and holds no Counter-Strike number: it exports `Body`, `Wish`, `MoveTuning`, `Hull`, `accelerate`, `airAccelerate`, `move`, `groundUnder`, `stuck`, `eyeHeight` and `hullHeight`, and every tuned value reaches it as a required argument in one boring order — subject, situation, tuning, hull: `move(body, wish, dt, boxes, tuning, hull)…
stopped closed without shipping deploy 2f47104
main is merged into this branch and the two landings stand together: src/engine/ is now math, trace, physics, mesh, texture and sound, while the game keeps its own numbers — CS_MOVE/CS_HULL and fall damage in src/client/movement.ts, and the asset recipes in models, materials and audio. boundary.test.ts still reads every file in src/engine/ and fails if one points at the game.
The only textual conflict was README's "Shape" section, where both sides had rewritten the same two bullets; it now names all six engine modules and both renames (textures → materials from main, physics → movement from here), and says which client modules are tuning and which are recipes. renderer.ts merged on its own and was checked by hand: it imports materials from main's side and engine/physics + movement from this one. The bundle both sides changed was rebuilt — static/app.46b3eaaa33.js and static/app.6864d577a4.js are replaced by static/app.c3680040c7.js, which the build reproduces byte for byte.
One test change, and it is not a conflict resolution: "a round is played out" simulates minutes of game at 64 Hz and crossed bun's default five-second timeout on a loaded machine, having passed on both parents. The test was right and the code was right; only the inherited wall-clock budget was wrong, so it and the whole-match test now state 60 s. bun test is 150 pass / 0 fail, and the server boots and answers / in 14 ms with the security floor intact.
To look at in the preview: a match played to the end (movement feel, step-ups and strafe gain come from the engine mover now) and the generated look and sound of it (meshes, atlas and audio come from the engine tools now) — the merge should be invisible in both.
🤖 Generated with Claude Code
Closed in the owner's sweep of 2026-10-12: a week old and in conflict with main now; the branch stays if anyone wants it back.
src/engine/physics.tsnow moves any body through any set of boxes and holds no Counter-Strike number: it exportsBody,Wish,MoveTuning,Hull,accelerate,airAccelerate,move,groundUnder,stuck,eyeHeightandhullHeight, and every tuned value reaches it as a required argument in one boring order — subject, situation, tuning, hull:move(body, wish, dt, boxes, tuning, hull),eyeHeight(body, hull),stuck(pos, height, boxes, hull),groundUnder(pos, height, boxes, reach, hull),airAccelerate(vel, dir, speed, dt, tuning). No parameter has a default, so nothing can substitute a tuning quietly. The Source numbers live in the newsrc/client/movement.tsasCS_MOVEandCS_HULL, withfallDamage— CS's curve, not physics — beside them. Two numbers needed a decision: the duck rate of 5/s was baked into the mover and is nowCS_MOVE.duckRate, and the two-unit floor contact stayed in the engine as a solver tolerance, namedCONTACTand documented as one rather than dressed up as tuning.The moved test is
src/client/movement.test.ts, notsrc/engine/physics.test.ts: it asserts today's numbers throughCS_MOVE, andboundary.test.tsforbids an engine module from importing the game, so the test that knows CS numbers belongs to the game. It keeps all eleven original assertions unchanged and adds four that run the same solver under a second profile — half gravity, a 144×48-unit hull, a 36-unit step, 500 u/s — including a hand-checked apex,v²/2g = 301.993²/1600 ≈ 57.0units under CS and≈ 114.0under half gravity, with hang time doubling. Re-baking gravity, the hull radius, the step size or the max speed into the engine fails exactly those four; I checked by doing it.Worth looking at in the preview: movement should feel bit-for-bit identical, and it is — 40 s of a seeded ten-bot round produces the same SHA-256 over every player's position, velocity, health and duck amount before and after (
47e39ec48b23de94). On the threading cost, this sandbox is loaded and noisy, so I interleaved runs and took minimums:scripts/train.ts --benchgives 7–8k steps/s on both the old and new code here (it reached 10–11k on both when the box was quiet, never the 13k the issue quotes for the forge's machine), and an isolated 300,000-tick mover benchmark against the full de_forge box set is 0.98 s before and 0.98 s after. I measured no regression, but the absolute number here is the sandbox's, not the forge's.src/rl/arena.tsneeded no change — it moves only throughworld.applyInput— andbun testis 123 pass / 0 fail with the rebuiltstatic/app.46b3eaaa33.jscommitted.🤖 Generated with Claude Code
Closes #3