Skip to main content

nil_core/world/infrastructure/building/
mod.rs

1// Copyright (C) Call of Nil contributors
2// SPDX-License-Identifier: AGPL-3.0-only
3
4mod academy;
5mod prefecture;
6mod stable;
7mod workshop;
8
9use crate::continent::coord::Coord;
10use crate::continent::index::ContinentKey;
11use crate::error::Result;
12use crate::infrastructure::prelude::{BuildingId, BuildingLevel};
13use crate::world::World;
14
15impl World {
16  /// Sets the level of a building.
17  ///
18  /// Does **NOT** emit any events.
19  pub(crate) fn set_building_level(
20    &mut self,
21    key: impl ContinentKey,
22    id: BuildingId,
23    level: BuildingLevel,
24  ) -> Result<()> {
25    self
26      .city_mut(key)?
27      .infrastructure_mut()
28      .building_mut(id)
29      .set_level(level);
30
31    Ok(())
32  }
33
34  pub fn toggle_building(&mut self, coord: Coord, id: BuildingId, enabled: bool) -> Result<()> {
35    self
36      .continent
37      .city_mut(coord)?
38      .infrastructure_mut()
39      .building_mut(id)
40      .toggle(enabled);
41
42    self.emit_city(coord)?;
43
44    Ok(())
45  }
46}
47
48#[doc(hidden)]
49#[macro_export]
50macro_rules! decl_world_recruit_order_fn {
51  ($building:ident) => {
52    paste::paste! {
53      impl World {
54        pub fn [<add_ $building:snake _recruit_order>](
55          &mut self,
56          req: &[<$building RecruitOrderRequest>]
57        ) -> Result<()> {
58          let player_id = self.city(req.coord)?.player().cloned();
59          let curr_res = if let Some(id) = &player_id {
60            Some(self.player(id)?.resources().clone())
61          } else {
62            None
63          };
64
65          let order = self
66            .city_mut(req.coord)?
67            .infrastructure_mut()
68            .[<add_ $building:snake _recruit_order>](req, curr_res.as_ref())?
69            .clone();
70
71          if let Some(id) = player_id {
72            let player = self.player_mut(&id)?;
73            let resources = player.resources_mut();
74            *resources = resources
75              .checked_sub(order.resources())
76              .ok_or(Error::InsufficientResources)?;
77
78            self.emit_player(id)?;
79            self.emit_city(req.coord)?;
80          }
81
82          Ok(())
83        }
84
85        pub fn [<cancel_ $building:snake _recruit_order>](
86          &mut self,
87          coord: Coord,
88          id: [<$building RecruitOrderId>]
89        ) -> Result<()> {
90          let city = self.city_mut(coord)?;
91          let order = city
92            .infrastructure_mut()
93            .[<cancel_ $building:snake _recruit_order>](id);
94
95          if let Some(order) = order
96            && let Some(id) = city.player().cloned()
97          {
98            let player = self.player_mut(&id)?;
99            let resources = player.resources_mut();
100            *resources += order.resources();
101
102            self.emit_player(id)?;
103            self.emit_city(coord)?;
104          }
105
106          Ok(())
107        }
108      }
109    }
110  };
111}