1use super::*;
2use crate::{
3 Land,
4 util::{RandomField, Sampler},
5};
6use common::terrain::{Block, BlockKind};
7use rand::prelude::*;
8use std::sync::Arc;
9use vek::*;
10
11pub struct DesertCityTemple {
13 pub door_tile: Vec2<i32>,
15 bounds: Aabr<i32>,
17 pub(crate) alt: i32,
19}
20
21impl DesertCityTemple {
22 pub fn generate(
23 land: &Land,
24 _rng: &mut impl Rng,
25 site: &Site,
26 door_tile: Vec2<i32>,
27 door_dir: Vec2<i32>,
28 tile_aabr: Aabr<i32>,
29 alt: Option<i32>,
30 ) -> Self {
31 let door_tile_pos = site.tile_center_wpos(door_tile);
32 let bounds = Aabr {
33 min: site.tile_wpos(tile_aabr.min),
34 max: site.tile_wpos(tile_aabr.max),
35 };
36
37 Self {
38 bounds,
39 door_tile: door_tile_pos,
40 alt: alt.unwrap_or_else(|| {
41 land.get_alt_approx(site.tile_center_wpos(door_tile + door_dir)) as i32
42 }),
43 }
44 }
45}
46
47impl Structure for DesertCityTemple {
48 #[cfg(feature = "dyn-lib")]
49 #[unsafe(export_name = "as_dyn_structure_desertcitytemple")]
50 fn as_dyn_outer(&self) -> Option<(&dyn Structure, &'static str)> {
51 Some((Self::as_dyn_impl(self), "as_dyn_structure_desertcitytemple"))
52 }
53
54 fn door_tile(&self) -> Option<Vec2<i32>> { Some(self.door_tile) }
55
56 fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) {
57 let sandstone = Fill::Sampling(Arc::new(|center| {
58 Some(match (RandomField::new(0).get(center)) % 37 {
59 0..=8 => Block::new(BlockKind::Rock, Rgb::new(245, 212, 129)),
60 9..=17 => Block::new(BlockKind::Rock, Rgb::new(246, 214, 133)),
61 18..=26 => Block::new(BlockKind::Rock, Rgb::new(247, 216, 136)),
62 27..=35 => Block::new(BlockKind::Rock, Rgb::new(248, 219, 142)),
63 _ => Block::new(BlockKind::Rock, Rgb::new(235, 178, 99)),
64 })
65 }));
66 let sandstone_broken = Fill::Sampling(Arc::new(|center| {
67 Some(match (RandomField::new(0).get(center)) % 42 {
68 0..=8 => Block::new(BlockKind::Rock, Rgb::new(245, 212, 129)),
69 9..=17 => Block::new(BlockKind::Rock, Rgb::new(246, 214, 133)),
70 18..=26 => Block::new(BlockKind::Rock, Rgb::new(247, 216, 136)),
71 27..=35 => Block::new(BlockKind::Rock, Rgb::new(248, 219, 142)),
72 36..=40 => Block::new(BlockKind::Air, Rgb::new(0, 0, 0)),
73 _ => Block::new(BlockKind::Rock, Rgb::new(235, 178, 99)),
74 })
75 }));
76 let base = self.alt + 1;
77 let center = self.bounds.center();
78 let diameter =
79 10 + (self.bounds.max.x - self.bounds.min.x).min(self.bounds.max.y - self.bounds.min.y);
80 painter
82 .aabb(Aabb {
83 min: Vec2::new(self.bounds.min.x + 1, self.bounds.min.y + 1).with_z(base - 20),
84 max: Vec2::new(self.bounds.min.x + 2, self.bounds.max.y).with_z(base + 2),
85 })
86 .union(painter.aabb(Aabb {
87 min: Vec2::new(self.bounds.max.x - 1, self.bounds.min.y + 1).with_z(base - 20),
88 max: Vec2::new(self.bounds.max.x, self.bounds.max.y).with_z(base + 2),
89 }))
90 .union(painter.aabb(Aabb {
91 min: Vec2::new(self.bounds.min.x + 1, self.bounds.min.y + 1).with_z(base - 20),
92 max: Vec2::new(self.bounds.max.x, self.bounds.min.y + 2).with_z(base + 2),
93 }))
94 .union(painter.aabb(Aabb {
95 min: Vec2::new(self.bounds.min.x + 1, self.bounds.max.y - 1).with_z(base - 20),
96 max: Vec2::new(self.bounds.max.x, self.bounds.max.y).with_z(base + 2),
97 }))
98 .fill(sandstone_broken);
99 painter
100 .aabb(Aabb {
101 min: Vec2::new(self.bounds.min.x + 1, center.y - 8).with_z(base),
102 max: Vec2::new(self.bounds.max.x, center.y + 8).with_z(base + 7),
103 })
104 .clear();
105 painter
106 .aabb(Aabb {
107 min: Vec2::new(center.x - 7, self.bounds.min.y + 1).with_z(base),
108 max: Vec2::new(center.x + 9, self.bounds.max.y).with_z(base + 7),
109 })
110 .clear();
111 painter
113 .aabb(Aabb {
114 min: (self.bounds.min + 1).with_z(base - 20),
115 max: (self.bounds.max).with_z(base),
116 })
117 .fill(sandstone.clone());
118
119 let temple_color = match (RandomField::new(0).get((center - 3).with_z(base))) % 2 {
121 0 => Fill::Brick(BlockKind::Rock, Rgb::new(100, 101, 250), 3),
122 _ => Fill::Brick(BlockKind::Rock, Rgb::new(63, 49, 63), 24),
123 };
124 let temple_size = diameter / 3;
125 let floaty_block = Fill::Brick(BlockKind::GlowingWeakRock, Rgb::new(253, 240, 149), 2);
126 let temple = Aabb {
127 min: (center - temple_size).with_z(base),
128 max: (center + temple_size - 1).with_z(base + temple_size + 1),
129 };
130
131 painter.aabb(temple).fill(sandstone.clone());
133 painter
135 .aabb(Aabb {
136 min: (center - temple_size - 1).with_z(base + temple_size + 1),
137 max: (center + temple_size).with_z(base + temple_size + 4),
138 })
139 .fill(sandstone.clone());
140 painter
141 .aabb(Aabb {
142 min: (center - temple_size).with_z(base + temple_size + 2),
143 max: (center + temple_size - 1).with_z(base + temple_size + 4),
144 })
145 .clear();
146 painter
147 .aabb(Aabb {
148 min: Vec2::new(center.x - temple_size - 1, center.y - (temple_size / 4) - 2)
149 .with_z(base + temple_size + 3),
150 max: Vec2::new(center.x + temple_size, center.y + (temple_size / 4) + 1)
151 .with_z(base + temple_size + 4),
152 })
153 .clear();
154 painter
155 .aabb(Aabb {
156 min: Vec2::new(center.x - (temple_size / 4) - 2, center.y - temple_size - 1)
157 .with_z(base + temple_size + 3),
158 max: Vec2::new(center.x + (temple_size / 4) + 1, center.y + temple_size)
159 .with_z(base + temple_size + 4),
160 })
161 .clear();
162
163 painter
165 .aabb(Aabb {
166 min: (center - temple_size + 1).with_z(base + temple_size),
167 max: (center + temple_size - 2).with_z(base + temple_size + 3),
168 })
169 .clear();
170 for dir in SQUARE_4 {
172 let corner_pos = center - temple_size;
173 let pillar_center = corner_pos + (dir * ((2 * temple_size) - 1));
174 painter
176 .aabb(Aabb {
177 min: (pillar_center - 4).with_z(base),
178 max: (pillar_center + 4).with_z(base + 4),
179 })
180 .fill(sandstone.clone());
181
182 painter
184 .aabb(Aabb {
185 min: (pillar_center - 3).with_z(base + 4),
186 max: (pillar_center + 3).with_z(base + temple_size + 3),
187 })
188 .fill(sandstone.clone());
189 painter
191 .aabb(Aabb {
192 min: (pillar_center - 4).with_z(base + temple_size + 3),
193 max: (pillar_center + 4).with_z(base + temple_size + 6),
194 })
195 .fill(sandstone.clone());
196
197 painter
198 .aabb(Aabb {
199 min: (pillar_center - 3).with_z(base + temple_size + 4),
200 max: (pillar_center + 3).with_z(base + temple_size + 6),
201 })
202 .clear();
203
204 painter
206 .aabb(Aabb {
207 min: (center - temple_size).with_z(base + temple_size + 3),
208 max: (center + temple_size - 1).with_z(base + temple_size + 6),
209 })
210 .clear()
211 }
212
213 for s in 0..2 {
217 let spread_select = ((RandomField::new(0).get((center - 1).with_z(base))) % 2) as i32;
219 let spread = 3 * spread_select;
220 let carve_style = ((RandomField::new(0).get((center - 2 - s).with_z(base))) % 3) as i32;
221 match carve_style {
222 0 => {
224 for c in 0..(temple_size - 5) {
226 painter
227 .aabb(Aabb {
228 min: Vec2::new(
229 center.x - temple_size + 5 + (2 * c),
230 center.y - temple_size,
231 )
232 .with_z(base + 2),
233 max: Vec2::new(
234 center.x - temple_size + 6 + (2 * c),
235 center.y + temple_size - 1,
236 )
237 .with_z(base + temple_size - 1),
238 })
239 .clear();
240 }
241 for c in 0..(temple_size - 5) {
242 painter
243 .aabb(Aabb {
244 min: Vec2::new(
245 center.x - temple_size,
246 center.y - temple_size + 5 + (2 * c),
247 )
248 .with_z(base + 2),
249 max: Vec2::new(
250 center.x + temple_size - 1,
251 center.y - temple_size + 6 + (2 * c),
252 )
253 .with_z(base + temple_size - 1),
254 })
255 .clear();
256 }
257 },
258 1 => {
259 for c in 0..((temple_size / 2) - 2) {
261 painter
262 .aabb(Aabb {
263 min: Vec2::new(center.x - temple_size + 5, center.y - temple_size)
264 .with_z(base + 2 + ((spread + 2) * c)),
265 max: Vec2::new(
266 center.x + temple_size - 6,
267 center.y + temple_size - 1,
268 )
269 .with_z(base + 3 + ((spread + 2) * c) + spread_select),
270 })
271 .clear();
272 }
273 for c in 0..((temple_size / 2) - 2) {
274 painter
275 .aabb(Aabb {
276 min: Vec2::new(center.x - temple_size, center.y - temple_size + 5)
277 .with_z(base + 2 + ((spread + 2) * c)),
278 max: Vec2::new(
279 center.x + temple_size - 1,
280 center.y + temple_size - 6,
281 )
282 .with_z(base + 3 + ((spread + 2) * c) + spread_select),
283 })
284 .clear();
285 }
286 },
287 _ => {},
288 }
289 }
290 painter
292 .aabb(Aabb {
293 min: Vec2::new(center.x - temple_size + 2, center.y - temple_size + 2)
294 .with_z(base + 2),
295 max: Vec2::new(center.x + temple_size - 3, center.y - temple_size + 3)
296 .with_z(base + temple_size - 1),
297 })
298 .fill(temple_color.clone());
299
300 painter
301 .aabb(Aabb {
302 min: Vec2::new(center.x - temple_size + 2, center.y + temple_size - 4)
303 .with_z(base + 2),
304 max: Vec2::new(center.x + temple_size - 3, center.y + temple_size - 3)
305 .with_z(base + temple_size - 1),
306 })
307 .fill(temple_color.clone());
308 painter
310 .aabb(Aabb {
311 min: Vec2::new(center.x - temple_size + 2, center.y - temple_size + 2)
312 .with_z(base + 2),
313 max: Vec2::new(center.x - temple_size + 3, center.y + temple_size - 3)
314 .with_z(base + temple_size - 1),
315 })
316 .fill(temple_color.clone());
317 painter
318 .aabb(Aabb {
319 min: Vec2::new(center.x + temple_size - 4, center.y - temple_size + 2)
320 .with_z(base + 2),
321 max: Vec2::new(center.x + temple_size - 3, center.y + temple_size - 3)
322 .with_z(base + temple_size - 1),
323 })
324 .fill(temple_color.clone());
325 painter
327 .aabb(Aabb {
328 min: Vec2::new(center.x - temple_size + 6, center.y - temple_size).with_z(base + 3),
329 max: Vec2::new(center.x + temple_size - 7, center.y - temple_size + 1)
330 .with_z(base + temple_size - 2),
331 })
332 .clear();
333 painter
334 .aabb(Aabb {
335 min: Vec2::new(center.x - temple_size + 6, center.y + temple_size - 2)
336 .with_z(base + 3),
337 max: Vec2::new(center.x + temple_size - 7, center.y + temple_size - 1)
338 .with_z(base + temple_size - 2),
339 })
340 .clear();
341 painter
343 .aabb(Aabb {
344 min: Vec2::new(center.x - temple_size, center.y - temple_size + 6).with_z(base + 3),
345 max: Vec2::new(center.x - temple_size + 1, center.y + temple_size - 7)
346 .with_z(base + temple_size - 2),
347 })
348 .clear();
349 painter
350 .aabb(Aabb {
351 min: Vec2::new(center.x + temple_size - 2, center.y - temple_size + 6)
352 .with_z(base + 3),
353 max: Vec2::new(center.x + temple_size - 1, center.y + temple_size - 7)
354 .with_z(base + temple_size - 2),
355 })
356 .clear();
357 painter
359 .cylinder(Aabb {
360 min: (center - temple_size + 3).with_z(base + temple_size),
361 max: (center + temple_size - 4).with_z(base + temple_size + 1),
362 })
363 .fill(sandstone.clone());
364 let top = painter.sphere(Aabb {
366 min: (center - temple_size + 3).with_z(base),
367 max: (center + temple_size - 4).with_z(base + (2 * temple_size) - 7),
368 });
369 top.fill(sandstone.clone());
370
371 for s in 0..2 {
375 let spread_select =
377 ((RandomField::new(0).get((center - 1 - s).with_z(base))) % 2) as i32;
378 let spread = 3 * spread_select;
379 let carve_style = ((RandomField::new(0).get((center - 2 - s).with_z(base))) % 3) as i32;
380 match carve_style {
381 0 => {
383 for c in 0..(temple_size - 2) {
385 painter
386 .aabb(Aabb {
387 min: Vec2::new(
388 center.x - temple_size + 2 + ((spread + 2) * c),
389 center.y - temple_size,
390 )
391 .with_z(base + temple_size),
392 max: Vec2::new(
393 center.x - temple_size + 3 + ((spread + 2) * c) + spread_select,
394 center.y + temple_size - 1,
395 )
396 .with_z(base + (2 * temple_size)),
397 })
398 .intersect(top)
399 .fill(temple_color.clone());
400 }
401 },
402 1 => {
403 for c in 0..(temple_size - 2) {
404 painter
405 .aabb(Aabb {
406 min: Vec2::new(
407 center.x - temple_size,
408 center.y - temple_size + 2 + ((spread + 2) * c),
409 )
410 .with_z(base + temple_size),
411 max: Vec2::new(
412 center.x + temple_size - 1,
413 center.y - temple_size + 3 + ((spread + 2) * c) + spread_select,
414 )
415 .with_z(base + (2 * temple_size)),
416 })
417 .intersect(top)
418 .fill(temple_color.clone());
419 }
420 },
421 _ => {},
422 }
423 }
424 painter
426 .cylinder(Aabb {
427 min: (center - temple_size + 3).with_z(base + temple_size),
428 max: (center + temple_size - 4).with_z(base + temple_size + 1),
429 })
430 .fill(sandstone.clone());
431 painter
433 .sphere(Aabb {
434 min: (center - temple_size + 4).with_z(base + 1),
435 max: (center + temple_size - 5).with_z(base + (2 * temple_size) - 8),
436 })
437 .clear();
438
439 let entry_select = ((RandomField::new(0).get((center + 1).with_z(base))) % 2) as i32;
441 match entry_select {
442 0 => {
443 painter
445 .aabb(Aabb {
446 min: Vec2::new(center.x - 5, center.y - temple_size).with_z(base),
447 max: Vec2::new(center.x + 4, center.y + temple_size - 1).with_z(base + 4),
448 })
449 .fill(sandstone.clone());
450 painter
451 .aabb(Aabb {
452 min: Vec2::new(center.x - 4, center.y - temple_size).with_z(base),
453 max: Vec2::new(center.x + 3, center.y + temple_size - 1).with_z(base + 4),
454 })
455 .clear();
456
457 painter
458 .aabb(Aabb {
459 min: Vec2::new(center.x - 4, center.y - temple_size).with_z(base + 4),
460 max: Vec2::new(center.x + 3, center.y + temple_size - 1).with_z(base + 7),
461 })
462 .fill(sandstone.clone());
463 painter
464 .aabb(Aabb {
465 min: Vec2::new(center.x - 3, center.y - temple_size).with_z(base + 4),
466 max: Vec2::new(center.x + 2, center.y + temple_size - 1).with_z(base + 7),
467 })
468 .clear();
469
470 painter
471 .aabb(Aabb {
472 min: Vec2::new(center.x - 3, center.y - temple_size).with_z(base + 7),
473 max: Vec2::new(center.x + 2, center.y + temple_size - 1).with_z(base + 9),
474 })
475 .fill(sandstone.clone());
476 painter
477 .aabb(Aabb {
478 min: Vec2::new(center.x - 2, center.y - temple_size).with_z(base + 7),
479 max: Vec2::new(center.x + 1, center.y + temple_size - 1).with_z(base + 9),
480 })
481 .clear();
482
483 painter
484 .aabb(Aabb {
485 min: Vec2::new(center.x - 2, center.y - temple_size).with_z(base + 9),
486 max: Vec2::new(center.x + 1, center.y + temple_size - 1).with_z(base + 10),
487 })
488 .fill(sandstone.clone());
489
490 painter
492 .aabb(Aabb {
493 min: Vec2::new(center.x - temple_size, center.y - 5).with_z(base),
494 max: Vec2::new(center.x + temple_size - 1, center.y + 4).with_z(base + 4),
495 })
496 .fill(sandstone.clone());
497 painter
498 .aabb(Aabb {
499 min: Vec2::new(center.x - temple_size, center.y - 4).with_z(base),
500 max: Vec2::new(center.x + temple_size - 1, center.y + 3).with_z(base + 4),
501 })
502 .clear();
503
504 painter
505 .aabb(Aabb {
506 min: Vec2::new(center.x - temple_size, center.y - 4).with_z(base + 4),
507 max: Vec2::new(center.x + temple_size - 1, center.y + 3).with_z(base + 7),
508 })
509 .fill(sandstone.clone());
510 painter
511 .aabb(Aabb {
512 min: Vec2::new(center.x - temple_size, center.y - 3).with_z(base + 4),
513 max: Vec2::new(center.x + temple_size - 1, center.y + 2).with_z(base + 7),
514 })
515 .clear();
516
517 painter
518 .aabb(Aabb {
519 min: Vec2::new(center.x - temple_size, center.y - 3).with_z(base + 7),
520 max: Vec2::new(center.x + temple_size - 1, center.y + 2).with_z(base + 9),
521 })
522 .fill(sandstone.clone());
523 painter
524 .aabb(Aabb {
525 min: Vec2::new(center.x - temple_size, center.y - 2).with_z(base + 7),
526 max: Vec2::new(center.x + temple_size - 1, center.y + 1).with_z(base + 9),
527 })
528 .clear();
529
530 painter
531 .aabb(Aabb {
532 min: Vec2::new(center.x - temple_size, center.y - 2).with_z(base + 9),
533 max: Vec2::new(center.x + temple_size - 1, center.y + 1).with_z(base + 10),
534 })
535 .fill(sandstone.clone());
536 },
537 _ => {
538 painter
540 .aabb(Aabb {
541 min: Vec2::new(center.x - 5, center.y - temple_size).with_z(base),
542 max: Vec2::new(center.x + 4, center.y + temple_size - 1).with_z(base + 8),
543 })
544 .fill(sandstone.clone());
545 painter
546 .aabb(Aabb {
547 min: Vec2::new(center.x - 3, center.y - temple_size).with_z(base),
548 max: Vec2::new(center.x + 2, center.y + temple_size - 1).with_z(base + 6),
549 })
550 .clear();
551
552 painter
554 .aabb(Aabb {
555 min: Vec2::new(center.x - temple_size, center.y - 5).with_z(base),
556 max: Vec2::new(center.x + temple_size - 1, center.y + 4).with_z(base + 8),
557 })
558 .fill(sandstone.clone());
559 painter
560 .aabb(Aabb {
561 min: Vec2::new(center.x - temple_size, center.y - 3).with_z(base),
562 max: Vec2::new(center.x + temple_size - 1, center.y + 2).with_z(base + 6),
563 })
564 .clear();
565 },
566 }
567
568 painter
570 .aabb(Aabb {
571 min: (center - temple_size + 4).with_z(base),
572 max: (center + temple_size - 5).with_z(base + temple_size - 1),
573 })
574 .clear();
575
576 painter
579 .sphere(Aabb {
580 min: (center - 3).with_z(base),
581 max: (center + 2).with_z(base + 5),
582 })
583 .fill(sandstone.clone());
584 painter
585 .sphere(Aabb {
586 min: (center - 3).with_z(base + 4),
587 max: (center + 2).with_z(base + 9),
588 })
589 .fill(sandstone.clone());
590 painter
591 .sphere(Aabb {
592 min: (center - 3).with_z(base + 8),
593 max: (center + 2).with_z(base + 13),
594 })
595 .fill(sandstone.clone());
596 painter
597 .sphere(Aabb {
598 min: (center - 4).with_z(base + 14),
599 max: (center + 3).with_z(base + 15),
600 })
601 .fill(sandstone.clone());
602 painter
603 .sphere(Aabb {
604 min: (center - 3).with_z(base + 16),
605 max: (center + 2).with_z(base + 21),
606 })
607 .fill(floaty_block.clone());
608
609 for dir in SQUARE_4 {
611 let corner_pos = center - temple_size / 2;
612 let sclpt_center = corner_pos + (dir * (temple_size));
613
614 painter
615 .sphere(Aabb {
616 min: (sclpt_center - 2).with_z(base),
617 max: (sclpt_center + 1).with_z(base + 3),
618 })
619 .fill(sandstone.clone());
620 painter
621 .sphere(Aabb {
622 min: (sclpt_center - 2).with_z(base + 2),
623 max: (sclpt_center + 1).with_z(base + 5),
624 })
625 .fill(sandstone.clone());
626 painter
627 .sphere(Aabb {
628 min: (sclpt_center - 3).with_z(base + 5),
629 max: (sclpt_center + 2).with_z(base + 6),
630 })
631 .fill(sandstone.clone());
632 painter
633 .sphere(Aabb {
634 min: (sclpt_center - 3).with_z(base + 7),
635 max: (sclpt_center + 2).with_z(base + 8),
636 })
637 .fill(sandstone.clone());
638 painter
639 .sphere(Aabb {
640 min: (sclpt_center - 2).with_z(base + 9),
641 max: (sclpt_center + 1).with_z(base + 12),
642 })
643 .fill(floaty_block.clone());
644 }
645 }
646}