From 47d6832e5cdd312fa41725d0b3426ebb339956f4 Mon Sep 17 00:00:00 2001 From: Patrick Owen Date: Fri, 27 Oct 2023 19:34:23 -0400 Subject: [PATCH] Allow clients to handle block updates for unloaded chunks --- client/src/graphics/voxels/mod.rs | 9 +++++++++ client/src/sim.rs | 10 +++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/client/src/graphics/voxels/mod.rs b/client/src/graphics/voxels/mod.rs index 5ee944e9..9f9d1d34 100644 --- a/client/src/graphics/voxels/mod.rs +++ b/client/src/graphics/voxels/mod.rs @@ -102,6 +102,15 @@ impl Voxels { while let Some(chunk) = self.worldgen.poll() { let chunk_id = ChunkId::new(chunk.node, chunk.chunk); sim.graph.populate_chunk(chunk_id, chunk.voxels, false); + + // Now that the block is populated, we can apply any pending block updates the server + // provided that the client couldn't apply. + if let Some(block_updates) = sim.pending_modified_chunks.remove(&chunk_id) { + for block_update in block_updates { + // The chunk was just populated, so a block update should always succeed. + assert!(sim.graph.update_block(&block_update)); + } + } } // Determine what to load/render diff --git a/client/src/sim.rs b/client/src/sim.rs index a5f46633..1836556a 100644 --- a/client/src/sim.rs +++ b/client/src/sim.rs @@ -12,7 +12,7 @@ use common::{ collision_math::Ray, graph::{Graph, NodeId}, graph_ray_casting, - node::{populate_fresh_nodes, VoxelData}, + node::{populate_fresh_nodes, ChunkId, VoxelData}, proto::{ self, BlockUpdate, Character, CharacterInput, CharacterState, Command, Component, Position, }, @@ -25,6 +25,7 @@ use common::{ pub struct Sim { // World state pub graph: Graph, + pub pending_modified_chunks: FxHashMap>, pub graph_entities: GraphEntities, entity_ids: FxHashMap, pub world: hecs::World, @@ -67,6 +68,7 @@ impl Sim { populate_fresh_nodes(&mut graph); Self { graph, + pending_modified_chunks: FxHashMap::default(), graph_entities: GraphEntities::new(), entity_ids: FxHashMap::default(), world: hecs::World::new(), @@ -301,8 +303,10 @@ impl Sim { populate_fresh_nodes(&mut self.graph); for block_update in msg.block_updates.into_iter() { if !self.graph.update_block(&block_update) { - // TODO: This case should be handled to properly support multiple players. - tracing::error!("Voxel data received from server for ungenerated chunk.") + self.pending_modified_chunks + .entry(block_update.chunk_id) + .or_default() + .push(block_update); } } for (chunk_id, voxel_data) in msg.modified_chunks {