Checkpoint 2: integrate native Editor, MCP, gameplay builds and standalone export
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
# Native Editor extensions
|
||||
|
||||
Editor extensions are startup-loaded `.so`/`.dll` modules. They are trusted native
|
||||
code inside the Editor process. Gameplay remains statically linked into the separate
|
||||
Player; an Editor extension is never required by the exported game.
|
||||
|
||||
The initial SDK registers commands and small action panels. Inspector fields for
|
||||
runtime components come from the separate gameplay SchemaExporter. Rich custom
|
||||
widgets and a general marketplace/package manager are later work.
|
||||
|
||||
## Example: Beacon
|
||||
|
||||
`examples/extensions/beacon` contains:
|
||||
|
||||
- `Beacon.hpp`: a runtime component schema and rotating-object behavior.
|
||||
- `Editor.cpp`: an Editor command and a panel that creates a Beacon in one transaction.
|
||||
|
||||
Include `Beacon.hpp` from your project's `Scripts/Gameplay.cpp`. Call
|
||||
`beacon::register_behavior(runtime)` from `registerGameplay`, and append
|
||||
`beacon::schema()` to the array returned by `schema()`. Build gameplay so the Editor
|
||||
can load the new metadata. Read [the first behavior tutorial](../scripting/first-behavior.md)
|
||||
for the complete gameplay registration convention.
|
||||
|
||||
The normal engine build produces `example-plugin/` inside its build directory.
|
||||
Copy its `beacon.faset-plugin.json` and native library into your project's
|
||||
`Plugins/` directory, then restart the Editor. The **Beacon tools** panel offers
|
||||
**Add Beacon**. Its command is also discoverable through MCP as
|
||||
`plugin_example_beacon_create` and requires a document ID.
|
||||
|
||||
Disabling the Editor extension removes its panel and command after restart. It does
|
||||
not erase its saved component data. Removing the runtime registration leaves an
|
||||
unknown component preserved by authoring; exporting that scene fails until the
|
||||
runtime dependency is restored or the component is deliberately removed.
|
||||
|
||||
## Compatibility and ownership
|
||||
|
||||
A manifest includes module ID/version, `kind: editor`, API version, native library,
|
||||
build fingerprint and dependencies with exact versions. The loader validates the
|
||||
complete graph for missing dependencies and cycles before calling entry points.
|
||||
A failed dependency prevents loading its dependents.
|
||||
|
||||
The fingerprint includes the SDK sources, dependency lock, platform, architecture,
|
||||
compiler version, configuration and CRT settings. Rebuild a plugin for the exact
|
||||
Editor SDK. Compatibility across arbitrary C++ builds is not promised. Reloading an
|
||||
updated native module requires restarting the Editor.
|
||||
|
||||
`include/faset/editor/plugin_api.h` defines a small C interface. Borrowed UTF-8 JSON
|
||||
strings are valid during a call; responses are copied through a receiving callback.
|
||||
Each side frees its own allocations. Register only during startup and invoke the SDK
|
||||
on the Editor thread. Commands must use their owning module's name prefix. Panels
|
||||
can invoke owned commands; a `$document` argument resolves to the active authoring
|
||||
document. No EnTT registry, live runtime world, or arbitrary C++ object pointer is
|
||||
exposed as a scripting API.
|
||||
|
||||
The native plugin test loads the actual example module, creates a component,
|
||||
checks Undo, runs its separate runtime behavior, unloads command registrations,
|
||||
opens the saved scene without the package, and rejects incompatible/cyclic/missing
|
||||
plugin dependencies.
|
||||
@@ -0,0 +1,85 @@
|
||||
# Use the Editor through MCP
|
||||
|
||||
Faset exposes the same authoring commands to its native interface and to MCP. MCP
|
||||
runs in the **Editor**. It never provides access to a running game's entities, and
|
||||
is not linked into the Player or SchemaExporter.
|
||||
|
||||
Start a headless server after building Faset:
|
||||
|
||||
```sh
|
||||
build/linux-debug/faset_editor --project /absolute/path/to/game --mcp
|
||||
```
|
||||
|
||||
Configure your MCP client to launch that executable with those arguments using a
|
||||
stdio transport. On Windows select `build/windows-debug/faset_editor.exe`. Use
|
||||
absolute paths, including the project path. Add `--gui` when the same process
|
||||
should display the native Editor; a graphical session and supported GPU are then
|
||||
required. A separately launched Editor process owns a separate in-memory session.
|
||||
|
||||
The transport uses newline-delimited JSON-RPC and the MCP `2025-06-18` lifecycle.
|
||||
Initialize, send `notifications/initialized`, then discover commands with
|
||||
`tools/list`. Standard output is reserved for protocol messages. See the official
|
||||
[MCP transport](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports)
|
||||
and [tool contracts](https://modelcontextprotocol.io/specification/2025-06-18/server/tools).
|
||||
|
||||
## Authoring workflow
|
||||
|
||||
1. Use `faset_documents` or create/open a document.
|
||||
2. Query `faset_schema` for stable type and field IDs and their constraints.
|
||||
3. Query the document for its persistent ID and current revision.
|
||||
4. Submit one `faset_scene_edit` batch with that revision.
|
||||
5. Save with `faset_document_save`. Use Undo/Redo for authoring changes.
|
||||
|
||||
For example, the arguments to `faset_scene_edit` can be:
|
||||
|
||||
```json
|
||||
{
|
||||
"document": "REPLACE_WITH_DOCUMENT_ID",
|
||||
"revision": 0,
|
||||
"idempotency_key": "create-first-object",
|
||||
"operations": [{"op": "entity.create", "name": "Player"}]
|
||||
}
|
||||
```
|
||||
|
||||
The command returns the new revision and scene with generated IDs. Repeating the
|
||||
same batch and retry key in the same session returns its previous result. Reusing
|
||||
the key for a different payload is an error. An outdated revision produces
|
||||
`revision.conflict`; query the new state and decide how to apply the intended change.
|
||||
Do not blindly retry a write using a fresh revision.
|
||||
|
||||
Each successful batch is one Undo step. A failed operation rejects the whole batch.
|
||||
Manual Inspector edits use this same service, including revision checks.
|
||||
|
||||
## Jobs and capabilities
|
||||
|
||||
`faset_import`, `faset_build`, `faset_export`, and `faset_play` return job IDs.
|
||||
Use `faset_job` or `faset_jobs` for progress, diagnostics and results.
|
||||
`faset_job_cancel` requests cancellation; cancelling a build is separate from
|
||||
undoing a document change. Failed compilation/import preserves the last successful
|
||||
published generation.
|
||||
|
||||
`faset_capabilities` reports available services. `faset_editor_capture` is present
|
||||
only in a graphical Editor. It returns an MCP image and can save a project-relative
|
||||
PNG. A headless server has no screenshot tool. `faset_play_control` provides pause,
|
||||
resume and single-step process controls; it cannot read or modify game entities.
|
||||
|
||||
`faset_recovery_list` and `faset_recovery_restore` expose crash recovery, including
|
||||
scenes that have never been saved. Restoring an already open document requires its
|
||||
current revision. Recovery refuses to overwrite an externally changed scene file.
|
||||
|
||||
## Single-command CLI
|
||||
|
||||
The CLI is useful for scripts that do not need an MCP session:
|
||||
|
||||
```sh
|
||||
build/linux-debug/faset_editor --project /absolute/path/to/game \
|
||||
--command '{"name":"faset_import","arguments":{"path":"Assets/door/manifest.json"}}' --wait
|
||||
```
|
||||
|
||||
`--wait` follows a returned job until completion. Failed, cancelled and conflicting
|
||||
jobs produce a nonzero exit code. This shell quoting example targets Bash; use the
|
||||
appropriate argument quoting for your Windows shell.
|
||||
|
||||
Validation: unit tests cover protocol errors and shared authoring semantics.
|
||||
`editor_mcp_stdio` launches the real Editor and verifies initialization, clean JSON
|
||||
stdout, conflicts, retry behavior, Undo/Redo, saving, reopening, and orderly EOF.
|
||||
Reference in New Issue
Block a user