block queue works

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

View file

@ -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<LookingAtBlock>,
input: UniqueView<Inputs>,
prev_input: UniqueView<PrevInputs>,
mut world: UniqueViewMut<ChunkStorage>,
mut block_event_queue: UniqueViewMut<BlockUpdateQueue>,
mut entities: EntitiesViewMut,
mut events: ViewMut<EventComponent>,
mut player_events: ViewMut<PlayerActionEvent>,
@ -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),

View file

@ -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,

View file

@ -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());
}

View file

@ -46,7 +46,7 @@ pub struct Chunk {
pub mesh_index: Option<usize>,
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,
}
}
}

View file

@ -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}");
}

View file

@ -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<BlockUpdateEvent>
queue: Vec<BlockUpdateEvent>
}
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<BlockUpdateEvent> {
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<BlockUpdateQueue>,
mut world: UniqueViewMut<ChunkStorage>
) {
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
});
}