Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BRP resource methods #17423

Merged
merged 13 commits into from
Feb 26, 2025
Prev Previous commit
Next Next commit
Implement bevy/insert_resource
mweatherley committed Jan 18, 2025
commit 3201272f9951360e57ef2da5cf7c35e5a08a8466
43 changes: 42 additions & 1 deletion crates/bevy_remote/src/builtin_methods.rs
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ use bevy_ecs::{
query::QueryBuilder,
reflect::{AppTypeRegistry, ReflectComponent, ReflectResource},
removal_detection::RemovedComponentEntity,
system::{In, Local},
system::{In, Local, ParamSet},
world::{EntityRef, EntityWorldMut, FilteredEntityRef, World},
};
use bevy_hierarchy::BuildChildren as _;
@@ -192,6 +192,7 @@ pub struct BrpInsertParams {

/// `bevy/insert_resource`: Inserts a resource into the world with a given
/// value.
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct BrpInsertResourceParams {
/// The [full path] of the resource type to insert.
///
@@ -792,6 +793,29 @@ pub fn process_remote_insert_request(
Ok(Value::Null)
}

/// Handles a `bevy/insert_resource` request coming from a client.
pub fn process_remote_insert_resource_request(
In(params): In<Option<Value>>,
world: &mut World,
) -> BrpResult {
let BrpInsertResourceParams {
resource: resource_path,
value,
} = parse_some(params)?;

let app_type_registry = world.resource::<AppTypeRegistry>().clone();
let type_registry = app_type_registry.read();

let reflected_resource = deserialize_resource(&type_registry, &resource_path, value)
.map_err(BrpError::resource_error)?;

let reflect_resource =
get_reflect_resource(&type_registry, &resource_path).map_err(BrpError::resource_error)?;
reflect_resource.insert(world, &*reflected_resource, &type_registry);

Ok(Value::Null)
}

/// Handles a `bevy/mutate_component` request coming from a client.
///
/// This method allows you to mutate a single field inside an Entity's
@@ -1524,6 +1548,23 @@ fn deserialize_components(
Ok(reflect_components)
}

/// Given a resource path and an associated serialized value (`value`), return the
/// deserialized value.
fn deserialize_resource(
type_registry: &TypeRegistry,
resource_path: &str,
value: Value,
) -> AnyhowResult<Box<dyn PartialReflect>> {
let Some(resource_type) = type_registry.get_with_type_path(&resource_path) else {
return Err(anyhow!("Unknown resource type: `{}`", resource_path));
};
let reflected: Box<dyn PartialReflect> =
TypedReflectDeserializer::new(resource_type, type_registry)
.deserialize(&value)
.map_err(|err| anyhow!("{resource_path} is invalid: {err}"))?;
Ok(reflected)
}

/// Given a collection `reflect_components` of reflected component values, insert them into
/// the given entity (`entity_world_mut`).
fn insert_reflected_components(
4 changes: 2 additions & 2 deletions crates/bevy_remote/src/lib.rs
Original file line number Diff line number Diff line change
@@ -720,9 +720,9 @@ impl BrpError {
#[must_use]
pub fn resource_not_present(resource: &str) -> Self {
Self {
code: todo!(),
code: error_codes::RESOURCE_NOT_PRESENT,
message: format!("Resource `{resource}` not present in the world."),
data: todo!(),
data: None,
}
}