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