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, Copy, Debug)]
322#[derive_const(PartialEq, Eq)]
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, Copy, Debug)]
358#[derive_const(PartialEq, Eq)]
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, Copy, Debug)]
376#[derive_const(PartialEq, Eq)]
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, Copy, Debug)]
396#[derive_const(PartialEq, Eq)]
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, Eq)]
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, Copy, Debug)]
432#[derive_const(PartialEq, Eq)]
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, Copy, Debug)]
448#[derive_const(PartialEq, Eq)]
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, Copy, Debug)]
464#[derive_const(PartialEq, Eq)]
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, Copy, Debug)]
527#[derive_const(PartialEq, Eq)]
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, Copy, Debug)]
543#[derive_const(PartialEq, Eq)]
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, Copy, Debug)]
561#[derive_const(PartialEq, Eq)]
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, Copy, Debug)]
577#[derive_const(PartialEq, Eq)]
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, Eq)]
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]
626 pub const fn is_tunable(&self) -> bool {
627 !matches!(
628 self,
629 Self::Zombie
630 | Self::Skeleton
631 | Self::Creeper
632 | Self::Dragon
633 | Self::WitherSkeleton
634 | Self::Piglin
635 | Self::CustomHead
636 )
637 }
638
639 #[must_use]
640 pub const fn has_custom_sound(&self) -> bool {
641 matches!(self, Self::CustomHead)
642 }
643
644 #[must_use]
645 pub const fn works_above_note_block(&self) -> bool {
646 !self.is_tunable()
647 }
648}
649
650impl PropertyEnum for NoteBlockInstrument {
651 fn as_str(&self) -> &str {
652 match self {
653 NoteBlockInstrument::Harp => "harp",
654 NoteBlockInstrument::Basedrum => "basedrum",
655 NoteBlockInstrument::Snare => "snare",
656 NoteBlockInstrument::Hat => "hat",
657 NoteBlockInstrument::Bass => "bass",
658 NoteBlockInstrument::Flute => "flute",
659 NoteBlockInstrument::Bell => "bell",
660 NoteBlockInstrument::Guitar => "guitar",
661 NoteBlockInstrument::Chime => "chime",
662 NoteBlockInstrument::Xylophone => "xylophone",
663 NoteBlockInstrument::IronXylophone => "iron_xylophone",
664 NoteBlockInstrument::CowBell => "cow_bell",
665 NoteBlockInstrument::Didgeridoo => "didgeridoo",
666 NoteBlockInstrument::Bit => "bit",
667 NoteBlockInstrument::Banjo => "banjo",
668 NoteBlockInstrument::Pling => "pling",
669 NoteBlockInstrument::Trumpet => "trumpet",
670 NoteBlockInstrument::TrumpetExposed => "trumpet_exposed",
671 NoteBlockInstrument::TrumpetWeathered => "trumpet_weathered",
672 NoteBlockInstrument::TrumpetOxidized => "trumpet_oxidized",
673 NoteBlockInstrument::Zombie => "zombie",
674 NoteBlockInstrument::Skeleton => "skeleton",
675 NoteBlockInstrument::Creeper => "creeper",
676 NoteBlockInstrument::Dragon => "dragon",
677 NoteBlockInstrument::WitherSkeleton => "wither_skeleton",
678 NoteBlockInstrument::Piglin => "piglin",
679 NoteBlockInstrument::CustomHead => "custom_head",
680 }
681 }
682}
683
684#[derive(Clone, Copy, Debug)]
685#[derive_const(PartialEq, Eq)]
686pub enum PistonType {
687 Normal,
688 Sticky,
689}
690
691impl PropertyEnum for PistonType {
692 fn as_str(&self) -> &str {
693 match self {
694 PistonType::Normal => "normal",
695 PistonType::Sticky => "sticky",
696 }
697 }
698}
699
700#[derive(Clone, Copy, Debug)]
701#[derive_const(PartialEq, Eq)]
702pub enum SlabType {
703 Bottom,
704 Top,
705 Double,
706}
707
708impl PropertyEnum for SlabType {
709 fn as_str(&self) -> &str {
710 match self {
711 SlabType::Bottom => "bottom",
712 SlabType::Top => "top",
713 SlabType::Double => "double",
714 }
715 }
716}
717
718#[derive(Clone, Copy, Debug)]
719#[derive_const(PartialEq, Eq)]
720pub enum StairsShape {
721 Straight,
722 InnerLeft,
723 InnerRight,
724 OuterLeft,
725 OuterRight,
726}
727
728impl PropertyEnum for StairsShape {
729 fn as_str(&self) -> &str {
730 match self {
731 StairsShape::Straight => "straight",
732 StairsShape::InnerLeft => "inner_left",
733 StairsShape::InnerRight => "inner_right",
734 StairsShape::OuterLeft => "outer_left",
735 StairsShape::OuterRight => "outer_right",
736 }
737 }
738}
739
740#[derive(Clone, Copy, Debug)]
741#[derive_const(PartialEq, Eq)]
742pub enum StructureMode {
743 Save,
744 Load,
745 Corner,
746 Data,
747}
748
749impl PropertyEnum for StructureMode {
750 fn as_str(&self) -> &str {
751 match self {
752 StructureMode::Save => "save",
753 StructureMode::Load => "load",
754 StructureMode::Corner => "corner",
755 StructureMode::Data => "data",
756 }
757 }
758}
759
760#[derive(Clone, Copy, Debug)]
761#[derive_const(PartialEq, Eq)]
762pub enum BambooLeaves {
763 None,
764 Small,
765 Large,
766}
767
768impl PropertyEnum for BambooLeaves {
769 fn as_str(&self) -> &str {
770 match self {
771 BambooLeaves::None => "none",
772 BambooLeaves::Small => "small",
773 BambooLeaves::Large => "large",
774 }
775 }
776}
777
778#[derive(Clone, Copy, Debug)]
779#[derive_const(PartialEq, Eq)]
780pub enum Tilt {
781 None,
782 Unstable,
783 Partial,
784 Full,
785}
786
787impl PropertyEnum for Tilt {
788 fn as_str(&self) -> &str {
789 match self {
790 Tilt::None => "none",
791 Tilt::Unstable => "unstable",
792 Tilt::Partial => "partial",
793 Tilt::Full => "full",
794 }
795 }
796}
797
798#[derive(Clone, Copy, Debug)]
799#[derive_const(PartialEq, Eq)]
800pub enum DripstoneThickness {
801 TipMerge,
802 Tip,
803 Frustum,
804 Middle,
805 Base,
806}
807
808impl PropertyEnum for DripstoneThickness {
809 fn as_str(&self) -> &str {
810 match self {
811 DripstoneThickness::TipMerge => "tip_merge",
812 DripstoneThickness::Tip => "tip",
813 DripstoneThickness::Frustum => "frustum",
814 DripstoneThickness::Middle => "middle",
815 DripstoneThickness::Base => "base",
816 }
817 }
818}
819
820#[derive(Clone, Copy, Debug)]
821#[derive_const(PartialEq, Eq)]
822pub enum SpeleothemThickness {
823 TipMerge,
824 Tip,
825 Frustum,
826 Middle,
827 Base,
828}
829
830impl PropertyEnum for SpeleothemThickness {
831 fn as_str(&self) -> &str {
832 match self {
833 SpeleothemThickness::TipMerge => "tip_merge",
834 SpeleothemThickness::Tip => "tip",
835 SpeleothemThickness::Frustum => "frustum",
836 SpeleothemThickness::Middle => "middle",
837 SpeleothemThickness::Base => "base",
838 }
839 }
840}
841
842#[derive(Clone, Copy, Debug)]
843#[derive_const(PartialEq, Eq)]
844pub enum SculkSensorPhase {
845 Inactive,
846 Active,
847 Cooldown,
848}
849
850impl PropertyEnum for SculkSensorPhase {
851 fn as_str(&self) -> &str {
852 match self {
853 SculkSensorPhase::Inactive => "inactive",
854 SculkSensorPhase::Active => "active",
855 SculkSensorPhase::Cooldown => "cooldown",
856 }
857 }
858}
859
860#[derive(Clone, Copy, Debug)]
861#[derive_const(PartialEq, Eq)]
862pub enum TrialSpawnerState {
863 Inactive,
864 WaitingForPlayers,
865 Active,
866 WaitingForRewardEjection,
867 EjectingReward,
868 Cooldown,
869}
870
871impl PropertyEnum for TrialSpawnerState {
872 fn as_str(&self) -> &str {
873 match self {
874 TrialSpawnerState::Inactive => "inactive",
875 TrialSpawnerState::WaitingForPlayers => "waiting_for_players",
876 TrialSpawnerState::Active => "active",
877 TrialSpawnerState::WaitingForRewardEjection => "waiting_for_reward_ejection",
878 TrialSpawnerState::EjectingReward => "ejecting_reward",
879 TrialSpawnerState::Cooldown => "cooldown",
880 }
881 }
882}
883
884#[derive(Clone, Copy, Debug)]
885#[derive_const(PartialEq, Eq)]
886pub enum VaultState {
887 Inactive,
888 Active,
889 Unlocking,
890 Ejecting,
891}
892
893impl PropertyEnum for VaultState {
894 fn as_str(&self) -> &str {
895 match self {
896 VaultState::Inactive => "inactive",
897 VaultState::Active => "active",
898 VaultState::Unlocking => "unlocking",
899 VaultState::Ejecting => "ejecting",
900 }
901 }
902}
903
904#[derive(Clone, Copy, Debug)]
905#[derive_const(PartialEq, Eq)]
906pub enum CreakingHeartState {
907 Uprooted,
908 Dormant,
909 Awake,
910}
911
912impl PropertyEnum for CreakingHeartState {
913 fn as_str(&self) -> &str {
914 match self {
915 CreakingHeartState::Uprooted => "uprooted",
916 CreakingHeartState::Dormant => "dormant",
917 CreakingHeartState::Awake => "awake",
918 }
919 }
920}
921
922#[derive(Clone, Copy, Debug)]
923#[derive_const(PartialEq, Eq)]
924pub enum TestBlockMode {
925 Start,
926 Log,
927 Fail,
928 Accept,
929}
930
931impl PropertyEnum for TestBlockMode {
932 fn as_str(&self) -> &str {
933 match self {
934 TestBlockMode::Start => "start",
935 TestBlockMode::Log => "log",
936 TestBlockMode::Fail => "fail",
937 TestBlockMode::Accept => "accept",
938 }
939 }
940}
941
942#[derive(Clone, Copy, Debug)]
943#[derive_const(PartialEq, Eq)]
944pub enum Pose {
945 Standing,
946 Sitting,
947 Running,
948 Star,
949}
950
951impl PropertyEnum for Pose {
952 fn as_str(&self) -> &str {
953 match self {
954 Pose::Standing => "standing",
955 Pose::Sitting => "sitting",
956 Pose::Running => "running",
957 Pose::Star => "star",
958 }
959 }
960}
961
962#[derive(Clone, Copy, Debug)]
963#[derive_const(PartialEq, Eq)]
964pub enum PotentSulfurState {
965 Dry,
966 Wet,
967 Dormant,
968 Erupting,
969 Continuous,
970}
971
972impl PropertyEnum for PotentSulfurState {
973 fn as_str(&self) -> &str {
974 match self {
975 PotentSulfurState::Dry => "dry",
976 PotentSulfurState::Wet => "wet",
977 PotentSulfurState::Dormant => "dormant",
978 PotentSulfurState::Erupting => "erupting",
979 PotentSulfurState::Continuous => "continuous",
980 }
981 }
982}
983
984impl PropertyEnum for Axis {
985 fn as_str(&self) -> &str {
986 self.as_str()
987 }
988}
989
990pub struct BlockStateProperties;
991
992impl BlockStateProperties {
994 pub const ATTACHED: BoolProperty = BoolProperty::new("attached");
995 pub const BERRIES: BoolProperty = BoolProperty::new("berries");
996 pub const BLOOM: BoolProperty = BoolProperty::new("bloom");
997 pub const BOTTOM: BoolProperty = BoolProperty::new("bottom");
998 pub const CAN_SUMMON: BoolProperty = BoolProperty::new("can_summon");
999 pub const CONDITIONAL: BoolProperty = BoolProperty::new("conditional");
1000 pub const DISARMED: BoolProperty = BoolProperty::new("disarmed");
1001 pub const DRAG: BoolProperty = BoolProperty::new("drag");
1002 pub const ENABLED: BoolProperty = BoolProperty::new("enabled");
1003 pub const EXTENDED: BoolProperty = BoolProperty::new("extended");
1004 pub const EYE: BoolProperty = BoolProperty::new("eye");
1005 pub const FALLING: BoolProperty = BoolProperty::new("falling");
1006 pub const HANGING: BoolProperty = BoolProperty::new("hanging");
1007 pub const HAS_BOTTLE_0: BoolProperty = BoolProperty::new("has_bottle_0");
1008 pub const HAS_BOTTLE_1: BoolProperty = BoolProperty::new("has_bottle_1");
1009 pub const HAS_BOTTLE_2: BoolProperty = BoolProperty::new("has_bottle_2");
1010 pub const HAS_RECORD: BoolProperty = BoolProperty::new("has_record");
1011 pub const HAS_BOOK: BoolProperty = BoolProperty::new("has_book");
1012 pub const INVERTED: BoolProperty = BoolProperty::new("inverted");
1013 pub const IN_WALL: BoolProperty = BoolProperty::new("in_wall");
1014 pub const LIT: BoolProperty = BoolProperty::new("lit");
1015 pub const LOCKED: BoolProperty = BoolProperty::new("locked");
1016 pub const NATURAL: BoolProperty = BoolProperty::new("natural");
1017 pub const OCCUPIED: BoolProperty = BoolProperty::new("occupied");
1018 pub const OPEN: BoolProperty = BoolProperty::new("open");
1019 pub const PERSISTENT: BoolProperty = BoolProperty::new("persistent");
1020 pub const POWERED: BoolProperty = BoolProperty::new("powered");
1021 pub const SHORT: BoolProperty = BoolProperty::new("short");
1022 pub const SHRIEKING: BoolProperty = BoolProperty::new("shrieking");
1023 pub const SIGNAL_FIRE: BoolProperty = BoolProperty::new("signal_fire");
1024 pub const SNOWY: BoolProperty = BoolProperty::new("snowy");
1025 pub const TIP: BoolProperty = BoolProperty::new("tip");
1026 pub const TRIGGERED: BoolProperty = BoolProperty::new("triggered");
1027 pub const UNSTABLE: BoolProperty = BoolProperty::new("unstable");
1028 pub const WATERLOGGED: BoolProperty = BoolProperty::new("waterlogged");
1029 pub const HORIZONTAL_AXIS: EnumProperty<Axis> = EnumProperty::new("axis", &[Axis::X, Axis::Z]);
1030 pub const AXIS: EnumProperty<Axis> = EnumProperty::new("axis", &[Axis::X, Axis::Y, Axis::Z]);
1031 pub const UP: BoolProperty = BoolProperty::new("up");
1032 pub const DOWN: BoolProperty = BoolProperty::new("down");
1033 pub const NORTH: BoolProperty = BoolProperty::new("north");
1034 pub const EAST: BoolProperty = BoolProperty::new("east");
1035 pub const SOUTH: BoolProperty = BoolProperty::new("south");
1036 pub const WEST: BoolProperty = BoolProperty::new("west");
1037 pub const FACING: EnumProperty<Direction> = EnumProperty::with_comparison_order(
1038 "facing",
1039 &[
1040 Direction::North,
1041 Direction::East,
1042 Direction::South,
1043 Direction::West,
1044 Direction::Up,
1045 Direction::Down,
1046 ],
1047 &[
1048 Direction::Down,
1049 Direction::Up,
1050 Direction::North,
1051 Direction::South,
1052 Direction::West,
1053 Direction::East,
1054 ],
1055 );
1056 pub const FACING_HOPPER: EnumProperty<Direction> = EnumProperty::new(
1057 "facing",
1058 &[
1059 Direction::Down,
1060 Direction::North,
1061 Direction::South,
1062 Direction::West,
1063 Direction::East,
1064 ],
1065 );
1066 pub const HORIZONTAL_FACING: EnumProperty<Direction> = EnumProperty::new(
1067 "facing",
1068 &[
1069 Direction::North,
1070 Direction::South,
1071 Direction::West,
1072 Direction::East,
1073 ],
1074 );
1075 pub const FLOWER_AMOUNT: IntProperty = IntProperty::new("flower_amount", 1, 4);
1076 pub const SEGMENT_AMOUNT: IntProperty = IntProperty::new("segment_amount", 1, 4);
1077
1078 pub const ORIENTATION: EnumProperty<FrontAndTop> = EnumProperty::new(
1080 "orientation",
1081 &[
1082 FrontAndTop::DownEast,
1083 FrontAndTop::DownNorth,
1084 FrontAndTop::DownSouth,
1085 FrontAndTop::DownWest,
1086 FrontAndTop::UpEast,
1087 FrontAndTop::UpNorth,
1088 FrontAndTop::UpSouth,
1089 FrontAndTop::UpWest,
1090 FrontAndTop::WestUp,
1091 FrontAndTop::EastUp,
1092 FrontAndTop::NorthUp,
1093 FrontAndTop::SouthUp,
1094 ],
1095 );
1096 pub const ATTACH_FACE: EnumProperty<AttachFace> = EnumProperty::new(
1097 "face",
1098 &[AttachFace::Floor, AttachFace::Wall, AttachFace::Ceiling],
1099 );
1100 pub const BELL_ATTACHMENT: EnumProperty<BellAttachType> = EnumProperty::new(
1101 "attachment",
1102 &[
1103 BellAttachType::Floor,
1104 BellAttachType::Ceiling,
1105 BellAttachType::SingleWall,
1106 BellAttachType::DoubleWall,
1107 ],
1108 );
1109 pub const EAST_WALL: EnumProperty<WallSide> =
1110 EnumProperty::new("east", &[WallSide::None, WallSide::Low, WallSide::Tall]);
1111 pub const NORTH_WALL: EnumProperty<WallSide> =
1112 EnumProperty::new("north", &[WallSide::None, WallSide::Low, WallSide::Tall]);
1113 pub const SOUTH_WALL: EnumProperty<WallSide> =
1114 EnumProperty::new("south", &[WallSide::None, WallSide::Low, WallSide::Tall]);
1115 pub const WEST_WALL: EnumProperty<WallSide> =
1116 EnumProperty::new("west", &[WallSide::None, WallSide::Low, WallSide::Tall]);
1117 pub const EAST_REDSTONE: EnumProperty<RedstoneSide> = EnumProperty::new(
1118 "east",
1119 &[RedstoneSide::Up, RedstoneSide::Side, RedstoneSide::None],
1120 );
1121 pub const NORTH_REDSTONE: EnumProperty<RedstoneSide> = EnumProperty::new(
1122 "north",
1123 &[RedstoneSide::Up, RedstoneSide::Side, RedstoneSide::None],
1124 );
1125 pub const SOUTH_REDSTONE: EnumProperty<RedstoneSide> = EnumProperty::new(
1126 "south",
1127 &[RedstoneSide::Up, RedstoneSide::Side, RedstoneSide::None],
1128 );
1129 pub const WEST_REDSTONE: EnumProperty<RedstoneSide> = EnumProperty::new(
1130 "west",
1131 &[RedstoneSide::Up, RedstoneSide::Side, RedstoneSide::None],
1132 );
1133 pub const DOUBLE_BLOCK_HALF: EnumProperty<DoubleBlockHalf> =
1134 EnumProperty::new("half", &[DoubleBlockHalf::Upper, DoubleBlockHalf::Lower]);
1135 pub const HALF: EnumProperty<Half> = EnumProperty::new("half", &[Half::Top, Half::Bottom]);
1136 pub const SIDE_CHAIN_PART: EnumProperty<SideChainPart> = EnumProperty::new(
1137 "side_chain",
1138 &[
1139 SideChainPart::Unconnected,
1140 SideChainPart::Right,
1141 SideChainPart::Center,
1142 SideChainPart::Left,
1143 ],
1144 );
1145 pub const RAIL_SHAPE: EnumProperty<RailShape> = EnumProperty::new(
1146 "shape",
1147 &[
1148 RailShape::NorthSouth,
1149 RailShape::EastWest,
1150 RailShape::AscendingEast,
1151 RailShape::AscendingWest,
1152 RailShape::AscendingNorth,
1153 RailShape::AscendingSouth,
1154 RailShape::SouthEast,
1155 RailShape::SouthWest,
1156 RailShape::NorthWest,
1157 RailShape::NorthEast,
1158 ],
1159 );
1160 pub const RAIL_SHAPE_STRAIGHT: EnumProperty<RailShape> = EnumProperty::new(
1161 "shape",
1162 &[
1163 RailShape::NorthSouth,
1164 RailShape::EastWest,
1165 RailShape::AscendingEast,
1166 RailShape::AscendingWest,
1167 RailShape::AscendingNorth,
1168 RailShape::AscendingSouth,
1169 ],
1170 );
1171
1172 pub const AGE_1: IntProperty = IntProperty::new("age", 0, 1);
1174 pub const AGE_2: IntProperty = IntProperty::new("age", 0, 2);
1175 pub const AGE_3: IntProperty = IntProperty::new("age", 0, 3);
1176 pub const AGE_4: IntProperty = IntProperty::new("age", 0, 4);
1177 pub const AGE_5: IntProperty = IntProperty::new("age", 0, 5);
1178 pub const AGE_7: IntProperty = IntProperty::new("age", 0, 7);
1179 pub const AGE_15: IntProperty = IntProperty::new("age", 0, 15);
1180 pub const AGE_25: IntProperty = IntProperty::new("age", 0, 25);
1181
1182 pub const BITES: IntProperty = IntProperty::new("bites", 0, 6);
1184 pub const CANDLES: IntProperty = IntProperty::new("candles", 1, 4);
1185 pub const DELAY: IntProperty = IntProperty::new("delay", 1, 4);
1186 pub const DISTANCE: IntProperty = IntProperty::new("distance", 1, 7);
1187 pub const EGGS: IntProperty = IntProperty::new("eggs", 1, 4);
1188 pub const HATCH: IntProperty = IntProperty::new("hatch", 0, 2);
1189 pub const LAYERS: IntProperty = IntProperty::new("layers", 1, 8);
1190 pub const LEVEL_CAULDRON: IntProperty = IntProperty::new("level", 1, 3);
1191 pub const LEVEL_COMPOSTER: IntProperty = IntProperty::new("level", 0, 8);
1192 pub const LEVEL_FLOWING: IntProperty = IntProperty::new("level", 1, 8);
1193 pub const LEVEL_HONEY: IntProperty = IntProperty::new("honey_level", 0, 5);
1194 pub const LEVEL: IntProperty = IntProperty::new("level", 0, 15);
1195 pub const MOISTURE: IntProperty = IntProperty::new("moisture", 0, 7);
1196 pub const NOTE: IntProperty = IntProperty::new("note", 0, 24);
1197 pub const PICKLES: IntProperty = IntProperty::new("pickles", 1, 4);
1198 pub const POWER: IntProperty = IntProperty::new("power", 0, 15);
1199 pub const STAGE: IntProperty = IntProperty::new("stage", 0, 1);
1200 pub const STABILITY_DISTANCE: IntProperty = IntProperty::new("distance", 0, 7);
1201 pub const RESPAWN_ANCHOR_CHARGES: IntProperty = IntProperty::new("charges", 0, 4);
1202 pub const DRIED_GHAST_HYDRATION_LEVELS: IntProperty = IntProperty::new("hydration", 0, 3);
1203 pub const ROTATION_16: IntProperty = IntProperty::new("rotation", 0, 15);
1204 pub const DUSTED: IntProperty = IntProperty::new("dusted", 0, 3);
1205
1206 pub const BED_PART: EnumProperty<BedPart> =
1208 EnumProperty::new("part", &[BedPart::Head, BedPart::Foot]);
1209 pub const CHEST_TYPE: EnumProperty<ChestType> = EnumProperty::new(
1210 "type",
1211 &[ChestType::Single, ChestType::Left, ChestType::Right],
1212 );
1213 pub const MODE_COMPARATOR: EnumProperty<ComparatorMode> =
1214 EnumProperty::new("mode", &[ComparatorMode::Compare, ComparatorMode::Subtract]);
1215 pub const DOOR_HINGE: EnumProperty<DoorHingeSide> =
1216 EnumProperty::new("hinge", &[DoorHingeSide::Left, DoorHingeSide::Right]);
1217 pub const NOTEBLOCK_INSTRUMENT: EnumProperty<NoteBlockInstrument> = EnumProperty::new(
1218 "instrument",
1219 &[
1220 NoteBlockInstrument::Harp,
1221 NoteBlockInstrument::Basedrum,
1222 NoteBlockInstrument::Snare,
1223 NoteBlockInstrument::Hat,
1224 NoteBlockInstrument::Bass,
1225 NoteBlockInstrument::Flute,
1226 NoteBlockInstrument::Bell,
1227 NoteBlockInstrument::Guitar,
1228 NoteBlockInstrument::Chime,
1229 NoteBlockInstrument::Xylophone,
1230 NoteBlockInstrument::IronXylophone,
1231 NoteBlockInstrument::CowBell,
1232 NoteBlockInstrument::Didgeridoo,
1233 NoteBlockInstrument::Bit,
1234 NoteBlockInstrument::Banjo,
1235 NoteBlockInstrument::Pling,
1236 NoteBlockInstrument::Trumpet,
1237 NoteBlockInstrument::TrumpetExposed,
1238 NoteBlockInstrument::TrumpetOxidized,
1239 NoteBlockInstrument::TrumpetWeathered,
1240 NoteBlockInstrument::Zombie,
1241 NoteBlockInstrument::Skeleton,
1242 NoteBlockInstrument::Creeper,
1243 NoteBlockInstrument::Dragon,
1244 NoteBlockInstrument::WitherSkeleton,
1245 NoteBlockInstrument::Piglin,
1246 NoteBlockInstrument::CustomHead,
1247 ],
1248 );
1249 pub const PISTON_TYPE: EnumProperty<PistonType> =
1250 EnumProperty::new("type", &[PistonType::Normal, PistonType::Sticky]);
1251 pub const SLAB_TYPE: EnumProperty<SlabType> =
1252 EnumProperty::new("type", &[SlabType::Top, SlabType::Bottom, SlabType::Double]);
1253 pub const STAIRS_SHAPE: EnumProperty<StairsShape> = EnumProperty::new(
1254 "shape",
1255 &[
1256 StairsShape::Straight,
1257 StairsShape::InnerLeft,
1258 StairsShape::InnerRight,
1259 StairsShape::OuterLeft,
1260 StairsShape::OuterRight,
1261 ],
1262 );
1263 pub const STRUCTUREBLOCK_MODE: EnumProperty<StructureMode> = EnumProperty::new(
1264 "mode",
1265 &[
1266 StructureMode::Save,
1267 StructureMode::Load,
1268 StructureMode::Corner,
1269 StructureMode::Data,
1270 ],
1271 );
1272 pub const BAMBOO_LEAVES: EnumProperty<BambooLeaves> = EnumProperty::new(
1273 "leaves",
1274 &[BambooLeaves::None, BambooLeaves::Small, BambooLeaves::Large],
1275 );
1276 pub const TILT: EnumProperty<Tilt> = EnumProperty::new(
1277 "tilt",
1278 &[Tilt::None, Tilt::Unstable, Tilt::Partial, Tilt::Full],
1279 );
1280 pub const VERTICAL_DIRECTION: EnumProperty<Direction> = EnumProperty::with_comparison_order(
1281 "vertical_direction",
1282 &[Direction::Up, Direction::Down],
1283 &[Direction::Down, Direction::Up],
1284 );
1285 pub const DRIPSTONE_THICKNESS: EnumProperty<DripstoneThickness> = EnumProperty::new(
1286 "thickness",
1287 &[
1288 DripstoneThickness::TipMerge,
1289 DripstoneThickness::Tip,
1290 DripstoneThickness::Frustum,
1291 DripstoneThickness::Middle,
1292 DripstoneThickness::Base,
1293 ],
1294 );
1295 pub const SPELEOTHEM_THICKNESS: EnumProperty<SpeleothemThickness> = EnumProperty::new(
1296 "thickness",
1297 &[
1298 SpeleothemThickness::TipMerge,
1299 SpeleothemThickness::Tip,
1300 SpeleothemThickness::Frustum,
1301 SpeleothemThickness::Middle,
1302 SpeleothemThickness::Base,
1303 ],
1304 );
1305 pub const SCULK_SENSOR_PHASE: EnumProperty<SculkSensorPhase> = EnumProperty::new(
1306 "sculk_sensor_phase",
1307 &[
1308 SculkSensorPhase::Inactive,
1309 SculkSensorPhase::Active,
1310 SculkSensorPhase::Cooldown,
1311 ],
1312 );
1313 pub const TRIAL_SPAWNER_STATE: EnumProperty<TrialSpawnerState> = EnumProperty::new(
1314 "trial_spawner_state",
1315 &[
1316 TrialSpawnerState::Inactive,
1317 TrialSpawnerState::WaitingForPlayers,
1318 TrialSpawnerState::Active,
1319 TrialSpawnerState::WaitingForRewardEjection,
1320 TrialSpawnerState::EjectingReward,
1321 TrialSpawnerState::Cooldown,
1322 ],
1323 );
1324 pub const VAULT_STATE: EnumProperty<VaultState> = EnumProperty::new(
1325 "vault_state",
1326 &[
1327 VaultState::Inactive,
1328 VaultState::Active,
1329 VaultState::Unlocking,
1330 VaultState::Ejecting,
1331 ],
1332 );
1333 pub const CREAKING_HEART_STATE: EnumProperty<CreakingHeartState> = EnumProperty::new(
1334 "creaking_heart_state",
1335 &[
1336 CreakingHeartState::Uprooted,
1337 CreakingHeartState::Dormant,
1338 CreakingHeartState::Awake,
1339 ],
1340 );
1341 pub const TEST_BLOCK_MODE: EnumProperty<TestBlockMode> = EnumProperty::new(
1342 "mode",
1343 &[
1344 TestBlockMode::Start,
1345 TestBlockMode::Log,
1346 TestBlockMode::Fail,
1347 TestBlockMode::Accept,
1348 ],
1349 );
1350 pub const COPPER_GOLEM_POSE: EnumProperty<Pose> = EnumProperty::new(
1351 "copper_golem_pose",
1352 &[Pose::Standing, Pose::Sitting, Pose::Running, Pose::Star],
1353 );
1354 pub const POTENT_SULFUR_STATE: EnumProperty<PotentSulfurState> = EnumProperty::new(
1355 "potent_sulfur_state",
1356 &[
1357 PotentSulfurState::Dry,
1358 PotentSulfurState::Wet,
1359 PotentSulfurState::Dormant,
1360 PotentSulfurState::Erupting,
1361 PotentSulfurState::Continuous,
1362 ],
1363 );
1364
1365 pub const SLOT_0_OCCUPIED: BoolProperty = BoolProperty::new("slot_0_occupied");
1367 pub const SLOT_1_OCCUPIED: BoolProperty = BoolProperty::new("slot_1_occupied");
1368 pub const SLOT_2_OCCUPIED: BoolProperty = BoolProperty::new("slot_2_occupied");
1369 pub const SLOT_3_OCCUPIED: BoolProperty = BoolProperty::new("slot_3_occupied");
1370 pub const SLOT_4_OCCUPIED: BoolProperty = BoolProperty::new("slot_4_occupied");
1371 pub const SLOT_5_OCCUPIED: BoolProperty = BoolProperty::new("slot_5_occupied");
1372 pub const CRACKED: BoolProperty = BoolProperty::new("cracked");
1373 pub const CRAFTING: BoolProperty = BoolProperty::new("crafting");
1374 pub const OMINOUS: BoolProperty = BoolProperty::new("ominous");
1375 pub const MAP: BoolProperty = BoolProperty::new("map");
1376}