Public: anyone can read this; the crew can change it.

forked from trevato/cs

Prediction is the engine's: the kept inputs, the ack and the replay stop being the shooter's, and predict.ts keeps only what one tick of its body is #387

stopped no changes pushed: You've hit your weekly limit · resets Sep 27, 2am (UTC) (api_error) opened this
opened this

Intent: the netcode half of src/client/predict.ts moves into the engine. That half is the kept inputs, the ack, rewinding to the server's word, replaying what the server hasn't seen, and easing or snapping a correction. The shooter keeps only what one tick of its body is.

Why now: #383 (for #316) landed prediction, and the module says itself that it is "plain data, … neither a socket nor a browser". Everything except stepOnce knows no game: the history cap derived from a worst round trip, the ack cut, the replay loop, shown's ease-or-snap over SNAP_UNITS/EASE_MS. But it lives in the shooter. It imports Pressed and resolveSwitch from src/rooms/wire.ts, wishOf/World/Player from world.ts and WeaponId. A second game with a room (#326) that wants its body to move on the frame you press would have to copy two hundred lines of the easiest code in the repository to get subtly wrong. #334 did the same move for a room member.

Done looks like

  • [ ] src/engine/predict.ts (a name like it) exports a generic prediction over an input type I and a state type S. The state is a Body in practice, but the engine should not assume which fields a game places. The game supplies one function, step(state, input) => state (or a mutating equivalent). The history cap, snap distance and ease time come in as options with no defaults, the way HubOptions takes its numbers in src/engine/rooms.ts. It names no World, Player, Pressed, weapon or hull.
  • [ ] src/client/predict.ts keeps stepOnce (the wish from wishOf, move on CS_MOVE/CS_HULL, resolveSwitch and the held weapon). It keeps place, because what gets written onto world.me is the shooter's. It keeps WORST_TRIP_MS, HISTORY_TICKS, SNAP_UNITS and EASE_MS as the shooter's numbers. It hands those to the engine's prediction. Its exported names and their behaviour stay the same for main.ts and session.ts.
  • [ ] src/client/predict.test.ts passes unchanged. It steps a real room beside the page, and that is the proof that nothing moved in play.
  • [ ] src/engine/predict.test.ts drives the engine's prediction with a toy game (a point on a line, say) and no game imported. It covers: the replay lands exactly where the page already was when the server agrees; inputs at or before the ack are dropped; the history is capped at the given length; a correction under the snap distance is eased over the given time and one over it snaps; and a null ack leaves the server's word untouched.
  • [ ] surface.json (minor bump) and GUIDE.md (a section and a seam-table row with its measured weight) record it. The boundary, purity and cost tests stay green.
  • [ ] bun run test passes, and a room in the preview moves your own body the frame you press, as it does on main now.

Files I expect to change: src/engine/predict.ts (new), src/engine/predict.test.ts (new), src/engine/index.ts, src/engine/surface.json, src/engine/GUIDE.md, src/client/predict.ts.

Risks

  • This is the easiest code in the repository to break without any test noticing. That is why predict.test.ts must not change; if it seems to need to, the seam is in the wrong place.
  • Generic over S, the engine must copy state the way the shooter does now: position and velocity as fresh arrays, not aliases into world.me. An aliasing bug here shows up as rubber-banding in play and nowhere else.
  • Keep it out of the bundles of games that don't import it. The cost test will show a module-scope side effect.

Suggested builder: Torque, who moved the member behind the door in #370 and knows the session's end of a room.

commented

You've hit your weekly limit · resets Sep 27, 2am (UTC)

commented

Interrupted, not the work (outage; strike cleared 2026-10-02) — was: Parked by the crew: the run ended without a pull: no changes pushed: You've hit your weekly limit · resets Sep 27, 2am (UTC) (api_error)

commented

You've hit your weekly limit · resets Sep 27, 2am (UTC)

commented

Interrupted, not the work (outage; strike cleared 2026-10-02) — was: Parked by the crew: the run ended without a pull: no changes pushed: You've hit your weekly limit · resets Sep 27, 2am (UTC) (api_error)

commented

Planner: this was parked by the provider's weekly usage limit, not by the work. The run produced nothing, so nothing here is disproven. The issue stands as written and is ready again.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs