#Manually flush Commands in the middle of a system without exclusive mutability on the world?

71 messages · Page 1 of 1 (latest)

frail dome
#

Basically the title-- I want to manually flush Commands without a mutable ref to the world. I don't want to split up my function into two systems just for the sake of doing this flush.

Is there another way?

#

if not-- I basically know these two systems are going to run serially, one after another-- just for the sake of the flush

#

is the best way to pass data between two systems like that going to be with Events?

#

it almost feels like just IO for two normal functions, and i would really like to just do this work in an exclusive system-- but i don't want to lock the entire world

frail dome
#

maybe what i'm looking for here is a way to compose systems procedurally without an exclusive ref to World

#

because doing it declaratively for these things is getting annoying

gloomy estuary
#

you cannot mutate the World (apply commands) without a mutable reference to the World, commands can only ever be serial operations

#

spawning entities, despawning entities, adding components, removing components moves around data that would absolutely be prone to race conditions otherwise

frail dome
#

well this is basically what my code looks like right now

#

so what's going on is

#

the improvements i'd like to make are: passing current_frame into sync_entities_schedule-- ideally without statefully inserting/removing a resource into the world

#

is that possible?

#

one thing i was thinking was using system.run and par_iter

#

instead of schedules

gloomy estuary
#

🤔 if current_frame is stored inside the world, then you can't "pin it" with a reference and also take a mutable reference to the world at the same time

#

since that would break the "aliasing XOR mutability" rule

frail dome
#

current frame is a refcounted serialized snapshot of the world

#

so it should be fine

#

there's no active borrow or references to the world

gloomy estuary
#

you asked about passing current_frame into sync_entities_schedule, so I assumed you meant as like another input along with &mut World

frail dome
#

i mean yeah i kind of just want to provide it as kind of like a local resource to the schedule

#

or actually sorry-- i want to pass merged_snapshot, which is expensive to build

#

misspoke

#

i'm thinking maybe i should just do all this by hand

#

with par_iter

gloomy estuary
#

maybe yeah, sorry I don't understand what you're trying

frail dome
#

just want to run these two procedurally instead of building a schedule

#

first 1 sync_entities_to_world, and then N write_snapshot_to_world_components

#

write_snapshot_to_world_components in parallel

#

which should be safe i think?

gloomy estuary
#

hmm, I don't think you'll be able to run systems in a procedural way without storing them as entities

frail dome
#

actually maybe they don't even have to be systems

gloomy estuary
#

spawning and despawning entities and adding and removing components always requires an exclusive lock on the world tho

frail dome
#

so commands just defers those then?

#

and executes them in serial

gloomy estuary
#

yeah, queues them up basically

frail dome
#

then i guess these don't even have to be systems

#

since there's going to be an exclusive lock on the world the whole time anyway

gloomy estuary
#

yeah, commands are like a database transaction, prepared in advance but not committed until we have a lock

frail dome
#

ok actually maybe i will just break this out into normal systems

gloomy estuary
#

one exception, when you make a spawn command, you get the Entity value immediately

frail dome
#

i like being able to invoke systems procedurally though, it simplifies a ton of code

#

and especially if a Schedule can do IO, that would be really cool and useful

#

and have local Resources that don't pollute the whole world

gloomy estuary
#

yeah, it's a limit of bevy_ecs

#

once we implement entity relationships, we can store systems as entities and scheduling constraints as relationships

#

then you could "procedurally" query systems and run them that way

frail dome
#

so another thing is that i planned on making MergedSnapshot zero copy

#

basically storing a slice of &'a Snapshot

#

the idea here is that all of your peers send snapshots, and the client merges them

#

before reading the world state from them

#

but i don't think this is possible in the ECS at all

#

which is why i was trying to do it with exclusive systems

#

does that make sense? not sure how to explain it

gloomy estuary
#

right, data stored inside the world has to be T: 'static, cannot store short-lived data in it

#

there are cases where you can soundly transmute &'a to &'static, as long as you prove/ensure that 'a is functionally equivalent to 'static from the POV of the scope

frail dome
#

that makes sense

gloomy estuary
#

for example, you can send non-static references from thread A to thread B by transmuting them to 'static, as long as you force A to block until B drops them

frail dome
#

hmm

#

do you think im building this in a fundamentally stupid way

#

i understand that a lot of this could be resolved "automatically" if i just built a schedule and used resources for everything

#

that was the old solution, but then i built the zero-copy MergedSnapshot<'a> and went down this road

gloomy estuary
#

there are things that you can't do in a nice way with bevy because we haven't implemented features yet, or because rust makes it challenging

#

saving and restoring has been a big question for a long time

frail dome
#

i think what i have mostly works pretty well

#

there are a lot of issues with Event, Added, Removed, things like that

#

but i'm just building those abstractions myself and using my own for now