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 fn dangerously_end_round(&mut self, emit: bool) -> Result<()> {
43 self.round.dangerously_set_done();
44 self.next_round(emit)?;
45 Ok(())
46 }
47
48 pub(super) fn next_round(&mut self, emit: bool) -> Result<()> {
49 let ids = self
50 .player_manager
51 .active_players()
52 .map(Player::id);
53
54 self.round.next(ids)?;
55 self.prepare_next_round()?;
56 self.consume_pending_save()?;
57
58 if emit {
59 self.emit_round_updated();
60 }
61
62 if let Some(on_next_round) = self.on_next_round.clone() {
63 on_next_round.call(self);
64 }
65
66 Ok(())
67 }
68
69 fn prepare_next_round(&mut self) -> Result<()> {
70 self.update_resources()?;
71 self.process_city_queues();
72 self.collapse_armies();
73 self.process_maneuvers()?;
74 self.update_ranking()?;
75 self.process_npc_behavior()?;
76 Ok(())
77 }
78
79 fn update_resources(&mut self) -> Result<()> {
82 let stats = self.stats.infrastructure.as_ref();
83 let mut diff: HashMap<Ruler, ResourcesDiff> = HashMap::new();
84
85 for city in self.continent.cities() {
86 let owner = city.owner().clone();
87 let resources = diff.entry(owner).or_default();
88 *resources += city.round_production(stats)?;
89 resources.food -= city.maintenance(stats)?;
90 }
91
92 for (ruler, mut resources) in diff {
93 resources.food -= self.military.maintenance_of(ruler.clone());
94 let capacity = self.get_storage_capacity(ruler.clone())?;
95 self
96 .ruler_mut(&ruler)?
97 .resources_mut()
98 .add_within_capacity(&resources, &capacity);
99 }
100
101 Ok(())
102 }
103
104 fn process_city_queues(&mut self) {
106 for city in self.continent.cities_mut() {
107 let coord = city.coord();
108 let owner = city.owner().clone();
109 let infrastructure = city.infrastructure_mut();
110
111 infrastructure.process_prefecture_build_queue();
112
113 macro_rules! process_recruit_queue {
114 ($building:ident) => {
115 paste::paste! {
116 if let Some(personnel) = infrastructure.[<process_ $building:snake _recruit_queue>]() {
117 self.military.spawn(coord, owner.clone(), personnel);
118 }
119 }
120 };
121 }
122
123 process_recruit_queue!(Academy);
124 process_recruit_queue!(Stable);
125 process_recruit_queue!(Workshop);
126 }
127 }
128}