1use yog_ids::block_trait;
5
6#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
8pub struct BlockTraits(pub u64);
9
10const fn bit(name: &str) -> u64 {
12 let all = block_trait::ALL_VALUES;
13 let mut i = 0;
14 while i < all.len() {
15 if eq(all[i], name) {
16 return 1 << i;
17 }
18 i += 1;
19 }
20 panic!("not a block trait")
21}
22
23const fn eq(a: &str, b: &str) -> bool {
24 let (a, b) = (a.as_bytes(), b.as_bytes());
25 if a.len() != b.len() {
26 return false;
27 }
28 let mut i = 0;
29 while i < a.len() {
30 if a[i] != b[i] {
31 return false;
32 }
33 i += 1;
34 }
35 true
36}
37
38macro_rules! traits {
39 ($($name:ident),* $(,)?) => {
40 impl BlockTraits {
41 $(
42 #[doc = concat!("`block_trait::", stringify!($name), "`.")]
43 pub const $name: BlockTraits = BlockTraits(bit(block_trait::$name));
44 )*
45 #[cfg(test)]
47 pub(crate) const COUNT: usize = [$(stringify!($name)),*].len();
48 }
49 };
50}
51
52traits!(
53 AIR,
54 SOLID,
55 FULL,
56 LIQUID,
57 WATER,
58 LAVA,
59 SOURCE,
60 FLUID_BLOCK,
61 CLIMBABLE,
62 HARMFUL,
63 FALLS,
64 PATHFINDABLE,
65 REPLACEABLE,
66 STURDY_TOP,
67 FIRE,
68 SLAB,
69 STAIRS,
70 DOOR,
71 WOODEN_DOOR,
72 FENCE_GATE,
73 TRAPDOOR,
74 FENCE,
75 WALL,
76 CARPET,
77 SNOW_LAYER,
78 SKULL,
79 SHULKER_BOX,
80 LEAVES,
81 INFESTED,
82 CAULDRON,
83 AZALEA,
84 AMETHYST_CLUSTER,
85 POINTED_DRIPSTONE,
86 BAMBOO,
87 MOVING_PISTON,
88 SCAFFOLDING,
89 CHEST,
90 GLASS,
91);
92
93impl BlockTraits {
94 #[inline]
96 pub const fn has(self, t: BlockTraits) -> bool {
97 self.0 & t.0 == t.0
98 }
99
100 #[inline]
102 pub const fn any(self, t: BlockTraits) -> bool {
103 self.0 & t.0 != 0
104 }
105}
106
107impl std::ops::BitOr for BlockTraits {
108 type Output = BlockTraits;
109
110 fn bitor(self, o: BlockTraits) -> BlockTraits {
111 BlockTraits(self.0 | o.0)
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118
119 #[test]
120 fn every_trait_has_its_bit() {
121 assert_eq!(BlockTraits::COUNT, block_trait::ALL_VALUES.len());
122 assert_eq!(BlockTraits::AIR.0, 1);
123 assert_eq!(BlockTraits::GLASS.0, 1 << (block_trait::ALL_VALUES.len() - 1));
124 assert!((BlockTraits::SLAB | BlockTraits::WATER).has(BlockTraits::SLAB));
125 }
126}