Skip to main content

veloren_world/site/plot/
mod.rs

1mod adlet;
2mod airship_dock;
3mod barn;
4mod bridge;
5mod building;
6mod camp;
7mod castle;
8mod citadel;
9mod cliff_tower;
10mod cliff_town_airship_dock;
11mod coastal_airship_dock;
12mod coastal_house;
13mod coastal_workshop;
14mod cultist;
15mod desert_city_airship_dock;
16mod desert_city_arena;
17mod desert_city_multiplot;
18mod desert_city_temple;
19mod dwarven_mine;
20mod farm_field;
21mod giant_tree;
22mod glider_finish;
23mod glider_platform;
24mod glider_ring;
25mod gnarling;
26mod haniwa;
27mod house;
28mod jungle_ruin;
29mod myrmidon_arena;
30mod myrmidon_house;
31mod pirate_hideout;
32mod plaza;
33mod road;
34mod rock_circle;
35mod sahagin;
36mod savannah_airship_dock;
37mod savannah_guard_hut;
38mod savannah_hut;
39mod savannah_workshop;
40mod sea_chapel;
41pub mod tavern;
42mod terracotta_house;
43mod terracotta_palace;
44mod terracotta_yard;
45mod troll_cave;
46mod vampire_castle;
47mod workshop;
48
49pub use self::{
50    adlet::AdletStronghold,
51    airship_dock::AirshipDock,
52    barn::Barn,
53    bridge::Bridge,
54    building::Building,
55    camp::Camp,
56    castle::Castle,
57    citadel::Citadel,
58    cliff_tower::CliffTower,
59    cliff_town_airship_dock::CliffTownAirshipDock,
60    coastal_airship_dock::CoastalAirshipDock,
61    coastal_house::CoastalHouse,
62    coastal_workshop::CoastalWorkshop,
63    cultist::Cultist,
64    desert_city_airship_dock::DesertCityAirshipDock,
65    desert_city_arena::DesertCityArena,
66    desert_city_multiplot::DesertCityMultiPlot,
67    desert_city_temple::DesertCityTemple,
68    dwarven_mine::DwarvenMine,
69    farm_field::FarmField,
70    giant_tree::GiantTree,
71    glider_finish::GliderFinish,
72    glider_platform::GliderPlatform,
73    glider_ring::GliderRing,
74    gnarling::GnarlingFortification,
75    haniwa::Haniwa,
76    house::House,
77    jungle_ruin::JungleRuin,
78    myrmidon_arena::MyrmidonArena,
79    myrmidon_house::MyrmidonHouse,
80    pirate_hideout::PirateHideout,
81    plaza::Plaza,
82    road::{Road, RoadKind, RoadLights, RoadMaterial},
83    rock_circle::RockCircle,
84    sahagin::Sahagin,
85    savannah_airship_dock::SavannahAirshipDock,
86    savannah_guard_hut::SavannahGuardHut,
87    savannah_hut::SavannahHut,
88    savannah_workshop::SavannahWorkshop,
89    sea_chapel::SeaChapel,
90    tavern::Tavern,
91    terracotta_house::TerracottaHouse,
92    terracotta_palace::TerracottaPalace,
93    terracotta_yard::TerracottaYard,
94    troll_cave::TrollCave,
95    vampire_castle::VampireCastle,
96    workshop::Workshop,
97};
98
99use super::*;
100use crate::{ColumnSample, util::DHashSet};
101use common::{match_some, path::Path};
102use rand_chacha::ChaCha8Rng;
103use vek::*;
104
105pub struct Plot {
106    pub(crate) kind: PlotKind,
107    pub(crate) root_tile: Vec2<i32>,
108    pub(crate) tiles: DHashSet<Vec2<i32>>,
109}
110
111impl Plot {
112    pub fn find_bounds(&self) -> Aabr<i32> {
113        self.tiles
114            .iter()
115            .fold(Aabr::new_empty(self.root_tile), |b, t| {
116                b.expanded_to_contain_point(*t)
117            })
118    }
119
120    pub fn z_range(&self) -> Option<Range<i32>> {
121        match_some!(&self.kind, PlotKind::House(house) => house.z_range())
122    }
123
124    pub fn kind(&self) -> &PlotKind { &self.kind }
125
126    pub fn root_tile(&self) -> Vec2<i32> { self.root_tile }
127
128    pub fn tiles(&self) -> impl ExactSizeIterator<Item = Vec2<i32>> + '_ {
129        self.tiles.iter().copied()
130    }
131
132    pub fn is_house(&self) -> bool {
133        // TODO: Better than this
134        self.door_tile().is_some()
135    }
136
137    pub fn is_workshop(&self) -> bool {
138        // TODO: Better than this
139        matches!(
140            &self.kind,
141            PlotKind::Workshop(_) | PlotKind::CoastalWorkshop(_) | PlotKind::SavannahWorkshop(_)
142        )
143    }
144}
145
146#[derive(strum::Display)]
147pub enum PlotKind {
148    House(House),
149    AirshipDock(AirshipDock),
150    GliderRing(GliderRing),
151    GliderPlatform(GliderPlatform),
152    GliderFinish(GliderFinish),
153    Tavern(Tavern),
154    CoastalAirshipDock(CoastalAirshipDock),
155    CoastalHouse(CoastalHouse),
156    CoastalWorkshop(CoastalWorkshop),
157    Workshop(Workshop),
158    DesertCityMultiPlot(DesertCityMultiPlot),
159    DesertCityTemple(DesertCityTemple),
160    DesertCityArena(DesertCityArena),
161    DesertCityAirshipDock(DesertCityAirshipDock),
162    SeaChapel(SeaChapel),
163    JungleRuin(JungleRuin),
164    Plaza(Plaza),
165    Castle(Castle),
166    Cultist(Cultist),
167    Road(Road),
168    Gnarling(GnarlingFortification),
169    Adlet(AdletStronghold),
170    Haniwa(Haniwa),
171    GiantTree(GiantTree),
172    CliffTower(CliffTower),
173    CliffTownAirshipDock(CliffTownAirshipDock),
174    Sahagin(Sahagin),
175    Citadel(Citadel),
176    SavannahAirshipDock(SavannahAirshipDock),
177    SavannahGuardHut(SavannahGuardHut),
178    SavannahHut(SavannahHut),
179    SavannahWorkshop(SavannahWorkshop),
180    Barn(Barn),
181    Bridge(Bridge),
182    PirateHideout(PirateHideout),
183    RockCircle(RockCircle),
184    TrollCave(TrollCave),
185    Camp(Camp),
186    DwarvenMine(DwarvenMine),
187    TerracottaPalace(TerracottaPalace),
188    TerracottaHouse(TerracottaHouse),
189    TerracottaYard(TerracottaYard),
190    FarmField(FarmField),
191    VampireCastle(VampireCastle),
192    MyrmidonArena(MyrmidonArena),
193    MyrmidonHouse(MyrmidonHouse),
194    Building(Building),
195}
196
197/// # Syntax
198/// ```ignore
199/// foreach_plot!(expr, plot => plot.something())
200/// ```
201#[macro_export]
202macro_rules! foreach_plot {
203    ($p:expr, $x:ident => $y:expr $(,)?) => {
204        match $p {
205            PlotKind::House($x) => $y,
206            PlotKind::AirshipDock($x) => $y,
207            PlotKind::CoastalAirshipDock($x) => $y,
208            PlotKind::CoastalHouse($x) => $y,
209            PlotKind::CoastalWorkshop($x) => $y,
210            PlotKind::Workshop($x) => $y,
211            PlotKind::DesertCityAirshipDock($x) => $y,
212            PlotKind::DesertCityMultiPlot($x) => $y,
213            PlotKind::DesertCityTemple($x) => $y,
214            PlotKind::DesertCityArena($x) => $y,
215            PlotKind::SeaChapel($x) => $y,
216            PlotKind::JungleRuin($x) => $y,
217            PlotKind::Plaza($x) => $y,
218            PlotKind::Castle($x) => $y,
219            PlotKind::Road($x) => $y,
220            PlotKind::Gnarling($x) => $y,
221            PlotKind::Adlet($x) => $y,
222            PlotKind::GiantTree($x) => $y,
223            PlotKind::CliffTower($x) => $y,
224            PlotKind::CliffTownAirshipDock($x) => $y,
225            PlotKind::Citadel($x) => $y,
226            PlotKind::SavannahAirshipDock($x) => $y,
227            PlotKind::SavannahGuardHut($x) => $y,
228            PlotKind::SavannahHut($x) => $y,
229            PlotKind::SavannahWorkshop($x) => $y,
230            PlotKind::Barn($x) => $y,
231            PlotKind::Bridge($x) => $y,
232            PlotKind::PirateHideout($x) => $y,
233            PlotKind::Tavern($x) => $y,
234            PlotKind::Cultist($x) => $y,
235            PlotKind::Haniwa($x) => $y,
236            PlotKind::Sahagin($x) => $y,
237            PlotKind::RockCircle($x) => $y,
238            PlotKind::TrollCave($x) => $y,
239            PlotKind::Camp($x) => $y,
240            PlotKind::DwarvenMine($x) => $y,
241            PlotKind::TerracottaPalace($x) => $y,
242            PlotKind::TerracottaHouse($x) => $y,
243            PlotKind::TerracottaYard($x) => $y,
244            PlotKind::FarmField($x) => $y,
245            PlotKind::VampireCastle($x) => $y,
246            PlotKind::GliderRing($x) => $y,
247            PlotKind::GliderPlatform($x) => $y,
248            PlotKind::GliderFinish($x) => $y,
249            PlotKind::MyrmidonArena($x) => $y,
250            PlotKind::MyrmidonHouse($x) => $y,
251            PlotKind::Building($x) => $y,
252        }
253    };
254}
255
256pub use foreach_plot;
257
258impl Structure for Plot {
259    #[cfg(feature = "dyn-lib")]
260    #[unsafe(export_name = "as_dyn_structure_plot")]
261    fn as_dyn_outer(&self) -> Option<(&dyn Structure, &'static str)> {
262        Some((Self::as_dyn_impl(self), "as_dyn_structure_plot"))
263    }
264
265    fn render_inner(&self, site: &Site, land: &Land, painter: &Painter) {
266        foreach_plot!(&self.kind, plot => plot.render(site, land, painter))
267    }
268
269    fn spawn_rules_inner(
270        &self,
271        spawn_rules: &mut SpawnRules,
272        land: &Land,
273        wpos: Vec2<i32>,
274        weight: f32,
275    ) {
276        foreach_plot!(&self.kind, plot => plot.spawn_rules(spawn_rules, land, wpos, weight))
277    }
278
279    fn rel_terrain_offset(&self, col: &ColumnSample) -> i32 {
280        foreach_plot!(&self.kind, plot => plot.rel_terrain_offset(col))
281    }
282
283    fn terrain_surface_at_inner(
284        &self,
285        wpos: Vec2<i32>,
286        old: Block,
287        rng: &mut ChaCha8Rng,
288        col: &ColumnSample,
289        z_off: i32,
290        site: &Site,
291    ) -> Option<Block> {
292        foreach_plot!(&self.kind, plot => plot.terrain_surface_at(wpos, old, rng, col, z_off, site))
293    }
294
295    fn airship_dock_info(&self) -> Option<AirshipDockInfo<'_>> {
296        foreach_plot!(&self.kind, plot => plot.airship_dock_info())
297    }
298
299    fn door_tile(&self) -> Option<Vec2<i32>> { foreach_plot!(&self.kind, plot => plot.door_tile()) }
300
301    fn render_ordering(&self) -> u32 { foreach_plot!(&self.kind, plot => plot.render_ordering()) }
302}
303
304pub struct AirshipDockInfo<'plot> {
305    pub door_tile: Vec2<i32>,
306    pub center: Vec2<i32>,
307    pub docking_positions: &'plot [Vec3<i32>],
308}