Monorepo for Aesthetic.Computer aesthetic.computer
core menu-fighter ARCHITECTURE.md
3.8 kB
Markdown

Cross-platform architecture #

Menu Fighter should begin as one web-native game with thin platform hosts. The rollback core already has the property that matters most: deterministic, snapshot-complete state. Keep that core independent of browsers, rendering, controllers, accounts, and network APIs.

Layer boundaries #

platform host       web / WKWebView / Xbox host
        |           lifecycle, controller, audio, store services
presentation        paint, menus, animation, accessibility
        |
match coordinator   lobby, handshake, rounds, replay, disconnects, referee
        |
rollback session    input delay, prediction, rewind, checksums, time sync
        |
transport adapter   loopback / WebRTC / native datagram / replay file
        |
deterministic sim   Int32 state + input bits + seed -> next state

Only the bottom simulation layer decides hits, movement, timers, meter, wins, or random outcomes. Rendering and audio consume leading-frame events and never run during rollback replay.

Platform plan #

Target First shipping shape Input Online transport
Web AC piece at /menu-fighter Gamepad API + keyboard WebRTC data channel
macOS Swift WKWebView host derived from macos/fight-runner GameController bridge same in-page WebRTC adapter
Xbox validate on hardware, then choose ID@Xbox-compatible native host Windows.Gaming.Input WebRTC if supported; native datagram adapter otherwise

The macOS runner is the shortest route to a distributable app because it already hosts the live piece and polls native controllers. It should gain app identity, signing, fullscreen/window policy, deep links, and release packaging without absorbing gameplay code.

Xbox is deliberately a gate, not an assumption. The repository contains both a UWP WebView shell and a native DirectX/XAudio2/QuickJS BIOS. Microsoft currently directs game distribution through ID@Xbox, while its Xbox WebView guidance is not consistent across documentation. Prove the chosen renderer, network API, controller latency, suspend/resume, and Store path on real hardware before the product depends on it. The transport boundary lets Xbox use a native datagram channel without changing rollback or the sim.

For Xbox↔web crossplay, “native datagram adapter” also implies a compatible edge gateway unless the Xbox host embeds a WebRTC data-channel implementation. The gateway forwards common Menu Fighter packets; it never translates gameplay state or becomes a second simulation implementation.

Shared contracts #

The first extraction should be interfaces, not copied implementation:

transport.send(Uint8Array)
transport.onPacket = (Uint8Array) => {}
transport.close()

host.controllers.sample() // stable per-frame bitmasks
host.audio.emit(eventBits) // leading frames only
host.storage.get/set()

Network packets should be binary and versioned. A match handshake must include protocol version, build/content hash, simulation rules hash, fighter choices, stage/rules choice, random seed, player seat, and requested input delay. Refuse the match on incompatible hashes rather than allowing a late desync.

Build and content strategy #

For the first vertical slice, macOS and web load the same deployed or local AC content. Pin competitive builds to an immutable content version once matchmaking exists. Xbox may bundle the same JS modules if the runtime passes determinism and performance probes; otherwise compile or port only the platform boundary, not game rules ad hoc.

Do not move the current fight files yet. Imports and tests already anchor them, and an early move would obscure whether failures came from product scaffolding or gameplay changes. Extract after the direct-peer milestone, with the existing spec suite running unchanged before and after.