amethyst / legion

High performance Rust ECS library
MIT License
1.62k stars 139 forks source link

It should be possible to have `#[read_component(Component)]` and `&Component` on the same `for_each` system. #199

Open expenses opened 4 years ago

expenses commented 4 years ago

I have (a more complex version of) the following system:

struct Name;
struct InCryoTube(pub Entity);

#[system(for_each)]
#[read_component(Name)]
fn help_me(
    name: &Name,
    in_cryo_tube: &InCryoTube,
    world: &mut legion::world::SubWorld,
) {
    println!("{}", name);

    let entity: Entity = in_cryo_tube.0;
    let entry = world.entry_ref(entity).unwrap();
    let name = entry.get_component::<Name>().unwrap(); // panic here
    println!("{}", name);

}

Unfortunately it panics with this:

thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: Denied {
component_type: ComponentTypeId { type_id: TypeId { t: 12223289268359141760 },
name: "game::components::Name" }, component_name: "game::components::Name" }', src/main.rs:408:46

I know that this is to do with the limitations of SubWorlds, but it really should be possible to do this, as this is a fairly common pattern.

Uriopass commented 3 years ago

Did https://github.com/amethyst/legion/pull/235 fixed this issue ?

EDIT: Seems like it did :-)

This

use legion::{WorldOptions, Entity, EntityStore, Resources};
use legion::world::SubWorld;
use legion::system;

fn main() {
    let mut w = legion::world::World::new(WorldOptions::default());
    w.push((1i32, ));

    let mut v = legion::Schedule::builder().add_system(test_system()).build();

    v.execute(&mut w, &mut Resources::default());
}

#[system(for_each)]
#[read_component(i32)]
fn test(e: &Entity, v: &i32, sw: &SubWorld) {
    println!("{}", v);
    println!("{}", sw.entry_ref(*e).unwrap().get_component::<i32>().unwrap());
}

prints

1
1

Whereas in legion 0.3.1 it crashed!

basstabs commented 3 years ago

This still seems to be bugged for queries in 0.4. I have the following system:

#[system(for_each)]
#[read_component(Position)]
#[read_component(Player)]
pub fn chaser_ai(position: &mut Position, fov: &mut FOV, _chaser: &Chaser, world: &mut SubWorld, #[resource] map: &mut Map)
{

    let mut player_query = <(&Position, &Player)>::query();
    let path: rltk::NavigationPath;

    for (player_position, _) in player_query.iter(world)
    {

        //Calculate a path to player and chase them

    }

}

When attempting to run this, I get:

thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: AccessDenied', /.../legion-0.4.0/src/internals/query/mod.rs:345:65

This also happens if the query is just on &Position, but not if it is &Player, so it seems like the same issue for queries rather than entries.