azalea_block/
lib.rs

1#![doc = include_str!("../README.md")]
2
3mod behavior;
4pub mod block_state;
5pub mod fluid_state;
6mod generated;
7mod range;
8
9use core::fmt::Debug;
10use std::any::Any;
11
12pub use behavior::BlockBehavior;
13// re-exported for convenience
14pub use block_state::BlockState;
15pub use generated::{blocks, properties};
16pub use range::BlockStates;
17
18pub trait BlockTrait: Debug + Any {
19    fn behavior(&self) -> BlockBehavior;
20    /// Get the Minecraft ID for this block. For example `stone` or
21    /// `grass_block`.
22    fn id(&self) -> &'static str;
23    /// Convert the block to a block state. This is lossless, as the block
24    /// contains all the state data.
25    fn as_block_state(&self) -> BlockState;
26    /// Convert the block to an [`azalea_registry::Block`]. This is lossy, as
27    /// `azalea_registry::Block` doesn't contain any state data.
28    fn as_registry_block(&self) -> azalea_registry::Block;
29}
30impl dyn BlockTrait {
31    pub fn downcast_ref<T: BlockTrait>(&self) -> Option<&T> {
32        (self as &dyn Any).downcast_ref::<T>()
33    }
34}
35
36pub trait Property {
37    type Value;
38
39    fn try_from_block_state(state: BlockState) -> Option<Self::Value>;
40}
41
42#[cfg(test)]
43mod tests {
44    use crate::BlockTrait;
45
46    #[test]
47    pub fn roundtrip_block_state() {
48        let block = crate::blocks::OakTrapdoor {
49            facing: crate::properties::FacingCardinal::East,
50            half: crate::properties::TopBottom::Bottom,
51            open: true,
52            powered: false,
53            waterlogged: false,
54        };
55        let block_state = block.as_block_state();
56        let block_from_state = Box::<dyn BlockTrait>::from(block_state);
57        let block_from_state = block_from_state
58            .downcast_ref::<crate::blocks::OakTrapdoor>()
59            .unwrap()
60            .clone();
61        assert_eq!(block, block_from_state);
62    }
63}