A crate that allows an Amethyst game to communicate with an editor over IPC. This is being developed in conjunction with a WASM (Yew & web_view) editor, but is intended to be general enough to facilitate development of other editor front-ends.
Here's an example of how to setup an Amethyst game to communicate with the editor:
extern crate amethyst;
extern crate amethyst_editor_sync;
extern crate serde;
extern crate tap;
use amethyst::prelude::*;
use amethyst::ecs::prelude::*;
use amethyst_editor_sync::*;
use serde::*;
use tap::*;
fn main() -> Result<(), amethyst::Error> {
// Create a `SyncEditorBundle` which will register all necessary systems to serialize and send
// data to the editor.
let editor_bundle = SyncEditorBundle::default()
// Register the default types from the engine.
.tap(SyncEditorBundle::sync_default_types)
// Register the components and resources specified above.
.tap(|bundle| sync_components!(bundle, Foo))
.tap(|bundle| sync_resources!(bundle, BarResource));
let _game_data = GameDataBuilder::default()
.with_bundle(editor_bundle)?;
Ok(())
}
// Make sure you enable serialization for your custom components and resources!
#[derive(Serialize, Deserialize)]
struct Foo {
bar: usize,
baz: String,
}
impl Component for Foo {
type Storage = DenseVecStorage<Self>;
}
#[derive(Serialize, Deserialize)]
struct BarResource {
bar: usize,
}
Once your game is setup using amethyst-editor-sync
, it will automatically connect to any running
editor instance on your machine. You can use the WASM editor for visualization once
this is setup.
The goal of this project is to provide a functional 80% solution to the problem of sending arbitrary state data from an Amethyst game to an editor/visualizer tool. It doesn't attempt to perform any \~\~magic\~\~ in order to detect user-defined components, instead requiring that the developer explicitly list all components that they want to see in the editor. This introduces fairly heavy boilerplate when setting up editor support, but means that we have a functional solution that works today. The goal is that this project will act as a placeholder to get us going until we can put together a less boilerplate-heavy solution for registering user-defined components.
This project is also built around a multi-process architecture, where the game runs independently of the editor and the two communicate via IPC. This is a deliberate design choice in order to increase the robustness of the editor: If the game crashes, it cannot crash or corrupt the editor.
You'll need a stable version of Rust installed, which can be done via rustup. Install the
latest stable toolchain (if you don't already have a stable toolchain installed) and then clone
the repository. You can run the pong example for testing by running cargo run --example pong
.
If you need to test functionality against an editor, you can use the WASM editor.
For any feature requests, please open an issue in the GitHub issue tracker. Pull requests are also greatly appreciated :heart:
All contributors are expected to follow the Rust Code of Conduct.
This project is very early in development and should be treated as experimental.
Currently it supports communicating with an editor application over UDP. The entire world state
is serialized as a JSON string and broadcast to the editor every frame. It currently supports
sending arbitrary components and resources to an editor, and can do so for any component or
resource that implements Serialize
. Users must manually setup syncing for every component and
resource type that they wish to visualize in the editor, though.
The goal is to support communication over IPC in order to minimize overhead, and to use a binary protocol to speed up serialization and improve throughput. The current architecture allows for serialization of each component/resource type to happen in parallel, so we should try to keep that property going forward.