Reintroduce apps/arcade and the ten game crates that were ripped out of
the fork (assets, audio, blocks, coedit, gen, net, pkg, render, script,
session), from makepad-internal/dev. Reconcile against the fork's layout:
- makepad-game-sim/math come from the fork's existing libs/sim + sim/math;
the copied internal libs/game/{sim,math} are dropped and the kept game
crates plus arcade point at ../../sim and ../../sim/math.
- arcade AI is rewritten off the removed makepad-ai agent API onto the
makepad-ai-hub headless ChatProvider worker (example/cad pattern):
AiWorker{send,cancel,poll}, ai_worker_loop driving
ClaudeApiChatProvider(ClaudeCli), AiWorkerEvent availability/delta/
done/error mapped into the chat feed and authoring land_edit, with
main.rs send_message/cancel_request/event-drain rebuilt around it.
- the game-script sandbox is adapted to the fork's jailed splash storage:
every isolate gets mod.fs = splash_storage jail; splaes splash_storage
set_root_for_heap is now public so the ScriptHost (or Splash) can grant
a per-game jail root. ENT font: build.rs/dispatch.rs entities fill new
fork sim Entity/Part fields via ..Default::default(); world_raycast now
borrows mutably and returns the material id.
cargo check -p makepad-arcade and the game + arcade test suites pass.
Point the workspace at libs/asset and libs/render. Drop Arcade
frontend, gamemaker, rig, pack registry, physics, and the old
libs/game gameplay crates. Those live in the private sandbox repo.
**The HUD was never drawn.** `libs/game/render::hud` has existed and
gamemaker has called it all along; arcade simply never did. So the
interact prompt was computed every tick, published to `world.hud_slots`,
and thrown away — the get-in-a-car mechanic was discoverable only by
guessing the key. Same shape as the gamepad never being polled: the
capability was there and the app never called it.
Two things found while wiring it:
- The prompt asked for `size: 1.0`, which reads like a scale but is an
absolute point size to the renderer — any value above zero is taken
literally. It would have drawn a one-point speck. Now 17.0, deliberately
above the 12.0 default, since this is the one line a player has to
notice without being told to look.
- Added a standing controls hint. Nobody sits a child down with a manual,
and the affordance prompt only appears once you are already next to
something; this is what tells you how to get there.
**Arcade could not build headless.** The gamepad poll was added without
the `cfg(headless)` split gamemaker uses, and arcade had no `build.rs` to
define the cfg at all, so `MAKEPAD=headless` failed to compile and the
render-to-PNG path went with it.
**The walking camera sat too close** — at 6.5m the character filled a
fifth of the frame and hid the world behind them. Now 9.0m.
That broke a test asserting `car.distance > on_foot * 1.5`, and the fix
is the test, not the number. That ratio read like a decision but was
really the quotient of two values that happened to be current, so
correcting the walking boom on its own merits broke an assertion about
driving while nothing about driving had changed. Restated as a margin:
what has to hold is that getting into a car visibly widens the view, and
several metres does that at any walking distance.
Also logs gamepad connect/disconnect on change, so "the pad does nothing"
is answerable from a release log — either the app never saw the device or
it saw it and the mapping is at fault.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>