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 self.door_tile().is_some()
135 }
136
137 pub fn is_workshop(&self) -> bool {
138 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#[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}