veloren_world/site/
mod.rs

1mod block_mask;
2mod castle;
3pub mod economy;
4pub mod namegen;
5pub mod settlement;
6mod tree;
7
8// Reexports
9pub 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        // Should be commutative
38        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        // NOTE: Used only for dynamic elements like chests and entities!
453        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    /// Return the inner site2 site, if this site has one.
508    // TODO: Remove all of this when site1 gets removed.
509    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}