# Objective
We should have an API with filtering to allow BRP clients to retrieve
all relevant data from the world state. Currently working on adding
examples - but reviews are appreciated! Still semi-WIP while I get my
head around bevy’s reflection and implementation :)
## Solution
This change adds support to query all entities in the world, and returns
all of their Reflected Components with corresponding values. For custom
`Components` it's important to still implement `Reflect` so that this
endpoint returns these. This will be useful for the
`bevy_entity_inspector` so that we can easily get the current world
state. We have modified the existing query API
so that clients can now pass in an empty `components[]` on the JSON
request.
## Testing
Updated example to showcase how to use the new endpoint to get all data:
```rust
/// Create a query_all request to send to the remote Bevy app.
/// This request will return all entities in the app, their components, and their
/// component values.
fn run_query_all_components_and_entities(url: String) -> Result<(), anyhow::Error> {
    let query_all_req = BrpRequest {
        jsonrpc: String::from("2.0"),
        method: String::from(BRP_QUERY_METHOD),
        id: Some(serde_json::to_value(1)?),
        params: None,
    };
    println!("query_all req: {:#?}", query_all_req);
    let query_all_res = ureq::post(&url)
        .send_json(query_all_req)?
        .body_mut()
        .read_json::<serde_json::Value>()?;
    println!("{query_all_res:#}");
    Ok(())
}
```
---
## Showcase
In the `client.rs` example, we can clearly see (assuming the `server.rs`
is running) a query hit for all entities and components:
```text
query_all req: BrpRequest {
    jsonrpc: "2.0",
    method: "bevy/query",
    id: Some(
        Number(1),
    ),
    params: Some(
        Object {
            "data": Object {
                "components": Array [],
                "has": Array [],
                "option": Array [],
            },
            "filter": Object {
                "with": Array [],
                "without": Array [],
            },
            "strict": Bool(false),
        },
    ),
}
```
And in the massive response:
```text
.....
{
      "components": {
        "bevy_window::monitor::Monitor": {
          "name": "\\\\.\\DISPLAY1",
          "physical_height": 1080,
          "physical_position": [
            -1920,
            0
          ],
          "physical_width": 1920,
          "refresh_rate_millihertz": 240000,
          "scale_factor": 1.25,
          "video_modes": [
            {
              "bit_depth": 32,
              "physical_size": [
                1920,
                1080
              ],
              "refresh_rate_millihertz": 240000
            },
            {
              "bit_depth": 32,
              "physical_size": [
                1680,
                1050
              ],
              "refresh_rate_millihertz": 240000
            },
            {
              "bit_depth": 32,
              "physical_size": [
                1600,
                900
              ],
              "refresh_rate_millihertz": 240000
            },
            {
              "bit_depth": 32,
              "physical_size": [
                1440,
                900
              ],
              "refresh_rate_millihertz": 240000
            },
            {
              "bit_depth": 32,
              "physical_size": [
                1400,
                1050
              ],
              "refresh_rate_millihertz": 240000
            },
            {
              "bit_depth": 32,
              "physical_size": [
                1366,
                768
              ],
              "refresh_rate_millihertz": 240000
            },
            {
              "bit_depth": 32,
              "physical_size": [
                1360,
                768
              ],
              "refresh_rate_millihertz": 240000
            },
            {
              "bit_depth": 32,
              "physical_size": [
                1280,
                1024
              ],
              "refresh_rate_millihertz": 240000
            },
            {
              "bit_depth": 32,
              "physical_size": [
                1280,
                960
              ],
              "refresh_rate_millihertz": 240000
            },
            {
              "bit_depth": 32,
              "physical_size": [
                1280,
                800
              ],
              "refresh_rate_millihertz": 240000
            },
            {
              "bit_depth": 32,
              "physical_size": [
                1280,
                768
              ],
              "refresh_rate_millihertz": 240000
            },
            {
              "bit_depth": 32,
              "physical_size": [
                1280,
                720
              ],
              "refresh_rate_millihertz": 240000
            },
            {
              "bit_depth": 32,
              "physical_size": [
                1280,
                600
              ],
              "refresh_rate_millihertz": 240000
            },
            {
              "bit_depth": 32,
              "physical_size": [
                1152,
                864
              ],
              "refresh_rate_millihertz": 240000
            },
            {
              "bit_depth": 32,
              "physical_size": [
                1024,
                768
              ],
              "refresh_rate_millihertz": 240000
            },
            {
              "bit_depth": 32,
              "physical_size": [
                800,
                600
              ],
              "refresh_rate_millihertz": 240000
            },
            {
              "bit_depth": 32,
              "physical_size": [
                640,
                480
              ],
              "refresh_rate_millihertz": 240000
            },
            {
              "bit_depth": 32,
              "physical_size": [
                640,
                400
              ],
              "refresh_rate_millihertz": 240000
            },
            {
              "bit_depth": 32,
              "physical_size": [
                512,
                384
              ],
              "refresh_rate_millihertz": 240000
            },
            {
              "bit_depth": 32,
              "physical_size": [
                400,
                300
              ],
              "refresh_rate_millihertz": 240000
            },
            {
              "bit_depth": 32,
              "physical_size": [
                320,
                240
              ],
              "refresh_rate_millihertz": 240000
            },
            {
              "bit_depth": 32,
              "physical_size": [
                320,
                200
              ],
              "refresh_rate_millihertz": 240000
            }
          ]
        }
      },
      "entity": 4294967267
    },
....
```
What's also really cool about this and `bevy_reflect` is that we also
get custom components returned as well (see below for `"server::Cube":
1.0` as the custom reflected struct specified in `server.rs`:
```text
{
      "components": {
        "bevy_render::primitives::Aabb": {
          "center": [
            0.0,
            0.0,
            0.0
          ],
          "half_extents": [
            0.5,
            0.5,
            0.5
          ]
        },
        "bevy_render::view::visibility::InheritedVisibility": true,
        "bevy_render::view::visibility::ViewVisibility": true,
        "bevy_render::view::visibility::Visibility": "Inherited",
        "bevy_transform::components::global_transform::GlobalTransform": [
          1.0,
          0.0,
          0.0,
          0.0,
          1.0,
          0.0,
          0.0,
          0.0,
          1.0,
          0.0,
          2.4572744369506836,
          0.0
        ],
        "bevy_transform::components::transform::Transform": {
          "rotation": [
            0.0,
            0.0,
            0.0,
            1.0
          ],
          "scale": [
            1.0,
            1.0,
            1.0
          ],
          "translation": [
            0.0,
            2.4572744369506836,
            0.0
          ]
        },
        "bevy_transform::components::transform::TransformTreeChanged": null,
        "server::Cube": 1.0
      },
```
---------
Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
		
	
			
		
			
				
	
	
		
			95 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			95 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
//! A Bevy app that you can connect to with the BRP and edit.
 | 
						|
//! Run this example with the `remote` feature enabled:
 | 
						|
//! ```bash
 | 
						|
//! cargo run --example server --features="bevy_remote"
 | 
						|
//! ```
 | 
						|
 | 
						|
use bevy::math::ops::cos;
 | 
						|
use bevy::{
 | 
						|
    input::common_conditions::input_just_pressed,
 | 
						|
    prelude::*,
 | 
						|
    remote::{http::RemoteHttpPlugin, RemotePlugin},
 | 
						|
};
 | 
						|
use serde::{Deserialize, Serialize};
 | 
						|
 | 
						|
fn main() {
 | 
						|
    App::new()
 | 
						|
        .add_plugins(DefaultPlugins)
 | 
						|
        .add_plugins(RemotePlugin::default())
 | 
						|
        .add_plugins(RemoteHttpPlugin::default())
 | 
						|
        .add_systems(Startup, setup)
 | 
						|
        .add_systems(Update, remove.run_if(input_just_pressed(KeyCode::Space)))
 | 
						|
        .add_systems(Update, move_cube)
 | 
						|
        // New types must be registered in order to be usable with reflection.
 | 
						|
        .register_type::<Cube>()
 | 
						|
        .register_type::<TestResource>()
 | 
						|
        .run();
 | 
						|
}
 | 
						|
 | 
						|
fn setup(
 | 
						|
    mut commands: Commands,
 | 
						|
    mut meshes: ResMut<Assets<Mesh>>,
 | 
						|
    mut materials: ResMut<Assets<StandardMaterial>>,
 | 
						|
) {
 | 
						|
    // circular base
 | 
						|
    commands.spawn((
 | 
						|
        Mesh3d(meshes.add(Circle::new(4.0))),
 | 
						|
        MeshMaterial3d(materials.add(Color::WHITE)),
 | 
						|
        Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
 | 
						|
    ));
 | 
						|
 | 
						|
    // cube
 | 
						|
    commands.spawn((
 | 
						|
        Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
 | 
						|
        MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
 | 
						|
        Transform::from_xyz(0.0, 0.5, 0.0),
 | 
						|
        Cube(1.0),
 | 
						|
    ));
 | 
						|
 | 
						|
    // test resource
 | 
						|
    commands.insert_resource(TestResource {
 | 
						|
        foo: Vec2::new(1.0, -1.0),
 | 
						|
        bar: false,
 | 
						|
    });
 | 
						|
 | 
						|
    // light
 | 
						|
    commands.spawn((
 | 
						|
        PointLight {
 | 
						|
            shadows_enabled: true,
 | 
						|
            ..default()
 | 
						|
        },
 | 
						|
        Transform::from_xyz(4.0, 8.0, 4.0),
 | 
						|
    ));
 | 
						|
 | 
						|
    // camera
 | 
						|
    commands.spawn((
 | 
						|
        Camera3d::default(),
 | 
						|
        Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
 | 
						|
    ));
 | 
						|
}
 | 
						|
 | 
						|
/// An arbitrary resource that can be inspected and manipulated with remote methods.
 | 
						|
#[derive(Resource, Reflect, Serialize, Deserialize)]
 | 
						|
#[reflect(Resource, Serialize, Deserialize)]
 | 
						|
pub struct TestResource {
 | 
						|
    /// An arbitrary field of the test resource.
 | 
						|
    pub foo: Vec2,
 | 
						|
 | 
						|
    /// Another arbitrary field.
 | 
						|
    pub bar: bool,
 | 
						|
}
 | 
						|
 | 
						|
fn move_cube(mut query: Query<&mut Transform, With<Cube>>, time: Res<Time>) {
 | 
						|
    for mut transform in &mut query {
 | 
						|
        transform.translation.y = -cos(time.elapsed_secs()) + 1.5;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
fn remove(mut commands: Commands, cube_entity: Single<Entity, With<Cube>>) {
 | 
						|
    commands.entity(*cube_entity).remove::<Cube>();
 | 
						|
}
 | 
						|
 | 
						|
#[derive(Component, Reflect, Serialize, Deserialize)]
 | 
						|
#[reflect(Component, Serialize, Deserialize)]
 | 
						|
struct Cube(f32);
 |