155 lines
6.4 KiB
Markdown
155 lines
6.4 KiB
Markdown
# Bevy Remote Protocol (BRP)
|
||
|
||
The editor enables Bevy’s built-in **Remote Plugin** over HTTP for automation, CI, and future tooling interop. BRP is **editor-only** — the shipped `game` binary does not expose a port.
|
||
|
||
## Enablement
|
||
|
||
`BrpPlugin` in `crates/editor/src/ext/brp.rs` adds:
|
||
|
||
- `RemotePlugin` — core remote API
|
||
- `RemoteHttpPlugin` — HTTP transport
|
||
|
||
Launch the editor with dev features as usual:
|
||
|
||
```bash
|
||
cargo run -p editor --features dev
|
||
```
|
||
|
||
Default HTTP endpoint follows Bevy 0.19 remote defaults (port **15702**, routes under `/remote/`).
|
||
|
||
## Authoring-only mutation policy
|
||
|
||
**BRP and durable automation must mutate authoring components only** — the same allowlist used on
|
||
scene save in `scene_io.rs`. Hydration rebuilds runtime ECS (`Mesh3d`, Bevy lights, physics,
|
||
`WorldAssetRoot`, etc.) on the next frame. One deliberate editor-only exception exists for
|
||
`MaterialPropertyBlocks`: trusted local tooling may inject this explicitly runtime-only component
|
||
to preview or promote a transient override. It is still excluded from scene/prefab persistence and
|
||
the Add Component registry.
|
||
|
||
| Allowed (examples) | Forbidden on level objects |
|
||
|--------------------|----------------------------|
|
||
| `Transform`, `Name`, `ActorKind` | `PointLight`, `SpotLight`, `DirectionalLight` |
|
||
| `Primitive`, `StaticMeshRenderer`, `SkinnedMeshRenderer`, brush-only legacy `MaterialDesc`, `LightDesc` | `Mesh3d`, `MeshMaterial3d`, `RigidBody`, `Collider` |
|
||
| `ModelRef`, `RigidBodyDesc`, `ColliderDesc`, legacy `PhysicsBody`, gameplay markers | `WorldAssetRoot`, generated static/skinned roots, internal visibility types |
|
||
| `PostProcessVolumeDesc` | Runtime post-process components on cameras |
|
||
|
||
`shared::renderer_material::MaterialPropertyBlocks` is a runtime diagnostic/tooling exception, not
|
||
a durable authoring component. Use **Promote to Material Instance** in the exact Inspector slot when
|
||
the variation should become project content.
|
||
|
||
Prefer:
|
||
|
||
1. Editing `LightDesc` instead of `SpotLight` / `DirectionalLight`
|
||
2. Editing the owning `Primitive.surface` or renderer `MaterialSlotSet` instead of `StandardMaterial` handles; `MaterialDesc` is limited to the brush/legacy fallback path
|
||
3. Editing `StaticMeshRenderer` instead of child `Mesh3d` entities
|
||
4. Editing `SkinnedMeshRenderer` instead of its hydrated joint/mesh hierarchy
|
||
5. Editing `ColliderDesc` / `RigidBodyDesc` instead of runtime Avian components
|
||
6. Version-controlled `assets/levels/*.scn.ron` for durable changes
|
||
|
||
See [ADR 0009 — Authoring vs hydrated](../adr/0009-authoring-vs-hydrated.md).
|
||
|
||
## Example flows
|
||
|
||
### List entities
|
||
|
||
```bash
|
||
curl -s http://127.0.0.1:15702/remote/world/entities | head
|
||
```
|
||
|
||
### Get entity components
|
||
|
||
```bash
|
||
curl -s -X POST http://127.0.0.1:15702/remote/world/get \
|
||
-H 'Content-Type: application/json' \
|
||
-d '{"entity":4294967296,"components":["bevy_transform::Transform"]}'
|
||
```
|
||
|
||
### Mutate authoring transform (automation smoke)
|
||
|
||
```bash
|
||
curl -s -X POST http://127.0.0.1:15702/remote/world/mutate \
|
||
-H 'Content-Type: application/json' \
|
||
-d '{"entity":4294967296,"component":"bevy_transform::Transform","value":{"translation":[0,2,0]}}'
|
||
```
|
||
|
||
Replace `entity` with a live id from the list call while the editor is running.
|
||
|
||
### Mutate `LightDesc` (not runtime lights)
|
||
|
||
```bash
|
||
curl -s -X POST http://127.0.0.1:15702/remote/world/mutate \
|
||
-H 'Content-Type: application/json' \
|
||
-d '{"entity":ENTITY_ID,"component":"shared::components::LightDesc","value":{...}}'
|
||
```
|
||
|
||
Hydration applies the change to viewport lighting after the next update.
|
||
|
||
### Mutate `PostProcessVolumeDesc`
|
||
|
||
```bash
|
||
curl -s -X POST http://127.0.0.1:15702/remote/world/mutate \
|
||
-H 'Content-Type: application/json' \
|
||
-d '{"entity":ENTITY_ID,"component":"shared::components::PostProcessVolumeDesc","value":{...}}'
|
||
```
|
||
|
||
Overrides use `None` = inherit project; `Some(v)` = local override per field.
|
||
|
||
## Editor command palette bridge
|
||
|
||
Registered commands in `extensibility.rs` are invokable via **Ctrl+P** and `PendingEditorCommands`:
|
||
|
||
| Command | Action |
|
||
|---------|--------|
|
||
| `play.toggle` | Edit / Play |
|
||
| `play.toggle_pause` | Pause / resume sim in Play |
|
||
| `play.toggle_possession` | Possess / eject (Play only) |
|
||
| `scene.reset_lighting` | Remove all authored `LightDesc`; use project sun/ambient |
|
||
| `selection.group` | Spawn empty group; reparent selection |
|
||
| `selection.focus` | Frame editor camera on selection (same as **F**) |
|
||
| `rendering.create_volume` | Spawn post-process volume at editor camera |
|
||
| `rendering.select_volumes_at_camera` | Select highest-priority volume at camera |
|
||
| `rendering.focus_active_volumes` | Select + frame volumes at camera |
|
||
|
||
External automation can enqueue the same names through the editor command queue when integrated.
|
||
|
||
## CI / headless validation
|
||
|
||
Validate committed levels and prefab dependency graphs without the editor UI:
|
||
|
||
```bash
|
||
cargo validate-levels
|
||
# JSON for CI, packaging, or external tools
|
||
cargo validate-levels --json
|
||
```
|
||
|
||
This runs the shared `scene::validate_project` report used by the editor Diagnostics window. It
|
||
validates authored levels and recursive prefab/composition graphs, emits an owner-attributed
|
||
dependency manifest, reports blocking content references, and exits nonzero on errors.
|
||
`--project <path>` validates another project root. The graph pass validates link paths, stable actor
|
||
identity, cycles, anchors, and override payloads without starting the editor. The same report scans
|
||
project settings and asset roots, registry/import dependencies, generated mesh manifests, material
|
||
and shader documents, post effects, brush geometry, collider dimensions, Git LFS hydration, and
|
||
platform requirements. Validation and packaging share one runtime-inclusion policy: hidden/editor
|
||
trees, source formats such as PSD/Blend, symlinks, and unreadable traversal are blocking when a
|
||
runtime dependency reaches them. `asset.git_lfs_object_missing` is blocking; run `git lfs pull` in
|
||
the project checkout and rerun validation before building a package.
|
||
|
||
```bash
|
||
cargo test -p shared
|
||
cargo test -p scene
|
||
cargo check -p editor --features dev
|
||
```
|
||
|
||
## Safety
|
||
|
||
- Run BRP only in trusted local dev environments.
|
||
- Do not enable `BrpPlugin` in production game builds.
|
||
- Scene files remain the source of truth; prefer version-controlled `assets/levels/*.scn.ron` over live mutation for durable changes.
|
||
|
||
## Related
|
||
|
||
- [Editor architecture](architecture.md)
|
||
- [Debt audit checklist](debt-audit.md)
|
||
- [Mission — BRP-aligned tooling](../mission.md)
|
||
- [Release notes](release-notes.md)
|