BRP strict field in query (#16725)
# Objective - Allow skiping components that don't have ComponentId yet instead of failing `bevy/query` request. ## Solution - Describe the solution used to achieve the objective above. ## Testing My naive approach boils down to: - bevy/list to get list of all components. - bevy/query with empty components and has fields and a option that contains result of the bevy/list. Before that change I end up with bunch of `Component xxx isn't used in the world` because some of the components wasn't spawned at any moment yet in the game. Now it should work. ## Migration Guide - `BrpQueryParams` now has `strict` boolean field. It serfs as a flag to fail when encountering an invalid component rather than skipping it. Defaults to false.
This commit is contained in:
		
							parent
							
								
									30bd641af4
								
							
						
					
					
						commit
						897ffad8af
					
				| @ -92,6 +92,11 @@ pub struct BrpQueryParams { | ||||
|     /// exclude from the results.
 | ||||
|     #[serde(default)] | ||||
|     pub filter: BrpQueryFilter, | ||||
| 
 | ||||
|     /// An optional flag to fail when encountering an invalid component rather
 | ||||
|     /// than skipping it. Defaults to false.
 | ||||
|     #[serde(default)] | ||||
|     pub strict: bool, | ||||
| } | ||||
| 
 | ||||
| /// `bevy/spawn`: Creates a new entity with the given components and responds
 | ||||
| @ -527,19 +532,22 @@ pub fn process_remote_query_request(In(params): In<Option<Value>>, world: &mut W | ||||
|             has, | ||||
|         }, | ||||
|         filter: BrpQueryFilter { without, with }, | ||||
|         strict, | ||||
|     } = parse_some(params)?; | ||||
| 
 | ||||
|     let app_type_registry = world.resource::<AppTypeRegistry>().clone(); | ||||
|     let type_registry = app_type_registry.read(); | ||||
| 
 | ||||
|     let components = | ||||
|         get_component_ids(&type_registry, world, components).map_err(BrpError::component_error)?; | ||||
|     let option = | ||||
|         get_component_ids(&type_registry, world, option).map_err(BrpError::component_error)?; | ||||
|     let has = get_component_ids(&type_registry, world, has).map_err(BrpError::component_error)?; | ||||
|     let without = | ||||
|         get_component_ids(&type_registry, world, without).map_err(BrpError::component_error)?; | ||||
|     let with = get_component_ids(&type_registry, world, with).map_err(BrpError::component_error)?; | ||||
|     let components = get_component_ids(&type_registry, world, components, strict) | ||||
|         .map_err(BrpError::component_error)?; | ||||
|     let option = get_component_ids(&type_registry, world, option, strict) | ||||
|         .map_err(BrpError::component_error)?; | ||||
|     let has = | ||||
|         get_component_ids(&type_registry, world, has, strict).map_err(BrpError::component_error)?; | ||||
|     let without = get_component_ids(&type_registry, world, without, strict) | ||||
|         .map_err(BrpError::component_error)?; | ||||
|     let with = get_component_ids(&type_registry, world, with, strict) | ||||
|         .map_err(BrpError::component_error)?; | ||||
| 
 | ||||
|     let mut query = QueryBuilder::<FilteredEntityRef>::new(world); | ||||
|     for (_, component) in &components { | ||||
| @ -659,8 +667,8 @@ pub fn process_remote_remove_request( | ||||
|     let app_type_registry = world.resource::<AppTypeRegistry>().clone(); | ||||
|     let type_registry = app_type_registry.read(); | ||||
| 
 | ||||
|     let component_ids = | ||||
|         get_component_ids(&type_registry, world, components).map_err(BrpError::component_error)?; | ||||
|     let component_ids = get_component_ids(&type_registry, world, components, true) | ||||
|         .map_err(BrpError::component_error)?; | ||||
| 
 | ||||
|     // Remove the components.
 | ||||
|     let mut entity_world_mut = get_entity_mut(world, entity)?; | ||||
| @ -818,16 +826,20 @@ fn get_component_ids( | ||||
|     type_registry: &TypeRegistry, | ||||
|     world: &World, | ||||
|     component_paths: Vec<String>, | ||||
|     strict: bool, | ||||
| ) -> AnyhowResult<Vec<(TypeId, ComponentId)>> { | ||||
|     let mut component_ids = vec![]; | ||||
| 
 | ||||
|     for component_path in component_paths { | ||||
|         let type_id = get_component_type_registration(type_registry, &component_path)?.type_id(); | ||||
|         let Some(component_id) = world.components().get_id(type_id) else { | ||||
|             return Err(anyhow!( | ||||
|                 "Component `{}` isn't used in the world", | ||||
|                 component_path | ||||
|             )); | ||||
|             if strict { | ||||
|                 return Err(anyhow!( | ||||
|                     "Component `{}` isn't used in the world", | ||||
|                     component_path | ||||
|                 )); | ||||
|             } | ||||
|             continue; | ||||
|         }; | ||||
| 
 | ||||
|         component_ids.push((type_id, component_id)); | ||||
|  | ||||
| @ -142,6 +142,8 @@ | ||||
| //!     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.
 | ||||
| //! - `strict` (optional): A flag to enable strict mode which will fail if any one of the
 | ||||
| //!   components is not present or can not be reflected. Defaults to false.
 | ||||
| //!
 | ||||
| //! `result`: An array, each of which is an object containing:
 | ||||
| //! - `entity`: The ID of a query-matching entity.
 | ||||
|  | ||||
| @ -57,6 +57,7 @@ fn main() -> AnyhowResult<()> { | ||||
|                     option: Vec::default(), | ||||
|                     has: Vec::default(), | ||||
|                 }, | ||||
|                 strict: false, | ||||
|                 filter: BrpQueryFilter::default(), | ||||
|             }) | ||||
|             .expect("Unable to convert query parameters to a valid JSON value"), | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 MevLyshkin
						MevLyshkin