Indra-db / Flecs-Rust

Rust API for Flecs: A Fast and Flexible Entity Component System (ECS)
MIT License
188 stars 11 forks source link

Querying optional components returns wrong results #198

Closed m-walther closed 1 week ago

m-walther commented 1 week ago

Describe the bug When I have two entities both having component A, one of them also has component B. Both entities are inserted into the world in a startup system during World::progress.

Then if I run a query after World::progress using an Option-operator for component B the result will report both entities having component B although I would expect only one of them having that component.

Do I miss something here?

To Reproduce (Rust)

use flecs_ecs::prelude::*;
use flecs_ecs::prelude::flecs::pipeline::*;

#[derive(Component)]
struct A {
    pub val: i32
}

#[derive(Component)]
struct B {
    pub val: i32
}

fn main() {
    let world = World::new();

    world.system::<()>()
        .kind::<OnStart>()
        .run(|it| {

            print!("running OnStart-system...");

            let world = it.world();
            world.entity()
                .set(A { val: 1 })
                .set(B { val: 1 })
            ;
            world.entity()
                .set(A { val: 2 })
            ;
            println!("done");
        });

    // this correctly reports archetypes
    world.system::<(&A, Option<&B>)>()
        .kind::<OnUpdate>()
        .each_entity(|e, (a, b)| {
            println!("OnUpdate: entity archetype is {}", e.archetype().to_string().unwrap());
        });

    println!("\nprogress world\n");

    world.progress();

    println!("\nQuery:");

    // *:

    world.new_query::<(&A, Option<&B>)>()
        .each_entity(|e, (a, b)| {
            // this should be true for one entity only
            if let Some(b) = b {
                println!("entity archetype is: {}", e.archetype().to_string().unwrap());
                println!("component values are: (A.val: {}, B.val: {})", a.val, b.val);
            }
        });
}

Expected behavior The query at * should return component B only for one of the two results.

Additional context Potential bug occurs using flecs-ecs 0.1.3 .

EDIT: If I remove world.progress with both systems and instead just create both entities directly the query will be working as expected:

use flecs_ecs::prelude::*;

#[derive(Component)]
struct A {
    pub val: i32
}

#[derive(Component)]
struct B {
    pub val: i32
}

fn main() {
    let world = World::new();

    world.entity()
        .set(A { val: 1 })
        .set(B { val: 1 });
    world.entity()
        .set(A { val: 2 })
    ;

    // this correctly reports one archetype

    world.new_query::<(&A, Option<&B>)>()
        .each_entity(|e, (a, b)| {
            if let Some(b) = b {
                println!("entity archetype is: {}", e.archetype().to_string().unwrap());
                println!("component values are: (A.val: {}, B.val: {})", a.val, b.val);
            }
        });
}

Regards, Marko.

Indra-db commented 1 week ago

This has been patched on main branch, I expect a 0.2 release next-week ish.

for the time being, feel free to use

[workspace.dependencies.flecs_ecs]
git = "https://github.com/Indra-db/Flecs-Rust.git"
rev = "98b53fb" # main
version = "0.1.3"

for the time being.