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

Add DefaultQueryFilters #13120

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open

Conversation

NiseVoid
Copy link
Contributor

Objective

Some usecases in the ecosystems are blocked by the inability to stop bevy internals and third party plugins from touching their entities. However the specifics of a general purpose entity disabling system are controversial and further complicated by hierarchies. We can partially unblock these usecases with an opt-in approach: default query filters.

Solution

  • Introduce DefaultQueryFilters, these filters are automatically applied to queries that don't otherwise mention the filtered component.
  • End users and third party plugins can register default filters and are responsible for handling entities they have hidden this way.
  • Extra features can be left for after user feedback
  • The default value could later include official ways to hide entities

Changelog

  • Add DefaultQueryFilters

@iiYese iiYese self-requested a review April 27, 2024 21:18
@iiYese
Copy link
Contributor

iiYese commented Apr 28, 2024

Two things you should probably do:

  • Add a way to bypass default filters.
  • Change .retain. Make it so it doesn't remove components that are filtered as Without & add another variant that bypasses that.

@NiseVoid
Copy link
Contributor Author

Add a way to bypass default filters.

This seems reasonable, yet it might also be problematic for things that get added to the list in the future. It's hard to anticipiate all the uses for this before people have a chance to use it. It's hard to say if a universal bypass makes sense or if we'd be better off with some alternative approach like assigning a group to each filter, and allowing groups to be bypassed. Or perhaps bypassing default filters won't even be needed in practice. It might be better to leave it until people report running into issues, or until we start including default features and know we need a way to bypass them collectively.

Change .retain. Make it so it doesn't remove components that are filtered as Without & add another variant that bypasses that.

This behavior feels a bit implicit, but I think creating a list of components retain shouldn't touch could make a lot of sense, it would also be a lot easier to explain and reason about for users. There might even be uses that do want to bypass retain but not be filtered out, or the other way around. But it should probably be in a separate PR. The bypass variant might also have the same issues as the point above.

@iiYese
Copy link
Contributor

iiYese commented Apr 28, 2024

This behavior feels a bit implicit, but I think creating a list of components retain shouldn't touch could make a lot of sense

At the very least it should be the same list. It shouldn't be a different one. I still think it would be a good idea to include this now anyway even if you don't want to add bypasses yet because introducing it later will be a breaking change & using it without default filters applied will surprise users.

@NiseVoid
Copy link
Contributor Author

At the very least it should be the same list.

I'm thinking more along the lines: Most users wouldn't manually add default filters, we'll probably want built-in abstractions on top in a future release. Meaning they'd probably be configured by plugins (something like a DisabledPlugin<T> or a HidePlugin<T>), and at this point the list of plugins serves as the list, which this list and a "retain filters" list could then be derived from.

Tho I've never actually used retain so it's a bit hard for me to comment on how it should behave.

@alice-i-cecile alice-i-cecile added A-ECS Entities, components, systems, and events C-Feature A new feature, making something new possible X-Controversial There is active debate or serious implications around merging this PR labels Apr 29, 2024
@NiseVoid NiseVoid mentioned this pull request May 3, 2024
@NiseVoid NiseVoid added the S-Needs-SME Decision or review from an SME is required label May 14, 2024
Copy link
Contributor

@Shatur Shatur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code is simple and clear. I would add references to DefaultQueryFilters from Query for discoverability.

This feature would be quite useful for rollback in networking.

Copy link
Contributor

@cBournhonesque cBournhonesque left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems well thought-out, and definitely useful

crates/bevy_ecs/src/query/default_filters.rs Outdated Show resolved Hide resolved
crates/bevy_ecs/src/query/default_filters.rs Outdated Show resolved Hide resolved
crates/bevy_ecs/src/query/default_filters.rs Outdated Show resolved Hide resolved
@alice-i-cecile alice-i-cecile added the M-Needs-Release-Note Work that should be called out in the blog due to impact label May 19, 2024
@NiseVoid
Copy link
Contributor Author

I think with @SkiFire13's fix (#14615) it should be possible to fix the sparse-related problems. I have updated the PR and added a test for it and it seems to work as one would expect. I have somehow never been able to reproduce @re0312's panic, but it also completely ignored sparse filters previously, which caused unsound behavior as queries that got detected as not overlapping could alias mutable references.

@janhohenheim janhohenheim added S-Needs-Review Needs reviewer attention (from anyone!) to move forward and removed S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged labels Aug 28, 2024
@alice-i-cecile alice-i-cecile added X-Blessed Has a large architectural impact or tradeoffs, but the design has been endorsed by decision makers and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward S-Needs-SME Decision or review from an SME is required X-Controversial There is active debate or serious implications around merging this PR labels Sep 18, 2024
@alice-i-cecile
Copy link
Member

After discussion with @maniwani, we have approval from two SME-ECS: them and myself.

As a follow-up, we should add a first-party Disabled marker component for ecosystem coordination purposes, and include a default default query filter.

@alice-i-cecile alice-i-cecile added the S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it label Sep 18, 2024
@iiYese
Copy link
Contributor

iiYese commented Sep 18, 2024

I'm going to raise a concern I've already mentioned on discord. If we have a Disabled marker it is easy to define what is considered erroneous for that. Eg. mutating an entity while it's disabled. It's also easy for authors to handle the addition & removal of Disabled via hooks & observers. This is not the case for default filters. Default filters will have completely different semantics depending on the author & there is no way for authors to handle the addition & removal of all filters from other authors. It would create users needing to request plugin authors for compatibility hooks for other plugins.

@alice-i-cecile alice-i-cecile added S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged and removed S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it labels Sep 23, 2024
@alice-i-cecile
Copy link
Member

@NiseVoid I know you've been chewing on designs for this, what's the plan for this work? My current understanding is:

  1. Ship something shaped broadly like this PR, but make it fully pub(crate)
  2. Add a trivial Disabled component, and add it to DefaultQueryFilters via a plugin.
  3. Figure out how to make it play nicer with hierarchies.
  4. Swap OnAdd and friends to trigger when entities are disabled.

Is that correct? What needs to be done to this PR to get step 1 above mergeable?

@NiseVoid
Copy link
Contributor Author

@NiseVoid I know you've been chewing on designs for this, what's the plan for this work? My current understanding is:

  1. Ship something shaped broadly like this PR, but make it fully pub(crate)
  2. Add a trivial Disabled component, and add it to DefaultQueryFilters via a plugin.
  3. Figure out how to make it play nicer with hierarchies.
  4. Swap OnAdd and friends to trigger when entities are disabled.

Is that correct? What needs to be done to this PR to get step 1 above mergeable?

Yes, this is correct. For docs and lint reasons making it pub(crate) in this PR might be difficult (doc tests would fail to compile and all of the code would get marked dead), but I have some changes that should generally prevent the issues @iiYese mentioned. Mainly you can only set one filter "per concept" (so entity disabling gets 1 filter, if we later add prefabs we could add one there too). Once we add Disabled, if we're okay with that living in bevy_ecs we can make the setter for the disabled component id pub(crate), and only expose a way to init_component::<Disabled>() and set that ComponentId as the filter.

@alice-i-cecile
Copy link
Member

Sounds good. Feel free to add expect(dead_code) to get CI to pass for now :)

@NiseVoid
Copy link
Contributor Author

NiseVoid commented Oct 1, 2024

@alice-i-cecile Where do you think docs for entity disabling and other similar features should live? Currently there's some docs and a doc test on DefaultQueryFilters, and with the limited scope of this PR I can't currently both have doc test and make set_disabled pub(crate) since doc tests can only access public functions. If we don't want DefaultQueryFilters to be the primary place explaining the features removing the doc test for the now simplified version wouldn't be a huge deal, but if it is the right place going forward we might need to merge the PR with that function public and make it not public and replace it with something less abusable like a function that calls set_disabled with the ComponentId for Disabled.

Also comments on the last commit would be welcome, I simplified the design somewhat for the more locked down design, but some parts of it do feel a bit odd like the Option<()> on set_disabled or working on an iterator that isn't currently necessary (but should simplify extending it with say Prefab or InternalMarkerPlsNoTouch later)

@alice-i-cecile
Copy link
Member

Can we make an entity_disabling module that stores these types? And then Disabled can live in there as one of the few pub types?

@NiseVoid NiseVoid added S-Needs-Review Needs reviewer attention (from anyone!) to move forward and removed S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged labels Oct 2, 2024
@BenjaminBrienen BenjaminBrienen added the D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes label Oct 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ECS Entities, components, systems, and events A-Networking Sending data between clients, servers and machines C-Feature A new feature, making something new possible D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes M-Needs-Release-Note Work that should be called out in the blog due to impact S-Needs-Review Needs reviewer attention (from anyone!) to move forward X-Blessed Has a large architectural impact or tradeoffs, but the design has been endorsed by decision makers
Projects
None yet
Development

Successfully merging this pull request may close these issues.