steel_core/worldgen/feature/
state.rs1use super::prelude::*;
2use super::runner::FeatureDecorationRunner;
3use steel_worldgen::state_resolver::WorldgenStateResolver;
4
5impl FeatureDecorationRunner {
6 pub(super) fn block_matches_holder_set(block: BlockRef, blocks: &BlockHolderSet) -> bool {
7 match blocks {
8 BlockHolderSet::Tag(tag) => block.has_tag(tag),
9 BlockHolderSet::Entries(entries) => entries.contains(&block),
10 }
11 }
12
13 pub(super) fn block_state_from_data(
14 registry: &Registry,
15 data: &BlockStateData,
16 ) -> steel_utils::BlockStateId {
17 WorldgenStateResolver::feature_block_state_from_data(registry, data, "block state provider")
18 }
19
20 pub(super) fn fluid_state_from_data(data: &FluidStateData) -> FluidState {
21 let mut amount = Self::default_fluid_amount(data.fluid);
22 let mut falling = false;
23
24 for &(property, value) in data.properties {
25 match property {
26 "falling" if !data.fluid.is_empty => {
27 falling = Self::parse_fluid_bool_property(&data.fluid.key, property, value);
28 }
29 "level" if !data.fluid.is_empty && !data.fluid.is_source => {
30 amount = Self::parse_flowing_fluid_level(&data.fluid.key, value);
31 }
32 _ => {
33 panic!(
34 "fluid state provider references unknown property {property} on {}",
35 data.fluid.key
36 );
37 }
38 }
39 }
40
41 FluidState::new(data.fluid, amount, falling)
42 }
43
44 pub(super) const fn default_fluid_amount(fluid: FluidRef) -> u8 {
45 if fluid.is_empty {
46 0
47 } else if fluid.is_source {
48 8
49 } else {
50 1
51 }
52 }
53
54 pub(super) fn parse_fluid_bool_property(
55 fluid_name: &steel_utils::Identifier,
56 property: &str,
57 value: &str,
58 ) -> bool {
59 match value {
60 "true" => true,
61 "false" => false,
62 _ => panic!(
63 "fluid state provider references invalid boolean value {value} for property {property} on {fluid_name}"
64 ),
65 }
66 }
67
68 pub(super) fn parse_flowing_fluid_level(
69 fluid_name: &steel_utils::Identifier,
70 value: &str,
71 ) -> u8 {
72 let Ok(level) = value.parse::<u8>() else {
73 panic!("fluid state provider references invalid flowing level {value} on {fluid_name}");
74 };
75 assert!(
76 (1..=8).contains(&level),
77 "fluid state provider references flowing level {level} outside 1..=8 on {fluid_name}"
78 );
79 level
80 }
81
82 pub(super) fn legacy_block_from_fluid_state(
83 registry: &Registry,
84 fluid_state: FluidState,
85 ) -> BlockStateId {
86 let Some(block) = registry.blocks.by_key(&fluid_state.fluid_id.block) else {
87 panic!(
88 "fluid {} references unknown legacy block {}",
89 fluid_state.fluid_id.key, fluid_state.fluid_id.block
90 );
91 };
92
93 let mut state = registry.blocks.get_default_state_id(block);
94 if registry
95 .blocks
96 .try_get_property(state, &BlockStateProperties::LEVEL)
97 .is_some()
98 {
99 state = Self::set_int_property_by_name(
100 registry,
101 state,
102 "level",
103 i32::from(Self::legacy_fluid_block_level(fluid_state)),
104 );
105 }
106 state
107 }
108
109 pub(super) fn legacy_fluid_block_level(fluid_state: FluidState) -> u8 {
110 if fluid_state.fluid_id.is_source {
111 return 0;
112 }
113
114 let amount = fluid_state.amount.min(8);
115 if fluid_state.falling {
116 8 + (8 - amount)
117 } else {
118 8 - amount
119 }
120 }
121}