Buildings Processing
Tile/Chunk updates events
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
use bevy::{prelude::*, window::PrimaryWindow};
|
||||
use std::f32::consts::E;
|
||||
|
||||
use bevy::{ecs::world::CommandQueue, prelude::*, window::PrimaryWindow};
|
||||
use bevy_asset_loader::loading_state::{
|
||||
config::{ConfigureLoadingState, LoadingStateConfig},
|
||||
LoadingStateAppExt,
|
||||
@@ -6,10 +8,13 @@ use bevy_asset_loader::loading_state::{
|
||||
use bevy_rapier3d::{parry::transformation::utils::transform, pipeline::QueryFilter, plugin::RapierContext};
|
||||
use shared::{
|
||||
despawn::Despawn,
|
||||
events::TileModifiedEvent,
|
||||
states::{AssetLoadState, GameplayState},
|
||||
tags::MainCamera,
|
||||
};
|
||||
use world_generation::{heightmap, hex_utils::HexCoord, map::map::Map};
|
||||
use world_generation::{
|
||||
heightmap, hex_utils::HexCoord, map::map::Map, prelude::GenerationConfig, states::GeneratorState,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
assets::{
|
||||
@@ -17,7 +22,8 @@ use crate::{
|
||||
building_database::BuildingDatabase,
|
||||
},
|
||||
build_queue::{BuildQueue, QueueEntry},
|
||||
buildings_map::BuildingMap,
|
||||
buildings_map::{BuildingEntry, BuildingMap},
|
||||
prelude::Building,
|
||||
};
|
||||
|
||||
pub struct BuildingPugin;
|
||||
@@ -25,7 +31,6 @@ pub struct BuildingPugin;
|
||||
impl Plugin for BuildingPugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.insert_resource(BuildQueue::default());
|
||||
app.init_resource::<BuildingMap>();
|
||||
app.add_plugins(BuildingAssetPlugin);
|
||||
|
||||
app.configure_loading_state(
|
||||
@@ -34,11 +39,31 @@ impl Plugin for BuildingPugin {
|
||||
|
||||
app.add_systems(Update, init.run_if(in_state(AssetLoadState::Loading)));
|
||||
app.add_systems(Update, hq_placement.run_if(in_state(GameplayState::PlaceHQ)));
|
||||
app.add_systems(
|
||||
PreUpdate,
|
||||
prepare_building_map.run_if(in_state(GeneratorState::SpawnMap)),
|
||||
);
|
||||
app.add_systems(Update, regernerate.run_if(in_state(GeneratorState::Regenerate)));
|
||||
app.add_systems(
|
||||
PostUpdate,
|
||||
update_building_heights.run_if(in_state(GeneratorState::Idle)),
|
||||
);
|
||||
|
||||
app.add_systems(PreUpdate, process_build_queue.run_if(in_state(GameplayState::Playing)));
|
||||
}
|
||||
}
|
||||
|
||||
fn prepare_building_map(mut commands: Commands, cfg: Res<GenerationConfig>) {
|
||||
commands.insert_resource(BuildingMap::new(cfg.size));
|
||||
}
|
||||
|
||||
fn regernerate(mut commands: Commands, buildings: Query<Entity, With<Building>>, cfg: Res<GenerationConfig>) {
|
||||
for e in buildings.iter() {
|
||||
commands.entity(e).despawn();
|
||||
}
|
||||
commands.insert_resource(BuildingMap::new(cfg.size));
|
||||
}
|
||||
|
||||
#[derive(Resource)]
|
||||
struct IndicatorCube(Handle<Mesh>, Handle<StandardMaterial>);
|
||||
|
||||
@@ -114,6 +139,7 @@ fn process_build_queue(
|
||||
mut commands: Commands,
|
||||
db: Res<BuildingDatabase>,
|
||||
building_assets: Res<Assets<BuildingAsset>>,
|
||||
mut building_map: ResMut<BuildingMap>,
|
||||
heightmap: Res<Map>,
|
||||
) {
|
||||
for item in &queue.queue {
|
||||
@@ -121,12 +147,44 @@ fn process_build_queue(
|
||||
if let Some(building) = building_assets.get(handle.id()) {
|
||||
let h = heightmap.sample_height(&item.pos);
|
||||
println!("Spawning {} at {}", building.name, item.pos);
|
||||
commands.spawn(SceneBundle {
|
||||
scene: building.prefab.clone(),
|
||||
transform: Transform::from_translation(item.pos.to_world(h)),
|
||||
..Default::default()
|
||||
});
|
||||
let e = commands.spawn((
|
||||
SceneBundle {
|
||||
scene: building.prefab.clone(),
|
||||
transform: Transform::from_translation(item.pos.to_world(h)),
|
||||
..Default::default()
|
||||
},
|
||||
Building,
|
||||
));
|
||||
|
||||
building_map.add_building(BuildingEntry::new(item.pos, e.id()));
|
||||
}
|
||||
}
|
||||
queue.queue.clear();
|
||||
}
|
||||
|
||||
fn update_building_heights(
|
||||
mut tile_updates: EventReader<TileModifiedEvent>,
|
||||
building_map: Res<BuildingMap>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
for event in tile_updates.read() {
|
||||
match event {
|
||||
TileModifiedEvent::HeightChanged(coord, new_height) => {
|
||||
if let Some(building) = building_map.get_building(coord) {
|
||||
let mut queue = CommandQueue::default();
|
||||
let e = building.entity.clone();
|
||||
let h = *new_height;
|
||||
queue.push(move |world: &mut World| {
|
||||
let mut emut = world.entity_mut(e);
|
||||
if let Some(mut transform) = emut.get_mut::<Transform>() {
|
||||
transform.translation.y = h;
|
||||
}
|
||||
});
|
||||
|
||||
commands.append(&mut queue);
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
use bevy::prelude::*;
|
||||
use world_generation::hex_utils::HexCoord;
|
||||
use world_generation::{hex_utils::HexCoord, prelude::Chunk};
|
||||
|
||||
#[derive(Resource, Default)]
|
||||
#[derive(Resource)]
|
||||
pub struct BuildingMap {
|
||||
pub chunks: Vec<BuildingChunk>,
|
||||
pub size: UVec2,
|
||||
}
|
||||
|
||||
impl BuildingMap {
|
||||
pub fn new(size: UVec2) -> Self {
|
||||
let mut db = BuildingMap {
|
||||
size,
|
||||
chunks: Vec::with_capacity(size.length_squared() as usize),
|
||||
};
|
||||
|
||||
@@ -23,19 +25,39 @@ impl BuildingMap {
|
||||
return db;
|
||||
}
|
||||
|
||||
pub fn get_buildings_in_range(&self, coord: &HexCoord, radius: usize) -> Option<Vec<&BuildingEntry>> {
|
||||
pub fn get_buildings_in_range(&self, coord: &HexCoord, radius: usize) -> Vec<&BuildingEntry> {
|
||||
assert!(radius != 0, "Radius cannot be zero");
|
||||
todo!();
|
||||
|
||||
let w = self.size.x as usize * Chunk::SIZE;
|
||||
let h = self.size.y as usize * Chunk::SIZE;
|
||||
let coords = coord.hex_select_bounded(radius, true, h, w);
|
||||
return self.get_buildings_in_coords(coords);
|
||||
}
|
||||
|
||||
pub fn get_buildings_in_coords(&self, coords: Vec<HexCoord>) -> Vec<&BuildingEntry> {
|
||||
let mut result = Vec::new();
|
||||
for coord in &coords {
|
||||
if let Some(buidling) = self.get_building(coord) {
|
||||
result.push(buidling);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn get_building(&self, coord: &HexCoord) -> Option<&BuildingEntry> {
|
||||
todo!();
|
||||
let chunk = &self.chunks[coord.to_chunk_index(self.size.x as usize)];
|
||||
return chunk.get_building(coord);
|
||||
}
|
||||
|
||||
pub fn add_building(&mut self, entry: BuildingEntry) {
|
||||
let chunk = &mut self.chunks[entry.coord.to_chunk_index(self.size.x as usize)];
|
||||
chunk.add_building(entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub struct BuildingChunk {
|
||||
pub entries: Vec<BuildingChunk>,
|
||||
pub entries: Vec<BuildingEntry>,
|
||||
pub index: usize,
|
||||
pub offset: IVec2,
|
||||
}
|
||||
@@ -50,7 +72,11 @@ impl BuildingChunk {
|
||||
}
|
||||
|
||||
pub fn get_building(&self, coord: &HexCoord) -> Option<&BuildingEntry> {
|
||||
todo!();
|
||||
return self.entries.iter().find(|b| &b.coord == coord);
|
||||
}
|
||||
|
||||
pub fn add_building(&mut self, entry: BuildingEntry) {
|
||||
self.entries.push(entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,4 +3,5 @@ pub mod build_queue;
|
||||
pub mod building_plugin;
|
||||
pub mod buildings_map;
|
||||
pub mod footprint;
|
||||
pub mod prelude;
|
||||
pub use building_plugin::*;
|
||||
|
||||
3
game/buildings/src/prelude.rs
Normal file
3
game/buildings/src/prelude.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
use bevy::prelude::*;
|
||||
#[derive(Component)]
|
||||
pub struct Building;
|
||||
Reference in New Issue
Block a user