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