From 0bd798045c4328208667df37348e9affb37e384f Mon Sep 17 00:00:00 2001 From: mat Date: Tue, 3 May 2022 00:33:32 -0500 Subject: more azalea-world stuff --- bot/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'bot/src') diff --git a/bot/src/main.rs b/bot/src/main.rs index 8314eb5c..6a2d5959 100644 --- a/bot/src/main.rs +++ b/bot/src/main.rs @@ -5,7 +5,7 @@ async fn main() { println!("Hello, world!"); // let address = "95.111.249.143:10000"; - let address = "172.23.192.1:58024"; + let address = "172.23.192.1:59152"; // let response = azalea_client::ping::ping_server(&address.try_into().unwrap()) // .await // .unwrap(); -- cgit v1.2.3 From 18dc3a84d4b58a58085682cc97f1b52ffee5091c Mon Sep 17 00:00:00 2001 From: mat Date: Tue, 3 May 2022 22:48:57 -0500 Subject: start adding bit storage --- .gitignore | 3 + azalea-world/src/bit_storage.rs | 149 ++++++++++++++++++++++++++++++++++++++++ azalea-world/src/lib.rs | 2 + bot/src/main.rs | 2 +- 4 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 azalea-world/src/bit_storage.rs (limited to 'bot/src') diff --git a/.gitignore b/.gitignore index ad9bfc78..364ea72c 100755 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,6 @@ flamegraph.svg perf.data perf.data.old + +# TODO: remove this after chunk-decoding is merged +/login.txt diff --git a/azalea-world/src/bit_storage.rs b/azalea-world/src/bit_storage.rs new file mode 100644 index 00000000..b2202e48 --- /dev/null +++ b/azalea-world/src/bit_storage.rs @@ -0,0 +1,149 @@ +use std::{error::Error, fmt}; + +// this is from minecraft's code +// yeah idk either +const MAGIC: [(i32, i32, i32); 64] = [ + (-1, -1, 0), + (-2147483648, 0, 0), + (1431655765, 1431655765, 0), + (-2147483648, 0, 1), + (858993459, 858993459, 0), + (715827882, 715827882, 0), + (613566756, 613566756, 0), + (-2147483648, 0, 2), + (477218588, 477218588, 0), + (429496729, 429496729, 0), + (390451572, 390451572, 0), + (357913941, 357913941, 0), + (330382099, 330382099, 0), + (306783378, 306783378, 0), + (286331153, 286331153, 0), + (-2147483648, 0, 3), + (252645135, 252645135, 0), + (238609294, 238609294, 0), + (226050910, 226050910, 0), + (214748364, 214748364, 0), + (204522252, 204522252, 0), + (195225786, 195225786, 0), + (186737708, 186737708, 0), + (178956970, 178956970, 0), + (171798691, 171798691, 0), + (165191049, 165191049, 0), + (159072862, 159072862, 0), + (153391689, 153391689, 0), + (148102320, 148102320, 0), + (143165576, 143165576, 0), + (138547332, 138547332, 0), + (-2147483648, 0, 4), + (130150524, 130150524, 0), + (126322567, 126322567, 0), + (122713351, 122713351, 0), + (119304647, 119304647, 0), + (116080197, 116080197, 0), + (113025455, 113025455, 0), + (110127366, 110127366, 0), + (107374182, 107374182, 0), + (104755299, 104755299, 0), + (102261126, 102261126, 0), + (99882960, 99882960, 0), + (97612893, 97612893, 0), + (95443717, 95443717, 0), + (93368854, 93368854, 0), + (91382282, 91382282, 0), + (89478485, 89478485, 0), + (87652393, 87652393, 0), + (85899345, 85899345, 0), + (84215045, 84215045, 0), + (82595524, 82595524, 0), + (81037118, 81037118, 0), + (79536431, 79536431, 0), + (78090314, 78090314, 0), + (76695844, 76695844, 0), + (75350303, 75350303, 0), + (74051160, 74051160, 0), + (72796055, 72796055, 0), + (71582788, 71582788, 0), + (70409299, 70409299, 0), + (69273666, 69273666, 0), + (68174084, 68174084, 0), + (-2147483648, 0, 5), +]; + +/// A compact list of integers with the given number of bits per entry. +pub struct BitStorage { + data: Vec, + bits: u32, + mask: u64, + size: u32, + values_per_long: u8, + divide_mul: i32, + divide_add: i32, + divide_shift: i32, +} + +#[derive(Debug)] +pub enum BitStorageError { + InvalidLength { got: usize, expected: usize }, +} +impl fmt::Display for BitStorageError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + BitStorageError::InvalidLength { got, expected } => write!( + f, + "Invalid length given for storage, got: {}, but expected: {}", + got, expected + ), + } + } +} +impl Error for BitStorageError {} + +impl BitStorage { + /// Create a new BitStorage with the given number of bits per entry. + /// `size` is the number of entries in the BitStorage. + pub fn new(bits: u32, size: u32, data: Option>) -> Result { + let values_per_long = 64 / bits; + let magic_index = values_per_long - 1; + let (divide_mul, divide_add, divide_shift) = MAGIC[magic_index as usize]; + let calculated_length = (size + values_per_long - 1) / values_per_long; + + let mask = (1 << bits) - 1; + + let using_data = if let Some(data) = data { + if data.len() != calculated_length as usize { + return Err(BitStorageError::InvalidLength { + got: data.len(), + expected: calculated_length as usize, + }); + } + data + } else { + vec![0; calculated_length as usize] + }; + + Ok(BitStorage { + data: using_data, + bits, + mask, + size, + values_per_long: values_per_long as u8, + divide_mul, + divide_add, + divide_shift, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_wikivg_example() { + let data = [ + 1, 2, 2, 3, 4, 4, 5, 6, 6, 4, 8, 0, 7, 4, 3, 13, 15, 16, 9, 14, 10, 12, 0, 2, + ]; + let expected_compact: [u64; 2] = [0x0020863148418841, 0x01018A7260F68C87]; + let storage = BitStorage::new(5, 10, None).unwrap(); + } +} diff --git a/azalea-world/src/lib.rs b/azalea-world/src/lib.rs index ea7798f8..54961401 100644 --- a/azalea-world/src/lib.rs +++ b/azalea-world/src/lib.rs @@ -1,7 +1,9 @@ +mod bit_storage; mod palette; use azalea_core::ChunkPos; use azalea_protocol::mc_buf::{McBufReadable, McBufWritable}; +pub use bit_storage::BitStorage; use palette::PalettedContainer; use std::{ io::{Read, Write}, diff --git a/bot/src/main.rs b/bot/src/main.rs index 6a2d5959..504c8d41 100644 --- a/bot/src/main.rs +++ b/bot/src/main.rs @@ -5,7 +5,7 @@ async fn main() { println!("Hello, world!"); // let address = "95.111.249.143:10000"; - let address = "172.23.192.1:59152"; + let address = "172.23.192.1:65163"; // let response = azalea_client::ping::ping_server(&address.try_into().unwrap()) // .await // .unwrap(); -- cgit v1.2.3 From 57b76ef52b7a9b516710aea5ba5d6f0141c8d6cf Mon Sep 17 00:00:00 2001 From: mat Date: Thu, 5 May 2022 19:57:46 -0500 Subject: Add bit storage --- azalea-world/src/bit_storage.rs | 53 +++++++++++++++++++++++++++++++++++++---- bot/src/main.rs | 2 +- 2 files changed, 49 insertions(+), 6 deletions(-) (limited to 'bot/src') diff --git a/azalea-world/src/bit_storage.rs b/azalea-world/src/bit_storage.rs index b2202e48..5ced67fe 100644 --- a/azalea-world/src/bit_storage.rs +++ b/azalea-world/src/bit_storage.rs @@ -1,4 +1,4 @@ -use std::{error::Error, fmt}; +use std::{error::Error, fmt, ops::Index}; // this is from minecraft's code // yeah idk either @@ -72,9 +72,9 @@ const MAGIC: [(i32, i32, i32); 64] = [ /// A compact list of integers with the given number of bits per entry. pub struct BitStorage { data: Vec, - bits: u32, + bits: usize, mask: u64, - size: u32, + size: usize, values_per_long: u8, divide_mul: i32, divide_add: i32, @@ -101,7 +101,7 @@ impl Error for BitStorageError {} impl BitStorage { /// Create a new BitStorage with the given number of bits per entry. /// `size` is the number of entries in the BitStorage. - pub fn new(bits: u32, size: u32, data: Option>) -> Result { + pub fn new(bits: usize, size: usize, data: Option>) -> Result { let values_per_long = 64 / bits; let magic_index = values_per_long - 1; let (divide_mul, divide_add, divide_shift) = MAGIC[magic_index as usize]; @@ -132,6 +132,45 @@ impl BitStorage { divide_shift, }) } + + pub fn cell_index(&self, index: u64) -> usize { + let first = self.divide_mul as u64; + let second = self.divide_mul as u64; + + (index * first + second >> 32 >> self.divide_shift) + .try_into() + .unwrap() + } + + pub fn get(&self, index: usize) -> u64 { + // Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)var1); + // int var2 = this.cellIndex(var1); + // long var3 = this.data[var2]; + // int var5 = (var1 - var2 * this.valuesPerLong) * this.bits; + // return (int)(var3 >> var5 & this.mask); + + assert!(index <= self.size - 1); + let cell_index = self.cell_index(index as u64); + let cell = &self.data[cell_index as usize]; + let bit_index = (index - cell_index * self.values_per_long as usize) * self.bits; + cell >> bit_index & self.mask + } + + pub fn set(&mut self, index: usize, value: u64) { + // Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)var1); + // Validate.inclusiveBetween(0L, this.mask, (long)var2); + // int var3 = this.cellIndex(var1); + // long var4 = this.data[var3]; + // int var6 = (var1 - var3 * this.valuesPerLong) * this.bits; + // this.data[var3] = var4 & ~(this.mask << var6) | ((long)var2 & this.mask) << var6; + + assert!(index <= self.size - 1); + assert!(value <= self.mask); + let cell_index = self.cell_index(index as u64); + let cell = &mut self.data[cell_index as usize]; + let bit_index = (index - cell_index * self.values_per_long as usize) * self.bits; + *cell = *cell & !(self.mask << bit_index) | (value & self.mask) << bit_index; + } } #[cfg(test)] @@ -144,6 +183,10 @@ mod tests { 1, 2, 2, 3, 4, 4, 5, 6, 6, 4, 8, 0, 7, 4, 3, 13, 15, 16, 9, 14, 10, 12, 0, 2, ]; let expected_compact: [u64; 2] = [0x0020863148418841, 0x01018A7260F68C87]; - let storage = BitStorage::new(5, 10, None).unwrap(); + let storage = BitStorage::new(5, data.len(), Some(expected_compact.to_vec())).unwrap(); + + for (i, expected) in data.iter().enumerate() { + assert_eq!(storage.get(i), *expected); + } } } diff --git a/bot/src/main.rs b/bot/src/main.rs index 504c8d41..167f4edc 100644 --- a/bot/src/main.rs +++ b/bot/src/main.rs @@ -5,7 +5,7 @@ async fn main() { println!("Hello, world!"); // let address = "95.111.249.143:10000"; - let address = "172.23.192.1:65163"; + let address = "172.23.192.1:65111"; // let response = azalea_client::ping::ping_server(&address.try_into().unwrap()) // .await // .unwrap(); -- cgit v1.2.3 From 4dac004635e50682d9ebe8812fdf654a0c1808f1 Mon Sep 17 00:00:00 2001 From: mat Date: Thu, 5 May 2022 22:12:54 -0500 Subject: Fix chunk decoding --- azalea-protocol/src/mc_buf/mod.rs | 2 ++ azalea-protocol/src/mc_buf/read.rs | 11 ++++++++ azalea-protocol/src/mc_buf/write.rs | 7 +++++ azalea-world/src/bit_storage.rs | 9 ++++--- azalea-world/src/lib.rs | 19 ++++++++++--- azalea-world/src/palette.rs | 54 ++++++++++++++++++++++++++++++------- bot/src/main.rs | 2 +- 7 files changed, 85 insertions(+), 19 deletions(-) (limited to 'bot/src') diff --git a/azalea-protocol/src/mc_buf/mod.rs b/azalea-protocol/src/mc_buf/mod.rs index a82334fb..debf2991 100755 --- a/azalea-protocol/src/mc_buf/mod.rs +++ b/azalea-protocol/src/mc_buf/mod.rs @@ -12,6 +12,8 @@ pub use write::{McBufVarintWritable, McBufWritable, Writable}; const MAX_STRING_LENGTH: u16 = 32767; // const MAX_COMPONENT_STRING_LENGTH: u32 = 262144; +// TODO: maybe get rid of the readable/writable traits so there's not two ways to do the same thing and improve McBufReadable/McBufWritable + // TODO: have a definitions.rs in mc_buf that contains UnsizedByteArray and BitSet /// A Vec that isn't prefixed by a VarInt with the size. diff --git a/azalea-protocol/src/mc_buf/read.rs b/azalea-protocol/src/mc_buf/read.rs index e1ae321c..a8c44bdf 100755 --- a/azalea-protocol/src/mc_buf/read.rs +++ b/azalea-protocol/src/mc_buf/read.rs @@ -255,6 +255,17 @@ impl McBufVarintReadable for i32 { } } +impl McBufVarintReadable for Vec { + fn varint_read_into(buf: &mut impl Read) -> Result { + let length = u32::varint_read_into(buf)?; + let mut vec = Vec::with_capacity(length as usize); + for _ in 0..length { + vec.push(T::varint_read_into(buf)?); + } + Ok(vec) + } +} + impl McBufReadable for UnsizedByteArray { fn read_into(buf: &mut impl Read) -> Result { Ok(UnsizedByteArray(buf.read_bytes()?)) diff --git a/azalea-protocol/src/mc_buf/write.rs b/azalea-protocol/src/mc_buf/write.rs index 3a4a02f8..cc5f2284 100755 --- a/azalea-protocol/src/mc_buf/write.rs +++ b/azalea-protocol/src/mc_buf/write.rs @@ -210,6 +210,13 @@ impl McBufVarintWritable for u32 { } } +// Vec varint +impl McBufVarintWritable for Vec { + fn varint_write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { + buf.write_list(self, |buf, i| i.varint_write_into(buf)) + } +} + // u16 impl McBufWritable for u16 { fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { diff --git a/azalea-world/src/bit_storage.rs b/azalea-world/src/bit_storage.rs index 5ced67fe..9cc3a053 100644 --- a/azalea-world/src/bit_storage.rs +++ b/azalea-world/src/bit_storage.rs @@ -1,4 +1,4 @@ -use std::{error::Error, fmt, ops::Index}; +use std::{error::Error, fmt}; // this is from minecraft's code // yeah idk either @@ -70,6 +70,7 @@ const MAGIC: [(i32, i32, i32); 64] = [ ]; /// A compact list of integers with the given number of bits per entry. +#[derive(Clone)] pub struct BitStorage { data: Vec, bits: usize, @@ -135,7 +136,7 @@ impl BitStorage { pub fn cell_index(&self, index: u64) -> usize { let first = self.divide_mul as u64; - let second = self.divide_mul as u64; + let second = self.divide_add as u64; (index * first + second >> 32 >> self.divide_shift) .try_into() @@ -182,8 +183,8 @@ mod tests { let data = [ 1, 2, 2, 3, 4, 4, 5, 6, 6, 4, 8, 0, 7, 4, 3, 13, 15, 16, 9, 14, 10, 12, 0, 2, ]; - let expected_compact: [u64; 2] = [0x0020863148418841, 0x01018A7260F68C87]; - let storage = BitStorage::new(5, data.len(), Some(expected_compact.to_vec())).unwrap(); + let compact_data: [u64; 2] = [0x0020863148418841, 0x01018A7260F68C87]; + let storage = BitStorage::new(5, data.len(), Some(compact_data.to_vec())).unwrap(); for (i, expected) in data.iter().enumerate() { assert_eq!(storage.get(i), *expected); diff --git a/azalea-world/src/lib.rs b/azalea-world/src/lib.rs index 54961401..abeac181 100644 --- a/azalea-world/src/lib.rs +++ b/azalea-world/src/lib.rs @@ -11,6 +11,8 @@ use std::{ sync::{Arc, Mutex}, }; +use crate::palette::PalettedContainerType; + #[cfg(test)] mod tests { #[test] @@ -43,7 +45,7 @@ impl World { // let existing_chunk = &self.storage[pos]; let chunk = Arc::new(Mutex::new(Chunk::read_with_world(data, self)?)); - println!("Loaded chunk {:?}", chunk); + println!("Loaded chunk {:?}", pos); self.storage[pos] = Some(chunk); Ok(()) @@ -121,7 +123,9 @@ impl Chunk { pub fn read_with_world_height(buf: &mut impl Read, world_height: u32) -> Result { let section_count = world_height / SECTION_HEIGHT; let mut sections = Vec::with_capacity(section_count as usize); - for _ in 0..section_count { + println!("\n\nreading {} sections", section_count); + for i in 0..section_count { + println!("reading section #{}", i); let section = Section::read_into(buf)?; sections.push(section); } @@ -148,8 +152,15 @@ pub struct Section { impl McBufReadable for Section { fn read_into(buf: &mut impl Read) -> Result { let block_count = u16::read_into(buf)?; - let states = PalettedContainer::read_into(buf)?; - let biomes = PalettedContainer::read_into(buf)?; + println!("block count: {}\n", block_count); + // assert!( + // block_count <= 16 * 16 * 16, + // "A section has more blocks than what should be possible. This is a bug!" + // ); + let states = PalettedContainer::read_with_type(buf, &PalettedContainerType::BlockStates)?; + println!("! read states, reading biomes next"); + let biomes = PalettedContainer::read_with_type(buf, &PalettedContainerType::Biomes)?; + println!(); Ok(Section { block_count, states, diff --git a/azalea-world/src/palette.rs b/azalea-world/src/palette.rs index 69900fe6..47354c94 100644 --- a/azalea-world/src/palette.rs +++ b/azalea-world/src/palette.rs @@ -1,20 +1,43 @@ +use azalea_protocol::mc_buf::{ + McBufReadable, McBufVarintReadable, McBufWritable, Readable, Writable, +}; use std::io::{Read, Write}; -use azalea_protocol::mc_buf::{McBufReadable, McBufWritable, Readable, Writable}; +#[derive(Clone, Debug, Copy)] +pub enum PalettedContainerType { + Biomes, + BlockStates, +} #[derive(Clone, Debug)] pub struct PalettedContainer { pub bits_per_entry: u8, pub palette: Palette, /// Compacted list of indices pointing to entry IDs in the Palette. - pub data: Vec, + pub data: Vec, } -impl McBufReadable for PalettedContainer { - fn read_into(buf: &mut impl Read) -> Result { +impl PalettedContainer { + pub fn read_with_type( + buf: &mut impl Read, + type_: &'static PalettedContainerType, + ) -> Result { let bits_per_entry = buf.read_byte()?; - let palette = Palette::read_with_bits_per_entry(buf, bits_per_entry)?; - let data = Vec::::read_into(buf)?; + let palette = match type_ { + PalettedContainerType::BlockStates => { + Palette::block_states_read_with_bits_per_entry(buf, bits_per_entry)? + } + PalettedContainerType::Biomes => { + Palette::biomes_read_with_bits_per_entry(buf, bits_per_entry)? + } + }; + + let data = Vec::::read_into(buf)?; + debug_assert!( + bits_per_entry != 0 || data.is_empty(), + "Bits per entry is 0 but data is not empty." + ); + Ok(PalettedContainer { bits_per_entry, palette, @@ -41,14 +64,25 @@ pub enum Palette { } impl Palette { - pub fn read_with_bits_per_entry( + pub fn block_states_read_with_bits_per_entry( + buf: &mut impl Read, + bits_per_entry: u8, + ) -> Result { + Ok(match bits_per_entry { + 0 => Palette::SingleValue(u32::varint_read_into(buf)?), + 1..=4 => Palette::Linear(Vec::::varint_read_into(buf)?), + 5..=8 => Palette::Hashmap(Vec::::varint_read_into(buf)?), + _ => Palette::Global, + }) + } + + pub fn biomes_read_with_bits_per_entry( buf: &mut impl Read, bits_per_entry: u8, ) -> Result { Ok(match bits_per_entry { - 0 => Palette::SingleValue(u32::read_into(buf)?), - 1..=4 => Palette::Linear(Vec::::read_into(buf)?), - 5..=8 => Palette::Hashmap(Vec::::read_into(buf)?), + 0 => Palette::SingleValue(u32::varint_read_into(buf)?), + 1..=3 => Palette::Linear(Vec::::varint_read_into(buf)?), _ => Palette::Global, }) } diff --git a/bot/src/main.rs b/bot/src/main.rs index 167f4edc..7cf056bf 100644 --- a/bot/src/main.rs +++ b/bot/src/main.rs @@ -5,7 +5,7 @@ async fn main() { println!("Hello, world!"); // let address = "95.111.249.143:10000"; - let address = "172.23.192.1:65111"; + let address = "172.23.192.1:62522"; // let response = azalea_client::ping::ping_server(&address.try_into().unwrap()) // .await // .unwrap(); -- cgit v1.2.3 From e0239865659b2f2750edda7556548f6a2b8d4127 Mon Sep 17 00:00:00 2001 From: mat Date: Thu, 5 May 2022 23:33:08 -0500 Subject: random polish --- Cargo.lock | 1 + azalea-core/src/lib.rs | 2 +- azalea-core/src/position.rs | 13 +++++++++++++ azalea-world/src/lib.rs | 14 +++++++++++++- bot/Cargo.toml | 1 + bot/src/main.rs | 13 ++++++++++++- 6 files changed, 41 insertions(+), 3 deletions(-) (limited to 'bot/src') diff --git a/Cargo.lock b/Cargo.lock index 73a8dafd..e5b6a112 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -191,6 +191,7 @@ name = "bot" version = "0.1.0" dependencies = [ "azalea-client", + "azalea-core", "azalea-protocol", "tokio", ] diff --git a/azalea-core/src/lib.rs b/azalea-core/src/lib.rs index 6f0c25cc..0053dc9b 100755 --- a/azalea-core/src/lib.rs +++ b/azalea-core/src/lib.rs @@ -9,7 +9,7 @@ mod slot; pub use slot::{Slot, SlotData}; mod position; -pub use position::{BlockPos, ChunkPos}; +pub use position::{BlockPos, ChunkPos, ChunkSectionPos}; mod direction; pub use direction::Direction; diff --git a/azalea-core/src/position.rs b/azalea-core/src/position.rs index aa82c1f9..a57f5c0b 100644 --- a/azalea-core/src/position.rs +++ b/azalea-core/src/position.rs @@ -22,3 +22,16 @@ impl ChunkPos { ChunkPos { x, z } } } + +#[derive(Clone, Copy, Debug, Default)] +pub struct ChunkSectionPos { + pub x: i32, + pub y: i32, + pub z: i32, +} + +impl ChunkSectionPos { + pub fn new(x: i32, y: i32, z: i32) -> Self { + ChunkSectionPos { x, y, z } + } +} diff --git a/azalea-world/src/lib.rs b/azalea-world/src/lib.rs index 36bbceac..4b8c21e9 100644 --- a/azalea-world/src/lib.rs +++ b/azalea-world/src/lib.rs @@ -55,6 +55,18 @@ impl World { self.storage.view_center = *pos; } } +impl Index<&ChunkPos> for World { + type Output = Option>>; + + fn index(&self, pos: &ChunkPos) -> &Self::Output { + &self.storage[pos] + } +} +impl IndexMut<&ChunkPos> for World { + fn index_mut<'a>(&'a mut self, pos: &ChunkPos) -> &'a mut Self::Output { + &mut self.storage[pos] + } +} pub struct ChunkStorage { view_center: ChunkPos, @@ -150,7 +162,7 @@ pub struct Section { impl McBufReadable for Section { fn read_into(buf: &mut impl Read) -> Result { let block_count = u16::read_into(buf)?; - // this is commented out because apparently the vanilla server just gives us an incorrect block count sometimes + // this is commented out because the vanilla server is wrong // assert!( // block_count <= 16 * 16 * 16, // "A section has more blocks than what should be possible. This is a bug!" diff --git a/bot/Cargo.toml b/bot/Cargo.toml index fd6ad067..e55f6c3d 100755 --- a/bot/Cargo.toml +++ b/bot/Cargo.toml @@ -7,5 +7,6 @@ version = "0.1.0" [dependencies] azalea-client = {path = "../azalea-client"} +azalea-core = {path = "../azalea-core"} azalea-protocol = {path = "../azalea-protocol"} tokio = "^1.14.0" diff --git a/bot/src/main.rs b/bot/src/main.rs index 7cf056bf..657d1adb 100644 --- a/bot/src/main.rs +++ b/bot/src/main.rs @@ -1,4 +1,5 @@ use azalea_client::{Account, Event}; +use azalea_core::ChunkPos; #[tokio::main] async fn main() { @@ -17,7 +18,17 @@ async fn main() { while let Some(e) = client.next().await { match e { - Event::Login => {} + // TODO: have a "loaded" or "ready" event that fires when all chunks are loaded + Event::Login => { + // let state = client.state.lock().await; + // let world = state.world.as_ref().unwrap(); + // let c = world[&ChunkPos::new(-1, -4)] + // .as_ref() + // .unwrap() + // .lock() + // .unwrap(); + // println!("{:?}", c); + } } } -- cgit v1.2.3 From 345cecf7afa84df2d5ecf075ecfb499e3fd10a55 Mon Sep 17 00:00:00 2001 From: mat Date: Sun, 8 May 2022 23:45:15 -0500 Subject: add more stuff --- .gitignore | 2 -- azalea-client/src/connect.rs | 1 - azalea-core/src/position.rs | 25 +++++++++++++++++++++++++ azalea-world/src/bit_storage.rs | 12 ++++++++++-- azalea-world/src/lib.rs | 9 +++++++++ azalea-world/src/palette.rs | 14 +++++++++++--- bot/src/main.rs | 23 ++++++++++++----------- 7 files changed, 67 insertions(+), 19 deletions(-) (limited to 'bot/src') diff --git a/.gitignore b/.gitignore index dc2a59d1..53141060 100644 --- a/.gitignore +++ b/.gitignore @@ -4,8 +4,6 @@ flamegraph.svg perf.data perf.data.old -# TODO: remove this after chunk-decoding is merged -/login.txt code-generator/Burger code-generator/client.jar diff --git a/azalea-client/src/connect.rs b/azalea-client/src/connect.rs index 2f38b305..522d7d48 100755 --- a/azalea-client/src/connect.rs +++ b/azalea-client/src/connect.rs @@ -177,7 +177,6 @@ impl Client { match packet { GamePacket::ClientboundLoginPacket(p) => { println!("Got login packet {:?}", p); - std::fs::write("login.txt", format!("{:#?}", p)).expect("Unable to write file"); let mut state = state.lock().await; state.player.entity.id = p.player_id; diff --git a/azalea-core/src/position.rs b/azalea-core/src/position.rs index a57f5c0b..a2292651 100644 --- a/azalea-core/src/position.rs +++ b/azalea-core/src/position.rs @@ -23,6 +23,15 @@ impl ChunkPos { } } +impl From for ChunkPos { + fn from(pos: BlockPos) -> Self { + ChunkPos { + x: pos.x / 16, + z: pos.z / 16, + } + } +} + #[derive(Clone, Copy, Debug, Default)] pub struct ChunkSectionPos { pub x: i32, @@ -35,3 +44,19 @@ impl ChunkSectionPos { ChunkSectionPos { x, y, z } } } + +impl From for ChunkSectionPos { + fn from(pos: BlockPos) -> Self { + ChunkSectionPos { + x: pos.x / 16, + y: pos.y / 16, + z: pos.z / 16, + } + } +} + +impl From for ChunkPos { + fn from(pos: ChunkSectionPos) -> Self { + ChunkPos { x: pos.x, z: pos.z } + } +} diff --git a/azalea-world/src/bit_storage.rs b/azalea-world/src/bit_storage.rs index 9cc3a053..211a4a04 100644 --- a/azalea-world/src/bit_storage.rs +++ b/azalea-world/src/bit_storage.rs @@ -70,9 +70,9 @@ const MAGIC: [(i32, i32, i32); 64] = [ ]; /// A compact list of integers with the given number of bits per entry. -#[derive(Clone)] +#[derive(Clone, Debug, Default)] pub struct BitStorage { - data: Vec, + pub data: Vec, bits: usize, mask: u64, size: usize, @@ -103,9 +103,17 @@ impl BitStorage { /// Create a new BitStorage with the given number of bits per entry. /// `size` is the number of entries in the BitStorage. pub fn new(bits: usize, size: usize, data: Option>) -> Result { + if let Some(data) = &data { + if data.len() == 0 { + // TODO: make 0 bit storage actually work + return Ok(BitStorage::default()); + } + } + let values_per_long = 64 / bits; let magic_index = values_per_long - 1; let (divide_mul, divide_add, divide_shift) = MAGIC[magic_index as usize]; + println!("values_per_long: {}, size: {}", values_per_long, size); let calculated_length = (size + values_per_long - 1) / values_per_long; let mask = (1 << bits) - 1; diff --git a/azalea-world/src/lib.rs b/azalea-world/src/lib.rs index 4b8c21e9..4da2fb0f 100644 --- a/azalea-world/src/lib.rs +++ b/azalea-world/src/lib.rs @@ -67,6 +67,15 @@ impl IndexMut<&ChunkPos> for World { &mut self.storage[pos] } } +// impl Index<&BlockPos> for World { +// type Output = Option>>; + +// fn index(&self, pos: &BlockPos) -> &Self::Output { +// let chunk = &self[ChunkPos::from(pos)]; +// // chunk. + +// } +// } pub struct ChunkStorage { view_center: ChunkPos, diff --git a/azalea-world/src/palette.rs b/azalea-world/src/palette.rs index db722a5b..c33992b1 100644 --- a/azalea-world/src/palette.rs +++ b/azalea-world/src/palette.rs @@ -1,6 +1,8 @@ use azalea_protocol::mc_buf::{McBufReadable, McBufVarReadable, McBufWritable, Readable, Writable}; use std::io::{Read, Write}; +use crate::BitStorage; + #[derive(Clone, Debug, Copy)] pub enum PalettedContainerType { Biomes, @@ -12,7 +14,7 @@ pub struct PalettedContainer { pub bits_per_entry: u8, pub palette: Palette, /// Compacted list of indices pointing to entry IDs in the Palette. - pub data: Vec, + pub storage: BitStorage, } impl PalettedContainer { @@ -29,17 +31,23 @@ impl PalettedContainer { Palette::biomes_read_with_bits_per_entry(buf, bits_per_entry)? } }; + let size = match type_ { + PalettedContainerType::BlockStates => 4096, + PalettedContainerType::Biomes => 64, + }; let data = Vec::::read_into(buf)?; debug_assert!( bits_per_entry != 0 || data.is_empty(), "Bits per entry is 0 but data is not empty." ); + println!("data: {:?}", data); + let storage = BitStorage::new(bits_per_entry.into(), size, Some(data)).unwrap(); Ok(PalettedContainer { bits_per_entry, palette, - data, + storage, }) } } @@ -47,7 +55,7 @@ impl McBufWritable for PalettedContainer { fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { buf.write_byte(self.bits_per_entry)?; self.palette.write_into(buf)?; - self.data.write_into(buf)?; + self.storage.data.write_into(buf)?; Ok(()) } } diff --git a/bot/src/main.rs b/bot/src/main.rs index 075bfa44..2686636b 100644 --- a/bot/src/main.rs +++ b/bot/src/main.rs @@ -1,5 +1,5 @@ use azalea_client::{Account, Event}; -use azalea_core::ChunkPos; +use azalea_core::{BlockPos, ChunkPos}; #[tokio::main] async fn main() { @@ -19,18 +19,19 @@ async fn main() { while let Some(e) = client.next().await { match e { // TODO: have a "loaded" or "ready" event that fires when all chunks are loaded - Event::Login => { - // let state = client.state.lock().await; - // let world = state.world.as_ref().unwrap(); - // let c = world[&ChunkPos::new(-1, -4)] - // .as_ref() - // .unwrap() - // .lock() - // .unwrap(); - // println!("{:?}", c); - } + Event::Login => {} Event::Chat(p) => { println!("{}", p.message.to_ansi(None)); + if p.message.to_ansi(None) == " ok" { + let state = client.state.lock().await; + let world = state.world.as_ref().unwrap(); + // let c = world[&BlockPos::new(5, 78, -2)] + // .as_ref() + // .unwrap() + // .lock() + // .unwrap(); + // println!("{:?}", c); + } } } } -- cgit v1.2.3 From 7c194fb245fac1c52fbb9e4ca042dd5c42d522b6 Mon Sep 17 00:00:00 2001 From: mat Date: Sat, 14 May 2022 11:20:33 -0500 Subject: remove some printlns --- azalea-language/src/lib.rs | 1 - azalea-world/src/bit_storage.rs | 1 - azalea-world/src/palette.rs | 1 - bot/src/main.rs | 2 +- 4 files changed, 1 insertion(+), 4 deletions(-) (limited to 'bot/src') diff --git a/azalea-language/src/lib.rs b/azalea-language/src/lib.rs index b48a0a6b..f54de3cb 100644 --- a/azalea-language/src/lib.rs +++ b/azalea-language/src/lib.rs @@ -32,7 +32,6 @@ use std::{collections::HashMap, fs::File}; lazy_static! { pub static ref STORAGE: HashMap = serde_json::from_str(&{ let src_dir = Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/src/en_us.json")); - println!("dir: {:?}", src_dir); let mut file = File::open(src_dir).unwrap(); let mut contents = String::new(); file.read_to_string(&mut contents).unwrap(); diff --git a/azalea-world/src/bit_storage.rs b/azalea-world/src/bit_storage.rs index 211a4a04..3f810f40 100644 --- a/azalea-world/src/bit_storage.rs +++ b/azalea-world/src/bit_storage.rs @@ -113,7 +113,6 @@ impl BitStorage { let values_per_long = 64 / bits; let magic_index = values_per_long - 1; let (divide_mul, divide_add, divide_shift) = MAGIC[magic_index as usize]; - println!("values_per_long: {}, size: {}", values_per_long, size); let calculated_length = (size + values_per_long - 1) / values_per_long; let mask = (1 << bits) - 1; diff --git a/azalea-world/src/palette.rs b/azalea-world/src/palette.rs index c33992b1..55a33bde 100644 --- a/azalea-world/src/palette.rs +++ b/azalea-world/src/palette.rs @@ -41,7 +41,6 @@ impl PalettedContainer { bits_per_entry != 0 || data.is_empty(), "Bits per entry is 0 but data is not empty." ); - println!("data: {:?}", data); let storage = BitStorage::new(bits_per_entry.into(), size, Some(data)).unwrap(); Ok(PalettedContainer { diff --git a/bot/src/main.rs b/bot/src/main.rs index 2686636b..2f9fb9e6 100644 --- a/bot/src/main.rs +++ b/bot/src/main.rs @@ -6,7 +6,7 @@ async fn main() { println!("Hello, world!"); // let address = "95.111.249.143:10000"; - let address = "172.23.192.1:61385"; + let address = "192.168.2.234:62840"; // let response = azalea_client::ping::ping_server(&address.try_into().unwrap()) // .await // .unwrap(); -- cgit v1.2.3 From 6d2fd8afbad44bbe88f701e1d67cc2f251246c07 Mon Sep 17 00:00:00 2001 From: mat Date: Sat, 14 May 2022 14:12:57 -0500 Subject: start adding get_block_state --- azalea-core/src/lib.rs | 2 +- azalea-core/src/position.rs | 43 +++++++++++++++++++++++++++++++++++++++-- azalea-world/src/bit_storage.rs | 16 ++++++++++++--- azalea-world/src/lib.rs | 43 ++++++++++++++++++++++++++++++++++++++--- azalea-world/src/palette.rs | 30 ++++++++++++++++++++++++++++ bot/src/main.rs | 8 ++------ 6 files changed, 127 insertions(+), 15 deletions(-) (limited to 'bot/src') diff --git a/azalea-core/src/lib.rs b/azalea-core/src/lib.rs index 0053dc9b..2b12db53 100755 --- a/azalea-core/src/lib.rs +++ b/azalea-core/src/lib.rs @@ -9,7 +9,7 @@ mod slot; pub use slot::{Slot, SlotData}; mod position; -pub use position::{BlockPos, ChunkPos, ChunkSectionPos}; +pub use position::{BlockPos, ChunkPos, ChunkSectionBlockPos, ChunkSectionPos}; mod direction; pub use direction::Direction; diff --git a/azalea-core/src/position.rs b/azalea-core/src/position.rs index a2292651..1dd200ab 100644 --- a/azalea-core/src/position.rs +++ b/azalea-core/src/position.rs @@ -1,3 +1,5 @@ +use std::ops::Rem; + #[derive(Clone, Copy, Debug, Default)] pub struct BlockPos { pub x: i32, @@ -11,6 +13,18 @@ impl BlockPos { } } +impl Rem for BlockPos { + type Output = Self; + + fn rem(self, rhs: i32) -> Self { + BlockPos { + x: self.x % rhs, + y: self.y % rhs, + z: self.z % rhs, + } + } +} + #[derive(Clone, Copy, Debug, Default)] pub struct ChunkPos { pub x: i32, @@ -23,8 +37,8 @@ impl ChunkPos { } } -impl From for ChunkPos { - fn from(pos: BlockPos) -> Self { +impl From<&BlockPos> for ChunkPos { + fn from(pos: &BlockPos) -> Self { ChunkPos { x: pos.x / 16, z: pos.z / 16, @@ -32,6 +46,7 @@ impl From for ChunkPos { } } +/// The coordinates of a chunk section in the world. #[derive(Clone, Copy, Debug, Default)] pub struct ChunkSectionPos { pub x: i32, @@ -60,3 +75,27 @@ impl From for ChunkPos { ChunkPos { x: pos.x, z: pos.z } } } + +/// The coordinates of a block inside a chunk section. +#[derive(Clone, Copy, Debug, Default)] +pub struct ChunkSectionBlockPos { + pub x: u8, + pub y: u8, + pub z: u8, +} + +impl ChunkSectionBlockPos { + pub fn new(x: u8, y: u8, z: u8) -> Self { + ChunkSectionBlockPos { x, y, z } + } +} + +impl From<&BlockPos> for ChunkSectionBlockPos { + fn from(pos: &BlockPos) -> Self { + ChunkSectionBlockPos { + x: pos.x.rem(16).abs() as u8, + y: pos.y.rem(16).abs() as u8, + z: pos.z.rem(16).abs() as u8, + } + } +} diff --git a/azalea-world/src/bit_storage.rs b/azalea-world/src/bit_storage.rs index 3f810f40..f24a0514 100644 --- a/azalea-world/src/bit_storage.rs +++ b/azalea-world/src/bit_storage.rs @@ -103,6 +103,9 @@ impl BitStorage { /// Create a new BitStorage with the given number of bits per entry. /// `size` is the number of entries in the BitStorage. pub fn new(bits: usize, size: usize, data: Option>) -> Result { + // vanilla has this assert but it's not always true for some reason?? + // assert!(bits >= 1 && bits <= 32); + if let Some(data) = &data { if data.len() == 0 { // TODO: make 0 bit storage actually work @@ -142,10 +145,12 @@ impl BitStorage { } pub fn cell_index(&self, index: u64) -> usize { - let first = self.divide_mul as u64; + // as unsigned wrap + let first = self.divide_mul as u32 as u64; let second = self.divide_add as u64; + dbg!(first, second, index); - (index * first + second >> 32 >> self.divide_shift) + (((index * first) + second) >> 32 >> self.divide_shift) .try_into() .unwrap() } @@ -157,7 +162,12 @@ impl BitStorage { // int var5 = (var1 - var2 * this.valuesPerLong) * this.bits; // return (int)(var3 >> var5 & this.mask); - assert!(index <= self.size - 1); + assert!( + index <= self.size - 1, + "Index {} out of bounds (max is {})", + index, + self.size - 1 + ); let cell_index = self.cell_index(index as u64); let cell = &self.data[cell_index as usize]; let bit_index = (index - cell_index * self.values_per_long as usize) * self.bits; diff --git a/azalea-world/src/lib.rs b/azalea-world/src/lib.rs index 4da2fb0f..aa99a470 100644 --- a/azalea-world/src/lib.rs +++ b/azalea-world/src/lib.rs @@ -1,7 +1,8 @@ mod bit_storage; mod palette; -use azalea_core::ChunkPos; +use crate::palette::PalettedContainerType; +use azalea_core::{BlockPos, ChunkPos, ChunkSectionBlockPos}; use azalea_protocol::mc_buf::{McBufReadable, McBufWritable}; pub use bit_storage::BitStorage; use palette::PalettedContainer; @@ -11,8 +12,6 @@ use std::{ sync::{Arc, Mutex}, }; -use crate::palette::PalettedContainerType; - #[cfg(test)] mod tests { #[test] @@ -54,6 +53,10 @@ impl World { pub fn update_view_center(&mut self, pos: &ChunkPos) { self.storage.view_center = *pos; } + + pub fn get_block_state(&self, pos: &BlockPos) -> Option { + self.storage.get_block_state(pos) + } } impl Index<&ChunkPos> for World { type Output = Option>>; @@ -115,6 +118,15 @@ impl ChunkStorage { (chunk_pos.x - self.view_center.x).unsigned_abs() <= self.chunk_radius && (chunk_pos.z - self.view_center.z).unsigned_abs() <= self.chunk_radius } + + pub fn get_block_state(&self, pos: &BlockPos) -> Option { + let chunk_pos = ChunkPos::from(pos); + let chunk = &self[&chunk_pos]; + match chunk { + Some(chunk) => Some(chunk.lock().unwrap().get(pos)), + None => None, + } + } } impl Index<&ChunkPos> for ChunkStorage { @@ -150,6 +162,23 @@ impl Chunk { } Ok(Chunk { sections }) } + + pub fn section_index(&self, y: i32) -> u32 { + // TODO: check the build height and stuff, this code will be broken if the min build height is 0 + // (LevelHeightAccessor.getMinSection in vanilla code) + assert!(y >= 0); + (y as u32) / 16 + } + + pub fn get(&self, pos: &BlockPos) -> u32 { + let section_index = self.section_index(pos.y); + println!("section index: {}", section_index); + // TODO: make sure the section exists + let section = &self.sections[section_index as usize]; + let chunk_section_pos = ChunkSectionBlockPos::from(pos); + let block_state = section.get(chunk_section_pos); + block_state + } } impl McBufWritable for Chunk { @@ -194,3 +223,11 @@ impl McBufWritable for Section { Ok(()) } } + +impl Section { + // TODO: return a BlockState instead of a u32 + fn get(&self, pos: ChunkSectionBlockPos) -> u32 { + self.states + .get(pos.x as usize, pos.y as usize, pos.z as usize) + } +} diff --git a/azalea-world/src/palette.rs b/azalea-world/src/palette.rs index 55a33bde..6dc5e183 100644 --- a/azalea-world/src/palette.rs +++ b/azalea-world/src/palette.rs @@ -15,6 +15,7 @@ pub struct PalettedContainer { pub palette: Palette, /// Compacted list of indices pointing to entry IDs in the Palette. pub storage: BitStorage, + pub container_type: PalettedContainerType, } impl PalettedContainer { @@ -47,9 +48,29 @@ impl PalettedContainer { bits_per_entry, palette, storage, + container_type: *type_, }) } + + pub fn get_index(&self, x: usize, y: usize, z: usize) -> usize { + let size_bits = match self.container_type { + PalettedContainerType::BlockStates => 4, + PalettedContainerType::Biomes => 2, + }; + + (((y << size_bits) | z) << size_bits) | x + } + + pub fn get(&self, x: usize, y: usize, z: usize) -> u32 { + println!( + "get: {} {} {}, bits per entry: {}", + x, y, z, self.bits_per_entry + ); + let paletted_value = self.storage.get(self.get_index(x, y, z)); + self.palette.value_for(paletted_value as usize) + } } + impl McBufWritable for PalettedContainer { fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { buf.write_byte(self.bits_per_entry)?; @@ -91,6 +112,15 @@ impl Palette { _ => Palette::Global, }) } + + pub fn value_for(&self, value: usize) -> u32 { + match self { + Palette::SingleValue(v) => *v, + Palette::Linear(v) => v[value], + Palette::Hashmap(v) => v[value], + Palette::Global => value as u32, + } + } } impl McBufWritable for Palette { diff --git a/bot/src/main.rs b/bot/src/main.rs index 2f9fb9e6..93d83be9 100644 --- a/bot/src/main.rs +++ b/bot/src/main.rs @@ -25,12 +25,8 @@ async fn main() { if p.message.to_ansi(None) == " ok" { let state = client.state.lock().await; let world = state.world.as_ref().unwrap(); - // let c = world[&BlockPos::new(5, 78, -2)] - // .as_ref() - // .unwrap() - // .lock() - // .unwrap(); - // println!("{:?}", c); + let c = world.get_block_state(&BlockPos::new(5, 78, -2)).unwrap(); + println!("{:?}", c); } } } -- cgit v1.2.3 From e58c9390a717517db0bf4366c55a3802c832b144 Mon Sep 17 00:00:00 2001 From: mat Date: Sat, 14 May 2022 15:02:13 -0500 Subject: get_block_state works --- azalea-client/src/connect.rs | 8 +++++ azalea-core/src/difficulty.rs | 1 - azalea-core/src/lib.rs | 4 ++- azalea-core/src/position.rs | 68 +++++++++++++++++++++++++++++++++++++---- azalea-world/src/bit_storage.rs | 1 - azalea-world/src/lib.rs | 24 +++++++++------ azalea-world/src/palette.rs | 5 +-- bot/src/main.rs | 2 +- 8 files changed, 90 insertions(+), 23 deletions(-) (limited to 'bot/src') diff --git a/azalea-client/src/connect.rs b/azalea-client/src/connect.rs index 522d7d48..8d2e9dc1 100755 --- a/azalea-client/src/connect.rs +++ b/azalea-client/src/connect.rs @@ -195,9 +195,17 @@ impl Client { .expect("height tag is not int")) .try_into() .expect("height is not a u32"); + let min_y = (*dimension_type + .get("min_y") + .expect("No min_y tag") + .as_int() + .expect("min_y tag is not int")) + .try_into() + .expect("min_y is not an i32"); state.world = Some(World { height, + min_y, storage: ChunkStorage::new(16), }); diff --git a/azalea-core/src/difficulty.rs b/azalea-core/src/difficulty.rs index 21e980ba..5d869325 100755 --- a/azalea-core/src/difficulty.rs +++ b/azalea-core/src/difficulty.rs @@ -83,7 +83,6 @@ mod tests { assert_eq!(1, Difficulty::EASY.id()); assert_eq!(2, Difficulty::NORMAL.id()); assert_eq!(3, Difficulty::HARD.id()); - assert_eq!(4, Difficulty::PEACEFUL.id()); } #[test] diff --git a/azalea-core/src/lib.rs b/azalea-core/src/lib.rs index 2b12db53..d2a2d558 100755 --- a/azalea-core/src/lib.rs +++ b/azalea-core/src/lib.rs @@ -1,5 +1,7 @@ //! Random miscellaneous things like UUIDs that don't deserve their own crate. +#![feature(int_roundings)] + pub mod difficulty; pub mod game_type; pub mod resource_location; @@ -9,7 +11,7 @@ mod slot; pub use slot::{Slot, SlotData}; mod position; -pub use position::{BlockPos, ChunkPos, ChunkSectionBlockPos, ChunkSectionPos}; +pub use position::{BlockPos, ChunkBlockPos, ChunkPos, ChunkSectionBlockPos, ChunkSectionPos}; mod direction; pub use direction::Direction; diff --git a/azalea-core/src/position.rs b/azalea-core/src/position.rs index 1dd200ab..9c7cd132 100644 --- a/azalea-core/src/position.rs +++ b/azalea-core/src/position.rs @@ -25,7 +25,7 @@ impl Rem for BlockPos { } } -#[derive(Clone, Copy, Debug, Default)] +#[derive(Clone, Copy, Debug, Default, PartialEq)] pub struct ChunkPos { pub x: i32, pub z: i32, @@ -40,8 +40,8 @@ impl ChunkPos { impl From<&BlockPos> for ChunkPos { fn from(pos: &BlockPos) -> Self { ChunkPos { - x: pos.x / 16, - z: pos.z / 16, + x: pos.x.div_floor(16), + z: pos.z.div_floor(16), } } } @@ -63,9 +63,9 @@ impl ChunkSectionPos { impl From for ChunkSectionPos { fn from(pos: BlockPos) -> Self { ChunkSectionPos { - x: pos.x / 16, - y: pos.y / 16, - z: pos.z / 16, + x: pos.x.div_floor(16), + y: pos.y.div_floor(16), + z: pos.z.div_floor(16), } } } @@ -76,11 +76,38 @@ impl From for ChunkPos { } } +/// The coordinates of a block inside a chunk. +#[derive(Clone, Copy, Debug, Default, PartialEq)] +pub struct ChunkBlockPos { + pub x: u8, + pub y: i32, + pub z: u8, +} + +impl ChunkBlockPos { + pub fn new(x: u8, y: i32, z: u8) -> Self { + ChunkBlockPos { x, y, z } + } +} + +impl From<&BlockPos> for ChunkBlockPos { + fn from(pos: &BlockPos) -> Self { + ChunkBlockPos { + x: pos.x.rem_euclid(16).abs() as u8, + y: pos.y, + z: pos.z.rem_euclid(16).abs() as u8, + } + } +} + /// The coordinates of a block inside a chunk section. #[derive(Clone, Copy, Debug, Default)] pub struct ChunkSectionBlockPos { + /// A number between 0 and 16. pub x: u8, + /// A number between 0 and 16. pub y: u8, + /// A number between 0 and 16. pub z: u8, } @@ -99,3 +126,32 @@ impl From<&BlockPos> for ChunkSectionBlockPos { } } } + +impl From<&ChunkBlockPos> for ChunkSectionBlockPos { + fn from(pos: &ChunkBlockPos) -> Self { + ChunkSectionBlockPos { + x: pos.x, + y: pos.y.rem(16).abs() as u8, + z: pos.z, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_from_block_pos_to_chunk_pos() { + let block_pos = BlockPos::new(5, 78, -2); + let chunk_pos = ChunkPos::from(&block_pos); + assert_eq!(chunk_pos, ChunkPos::new(0, -1)); + } + + #[test] + fn test_from_block_pos_to_chunk_block_pos() { + let block_pos = BlockPos::new(5, 78, -2); + let chunk_block_pos = ChunkBlockPos::from(&block_pos); + assert_eq!(chunk_block_pos, ChunkBlockPos::new(5, 78, 14)); + } +} diff --git a/azalea-world/src/bit_storage.rs b/azalea-world/src/bit_storage.rs index f24a0514..aba52aef 100644 --- a/azalea-world/src/bit_storage.rs +++ b/azalea-world/src/bit_storage.rs @@ -148,7 +148,6 @@ impl BitStorage { // as unsigned wrap let first = self.divide_mul as u32 as u64; let second = self.divide_add as u64; - dbg!(first, second, index); (((index * first) + second) >> 32 >> self.divide_shift) .try_into() diff --git a/azalea-world/src/lib.rs b/azalea-world/src/lib.rs index aa99a470..4641729c 100644 --- a/azalea-world/src/lib.rs +++ b/azalea-world/src/lib.rs @@ -1,8 +1,10 @@ +#![feature(int_roundings)] + mod bit_storage; mod palette; use crate::palette::PalettedContainerType; -use azalea_core::{BlockPos, ChunkPos, ChunkSectionBlockPos}; +use azalea_core::{BlockPos, ChunkBlockPos, ChunkPos, ChunkSectionBlockPos}; use azalea_protocol::mc_buf::{McBufReadable, McBufWritable}; pub use bit_storage::BitStorage; use palette::PalettedContainer; @@ -26,6 +28,7 @@ const SECTION_HEIGHT: u32 = 16; pub struct World { pub storage: ChunkStorage, pub height: u32, + pub min_y: i32, } impl World { @@ -55,7 +58,7 @@ impl World { } pub fn get_block_state(&self, pos: &BlockPos) -> Option { - self.storage.get_block_state(pos) + self.storage.get_block_state(pos, self.min_y) } } impl Index<&ChunkPos> for World { @@ -119,11 +122,12 @@ impl ChunkStorage { && (chunk_pos.z - self.view_center.z).unsigned_abs() <= self.chunk_radius } - pub fn get_block_state(&self, pos: &BlockPos) -> Option { + pub fn get_block_state(&self, pos: &BlockPos, min_y: i32) -> Option { let chunk_pos = ChunkPos::from(pos); + println!("chunk_pos {:?} block_pos {:?}", chunk_pos, pos); let chunk = &self[&chunk_pos]; match chunk { - Some(chunk) => Some(chunk.lock().unwrap().get(pos)), + Some(chunk) => Some(chunk.lock().unwrap().get(&ChunkBlockPos::from(pos), min_y)), None => None, } } @@ -156,26 +160,28 @@ impl Chunk { pub fn read_with_world_height(buf: &mut impl Read, world_height: u32) -> Result { let section_count = world_height / SECTION_HEIGHT; let mut sections = Vec::with_capacity(section_count as usize); - for i in 0..section_count { + for _ in 0..section_count { let section = Section::read_into(buf)?; sections.push(section); } Ok(Chunk { sections }) } - pub fn section_index(&self, y: i32) -> u32 { + pub fn section_index(&self, y: i32, min_y: i32) -> u32 { // TODO: check the build height and stuff, this code will be broken if the min build height is 0 // (LevelHeightAccessor.getMinSection in vanilla code) assert!(y >= 0); - (y as u32) / 16 + let min_section_index = min_y.div_floor(16); + (y.div_floor(16) - min_section_index) as u32 } - pub fn get(&self, pos: &BlockPos) -> u32 { - let section_index = self.section_index(pos.y); + pub fn get(&self, pos: &ChunkBlockPos, min_y: i32) -> u32 { + let section_index = self.section_index(pos.y, min_y); println!("section index: {}", section_index); // TODO: make sure the section exists let section = &self.sections[section_index as usize]; let chunk_section_pos = ChunkSectionBlockPos::from(pos); + println!("chunk section pos: {:?}", chunk_section_pos); let block_state = section.get(chunk_section_pos); block_state } diff --git a/azalea-world/src/palette.rs b/azalea-world/src/palette.rs index 6dc5e183..be6f022c 100644 --- a/azalea-world/src/palette.rs +++ b/azalea-world/src/palette.rs @@ -62,11 +62,8 @@ impl PalettedContainer { } pub fn get(&self, x: usize, y: usize, z: usize) -> u32 { - println!( - "get: {} {} {}, bits per entry: {}", - x, y, z, self.bits_per_entry - ); let paletted_value = self.storage.get(self.get_index(x, y, z)); + println!("palette: {:?}", self.palette); self.palette.value_for(paletted_value as usize) } } diff --git a/bot/src/main.rs b/bot/src/main.rs index 93d83be9..1f2cb6e1 100644 --- a/bot/src/main.rs +++ b/bot/src/main.rs @@ -26,7 +26,7 @@ async fn main() { let state = client.state.lock().await; let world = state.world.as_ref().unwrap(); let c = world.get_block_state(&BlockPos::new(5, 78, -2)).unwrap(); - println!("{:?}", c); + println!("block state: {:?}", c); } } } -- cgit v1.2.3 From 42f86f73f256c0219a923c5ff67a509e7a8a898d Mon Sep 17 00:00:00 2001 From: mat Date: Sat, 14 May 2022 19:14:34 -0500 Subject: add unhandled ClientboundSectionBlocksUpdatePacket --- azalea-client/src/connect.rs | 3 +++ azalea-protocol/src/mc_buf/read.rs | 14 +++++++++++++- azalea-protocol/src/mc_buf/write.rs | 13 ++++++++++++- .../game/clientbound_section_blocks_update_packet.rs | 10 ++++++++++ azalea-protocol/src/packets/game/mod.rs | 2 ++ bot/src/main.rs | 4 ++-- 6 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 azalea-protocol/src/packets/game/clientbound_section_blocks_update_packet.rs (limited to 'bot/src') diff --git a/azalea-client/src/connect.rs b/azalea-client/src/connect.rs index 8d2e9dc1..48fd16f2 100755 --- a/azalea-client/src/connect.rs +++ b/azalea-client/src/connect.rs @@ -373,6 +373,9 @@ impl Client { GamePacket::ClientboundAnimatePacket(p) => { println!("Got animate packet {:?}", p); } + GamePacket::ClientboundSectionBlocksUpdatePacket(p) => { + println!("Got section blocks update packet {:?}", p); + } _ => panic!("Unexpected packet {:?}", packet), } } diff --git a/azalea-protocol/src/mc_buf/read.rs b/azalea-protocol/src/mc_buf/read.rs index ebafad92..1c4fbd6f 100644 --- a/azalea-protocol/src/mc_buf/read.rs +++ b/azalea-protocol/src/mc_buf/read.rs @@ -2,7 +2,7 @@ use super::{UnsizedByteArray, MAX_STRING_LENGTH}; use azalea_chat::component::Component; use azalea_core::{ difficulty::Difficulty, game_type::GameType, resource_location::ResourceLocation, - serializable_uuid::SerializableUuid, BlockPos, Direction, Slot, SlotData, + serializable_uuid::SerializableUuid, BlockPos, ChunkSectionPos, Direction, Slot, SlotData, }; use byteorder::{ReadBytesExt, BE}; use serde::Deserialize; @@ -518,3 +518,15 @@ impl McBufReadable for Direction { } } } + +// ChunkSectionPos +impl McBufReadable for ChunkSectionPos { + fn read_into(buf: &mut impl Read) -> Result { + let long = i64::read_into(buf)?; + Ok(ChunkSectionPos { + x: (long >> 42) as i32, + y: (long << 44 >> 44) as i32, + z: (long << 22 >> 42) as i32, + }) + } +} diff --git a/azalea-protocol/src/mc_buf/write.rs b/azalea-protocol/src/mc_buf/write.rs index 7fe61752..c46297a6 100644 --- a/azalea-protocol/src/mc_buf/write.rs +++ b/azalea-protocol/src/mc_buf/write.rs @@ -2,7 +2,7 @@ use super::{UnsizedByteArray, MAX_STRING_LENGTH}; use azalea_chat::component::Component; use azalea_core::{ difficulty::Difficulty, game_type::GameType, resource_location::ResourceLocation, - serializable_uuid::SerializableUuid, BlockPos, Direction, Slot, + serializable_uuid::SerializableUuid, BlockPos, ChunkSectionPos, Direction, Slot, }; use byteorder::{BigEndian, WriteBytesExt}; use std::{collections::HashMap, io::Write}; @@ -425,3 +425,14 @@ impl McBufWritable for Direction { buf.write_varint(*self as i32) } } + +// ChunkSectionPos +impl McBufWritable for ChunkSectionPos { + fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { + let long = (((self.x & 0x3FFFFF) as i64) << 42) + | (self.y & 0xFFFFF) as i64 + | (((self.z & 0x3FFFFF) as i64) << 20); + long.write_into(buf)?; + Ok(()) + } +} diff --git a/azalea-protocol/src/packets/game/clientbound_section_blocks_update_packet.rs b/azalea-protocol/src/packets/game/clientbound_section_blocks_update_packet.rs new file mode 100644 index 00000000..f220b07f --- /dev/null +++ b/azalea-protocol/src/packets/game/clientbound_section_blocks_update_packet.rs @@ -0,0 +1,10 @@ +use azalea_core::ChunkSectionPos; +use packet_macros::GamePacket; + +#[derive(Clone, Debug, GamePacket)] +pub struct ClientboundSectionBlocksUpdatePacket { + pub section_pos: ChunkSectionPos, + pub suppress_light_updates: bool, + #[var] + pub states: Vec, +} diff --git a/azalea-protocol/src/packets/game/mod.rs b/azalea-protocol/src/packets/game/mod.rs index 0391ee10..66c55cd2 100755 --- a/azalea-protocol/src/packets/game/mod.rs +++ b/azalea-protocol/src/packets/game/mod.rs @@ -26,6 +26,7 @@ pub mod clientbound_player_position_packet; pub mod clientbound_recipe_packet; pub mod clientbound_remove_entities_packet; pub mod clientbound_rotate_head_packet; +pub mod clientbound_section_blocks_update_packet; pub mod clientbound_set_carried_item_packet; pub mod clientbound_set_chunk_cache_center; pub mod clientbound_set_default_spawn_position_packet; @@ -80,6 +81,7 @@ declare_state_packets!( 0x39: clientbound_recipe_packet::ClientboundRecipePacket, 0x3a: clientbound_remove_entities_packet::ClientboundRemoveEntitiesPacket, 0x3e: clientbound_rotate_head_packet::ClientboundRotateHeadPacket, + 0x3f: clientbound_section_blocks_update_packet::ClientboundSectionBlocksUpdatePacket, 0x48: clientbound_set_carried_item_packet::ClientboundSetCarriedItemPacket, 0x49: clientbound_set_chunk_cache_center::ClientboundSetChunkCacheCenterPacket, 0x4a: clientbound_update_view_distance_packet::ClientboundUpdateViewDistancePacket, diff --git a/bot/src/main.rs b/bot/src/main.rs index 1f2cb6e1..76a5a15d 100644 --- a/bot/src/main.rs +++ b/bot/src/main.rs @@ -1,12 +1,12 @@ use azalea_client::{Account, Event}; -use azalea_core::{BlockPos, ChunkPos}; +use azalea_core::BlockPos; #[tokio::main] async fn main() { println!("Hello, world!"); // let address = "95.111.249.143:10000"; - let address = "192.168.2.234:62840"; + let address = "192.168.2.234:50736"; // let response = azalea_client::ping::ping_server(&address.try_into().unwrap()) // .await // .unwrap(); -- cgit v1.2.3