diff --git a/common/src/msg/client.rs b/common/src/msg/client.rs index e2339aada3..5a599633d7 100644 --- a/common/src/msg/client.rs +++ b/common/src/msg/client.rs @@ -1,3 +1,4 @@ +use vek::*; use crate::comp; #[derive(Clone, Serialize, Deserialize)] @@ -14,5 +15,8 @@ pub enum ClientMsg { vel: comp::phys::Vel, dir: comp::phys::Dir, }, + TerrainChunkRequest { + key: Vec3, + }, Disconnect, } diff --git a/common/src/volumes/vol_map.rs b/common/src/volumes/vol_map.rs index 2060b63989..ab2947a416 100644 --- a/common/src/volumes/vol_map.rs +++ b/common/src/volumes/vol_map.rs @@ -126,8 +126,12 @@ impl VolMap { self.chunks.insert(key, chunk) } - pub fn remove(&mut self, key: &Vec3) -> Option> { - self.chunks.remove(key) + pub fn get_key(&self, key: Vec3) -> Option<&Chunk> { + self.chunks.get(&key) + } + + pub fn remove(&mut self, key: Vec3) -> Option> { + self.chunks.remove(&key) } pub fn key_pos(&self, key: Vec3) -> Vec3 { diff --git a/server/src/lib.rs b/server/src/lib.rs index 0d3d4f872c..9313505a71 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -14,6 +14,7 @@ use std::{ time::Duration, net::SocketAddr, sync::mpsc, + collections::HashSet, }; use specs::{ Entity as EcsEntity, @@ -63,6 +64,7 @@ pub struct Server { thread_pool: ThreadPool, chunk_tx: mpsc::Sender<(Vec3, TerrainChunk)>, chunk_rx: mpsc::Receiver<(Vec3, TerrainChunk)>, + pending_chunks: HashSet>, } impl Server { @@ -83,6 +85,7 @@ impl Server { .build(), chunk_tx, chunk_rx, + pending_chunks: HashSet::new(), }) } @@ -200,6 +203,7 @@ impl Server { let state = &mut self.state; let mut new_chat_msgs = Vec::new(); let mut disconnected_clients = Vec::new(); + let mut requested_chunks = Vec::new(); self.clients.remove_if(|entity, client| { let mut disconnect = false; @@ -240,6 +244,7 @@ impl Server { }, ClientState::Connected => match msg { ClientMsg::Connect { .. } => disconnect = true, // Not allowed when already connected + ClientMsg::Disconnect => disconnect = true, ClientMsg::Ping => client.postbox.send(ServerMsg::Pong), ClientMsg::Pong => {}, ClientMsg::Chat(msg) => new_chat_msgs.push((entity, msg)), @@ -248,7 +253,13 @@ impl Server { state.write_component(entity, vel); state.write_component(entity, dir); }, - ClientMsg::Disconnect => disconnect = true, + ClientMsg::TerrainChunkRequest { key } => match state.terrain().get_key(key) { + Some(chunk) => client.postbox.send(ServerMsg::TerrainChunkUpdate { + key, + chunk: chunk.clone(), + }), + None => requested_chunks.push(key), + }, }, } } @@ -297,6 +308,11 @@ impl Server { }); } + // Generate requested chunks + for key in requested_chunks { + self.generate_chunk(key); + } + Ok(frontend_events) } @@ -304,6 +320,13 @@ impl Server { fn sync_clients(&mut self) { self.clients.notify_connected(ServerMsg::EcsSync(self.state.ecs_mut().next_sync_package())); } + + pub fn generate_chunk(&mut self, key: Vec3) { + if self.pending_chunks.insert(key) { + let chunk_tx = self.chunk_tx.clone(); + self.thread_pool.execute(move || chunk_tx.send((key, World::generate_chunk(key))).unwrap()); + } + } } impl Drop for Server { diff --git a/world/src/lib.rs b/world/src/lib.rs index b296ff2e6b..5c9d57b42c 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -24,7 +24,7 @@ impl World { Self } - pub fn generate_chunk(&self, chunk_pos: Vec3) -> TerrainChunk { + pub fn generate_chunk(chunk_pos: Vec3) -> TerrainChunk { // TODO: This is all test code, remove/improve this later let mut chunk = TerrainChunk::filled(Block::empty(), TerrainChunkMeta::void());