From e52349703e80ec532d3cd42b5166510e5ba57be0 Mon Sep 17 00:00:00 2001 From: Piotr Siuszko Date: Fri, 12 Sep 2025 08:11:15 +0200 Subject: [PATCH 1/4] BRP allow spawning/inserting Components with only `Reflect` --- crates/bevy_remote/src/builtin_methods.rs | 35 +++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/crates/bevy_remote/src/builtin_methods.rs b/crates/bevy_remote/src/builtin_methods.rs index 27ebc63ee945f..c61f6db91fcb7 100644 --- a/crates/bevy_remote/src/builtin_methods.rs +++ b/crates/bevy_remote/src/builtin_methods.rs @@ -1557,8 +1557,12 @@ fn insert_reflected_components( reflect_components: Vec>, ) -> AnyhowResult<()> { for reflected in reflect_components { - let reflect_component = - get_reflect_component(type_registry, reflected.reflect_type_path())?; + let type_path = if let Some(represented_type_info) = reflected.get_represented_type_info() { + represented_type_info.type_path() // Use the actual component type + } else { + reflected.reflect_type_path() // Fallback for non-dynamic types + }; + let reflect_component = get_reflect_component(type_registry, type_path)?; reflect_component.insert(&mut entity_world_mut, &*reflected, type_registry); } @@ -1636,6 +1640,33 @@ mod tests { use super::*; + #[test] + fn insert_reflect_only_component() { + use bevy_ecs::prelude::Component; + use bevy_reflect::Reflect; + #[derive(Reflect, Component)] + #[reflect(Component)] + struct Player { + name: String, + health: u32, + } + let components: HashMap = [( + String::from("bevy_remote::builtin_methods::tests::Player"), + serde_json::json!({"name": "DSA", "health": 50}), + )] + .into(); + let atr = AppTypeRegistry::default(); + { + let mut register = atr.write(); + register.register::(); + } + let type_reg = atr.read(); + let des = deserialize_components(&*type_reg, components).expect("FAIL"); + let mut world = World::new(); + let e = world.spawn_empty(); + insert_reflected_components(&*type_reg, e, des).expect("FAIL"); + } + #[test] fn serialization_tests() { test_serialize_deserialize(BrpQueryRow { From d76e1bdbf3469baededb75ae49d6e445d28178fe Mon Sep 17 00:00:00 2001 From: Piotr Siuszko Date: Fri, 12 Sep 2025 08:12:47 +0200 Subject: [PATCH 2/4] Normal name --- crates/bevy_remote/src/builtin_methods.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_remote/src/builtin_methods.rs b/crates/bevy_remote/src/builtin_methods.rs index c61f6db91fcb7..d3d48a2edc585 100644 --- a/crates/bevy_remote/src/builtin_methods.rs +++ b/crates/bevy_remote/src/builtin_methods.rs @@ -1652,7 +1652,7 @@ mod tests { } let components: HashMap = [( String::from("bevy_remote::builtin_methods::tests::Player"), - serde_json::json!({"name": "DSA", "health": 50}), + serde_json::json!({"name": "John", "health": 50}), )] .into(); let atr = AppTypeRegistry::default(); From 71305133bf902bbdddee340daca7fa3351a5e162 Mon Sep 17 00:00:00 2001 From: Piotr Siuszko Date: Fri, 12 Sep 2025 08:32:09 +0200 Subject: [PATCH 3/4] Update builtin_methods.rs --- crates/bevy_remote/src/builtin_methods.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_remote/src/builtin_methods.rs b/crates/bevy_remote/src/builtin_methods.rs index d3d48a2edc585..a775b27f1dfa5 100644 --- a/crates/bevy_remote/src/builtin_methods.rs +++ b/crates/bevy_remote/src/builtin_methods.rs @@ -1661,10 +1661,10 @@ mod tests { register.register::(); } let type_reg = atr.read(); - let des = deserialize_components(&*type_reg, components).expect("FAIL"); + let des = deserialize_components(&type_reg, components).expect("FAIL"); let mut world = World::new(); let e = world.spawn_empty(); - insert_reflected_components(&*type_reg, e, des).expect("FAIL"); + insert_reflected_components(&type_reg, e, des).expect("FAIL"); } #[test] From 2a367cffb66f7b83597492e85ee556946a78555d Mon Sep 17 00:00:00 2001 From: Piotr Siuszko Date: Fri, 12 Sep 2025 21:32:43 +0200 Subject: [PATCH 4/4] Simplify `insert_reflected_components` --- crates/bevy_remote/src/builtin_methods.rs | 29 ++++++++--------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/crates/bevy_remote/src/builtin_methods.rs b/crates/bevy_remote/src/builtin_methods.rs index a775b27f1dfa5..6c7cdd02e2894 100644 --- a/crates/bevy_remote/src/builtin_methods.rs +++ b/crates/bevy_remote/src/builtin_methods.rs @@ -952,8 +952,7 @@ pub fn process_remote_spawn_entity_request( let entity = world.spawn_empty(); let entity_id = entity.id(); - insert_reflected_components(&type_registry, entity, reflect_components) - .map_err(BrpError::component_error)?; + insert_reflected_components(entity, reflect_components).map_err(BrpError::component_error)?; let response = BrpSpawnEntityResponse { entity: entity_id }; serde_json::to_value(response).map_err(BrpError::internal) @@ -1010,12 +1009,8 @@ pub fn process_remote_insert_components_request( let reflect_components = deserialize_components(&type_registry, components).map_err(BrpError::component_error)?; - insert_reflected_components( - &type_registry, - get_entity_mut(world, entity)?, - reflect_components, - ) - .map_err(BrpError::component_error)?; + insert_reflected_components(get_entity_mut(world, entity)?, reflect_components) + .map_err(BrpError::component_error)?; Ok(Value::Null) } @@ -1552,18 +1547,11 @@ fn deserialize_resource( /// Given a collection `reflect_components` of reflected component values, insert them into /// the given entity (`entity_world_mut`). fn insert_reflected_components( - type_registry: &TypeRegistry, mut entity_world_mut: EntityWorldMut, reflect_components: Vec>, ) -> AnyhowResult<()> { for reflected in reflect_components { - let type_path = if let Some(represented_type_info) = reflected.get_represented_type_info() { - represented_type_info.type_path() // Use the actual component type - } else { - reflected.reflect_type_path() // Fallback for non-dynamic types - }; - let reflect_component = get_reflect_component(type_registry, type_path)?; - reflect_component.insert(&mut entity_world_mut, &*reflected, type_registry); + entity_world_mut.insert_reflect(reflected); } Ok(()) @@ -1660,11 +1648,14 @@ mod tests { let mut register = atr.write(); register.register::(); } - let type_reg = atr.read(); - let des = deserialize_components(&type_reg, components).expect("FAIL"); + let deserialized_components = { + let type_reg = atr.read(); + deserialize_components(&type_reg, components).expect("FAIL") + }; let mut world = World::new(); + world.insert_resource(atr); let e = world.spawn_empty(); - insert_reflected_components(&type_reg, e, des).expect("FAIL"); + insert_reflected_components(e, deserialized_components).expect("FAIL"); } #[test]