Pumpkin/pumpkin-data/src/block_state.rs
2025-11-27 18:44:14 +01:00

168 lines
4.8 KiB
Rust

use pumpkin_util::math::vector3::Vector3;
use crate::block_properties::{COLLISION_SHAPES, Instrument};
use crate::{Block, BlockDirection, CollisionShape};
#[derive(Debug)]
pub struct BlockState {
pub id: u16,
pub state_flags: u16,
pub side_flags: u8,
pub instrument: Instrument,
pub luminance: u8,
pub piston_behavior: PistonBehavior,
pub hardness: f32,
pub collision_shapes: &'static [u16],
pub outline_shapes: &'static [u16],
/// u8::MAX is used as None
pub opacity: u8,
/// u16::MAX is used as None
pub block_entity_type: u16,
}
impl PartialEq for BlockState {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[repr(u8)]
pub enum PistonBehavior {
Normal,
Destroy,
Block,
Ignore,
PushOnly,
}
// Add your methods here
impl BlockState {
pub const fn is_air(&self) -> bool {
self.state_flags & IS_AIR != 0
}
pub const fn burnable(&self) -> bool {
self.state_flags & BURNABLE != 0
}
pub const fn tool_required(&self) -> bool {
self.state_flags & TOOL_REQUIRED != 0
}
pub const fn sided_transparency(&self) -> bool {
self.state_flags & SIDED_TRANSPARENCY != 0
}
pub const fn replaceable(&self) -> bool {
self.state_flags & REPLACEABLE != 0
}
pub const fn is_liquid(&self) -> bool {
self.state_flags & IS_LIQUID != 0
}
/// Returns the legacy value for whether a block is solid.
pub const fn is_solid(&self) -> bool {
self.state_flags & IS_SOLID != 0
}
pub const fn is_full_cube(&self) -> bool {
self.state_flags & IS_FULL_CUBE != 0
}
/// Returns whether the block is solid.
/// Solid blocks conduct redstone and block redstone wire.
/// Non-solid blocks don't allow redstone wire on top to propagate their signal downwards in java.
pub const fn is_solid_block(&self) -> bool {
self.state_flags & IS_SOLID_BLOCK != 0
}
pub const fn has_random_ticks(&self) -> bool {
self.state_flags & HAS_RANDOM_TICKS != 0
}
///isSideSolidFullSquare() in Java!
pub const fn is_side_solid(&self, side: BlockDirection) -> bool {
match side {
BlockDirection::Down => self.side_flags & DOWN_SIDE_SOLID != 0,
BlockDirection::Up => self.side_flags & UP_SIDE_SOLID != 0,
BlockDirection::North => self.side_flags & NORTH_SIDE_SOLID != 0,
BlockDirection::South => self.side_flags & SOUTH_SIDE_SOLID != 0,
BlockDirection::West => self.side_flags & WEST_SIDE_SOLID != 0,
BlockDirection::East => self.side_flags & EAST_SIDE_SOLID != 0,
}
}
///isSideSolid(..., Direction.UP, SideShapeType.CENTER) in Java!
///Only valid for UP and DOWN sides
pub const fn is_center_solid(&self, side: BlockDirection) -> bool {
match side {
BlockDirection::Down => self.side_flags & DOWN_CENTER_SOLID != 0,
BlockDirection::Up => self.side_flags & UP_CENTER_SOLID != 0,
_ => unreachable!(),
}
}
pub fn get_block_collision_shapes(&self) -> Vec<CollisionShape> {
self.collision_shapes
.iter()
.map(|&id| COLLISION_SHAPES[id as usize])
.collect()
}
pub fn get_block_outline_shapes(&self) -> Option<Vec<CollisionShape>> {
let mut shapes: Vec<CollisionShape> = self
.outline_shapes
.iter()
.map(|&id| COLLISION_SHAPES[id as usize])
.collect();
let block = Block::from_state_id(self.id);
if let Some(props) = block.properties(self.id) {
let is_waterlogged = props
.to_props()
.iter()
.any(|(k, v)| *k == "waterlogged" && *v == "true");
if is_waterlogged {
shapes.push(CollisionShape::new(
Vector3::new(0.0, 0.0, 0.0),
Vector3::new(1.0, 0.875, 1.0),
));
}
}
Some(shapes)
}
}
#[derive(Clone, Debug)]
pub struct BlockStateRef {
pub id: u16,
pub state_idx: u16,
}
//This is the Layout of state_props in the right order
// state_flags
const IS_AIR: u16 = 1 << 0;
const BURNABLE: u16 = 1 << 1;
const TOOL_REQUIRED: u16 = 1 << 2;
const SIDED_TRANSPARENCY: u16 = 1 << 3;
const REPLACEABLE: u16 = 1 << 4;
const IS_LIQUID: u16 = 1 << 5;
const IS_SOLID: u16 = 1 << 6;
const IS_FULL_CUBE: u16 = 1 << 7;
const IS_SOLID_BLOCK: u16 = 1 << 8;
const HAS_RANDOM_TICKS: u16 = 1 << 9;
// side_flags
const DOWN_SIDE_SOLID: u8 = 1 << 0;
const UP_SIDE_SOLID: u8 = 1 << 1;
const NORTH_SIDE_SOLID: u8 = 1 << 2;
const SOUTH_SIDE_SOLID: u8 = 1 << 3;
const WEST_SIDE_SOLID: u8 = 1 << 4;
const EAST_SIDE_SOLID: u8 = 1 << 5;
const DOWN_CENTER_SOLID: u8 = 1 << 6;
const UP_CENTER_SOLID: u8 = 1 << 7;