veloren_world/site/settlement/
town.rs

1use super::{AREA_SIZE, GenCtx};
2use common::store::Store;
3use rand::prelude::*;
4use vek::*;
5
6pub struct Town {
7    pub base_tile: Vec2<i32>,
8    radius: i32,
9    districts: Store<District>,
10}
11
12impl Town {
13    pub fn districts(&self) -> &Store<District> { &self.districts }
14
15    pub fn generate(origin: Vec2<i32>, base_tile: Vec2<i32>, ctx: &mut GenCtx<impl Rng>) -> Self {
16        let mut this = Self {
17            base_tile,
18            radius: 4,
19            districts: Store::default(),
20        };
21
22        this.generate_districts(origin, ctx);
23
24        this
25    }
26
27    fn generate_districts(&mut self, origin: Vec2<i32>, ctx: &mut GenCtx<impl Rng>) {
28        let base_aabr = Aabr {
29            min: self.base_tile - self.radius,
30            max: self.base_tile + self.radius,
31        };
32
33        gen_plot(base_aabr, ctx).for_each(base_aabr, &mut |aabr| {
34            if aabr.center().distance_squared(self.base_tile) < self.radius.pow(2) {
35                self.districts.insert(District {
36                    seed: ctx.rng.gen(),
37                    aabr,
38                    alt: ctx
39                        .sim
40                        .and_then(|sim| {
41                            sim.get_alt_approx(
42                                origin + aabr.center() * AREA_SIZE as i32 + AREA_SIZE as i32 / 2,
43                            )
44                        })
45                        .unwrap_or(0.0) as i32,
46                });
47            }
48        });
49    }
50}
51
52pub struct District {
53    pub seed: u32,
54    pub aabr: Aabr<i32>,
55    pub alt: i32,
56}
57
58enum Plot {
59    District,
60    Parent(Vec<(Aabr<i32>, Plot)>),
61}
62
63impl Plot {
64    fn for_each(&self, aabr: Aabr<i32>, f: &mut impl FnMut(Aabr<i32>)) {
65        match self {
66            Plot::District => f(aabr),
67            Plot::Parent(children) => children.iter().for_each(|(aabr, p)| p.for_each(*aabr, f)),
68        }
69    }
70}
71
72fn gen_plot(aabr: Aabr<i32>, ctx: &mut GenCtx<impl Rng>) -> Plot {
73    if aabr.size().product() <= 9 {
74        Plot::District
75    } else if aabr.size().w < aabr.size().h {
76        let [a, b] = aabr.split_at_y(aabr.min.y + ctx.rng.gen_range(1..aabr.size().h));
77        Plot::Parent(vec![(a, gen_plot(a, ctx)), (b, gen_plot(b, ctx))])
78    } else {
79        let [a, b] = aabr.split_at_x(aabr.min.x + ctx.rng.gen_range(1..aabr.size().w));
80        Plot::Parent(vec![(a, gen_plot(a, ctx)), (b, gen_plot(b, ctx))])
81    }
82}