Maybe progress? A task per tile because we're super lazy

This commit is contained in:
Daniel Flanagan 2024-08-02 21:43:30 -05:00
parent deabad05ee
commit 21cec093b9
7 changed files with 74 additions and 122 deletions

View file

@ -1,3 +0,0 @@
[target.x86_64-unknown-linux-gnu]
linker = "clang"
rustflags = ["-C", "link-arg=-fuse-ld=/nix/store/46n1qljc0drdz4r2k9smxxb8kl79di25-mold-2.32.1/bin/mold"]

View file

@ -108,18 +108,20 @@
nativeBuildInputs = buildTimeDeps pkgs; nativeBuildInputs = buildTimeDeps pkgs;
buildInputs = linkTimeDeps pkgs; buildInputs = linkTimeDeps pkgs;
# hash = pkgs.lib.fakeHash;
# a hack to avoid using mold as our linker when building with nix
postUnpack = ''
ls -la
rm -r ./*/.cargo
'';
}; };
ZSTD_SYS_USE_PKG_CONFIG = "1";
LIBSSH2_SYS_USE_PKG_CONFIG = "1";
RUSTFLAGS = pkgs.lib.optionalString pkgs.stdenv.isLinux "-C link-arg=-fuse-ld=mold";
default = outputs.packages.${pkgs.system}.kodotag; default = outputs.packages.${pkgs.system}.kodotag;
}); });
apps = forSystems (system: {
kodotag = outputs.packages.${system}.kodotag;
default = outputs.apps.${system}.kodotag;
});
devShells = genPkgs (pkgs: { devShells = genPkgs (pkgs: {
default = pkgs.mkShell { default = pkgs.mkShell {
inherit (self.checks.${pkgs.system}.git-hooks) shellHook; inherit (self.checks.${pkgs.system}.git-hooks) shellHook;

View file

@ -79,6 +79,8 @@ fn main() -> AppExit {
.init_state::<View>() .init_state::<View>()
.init_state::<Game>(); .init_state::<Game>();
app.enable_state_scoped_entities::<View>();
app.configure_sets( app.configure_sets(
Update, Update,
( (
@ -100,6 +102,7 @@ fn main() -> AppExit {
OnEnter(View::LoadingGame), OnEnter(View::LoadingGame),
(player::startup, statue::startup, map::spawn), (player::startup, statue::startup, map::spawn),
) )
.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),

View file

@ -1,5 +1,7 @@
use bevy::prelude::*; use bevy::prelude::*;
use crate::View;
#[derive(Component, Debug)] #[derive(Component, Debug)]
pub struct MainMenu; pub struct MainMenu;
@ -7,6 +9,7 @@ pub fn startup(mut commands: Commands) {
commands commands
.spawn(( .spawn((
MainMenu, MainMenu,
StateScoped(View::MainMenu),
Name::new("MenuRoot"), Name::new("MenuRoot"),
NodeBundle { NodeBundle {
style: Style { style: Style {

View file

@ -1,6 +1,6 @@
use crate::{inspector::HideFromInspector, prelude::*}; use crate::{inspector::HideFromInspector, prelude::*};
use bevy::{ use bevy::{
ecs::world::CommandQueue, ecs::{system::SystemState, world::CommandQueue},
tasks::{block_on, futures_lite::future, AsyncComputeTaskPool, Task}, tasks::{block_on, futures_lite::future, AsyncComputeTaskPool, Task},
}; };
// use bevy::{ // use bevy::{
@ -11,13 +11,15 @@ use bevy_ecs_tilemap::prelude::*;
use rand::prelude::*; use rand::prelude::*;
use rand_pcg::Pcg64; use rand_pcg::Pcg64;
use rand_seeder::Seeder; use rand_seeder::Seeder;
use std::sync::mpsc::channel;
#[derive(Component, Debug)] #[derive(Component, Debug)]
pub struct Tilemap; pub struct Tilemap;
#[derive(Component)] #[derive(Component)]
struct MapGen(Task<TileBundleBuilder>); struct MapGenTask(Task<CommandQueue>);
#[derive(Resource, Deref)]
struct TileStorageHandle(TileStorage);
pub fn spawn(mut commands: Commands, assets: Res<AssetServer>) { pub fn spawn(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?
@ -25,14 +27,8 @@ pub fn spawn(mut commands: Commands, assets: Res<AssetServer>) {
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(); let tilemap = commands.spawn((Tilemap, Name::new("Tilemap"))).id();
commands.insert_resource(TileStorageHandle(TileStorage::empty(size)));
let mut storage = TileStorage::empty(size); let pool = AsyncComputeTaskPool::get();
// let mutex_storage = Mutex::new(storage);
let task_pool = AsyncComputeTaskPool::get();
let (tx, rx) = channel::<TileBundle>();
let tilebundlegenerator = task_pool.spawn(async move {
// this task is for generating tilebundles // this task is for generating tilebundles
for x in 0..size.x { for x in 0..size.x {
for y in 0..size.y { for y in 0..size.y {
@ -42,28 +38,54 @@ pub fn spawn(mut commands: Commands, assets: Res<AssetServer>) {
} else { } else {
0 0
}); });
tx.send(TileBundle { let task = pool.spawn(async move {
let mut command_queue = CommandQueue::default();
command_queue.push(move |world: &mut World| {
let mut state = SystemState::<Res<TileStorageHandle>>::new(world);
let storage = state.get_mut(world);
let entity = world
.spawn((
HideFromInspector,
TileBundle {
position, position,
tilemap_id: TilemapId(tilemap), tilemap_id: TilemapId(tilemap),
texture_index, texture_index,
..Default::default() ..Default::default()
},
))
.id();
storage.set(&position, entity);
});
command_queue
}); });
} }
} }
}); }
for x in 0..size.x { fn load(mut commands: Commands, mut tasks: Query<&mut MapGenTask>) {
for y in 0..size.y { // to avoid locking up the universe we only want to handle a certain number per iteration (Update)
let tile = commands.spawn().id(); for mut task in &mut tasks {
storage.set(&position, tile); 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>,
) {
// TODO: dedupe with load
let size = TilemapSize::new(1024, 1024);
let texture = TilemapTexture::Single(assets.load("img/Tileset Grass.png")); let texture = TilemapTexture::Single(assets.load("img/Tileset Grass.png"));
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 tilemap = tilemap.single();
commands.entity(tilemap).insert(TilemapBundle { commands.entity(tilemap).insert(TilemapBundle {
grid_size, grid_size,
map_type, map_type,
@ -76,82 +98,6 @@ pub fn spawn(mut commands: Commands, assets: Res<AssetServer>) {
}); });
} }
// pub fn spawn_in_background(mut commands: Commands, assets: Res<AssetServer>) {
// let pool = AsyncComputeTaskPool::get();
// let tilemap_entity = commands.spawn(Name::new("TilemapEntity")).id();
// let texture_handle: Handle<Image> = assets.load("img/Tileset Grass.png");
// let mut rng: Pcg64 = Seeder::from("default_seed").make_rng();
// let map_size = UVec2::new(1024, 1024);
// let tile_size = Vec2 { x: 16.0, y: 16.0 };
// // tiletypes?
// let task = pool.spawn(async move {
// let mut queue = CommandQueue::default();
// for x in 0..map_size.x {
// for y in 0..map_size.y {
// let pos = Vec2::new(x as f32, y as f32) * tile_size;
// let texture_index = TileTextureIndex(if rng.gen_range(0..1000) > 925 {
// rng.gen_range(0..(16 * 8))
// } else {
// 0
// });
// queue.push(move |world: &mut World| {
// let tile_entity = world
// .spawn((
// HideFromInspector,
// TileBundle {
// position: tile_pos,
// tilemap_id: TilemapId(tilemap_entity),
// texture_index,
// ..Default::default()
// },
// ))
// .id();
// tile_storage_ref.set(&tile_pos, tile_entity);
// });
// }
// }
// queue.push(move |world: &mut World| {
// world.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()
// },
// ));
// });
// queue
// });
// commands.entity(tilemap_entity).insert(MapGen(task));
// }
// fn handle_tasks(mut commands: Commands, mut tasks: Query<&mut MapGen>) {
// for mut task in &mut tasks {
// if let Some(mut queue) = block_on(future::poll_once(&mut task.0)) {
// commands.append(&mut queue);
// }
// }
// }
fn load(mut commands: Commands, mut tasks: Query<&mut MapGen>) {
// 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>>) {
for id in q.iter() { for id in q.iter() {
commands.entity(id).despawn_recursive(); commands.entity(id).despawn_recursive();

View file

@ -2,7 +2,7 @@ use std::f32::consts::TAU;
use crate::camera::Watched; use crate::camera::Watched;
use crate::movement::{Heading, Mover, Speed, Velocity, YSortable}; use crate::movement::{Heading, Mover, Speed, Velocity, YSortable};
use crate::prelude::*; use crate::{prelude::*, View};
use bevy::sprite::MaterialMesh2dBundle; use bevy::sprite::MaterialMesh2dBundle;
const PLAYER_SPEED: f32 = 200.; const PLAYER_SPEED: f32 = 200.;
@ -35,6 +35,7 @@ pub fn startup(
commands commands
.spawn(( .spawn((
Player, Player,
StateScoped(View::InGame),
Name::new("Player"), Name::new("Player"),
VisibilityBundle { VisibilityBundle {
visibility: Visibility::Inherited, visibility: Visibility::Inherited,

View file

@ -1,5 +1,5 @@
use crate::movement::YSortable; use crate::movement::YSortable;
use crate::prelude::*; use crate::{prelude::*, View};
#[derive(Component, Debug, Default)] #[derive(Component, Debug, Default)]
pub struct Statue; pub struct Statue;
@ -51,7 +51,7 @@ pub fn spawn_statue(
}, },
..default() ..default()
}; };
commands.spawn((Name::new("Statue"), bundle)); commands.spawn((Name::new("Statue"), StateScoped(View::InGame), bundle));
} }
} }