Skip to main content

nil_core/world/cheat/
city.rs

1// Copyright (C) Call of Nil contributors
2// SPDX-License-Identifier: AGPL-3.0-only
3
4use crate::bail_if_cheats_are_not_allowed;
5use crate::city::City;
6use crate::city::stability::Stability;
7use crate::continent::field::Field;
8use crate::continent::index::ContinentKey;
9use crate::error::{Error, Result};
10use crate::ruler::Ruler;
11use crate::world::World;
12use itertools::Itertools;
13
14pub fn fill_world(world: &mut World, ruler: &Ruler) -> Result<()> {
15  bail_if_cheats_are_not_allowed!(world);
16
17  let size = world.continent.size();
18  let coords = world
19    .continent
20    .enumerate_fields()
21    .filter(|(_, field)| field.is_empty())
22    .filter_map(|(idx, _)| idx.to_coord(size).ok())
23    .collect_vec();
24
25  for coord in coords {
26    spawn_city_with_emit(world)
27      .ruler(ruler)
28      .key(coord)
29      .emit(false)
30      .call()?;
31
32    world.emit_public_city(coord)?;
33  }
34
35  if let Some(player) = ruler.player() {
36    world.emit_player(player.clone())?;
37  }
38
39  Ok(())
40}
41
42pub fn get_city(world: &World, key: impl ContinentKey) -> Result<&City> {
43  bail_if_cheats_are_not_allowed!(world);
44  world.continent.city(key)
45}
46
47pub fn set_stability(
48  world: &mut World,
49  key: impl ContinentKey,
50  stability: Stability,
51) -> Result<()> {
52  bail_if_cheats_are_not_allowed!(world);
53
54  let coord = key.into_coord(world.continent.size())?;
55  let city = world.city_mut(coord)?;
56  *city.stability_mut() = stability;
57
58  world.emit_city(coord)?;
59
60  Ok(())
61}
62
63pub fn spawn_city(world: &mut World, ruler: &Ruler, key: impl ContinentKey) -> Result<()> {
64  spawn_city_with_emit(world)
65    .ruler(ruler)
66    .key(key)
67    .emit(true)
68    .call()
69}
70
71#[bon::builder]
72fn spawn_city_with_emit(
73  #[builder(start_fn)] world: &mut World,
74  ruler: &Ruler,
75  key: impl ContinentKey,
76  emit: bool,
77) -> Result<()> {
78  bail_if_cheats_are_not_allowed!(world);
79
80  let coord = key.into_coord(world.continent.size())?;
81  let city = City::builder(coord)
82    .name(ruler)
83    .owner(ruler.clone())
84    .build();
85
86  let field = world.continent.field_mut(coord)?;
87  if field.is_empty() {
88    *field = Field::City { city: Box::new(city) };
89
90    if emit {
91      world.emit_public_city(coord)?;
92      if let Some(player) = ruler.player() {
93        world.emit_player(player.clone())?;
94      }
95    }
96  } else {
97    return Err(Error::FieldNotEmpty(coord));
98  }
99
100  Ok(())
101}