From eaf806a9285145b4ffe66d9049c8433486f698a6 Mon Sep 17 00:00:00 2001 From: lukas0008 Date: Mon, 12 Aug 2024 20:23:15 +0200 Subject: [PATCH] NOW IT FULLY WORKS --- .../src/client/play/c_chunk_data.rs | 91 ++++++++++++------- pumpkin-world/src/chunk.rs | 30 +++--- pumpkin-world/src/lib.rs | 3 +- pumpkin/src/server.rs | 19 +++- 4 files changed, 89 insertions(+), 54 deletions(-) diff --git a/pumpkin-protocol/src/client/play/c_chunk_data.rs b/pumpkin-protocol/src/client/play/c_chunk_data.rs index 8aea2ed52..d225f14e5 100644 --- a/pumpkin-protocol/src/client/play/c_chunk_data.rs +++ b/pumpkin-protocol/src/client/play/c_chunk_data.rs @@ -4,7 +4,7 @@ use crate::{bytebuf::ByteBuffer, BitSet, ClientPacket, VarInt}; use fastnbt::LongArray; use itertools::Itertools; use pumpkin_macros::packet; -use pumpkin_world::chunk::ChunkData; +use pumpkin_world::{chunk::ChunkData, DIRECT_PALETTE_BITS}; #[packet(0x27)] pub struct CChunkData<'a>(pub &'a ChunkData); @@ -37,45 +37,66 @@ impl<'a> ClientPacket for CChunkData<'a> { // Block count data_buf.put_i16(block_count); //// Block states + let palette = chunk.clone().into_iter().dedup().collect_vec(); - let mut palette_map = HashMap::new(); - let block_size = 8; - // let block_size = { - // let palette_bit_len = palette.len().leading_zeros(); - // if palette_bit_len > 3 { - // palette_bit_len - // } else { - // 4 - // } - // }; - // Bits per entry - data_buf.put_u8(block_size as u8); - // Palette length - data_buf.put_var_int(&VarInt(palette.len() as i32)); - palette.iter().enumerate().for_each(|(i, id)| { - palette_map.insert(*id, i); - // Palette - data_buf.put_var_int(&VarInt(**id as i32)); - }); - let mut block_data_array = Vec::new(); - for block_clump in chunk.chunks(64 / block_size as usize) { - let mut out_long: i64 = 0; - let mut first = true; - for block in block_clump { - if first { - first = false; - } else { - out_long = out_long << block_size; - } - let index = palette_map - .get(block) - .expect("Its just got added, ofc it should be there"); - out_long = out_long | *index as i64; + // TODO: make dynamic block_size work + // TODO: make direct block_size work + enum PaletteType { + Indirect(u32), + Direct, + } + let palette_type = { + let palette_bit_len = 64 - (palette.len() as i64 - 1).leading_zeros(); + if palette_bit_len > 8 { + PaletteType::Direct + } else if palette_bit_len > 3 { + PaletteType::Indirect(palette_bit_len) + } else { + PaletteType::Indirect(4) + } + // TODO: fix indirect palette to work correctly + // PaletteType::Direct + }; + + let mut block_data_array = Vec::new(); + match palette_type { + PaletteType::Indirect(block_size) => { + // Bits per entry + data_buf.put_u8(block_size as u8); + // Palette length + data_buf.put_var_int(&VarInt(palette.len() as i32)); + let mut palette_map = HashMap::new(); + palette.iter().enumerate().for_each(|(i, id)| { + palette_map.insert(**id, i); + // Palette + data_buf.put_var_int(&VarInt(**id as i32)); + }); + for block_clump in chunk.chunks(64 / block_size as usize) { + let mut out_long: i64 = 0; + for block in block_clump.iter().rev() { + let index = palette_map + .get(*block) + .expect("Its just got added, ofc it should be there"); + out_long = out_long << block_size | (*index as i64); + } + block_data_array.push(out_long); + } + } + PaletteType::Direct => { + // Bits per entry + data_buf.put_u8(DIRECT_PALETTE_BITS as u8); + for block_clump in chunk.chunks(64 / DIRECT_PALETTE_BITS as usize) { + let mut out_long: i64 = 0; + for block in block_clump.iter().rev() { + out_long = out_long << DIRECT_PALETTE_BITS | (**block as i64); + } + block_data_array.push(out_long); + } } - block_data_array.push(out_long); } // Data array length + // TODO: precompute this and omit making the `block_data_array` data_buf.put_var_int(&VarInt(block_data_array.len() as i32)); // Data array for data_int in block_data_array { diff --git a/pumpkin-world/src/chunk.rs b/pumpkin-world/src/chunk.rs index 8d49e87ca..fcb1b3dd8 100644 --- a/pumpkin-world/src/chunk.rs +++ b/pumpkin-world/src/chunk.rs @@ -105,7 +105,7 @@ impl ChunkData { } .into_inner(); let block_size = { - let size = 64 - (palette.len() - 1).leading_zeros(); + let size = 64 - (palette.len() as i64 - 1).leading_zeros(); if size >= 4 { size } else { @@ -114,14 +114,17 @@ impl ChunkData { }; let mask = (1 << block_size) - 1; - println!("{block_size} {:#08b}", mask); - println!( - "{} {}", - block_size, - palette.iter().map(|v| v.to_string()).join(",") - ); + // println!("{block_size} {:#08b}", mask); + // println!( + // "{} {}", + // block_size, + // palette.iter().map(|v| v.to_string()).join(",") + // ); let mut blocks_left = 16 * 16 * 16; 'block_loop: for (j, block) in block_data.iter().enumerate() { + // if at == (0,0) && block_size != 4 { + // println!("{} {:#066b}", 64 - (64 / block_size) * block_size, *block); + // } for i in 0..64 / block_size { if blocks_left <= 0 { break 'block_loop; @@ -146,12 +149,13 @@ impl ChunkData { // .as_bytes(), // ); - if at == (0, 0) { - println!( - "[{}]", - &blocks[0..10000].iter().map(|v| v.to_string()).join(",") - ); - } + // if at == (0, 0) { + // println!( + // "[{}]", + // &blocks[0..10000].iter().map(|v| v.to_string()).join(",") + // ); + // } + // dbg!("{}", blocks.iter().filter(|v| **v == 2005).collect_vec().len()); Ok(ChunkData { blocks: blocks, position: at, diff --git a/pumpkin-world/src/lib.rs b/pumpkin-world/src/lib.rs index e9db38320..98b0d4701 100644 --- a/pumpkin-world/src/lib.rs +++ b/pumpkin-world/src/lib.rs @@ -2,5 +2,6 @@ pub mod chunk; pub mod dimension; pub const WORLD_HEIGHT: usize = 384; pub const WORLD_Y_START_AT: i32 = -64; // TODO: make sure where it actually starts at (i think its at -64 but not sure) +pub const DIRECT_PALETTE_BITS: u32 = 15; mod world; -mod block_registry; \ No newline at end of file +mod block_registry; diff --git a/pumpkin/src/server.rs b/pumpkin/src/server.rs index 0b4d1ef41..61467a5dc 100644 --- a/pumpkin/src/server.rs +++ b/pumpkin/src/server.rs @@ -12,14 +12,13 @@ use mio::{event::Event, Poll, Token}; use num_traits::ToPrimitive; use pumpkin_entity::{entity_type::EntityType, EntityId}; use pumpkin_protocol::{ - client::{ + bytebuf::ByteBuffer, client::{ config::CPluginMessage, play::{ CCenterChunk, CChunkData, CChunkDataUpdateLight, CGameEvent, CLogin, CPlayerAbilities, CPlayerInfoUpdate, CRemoveEntities, CSpawnEntity, PlayerAction, }, - }, - BitSet, ClientPacket, Players, Sample, StatusResponse, VarInt, Version, CURRENT_MC_PROTOCOL, + }, BitSet, ClientPacket, Players, Sample, StatusResponse, VarInt, Version, CURRENT_MC_PROTOCOL }; use pumpkin_world::dimension::Dimension; use rsa::{traits::PublicKeyParts, RsaPrivateKey, RsaPublicKey}; @@ -316,13 +315,23 @@ impl Server { chunk_z: 0.into(), }); - chunks.iter().for_each(|chunk| match &chunk.1 { + chunks.iter().for_each(|chunk| { + if chunk.0 == (0,0) { + let mut test = ByteBuffer::empty(); + CChunkData(chunk.1.as_ref().unwrap()).write(&mut test); + let len = test.buf().len(); + dbg!("Chunk packet size: {}B {}KB {}MB", len, len/1024, len/(1024*1024)); + } + match &chunk.1 { Err(err) => println!( "Chunk loading failed for chunk ({},{}): {}", chunk.0 .0, chunk.0 .1, err ), Ok(data) => client.send_packet(CChunkData(data)), - }); + }}); + + + // let test_chunk = TestChunk::new(); // client.send_packet(CChunkDataUpdateLight::new(