block queue works

This commit is contained in:
griffi-gh 2023-02-05 00:58:25 +01:00
parent 00f54a2f5f
commit 319cffbb4e
6 changed files with 32 additions and 36 deletions

View file

@ -1,7 +1,7 @@
use shipyard::{UniqueViewMut, UniqueView, View, IntoIter, ViewMut, EntitiesViewMut}; use shipyard::{UniqueViewMut, UniqueView, View, IntoIter, ViewMut, EntitiesViewMut};
use crate::{ use crate::{
player::MainPlayer, player::MainPlayer,
world::{raycast::LookingAtBlock, ChunkStorage, block::Block}, world::{raycast::LookingAtBlock, ChunkStorage, block::Block, queue::{BlockUpdateQueue, BlockUpdateEvent}},
input::{Inputs, PrevInputs}, input::{Inputs, PrevInputs},
events::{EventComponent, player_actions::PlayerActionEvent}, events::{EventComponent, player_actions::PlayerActionEvent},
}; };
@ -11,7 +11,7 @@ pub fn block_placement_system(
raycast: View<LookingAtBlock>, raycast: View<LookingAtBlock>,
input: UniqueView<Inputs>, input: UniqueView<Inputs>,
prev_input: UniqueView<PrevInputs>, prev_input: UniqueView<PrevInputs>,
mut world: UniqueViewMut<ChunkStorage>, mut block_event_queue: UniqueViewMut<BlockUpdateQueue>,
mut entities: EntitiesViewMut, mut entities: EntitiesViewMut,
mut events: ViewMut<EventComponent>, mut events: ViewMut<EventComponent>,
mut player_events: ViewMut<PlayerActionEvent>, mut player_events: ViewMut<PlayerActionEvent>,
@ -21,21 +21,18 @@ pub fn block_placement_system(
if action_place ^ action_break { if action_place ^ action_break {
//get raycast info //get raycast info
let Some(ray) = (&main_player, &raycast).iter().next().unwrap().1/**/.0 else { return }; 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 (place_position, place_block) = if action_place {
let position = (ray.position - ray.direction * 0.5).floor().as_ivec3(); let position = (ray.position - ray.direction * 0.5).floor().as_ivec3();
let Some(block) = world.get_block_mut(position) else { return }; (position, Block::Dirt)
*block = Block::Dirt;
(position, *block)
} else { } else {
let Some(block) = world.get_block_mut(ray.block_position) else { return }; (ray.block_position, Block::Air)
*block = Block::Air;
(ray.block_position, *block)
}; };
//mark chunk as dirty //queue place
let (chunk_pos, _) = ChunkStorage::to_chunk_coords(place_position); block_event_queue.push(BlockUpdateEvent {
let chunk = world.chunks.get_mut(&chunk_pos).unwrap(); position: place_position,
chunk.dirty = true; value: place_block,
});
//send event //send event
entities.add_entity( entities.add_entity(
(&mut events, &mut player_events), (&mut events, &mut player_events),

View file

@ -35,7 +35,7 @@ pub(crate) mod control_flow;
use world::{ use world::{
init_game_world, init_game_world,
loading::update_loaded_world_around_player, loading::update_loaded_world_around_player,
raycast::update_raycasts raycast::update_raycasts, queue::apply_queued_blocks
}; };
use player::spawn_player; use player::spawn_player;
use prefabs::load_prefabs; use prefabs::load_prefabs;
@ -84,6 +84,7 @@ fn update() -> Workload {
update_loaded_world_around_player, update_loaded_world_around_player,
update_raycasts, update_raycasts,
block_placement_system, block_placement_system,
apply_queued_blocks,
update_cursor_lock_state, update_cursor_lock_state,
compute_cameras, compute_cameras,
exit_on_esc, exit_on_esc,

View file

@ -15,10 +15,10 @@ pub mod neighbors;
pub mod raycast; pub mod raycast;
pub mod queue; pub mod queue;
use chunk::{Chunk, ChunkMesh}; use block::Block;
use chunk::{Chunk, ChunkMesh, CHUNK_SIZE};
use tasks::ChunkTaskManager; use tasks::ChunkTaskManager;
use queue::BlockUpdateQueue;
use self::{chunk::CHUNK_SIZE, block::Block};
//TODO separate world struct for render data //TODO separate world struct for render data
// because this is not send-sync // 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_non_send_sync(ChunkMeshStorage::new());
storages.add_unique(ChunkStorage::new()); storages.add_unique(ChunkStorage::new());
storages.add_unique(ChunkTaskManager::new()); storages.add_unique(ChunkTaskManager::new());
storages.add_unique(BlockUpdateQueue::new());
} }

View file

@ -46,7 +46,7 @@ pub struct Chunk {
pub mesh_index: Option<usize>, pub mesh_index: Option<usize>,
pub current_state: CurrentChunkState, pub current_state: CurrentChunkState,
pub desired_state: DesiredChunkState, pub desired_state: DesiredChunkState,
pub dirty: bool, pub mesh_dirty: bool,
} }
impl Chunk { impl Chunk {
pub fn new(position: IVec3) -> Self { pub fn new(position: IVec3) -> Self {
@ -56,7 +56,7 @@ impl Chunk {
mesh_index: None, mesh_index: None,
current_state: Default::default(), current_state: Default::default(),
desired_state: Default::default(), desired_state: Default::default(),
dirty: false, mesh_dirty: false,
} }
} }
} }

View file

@ -138,7 +138,7 @@ fn start_required_tasks(
// =========== // ===========
//log::trace!("Started loading chunk {position}"); //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 //get needed data
let Some(neighbors) = world.neighbors_all(position) else { let Some(neighbors) = world.neighbors_all(position) else {
continue continue
@ -150,12 +150,12 @@ fn start_required_tasks(
task_manager.spawn_task(ChunkTask::GenerateMesh { data, position }); task_manager.spawn_task(ChunkTask::GenerateMesh { data, position });
//Update chunk state //Update chunk state
let chunk = world.chunks.get_mut(&position).unwrap(); let chunk = world.chunks.get_mut(&position).unwrap();
if chunk.dirty { if chunk.mesh_dirty {
chunk.current_state = CurrentChunkState::RecalculatingMesh; chunk.current_state = CurrentChunkState::RecalculatingMesh;
} else { } else {
chunk.current_state = CurrentChunkState::CalculatingMesh; chunk.current_state = CurrentChunkState::CalculatingMesh;
} }
chunk.dirty = false; chunk.mesh_dirty = false;
// =========== // ===========
//log::trace!("Started generating mesh for chunk {position}"); //log::trace!("Started generating mesh for chunk {position}");
} }

View file

@ -1,4 +1,3 @@
use std::collections::VecDeque;
use glam::IVec3; use glam::IVec3;
use kubi_shared::blocks::Block; use kubi_shared::blocks::Block;
use shipyard::{UniqueViewMut, Unique}; use shipyard::{UniqueViewMut, Unique};
@ -13,33 +12,31 @@ pub struct BlockUpdateEvent {
#[derive(Unique, Default, Clone)] #[derive(Unique, Default, Clone)]
pub struct BlockUpdateQueue { pub struct BlockUpdateQueue {
queue: VecDeque<BlockUpdateEvent> queue: Vec<BlockUpdateEvent>
} }
impl BlockUpdateQueue { impl BlockUpdateQueue {
pub fn new() -> Self { pub fn new() -> Self {
Self::default() Self::default()
} }
pub fn push(&mut self, event: BlockUpdateEvent) { pub fn push(&mut self, event: BlockUpdateEvent) {
self.queue.push_back(event) self.queue.push(event)
}
pub fn pop(&mut self) -> Option<BlockUpdateEvent> {
self.queue.pop_front()
}
pub fn clear(&mut self) {
self.queue.clear();
} }
} }
pub fn apply_events( pub fn apply_queued_blocks(
mut queue: UniqueViewMut<BlockUpdateQueue>, mut queue: UniqueViewMut<BlockUpdateQueue>,
mut world: UniqueViewMut<ChunkStorage> mut world: UniqueViewMut<ChunkStorage>
) { ) {
while let Some(event) = queue.pop() { queue.queue.retain(|&event| {
if let Some(block) = world.get_block_mut(event.position) { 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_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."); 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
} });
} }