Skip to main content

steel_core/worldgen/feature/
state.rs

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