1mod battle;
5mod capital;
6mod chat;
7mod city;
8mod continent;
9mod event;
10mod infrastructure;
11mod market;
12mod military;
13mod npc;
14mod player;
15mod ranking;
16mod report;
17mod resources;
18mod round;
19mod savedata;
20
21pub mod cheat;
22pub mod config;
23pub mod stats;
24
25use crate::chat::Chat;
26use crate::continent::Continent;
27use crate::continent::size::ContinentSize;
28use crate::error::{Error, Result};
29use crate::event::Emitter;
30use crate::hooks::OnNextRound;
31use crate::market::Market;
32use crate::market::fee::MarketFee;
33use crate::military::Military;
34use crate::npc::bot::BotManager;
35use crate::npc::precursor::PrecursorManager;
36use crate::player::PlayerManager;
37use crate::ranking::Ranking;
38use crate::round::Round;
39use crate::ruler::{Ruler, RulerRef, RulerRefMut};
40use crate::savedata::{SaveHandle, Savedata};
41use crate::world::config::{WorldSpeed, WorldUnitSpeed};
42use bon::Builder;
43use config::{BotAdvancedStartRatio, BotDensity, Locale, WorldConfig, WorldId, WorldName};
44use serde::{Deserialize, Serialize};
45use stats::WorldStats;
46use std::sync::Arc;
47
48#[derive(Debug)]
49pub struct World {
50 round: Round,
51 continent: Continent,
52 player_manager: PlayerManager,
53 bot_manager: BotManager,
54 precursor_manager: PrecursorManager,
55 military: Military,
56 market: Market,
57 ranking: Ranking,
58 chat: Chat,
59
60 config: Arc<WorldConfig>,
61 stats: WorldStats,
62
63 emitter: Emitter,
65 save_handle: Option<SaveHandle>,
66 on_next_round: Option<OnNextRound>,
67}
68
69impl World {
70 pub fn new(mut options: WorldOptions) -> Result<Self> {
71 WorldOptions::clamp(&mut options);
72 options.name = options.name.trim().into();
73
74 let config = WorldConfig::new(&options);
75 let stats = WorldStats::new(&config);
76 let continent = Continent::new(options.size.unwrap_or_default());
77 let precursor_manager = PrecursorManager::new(continent.size());
78 let military = Military::new(continent.size());
79 let market = Market::new(options.market_fee.unwrap_or_default());
80
81 let mut world = Self {
82 round: Round::default(),
83 continent,
84 player_manager: PlayerManager::default(),
85 bot_manager: BotManager::default(),
86 precursor_manager,
87 military,
88 market,
89 ranking: Ranking::default(),
90 config: Arc::new(config),
91 stats,
92 chat: Chat::default(),
93
94 emitter: Emitter::default(),
95 save_handle: None,
96 on_next_round: None,
97 };
98
99 world.spawn_precursors()?;
100 world.spawn_bots()?;
101 world.update_ranking()?;
102
103 Ok(world)
104 }
105
106 #[inline]
107 pub fn with_savedata(savedata: Savedata) -> Self {
108 Self::from(savedata)
109 }
110
111 pub fn load(bytes: &[u8]) -> Result<Self> {
112 let savedata = Savedata::read(bytes)?;
113 Ok(Self::with_savedata(savedata))
114 }
115
116 #[inline]
117 pub fn id(&self) -> WorldId {
118 self.config.id()
119 }
120
121 #[inline]
122 pub fn config(&self) -> Arc<WorldConfig> {
123 Arc::clone(&self.config)
124 }
125
126 #[inline]
127 pub fn stats(&self) -> WorldStats {
128 self.stats.clone()
129 }
130
131 pub fn ruler(&self, ruler: &Ruler) -> Result<RulerRef<'_>> {
132 let ruler = match ruler {
133 Ruler::Bot { id } => RulerRef::Bot(self.bot(id)?),
134 Ruler::Player { id } => RulerRef::Player(self.player(id)?),
135 Ruler::Precursor { id } => RulerRef::Precursor(self.precursor(*id)),
136 };
137
138 Ok(ruler)
139 }
140
141 fn ruler_mut(&mut self, ruler: &Ruler) -> Result<RulerRefMut<'_>> {
142 let ruler = match ruler {
143 Ruler::Bot { id } => RulerRefMut::Bot(self.bot_mut(id)?),
144 Ruler::Player { id } => RulerRefMut::Player(self.player_mut(id)?),
145 Ruler::Precursor { id } => RulerRefMut::Precursor(self.precursor_mut(*id)),
146 };
147
148 Ok(ruler)
149 }
150
151 pub fn rulers(&self) -> impl Iterator<Item = RulerRef<'_>> {
152 self
153 .players()
154 .map(RulerRef::from)
155 .chain(self.bots().map(RulerRef::from))
156 .chain(self.precursors().map(RulerRef::from))
157 }
158
159 pub fn save<F>(&mut self, f: F)
162 where
163 F: FnOnce(Vec<u8>) + Send + Sync + 'static,
164 {
165 self.save_handle = Some(SaveHandle::new(f));
166 }
167
168 pub fn on_next_round<F>(&mut self, f: F)
170 where
171 F: Fn(&mut World) + Send + Sync + 'static,
172 {
173 self.on_next_round = Some(OnNextRound::new(f));
174 }
175}
176
177impl Drop for World {
178 fn drop(&mut self) {
179 let _ = self.emit_drop();
180 }
181}
182
183impl TryFrom<WorldOptions> for World {
184 type Error = Error;
185
186 fn try_from(options: WorldOptions) -> Result<Self> {
187 Self::new(options)
188 }
189}
190
191#[derive(Builder, Clone, Debug, Deserialize, Serialize)]
192#[serde(rename_all = "camelCase")]
193#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
194#[cfg_attr(feature = "typescript", ts(optional_fields = nullable))]
195pub struct WorldOptions {
196 #[builder(start_fn, into)]
197 pub name: WorldName,
198
199 #[serde(default)]
200 #[builder(into)]
201 pub size: Option<ContinentSize>,
202
203 #[serde(default)]
204 pub locale: Option<Locale>,
205
206 #[serde(default)]
207 pub allow_cheats: Option<bool>,
208
209 #[serde(default)]
210 #[builder(into)]
211 pub speed: Option<WorldSpeed>,
212
213 #[serde(default)]
214 #[builder(into)]
215 pub unit_speed: Option<WorldUnitSpeed>,
216
217 #[serde(default)]
218 #[builder(into)]
219 pub bot_density: Option<BotDensity>,
220
221 #[serde(default)]
222 #[builder(into)]
223 pub bot_advanced_start_ratio: Option<BotAdvancedStartRatio>,
224
225 #[serde(default)]
226 #[builder(into)]
227 pub market_fee: Option<MarketFee>,
228}
229
230impl WorldOptions {
231 pub fn clamp(&mut self) {
232 macro_rules! clamp {
233 ($($field_ty:ident => $field:ident),* $(,)?) => {
234 $(
235 if let Some(value) = self.$field.as_mut() {
236 $field_ty::clamp(value);
237 }
238 )*
239 };
240 }
241
242 clamp!(
243 ContinentSize => size,
244 WorldSpeed => speed,
245 WorldUnitSpeed => unit_speed,
246 BotDensity => bot_density,
247 BotAdvancedStartRatio => bot_advanced_start_ratio,
248 MarketFee => market_fee,
249 );
250 }
251}