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