diff --git a/.vscode/settings.json b/.vscode/settings.json index 4fb2774..344b96f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,8 @@ { "editor.tabSize": 2, "rust-analyzer.diagnostics.disabled": [ - "unresolved-method" //rust-analyzer issue #14269 + //rust-analyzer issue #14269, + "unresolved-method", + "unresolved-import" ] } diff --git a/Cargo.lock b/Cargo.lock index b2c5b20..ad34951 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -66,6 +66,15 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +[[package]] +name = "atomic-polyfill" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28" +dependencies = [ + "critical-section", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -87,25 +96,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "bincode" -version = "2.0.0-rc.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bb50c5a2ef4b9b1e7ae73e3a73b52ea24b20312d629f9c4df28260b7ad2c3c4" -dependencies = [ - "bincode_derive", - "serde", -] - -[[package]] -name = "bincode_derive" -version = "2.0.0-rc.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a45a23389446d2dd25dc8e73a7a3b3c43522b630cac068927f0649d43d719d2" -dependencies = [ - "virtue", -] - [[package]] name = "bitflags" version = "1.3.2" @@ -203,6 +193,12 @@ dependencies = [ "cc", ] +[[package]] +name = "cobs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" + [[package]] name = "cocoa" version = "0.24.1" @@ -302,6 +298,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "critical-section" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6548a0ad5d2549e111e1f6a11a6c2e2d00ce6a3dafe22948d67c2b443f775e52" + [[package]] name = "crossbeam-channel" version = "0.5.7" @@ -753,6 +755,15 @@ dependencies = [ "gl_generator", ] +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -771,6 +782,20 @@ dependencies = [ "ahash 0.8.3", ] +[[package]] +name = "heapless" +version = "0.7.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743" +dependencies = [ + "atomic-polyfill", + "hash32", + "rustc_version", + "serde", + "spin", + "stable_deref_trait", +] + [[package]] name = "heck" version = "0.4.1" @@ -908,9 +933,11 @@ dependencies = [ "kubi-shared", "log", "nohash-hasher", + "postcard", "rayon", "shipyard", "strum", + "uflow", "winapi", ] @@ -945,11 +972,12 @@ name = "kubi-shared" version = "0.1.0" dependencies = [ "anyhow", - "bincode", "bracket-noise", "glam", + "postcard", "rand", "rand_xoshiro", + "serde", "shipyard", "strum", ] @@ -1374,6 +1402,17 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "postcard" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfa512cd0d087cc9f99ad30a1bf64795b67871edbead083ffc3a4dfafa59aa00" +dependencies = [ + "cobs", + "heapless", + "serde", +] + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1529,6 +1568,15 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "0.36.9" @@ -1593,6 +1641,12 @@ dependencies = [ "tiny-skia", ] +[[package]] +name = "semver" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" + [[package]] name = "serde" version = "1.0.152" @@ -1717,6 +1771,12 @@ dependencies = [ "lock_api", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "strsim" version = "0.10.0" @@ -1850,6 +1910,15 @@ dependencies = [ "winnow", ] +[[package]] +name = "uflow" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be4d71c1c106a57b0333ac2c28bd4521e0b16a2b98fe84405cdf7f544be46b6" +dependencies = [ + "rand", +] + [[package]] name = "unicode-ident" version = "1.0.8" @@ -1874,12 +1943,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "virtue" -version = "0.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b60dcd6a64dd45abf9bd426970c9843726da7fc08f44cd6fcebf68c21220a63" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/kubi-server/src/server.rs b/kubi-server/src/server.rs index c9bde00..f576b3e 100644 --- a/kubi-server/src/server.rs +++ b/kubi-server/src/server.rs @@ -1,5 +1,4 @@ use shipyard::{AllStoragesView, Unique, UniqueView, UniqueViewMut}; -use kubi_udp::server::{Server, ServerConfig, ServerEvent}; use kubi_shared::networking::messages::{ClientToServerMessage, ServerToClientMessage}; use std::time::Duration; use crate::config::ConfigTable; diff --git a/kubi-server/src/world.rs b/kubi-server/src/world.rs index c7de485..4124e7b 100644 --- a/kubi-server/src/world.rs +++ b/kubi-server/src/world.rs @@ -86,7 +86,7 @@ fn process_finished_tasks( server.0.send_message(subscriber, ServerToClientMessage::ChunkResponse { chunk: chunk_position.to_array(), data: blocks.clone(), - queued: queue.iter().map(|item| (item.position.to_array(), item.block_type)).collect() + queued: queue }).map_err(log_error).ok(); } log::debug!("Chunk {chunk_position} loaded, {} subs", chunk.subscriptions.len()); diff --git a/kubi-server/src/world/tasks.rs b/kubi-server/src/world/tasks.rs index fd2d120..8094632 100644 --- a/kubi-server/src/world/tasks.rs +++ b/kubi-server/src/world/tasks.rs @@ -5,7 +5,8 @@ use rayon::{ThreadPool, ThreadPoolBuilder}; use anyhow::Result; use kubi_shared::{ chunk::BlockData, - worldgen::{QueuedBlock, generate_world} + worldgen::generate_world, + queue::QueuedBlock, }; pub enum ChunkTask { diff --git a/kubi-shared/Cargo.toml b/kubi-shared/Cargo.toml index 7a4f1cc..be2079d 100644 --- a/kubi-shared/Cargo.toml +++ b/kubi-shared/Cargo.toml @@ -10,7 +10,8 @@ publish = false glam = { version = "0.23", features = ["debug-glam-assert", "fast-math", "serde"] } shipyard = { git = "https://github.com/leudz/shipyard", rev = "eb189f66" } strum = { version = "0.24", features = ["derive"] } -bincode = "2.0.0-rc" +postcard = { version = "1.0", features = ["alloc"] } +serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } anyhow = "1.0" bracket-noise = "0.8" rand = { version = "0.8", default_features = false, features = ["std", "min_const_gen"] } @@ -18,4 +19,4 @@ rand_xoshiro = "0.6" [features] default = [] -nightly = ["rand/nightly", "rand/simd_support"] +nightly = ["rand/nightly", "rand/simd_support", "serde/unstable"] diff --git a/kubi-shared/src/block.rs b/kubi-shared/src/block.rs index 5afc8db..b2f0bee 100644 --- a/kubi-shared/src/block.rs +++ b/kubi-shared/src/block.rs @@ -1,7 +1,7 @@ -use bincode::{Encode, Decode}; +use serde::{Serialize, Deserialize}; use strum::EnumIter; -#[derive(Clone, Copy, Debug, EnumIter)] +#[derive(Serialize, Deserialize, Clone, Copy, Debug, EnumIter)] #[repr(u8)] pub enum BlockTexture { Stone, @@ -22,7 +22,7 @@ pub enum BlockTexture { WaterSolid, } -#[derive(Encode, Decode, Clone, Copy, Debug, PartialEq, Eq, EnumIter)] +#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, EnumIter)] #[repr(u8)] pub enum Block { Air, diff --git a/kubi-shared/src/lib.rs b/kubi-shared/src/lib.rs index 2f1da39..79f16a7 100644 --- a/kubi-shared/src/lib.rs +++ b/kubi-shared/src/lib.rs @@ -4,3 +4,4 @@ pub mod worldgen; pub mod chunk; pub mod transform; pub mod entity; +pub mod queue; diff --git a/kubi-shared/src/networking/messages.rs b/kubi-shared/src/networking/messages.rs index c8b17a9..9213547 100644 --- a/kubi-shared/src/networking/messages.rs +++ b/kubi-shared/src/networking/messages.rs @@ -1,30 +1,63 @@ use std::num::NonZeroUsize; -use bincode::{Encode, Decode}; -use crate::{chunk::BlockData, block::Block}; +use serde::{Serialize, Deserialize}; +use crate::{chunk::BlockData, queue::QueuedBlock}; -type IVec3Arr = [i32; 3]; -type Vec3Arr = [f32; 3]; -type QuatArr = [f32; 3]; +pub type IVec3Arr = [i32; 3]; +pub type Vec3Arr = [f32; 3]; +pub type QuatArr = [f32; 3]; -pub const PROTOCOL_ID: u16 = 1; +pub const PROTOCOL_ID: u16 = 2; -#[derive(Encode, Decode, Clone)] +pub const C_CLIENT_HELLO: u8 = 0; +pub const C_POSITION_CHANGED: u8 = 1; +pub const C_CHUNK_SUB_REQUEST: u8 = 2; + +#[derive(Serialize, Deserialize, Clone)] +#[repr(u8)] pub enum ClientToServerMessage { ClientHello { username: String, password: Option, - }, + } = C_CLIENT_HELLO, PositionChanged { position: Vec3Arr, velocity: Vec3Arr, direction: QuatArr, - }, + } = C_POSITION_CHANGED, ChunkSubRequest { chunk: IVec3Arr, - }, + } = C_CHUNK_SUB_REQUEST, } -#[derive(Encode, Decode, Clone)] +pub const S_SERVER_HELLO: u8 = 0; +pub const S_SERVER_FUCK_OFF: u8 = 1; +pub const S_PLAYER_POSITION_CHANGED: u8 = 2; +pub const S_CHUNK_RESPONSE: u8 = 3; + +#[derive(Serialize, Deserialize, Clone)] +#[repr(u8)] +pub enum ServerToClientMessage { + ServerHello { + init: InitData + } = S_SERVER_HELLO, + ServerFuckOff { + reason: String, + } = S_SERVER_FUCK_OFF, + PlayerPositionChanged { + client_id: u8, + position: Vec3Arr, + direction: QuatArr, + } = S_PLAYER_POSITION_CHANGED, + ChunkResponse { + chunk: IVec3Arr, + data: BlockData, + queued: Vec, + } = S_CHUNK_RESPONSE, +} + +//--- + +#[derive(Serialize, Deserialize, Clone)] pub struct UserInitData { pub client_id: NonZeroUsize, //maybe use the proper type instead pub username: String, @@ -33,27 +66,7 @@ pub struct UserInitData { pub direction: QuatArr, } -#[derive(Encode, Decode, Clone)] +#[derive(Serialize, Deserialize, Clone)] pub struct InitData { pub users: Vec } - -#[derive(Encode, Decode, Clone)] -pub enum ServerToClientMessage { - ServerHello { - init: InitData - }, - ServerFuckOff { - reason: String, - }, - PlayerPositionChanged { - client_id: u8, - position: Vec3Arr, - direction: QuatArr, - }, - ChunkResponse { - chunk: IVec3Arr, - data: BlockData, - queued: Vec<(IVec3Arr, Block)>, - } -} diff --git a/kubi-shared/src/queue.rs b/kubi-shared/src/queue.rs new file mode 100644 index 0000000..7216756 --- /dev/null +++ b/kubi-shared/src/queue.rs @@ -0,0 +1,11 @@ +use glam::IVec3; +use serde::{Serialize, Deserialize}; +use crate::block::Block; + +#[derive(Serialize, Deserialize, Clone, Copy, Debug)] +pub struct QueuedBlock { + pub position: IVec3, + pub block_type: Block, + /// Only replace air blocks + pub soft: bool, +} diff --git a/kubi-shared/src/worldgen.rs b/kubi-shared/src/worldgen.rs index 09cb993..56fd807 100644 --- a/kubi-shared/src/worldgen.rs +++ b/kubi-shared/src/worldgen.rs @@ -4,7 +4,8 @@ use glam::{IVec3, ivec3, Vec3Swizzles, IVec2}; use rand_xoshiro::Xoshiro256StarStar; use crate::{ chunk::{BlockData, CHUNK_SIZE}, - block::Block + block::Block, + queue::QueuedBlock, }; fn mountain_ramp(mut x: f32) -> f32 { @@ -29,10 +30,6 @@ fn local_y_position(height: i32, chunk_position: IVec3) -> Option { (0..CHUNK_SIZE as i32).contains(&position).then_some(position as usize) } -pub struct QueuedBlock { - pub position: IVec3, - pub block_type: Block, -} pub fn generate_world(chunk_position: IVec3, seed: u64) -> (BlockData, Vec) { let offset = chunk_position * CHUNK_SIZE as i32; @@ -47,7 +44,8 @@ pub fn generate_world(chunk_position: IVec3, seed: u64) -> (BlockData, Vec); +pub struct UdpClient(pub Client); #[derive(Component)] -pub struct NetworkEvent(pub ClientEvent); +pub struct NetworkEvent(pub ClientEvent); -fn create_client( +impl NetworkEvent { + ///Checks if postcard-encoded message has a type + pub fn is_message_of_type(&self) -> bool { + let ClientEvent::Receive(data) = &self.0 else { return false }; + if data.len() == 0 { return false } + data[0] == T + } +} + +#[derive(Component)] +pub struct NetworkMessageEvent(pub ServerToClientMessage); + +fn connect_client( storages: AllStoragesView ) { log::info!("Creating client"); let address = storages.borrow::>().unwrap(); - storages.add_unique(UdpClient(Client::new( - address.0, - ClientConfig::default() - ).unwrap())); + let client = Client::connect(address.0, ClientConfig::default()).expect("Client connection failed"); + storages.add_unique(UdpClient(client)); storages.add_unique(ClientJoinState::Disconnected); } -fn connect_client( - mut client: UniqueViewMut -) { - log::info!("Connect called"); - client.0.connect().unwrap(); -} - -fn should_connect( - client: UniqueView -) -> bool { - client.0.has_not_made_connection_attempts() -} - -fn update_client( - mut client: UniqueViewMut, -) { - client.0.update().unwrap(); -} - -fn insert_client_events( +fn poll_client( mut client: UniqueViewMut, mut entities: EntitiesViewMut, mut events: ViewMut, @@ -62,7 +54,7 @@ fn insert_client_events( entities.bulk_add_entity(( &mut events, &mut network_events, - ), client.0.process_events().map(|event| { + ), client.0.step().map(|event| { (EventComponent, NetworkEvent(event)) })); } @@ -75,13 +67,19 @@ fn set_client_join_state_to_connected( } fn say_hello( - client: UniqueViewMut, + mut client: UniqueViewMut, ) { log::info!("Authenticating"); - client.0.send_message(ClientToServerMessage::ClientHello { - username: "Sbeve".into(), - password: None - }).unwrap(); + client.0.send( + postcard::to_allocvec( + &ClientToServerMessage::ClientHello { + username: "Sbeve".into(), + password: None + } + ).unwrap().into_boxed_slice(), + 0, + uflow::SendMode::Reliable + ); } fn check_server_hello_response( @@ -89,20 +87,20 @@ fn check_server_hello_response( mut join_state: UniqueViewMut ) { for event in network_events.iter() { - if let ClientEvent::MessageReceived(ServerToClientMessage::ServerHello { init }) = &event.0 { + if let ClientEvent::Receive(data) = &event.0 { + log::info!("Joined the server!"); //TODO handle init data *join_state = ClientJoinState::Joined; + return; } } } pub fn update_networking() -> Workload { ( - create_client.run_if_missing_unique::(), - connect_client.run_if(should_connect), - update_client, - insert_client_events, + connect_client.run_if_missing_unique::(), + poll_client, ( set_client_join_state_to_connected, say_hello, @@ -118,12 +116,19 @@ pub fn disconnect_on_exit( mut client: UniqueViewMut, ) { if let Some(ControlFlow::ExitWithCode(_)) = control_flow.0 { - client.0.set_nonblocking(false).expect("Failed to switch socket to blocking mode"); - if let Err(error) = client.0.disconnect() { - log::error!("failed to disconnect: {}", error); - } else { + if client.0.is_active() { + client.0.flush(); + client.0.disconnect(); + while client.0.is_active() { client.0.step(); } log::info!("Client disconnected"); + } else { + log::info!("Client inactive") } + // if let Err(error) = client.0. { + // log::error!("failed to disconnect: {}", error); + // } else { + // log::info!("Client disconnected"); + // } } } @@ -132,7 +137,7 @@ pub fn disconnect_on_exit( fn if_just_connected( network_events: View, ) -> bool { - network_events.iter().any(|event| matches!(&event.0, ClientEvent::Connected(_))) + network_events.iter().any(|event| matches!(&event.0, ClientEvent::Connect)) } fn is_join_state( diff --git a/kubi/src/world/loading.rs b/kubi/src/world/loading.rs index 76d67f3..154782d 100644 --- a/kubi/src/world/loading.rs +++ b/kubi/src/world/loading.rs @@ -2,6 +2,8 @@ use glam::{IVec3, ivec3}; use glium::{VertexBuffer, IndexBuffer, index::PrimitiveType}; use kubi_shared::networking::messages::ClientToServerMessage; use shipyard::{View, UniqueView, UniqueViewMut, IntoIter, Workload, IntoWorkload, NonSendSync, track}; +use kubi_shared::queue::QueuedBlock; +use uflow::SendMode; use crate::{ player::MainPlayer, transform::Transform, @@ -14,7 +16,7 @@ use super::{ ChunkStorage, ChunkMeshStorage, chunk::{Chunk, DesiredChunkState, CHUNK_SIZE, ChunkMesh, CurrentChunkState, ChunkData}, tasks::{ChunkTaskManager, ChunkTaskResponse, ChunkTask}, - queue::{BlockUpdateQueue, BlockUpdateEvent}, + queue::BlockUpdateQueue }; const MAX_CHUNK_OPS_INGAME: usize = 6; @@ -120,7 +122,7 @@ fn unload_downgrade_chunks( fn start_required_tasks( task_manager: UniqueView, - udp_client: Option>, + mut udp_client: Option>, mut world: UniqueViewMut, ) { if !world.is_modified() { @@ -133,10 +135,14 @@ fn start_required_tasks( match chunk.desired_state { DesiredChunkState::Loaded | DesiredChunkState::Rendered if chunk.current_state == CurrentChunkState::Nothing => { //start load task - if let Some(client) = &udp_client { - client.0.send_message(ClientToServerMessage::ChunkSubRequest { - chunk: position.to_array() - }).unwrap(); + if let Some(client) = &mut udp_client { + client.0.send( + postcard::to_allocvec(&ClientToServerMessage::ChunkSubRequest { + chunk: position.to_array() + }).unwrap().into_boxed_slice(), + 0, + SendMode::Reliable + ); } else { task_manager.spawn_task(ChunkTask::LoadChunk { seed: 0xbeef_face_dead_cafe, @@ -208,12 +214,9 @@ fn process_completed_tasks( chunk.current_state = CurrentChunkState::Loaded; //push queued blocks - for event in queued { - queue.push(BlockUpdateEvent { - position: event.position, - value: event.block_type, - soft: true, - }); + //TODO use extend + for item in queued { + queue.push(item); } //increase ops counter diff --git a/kubi/src/world/queue.rs b/kubi/src/world/queue.rs index 670e909..eb9f346 100644 --- a/kubi/src/world/queue.rs +++ b/kubi/src/world/queue.rs @@ -1,26 +1,17 @@ use glam::{IVec3, ivec3}; -use kubi_shared::{block::Block, chunk::CHUNK_SIZE}; +use kubi_shared::{block::Block, chunk::CHUNK_SIZE, queue::QueuedBlock}; use shipyard::{UniqueViewMut, Unique}; - use super::ChunkStorage; -#[derive(Clone, Copy, Debug)] -pub struct BlockUpdateEvent { - pub position: IVec3, - pub value: Block, - //Only replace air blocks - pub soft: bool, -} - #[derive(Unique, Default, Clone)] pub struct BlockUpdateQueue { - queue: Vec + queue: Vec } impl BlockUpdateQueue { pub fn new() -> Self { Self::default() } - pub fn push(&mut self, event: BlockUpdateEvent) { + pub fn push(&mut self, event: QueuedBlock) { self.queue.push(event) } } @@ -35,7 +26,7 @@ pub fn apply_queued_blocks( if event.soft && *block != Block::Air { return false } - *block = event.value; + *block = event.block_type; //mark chunk as dirty let (chunk_pos, block_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."); diff --git a/kubi/src/world/tasks.rs b/kubi/src/world/tasks.rs index 713c460..3a50ea4 100644 --- a/kubi/src/world/tasks.rs +++ b/kubi/src/world/tasks.rs @@ -1,11 +1,12 @@ use flume::{Sender, Receiver}; use glam::IVec3; use kubi_shared::{ - networking::messages::ServerToClientMessage, - worldgen::QueuedBlock + networking::messages::{S_CHUNK_RESPONSE, ServerToClientMessage}, + queue::QueuedBlock }; use shipyard::{Unique, UniqueView, View, IntoIter}; use rayon::{ThreadPool, ThreadPoolBuilder}; +use uflow::client::Event as ClientEvent; use super::{ chunk::BlockData, mesh::{generate_mesh, data::MeshGenData}, @@ -82,16 +83,24 @@ pub fn inject_network_responses_into_manager_queue( events: View ) { for event in events.iter() { - if let ClientEvent::MessageReceived(ServerToClientMessage::ChunkResponse { chunk, data, queued }) = &event.0 { - let position = IVec3::from_array(*chunk); + if event.is_message_of_type::() { + let NetworkEvent(ClientEvent::Receive(data)) = &event else { unreachable!() }; + let ServerToClientMessage::ChunkResponse { + chunk, data, queued + } = postcard::from_bytes(data).expect("Chunk decode failed") else { unreachable!() }; manager.add_sussy_response(ChunkTaskResponse::LoadedChunk { - position, - chunk_data: data.clone(), - queued: queued.iter().map(|&(position, block_type)| QueuedBlock { - position: IVec3::from_array(position), - block_type - }).collect() + position: IVec3::from_array(chunk), + chunk_data: data, + queued }); } + // if let ClientEvent::MessageReceived(ServerToClientMessage::ChunkResponse { &chunk, data, queued }) = &event.0 { + // let position = IVec3::from_array(chunk); + // manager.add_sussy_response(ChunkTaskResponse::LoadedChunk { + // position, + // chunk_data: data.clone(), + // queued + // }); + // } } }