mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 14:26:04 +00:00
Fix chunk decoding
This commit is contained in:
parent
57b76ef52b
commit
4dac004635
7 changed files with 85 additions and 19 deletions
|
@ -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<u8> that isn't prefixed by a VarInt with the size.
|
||||
|
|
|
@ -255,6 +255,17 @@ impl McBufVarintReadable for i32 {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: McBufVarintReadable> McBufVarintReadable for Vec<T> {
|
||||
fn varint_read_into(buf: &mut impl Read) -> Result<Self, String> {
|
||||
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<Self, String> {
|
||||
Ok(UnsizedByteArray(buf.read_bytes()?))
|
||||
|
|
|
@ -210,6 +210,13 @@ impl McBufVarintWritable for u32 {
|
|||
}
|
||||
}
|
||||
|
||||
// Vec<T> varint
|
||||
impl<T: McBufVarintWritable> McBufVarintWritable for Vec<T> {
|
||||
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> {
|
||||
|
|
|
@ -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<u64>,
|
||||
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);
|
||||
|
|
|
@ -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<Self, String> {
|
||||
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<Self, String> {
|
||||
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,
|
||||
|
|
|
@ -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<i64>,
|
||||
pub data: Vec<u64>,
|
||||
}
|
||||
|
||||
impl McBufReadable for PalettedContainer {
|
||||
fn read_into(buf: &mut impl Read) -> Result<Self, String> {
|
||||
impl PalettedContainer {
|
||||
pub fn read_with_type(
|
||||
buf: &mut impl Read,
|
||||
type_: &'static PalettedContainerType,
|
||||
) -> Result<Self, String> {
|
||||
let bits_per_entry = buf.read_byte()?;
|
||||
let palette = Palette::read_with_bits_per_entry(buf, bits_per_entry)?;
|
||||
let data = Vec::<i64>::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::<u64>::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<Palette, String> {
|
||||
Ok(match bits_per_entry {
|
||||
0 => Palette::SingleValue(u32::read_into(buf)?),
|
||||
1..=4 => Palette::Linear(Vec::<u32>::read_into(buf)?),
|
||||
5..=8 => Palette::Hashmap(Vec::<u32>::read_into(buf)?),
|
||||
0 => Palette::SingleValue(u32::varint_read_into(buf)?),
|
||||
1..=4 => Palette::Linear(Vec::<u32>::varint_read_into(buf)?),
|
||||
5..=8 => Palette::Hashmap(Vec::<u32>::varint_read_into(buf)?),
|
||||
_ => Palette::Global,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn biomes_read_with_bits_per_entry(
|
||||
buf: &mut impl Read,
|
||||
bits_per_entry: u8,
|
||||
) -> Result<Palette, String> {
|
||||
Ok(match bits_per_entry {
|
||||
0 => Palette::SingleValue(u32::varint_read_into(buf)?),
|
||||
1..=3 => Palette::Linear(Vec::<u32>::varint_read_into(buf)?),
|
||||
_ => Palette::Global,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Add table
Reference in a new issue