world/section: add method to get block ID at coordinate

This commit is contained in:
Matthias Schiffer 2023-02-12 20:04:31 +01:00
parent 3cee4a4247
commit b918ff6106
Signed by: neocturne
GPG key ID: 16EF3F64CB201D9C

View file

@ -1,6 +1,7 @@
use anyhow::{bail, Context, Result}; use anyhow::{bail, Context, Result};
use super::de; use super::de;
use crate::{resource, types::*};
fn palette_bits(len: usize, min: u8, max: u8) -> Option<u8> { fn palette_bits(len: usize, min: u8, max: u8) -> Option<u8> {
let mut bits = min; let mut bits = min;
@ -15,7 +16,9 @@ fn palette_bits(len: usize, min: u8, max: u8) -> Option<u8> {
Some(bits) Some(bits)
} }
pub trait Section {} pub trait Section {
fn get_block_id(&self, coords: BlockCoords) -> Result<&str>;
}
#[derive(Debug)] #[derive(Debug)]
pub struct PaletteSectionBiomes<'a> { pub struct PaletteSectionBiomes<'a> {
@ -81,9 +84,48 @@ impl<'a> PaletteSection<'a> {
aligned_blocks, aligned_blocks,
}) })
} }
fn get_palette_index(&self, coords: BlockCoords) -> usize {
let Some(block_states) = self.block_states else {
return 0;
};
let bits = self.bits as usize;
let mask = (1 << bits) - 1;
let offset = coords.offset();
let shifted = if self.aligned_blocks {
let blocks_per_word = 64 / bits;
let (word, shift) = offset.div_rem(blocks_per_word);
block_states[word] as u64 >> (shift * bits)
} else {
let bit_offset = offset * bits;
let (word, bit_shift) = bit_offset.div_rem(64);
if bit_shift + bits <= 64 {
block_states[word] as u64 >> bit_shift
} else {
let tmp = (block_states[word + 1] as u64 as u128) << 64
| block_states[word] as u64 as u128;
(tmp >> bit_shift) as u64
}
};
(shifted & mask) as usize
}
} }
impl<'a> Section for PaletteSection<'a> {} impl<'a> Section for PaletteSection<'a> {
fn get_block_id(&self, coords: BlockCoords) -> Result<&str> {
let index = self.get_palette_index(coords);
let entry = self
.palette
.get(index)
.context("Palette index out of bounds")?;
Ok(&entry.name)
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct OldSection<'a> { pub struct OldSection<'a> {
@ -93,9 +135,31 @@ pub struct OldSection<'a> {
impl<'a> OldSection<'a> { impl<'a> OldSection<'a> {
pub fn new(blocks: &'a fastnbt::ByteArray, data: &'a fastnbt::ByteArray) -> Result<Self> { pub fn new(blocks: &'a fastnbt::ByteArray, data: &'a fastnbt::ByteArray) -> Result<Self> {
// TODO: Check lengths const N: usize = BLOCKS_PER_CHUNK as usize;
Ok(Self { blocks, data }) if blocks.len() != N * N * N {
bail!("Invalid section block data");
}
if data.len() != N * N * N / 2 {
bail!("Invalid section extra data");
}
Ok(OldSection { blocks, data })
} }
} }
impl<'a> Section for OldSection<'a> {} impl<'a> Section for OldSection<'a> {
fn get_block_id(&self, coords: BlockCoords) -> Result<&str> {
let offset = coords.offset();
let block = self.blocks[offset] as u8;
let (data_offset, data_nibble) = offset.div_rem(2);
let data_byte = self.data[data_offset] as u8;
let data = if data_nibble == 1 {
data_byte >> 4
} else {
data_byte & 0xf
};
Ok(resource::LEGACY_BLOCK_TYPES[block as usize][data as usize])
}
}