nil_core/world/round/
mod.rs1mod behavior;
5mod maneuver;
6
7use crate::error::Result;
8use crate::player::{Player, PlayerId};
9use crate::resources::prelude::*;
10use crate::ruler::Ruler;
11use crate::world::World;
12use std::collections::HashMap;
13
14impl World {
15 pub fn start_round(&mut self) -> Result<()> {
16 if self.round.is_idle() {
17 let ids = self
18 .player_manager
19 .active_players()
20 .map(Player::id);
21
22 self.round.start(ids)?;
23 self.emit_round_updated();
24 }
25
26 Ok(())
27 }
28
29 pub fn set_player_ready(&mut self, player: &PlayerId, is_ready: bool) -> Result<()> {
30 self.round.set_ready(player, is_ready);
31
32 if self.round.is_done() {
33 self.next_round(true)?;
34 } else {
35 self.emit_round_updated();
36 }
37
38 Ok(())
39 }
40
41 pub(super) fn next_round(&mut self, emit: bool) -> Result<()> {
42 let ids = self
43 .player_manager
44 .active_players()
45 .map(Player::id);
46
47 self.round.next(ids)?;
48 self.prepare_next_round()?;
49 self.consume_pending_save()?;
50
51 if emit {
52 self.emit_round_updated();
53 }
54
55 if let Some(on_next_round) = self.on_next_round.clone() {
56 on_next_round.call(self);
57 }
58
59 Ok(())
60 }
61
62 fn prepare_next_round(&mut self) -> Result<()> {
63 self.update_resources()?;
64 self.process_city_queues();
65 self.collapse_armies();
66 self.process_maneuvers()?;
67 self.update_ranking()?;
68 self.process_npc_behavior()?;
69 Ok(())
70 }
71
72 fn update_resources(&mut self) -> Result<()> {
75 let stats = self.stats.infrastructure.as_ref();
76 let mut diff: HashMap<Ruler, ResourcesDiff> = HashMap::new();
77
78 for city in self.continent.cities() {
79 let owner = city.owner().clone();
80 let resources = diff.entry(owner).or_default();
81 *resources += city.round_production(stats)?;
82 resources.food -= city.maintenance(stats)?;
83 }
84
85 for (ruler, mut resources) in diff {
86 resources.food -= self.military.maintenance_of(ruler.clone());
87 let capacity = self.get_storage_capacity(ruler.clone())?;
88 self
89 .ruler_mut(&ruler)?
90 .resources_mut()
91 .add_within_capacity(&resources, &capacity);
92 }
93
94 Ok(())
95 }
96
97 fn process_city_queues(&mut self) {
99 for city in self.continent.cities_mut() {
100 let coord = city.coord();
101 let owner = city.owner().clone();
102 let infrastructure = city.infrastructure_mut();
103
104 infrastructure.process_prefecture_build_queue();
105
106 macro_rules! process_recruit_queue {
107 ($building:ident) => {
108 paste::paste! {
109 if let Some(personnel) = infrastructure.[<process_ $building:snake _recruit_queue>]() {
110 self.military.spawn(coord, owner.clone(), personnel);
111 }
112 }
113 };
114 }
115
116 process_recruit_queue!(Academy);
117 process_recruit_queue!(Stable);
118 process_recruit_queue!(Workshop);
119 }
120 }
121}