1mod battle;
5mod chat;
6mod cheat;
7mod city;
8pub mod config;
9mod continent;
10mod event;
11mod infrastructure;
12mod military;
13mod npc;
14mod player;
15mod ranking;
16mod resources;
17mod round;
18mod savedata;
19pub mod stats;
20
21use crate::chat::Chat;
22use crate::city::City;
23use crate::continent::{Continent, ContinentSize, Coord};
24use crate::error::{Error, Result};
25use crate::event::Emitter;
26use crate::hooks::OnNextRound;
27use crate::infrastructure::Infrastructure;
28use crate::military::Military;
29use crate::npc::bot::{Bot, BotId, BotManager};
30use crate::npc::precursor::{Precursor, PrecursorId, PrecursorManager};
31use crate::player::{Player, PlayerId, PlayerManager};
32use crate::ranking::Ranking;
33use crate::report::ReportManager;
34use crate::round::Round;
35use crate::ruler::{Ruler, RulerRef, RulerRefMut};
36use crate::savedata::{SaveHandle, Savedata};
37use bon::Builder;
38use config::{BotAdvancedStartRatio, BotDensity, Locale, WorldConfig, WorldId, WorldName};
39use serde::{Deserialize, Serialize};
40use stats::WorldStats;
41
42#[derive(Debug)]
43pub struct World {
44 round: Round,
45 continent: Continent,
46 player_manager: PlayerManager,
47 bot_manager: BotManager,
48 precursor_manager: PrecursorManager,
49 military: Military,
50 ranking: Ranking,
51 report: ReportManager,
52 config: WorldConfig,
53 stats: WorldStats,
54 chat: Chat,
55
56 emitter: Emitter,
58 save_handle: Option<SaveHandle>,
59 on_next_round: Option<OnNextRound>,
60}
61
62impl World {
63 pub fn new(options: &WorldOptions) -> Result<Self> {
64 let config = WorldConfig::new(options);
65 let continent = Continent::new(options.size.get());
66 let precursor_manager = PrecursorManager::new(continent.size());
67 let military = Military::new(continent.size());
68
69 let mut world = Self {
70 round: Round::default(),
71 continent,
72 player_manager: PlayerManager::default(),
73 bot_manager: BotManager::default(),
74 precursor_manager,
75 military,
76 ranking: Ranking::default(),
77 report: ReportManager::default(),
78 config,
79 stats: WorldStats::new(),
80 chat: Chat::default(),
81
82 emitter: Emitter::default(),
83 save_handle: None,
84 on_next_round: None,
85 };
86
87 world.spawn_precursors()?;
88 world.spawn_bots()?;
89 world.update_ranking()?;
90
91 Ok(world)
92 }
93
94 #[inline]
95 pub fn with_savedata(savedata: Savedata) -> Self {
96 Self::from(savedata)
97 }
98
99 pub fn load(bytes: &[u8]) -> Result<Self> {
100 let savedata = Savedata::read(bytes)?;
101 Ok(Self::with_savedata(savedata))
102 }
103
104 #[inline]
105 pub fn id(&self) -> WorldId {
106 self.config.id()
107 }
108
109 #[inline]
110 pub fn config(&self) -> &WorldConfig {
111 &self.config
112 }
113
114 #[inline]
115 pub fn stats(&self) -> WorldStats {
116 self.stats.clone()
117 }
118
119 #[inline]
120 pub fn continent(&self) -> &Continent {
121 &self.continent
122 }
123
124 #[inline]
125 pub fn city(&self, coord: Coord) -> Result<&City> {
126 self.continent.city(coord)
127 }
128
129 #[inline]
130 pub(crate) fn city_mut(&mut self, coord: Coord) -> Result<&mut City> {
131 self.continent.city_mut(coord)
132 }
133
134 #[inline]
135 pub fn infrastructure(&self, coord: Coord) -> Result<&Infrastructure> {
136 self.city(coord).map(City::infrastructure)
137 }
138
139 #[inline]
140 pub fn round(&self) -> &Round {
141 &self.round
142 }
143
144 #[inline]
145 pub fn chat(&self) -> &Chat {
146 &self.chat
147 }
148
149 #[inline]
150 pub fn ranking(&self) -> &Ranking {
151 &self.ranking
152 }
153
154 #[inline]
155 pub fn report(&self) -> &ReportManager {
156 &self.report
157 }
158
159 #[inline]
160 pub fn player_manager(&self) -> &PlayerManager {
161 &self.player_manager
162 }
163
164 #[inline]
165 pub fn player(&self, id: &PlayerId) -> Result<&Player> {
166 self.player_manager.player(id)
167 }
168
169 #[inline]
170 fn player_mut(&mut self, id: &PlayerId) -> Result<&mut Player> {
171 self.player_manager.player_mut(id)
172 }
173
174 pub fn players(&self) -> impl Iterator<Item = &Player> {
175 self.player_manager.players()
176 }
177
178 #[inline]
179 pub fn bot_manager(&self) -> &BotManager {
180 &self.bot_manager
181 }
182
183 #[inline]
184 pub fn bot(&self, id: &BotId) -> Result<&Bot> {
185 self.bot_manager.bot(id)
186 }
187
188 #[inline]
189 fn bot_mut(&mut self, id: &BotId) -> Result<&mut Bot> {
190 self.bot_manager.bot_mut(id)
191 }
192
193 pub fn bots(&self) -> impl Iterator<Item = &Bot> {
194 self.bot_manager.bots()
195 }
196
197 #[inline]
198 pub fn precursor_manager(&self) -> &PrecursorManager {
199 &self.precursor_manager
200 }
201
202 #[inline]
203 pub fn precursor(&self, id: PrecursorId) -> &dyn Precursor {
204 self.precursor_manager.precursor(id)
205 }
206
207 #[inline]
208 fn precursor_mut(&mut self, id: PrecursorId) -> &mut dyn Precursor {
209 self.precursor_manager.precursor_mut(id)
210 }
211
212 pub fn precursors(&self) -> impl Iterator<Item = &dyn Precursor> {
213 self.precursor_manager.precursors()
214 }
215
216 pub fn ruler(&self, ruler: &Ruler) -> Result<RulerRef<'_>> {
217 let ruler = match ruler {
218 Ruler::Bot { id } => RulerRef::Bot(self.bot(id)?),
219 Ruler::Player { id } => RulerRef::Player(self.player(id)?),
220 Ruler::Precursor { id } => RulerRef::Precursor(self.precursor(*id)),
221 };
222
223 Ok(ruler)
224 }
225
226 fn ruler_mut(&mut self, ruler: &Ruler) -> Result<RulerRefMut<'_>> {
227 let ruler = match ruler {
228 Ruler::Bot { id } => RulerRefMut::Bot(self.bot_mut(id)?),
229 Ruler::Player { id } => RulerRefMut::Player(self.player_mut(id)?),
230 Ruler::Precursor { id } => RulerRefMut::Precursor(self.precursor_mut(*id)),
231 };
232
233 Ok(ruler)
234 }
235
236 pub fn rulers(&self) -> impl Iterator<Item = RulerRef<'_>> {
237 self
238 .players()
239 .map(RulerRef::from)
240 .chain(self.bots().map(RulerRef::from))
241 .chain(self.precursors().map(RulerRef::from))
242 }
243
244 #[inline]
245 pub fn military(&self) -> &Military {
246 &self.military
247 }
248
249 pub fn save<F>(&mut self, f: F)
250 where
251 F: FnOnce(Vec<u8>) + Send + Sync + 'static,
252 {
253 self.save_handle = Some(SaveHandle::new(f));
254 }
255
256 pub fn on_next_round<F>(&mut self, f: F)
257 where
258 F: Fn(&mut World) + Send + Sync + 'static,
259 {
260 self.on_next_round = Some(OnNextRound::new(f));
261 }
262}
263
264#[derive(Builder, Clone, Debug, Deserialize, Serialize)]
265#[serde(rename_all = "camelCase")]
266pub struct WorldOptions {
267 #[builder(start_fn, into)]
268 pub name: WorldName,
269
270 #[serde(default)]
271 #[builder(default)]
272 pub size: ContinentSize,
273
274 #[serde(default)]
275 #[builder(default)]
276 pub locale: Locale,
277
278 #[serde(default)]
279 #[builder(default)]
280 pub allow_cheats: bool,
281
282 #[serde(default)]
283 #[builder(default)]
284 pub bot_density: BotDensity,
285
286 #[serde(default)]
287 #[builder(default)]
288 pub bot_advanced_start_ratio: BotAdvancedStartRatio,
289}
290
291impl WorldOptions {
292 pub fn to_world(&self) -> Result<World> {
293 World::try_from(self)
294 }
295}
296
297impl TryFrom<&WorldOptions> for World {
298 type Error = Error;
299
300 fn try_from(options: &WorldOptions) -> Result<Self> {
301 Self::new(options)
302 }
303}