Skip to main content

steel_registry/blocks/
properties.rs

1use std::fmt::Debug;
2
3pub use steel_utils::{Direction, axis::Axis, codec::VarInt, serial::ReadFrom};
4
5pub trait Property<T>: Sync + Send {
6    fn get_value(&self, value: &str) -> Option<T>;
7    fn get_possible_values(&self) -> Box<[T]>;
8    fn get_internal_index(&self, value: &T) -> usize;
9    fn value_from_index(&self, index: usize) -> T;
10    fn as_dyn(&self) -> &dyn DynProperty;
11}
12
13pub trait DynProperty: Debug + Sync + Send {
14    fn get_possible_values(&self) -> Box<[&str]>;
15    fn get_name(&self) -> &'static str;
16}
17
18pub trait PropertyEnum: PartialEq + Clone + Debug + Sync + Send {
19    fn as_str(&self) -> &str;
20}
21
22#[derive(Debug, Clone)]
23pub struct BoolProperty {
24    pub name: &'static str,
25}
26impl BoolProperty {
27    #[must_use]
28    pub const fn new(name: &'static str) -> Self {
29        Self { name }
30    }
31
32    #[must_use]
33    pub const fn value_count(&self) -> usize {
34        2
35    }
36
37    /// Convert a boolean value to its internal index (true=0, false=1 for Java compatibility)
38    #[must_use]
39    pub const fn index_of(&self, value: bool) -> usize {
40        !value as usize
41    }
42}
43
44impl DynProperty for BoolProperty {
45    fn get_possible_values(&self) -> Box<[&str]> {
46        ["true", "false"].into()
47    }
48
49    fn get_name(&self) -> &'static str {
50        self.name
51    }
52}
53
54impl Property<bool> for BoolProperty {
55    fn get_value(&self, value: &str) -> Option<bool> {
56        if value == "true" {
57            Some(true)
58        } else if value == "false" {
59            Some(false)
60        } else {
61            None
62        }
63    }
64
65    fn get_possible_values(&self) -> Box<[bool]> {
66        [true, false].into()
67    }
68
69    fn get_internal_index(&self, value: &bool) -> usize {
70        usize::from(!*value)
71    }
72
73    fn value_from_index(&self, index: usize) -> bool {
74        index == 0
75    }
76
77    fn as_dyn(&self) -> &dyn DynProperty {
78        self
79    }
80}
81
82impl BoolProperty {
83    #[must_use]
84    pub const fn get_internal_index_const(self, value: bool) -> usize {
85        if value { 0 } else { 1 }
86    }
87}
88
89// Instead of million heap allocs we just use 42 bytes of static mem :)
90const NUM_STR: [&str; 26] = [
91    "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16",
92    "17", "18", "19", "20", "21", "22", "23", "24", "25",
93];
94
95#[derive(Debug, Clone)]
96pub struct IntProperty {
97    pub min: u8,
98    pub max: u8,
99    pub name: &'static str,
100}
101
102impl IntProperty {
103    #[must_use]
104    pub const fn new(name: &'static str, min: u8, max: u8) -> Self {
105        Self { min, max, name }
106    }
107
108    #[must_use]
109    pub const fn value_count(&self) -> usize {
110        (self.max - self.min + 1) as usize
111    }
112}
113
114impl DynProperty for IntProperty {
115    fn get_possible_values(&self) -> Box<[&str]> {
116        (self.min..=self.max).map(|v| NUM_STR[v as usize]).collect()
117    }
118
119    fn get_name(&self) -> &'static str {
120        self.name
121    }
122}
123
124impl Property<u8> for IntProperty {
125    fn get_value(&self, value: &str) -> Option<u8> {
126        value
127            .parse()
128            .ok()
129            .filter(|v| v >= &self.min && v <= &self.max)
130    }
131
132    fn get_possible_values(&self) -> Box<[u8]> {
133        (self.min..=self.max).collect()
134    }
135
136    fn get_internal_index(&self, value: &u8) -> usize {
137        if *value <= self.max {
138            (*value - self.min) as usize
139        } else {
140            0
141        }
142    }
143
144    fn value_from_index(&self, index: usize) -> u8 {
145        self.min + index as u8
146    }
147
148    fn as_dyn(&self) -> &dyn DynProperty {
149        self
150    }
151}
152
153impl IntProperty {
154    #[must_use]
155    pub const fn get_internal_index_const(self, value: &u8) -> usize {
156        if *value <= self.max {
157            (*value - self.min) as usize
158        } else {
159            0
160        }
161    }
162}
163
164#[derive(Debug, Clone)]
165pub struct EnumProperty<T: PropertyEnum + 'static> {
166    pub name: &'static str,
167    pub possible_values: &'static [T],
168}
169
170impl<T: PropertyEnum + 'static> DynProperty for EnumProperty<T> {
171    fn get_possible_values(&self) -> Box<[&str]> {
172        self.possible_values
173            .iter()
174            .map(PropertyEnum::as_str)
175            .collect()
176    }
177
178    fn get_name(&self) -> &'static str {
179        self.name
180    }
181}
182
183impl<T: PropertyEnum> EnumProperty<T> {
184    pub const fn new(name: &'static str, possible_values: &'static [T]) -> Self {
185        Self {
186            name,
187            possible_values,
188        }
189    }
190
191    #[must_use]
192    pub const fn value_count(&self) -> usize {
193        self.possible_values.len()
194    }
195}
196
197impl<T: PropertyEnum> Property<T> for EnumProperty<T> {
198    fn get_value(&self, value: &str) -> Option<T> {
199        self.possible_values
200            .iter()
201            .find(|v| v.as_str() == value)
202            .cloned()
203    }
204
205    fn get_possible_values(&self) -> Box<[T]> {
206        self.possible_values.into()
207    }
208
209    fn get_internal_index(&self, value: &T) -> usize {
210        self.possible_values
211            .iter()
212            .position(|v| v == value)
213            .unwrap()
214    }
215
216    fn value_from_index(&self, index: usize) -> T {
217        self.possible_values[index].clone()
218    }
219
220    fn as_dyn(&self) -> &dyn DynProperty {
221        self
222    }
223}
224
225impl<T: const PartialEq + PropertyEnum + 'static> EnumProperty<T> {
226    pub const fn get_internal_index_const(&self, value: &T) -> usize {
227        let mut i = 0;
228        while i < self.possible_values.len() {
229            if &self.possible_values[i] == value {
230                return i;
231            }
232            i += 1;
233        }
234        panic!("value not found in possible_values");
235    }
236}
237
238impl PropertyEnum for Direction {
239    fn as_str(&self) -> &str {
240        Direction::as_str(self)
241    }
242}
243
244// Additional enum types for properties
245#[derive(Clone, Debug)]
246#[derive_const(PartialEq)]
247pub enum FrontAndTop {
248    DownEast,
249    DownNorth,
250    DownSouth,
251    DownWest,
252    UpEast,
253    UpNorth,
254    UpSouth,
255    UpWest,
256    WestUp,
257    EastUp,
258    NorthUp,
259    SouthUp,
260}
261
262impl PropertyEnum for FrontAndTop {
263    fn as_str(&self) -> &str {
264        match self {
265            FrontAndTop::DownEast => "down_east",
266            FrontAndTop::DownNorth => "down_north",
267            FrontAndTop::DownSouth => "down_south",
268            FrontAndTop::DownWest => "down_west",
269            FrontAndTop::UpEast => "up_east",
270            FrontAndTop::UpNorth => "up_north",
271            FrontAndTop::UpSouth => "up_south",
272            FrontAndTop::UpWest => "up_west",
273            FrontAndTop::WestUp => "west_up",
274            FrontAndTop::EastUp => "east_up",
275            FrontAndTop::NorthUp => "north_up",
276            FrontAndTop::SouthUp => "south_up",
277        }
278    }
279}
280
281#[derive(Clone, Debug)]
282#[derive_const(PartialEq)]
283pub enum AttachFace {
284    Floor,
285    Wall,
286    Ceiling,
287}
288
289impl PropertyEnum for AttachFace {
290    fn as_str(&self) -> &str {
291        match self {
292            AttachFace::Floor => "floor",
293            AttachFace::Wall => "wall",
294            AttachFace::Ceiling => "ceiling",
295        }
296    }
297}
298
299#[derive(Clone, Debug)]
300#[derive_const(PartialEq)]
301pub enum BellAttachType {
302    Floor,
303    Ceiling,
304    SingleWall,
305    DoubleWall,
306}
307
308impl PropertyEnum for BellAttachType {
309    fn as_str(&self) -> &str {
310        match self {
311            BellAttachType::Floor => "floor",
312            BellAttachType::Ceiling => "ceiling",
313            BellAttachType::SingleWall => "single_wall",
314            BellAttachType::DoubleWall => "double_wall",
315        }
316    }
317}
318
319#[derive(Clone, Debug)]
320#[derive_const(PartialEq)]
321pub enum WallSide {
322    None,
323    Low,
324    Tall,
325}
326
327impl PropertyEnum for WallSide {
328    fn as_str(&self) -> &str {
329        match self {
330            WallSide::None => "none",
331            WallSide::Low => "low",
332            WallSide::Tall => "tall",
333        }
334    }
335}
336
337#[derive(Clone, Debug)]
338#[derive_const(PartialEq)]
339pub enum RedstoneSide {
340    Up,
341    Side,
342    None,
343}
344
345impl PropertyEnum for RedstoneSide {
346    fn as_str(&self) -> &str {
347        match self {
348            RedstoneSide::None => "none",
349            RedstoneSide::Side => "side",
350            RedstoneSide::Up => "up",
351        }
352    }
353}
354
355#[derive(Clone, Debug)]
356#[derive_const(PartialEq)]
357pub enum DoubleBlockHalf {
358    Upper,
359    Lower,
360}
361
362impl PropertyEnum for DoubleBlockHalf {
363    fn as_str(&self) -> &str {
364        match self {
365            DoubleBlockHalf::Upper => "upper",
366            DoubleBlockHalf::Lower => "lower",
367        }
368    }
369}
370
371#[derive(Clone, Debug)]
372#[derive_const(PartialEq)]
373pub enum Half {
374    Top,
375    Bottom,
376}
377
378impl PropertyEnum for Half {
379    fn as_str(&self) -> &str {
380        match self {
381            Half::Top => "top",
382            Half::Bottom => "bottom",
383        }
384    }
385}
386
387#[derive(Clone, Debug)]
388#[derive_const(PartialEq)]
389pub enum SideChainPart {
390    Unconnected,
391    Right,
392    Center,
393    Left,
394}
395
396impl PropertyEnum for SideChainPart {
397    fn as_str(&self) -> &str {
398        match self {
399            SideChainPart::Unconnected => "unconnected",
400            SideChainPart::Right => "right",
401            SideChainPart::Center => "center",
402            SideChainPart::Left => "left",
403        }
404    }
405}
406
407#[derive(Clone, Debug)]
408#[derive_const(PartialEq)]
409pub enum RailShape {
410    NorthSouth,
411    EastWest,
412    AscendingEast,
413    AscendingWest,
414    AscendingNorth,
415    AscendingSouth,
416    SouthEast,
417    SouthWest,
418    NorthWest,
419    NorthEast,
420}
421
422impl PropertyEnum for RailShape {
423    fn as_str(&self) -> &str {
424        match self {
425            RailShape::NorthSouth => "north_south",
426            RailShape::EastWest => "east_west",
427            RailShape::AscendingEast => "ascending_east",
428            RailShape::AscendingWest => "ascending_west",
429            RailShape::AscendingNorth => "ascending_north",
430            RailShape::AscendingSouth => "ascending_south",
431            RailShape::SouthEast => "south_east",
432            RailShape::SouthWest => "south_west",
433            RailShape::NorthWest => "north_west",
434            RailShape::NorthEast => "north_east",
435        }
436    }
437}
438
439#[derive(Clone, Debug)]
440#[derive_const(PartialEq)]
441pub enum BedPart {
442    Head,
443    Foot,
444}
445
446impl PropertyEnum for BedPart {
447    fn as_str(&self) -> &str {
448        match self {
449            BedPart::Head => "head",
450            BedPart::Foot => "foot",
451        }
452    }
453}
454
455#[derive(Clone, Debug)]
456#[derive_const(PartialEq)]
457pub enum ChestType {
458    Single,
459    Left,
460    Right,
461}
462
463impl PropertyEnum for ChestType {
464    fn as_str(&self) -> &str {
465        match self {
466            ChestType::Single => "single",
467            ChestType::Left => "left",
468            ChestType::Right => "right",
469        }
470    }
471}
472
473#[derive(Clone, Debug)]
474#[derive_const(PartialEq)]
475pub enum ComparatorMode {
476    Compare,
477    Subtract,
478}
479
480impl PropertyEnum for ComparatorMode {
481    fn as_str(&self) -> &str {
482        match self {
483            ComparatorMode::Compare => "compare",
484            ComparatorMode::Subtract => "subtract",
485        }
486    }
487}
488
489#[derive(Clone, Debug)]
490#[derive_const(PartialEq)]
491pub enum DoorHingeSide {
492    Left,
493    Right,
494}
495
496impl PropertyEnum for DoorHingeSide {
497    fn as_str(&self) -> &str {
498        match self {
499            DoorHingeSide::Left => "left",
500            DoorHingeSide::Right => "right",
501        }
502    }
503}
504
505#[derive(Clone, Debug)]
506#[derive_const(PartialEq)]
507pub enum NoteBlockInstrument {
508    Harp,
509    Basedrum,
510    Snare,
511    Hat,
512    Bass,
513    Flute,
514    Bell,
515    Guitar,
516    Chime,
517    Xylophone,
518    IronXylophone,
519    CowBell,
520    Didgeridoo,
521    Bit,
522    Banjo,
523    Pling,
524    Trumpet,
525    TrumpetExposed,
526    TrumpetOxidized,
527    TrumpetWeathered,
528    Zombie,
529    Skeleton,
530    Creeper,
531    Dragon,
532    WitherSkeleton,
533    Piglin,
534    CustomHead,
535}
536
537impl PropertyEnum for NoteBlockInstrument {
538    fn as_str(&self) -> &str {
539        match self {
540            NoteBlockInstrument::Harp => "harp",
541            NoteBlockInstrument::Basedrum => "basedrum",
542            NoteBlockInstrument::Snare => "snare",
543            NoteBlockInstrument::Hat => "hat",
544            NoteBlockInstrument::Bass => "bass",
545            NoteBlockInstrument::Flute => "flute",
546            NoteBlockInstrument::Bell => "bell",
547            NoteBlockInstrument::Guitar => "guitar",
548            NoteBlockInstrument::Chime => "chime",
549            NoteBlockInstrument::Xylophone => "xylophone",
550            NoteBlockInstrument::IronXylophone => "iron_xylophone",
551            NoteBlockInstrument::CowBell => "cow_bell",
552            NoteBlockInstrument::Didgeridoo => "didgeridoo",
553            NoteBlockInstrument::Bit => "bit",
554            NoteBlockInstrument::Banjo => "banjo",
555            NoteBlockInstrument::Pling => "pling",
556            NoteBlockInstrument::Trumpet => "trumpet",
557            NoteBlockInstrument::TrumpetExposed => "trumpet_exposed",
558            NoteBlockInstrument::TrumpetWeathered => "trumpet_weathered",
559            NoteBlockInstrument::TrumpetOxidized => "trumpet_oxidized",
560            NoteBlockInstrument::Zombie => "zombie",
561            NoteBlockInstrument::Skeleton => "skeleton",
562            NoteBlockInstrument::Creeper => "creeper",
563            NoteBlockInstrument::Dragon => "dragon",
564            NoteBlockInstrument::WitherSkeleton => "wither_skeleton",
565            NoteBlockInstrument::Piglin => "piglin",
566            NoteBlockInstrument::CustomHead => "custom_head",
567        }
568    }
569}
570
571#[derive(Clone, Debug)]
572#[derive_const(PartialEq)]
573pub enum PistonType {
574    Normal,
575    Sticky,
576}
577
578impl PropertyEnum for PistonType {
579    fn as_str(&self) -> &str {
580        match self {
581            PistonType::Normal => "normal",
582            PistonType::Sticky => "sticky",
583        }
584    }
585}
586
587#[derive(Clone, Debug)]
588#[derive_const(PartialEq)]
589pub enum SlabType {
590    Bottom,
591    Top,
592    Double,
593}
594
595impl PropertyEnum for SlabType {
596    fn as_str(&self) -> &str {
597        match self {
598            SlabType::Bottom => "bottom",
599            SlabType::Top => "top",
600            SlabType::Double => "double",
601        }
602    }
603}
604
605#[derive(Clone, Debug)]
606#[derive_const(PartialEq)]
607pub enum StairsShape {
608    Straight,
609    InnerLeft,
610    InnerRight,
611    OuterLeft,
612    OuterRight,
613}
614
615impl PropertyEnum for StairsShape {
616    fn as_str(&self) -> &str {
617        match self {
618            StairsShape::Straight => "straight",
619            StairsShape::InnerLeft => "inner_left",
620            StairsShape::InnerRight => "inner_right",
621            StairsShape::OuterLeft => "outer_left",
622            StairsShape::OuterRight => "outer_right",
623        }
624    }
625}
626
627#[derive(Clone, Debug)]
628#[derive_const(PartialEq)]
629pub enum StructureMode {
630    Save,
631    Load,
632    Corner,
633    Data,
634}
635
636impl PropertyEnum for StructureMode {
637    fn as_str(&self) -> &str {
638        match self {
639            StructureMode::Save => "save",
640            StructureMode::Load => "load",
641            StructureMode::Corner => "corner",
642            StructureMode::Data => "data",
643        }
644    }
645}
646
647#[derive(Clone, Debug)]
648#[derive_const(PartialEq)]
649pub enum BambooLeaves {
650    None,
651    Small,
652    Large,
653}
654
655impl PropertyEnum for BambooLeaves {
656    fn as_str(&self) -> &str {
657        match self {
658            BambooLeaves::None => "none",
659            BambooLeaves::Small => "small",
660            BambooLeaves::Large => "large",
661        }
662    }
663}
664
665#[derive(Clone, Debug)]
666#[derive_const(PartialEq)]
667pub enum Tilt {
668    None,
669    Unstable,
670    Partial,
671    Full,
672}
673
674impl PropertyEnum for Tilt {
675    fn as_str(&self) -> &str {
676        match self {
677            Tilt::None => "none",
678            Tilt::Unstable => "unstable",
679            Tilt::Partial => "partial",
680            Tilt::Full => "full",
681        }
682    }
683}
684
685#[derive(Clone, Debug)]
686#[derive_const(PartialEq)]
687pub enum DripstoneThickness {
688    TipMerge,
689    Tip,
690    Frustum,
691    Middle,
692    Base,
693}
694
695impl PropertyEnum for DripstoneThickness {
696    fn as_str(&self) -> &str {
697        match self {
698            DripstoneThickness::TipMerge => "tip_merge",
699            DripstoneThickness::Tip => "tip",
700            DripstoneThickness::Frustum => "frustum",
701            DripstoneThickness::Middle => "middle",
702            DripstoneThickness::Base => "base",
703        }
704    }
705}
706
707#[derive(Clone, Debug)]
708#[derive_const(PartialEq)]
709pub enum SculkSensorPhase {
710    Inactive,
711    Active,
712    Cooldown,
713}
714
715impl PropertyEnum for SculkSensorPhase {
716    fn as_str(&self) -> &str {
717        match self {
718            SculkSensorPhase::Inactive => "inactive",
719            SculkSensorPhase::Active => "active",
720            SculkSensorPhase::Cooldown => "cooldown",
721        }
722    }
723}
724
725#[derive(Clone, Debug)]
726#[derive_const(PartialEq)]
727pub enum TrialSpawnerState {
728    Inactive,
729    WaitingForPlayers,
730    Active,
731    WaitingForRewardEjection,
732    EjectingReward,
733    Cooldown,
734}
735
736impl PropertyEnum for TrialSpawnerState {
737    fn as_str(&self) -> &str {
738        match self {
739            TrialSpawnerState::Inactive => "inactive",
740            TrialSpawnerState::WaitingForPlayers => "waiting_for_players",
741            TrialSpawnerState::Active => "active",
742            TrialSpawnerState::WaitingForRewardEjection => "waiting_for_reward_ejection",
743            TrialSpawnerState::EjectingReward => "ejecting_reward",
744            TrialSpawnerState::Cooldown => "cooldown",
745        }
746    }
747}
748
749#[derive(Clone, Debug)]
750#[derive_const(PartialEq)]
751pub enum VaultState {
752    Inactive,
753    Active,
754    Unlocking,
755    Ejecting,
756}
757
758impl PropertyEnum for VaultState {
759    fn as_str(&self) -> &str {
760        match self {
761            VaultState::Inactive => "inactive",
762            VaultState::Active => "active",
763            VaultState::Unlocking => "unlocking",
764            VaultState::Ejecting => "ejecting",
765        }
766    }
767}
768
769#[derive(Clone, Debug)]
770#[derive_const(PartialEq)]
771pub enum CreakingHeartState {
772    Uprooted,
773    Dormant,
774    Awake,
775}
776
777impl PropertyEnum for CreakingHeartState {
778    fn as_str(&self) -> &str {
779        match self {
780            CreakingHeartState::Uprooted => "uprooted",
781            CreakingHeartState::Dormant => "dormant",
782            CreakingHeartState::Awake => "awake",
783        }
784    }
785}
786
787#[derive(Clone, Debug)]
788#[derive_const(PartialEq)]
789pub enum TestBlockMode {
790    Start,
791    Log,
792    Fail,
793    Accept,
794}
795
796impl PropertyEnum for TestBlockMode {
797    fn as_str(&self) -> &str {
798        match self {
799            TestBlockMode::Start => "start",
800            TestBlockMode::Log => "log",
801            TestBlockMode::Fail => "fail",
802            TestBlockMode::Accept => "accept",
803        }
804    }
805}
806
807#[derive(Clone, Debug)]
808#[derive_const(PartialEq)]
809pub enum Pose {
810    Standing,
811    Sitting,
812    Running,
813    Star,
814}
815
816impl PropertyEnum for Pose {
817    fn as_str(&self) -> &str {
818        match self {
819            Pose::Standing => "standing",
820            Pose::Sitting => "sitting",
821            Pose::Running => "running",
822            Pose::Star => "star",
823        }
824    }
825}
826
827impl PropertyEnum for Axis {
828    fn as_str(&self) -> &str {
829        self.as_str()
830    }
831}
832
833pub struct BlockStateProperties;
834
835//TODO: These got quickly implemented so the ordering might be off. Fix in the future.
836impl BlockStateProperties {
837    pub const ATTACHED: BoolProperty = BoolProperty::new("attached");
838    pub const BERRIES: BoolProperty = BoolProperty::new("berries");
839    pub const BLOOM: BoolProperty = BoolProperty::new("bloom");
840    pub const BOTTOM: BoolProperty = BoolProperty::new("bottom");
841    pub const CAN_SUMMON: BoolProperty = BoolProperty::new("can_summon");
842    pub const CONDITIONAL: BoolProperty = BoolProperty::new("conditional");
843    pub const DISARMED: BoolProperty = BoolProperty::new("disarmed");
844    pub const DRAG: BoolProperty = BoolProperty::new("drag");
845    pub const ENABLED: BoolProperty = BoolProperty::new("enabled");
846    pub const EXTENDED: BoolProperty = BoolProperty::new("extended");
847    pub const EYE: BoolProperty = BoolProperty::new("eye");
848    pub const FALLING: BoolProperty = BoolProperty::new("falling");
849    pub const HANGING: BoolProperty = BoolProperty::new("hanging");
850    pub const HAS_BOTTLE_0: BoolProperty = BoolProperty::new("has_bottle_0");
851    pub const HAS_BOTTLE_1: BoolProperty = BoolProperty::new("has_bottle_1");
852    pub const HAS_BOTTLE_2: BoolProperty = BoolProperty::new("has_bottle_2");
853    pub const HAS_RECORD: BoolProperty = BoolProperty::new("has_record");
854    pub const HAS_BOOK: BoolProperty = BoolProperty::new("has_book");
855    pub const INVERTED: BoolProperty = BoolProperty::new("inverted");
856    pub const IN_WALL: BoolProperty = BoolProperty::new("in_wall");
857    pub const LIT: BoolProperty = BoolProperty::new("lit");
858    pub const LOCKED: BoolProperty = BoolProperty::new("locked");
859    pub const NATURAL: BoolProperty = BoolProperty::new("natural");
860    pub const OCCUPIED: BoolProperty = BoolProperty::new("occupied");
861    pub const OPEN: BoolProperty = BoolProperty::new("open");
862    pub const PERSISTENT: BoolProperty = BoolProperty::new("persistent");
863    pub const POWERED: BoolProperty = BoolProperty::new("powered");
864    pub const SHORT: BoolProperty = BoolProperty::new("short");
865    pub const SHRIEKING: BoolProperty = BoolProperty::new("shrieking");
866    pub const SIGNAL_FIRE: BoolProperty = BoolProperty::new("signal_fire");
867    pub const SNOWY: BoolProperty = BoolProperty::new("snowy");
868    pub const TIP: BoolProperty = BoolProperty::new("tip");
869    pub const TRIGGERED: BoolProperty = BoolProperty::new("triggered");
870    pub const UNSTABLE: BoolProperty = BoolProperty::new("unstable");
871    pub const WATERLOGGED: BoolProperty = BoolProperty::new("waterlogged");
872    pub const HORIZONTAL_AXIS: EnumProperty<Axis> = EnumProperty::new("axis", &[Axis::X, Axis::Z]);
873    pub const AXIS: EnumProperty<Axis> = EnumProperty::new("axis", &[Axis::X, Axis::Y, Axis::Z]);
874    pub const UP: BoolProperty = BoolProperty::new("up");
875    pub const DOWN: BoolProperty = BoolProperty::new("down");
876    pub const NORTH: BoolProperty = BoolProperty::new("north");
877    pub const EAST: BoolProperty = BoolProperty::new("east");
878    pub const SOUTH: BoolProperty = BoolProperty::new("south");
879    pub const WEST: BoolProperty = BoolProperty::new("west");
880    pub const FACING: EnumProperty<Direction> = EnumProperty::new(
881        "facing",
882        &[
883            Direction::North,
884            Direction::East,
885            Direction::South,
886            Direction::West,
887            Direction::Up,
888            Direction::Down,
889        ],
890    );
891    pub const FACING_HOPPER: EnumProperty<Direction> = EnumProperty::new(
892        "facing",
893        &[
894            Direction::Down,
895            Direction::North,
896            Direction::South,
897            Direction::West,
898            Direction::East,
899        ],
900    );
901    pub const HORIZONTAL_FACING: EnumProperty<Direction> = EnumProperty::new(
902        "facing",
903        &[
904            Direction::North,
905            Direction::South,
906            Direction::West,
907            Direction::East,
908        ],
909    );
910    pub const FLOWER_AMOUNT: IntProperty = IntProperty::new("flower_amount", 1, 4);
911    pub const SEGMENT_AMOUNT: IntProperty = IntProperty::new("segment_amount", 1, 4);
912
913    // Additional enum types needed for properties
914    pub const ORIENTATION: EnumProperty<FrontAndTop> = EnumProperty::new(
915        "orientation",
916        &[
917            FrontAndTop::DownEast,
918            FrontAndTop::DownNorth,
919            FrontAndTop::DownSouth,
920            FrontAndTop::DownWest,
921            FrontAndTop::UpEast,
922            FrontAndTop::UpNorth,
923            FrontAndTop::UpSouth,
924            FrontAndTop::UpWest,
925            FrontAndTop::WestUp,
926            FrontAndTop::EastUp,
927            FrontAndTop::NorthUp,
928            FrontAndTop::SouthUp,
929        ],
930    );
931    pub const ATTACH_FACE: EnumProperty<AttachFace> = EnumProperty::new(
932        "face",
933        &[AttachFace::Floor, AttachFace::Wall, AttachFace::Ceiling],
934    );
935    pub const BELL_ATTACHMENT: EnumProperty<BellAttachType> = EnumProperty::new(
936        "attachment",
937        &[
938            BellAttachType::Floor,
939            BellAttachType::Ceiling,
940            BellAttachType::SingleWall,
941            BellAttachType::DoubleWall,
942        ],
943    );
944    pub const EAST_WALL: EnumProperty<WallSide> =
945        EnumProperty::new("east", &[WallSide::None, WallSide::Low, WallSide::Tall]);
946    pub const NORTH_WALL: EnumProperty<WallSide> =
947        EnumProperty::new("north", &[WallSide::None, WallSide::Low, WallSide::Tall]);
948    pub const SOUTH_WALL: EnumProperty<WallSide> =
949        EnumProperty::new("south", &[WallSide::None, WallSide::Low, WallSide::Tall]);
950    pub const WEST_WALL: EnumProperty<WallSide> =
951        EnumProperty::new("west", &[WallSide::None, WallSide::Low, WallSide::Tall]);
952    pub const EAST_REDSTONE: EnumProperty<RedstoneSide> = EnumProperty::new(
953        "east",
954        &[RedstoneSide::Up, RedstoneSide::Side, RedstoneSide::None],
955    );
956    pub const NORTH_REDSTONE: EnumProperty<RedstoneSide> = EnumProperty::new(
957        "north",
958        &[RedstoneSide::Up, RedstoneSide::Side, RedstoneSide::None],
959    );
960    pub const SOUTH_REDSTONE: EnumProperty<RedstoneSide> = EnumProperty::new(
961        "south",
962        &[RedstoneSide::Up, RedstoneSide::Side, RedstoneSide::None],
963    );
964    pub const WEST_REDSTONE: EnumProperty<RedstoneSide> = EnumProperty::new(
965        "west",
966        &[RedstoneSide::Up, RedstoneSide::Side, RedstoneSide::None],
967    );
968    pub const DOUBLE_BLOCK_HALF: EnumProperty<DoubleBlockHalf> =
969        EnumProperty::new("half", &[DoubleBlockHalf::Upper, DoubleBlockHalf::Lower]);
970    pub const HALF: EnumProperty<Half> = EnumProperty::new("half", &[Half::Top, Half::Bottom]);
971    pub const SIDE_CHAIN_PART: EnumProperty<SideChainPart> = EnumProperty::new(
972        "side_chain",
973        &[
974            SideChainPart::Unconnected,
975            SideChainPart::Right,
976            SideChainPart::Center,
977            SideChainPart::Left,
978        ],
979    );
980    pub const RAIL_SHAPE: EnumProperty<RailShape> = EnumProperty::new(
981        "shape",
982        &[
983            RailShape::NorthSouth,
984            RailShape::EastWest,
985            RailShape::AscendingEast,
986            RailShape::AscendingWest,
987            RailShape::AscendingNorth,
988            RailShape::AscendingSouth,
989            RailShape::SouthEast,
990            RailShape::SouthWest,
991            RailShape::NorthWest,
992            RailShape::NorthEast,
993        ],
994    );
995    pub const RAIL_SHAPE_STRAIGHT: EnumProperty<RailShape> = EnumProperty::new(
996        "shape",
997        &[
998            RailShape::NorthSouth,
999            RailShape::EastWest,
1000            RailShape::AscendingEast,
1001            RailShape::AscendingWest,
1002            RailShape::AscendingNorth,
1003            RailShape::AscendingSouth,
1004        ],
1005    );
1006
1007    // Age properties
1008    pub const AGE_1: IntProperty = IntProperty::new("age", 0, 1);
1009    pub const AGE_2: IntProperty = IntProperty::new("age", 0, 2);
1010    pub const AGE_3: IntProperty = IntProperty::new("age", 0, 3);
1011    pub const AGE_4: IntProperty = IntProperty::new("age", 0, 4);
1012    pub const AGE_5: IntProperty = IntProperty::new("age", 0, 5);
1013    pub const AGE_7: IntProperty = IntProperty::new("age", 0, 7);
1014    pub const AGE_15: IntProperty = IntProperty::new("age", 0, 15);
1015    pub const AGE_25: IntProperty = IntProperty::new("age", 0, 25);
1016
1017    // Other integer properties
1018    pub const BITES: IntProperty = IntProperty::new("bites", 0, 6);
1019    pub const CANDLES: IntProperty = IntProperty::new("candles", 1, 4);
1020    pub const DELAY: IntProperty = IntProperty::new("delay", 1, 4);
1021    pub const DISTANCE: IntProperty = IntProperty::new("distance", 1, 7);
1022    pub const EGGS: IntProperty = IntProperty::new("eggs", 1, 4);
1023    pub const HATCH: IntProperty = IntProperty::new("hatch", 0, 2);
1024    pub const LAYERS: IntProperty = IntProperty::new("layers", 1, 8);
1025    pub const LEVEL_CAULDRON: IntProperty = IntProperty::new("level", 1, 3);
1026    pub const LEVEL_COMPOSTER: IntProperty = IntProperty::new("level", 0, 8);
1027    pub const LEVEL_FLOWING: IntProperty = IntProperty::new("level", 1, 8);
1028    pub const LEVEL_HONEY: IntProperty = IntProperty::new("honey_level", 0, 5);
1029    pub const LEVEL: IntProperty = IntProperty::new("level", 0, 15);
1030    pub const MOISTURE: IntProperty = IntProperty::new("moisture", 0, 7);
1031    pub const NOTE: IntProperty = IntProperty::new("note", 0, 24);
1032    pub const PICKLES: IntProperty = IntProperty::new("pickles", 1, 4);
1033    pub const POWER: IntProperty = IntProperty::new("power", 0, 15);
1034    pub const STAGE: IntProperty = IntProperty::new("stage", 0, 1);
1035    pub const STABILITY_DISTANCE: IntProperty = IntProperty::new("distance", 0, 7);
1036    pub const RESPAWN_ANCHOR_CHARGES: IntProperty = IntProperty::new("charges", 0, 4);
1037    pub const DRIED_GHAST_HYDRATION_LEVELS: IntProperty = IntProperty::new("hydration", 0, 3);
1038    pub const ROTATION_16: IntProperty = IntProperty::new("rotation", 0, 15);
1039    pub const DUSTED: IntProperty = IntProperty::new("dusted", 0, 3);
1040
1041    // Enum properties
1042    pub const BED_PART: EnumProperty<BedPart> =
1043        EnumProperty::new("part", &[BedPart::Head, BedPart::Foot]);
1044    pub const CHEST_TYPE: EnumProperty<ChestType> = EnumProperty::new(
1045        "type",
1046        &[ChestType::Single, ChestType::Left, ChestType::Right],
1047    );
1048    pub const MODE_COMPARATOR: EnumProperty<ComparatorMode> =
1049        EnumProperty::new("mode", &[ComparatorMode::Compare, ComparatorMode::Subtract]);
1050    pub const DOOR_HINGE: EnumProperty<DoorHingeSide> =
1051        EnumProperty::new("hinge", &[DoorHingeSide::Left, DoorHingeSide::Right]);
1052    pub const NOTEBLOCK_INSTRUMENT: EnumProperty<NoteBlockInstrument> = EnumProperty::new(
1053        "instrument",
1054        &[
1055            NoteBlockInstrument::Harp,
1056            NoteBlockInstrument::Basedrum,
1057            NoteBlockInstrument::Snare,
1058            NoteBlockInstrument::Hat,
1059            NoteBlockInstrument::Bass,
1060            NoteBlockInstrument::Flute,
1061            NoteBlockInstrument::Bell,
1062            NoteBlockInstrument::Guitar,
1063            NoteBlockInstrument::Chime,
1064            NoteBlockInstrument::Xylophone,
1065            NoteBlockInstrument::IronXylophone,
1066            NoteBlockInstrument::CowBell,
1067            NoteBlockInstrument::Didgeridoo,
1068            NoteBlockInstrument::Bit,
1069            NoteBlockInstrument::Banjo,
1070            NoteBlockInstrument::Pling,
1071            NoteBlockInstrument::Trumpet,
1072            NoteBlockInstrument::TrumpetExposed,
1073            NoteBlockInstrument::TrumpetOxidized,
1074            NoteBlockInstrument::TrumpetWeathered,
1075            NoteBlockInstrument::Zombie,
1076            NoteBlockInstrument::Skeleton,
1077            NoteBlockInstrument::Creeper,
1078            NoteBlockInstrument::Dragon,
1079            NoteBlockInstrument::WitherSkeleton,
1080            NoteBlockInstrument::Piglin,
1081            NoteBlockInstrument::CustomHead,
1082        ],
1083    );
1084    pub const PISTON_TYPE: EnumProperty<PistonType> =
1085        EnumProperty::new("type", &[PistonType::Normal, PistonType::Sticky]);
1086    pub const SLAB_TYPE: EnumProperty<SlabType> =
1087        EnumProperty::new("type", &[SlabType::Top, SlabType::Bottom, SlabType::Double]);
1088    pub const STAIRS_SHAPE: EnumProperty<StairsShape> = EnumProperty::new(
1089        "shape",
1090        &[
1091            StairsShape::Straight,
1092            StairsShape::InnerLeft,
1093            StairsShape::InnerRight,
1094            StairsShape::OuterLeft,
1095            StairsShape::OuterRight,
1096        ],
1097    );
1098    pub const STRUCTUREBLOCK_MODE: EnumProperty<StructureMode> = EnumProperty::new(
1099        "mode",
1100        &[
1101            StructureMode::Save,
1102            StructureMode::Load,
1103            StructureMode::Corner,
1104            StructureMode::Data,
1105        ],
1106    );
1107    pub const BAMBOO_LEAVES: EnumProperty<BambooLeaves> = EnumProperty::new(
1108        "leaves",
1109        &[BambooLeaves::None, BambooLeaves::Small, BambooLeaves::Large],
1110    );
1111    pub const TILT: EnumProperty<Tilt> = EnumProperty::new(
1112        "tilt",
1113        &[Tilt::None, Tilt::Unstable, Tilt::Partial, Tilt::Full],
1114    );
1115    pub const VERTICAL_DIRECTION: EnumProperty<Direction> =
1116        EnumProperty::new("vertical_direction", &[Direction::Up, Direction::Down]);
1117    pub const DRIPSTONE_THICKNESS: EnumProperty<DripstoneThickness> = EnumProperty::new(
1118        "thickness",
1119        &[
1120            DripstoneThickness::TipMerge,
1121            DripstoneThickness::Tip,
1122            DripstoneThickness::Frustum,
1123            DripstoneThickness::Middle,
1124            DripstoneThickness::Base,
1125        ],
1126    );
1127    pub const SCULK_SENSOR_PHASE: EnumProperty<SculkSensorPhase> = EnumProperty::new(
1128        "sculk_sensor_phase",
1129        &[
1130            SculkSensorPhase::Inactive,
1131            SculkSensorPhase::Active,
1132            SculkSensorPhase::Cooldown,
1133        ],
1134    );
1135    pub const TRIAL_SPAWNER_STATE: EnumProperty<TrialSpawnerState> = EnumProperty::new(
1136        "trial_spawner_state",
1137        &[
1138            TrialSpawnerState::Inactive,
1139            TrialSpawnerState::WaitingForPlayers,
1140            TrialSpawnerState::Active,
1141            TrialSpawnerState::WaitingForRewardEjection,
1142            TrialSpawnerState::EjectingReward,
1143            TrialSpawnerState::Cooldown,
1144        ],
1145    );
1146    pub const VAULT_STATE: EnumProperty<VaultState> = EnumProperty::new(
1147        "vault_state",
1148        &[
1149            VaultState::Inactive,
1150            VaultState::Active,
1151            VaultState::Unlocking,
1152            VaultState::Ejecting,
1153        ],
1154    );
1155    pub const CREAKING_HEART_STATE: EnumProperty<CreakingHeartState> = EnumProperty::new(
1156        "creaking_heart_state",
1157        &[
1158            CreakingHeartState::Uprooted,
1159            CreakingHeartState::Dormant,
1160            CreakingHeartState::Awake,
1161        ],
1162    );
1163    pub const TEST_BLOCK_MODE: EnumProperty<TestBlockMode> = EnumProperty::new(
1164        "mode",
1165        &[
1166            TestBlockMode::Start,
1167            TestBlockMode::Log,
1168            TestBlockMode::Fail,
1169            TestBlockMode::Accept,
1170        ],
1171    );
1172    pub const COPPER_GOLEM_POSE: EnumProperty<Pose> = EnumProperty::new(
1173        "copper_golem_pose",
1174        &[Pose::Standing, Pose::Sitting, Pose::Running, Pose::Star],
1175    );
1176
1177    // Additional boolean properties
1178    pub const SLOT_0_OCCUPIED: BoolProperty = BoolProperty::new("slot_0_occupied");
1179    pub const SLOT_1_OCCUPIED: BoolProperty = BoolProperty::new("slot_1_occupied");
1180    pub const SLOT_2_OCCUPIED: BoolProperty = BoolProperty::new("slot_2_occupied");
1181    pub const SLOT_3_OCCUPIED: BoolProperty = BoolProperty::new("slot_3_occupied");
1182    pub const SLOT_4_OCCUPIED: BoolProperty = BoolProperty::new("slot_4_occupied");
1183    pub const SLOT_5_OCCUPIED: BoolProperty = BoolProperty::new("slot_5_occupied");
1184    pub const CRACKED: BoolProperty = BoolProperty::new("cracked");
1185    pub const CRAFTING: BoolProperty = BoolProperty::new("crafting");
1186    pub const OMINOUS: BoolProperty = BoolProperty::new("ominous");
1187    pub const MAP: BoolProperty = BoolProperty::new("map");
1188}