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