# ADR 0004: Editor Gameplay Hot Reload

## Status

Accepted

## Context

Iterating on FPS controller feel (sim movement, player input, camera presentation) required restarting the entire editor after every Rust change. Full restarts are slow (GPU init, egui layout, scene reload) and break flow.

Competing approaches:

1. **Full editor restart** — simple; too slow for gameplay iteration.
2. **Subprocess game binary** — preserves editor shell; breaks in-process viewport render-to-texture (cross-process GPU sharing).
3. **In-process dylib hot reload** — keeps one world and PIE model; swaps gameplay function bodies via [`hot-lib-reloader`](https://github.com/rksm/hot-lib-reloader-rs).

## Decision

Add dev-only **in-process hot reload** for the full `GamePlugin` surface:

| Layer | Crate | Hot reload? |
|-------|-------|-------------|
| Components, resources, TypeIds | `protocol`, `shared`, `settings`, `sim` | Static (never swapped) |
| Gameplay system bodies | `game_hot` (cdylib + rlib) | Yes |
| Plugin registration shell | `game`, `editor` | Static |
| Editor UI | `editor` | Static |

Implementation:

- [`crates/game_hot`](../../crates/game_hot) holds `#[unsafe(no_mangle)]` systems (sim, player, world, rendering bootstrap).
- [`game`](../../crates/game) registers systems once; with `hot-reload` feature, [`hot_module`](../../crates/game/src/lib.rs) wraps dylib functions.
- [`editor`](../../crates/editor) `HotReloadPlugin` (enabled via `dev` feature) polls `LibReloadObserver`, watches the dylib with `notify`, shows status in the bottom bar, and supports **Ctrl+Shift+R** manual refresh.
- `on_hot_reload` re-applies idempotent bootstrap (camera FX tags, ambient light); spawns guard against duplicate player/world entities.

Release builds omit `hot-reload`; shipped game binary links `game_hot` statically.

## Consequences

- Gameplay iteration no longer requires editor restart for logic-only changes.
- Component layout or schedule graph changes still require a full restart (documented in README).
- Linux uses a single `target/` directory; Windows may need separate bin/dylib target dirs to avoid DLL locking (follow-up).
- `dev` feature on editor implies `hot-reload` (not optional in daily dev workflow).

## Related

- [Editor architecture](../editor/architecture.md)
- [Editor roadmap — Phase 3](../editor/roadmap.md)
- [ADR 0003: Editor Framework Mission](0003-editor-framework-mission.md)
