Can't seem to get an eventwriter in the context of an asynccomputetask -- at least not easily

I did find this, though https://github.com/bevyengine/bevy/issues/8983

Which shows a mutex around a reciever - maybe that could work so I can use channels?
This commit is contained in:
Daniel Flanagan 2024-08-02 23:31:32 -05:00
parent 5942539ead
commit 315fb69a32
2 changed files with 33 additions and 22 deletions

View file

@ -14,6 +14,7 @@ use bevy::audio::{AudioPlugin, SpatialScale};
use bevy::window::{PrimaryWindow, WindowMode}; use bevy::window::{PrimaryWindow, WindowMode};
use bevy_ecs_tilemap::TilemapPlugin; use bevy_ecs_tilemap::TilemapPlugin;
use input::Input; use input::Input;
use map::TileLoadEvent;
use prelude::*; use prelude::*;
use statue::SpawnStatueEvent; use statue::SpawnStatueEvent;
@ -92,6 +93,7 @@ fn main() -> AppExit {
); );
app.add_event::<SpawnStatueEvent>(); app.add_event::<SpawnStatueEvent>();
app.add_event::<TileLoadEvent>();
app.add_systems( app.add_systems(
OnEnter(View::LoadingMenu), OnEnter(View::LoadingMenu),

View file

@ -1,10 +1,5 @@
use std::sync::mpsc::{channel, Receiver};
use crate::{inspector::HideFromInspector, prelude::*}; use crate::{inspector::HideFromInspector, prelude::*};
use bevy::{ use bevy::tasks::{block_on, futures_lite::future, AsyncComputeTaskPool, Task};
ecs::{system::SystemState, world::CommandQueue},
tasks::{block_on, futures_lite::future, AsyncComputeTaskPool, Task},
};
// use bevy::{ // use bevy::{
// ecs::world::CommandQueue, // ecs::world::CommandQueue,
// tasks::{AsyncComputeTaskPool, Task}, // tasks::{AsyncComputeTaskPool, Task},
@ -17,13 +12,17 @@ use rand_seeder::Seeder;
#[derive(Component, Debug)] #[derive(Component, Debug)]
pub struct Tilemap; pub struct Tilemap;
#[derive(Resource, Debug)]
pub struct TileChan(Receiver<TileBundle>);
#[derive(Component, Debug)] #[derive(Component, Debug)]
pub struct TileInit(Task<()>); pub struct TileLoader(Task<()>);
pub fn init(mut commands: Commands, assets: Res<AssetServer>) { #[derive(Event)]
pub struct TileLoadEvent(TileBundle);
pub fn init(
mut commands: Commands,
assets: Res<AssetServer>,
mut loads: EventWriter<TileLoadEvent>,
) {
// TODO: I'm pretty determined to not have this sieze up the game despite the large number of entities being added. Should work with a "loading" screen and doing this in the background? // TODO: I'm pretty determined to not have this sieze up the game despite the large number of entities being added. Should work with a "loading" screen and doing this in the background?
let mut rng: Pcg64 = Seeder::from("default_seed").make_rng(); let mut rng: Pcg64 = Seeder::from("default_seed").make_rng();
@ -53,7 +52,6 @@ pub fn init(mut commands: Commands, assets: Res<AssetServer>) {
let pool = AsyncComputeTaskPool::get(); let pool = AsyncComputeTaskPool::get();
let task = pool.spawn(async move { let task = pool.spawn(async move {
let (tx, rx) = channel::<TileBundle>();
for x in 0..size.x { for x in 0..size.x {
for y in 0..size.y { for y in 0..size.y {
let position = TilePos::new(x, y); let position = TilePos::new(x, y);
@ -62,27 +60,38 @@ pub fn init(mut commands: Commands, assets: Res<AssetServer>) {
} else { } else {
0 0
}); });
tx.send(TileBundle { loads.send(TileLoadEvent(TileBundle {
position, position,
tilemap_id: TilemapId(tilemap), tilemap_id: TilemapId(tilemap),
texture_index, texture_index,
..Default::default() ..default()
}) }));
.unwrap();
} }
} }
tx
return ();
}); });
commands.entity(tilemap).insert(TileInit(task)); commands.entity(tilemap).insert(TileLoader(task));
} }
pub fn tile_loaders(mut commands: Commands, mut tasks: Query<&mut TileInit>) { pub fn tile_loaders(
mut commands: Commands,
mut storage: Query<&mut TileStorage>,
mut tasks: Query<&mut TileLoader>,
mut loads: EventReader<TileLoadEvent>,
) {
// TODO: to avoid locking up the universe we only want to handle a certain number per iteration (Update) // TODO: to avoid locking up the universe we only want to handle a certain number per iteration (Update)
let mut storage = storage.single_mut();
for ev in loads.read() {
let ref_position = &ev.0.position;
let tile = commands.spawn((HideFromInspector, ev.0)).id();
storage.set(ref_position, tile);
}
for mut task in &mut tasks { for mut task in &mut tasks {
if let Some(mut commands_queue) = block_on(future::poll_once(&mut task.0)) { if block_on(future::poll_once(&mut task.0)).is_some() {
// append the returned command queue to have it execute later // TODO: transition to game?
commands.append(&mut commands_queue);
} }
} }
} }