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