WIP exclusive system, but I can't seem to make it work nicely

This commit is contained in:
Daniel Flanagan 2024-08-04 20:26:46 -05:00
parent 692fbed157
commit 5d846fdeff

View file

@ -1,6 +1,7 @@
use crate::View;
use crate::{inspector::HideFromInspector, prelude::*};
use bevy::ecs::system::SystemState;
use bevy::ecs::world::CommandQueue;
use bevy::tasks::{block_on, futures_lite::future, AsyncComputeTaskPool, Task};
use bevy_ecs_tilemap::prelude::*;
use rand::prelude::*;
@ -16,7 +17,7 @@ pub struct Tilemap;
pub struct TileChan(Mutex<Receiver<TileBundle>>);
#[derive(Component, Debug)]
pub struct TileInit(Task<()>);
pub struct TileLoaderTask(Task<()>);
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?
@ -71,76 +72,93 @@ pub fn init(mut commands: Commands, assets: Res<AssetServer>) {
commands
.entity(tilemap)
.insert((TileInit(task), TileChan(Mutex::new(rx))));
.insert((TileLoaderTask(task), TileChan(Mutex::new(rx))));
}
const MAX_TILES_TO_LOAD_IN_ONE_UPDATE: usize = 5_000;
pub fn tile_loaders(
world: &mut World,
params: &mut SystemState<(
Query<(Entity, &mut TileStorage), With<Tilemap>>,
Query<&TileChan, With<Tilemap>>,
Query<&mut TileInit>,
ResMut<NextState<View>>,
)>,
tilemap: QueryState<Entity, With<Tilemap>>,
storage: &mut QueryState<&mut TileStorage, With<Tilemap>>,
chan: QueryState<&TileChan, With<Tilemap>>,
task: QueryState<&mut TileLoaderTask, With<Tilemap>>,
params: &mut SystemState<ResMut<NextState<View>>>,
) {
let (mut query, mut chan, mut tasks, mut next_view) = params.get_mut(world);
let mut tiles_done = true;
let (tilemap, mut storage) = query.single_mut();
// TODO: this state should maybe be converted to a resource or something?
let mut tiles_done = false;
let mut task_done = false;
type AddingTile = (HideFromInspector, TileBundle);
type AddedTile<'a> = (Entity, &'a TilePos);
let mut tiles_to_add: Vec<AddingTile> = Vec::with_capacity(MAX_TILES_TO_LOAD_IN_ONE_UPDATE);
let mut added_tiles: Vec<AddedTile> = Vec::with_capacity(MAX_TILES_TO_LOAD_IN_ONE_UPDATE);
let mut tasks_iter = tasks.iter_mut().peekable();
let mut remove_tasks = false;
if tasks_iter.peek().is_none() && tiles_done {
next_view.set(View::InGame)
} else {
for mut task in tasks_iter {
let poll = future::poll_once(&mut task.0);
if block_on(poll).is_some() {
remove_tasks = true;
// task is done, remove it so we don't poll it again
}
// let mut task = task;
// {
// task_done = true;
// let mut task = task_query.get_single();
// if let Ok(task) = task {
// let poll = future::poll_once(task.0);
// if block_on(poll).is_some() {
// task_done = true;
// // task is done, remove it so we don't poll it again
// world.entity_mut(tilemap).remove::<TileLoaderTask>();
// }
// } else {
// next_view.set(View::InGame)
// }
// let (tilemap, mut storage) = entity_query.single_mut();
// let tiles: Vec<TileBundle> = vec![];
// if let Ok(channel) = channel_query.get_single_mut() {
// let channel = channel.0.lock().unwrap();
// tiles_done = false;
// let mut counter = 0;
// loop {
// match channel.recv() {
// Ok(tile) => {
// let position = &tile.position;
// let tile = world.spawn((HideFromInspector, tile)).id();
// storage.set(position, tile);
// counter += 1;
// if counter >= MAX_TILES_TO_LOAD_IN_ONE_UPDATE {
// info!("Finished {}!", counter);
// break;
// }
// }
// Err(_) => {
// world.entity_mut(tilemap).remove::<TileChan>();
// if counter > 0 {
// info!("Finished {counter}! Probably finishing mapgen soon...");
// }
// // the channel is likely closed, so let's note that and be done
// tiles_done = true;
// break;
// }
// }
// }
// }
for tile in tiles_to_add {
added_tiles.push((id, &tile.1.position));
let id = world.spawn(tile).id();
}
// world.spawn_batch(
// tiles
// .into_iter()
// .map(|t| (HideFromInspector, t))
// .into_iter(),
// );
{
let mut storage = storage.single_mut(world);
// storage.set(&
let mut next_view = params.get_mut(world);
if task_done && tiles_done {
next_view.set(View::InGame)
}
}
let tile_bundles: Vec<TileBundle> = vec![];
if let Ok(chan) = chan.get_single_mut() {
let chan = chan.0.lock().unwrap();
tiles_done = false;
let mut counter = 0;
loop {
match chan.recv() {
Ok(ev) => {
let ref_position = &ev.position;
let tile = world.spawn((HideFromInspector, ev)).id();
storage.set(ref_position, tile);
counter += 1;
if counter >= MAX_TILES_TO_LOAD_IN_ONE_UPDATE {
info!("Finished {}!", counter);
break;
}
}
Err(_) => {
world.entity_mut(tilemap).remove::<TileChan>();
if counter > 0 {
info!("Finished {counter}! Probably finishing mapgen soon...");
}
// the channel is likely closed, so let's note that and be done
tiles_done = true;
break;
}
}
}
}
if remove_tasks {
world.entity_mut(tilemap).remove::<TileInit>();
}
world.spawn_batch(
tile_bundles
.into_iter()
.map(|t| (HideFromInspector, t))
.into_iter(),
);
}
pub fn exit(mut commands: Commands, q: Query<Entity, With<Tilemap>>) {