diff --git a/kubi/src/block_placement.rs b/kubi/src/block_placement.rs index aec44a3..f46ff1b 100644 --- a/kubi/src/block_placement.rs +++ b/kubi/src/block_placement.rs @@ -1,7 +1,7 @@ use shipyard::{UniqueViewMut, UniqueView, View, IntoIter, ViewMut, EntitiesViewMut}; use crate::{ player::MainPlayer, - world::{raycast::LookingAtBlock, ChunkStorage, block::Block}, + world::{raycast::LookingAtBlock, ChunkStorage, block::Block, queue::{BlockUpdateQueue, BlockUpdateEvent}}, input::{Inputs, PrevInputs}, events::{EventComponent, player_actions::PlayerActionEvent}, }; @@ -11,7 +11,7 @@ pub fn block_placement_system( raycast: View, input: UniqueView, prev_input: UniqueView, - mut world: UniqueViewMut, + mut block_event_queue: UniqueViewMut, mut entities: EntitiesViewMut, mut events: ViewMut, mut player_events: ViewMut, @@ -21,21 +21,18 @@ pub fn block_placement_system( if action_place ^ action_break { //get raycast info let Some(ray) = (&main_player, &raycast).iter().next().unwrap().1/**/.0 else { return }; - //update block + //get coord and block type let (place_position, place_block) = if action_place { let position = (ray.position - ray.direction * 0.5).floor().as_ivec3(); - let Some(block) = world.get_block_mut(position) else { return }; - *block = Block::Dirt; - (position, *block) + (position, Block::Dirt) } else { - let Some(block) = world.get_block_mut(ray.block_position) else { return }; - *block = Block::Air; - (ray.block_position, *block) + (ray.block_position, Block::Air) }; - //mark chunk as dirty - let (chunk_pos, _) = ChunkStorage::to_chunk_coords(place_position); - let chunk = world.chunks.get_mut(&chunk_pos).unwrap(); - chunk.dirty = true; + //queue place + block_event_queue.push(BlockUpdateEvent { + position: place_position, + value: place_block, + }); //send event entities.add_entity( (&mut events, &mut player_events), diff --git a/kubi/src/main.rs b/kubi/src/main.rs index 68a3e31..6af453e 100644 --- a/kubi/src/main.rs +++ b/kubi/src/main.rs @@ -35,7 +35,7 @@ pub(crate) mod control_flow; use world::{ init_game_world, loading::update_loaded_world_around_player, - raycast::update_raycasts + raycast::update_raycasts, queue::apply_queued_blocks }; use player::spawn_player; use prefabs::load_prefabs; @@ -84,6 +84,7 @@ fn update() -> Workload { update_loaded_world_around_player, update_raycasts, block_placement_system, + apply_queued_blocks, update_cursor_lock_state, compute_cameras, exit_on_esc, diff --git a/kubi/src/world.rs b/kubi/src/world.rs index 355d33b..4d8684d 100644 --- a/kubi/src/world.rs +++ b/kubi/src/world.rs @@ -15,10 +15,10 @@ pub mod neighbors; pub mod raycast; pub mod queue; -use chunk::{Chunk, ChunkMesh}; +use block::Block; +use chunk::{Chunk, ChunkMesh, CHUNK_SIZE}; use tasks::ChunkTaskManager; - -use self::{chunk::CHUNK_SIZE, block::Block}; +use queue::BlockUpdateQueue; //TODO separate world struct for render data // because this is not send-sync @@ -111,4 +111,5 @@ pub fn init_game_world( storages.add_unique_non_send_sync(ChunkMeshStorage::new()); storages.add_unique(ChunkStorage::new()); storages.add_unique(ChunkTaskManager::new()); + storages.add_unique(BlockUpdateQueue::new()); } diff --git a/kubi/src/world/chunk.rs b/kubi/src/world/chunk.rs index 285ab44..7d3733d 100644 --- a/kubi/src/world/chunk.rs +++ b/kubi/src/world/chunk.rs @@ -46,7 +46,7 @@ pub struct Chunk { pub mesh_index: Option, pub current_state: CurrentChunkState, pub desired_state: DesiredChunkState, - pub dirty: bool, + pub mesh_dirty: bool, } impl Chunk { pub fn new(position: IVec3) -> Self { @@ -56,7 +56,7 @@ impl Chunk { mesh_index: None, current_state: Default::default(), desired_state: Default::default(), - dirty: false, + mesh_dirty: false, } } } diff --git a/kubi/src/world/loading.rs b/kubi/src/world/loading.rs index 28ec501..7320f3b 100644 --- a/kubi/src/world/loading.rs +++ b/kubi/src/world/loading.rs @@ -138,7 +138,7 @@ fn start_required_tasks( // =========== //log::trace!("Started loading chunk {position}"); }, - DesiredChunkState::Rendered if (chunk.current_state == CurrentChunkState::Loaded || chunk.dirty) => { + DesiredChunkState::Rendered if (chunk.current_state == CurrentChunkState::Loaded || chunk.mesh_dirty) => { //get needed data let Some(neighbors) = world.neighbors_all(position) else { continue @@ -150,12 +150,12 @@ fn start_required_tasks( task_manager.spawn_task(ChunkTask::GenerateMesh { data, position }); //Update chunk state let chunk = world.chunks.get_mut(&position).unwrap(); - if chunk.dirty { + if chunk.mesh_dirty { chunk.current_state = CurrentChunkState::RecalculatingMesh; } else { chunk.current_state = CurrentChunkState::CalculatingMesh; } - chunk.dirty = false; + chunk.mesh_dirty = false; // =========== //log::trace!("Started generating mesh for chunk {position}"); } diff --git a/kubi/src/world/queue.rs b/kubi/src/world/queue.rs index 31c9f79..51adede 100644 --- a/kubi/src/world/queue.rs +++ b/kubi/src/world/queue.rs @@ -1,4 +1,3 @@ -use std::collections::VecDeque; use glam::IVec3; use kubi_shared::blocks::Block; use shipyard::{UniqueViewMut, Unique}; @@ -13,33 +12,31 @@ pub struct BlockUpdateEvent { #[derive(Unique, Default, Clone)] pub struct BlockUpdateQueue { - queue: VecDeque + queue: Vec } impl BlockUpdateQueue { pub fn new() -> Self { Self::default() } pub fn push(&mut self, event: BlockUpdateEvent) { - self.queue.push_back(event) - } - pub fn pop(&mut self) -> Option { - self.queue.pop_front() - } - pub fn clear(&mut self) { - self.queue.clear(); + self.queue.push(event) } } -pub fn apply_events( +pub fn apply_queued_blocks( mut queue: UniqueViewMut, mut world: UniqueViewMut ) { - while let Some(event) = queue.pop() { + queue.queue.retain(|&event| { if let Some(block) = world.get_block_mut(event.position) { + *block = event.value; + //mark chunk as dirty + //maybe i need to check for desired/current state here? let (chunk_pos, _) = ChunkStorage::to_chunk_coords(event.position); let chunk = world.chunks.get_mut(&chunk_pos).expect("This error should never happen, if it does then something is super fucked up and the whole project needs to be burnt down."); - chunk.dirty = true; + chunk.mesh_dirty = true; + return false } - - } + true + }); }