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

Expose SystemMeta fields #5497

Open
WinstonHartnett opened this issue Jul 30, 2022 · 8 comments
Open

Expose SystemMeta fields #5497

WinstonHartnett opened this issue Jul 30, 2022 · 8 comments
Labels
A-ECS Entities, components, systems, and events C-Usability A simple quality-of-life change that makes Bevy easier to use

Comments

@WinstonHartnett
Copy link

What problem does this solve or what need does it fill?

bevy_ecs' internal implementation of the default SystemParams use SystemMeta to initialize their states. Yet, only the is_send() field accessor is public to end-users and all other fields are pub(crate).

/// The metadata of a [`System`].
#[derive(Clone)]
pub struct SystemMeta {
    pub(crate) name: Cow<'static, str>,
    pub(crate) component_access_set: FilteredAccessSet<ComponentId>,
    pub(crate) archetype_component_access: Access<ArchetypeComponentId>,
    // NOTE: this must be kept private. making a SystemMeta non-send is irreversible to prevent
    // SystemParams from overriding each other
    is_send: bool,
    pub(crate) last_change_tick: u32,
}

Given that it's possible to directly implement SystemParam (and SystemParamFetch) for user-defined types in an unsafe impl, these fields should be exposed to advanced users.

What solution would you like?

Add unsafe mutable and safe immutable accessors for component_access_set and archetype_component_access, and immutable accessors for name and last_change_tick.

@WinstonHartnett WinstonHartnett added C-Enhancement A new feature S-Needs-Triage This issue needs to be labelled labels Jul 30, 2022
@alice-i-cecile alice-i-cecile added A-ECS Entities, components, systems, and events C-Usability A simple quality-of-life change that makes Bevy easier to use and removed C-Enhancement A new feature S-Needs-Triage This issue needs to be labelled labels Jul 30, 2022
@alice-i-cecile
Copy link
Member

I'm on board. Can you make a PR?

Very curious what your plans are here though.

@WinstonHartnett
Copy link
Author

I'm on board. Can you make a PR?

Sure!

Very curious what your plans are here though.

I'm working on a deterministic entity ID allocator (in addition to Entity) for use in a delayed-lockstep multiplayer game. Because the simulation-related (i.e. deterministic) systems' scheduling orders are shared across clients, the simulation IDs are indexed by the system that spawned them (by hashing the corresponding SystemMeta's name). You can then use these deterministic IDs to map from one client's entities to another's, as Entity allocation is not deterministic.

@DJMcNab
Copy link
Member

DJMcNab commented Jul 30, 2022

I'm not sure I want users to be implementing SystemParam - at the very least I'd be reluctant to claim it's currently supported.

I suppose unless/until we can work out a nicer API for dynamic components it's inevitable.

For your use case, we cannot provide the guarantee that the SystemMeta's name is unique per system as you seem to require it to be (since it's built on https://doc.rust-lang.org/std/any/fn.type_name.html) - the system name is absolutely not guaranteed to be the same across compilations too - e.g. for different platforms (or even within the same compilation, going by a strict reading of the docs). You need to do your own book-keeping.

E.g. with a Local initialised with the current system's id on first run (incrementing the ID counter in the progress), or a constant per system, etc.

@alice-i-cecile
Copy link
Member

Ping @BoxyUwU and @TheRawMeatball for opinions here. I share @DJMcNab's concerns, but I also don't like how the trait is public (and not sealed) but not feasibly implementable.

@WinstonHartnett
Copy link
Author

WinstonHartnett commented Jul 30, 2022

I'm not sure I want users to be implementing SystemParam - at the very least I'd be reluctant to claim it's currently supported.

I suppose unless/until we can work out a nicer API for dynamic components it's inevitable.

For your use case, I'm we cannot provide the guarantee that the SystemMeta's name is unique per system as you seem to require it to be (since it's built on https://doc.rust-lang.org/std/any/fn.type_name.html). You need to do your own book-keeping.

Yes that's unfortunate, but I've never run into problems [yet]. I'd prefer eventually using a stable TypeID (like #32). Nonetheless, it'd be nice to have the name and access information on-hand for debugging, although I'm sure you can get it from Schedule.

E.g. with a Local initialised with the current system's id on first run (incrementing the ID counter in the progress), or a constant per system, etc.

Yes, I see now that locals can be created with FromWorld, so I guess I don't need a custom SystemParam. Is the SystemParam initialization order stable across clients/binaries?

In the past, I've used a hash of a type's AST (along with the definition file location), but it's only marginally safer as a unique, binary-agnostic ID than type_name or type_id.

@alice-i-cecile
Copy link
Member

Is the SystemParam initialization order stable across clients/binaries?

This should be, but I don't think we explicitly make any guarantees to this effect yet.

@TheRawMeatball
Copy link
Member

I'd be OK merging such a change until we make a proper API for creating dynamic SystemParam s, though I still think the ideal version of such an api would involve

  • making "system initialization" explicit and shown by the type system
  • making a custom system param that will register certain accesses for a system by looking things up from a resource on the world it's being registered to
  • having the actual accessing for stuff registered this way happen through direct access to a potential UnsafeWorld system param which gives a &World, but without registering any accesses.

@WinstonHartnett
Copy link
Author

WinstonHartnett commented Jun 21, 2023

Just ran into this again, so I pushed some changes in #7119 . Some comments/questions:

  • Should the access sets always be a superset of their previous value in the context of implementing SystemParams (i.e. should Access::clear, etc. ever be used in SystemParam when adding accesses)? Looks like clear is only used in scheduling.
  • Regardless of the performance ramifications, is adding more R/W constraints to access sets than necessary ever unsafe?
  • If the first is true and the second false, then SystemMeta should just expose safe methods over Access and FilteredAccessSet for now.
  • Unrelated: change_detection should have module docs on how it works. Maybe copy SystemChangeTick?

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 C-Usability A simple quality-of-life change that makes Bevy easier to use
Projects
None yet
Development

No branches or pull requests

4 participants