steel_core/worldgen/feature/features/
weeping_vines.rs1use super::super::prelude::*;
2use super::super::runner::FeatureDecorationRunner;
3
4impl FeatureDecorationRunner {
5 pub(in crate::worldgen::feature) fn place_weeping_vines_feature(
6 region: &mut WorldGenRegion<'_>,
7 random: &mut WorldgenRandom,
8 origin: BlockPos,
9 ) -> bool {
10 if !region.block_state(origin).is_air() {
11 return false;
12 }
13
14 let above_block = region.block_state(origin.above()).get_block();
15 if above_block != &vanilla_blocks::NETHERRACK
16 && above_block != &vanilla_blocks::NETHER_WART_BLOCK
17 {
18 return false;
19 }
20
21 Self::place_roof_nether_wart(region, random, origin);
22 Self::place_roof_weeping_vines(region, random, origin);
23 true
24 }
25
26 fn place_roof_nether_wart(
27 region: &mut WorldGenRegion<'_>,
28 random: &mut WorldgenRandom,
29 origin: BlockPos,
30 ) {
31 let wart = vanilla_blocks::NETHER_WART_BLOCK.default_state();
32 let _ = region.set_block_state(origin, wart, UpdateFlags::UPDATE_CLIENTS);
33
34 for _ in 0..200 {
35 let place_pos = origin.offset(
36 random.next_i32_bounded(6) - random.next_i32_bounded(6),
37 random.next_i32_bounded(2) - random.next_i32_bounded(5),
38 random.next_i32_bounded(6) - random.next_i32_bounded(6),
39 );
40 if !region.block_state(place_pos).is_air() {
41 continue;
42 }
43
44 let mut neighbors = 0;
45 for direction in Self::VANILLA_DIRECTION_VALUES {
46 let neighbor_block = region
47 .block_state(place_pos.relative(direction))
48 .get_block();
49 if neighbor_block == &vanilla_blocks::NETHERRACK
50 || neighbor_block == &vanilla_blocks::NETHER_WART_BLOCK
51 {
52 neighbors += 1;
53 }
54
55 if neighbors > 1 {
56 break;
57 }
58 }
59
60 if neighbors == 1 {
61 let _ = region.set_block_state(place_pos, wart, UpdateFlags::UPDATE_CLIENTS);
62 }
63 }
64 }
65
66 fn place_roof_weeping_vines(
67 region: &mut WorldGenRegion<'_>,
68 random: &mut WorldgenRandom,
69 origin: BlockPos,
70 ) {
71 for _ in 0..100 {
72 let place_pos = origin.offset(
73 random.next_i32_bounded(8) - random.next_i32_bounded(8),
74 random.next_i32_bounded(2) - random.next_i32_bounded(7),
75 random.next_i32_bounded(8) - random.next_i32_bounded(8),
76 );
77 if !region.block_state(place_pos).is_air() {
78 continue;
79 }
80
81 let above_block = region.block_state(place_pos.above()).get_block();
82 if above_block == &vanilla_blocks::NETHERRACK
83 || above_block == &vanilla_blocks::NETHER_WART_BLOCK
84 {
85 let mut vine_height = random.next_i32_between(1, 8);
86 if random.next_i32_bounded(6) == 0 {
87 vine_height *= 2;
88 }
89
90 if random.next_i32_bounded(5) == 0 {
91 vine_height = 1;
92 }
93
94 Self::place_weeping_vines_column(region, random, place_pos, vine_height, 17, 25);
95 }
96 }
97 }
98
99 pub(in crate::worldgen::feature) fn place_weeping_vines_column(
100 region: &mut WorldGenRegion<'_>,
101 random: &mut WorldgenRandom,
102 mut place_pos: BlockPos,
103 total_height: i32,
104 min_age: u8,
105 max_age: u8,
106 ) {
107 for height in 0..=total_height {
108 if region.block_state(place_pos).is_air() {
109 if height == total_height || !region.block_state(place_pos.below()).is_air() {
110 let state = vanilla_blocks::WEEPING_VINES.default_state().set_value(
111 &BlockStateProperties::AGE_25,
112 random.next_i32_between(i32::from(min_age), i32::from(max_age)) as u8,
113 );
114 let _ = region.set_block_state(place_pos, state, UpdateFlags::UPDATE_CLIENTS);
115 break;
116 }
117
118 let _ = region.set_block_state(
119 place_pos,
120 vanilla_blocks::WEEPING_VINES_PLANT.default_state(),
121 UpdateFlags::UPDATE_CLIENTS,
122 );
123 }
124
125 place_pos = place_pos.below();
126 }
127 }
128}