2024-03-23 02:22:52 +00:00
|
|
|
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
2024-03-27 03:30:08 +00:00
|
|
|
#![forbid(unsafe_code)]
|
2024-03-25 18:52:50 +00:00
|
|
|
#![doc(
|
|
|
|
html_logo_url = "https://bevyengine.org/assets/icon.png",
|
|
|
|
html_favicon_url = "https://bevyengine.org/assets/icon.png"
|
|
|
|
)]
|
2024-03-23 02:22:52 +00:00
|
|
|
|
2022-01-01 21:22:04 +00:00
|
|
|
//! This module is separated into its own crate to enable simple dynamic linking for Bevy, and should not be used directly
|
|
|
|
|
2020-11-10 03:26:08 +00:00
|
|
|
/// `use bevy::prelude::*;` to import common components, bundles, and plugins.
|
|
|
|
pub mod prelude;
|
|
|
|
|
|
|
|
mod default_plugins;
|
|
|
|
pub use default_plugins::*;
|
|
|
|
|
2024-04-22 01:32:51 +00:00
|
|
|
pub use bevy_a11y as a11y;
|
2022-04-02 22:36:02 +00:00
|
|
|
#[cfg(feature = "bevy_animation")]
|
2024-04-22 01:32:51 +00:00
|
|
|
pub use bevy_animation as animation;
|
|
|
|
pub use bevy_app as app;
|
|
|
|
#[cfg(feature = "bevy_asset")]
|
|
|
|
pub use bevy_asset as asset;
|
2020-11-10 03:26:08 +00:00
|
|
|
#[cfg(feature = "bevy_audio")]
|
2024-04-22 01:32:51 +00:00
|
|
|
pub use bevy_audio as audio;
|
|
|
|
#[cfg(feature = "bevy_color")]
|
|
|
|
pub use bevy_color as color;
|
|
|
|
pub use bevy_core as core;
|
2021-07-28 21:29:32 +00:00
|
|
|
#[cfg(feature = "bevy_core_pipeline")]
|
2024-04-22 01:32:51 +00:00
|
|
|
pub use bevy_core_pipeline as core_pipeline;
|
|
|
|
#[cfg(feature = "bevy_dev_tools")]
|
|
|
|
pub use bevy_dev_tools as dev_tools;
|
|
|
|
pub use bevy_diagnostic as diagnostic;
|
|
|
|
pub use bevy_ecs as ecs;
|
2021-01-03 19:36:42 +00:00
|
|
|
#[cfg(feature = "bevy_gilrs")]
|
2024-04-22 01:32:51 +00:00
|
|
|
pub use bevy_gilrs as gilrs;
|
|
|
|
#[cfg(feature = "bevy_gizmos")]
|
|
|
|
pub use bevy_gizmos as gizmos;
|
2020-11-10 03:26:08 +00:00
|
|
|
#[cfg(feature = "bevy_gltf")]
|
2024-04-22 01:32:51 +00:00
|
|
|
pub use bevy_gltf as gltf;
|
|
|
|
pub use bevy_hierarchy as hierarchy;
|
|
|
|
pub use bevy_input as input;
|
|
|
|
pub use bevy_log as log;
|
|
|
|
pub use bevy_math as math;
|
2020-11-10 03:26:08 +00:00
|
|
|
#[cfg(feature = "bevy_pbr")]
|
2024-04-22 01:32:51 +00:00
|
|
|
pub use bevy_pbr as pbr;
|
2024-06-15 11:59:57 +00:00
|
|
|
#[cfg(feature = "bevy_picking")]
|
|
|
|
pub use bevy_picking as picking;
|
2024-04-22 01:32:51 +00:00
|
|
|
pub use bevy_ptr as ptr;
|
|
|
|
pub use bevy_reflect as reflect;
|
Initial implementation of the Bevy Remote Protocol (Adopted) (#14880)
# Objective
Adopted from #13563.
The goal is to implement the Bevy Remote Protocol over HTTP/JSON,
allowing the ECS to be interacted with remotely.
## Solution
At a high level, there are really two separate things that have been
undertaken here:
1. First, `RemotePlugin` has been created, which has the effect of
embedding a [JSON-RPC](https://www.jsonrpc.org/specification) endpoint
into a Bevy application.
2. Second, the [Bevy Remote Protocol
verbs](https://gist.github.com/coreh/1baf6f255d7e86e4be29874d00137d1d#file-bevy-remote-protocol-md)
(excluding `POLL`) have been implemented as remote methods for that
JSON-RPC endpoint under a Bevy-exclusive namespace (e.g. `bevy/get`,
`bevy/list`, etc.).
To avoid some repetition, here is the crate-level documentation, which
explains the request/response structure, built-in-methods, and custom
method configuration:
<details>
<summary>Click to view crate-level docs</summary>
```rust
//! An implementation of the Bevy Remote Protocol over HTTP and JSON, to allow
//! for remote control of a Bevy app.
//!
//! Adding the [`RemotePlugin`] to your [`App`] causes Bevy to accept
//! connections over HTTP (by default, on port 15702) while your app is running.
//! These *remote clients* can inspect and alter the state of the
//! entity-component system. Clients are expected to `POST` JSON requests to the
//! root URL; see the `client` example for a trivial example of use.
//!
//! The Bevy Remote Protocol is based on the JSON-RPC 2.0 protocol.
//!
//! ## Request objects
//!
//! A typical client request might look like this:
//!
//! ```json
//! {
//! "method": "bevy/get",
//! "id": 0,
//! "params": {
//! "entity": 4294967298,
//! "components": [
//! "bevy_transform::components::transform::Transform"
//! ]
//! }
//! }
//! ```
//!
//! The `id` and `method` fields are required. The `param` field may be omitted
//! for certain methods:
//!
//! * `id` is arbitrary JSON data. The server completely ignores its contents,
//! and the client may use it for any purpose. It will be copied via
//! serialization and deserialization (so object property order, etc. can't be
//! relied upon to be identical) and sent back to the client as part of the
//! response.
//!
//! * `method` is a string that specifies one of the possible [`BrpRequest`]
//! variants: `bevy/query`, `bevy/get`, `bevy/insert`, etc. It's case-sensitive.
//!
//! * `params` is parameter data specific to the request.
//!
//! For more information, see the documentation for [`BrpRequest`].
//! [`BrpRequest`] is serialized to JSON via `serde`, so [the `serde`
//! documentation] may be useful to clarify the correspondence between the Rust
//! structure and the JSON format.
//!
//! ## Response objects
//!
//! A response from the server to the client might look like this:
//!
//! ```json
//! {
//! "jsonrpc": "2.0",
//! "id": 0,
//! "result": {
//! "bevy_transform::components::transform::Transform": {
//! "rotation": { "x": 0.0, "y": 0.0, "z": 0.0, "w": 1.0 },
//! "scale": { "x": 1.0, "y": 1.0, "z": 1.0 },
//! "translation": { "x": 0.0, "y": 0.5, "z": 0.0 }
//! }
//! }
//! }
//! ```
//!
//! The `id` field will always be present. The `result` field will be present if the
//! request was successful. Otherwise, an `error` field will replace it.
//!
//! * `id` is the arbitrary JSON data that was sent as part of the request. It
//! will be identical to the `id` data sent during the request, modulo
//! serialization and deserialization. If there's an error reading the `id` field,
//! it will be `null`.
//!
//! * `result` will be present if the request succeeded and will contain the response
//! specific to the request.
//!
//! * `error` will be present if the request failed and will contain an error object
//! with more information about the cause of failure.
//!
//! ## Error objects
//!
//! An error object might look like this:
//!
//! ```json
//! {
//! "code": -32602,
//! "message": "Missing \"entity\" field"
//! }
//! ```
//!
//! The `code` and `message` fields will always be present. There may also be a `data` field.
//!
//! * `code` is an integer representing the kind of an error that happened. Error codes documented
//! in the [`error_codes`] module.
//!
//! * `message` is a short, one-sentence human-readable description of the error.
//!
//! * `data` is an optional field of arbitrary type containing additional information about the error.
//!
//! ## Built-in methods
//!
//! The Bevy Remote Protocol includes a number of built-in methods for accessing and modifying data
//! in the ECS. Each of these methods uses the `bevy/` prefix, which is a namespace reserved for
//! BRP built-in methods.
//!
//! ### bevy/get
//!
//! Retrieve the values of one or more components from an entity.
//!
//! `params`:
//! - `entity`: The ID of the entity whose components will be fetched.
//! - `components`: An array of fully-qualified type names of components to fetch.
//!
//! `result`: A map associating each type name to its value on the requested entity.
//!
//! ### bevy/query
//!
//! Perform a query over components in the ECS, returning all matching entities and their associated
//! component values.
//!
//! All of the arrays that comprise this request are optional, and when they are not provided, they
//! will be treated as if they were empty.
//!
//! `params`:
//! `params`:
//! - `data`:
//! - `components` (optional): An array of fully-qualified type names of components to fetch.
//! - `option` (optional): An array of fully-qualified type names of components to fetch optionally.
//! - `has` (optional): An array of fully-qualified type names of components whose presence will be
//! reported as boolean values.
//! - `filter` (optional):
//! - `with` (optional): An array of fully-qualified type names of components that must be present
//! on entities in order for them to be included in results.
//! - `without` (optional): An array of fully-qualified type names of components that must *not* be
//! present on entities in order for them to be included in results.
//!
//! `result`: An array, each of which is an object containing:
//! - `entity`: The ID of a query-matching entity.
//! - `components`: A map associating each type name from `components`/`option` to its value on the matching
//! entity if the component is present.
//! - `has`: A map associating each type name from `has` to a boolean value indicating whether or not the
//! entity has that component. If `has` was empty or omitted, this key will be omitted in the response.
//!
//! ### bevy/spawn
//!
//! Create a new entity with the provided components and return the resulting entity ID.
//!
//! `params`:
//! - `components`: A map associating each component's fully-qualified type name with its value.
//!
//! `result`:
//! - `entity`: The ID of the newly spawned entity.
//!
//! ### bevy/destroy
//!
//! Despawn the entity with the given ID.
//!
//! `params`:
//! - `entity`: The ID of the entity to be despawned.
//!
//! `result`: null.
//!
//! ### bevy/remove
//!
//! Delete one or more components from an entity.
//!
//! `params`:
//! - `entity`: The ID of the entity whose components should be removed.
//! - `components`: An array of fully-qualified type names of components to be removed.
//!
//! `result`: null.
//!
//! ### bevy/insert
//!
//! Insert one or more components into an entity.
//!
//! `params`:
//! - `entity`: The ID of the entity to insert components into.
//! - `components`: A map associating each component's fully-qualified type name with its value.
//!
//! `result`: null.
//!
//! ### bevy/reparent
//!
//! Assign a new parent to one or more entities.
//!
//! `params`:
//! - `entities`: An array of entity IDs of entities that will be made children of the `parent`.
//! - `parent` (optional): The entity ID of the parent to which the child entities will be assigned.
//! If excluded, the given entities will be removed from their parents.
//!
//! `result`: null.
//!
//! ### bevy/list
//!
//! List all registered components or all components present on an entity.
//!
//! When `params` is not provided, this lists all registered components. If `params` is provided,
//! this lists only those components present on the provided entity.
//!
//! `params` (optional):
//! - `entity`: The ID of the entity whose components will be listed.
//!
//! `result`: An array of fully-qualified type names of components.
//!
//! ## Custom methods
//!
//! In addition to the provided methods, the Bevy Remote Protocol can be extended to include custom
//! methods. This is primarily done during the initialization of [`RemotePlugin`], although the
//! methods may also be extended at runtime using the [`RemoteMethods`] resource.
//!
//! ### Example
//! ```ignore
//! fn main() {
//! App::new()
//! .add_plugins(DefaultPlugins)
//! .add_plugins(
//! // `default` adds all of the built-in methods, while `with_method` extends them
//! RemotePlugin::default()
//! .with_method("super_user/cool_method".to_owned(), path::to::my::cool::handler)
//! // ... more methods can be added by chaining `with_method`
//! )
//! .add_systems(
//! // ... standard application setup
//! )
//! .run();
//! }
//! ```
//!
//! The handler is expected to be a system-convertible function which takes optional JSON parameters
//! as input and returns a [`BrpResult`]. This means that it should have a type signature which looks
//! something like this:
//! ```
//! # use serde_json::Value;
//! # use bevy_ecs::prelude::{In, World};
//! # use bevy_remote::BrpResult;
//! fn handler(In(params): In<Option<Value>>, world: &mut World) -> BrpResult {
//! todo!()
//! }
//! ```
//!
//! Arbitrary system parameters can be used in conjunction with the optional `Value` input. The
//! handler system will always run with exclusive `World` access.
//!
//! [the `serde` documentation]: https://serde.rs/
```
</details>
### Message lifecycle
At a high level, the lifecycle of client-server interactions is
something like this:
1. The client sends one or more `BrpRequest`s. The deserialized version
of that is just the Rust representation of a JSON-RPC request, and it
looks like this:
```rust
pub struct BrpRequest {
/// The action to be performed. Parsing is deferred for the sake of error reporting.
pub method: Option<Value>,
/// Arbitrary data that will be returned verbatim to the client as part of
/// the response.
pub id: Option<Value>,
/// The parameters, specific to each method.
///
/// These are passed as the first argument to the method handler.
/// Sometimes params can be omitted.
pub params: Option<Value>,
}
```
2. These requests are accumulated in a mailbox resource (small lie but
close enough).
3. Each update, the mailbox is drained by a system
`process_remote_requests`, where each request is processed according to
its `method`, which has an associated handler. Each handler is a Bevy
system that runs with exclusive world access and returns a result; e.g.:
```rust
pub fn process_remote_get_request(In(params): In<Option<Value>>, world: &World) -> BrpResult { // ... }
```
4. The result (or an error) is reported back to the client.
## Testing
This can be tested by using the `server` and `client` examples. The
`client` example is not particularly exhaustive at the moment (it only
creates barebones `bevy/query` requests) but is still informative. Other
queries can be made using `curl` with the `server` example running.
For example, to make a `bevy/list` request and list all registered
components:
```bash
curl -X POST -d '{ "jsonrpc": "2.0", "id": 1, "method": "bevy/list" }' 127.0.0.1:15702 | jq .
```
---
## Future direction
There were a couple comments on BRP versioning while this was in draft.
I agree that BRP versioning is a good idea, but I think that it requires
some consensus on a couple fronts:
- First of all, what does the version actually mean? Is it a version for
the protocol itself or for the `bevy/*` methods implemented using it?
Both?
- Where does the version actually live? The most natural place is just
where we have `"jsonrpc"` right now (at least if it's versioning the
protocol itself), but this means we're not actually conforming to
JSON-RPC any more (so, for example, any client library used to construct
JSON-RPC requests would stop working). I'm not really against that, but
it's at least a real decision.
- What do we actually do when we encounter mismatched versions? Adding
handling for this would be actual scope creep instead of just a little
add-on in my opinion.
Another thing that would be nice is making the internal structure of the
implementation less JSON-specific. Right now, for example, component
values that will appear in server responses are quite eagerly converted
to JSON `Value`s, which prevents disentangling the handler logic from
the communication medium, but it can probably be done in principle and I
imagine it would enable more code reuse (e.g. for custom method
handlers) in addition to making the internals more readily usable for
other formats.
---------
Co-authored-by: Patrick Walton <pcwalton@mimiga.net>
Co-authored-by: DragonGamesStudios <margos.michal@gmail.com>
Co-authored-by: Christopher Biscardi <chris@christopherbiscardi.com>
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
2024-09-23 18:36:16 +00:00
|
|
|
#[cfg(feature = "bevy_remote")]
|
|
|
|
pub use bevy_remote as remote;
|
2020-11-10 03:26:08 +00:00
|
|
|
#[cfg(feature = "bevy_render")]
|
2024-04-22 01:32:51 +00:00
|
|
|
pub use bevy_render as render;
|
|
|
|
#[cfg(feature = "bevy_scene")]
|
|
|
|
pub use bevy_scene as scene;
|
2020-11-10 03:26:08 +00:00
|
|
|
#[cfg(feature = "bevy_sprite")]
|
2024-04-22 01:32:51 +00:00
|
|
|
pub use bevy_sprite as sprite;
|
Separate state crate (#13216)
# Objective
Extracts the state mechanisms into a new crate called "bevy_state".
This comes with a few goals:
- state wasn't really an inherent machinery of the ecs system, and so
keeping it within bevy_ecs felt forced
- by mixing it in with bevy_ecs, the maintainability of our more robust
state system was significantly compromised
moving state into a new crate makes it easier to encapsulate as it's own
feature, and easier to read and understand since it's no longer a
single, massive file.
## Solution
move the state-related elements from bevy_ecs to a new crate
## Testing
- Did you test these changes? If so, how? all the automated tests
migrated and passed, ran the pre-existing examples without changes to
validate.
---
## Migration Guide
Since bevy_state is now gated behind the `bevy_state` feature, projects
that use state but don't use the `default-features` will need to add
that feature flag.
Since it is no longer part of bevy_ecs, projects that use bevy_ecs
directly will need to manually pull in `bevy_state`, trigger the
StateTransition schedule, and handle any of the elements that bevy_app
currently sets up.
---------
Co-authored-by: Kristoffer Søholm <k.soeholm@gmail.com>
2024-05-09 18:06:05 +00:00
|
|
|
#[cfg(feature = "bevy_state")]
|
|
|
|
pub use bevy_state as state;
|
2024-04-22 01:32:51 +00:00
|
|
|
pub use bevy_tasks as tasks;
|
2020-11-10 03:26:08 +00:00
|
|
|
#[cfg(feature = "bevy_text")]
|
2024-04-22 01:32:51 +00:00
|
|
|
pub use bevy_text as text;
|
|
|
|
pub use bevy_time as time;
|
|
|
|
pub use bevy_transform as transform;
|
2020-11-10 03:26:08 +00:00
|
|
|
#[cfg(feature = "bevy_ui")]
|
2024-04-22 01:32:51 +00:00
|
|
|
pub use bevy_ui as ui;
|
|
|
|
pub use bevy_utils as utils;
|
|
|
|
pub use bevy_window as window;
|
2020-11-10 03:26:08 +00:00
|
|
|
#[cfg(feature = "bevy_winit")]
|
2024-04-22 01:32:51 +00:00
|
|
|
pub use bevy_winit as winit;
|