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

Best practice for borrowed resources in systems? #757

Open
alvaro-cuesta opened this issue Jul 15, 2022 · 4 comments
Open

Best practice for borrowed resources in systems? #757

alvaro-cuesta opened this issue Jul 15, 2022 · 4 comments
Labels

Comments

@alvaro-cuesta
Copy link

alvaro-cuesta commented Jul 15, 2022

I'm halfway through the Roguelike tutorial and I would like to move my render logic into a System and use a Dispatcher instead of manually running systems. In this case bracket-lib has a tick where you mutably borrow a BTerm instance, but it feels like this is a common pattern where some kind of context is mutably borrowed.

What's the best practice here? Should we just build a dispatcher per tick and pass the context in the system struct?

@torkleyy
Copy link
Member

I think I'm missing some context here, but if you just need mutable access to something from a system, that shouldn't be a problem, you can just use Write<'a, BTerm> (although I'm not sure what BTerm is).

Some games / game engines even use a second World and Dispatcher, and copy data from their main world to a rendering world in order to render the frame while processing data for the next frame (of course you still need to synchronize and extract data in that case).

@alvaro-cuesta
Copy link
Author

alvaro-cuesta commented Jul 15, 2022

Definitely lacks context, my fault. I will try to get a minimum-viable example (I tried https://play.rust-lang.org but specs is not available), but in the meantime here's some context in case it helps.

The problem is not access from the system, but insertion into the world.

pub struct MyGame {
    world: World,
    dispatcher: Dispatcher<'static, 'static>,
}

// This trait is from my framework
//
// Notice that `GameState` requires `Self: 'static` which is why my dispatcher is `<'static, 'static>`
impl GameState for MyGame {
    fn tick(&mut self, ctx: &mut Foo) {
        // Here `ctx` would escape out of the function
        self.world.insert(ctx);
        self.dispatcher.dispatch(&mut self.world);
        self.world.maintain();
        self.world.remove::<&mut Foo>();
    }
}

I think I can fix this by building the dispatcher once per tick and just storing the ctx in the render system struct (via with_thread_local), but that seems hacky. Any alternative I'm missing that still allows me using Dispatcher?

@torkleyy
Copy link
Member

Oh are you forced to use the GameState? Because yes you're not gonna be able to store a non-static reference in World.

If you cannot get ownership of ctx you can either use [World::exec] to run a system as a closure:

pub struct MyGame {
    world: World,
    dispatcher: Dispatcher<'static, 'static>,
}

// This trait is from my framework
//
// Notice that `GameState` requires `Self: 'static` which is why my dispatcher is `<'static, 'static>`
impl GameState for MyGame {
    fn tick(&mut self, ctx: &mut Foo) {
        self.dispatcher.dispatch(&mut self.world);
        self.world.exec(|components: ReadStorage<Component>, other: WriteStorage<Other>| {
            ctx.do_something();
        });
        self.world.maintain();
    }
}

or, if you want to put your rendering systems into the dispatcher, serialize required input from ctx into appropriate resources in World and record writes to ctx in components / resources and apply them after dispatching.

However, I recommend you check if you can get ownership of ctx: Foo, possibly by not making use of GameState. Then you can just insert it into World.

@bayou-brogrammer
Copy link

bayou-brogrammer commented Sep 13, 2022

@torkleyy I instead used draw batch feature of bracket lib to do the console printing from the system. I just made a rendering dispatcher and run it within my draw method of whichever state I am in.

https://github.com/lecoqjacob/blood_oath/blob/main/src/ecs/systems/render/renderer.rs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants