Channels won't work _easily_ as the Receiver is not Send

I think I'll try using Bevy's event system
This commit is contained in:
Daniel Flanagan 2024-08-02 23:16:54 -05:00
parent 84bceda2a2
commit 5942539ead
2 changed files with 55 additions and 74 deletions

View file

@ -100,9 +100,8 @@ fn main() -> AppExit {
.add_systems(OnExit(View::MainMenu), main_menu::exit) .add_systems(OnExit(View::MainMenu), main_menu::exit)
.add_systems( .add_systems(
OnEnter(View::LoadingGame), OnEnter(View::LoadingGame),
(player::startup, statue::startup, map::spawn), (player::startup, statue::startup, map::init),
) )
.add_systems(OnEnter(View::InGame), map::finalize)
.add_systems( .add_systems(
OnExit(View::InGame), OnExit(View::InGame),
(player::exit, statue::exit, map::exit), (player::exit, statue::exit, map::exit),
@ -112,6 +111,7 @@ fn main() -> AppExit {
( (
load_menu.run_if(in_state(View::LoadingMenu)), load_menu.run_if(in_state(View::LoadingMenu)),
load_game.run_if(in_state(View::LoadingGame)), load_game.run_if(in_state(View::LoadingGame)),
map::tile_loaders.run_if(in_state(View::LoadingGame)),
input::process_input, input::process_input,
(update,).after(input::process_input), (update,).after(input::process_input),
( (

View file

@ -1,3 +1,5 @@
use std::sync::mpsc::{channel, Receiver};
use crate::{inspector::HideFromInspector, prelude::*}; use crate::{inspector::HideFromInspector, prelude::*};
use bevy::{ use bevy::{
ecs::{system::SystemState, world::CommandQueue}, ecs::{system::SystemState, world::CommandQueue},
@ -15,86 +17,28 @@ use rand_seeder::Seeder;
#[derive(Component, Debug)] #[derive(Component, Debug)]
pub struct Tilemap; pub struct Tilemap;
#[derive(Component)] #[derive(Resource, Debug)]
struct MapGenTask(Task<CommandQueue>); pub struct TileChan(Receiver<TileBundle>);
#[derive(Resource, Deref, DerefMut)] #[derive(Component, Debug)]
struct TileStorageHandle(TileStorage); pub struct TileInit(Task<()>);
pub fn spawn(mut commands: Commands, assets: Res<AssetServer>) { pub fn init(mut commands: Commands, assets: Res<AssetServer>) {
// 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();
let size = TilemapSize::new(1024, 1024); let size = TilemapSize::new(1024, 1024);
let tilemap = commands.spawn((Tilemap, Name::new("Tilemap"))).id();
commands.insert_resource(TileStorageHandle(TileStorage::empty(size)));
let pool = AsyncComputeTaskPool::get();
// this task is for generating tilebundles
for x in 0..size.x {
for y in 0..size.y {
let position = TilePos::new(x, y);
let texture_index = TileTextureIndex(if rng.gen_range(0..1000) > 925 {
rng.gen_range(0..(16 * 8))
} else {
0
});
let task = pool.spawn(async move {
let mut command_queue = CommandQueue::default();
command_queue.push(move |world: &mut World| {
let mut state = SystemState::<ResMut<TileStorageHandle>>::new(world);
let entity = world
.spawn((
HideFromInspector,
TileBundle {
position,
tilemap_id: TilemapId(tilemap),
texture_index,
..Default::default()
},
))
.id();
let mut storage = state.get_mut(world);
storage.set(&position, entity);
});
command_queue
});
commands.entity(tilemap).insert(MapGenTask(task));
}
}
}
fn load(mut commands: Commands, mut tasks: Query<&mut MapGenTask>) {
// to avoid locking up the universe we only want to handle a certain number per iteration (Update)
for mut task in &mut tasks {
if let Some(mut commands_queue) = block_on(future::poll_once(&mut task.0)) {
// append the returned command queue to have it execute later
commands.append(&mut commands_queue);
}
}
}
pub fn finalize(
// mut commands: Commands,
// mut storage: Res<TileStorageHandle>,
// tilemap: Query<Entity, With<Tilemap>>,
// assets: Res<AssetServer>,
world: &mut World,
) {
let storage = world.remove_resource::<TileStorageHandle>().unwrap();
// TODO: dedupe with load
let size = TilemapSize::new(1024, 1024);
let tile_size = TilemapTileSize::new(16., 16.); let tile_size = TilemapTileSize::new(16., 16.);
let grid_size = TilemapGridSize::new(16., 16.); let grid_size = TilemapGridSize::new(16., 16.);
let map_type = TilemapType::Square; let map_type = TilemapType::Square;
let storage = storage.0;
let mut query = world.query_filtered::<Entity, With<Tilemap>>();
let tilemap = query.single(world);
let assets = world.resource::<AssetServer>();
let texture = TilemapTexture::Single(assets.load("img/Tileset Grass.png")); let texture = TilemapTexture::Single(assets.load("img/Tileset Grass.png"));
let mut commands = world.commands(); let storage = TileStorage::empty(size);
commands.entity(tilemap).insert(TilemapBundle {
let tilemap = commands
.spawn((
Tilemap,
Name::new("Tilemap"),
TilemapBundle {
grid_size, grid_size,
map_type, map_type,
size, size,
@ -103,7 +47,44 @@ pub fn finalize(
tile_size, tile_size,
transform: get_tilemap_center_transform(&size, &grid_size, &map_type, f32::MIN), transform: get_tilemap_center_transform(&size, &grid_size, &map_type, f32::MIN),
..Default::default() ..Default::default()
},
))
.id();
let pool = AsyncComputeTaskPool::get();
let task = pool.spawn(async move {
let (tx, rx) = channel::<TileBundle>();
for x in 0..size.x {
for y in 0..size.y {
let position = TilePos::new(x, y);
let texture_index = TileTextureIndex(if rng.gen_range(0..1000) > 925 {
rng.gen_range(0..(16 * 8))
} else {
0
}); });
tx.send(TileBundle {
position,
tilemap_id: TilemapId(tilemap),
texture_index,
..Default::default()
})
.unwrap();
}
}
tx
});
commands.entity(tilemap).insert(TileInit(task));
}
pub fn tile_loaders(mut commands: Commands, mut tasks: Query<&mut TileInit>) {
// TODO: to avoid locking up the universe we only want to handle a certain number per iteration (Update)
for mut task in &mut tasks {
if let Some(mut commands_queue) = block_on(future::poll_once(&mut task.0)) {
// append the returned command queue to have it execute later
commands.append(&mut commands_queue);
}
}
} }
pub fn exit(mut commands: Commands, q: Query<Entity, With<Tilemap>>) { pub fn exit(mut commands: Commands, q: Query<Entity, With<Tilemap>>) {