aboutsummaryrefslogtreecommitdiff
path: root/azalea-world/src
diff options
context:
space:
mode:
authormat <github@matdoes.dev>2022-05-14 14:12:57 -0500
committermat <github@matdoes.dev>2022-05-14 14:12:57 -0500
commit6d2fd8afbad44bbe88f701e1d67cc2f251246c07 (patch)
tree3fa06efe4408c28db89aa6f115414d7a6995b1cc /azalea-world/src
parent70271ede1982b618b5bb592da4adffabcdd76dac (diff)
downloadazalea-drasl-6d2fd8afbad44bbe88f701e1d67cc2f251246c07.tar.xz
start adding get_block_state
Diffstat (limited to 'azalea-world/src')
-rw-r--r--azalea-world/src/bit_storage.rs16
-rw-r--r--azalea-world/src/lib.rs43
-rw-r--r--azalea-world/src/palette.rs30
3 files changed, 83 insertions, 6 deletions
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<Vec<u64>>) -> Result<Self, BitStorageError> {
+ // 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<u32> {
+ self.storage.get_block_state(pos)
+ }
}
impl Index<&ChunkPos> for World {
type Output = Option<Arc<Mutex<Chunk>>>;
@@ -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<u32> {
+ 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 {