mirror of
https://github.com/mat-1/azalea.git
synced 2024-09-19 22:52:32 +00:00
azalea-world uses azalea-block
This commit is contained in:
parent
4f89f70091
commit
74c3ae52f8
6 changed files with 76 additions and 6 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -183,6 +183,7 @@ dependencies = [
|
|||
name = "azalea-world"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"azalea-block",
|
||||
"azalea-core",
|
||||
"azalea-nbt",
|
||||
"azalea-protocol",
|
||||
|
|
|
@ -461,9 +461,12 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
|
|||
block_structs.extend(block_struct);
|
||||
}
|
||||
|
||||
let last_state_id = (state_id - 1) as u32;
|
||||
quote! {
|
||||
#property_enums
|
||||
|
||||
#[repr(u32)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub enum BlockState {
|
||||
#block_state_enum_variants
|
||||
}
|
||||
|
@ -479,6 +482,15 @@ pub fn make_block_states(input: TokenStream) -> TokenStream {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockState {
|
||||
/// Returns the highest possible state
|
||||
#[inline]
|
||||
pub fn max_state() -> u32 {
|
||||
#last_state_id
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
|
|
@ -4,3 +4,44 @@ mod blocks;
|
|||
pub use behavior::BlockBehavior;
|
||||
pub use blocks::*;
|
||||
|
||||
use std::mem;
|
||||
|
||||
impl BlockState {
|
||||
/// Transmutes a u32 to a block state. UB if the value is not a valid block
|
||||
/// state.
|
||||
#[inline]
|
||||
pub unsafe fn from_u32_unsafe(state_id: u32) -> Self {
|
||||
mem::transmute::<u32, BlockState>(state_id)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_valid_state(state_id: u32) -> bool {
|
||||
state_id <= Self::max_state()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<u32> for BlockState {
|
||||
type Error = ();
|
||||
|
||||
/// Safely converts a state id to a block state.
|
||||
fn try_from(state_id: u32) -> Result<Self, Self::Error> {
|
||||
if Self::is_valid_state(state_id) {
|
||||
Ok(unsafe { Self::from_u32_unsafe(state_id) })
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_from_u32() {
|
||||
assert_eq!(BlockState::try_from(0).unwrap(), BlockState::Air);
|
||||
|
||||
assert!(BlockState::try_from(BlockState::max_state()).is_ok());
|
||||
assert!(BlockState::try_from(BlockState::max_state() + 1).is_err());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,3 +9,4 @@ version = "0.1.0"
|
|||
azalea-core = {path = "../azalea-core"}
|
||||
azalea-nbt = {path = "../azalea-nbt"}
|
||||
azalea-protocol = {path = "../azalea-protocol"}
|
||||
azalea-block = {path = "../azalea-block"}
|
||||
|
|
|
@ -188,6 +188,12 @@ impl BitStorage {
|
|||
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;
|
||||
}
|
||||
|
||||
/// The number of entries.
|
||||
#[inline]
|
||||
pub fn size(&self) -> usize {
|
||||
self.size
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -8,6 +8,7 @@ use azalea_core::{BlockPos, ChunkBlockPos, ChunkPos, ChunkSectionBlockPos};
|
|||
use azalea_protocol::mc_buf::{McBufReadable, McBufWritable};
|
||||
pub use bit_storage::BitStorage;
|
||||
use palette::PalettedContainer;
|
||||
use azalea_block::BlockState;
|
||||
use std::{
|
||||
io::{Read, Write},
|
||||
ops::{Index, IndexMut},
|
||||
|
@ -57,7 +58,7 @@ impl World {
|
|||
self.storage.view_center = *pos;
|
||||
}
|
||||
|
||||
pub fn get_block_state(&self, pos: &BlockPos) -> Option<u32> {
|
||||
pub fn get_block_state(&self, pos: &BlockPos) -> Option<BlockState> {
|
||||
self.storage.get_block_state(pos, self.min_y)
|
||||
}
|
||||
}
|
||||
|
@ -122,7 +123,7 @@ impl ChunkStorage {
|
|||
&& (chunk_pos.z - self.view_center.z).unsigned_abs() <= self.chunk_radius
|
||||
}
|
||||
|
||||
pub fn get_block_state(&self, pos: &BlockPos, min_y: i32) -> Option<u32> {
|
||||
pub fn get_block_state(&self, pos: &BlockPos, min_y: i32) -> Option<BlockState> {
|
||||
let chunk_pos = ChunkPos::from(pos);
|
||||
println!("chunk_pos {:?} block_pos {:?}", chunk_pos, pos);
|
||||
let chunk = &self[&chunk_pos];
|
||||
|
@ -175,7 +176,7 @@ impl Chunk {
|
|||
(y.div_floor(16) - min_section_index) as u32
|
||||
}
|
||||
|
||||
pub fn get(&self, pos: &ChunkBlockPos, min_y: i32) -> u32 {
|
||||
pub fn get(&self, pos: &ChunkBlockPos, min_y: i32) -> BlockState {
|
||||
let section_index = self.section_index(pos.y, min_y);
|
||||
// TODO: make sure the section exists
|
||||
let section = &self.sections[section_index as usize];
|
||||
|
@ -210,6 +211,14 @@ impl McBufReadable for Section {
|
|||
// "A section has more blocks than what should be possible. This is a bug!"
|
||||
// );
|
||||
let states = PalettedContainer::read_with_type(buf, &PalettedContainerType::BlockStates)?;
|
||||
for i in 0..states.storage.size() {
|
||||
if !BlockState::is_valid_state(states.storage.get(i) as u32) {
|
||||
return Err(format!(
|
||||
"Invalid block state {} (index {}) found in section.",
|
||||
states.storage.get(i), i
|
||||
));
|
||||
}
|
||||
}
|
||||
let biomes = PalettedContainer::read_with_type(buf, &PalettedContainerType::Biomes)?;
|
||||
Ok(Section {
|
||||
block_count,
|
||||
|
@ -229,9 +238,9 @@ impl McBufWritable for Section {
|
|||
}
|
||||
|
||||
impl Section {
|
||||
// TODO: return a BlockState instead of a u32
|
||||
fn get(&self, pos: ChunkSectionBlockPos) -> u32 {
|
||||
fn get(&self, pos: ChunkSectionBlockPos) -> BlockState {
|
||||
// TODO: use the unsafe method and do the check earlier
|
||||
self.states
|
||||
.get(pos.x as usize, pos.y as usize, pos.z as usize)
|
||||
.get(pos.x as usize, pos.y as usize, pos.z as usize).try_into().expect("Invalid block state.")
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue