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 --- azalea-core/src/block_pos.rs | 6 ------ azalea-core/src/lib.rs | 4 ++-- azalea-core/src/position.rs | 24 ++++++++++++++++++++++++ 3 files changed, 26 insertions(+), 8 deletions(-) delete mode 100644 azalea-core/src/block_pos.rs create mode 100644 azalea-core/src/position.rs (limited to 'azalea-core/src') diff --git a/azalea-core/src/block_pos.rs b/azalea-core/src/block_pos.rs deleted file mode 100644 index 96a234cb..00000000 --- a/azalea-core/src/block_pos.rs +++ /dev/null @@ -1,6 +0,0 @@ -#[derive(Clone, Copy, Debug)] -pub struct BlockPos { - pub x: i32, - pub y: i32, - pub z: i32, -} diff --git a/azalea-core/src/lib.rs b/azalea-core/src/lib.rs index c6b51cb1..6f0c25cc 100755 --- a/azalea-core/src/lib.rs +++ b/azalea-core/src/lib.rs @@ -8,8 +8,8 @@ pub mod serializable_uuid; mod slot; pub use slot::{Slot, SlotData}; -mod block_pos; -pub use block_pos::BlockPos; +mod position; +pub use position::{BlockPos, ChunkPos}; mod direction; pub use direction::Direction; diff --git a/azalea-core/src/position.rs b/azalea-core/src/position.rs new file mode 100644 index 00000000..aa82c1f9 --- /dev/null +++ b/azalea-core/src/position.rs @@ -0,0 +1,24 @@ +#[derive(Clone, Copy, Debug, Default)] +pub struct BlockPos { + pub x: i32, + pub y: i32, + pub z: i32, +} + +impl BlockPos { + pub fn new(x: i32, y: i32, z: i32) -> Self { + BlockPos { x, y, z } + } +} + +#[derive(Clone, Copy, Debug, Default)] +pub struct ChunkPos { + pub x: i32, + pub z: i32, +} + +impl ChunkPos { + pub fn new(x: i32, z: i32) -> Self { + ChunkPos { x, z } + } +} -- 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 'azalea-core/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 'azalea-core/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 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 'azalea-core/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 'azalea-core/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