1use super::*;
2use crate::{Land, site::generation::PrimitiveTransform};
3use common::terrain::BlockKind;
4use rand::prelude::*;
5use vek::*;
6
7pub struct GliderRing {
9 center: Vec2<i32>,
11 direction: Dir2,
13 number: usize,
15 base: i32,
17 ring_thickness: i32,
19 ring_height: i32,
21 ring_radius: i32,
23}
24
25impl GliderRing {
26 pub fn generate(
27 land: &Land,
28 _rng: &mut impl Rng,
29 _site: &Site,
30 wpos: &Vec2<i32>,
31 number: usize,
32 direction: Dir2,
33 ) -> Self {
34 Self {
35 center: *wpos,
36 direction,
37 number,
38 base: land.get_alt_approx(*wpos) as i32 + 1,
39 ring_thickness: 4,
40 ring_height: 35,
41 ring_radius: 16,
42 }
43 }
44}
45
46impl Structure for GliderRing {
47 #[cfg(feature = "dyn-lib")]
48 #[unsafe(export_name = "as_dyn_structure_gliderring")]
49 fn as_dyn_outer(&self) -> Option<(&dyn Structure, &'static str)> {
50 Some((Self::as_dyn_impl(self), "as_dyn_structure_gliderring"))
51 }
52
53 fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) {
54 let rotate_turns = match self.direction {
55 Dir2::X => 0,
56 Dir2::Y => 1,
57 Dir2::NegX => 2,
58 Dir2::NegY => 3,
59 };
60 let rotation_center = Vec3::new(self.center.x, self.center.y, self.base);
61
62 let red = Fill::Brick(BlockKind::Wood, Rgb::new(200, 0, 0), 24);
63 let green = Fill::Brick(BlockKind::Wood, Rgb::new(0, 200, 0), 24);
64 let white = Fill::Brick(BlockKind::GlowingRock, Rgb::new(200, 200, 200), 24);
65 let black = Fill::Brick(BlockKind::Wood, Rgb::new(0, 0, 0), 24);
66 let wood = Fill::Brick(BlockKind::Wood, Rgb::new(55, 25, 8), 24);
67
68 let ring_base = self.base + self.ring_height;
69 let ring_diameter = self.ring_radius * 2;
70 let ring_top = ring_base + ring_diameter;
71
72 let base = painter.aabb(Aabb {
74 min: Vec2::new(self.center.x - 1, self.center.y - 2).with_z(self.base - 30),
75 max: Vec2::new(self.center.x + 2, self.center.y + 2)
76 .with_z(self.base + self.ring_height + 1),
77 });
78 let green_ring = painter.horizontal_cylinder(
80 Aabb {
81 min: Vec2::new(self.center.x - 1, self.center.y - self.ring_radius)
82 .with_z(ring_base),
83 max: Vec2::new(self.center.x, self.center.y + self.ring_radius).with_z(ring_top),
84 },
85 Dir2::X,
86 );
87 let red_ring = painter.horizontal_cylinder(
88 Aabb {
89 min: Vec2::new(self.center.x, self.center.y - self.ring_radius).with_z(ring_base),
90 max: Vec2::new(self.center.x + 2, self.center.y + self.ring_radius)
91 .with_z(ring_top),
92 },
93 Dir2::X,
94 );
95 let front_white_ring = painter.horizontal_cylinder(
96 Aabb {
97 min: Vec2::new(
98 self.center.x - 1,
99 self.center.y - self.ring_radius + self.ring_thickness - 1,
100 )
101 .with_z(ring_base + self.ring_thickness - 1),
102 max: Vec2::new(
103 self.center.x,
104 self.center.y + self.ring_radius - self.ring_thickness + 1,
105 )
106 .with_z(ring_top - self.ring_thickness + 1),
107 },
108 Dir2::X,
109 );
110 let back_white_ring = painter.horizontal_cylinder(
111 Aabb {
112 min: Vec2::new(
113 self.center.x + 1,
114 self.center.y - self.ring_radius + self.ring_thickness - 1,
115 )
116 .with_z(ring_base + self.ring_thickness - 1),
117 max: Vec2::new(
118 self.center.x + 2,
119 self.center.y + self.ring_radius - self.ring_thickness + 1,
120 )
121 .with_z(ring_top - self.ring_thickness + 1),
122 },
123 Dir2::X,
124 );
125 let mut black_fills = Vec::new();
126 for y in self.center.y - self.ring_radius + self.ring_thickness - 1
127 ..=self.center.y + self.ring_radius - self.ring_thickness + 1
128 {
129 if y % 4 == 0 {
130 let stripe = painter
131 .aabb(Aabb {
132 min: Vec2::new(self.center.x - 1, y + 1).with_z(ring_base),
133 max: Vec2::new(self.center.x, y + 3).with_z(ring_top),
134 })
135 .intersect(front_white_ring);
136 black_fills.push(stripe);
137 }
138 }
139 for z in ring_base + self.ring_thickness + 3..=ring_top - self.ring_thickness - 9 {
140 if z % 4 == 0 {
141 let stripe = painter
142 .aabb(Aabb {
143 min: Vec2::new(
144 self.center.x - 1,
145 self.center.y - self.ring_radius + self.ring_thickness - 1,
146 )
147 .with_z(z + 1),
148 max: Vec2::new(
149 self.center.x,
150 self.center.y + self.ring_radius - self.ring_thickness + 1,
151 )
152 .with_z(z + 3),
153 })
154 .intersect(front_white_ring);
155 black_fills.push(stripe);
156 }
157 }
158 let ring_clear = painter.horizontal_cylinder(
159 Aabb {
160 min: Vec2::new(
161 self.center.x - 5,
162 self.center.y - self.ring_radius + self.ring_thickness,
163 )
164 .with_z(ring_base + self.ring_thickness),
165 max: Vec2::new(
166 self.center.x + 6,
167 self.center.y + self.ring_radius - self.ring_thickness,
168 )
169 .with_z(ring_top - self.ring_thickness),
170 },
171 Dir2::X,
172 );
173 let sign_base = ring_top - self.ring_thickness - 1;
175 let sign_height = 7;
176 let sign = painter.aabb(Aabb {
177 min: Vec2::new(self.center.x - 1, self.center.y - 3).with_z(sign_base),
178 max: Vec2::new(self.center.x + 1, self.center.y + 3).with_z(sign_base + sign_height),
179 });
180 let numeral_origin = Vec3::new(self.center.x, self.center.y - 2, sign_base + 1);
182 let numeral = painter
185 .numeral(numeral_origin, self.number)
186 .rotate_z_90_about(2, rotation_center);
187
188 let wood_fills = [base];
189 let red_fills = [red_ring];
190 let green_fills = [green_ring];
191 let white_fills = [front_white_ring, back_white_ring];
192 let sign_fills = [numeral];
193 let black_sign_fills = [sign];
194 let clear_fills = [ring_clear];
195
196 let fills = [
197 (&wood_fills as &[_], Some(wood)),
198 (&red_fills, Some(red)),
199 (&green_fills, Some(green)),
200 (&white_fills, Some(white.clone())),
201 (&black_fills, Some(black.clone())),
202 (&clear_fills, None),
203 (&black_sign_fills, Some(black)),
204 (&sign_fills, Some(white)),
205 ];
206 for (primitives, fill_color_maybe) in fills {
207 for prim in primitives {
208 if let Some(fill_color) = &fill_color_maybe {
209 prim.rotate_z_90_about(rotate_turns, rotation_center)
210 .fill(fill_color.clone());
211 } else {
212 prim.rotate_z_90_about(rotate_turns, rotation_center)
213 .clear();
214 }
215 }
216 }
217 }
218}