diff --git a/src/main.rs b/src/main.rs index bb78c4f..8e86411 100644 --- a/src/main.rs +++ b/src/main.rs @@ -100,9 +100,8 @@ fn main() -> AppExit { .add_systems(OnExit(View::MainMenu), main_menu::exit) .add_systems( OnEnter(View::LoadingGame), - (player::startup, statue::startup, map::spawn), + (player::startup, statue::startup, map::init), ) - .add_systems(OnEnter(View::InGame), map::finalize) .add_systems( OnExit(View::InGame), (player::exit, statue::exit, map::exit), @@ -112,6 +111,7 @@ fn main() -> AppExit { ( load_menu.run_if(in_state(View::LoadingMenu)), load_game.run_if(in_state(View::LoadingGame)), + map::tile_loaders.run_if(in_state(View::LoadingGame)), input::process_input, (update,).after(input::process_input), ( diff --git a/src/map.rs b/src/map.rs index e303406..1680157 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1,3 +1,5 @@ +use std::sync::mpsc::{channel, Receiver}; + use crate::{inspector::HideFromInspector, prelude::*}; use bevy::{ ecs::{system::SystemState, world::CommandQueue}, @@ -15,57 +17,68 @@ use rand_seeder::Seeder; #[derive(Component, Debug)] pub struct Tilemap; -#[derive(Component)] -struct MapGenTask(Task); +#[derive(Resource, Debug)] +pub struct TileChan(Receiver); -#[derive(Resource, Deref, DerefMut)] -struct TileStorageHandle(TileStorage); +#[derive(Component, Debug)] +pub struct TileInit(Task<()>); -pub fn spawn(mut commands: Commands, assets: Res) { +pub fn init(mut commands: Commands, assets: Res) { // 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 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::>::new(world); - let entity = world - .spawn(( - HideFromInspector, - TileBundle { - position, - tilemap_id: TilemapId(tilemap), - texture_index, - ..Default::default() - }, - )) - .id(); + let tile_size = TilemapTileSize::new(16., 16.); + let grid_size = TilemapGridSize::new(16., 16.); + let map_type = TilemapType::Square; + let texture = TilemapTexture::Single(assets.load("img/Tileset Grass.png")); + let storage = TileStorage::empty(size); - let mut storage = state.get_mut(world); - storage.set(&position, entity); + let tilemap = commands + .spawn(( + Tilemap, + Name::new("Tilemap"), + TilemapBundle { + grid_size, + map_type, + size, + storage, + texture, + tile_size, + transform: get_tilemap_center_transform(&size, &grid_size, &map_type, f32::MIN), + ..Default::default() + }, + )) + .id(); + + let pool = AsyncComputeTaskPool::get(); + let task = pool.spawn(async move { + let (tx, rx) = channel::(); + 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 }); - command_queue - }); - commands.entity(tilemap).insert(MapGenTask(task)); + tx.send(TileBundle { + position, + tilemap_id: TilemapId(tilemap), + texture_index, + ..Default::default() + }) + .unwrap(); + } } - } + tx + }); + + commands.entity(tilemap).insert(TileInit(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) +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 @@ -74,38 +87,6 @@ fn load(mut commands: Commands, mut tasks: Query<&mut MapGenTask>) { } } -pub fn finalize( - // mut commands: Commands, - // mut storage: Res, - // tilemap: Query>, - // assets: Res, - world: &mut World, -) { - let storage = world.remove_resource::().unwrap(); - - // TODO: dedupe with load - let size = TilemapSize::new(1024, 1024); - let tile_size = TilemapTileSize::new(16., 16.); - let grid_size = TilemapGridSize::new(16., 16.); - let map_type = TilemapType::Square; - let storage = storage.0; - let mut query = world.query_filtered::>(); - let tilemap = query.single(world); - let assets = world.resource::(); - let texture = TilemapTexture::Single(assets.load("img/Tileset Grass.png")); - let mut commands = world.commands(); - commands.entity(tilemap).insert(TilemapBundle { - grid_size, - map_type, - size, - storage, - texture, - tile_size, - transform: get_tilemap_center_transform(&size, &grid_size, &map_type, f32::MIN), - ..Default::default() - }); -} - pub fn exit(mut commands: Commands, q: Query>) { for id in q.iter() { commands.entity(id).despawn_recursive();