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.
|
/// exclude from the results.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub filter: BrpQueryFilter,
|
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
|
/// `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,
|
has,
|
||||||
},
|
},
|
||||||
filter: BrpQueryFilter { without, with },
|
filter: BrpQueryFilter { without, with },
|
||||||
|
strict,
|
||||||
} = parse_some(params)?;
|
} = parse_some(params)?;
|
||||||
|
|
||||||
let app_type_registry = world.resource::<AppTypeRegistry>().clone();
|
let app_type_registry = world.resource::<AppTypeRegistry>().clone();
|
||||||
let type_registry = app_type_registry.read();
|
let type_registry = app_type_registry.read();
|
||||||
|
|
||||||
let components =
|
let components = get_component_ids(&type_registry, world, components, strict)
|
||||||
get_component_ids(&type_registry, world, components).map_err(BrpError::component_error)?;
|
.map_err(BrpError::component_error)?;
|
||||||
let option =
|
let option = get_component_ids(&type_registry, world, option, strict)
|
||||||
get_component_ids(&type_registry, world, option).map_err(BrpError::component_error)?;
|
.map_err(BrpError::component_error)?;
|
||||||
let has = get_component_ids(&type_registry, world, has).map_err(BrpError::component_error)?;
|
let has =
|
||||||
let without =
|
get_component_ids(&type_registry, world, has, strict).map_err(BrpError::component_error)?;
|
||||||
get_component_ids(&type_registry, world, without).map_err(BrpError::component_error)?;
|
let without = get_component_ids(&type_registry, world, without, strict)
|
||||||
let with = get_component_ids(&type_registry, world, with).map_err(BrpError::component_error)?;
|
.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);
|
let mut query = QueryBuilder::<FilteredEntityRef>::new(world);
|
||||||
for (_, component) in &components {
|
for (_, component) in &components {
|
||||||
@ -659,8 +667,8 @@ pub fn process_remote_remove_request(
|
|||||||
let app_type_registry = world.resource::<AppTypeRegistry>().clone();
|
let app_type_registry = world.resource::<AppTypeRegistry>().clone();
|
||||||
let type_registry = app_type_registry.read();
|
let type_registry = app_type_registry.read();
|
||||||
|
|
||||||
let component_ids =
|
let component_ids = get_component_ids(&type_registry, world, components, true)
|
||||||
get_component_ids(&type_registry, world, components).map_err(BrpError::component_error)?;
|
.map_err(BrpError::component_error)?;
|
||||||
|
|
||||||
// Remove the components.
|
// Remove the components.
|
||||||
let mut entity_world_mut = get_entity_mut(world, entity)?;
|
let mut entity_world_mut = get_entity_mut(world, entity)?;
|
||||||
@ -818,16 +826,20 @@ fn get_component_ids(
|
|||||||
type_registry: &TypeRegistry,
|
type_registry: &TypeRegistry,
|
||||||
world: &World,
|
world: &World,
|
||||||
component_paths: Vec<String>,
|
component_paths: Vec<String>,
|
||||||
|
strict: bool,
|
||||||
) -> AnyhowResult<Vec<(TypeId, ComponentId)>> {
|
) -> AnyhowResult<Vec<(TypeId, ComponentId)>> {
|
||||||
let mut component_ids = vec![];
|
let mut component_ids = vec![];
|
||||||
|
|
||||||
for component_path in component_paths {
|
for component_path in component_paths {
|
||||||
let type_id = get_component_type_registration(type_registry, &component_path)?.type_id();
|
let type_id = get_component_type_registration(type_registry, &component_path)?.type_id();
|
||||||
let Some(component_id) = world.components().get_id(type_id) else {
|
let Some(component_id) = world.components().get_id(type_id) else {
|
||||||
return Err(anyhow!(
|
if strict {
|
||||||
"Component `{}` isn't used in the world",
|
return Err(anyhow!(
|
||||||
component_path
|
"Component `{}` isn't used in the world",
|
||||||
));
|
component_path
|
||||||
|
));
|
||||||
|
}
|
||||||
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
component_ids.push((type_id, component_id));
|
component_ids.push((type_id, component_id));
|
||||||
|
|||||||
@ -142,6 +142,8 @@
|
|||||||
//! on entities in order for them to be included in results.
|
//! 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
|
//! - `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.
|
//! 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:
|
//! `result`: An array, each of which is an object containing:
|
||||||
//! - `entity`: The ID of a query-matching entity.
|
//! - `entity`: The ID of a query-matching entity.
|
||||||
|
|||||||
@ -57,6 +57,7 @@ fn main() -> AnyhowResult<()> {
|
|||||||
option: Vec::default(),
|
option: Vec::default(),
|
||||||
has: Vec::default(),
|
has: Vec::default(),
|
||||||
},
|
},
|
||||||
|
strict: false,
|
||||||
filter: BrpQueryFilter::default(),
|
filter: BrpQueryFilter::default(),
|
||||||
})
|
})
|
||||||
.expect("Unable to convert query parameters to a valid JSON value"),
|
.expect("Unable to convert query parameters to a valid JSON value"),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user