1mod block_mask;
2mod castle;
3pub mod economy;
4pub mod namegen;
5pub mod settlement;
6mod tree;
7
8pub use self::{
10 block_mask::BlockMask, castle::Castle, economy::Economy, settlement::Settlement, tree::Tree,
11};
12
13pub use common::terrain::site::{DungeonKindMeta, SettlementKindMeta, SiteKindMeta};
14
15use crate::{Canvas, column::ColumnSample, site2};
16use common::{calendar::Calendar, generation::ChunkSupplement, resources::TimeOfDay};
17use rand::Rng;
18use serde::Deserialize;
19use vek::*;
20
21#[derive(Deserialize)]
22pub struct Colors {
23 pub castle: castle::Colors,
24 pub settlement: settlement::Colors,
25}
26
27pub struct SpawnRules {
28 pub trees: bool,
29 pub max_warp: f32,
30 pub paths: bool,
31 pub waypoints: bool,
32}
33
34impl SpawnRules {
35 #[must_use]
36 pub fn combine(self, other: Self) -> Self {
37 Self {
39 trees: self.trees && other.trees,
40 max_warp: self.max_warp.min(other.max_warp),
41 paths: self.paths && other.paths,
42 waypoints: self.waypoints && other.waypoints,
43 }
44 }
45}
46
47impl Default for SpawnRules {
48 fn default() -> Self {
49 Self {
50 trees: true,
51 max_warp: 1.0,
52 paths: true,
53 waypoints: true,
54 }
55 }
56}
57
58pub struct Site {
59 pub kind: SiteKind,
60 pub economy: Economy,
61}
62
63pub enum SiteKind {
64 Settlement(Settlement),
65 Castle(Castle),
66 Refactor(site2::Site),
67 CliffTown(site2::Site),
68 SavannahTown(site2::Site),
69 Tree(Tree),
70 DesertCity(site2::Site),
71 ChapelSite(site2::Site),
72 DwarvenMine(site2::Site),
73 CoastalTown(site2::Site),
74 Terracotta(site2::Site),
75 GiantTree(site2::Site),
76 Gnarling(site2::Site),
77 Bridge(site2::Site),
78 Adlet(site2::Site),
79 Haniwa(site2::Site),
80 PirateHideout(site2::Site),
81 JungleRuin(site2::Site),
82 RockCircle(site2::Site),
83 TrollCave(site2::Site),
84 Camp(site2::Site),
85 Cultist(site2::Site),
86 Sahagin(site2::Site),
87 VampireCastle(site2::Site),
88 GliderCourse(site2::Site),
89 Myrmidon(site2::Site),
90}
91
92impl Site {
93 pub fn settlement(s: Settlement) -> Self {
94 Self {
95 kind: SiteKind::Settlement(s),
96 economy: Economy::default(),
97 }
98 }
99
100 pub fn gnarling(g: site2::Site) -> Self {
101 Self {
102 kind: SiteKind::Gnarling(g),
103 economy: Economy::default(),
104 }
105 }
106
107 pub fn adlet(ad: site2::Site) -> Self {
108 Self {
109 kind: SiteKind::Adlet(ad),
110 economy: Economy::default(),
111 }
112 }
113
114 pub fn haniwa(ha: site2::Site) -> Self {
115 Self {
116 kind: SiteKind::Haniwa(ha),
117 economy: Economy::default(),
118 }
119 }
120
121 pub fn castle(c: Castle) -> Self {
122 Self {
123 kind: SiteKind::Castle(c),
124 economy: Economy::default(),
125 }
126 }
127
128 pub fn refactor(s: site2::Site) -> Self {
129 Self {
130 kind: SiteKind::Refactor(s),
131 economy: Economy::default(),
132 }
133 }
134
135 pub fn cliff_town(ct: site2::Site) -> Self {
136 Self {
137 kind: SiteKind::CliffTown(ct),
138 economy: Economy::default(),
139 }
140 }
141
142 pub fn savannah_town(st: site2::Site) -> Self {
143 Self {
144 kind: SiteKind::SavannahTown(st),
145 economy: Economy::default(),
146 }
147 }
148
149 pub fn coastal_town(ct: site2::Site) -> Self {
150 Self {
151 kind: SiteKind::CoastalTown(ct),
152 economy: Economy::default(),
153 }
154 }
155
156 pub fn pirate_hideout(ph: site2::Site) -> Self {
157 Self {
158 kind: SiteKind::PirateHideout(ph),
159 economy: Economy::default(),
160 }
161 }
162
163 pub fn jungle_ruin(jr: site2::Site) -> Self {
164 Self {
165 kind: SiteKind::JungleRuin(jr),
166 economy: Economy::default(),
167 }
168 }
169
170 pub fn rock_circle(rc: site2::Site) -> Self {
171 Self {
172 kind: SiteKind::RockCircle(rc),
173 economy: Economy::default(),
174 }
175 }
176
177 pub fn troll_cave(tc: site2::Site) -> Self {
178 Self {
179 kind: SiteKind::TrollCave(tc),
180 economy: Economy::default(),
181 }
182 }
183
184 pub fn camp(cp: site2::Site) -> Self {
185 Self {
186 kind: SiteKind::Camp(cp),
187 economy: Economy::default(),
188 }
189 }
190
191 pub fn desert_city(dc: site2::Site) -> Self {
192 Self {
193 kind: SiteKind::DesertCity(dc),
194 economy: Economy::default(),
195 }
196 }
197
198 pub fn chapel_site(p: site2::Site) -> Self {
199 Self {
200 kind: SiteKind::ChapelSite(p),
201 economy: Economy::default(),
202 }
203 }
204
205 pub fn cultist(cl: site2::Site) -> Self {
206 Self {
207 kind: SiteKind::Cultist(cl),
208 economy: Economy::default(),
209 }
210 }
211
212 pub fn sahagin(sg: site2::Site) -> Self {
213 Self {
214 kind: SiteKind::Sahagin(sg),
215 economy: Economy::default(),
216 }
217 }
218
219 pub fn vampire_castle(vc: site2::Site) -> Self {
220 Self {
221 kind: SiteKind::VampireCastle(vc),
222 economy: Economy::default(),
223 }
224 }
225
226 pub fn myrmidon(my: site2::Site) -> Self {
227 Self {
228 kind: SiteKind::Myrmidon(my),
229 economy: Economy::default(),
230 }
231 }
232
233 pub fn dwarven_mine(dm: site2::Site) -> Self {
234 Self {
235 kind: SiteKind::DwarvenMine(dm),
236 economy: Economy::default(),
237 }
238 }
239
240 pub fn terracotta(tr: site2::Site) -> Self {
241 Self {
242 kind: SiteKind::Terracotta(tr),
243 economy: Economy::default(),
244 }
245 }
246
247 pub fn tree(t: Tree) -> Self {
248 Self {
249 kind: SiteKind::Tree(t),
250 economy: Economy::default(),
251 }
252 }
253
254 pub fn giant_tree(gt: site2::Site) -> Self {
255 Self {
256 kind: SiteKind::GiantTree(gt),
257 economy: Economy::default(),
258 }
259 }
260
261 pub fn bridge(b: site2::Site) -> Self {
262 Self {
263 kind: SiteKind::Bridge(b),
264 economy: Economy::default(),
265 }
266 }
267
268 pub fn glider_course(g: site2::Site) -> Self {
269 Self {
270 kind: SiteKind::GliderCourse(g),
271 economy: Economy::default(),
272 }
273 }
274
275 pub fn radius(&self) -> f32 {
276 match &self.kind {
277 SiteKind::Settlement(s) => s.radius(),
278 SiteKind::Castle(c) => c.radius(),
279 SiteKind::Refactor(s) => s.radius(),
280 SiteKind::CliffTown(ct) => ct.radius(),
281 SiteKind::SavannahTown(st) => st.radius(),
282 SiteKind::CoastalTown(ct) => ct.radius(),
283 SiteKind::PirateHideout(ph) => ph.radius(),
284 SiteKind::JungleRuin(jr) => jr.radius(),
285 SiteKind::RockCircle(rc) => rc.radius(),
286 SiteKind::TrollCave(tc) => tc.radius(),
287 SiteKind::Camp(cp) => cp.radius(),
288 SiteKind::DesertCity(dc) => dc.radius(),
289 SiteKind::ChapelSite(p) => p.radius(),
290 SiteKind::DwarvenMine(dm) => dm.radius(),
291 SiteKind::Terracotta(tr) => tr.radius(),
292 SiteKind::Tree(t) => t.radius(),
293 SiteKind::GiantTree(gt) => gt.radius(),
294 SiteKind::Gnarling(g) => g.radius(),
295 SiteKind::Bridge(b) => b.radius(),
296 SiteKind::Adlet(ad) => ad.radius(),
297 SiteKind::Haniwa(ha) => ha.radius(),
298 SiteKind::Cultist(cl) => cl.radius(),
299 SiteKind::Sahagin(sg) => sg.radius(),
300 SiteKind::VampireCastle(vc) => vc.radius(),
301 SiteKind::GliderCourse(gc) => gc.radius(),
302 SiteKind::Myrmidon(my) => my.radius(),
303 }
304 }
305
306 pub fn get_origin(&self) -> Vec2<i32> {
307 match &self.kind {
308 SiteKind::Settlement(s) => s.get_origin(),
309 SiteKind::Castle(c) => c.get_origin(),
310 SiteKind::Refactor(s) => s.origin,
311 SiteKind::CliffTown(ct) => ct.origin,
312 SiteKind::SavannahTown(st) => st.origin,
313 SiteKind::CoastalTown(ct) => ct.origin,
314 SiteKind::PirateHideout(ph) => ph.origin,
315 SiteKind::JungleRuin(jr) => jr.origin,
316 SiteKind::RockCircle(rc) => rc.origin,
317 SiteKind::TrollCave(tc) => tc.origin,
318 SiteKind::Camp(cp) => cp.origin,
319 SiteKind::DesertCity(dc) => dc.origin,
320 SiteKind::ChapelSite(p) => p.origin,
321 SiteKind::DwarvenMine(dm) => dm.origin,
322 SiteKind::Terracotta(tr) => tr.origin,
323 SiteKind::Tree(t) => t.origin,
324 SiteKind::GiantTree(gt) => gt.origin,
325 SiteKind::Gnarling(g) => g.origin,
326 SiteKind::Bridge(b) => b.origin,
327 SiteKind::Adlet(ad) => ad.origin,
328 SiteKind::Haniwa(ha) => ha.origin,
329 SiteKind::Cultist(cl) => cl.origin,
330 SiteKind::Sahagin(sg) => sg.origin,
331 SiteKind::VampireCastle(vc) => vc.origin,
332 SiteKind::GliderCourse(gc) => gc.origin,
333 SiteKind::Myrmidon(my) => my.origin,
334 }
335 }
336
337 pub fn spawn_rules(&self, wpos: Vec2<i32>) -> SpawnRules {
338 match &self.kind {
339 SiteKind::Settlement(s) => s.spawn_rules(wpos),
340 SiteKind::Castle(c) => c.spawn_rules(wpos),
341 SiteKind::Refactor(s) => s.spawn_rules(wpos),
342 SiteKind::CliffTown(ct) => ct.spawn_rules(wpos),
343 SiteKind::SavannahTown(st) => st.spawn_rules(wpos),
344 SiteKind::CoastalTown(ct) => ct.spawn_rules(wpos),
345 SiteKind::PirateHideout(ph) => ph.spawn_rules(wpos),
346 SiteKind::JungleRuin(jr) => jr.spawn_rules(wpos),
347 SiteKind::RockCircle(rc) => rc.spawn_rules(wpos),
348 SiteKind::TrollCave(tc) => tc.spawn_rules(wpos),
349 SiteKind::Camp(cp) => cp.spawn_rules(wpos),
350 SiteKind::DesertCity(dc) => dc.spawn_rules(wpos),
351 SiteKind::ChapelSite(p) => p.spawn_rules(wpos),
352 SiteKind::DwarvenMine(dm) => dm.spawn_rules(wpos),
353 SiteKind::Terracotta(tr) => tr.spawn_rules(wpos),
354 SiteKind::Tree(t) => t.spawn_rules(wpos),
355 SiteKind::GiantTree(gt) => gt.spawn_rules(wpos),
356 SiteKind::Gnarling(g) => g.spawn_rules(wpos),
357 SiteKind::Bridge(b) => b.spawn_rules(wpos),
358 SiteKind::Adlet(ad) => ad.spawn_rules(wpos),
359 SiteKind::Haniwa(ha) => ha.spawn_rules(wpos),
360 SiteKind::Cultist(cl) => cl.spawn_rules(wpos),
361 SiteKind::Sahagin(sg) => sg.spawn_rules(wpos),
362 SiteKind::VampireCastle(vc) => vc.spawn_rules(wpos),
363 SiteKind::GliderCourse(gc) => gc.spawn_rules(wpos),
364 SiteKind::Myrmidon(my) => my.spawn_rules(wpos),
365 }
366 }
367
368 pub fn name(&self) -> &str {
369 match &self.kind {
370 SiteKind::Settlement(s) => s.name(),
371 SiteKind::Castle(c) => c.name(),
372 SiteKind::Refactor(s) => s.name(),
373 SiteKind::CliffTown(ct) => ct.name(),
374 SiteKind::SavannahTown(st) => st.name(),
375 SiteKind::CoastalTown(ct) => ct.name(),
376 SiteKind::PirateHideout(ph) => ph.name(),
377 SiteKind::JungleRuin(jr) => jr.name(),
378 SiteKind::RockCircle(rc) => rc.name(),
379 SiteKind::TrollCave(tc) => tc.name(),
380 SiteKind::Camp(cp) => cp.name(),
381 SiteKind::DesertCity(dc) => dc.name(),
382 SiteKind::ChapelSite(p) => p.name(),
383 SiteKind::Terracotta(tr) => tr.name(),
384 SiteKind::DwarvenMine(dm) => dm.name(),
385 SiteKind::Tree(_) => "Giant Tree",
386 SiteKind::GiantTree(gt) => gt.name(),
387 SiteKind::Gnarling(g) => g.name(),
388 SiteKind::Bridge(b) => b.name(),
389 SiteKind::Adlet(ad) => ad.name(),
390 SiteKind::Haniwa(ha) => ha.name(),
391 SiteKind::Cultist(cl) => cl.name(),
392 SiteKind::Sahagin(sg) => sg.name(),
393 SiteKind::VampireCastle(vc) => vc.name(),
394 SiteKind::GliderCourse(gc) => gc.name(),
395 SiteKind::Myrmidon(my) => my.name(),
396 }
397 }
398
399 pub fn trade_information(
400 &self,
401 site_id: common::trade::SiteId,
402 ) -> Option<common::trade::SiteInformation> {
403 match &self.kind {
404 SiteKind::Settlement(_)
405 | SiteKind::Refactor(_)
406 | SiteKind::CliffTown(_)
407 | SiteKind::SavannahTown(_)
408 | SiteKind::CoastalTown(_)
409 | SiteKind::DesertCity(_) => Some(common::trade::SiteInformation {
410 id: site_id,
411 unconsumed_stock: self.economy.get_available_stock(),
412 }),
413 _ => None,
414 }
415 }
416
417 pub fn apply_to(&self, canvas: &mut Canvas, dynamic_rng: &mut impl Rng) {
418 let info = canvas.info();
419 let get_col = |wpos| info.col(wpos + info.wpos);
420 match &self.kind {
421 SiteKind::Settlement(s) => s.apply_to(canvas.index, canvas.wpos, get_col, canvas.chunk),
422 SiteKind::Castle(c) => c.apply_to(canvas.index, canvas.wpos, get_col, canvas.chunk),
423 SiteKind::Refactor(s) => s.render(canvas, dynamic_rng),
424 SiteKind::CliffTown(ct) => ct.render(canvas, dynamic_rng),
425 SiteKind::SavannahTown(st) => st.render(canvas, dynamic_rng),
426 SiteKind::CoastalTown(ct) => ct.render(canvas, dynamic_rng),
427 SiteKind::PirateHideout(ph) => ph.render(canvas, dynamic_rng),
428 SiteKind::JungleRuin(jr) => jr.render(canvas, dynamic_rng),
429 SiteKind::RockCircle(rc) => rc.render(canvas, dynamic_rng),
430 SiteKind::TrollCave(tc) => tc.render(canvas, dynamic_rng),
431 SiteKind::Camp(cp) => cp.render(canvas, dynamic_rng),
432 SiteKind::DesertCity(dc) => dc.render(canvas, dynamic_rng),
433 SiteKind::ChapelSite(p) => p.render(canvas, dynamic_rng),
434 SiteKind::Terracotta(tr) => tr.render(canvas, dynamic_rng),
435 SiteKind::DwarvenMine(dm) => dm.render(canvas, dynamic_rng),
436 SiteKind::Tree(t) => t.render(canvas, dynamic_rng),
437 SiteKind::GiantTree(gt) => gt.render(canvas, dynamic_rng),
438 SiteKind::Gnarling(g) => g.render(canvas, dynamic_rng),
439 SiteKind::Bridge(b) => b.render(canvas, dynamic_rng),
440 SiteKind::Adlet(ad) => ad.render(canvas, dynamic_rng),
441 SiteKind::Haniwa(ha) => ha.render(canvas, dynamic_rng),
442 SiteKind::Cultist(cl) => cl.render(canvas, dynamic_rng),
443 SiteKind::Sahagin(sg) => sg.render(canvas, dynamic_rng),
444 SiteKind::VampireCastle(vc) => vc.render(canvas, dynamic_rng),
445 SiteKind::GliderCourse(gc) => gc.render(canvas, dynamic_rng),
446 SiteKind::Myrmidon(my) => my.render(canvas, dynamic_rng),
447 }
448 }
449
450 pub fn apply_supplement<'a>(
451 &'a self,
452 dynamic_rng: &mut impl Rng,
454 wpos2d: Vec2<i32>,
455 get_column: impl FnMut(Vec2<i32>) -> Option<&'a ColumnSample<'a>>,
456 supplement: &mut ChunkSupplement,
457 site_id: common::trade::SiteId,
458 time: Option<&(TimeOfDay, Calendar)>,
459 ) {
460 match &self.kind {
461 SiteKind::Settlement(s) => {
462 let economy = self
463 .trade_information(site_id)
464 .expect("Settlement has no economy");
465 s.apply_supplement(dynamic_rng, wpos2d, get_column, supplement, economy, time)
466 },
467 SiteKind::Castle(c) => c.apply_supplement(dynamic_rng, wpos2d, get_column, supplement),
468 SiteKind::Refactor(_)
469 | SiteKind::CliffTown(_)
470 | SiteKind::SavannahTown(_)
471 | SiteKind::CoastalTown(_)
472 | SiteKind::PirateHideout(_)
473 | SiteKind::JungleRuin(_)
474 | SiteKind::RockCircle(_)
475 | SiteKind::TrollCave(_)
476 | SiteKind::Camp(_)
477 | SiteKind::DesertCity(_)
478 | SiteKind::GliderCourse(_)
479 | SiteKind::Tree(_) => {},
480 SiteKind::ChapelSite(p) => p.apply_supplement(dynamic_rng, wpos2d, supplement),
481 SiteKind::Terracotta(tr) => tr.apply_supplement(dynamic_rng, wpos2d, supplement),
482 SiteKind::DwarvenMine(dm) => dm.apply_supplement(dynamic_rng, wpos2d, supplement),
483 SiteKind::GiantTree(gt) => gt.apply_supplement(dynamic_rng, wpos2d, supplement),
484 SiteKind::Gnarling(g) => g.apply_supplement(dynamic_rng, wpos2d, supplement),
485 SiteKind::Bridge(b) => b.apply_supplement(dynamic_rng, wpos2d, supplement),
486 SiteKind::Adlet(ad) => ad.apply_supplement(dynamic_rng, wpos2d, supplement),
487 SiteKind::Haniwa(ha) => ha.apply_supplement(dynamic_rng, wpos2d, supplement),
488 SiteKind::Cultist(cl) => cl.apply_supplement(dynamic_rng, wpos2d, supplement),
489 SiteKind::Sahagin(sg) => sg.apply_supplement(dynamic_rng, wpos2d, supplement),
490 SiteKind::VampireCastle(vc) => vc.apply_supplement(dynamic_rng, wpos2d, supplement),
491 SiteKind::Myrmidon(my) => my.apply_supplement(dynamic_rng, wpos2d, supplement),
492 }
493 }
494
495 pub fn do_economic_simulation(&self) -> bool {
496 matches!(
497 self.kind,
498 SiteKind::Refactor(_)
499 | SiteKind::CliffTown(_)
500 | SiteKind::SavannahTown(_)
501 | SiteKind::CoastalTown(_)
502 | SiteKind::DesertCity(_)
503 | SiteKind::Settlement(_)
504 )
505 }
506
507 pub fn site2(&self) -> Option<&site2::Site> {
510 match &self.kind {
511 SiteKind::Settlement(_) => None,
512 SiteKind::Castle(_) => None,
513 SiteKind::Refactor(site2) => Some(site2),
514 SiteKind::CliffTown(site2) => Some(site2),
515 SiteKind::SavannahTown(site2) => Some(site2),
516 SiteKind::CoastalTown(site2) => Some(site2),
517 SiteKind::PirateHideout(site2) => Some(site2),
518 SiteKind::JungleRuin(site2) => Some(site2),
519 SiteKind::RockCircle(site2) => Some(site2),
520 SiteKind::TrollCave(site2) => Some(site2),
521 SiteKind::Camp(site2) => Some(site2),
522 SiteKind::Tree(_) => None,
523 SiteKind::DesertCity(site2) => Some(site2),
524 SiteKind::ChapelSite(site2) => Some(site2),
525 SiteKind::DwarvenMine(site2) => Some(site2),
526 SiteKind::Terracotta(site2) => Some(site2),
527 SiteKind::GiantTree(site2) => Some(site2),
528 SiteKind::Gnarling(site2) => Some(site2),
529 SiteKind::Bridge(site2) => Some(site2),
530 SiteKind::Adlet(site2) => Some(site2),
531 SiteKind::Haniwa(site2) => Some(site2),
532 SiteKind::Cultist(site2) => Some(site2),
533 SiteKind::Sahagin(site2) => Some(site2),
534 SiteKind::VampireCastle(site2) => Some(site2),
535 SiteKind::GliderCourse(site2) => Some(site2),
536 SiteKind::Myrmidon(site2) => Some(site2),
537 }
538 }
539}
540
541impl SiteKind {
542 pub fn convert_to_meta(&self) -> Option<SiteKindMeta> {
543 match self {
544 SiteKind::Refactor(_) | SiteKind::Settlement(_) => {
545 Some(SiteKindMeta::Settlement(SettlementKindMeta::Default))
546 },
547 SiteKind::CliffTown(_) => Some(SiteKindMeta::Settlement(SettlementKindMeta::CliffTown)),
548 SiteKind::SavannahTown(_) => {
549 Some(SiteKindMeta::Settlement(SettlementKindMeta::SavannahTown))
550 },
551 SiteKind::CoastalTown(_) => {
552 Some(SiteKindMeta::Settlement(SettlementKindMeta::CoastalTown))
553 },
554 SiteKind::DesertCity(_) => {
555 Some(SiteKindMeta::Settlement(SettlementKindMeta::DesertCity))
556 },
557 SiteKind::Gnarling(_) => Some(SiteKindMeta::Dungeon(DungeonKindMeta::Gnarling)),
558 SiteKind::Adlet(_) => Some(SiteKindMeta::Dungeon(DungeonKindMeta::Adlet)),
559 SiteKind::Terracotta(_) => Some(SiteKindMeta::Dungeon(DungeonKindMeta::Terracotta)),
560 SiteKind::Haniwa(_) => Some(SiteKindMeta::Dungeon(DungeonKindMeta::Haniwa)),
561 SiteKind::Myrmidon(_) => Some(SiteKindMeta::Dungeon(DungeonKindMeta::Myrmidon)),
562 SiteKind::DwarvenMine(_) => Some(SiteKindMeta::Dungeon(DungeonKindMeta::DwarvenMine)),
563 SiteKind::ChapelSite(_) => Some(SiteKindMeta::Dungeon(DungeonKindMeta::SeaChapel)),
564 SiteKind::Cultist(_) => Some(SiteKindMeta::Dungeon(DungeonKindMeta::Cultist)),
565 SiteKind::Sahagin(_) => Some(SiteKindMeta::Dungeon(DungeonKindMeta::Sahagin)),
566 SiteKind::VampireCastle(_) => {
567 Some(SiteKindMeta::Dungeon(DungeonKindMeta::VampireCastle))
568 },
569
570 _ => None,
571 }
572 }
573}