Skip to main content

nil_core/world/
config.rs

1// Copyright (C) Call of Nil contributors
2// SPDX-License-Identifier: AGPL-3.0-only
3
4use crate::error::AnyResult;
5use crate::world::WorldOptions;
6use bon::Builder;
7use derive_more::{Deref, Display, Into};
8use serde::{Deserialize, Serialize};
9use uuid::Uuid;
10
11#[derive(Builder, Clone, Debug, Deserialize, Serialize)]
12#[serde(rename_all = "camelCase")]
13pub struct WorldConfig {
14  #[builder(start_fn, into)]
15  name: WorldName,
16
17  #[builder(skip)]
18  id: WorldId,
19
20  #[serde(default)]
21  #[builder(default)]
22  locale: Locale,
23
24  #[serde(default)]
25  #[builder(default)]
26  allow_cheats: bool,
27
28  #[serde(default)]
29  #[builder(default)]
30  speed: WorldSpeed,
31
32  #[serde(default)]
33  #[builder(default)]
34  unit_speed: WorldUnitSpeed,
35
36  #[serde(default)]
37  #[builder(default)]
38  bot_density: BotDensity,
39
40  #[serde(default)]
41  #[builder(default)]
42  bot_advanced_start_ratio: BotAdvancedStartRatio,
43}
44
45impl WorldConfig {
46  pub fn new(options: &WorldOptions) -> Self {
47    Self {
48      id: WorldId::new(),
49      name: options.name.clone(),
50      locale: options.locale,
51      allow_cheats: options.allow_cheats,
52      speed: options.speed,
53      unit_speed: options.unit_speed,
54      bot_density: options.bot_density,
55      bot_advanced_start_ratio: options.bot_advanced_start_ratio,
56    }
57  }
58
59  #[inline]
60  pub fn id(&self) -> WorldId {
61    self.id
62  }
63
64  #[inline]
65  pub fn name(&self) -> WorldName {
66    self.name.clone()
67  }
68
69  #[inline]
70  pub fn locale(&self) -> Locale {
71    self.locale
72  }
73
74  #[inline]
75  pub fn are_cheats_allowed(&self) -> bool {
76    self.allow_cheats
77  }
78
79  #[inline]
80  pub fn speed(&self) -> WorldSpeed {
81    self.speed
82  }
83
84  #[inline]
85  pub fn unit_speed(&self) -> WorldUnitSpeed {
86    self.unit_speed
87  }
88
89  #[inline]
90  pub fn bot_density(&self) -> BotDensity {
91    self.bot_density
92  }
93
94  #[inline]
95  pub fn bot_advanced_start_ratio(&self) -> BotAdvancedStartRatio {
96    self.bot_advanced_start_ratio
97  }
98}
99
100#[derive(
101  Clone, Copy, Debug, Deref, Display, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize,
102)]
103pub struct WorldId(Uuid);
104
105impl WorldId {
106  #[must_use]
107  pub fn new() -> Self {
108    Self(Uuid::now_v7())
109  }
110}
111
112impl Default for WorldId {
113  fn default() -> Self {
114    Self::new()
115  }
116}
117
118impl TryFrom<&str> for WorldId {
119  type Error = anyhow::Error;
120
121  fn try_from(value: &str) -> AnyResult<Self> {
122    Ok(Self(Uuid::try_parse(value)?))
123  }
124}
125
126#[derive(Clone, Debug, Deserialize, Serialize)]
127pub struct WorldName(Box<str>);
128
129impl<T: AsRef<str>> From<T> for WorldName {
130  fn from(value: T) -> Self {
131    Self(Box::from(value.as_ref()))
132  }
133}
134
135#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize)]
136pub enum Locale {
137  #[default]
138  #[serde(rename = "en-US")]
139  English,
140
141  #[serde(rename = "pt-BR")]
142  Portuguese,
143}
144
145macro_rules! impl_f64_newtype {
146  ($name:ident, min = $min:expr, max = $max:expr) => {
147    impl $name {
148      pub const MIN: Self = $name($min);
149      pub const MAX: Self = $name($max);
150
151      #[inline]
152      pub const fn new(value: f64) -> Self {
153        debug_assert!(value.is_finite());
154        debug_assert!(!value.is_subnormal());
155        Self(value.clamp(Self::MIN.0, Self::MAX.0))
156      }
157    }
158  };
159  ($name:ident, min = $min:expr, max = $max:expr, default = $default:expr) => {
160    impl_f64_newtype!($name, min = $min, max = $max);
161
162    impl Default for $name {
163      fn default() -> Self {
164        Self::new($default)
165      }
166    }
167  };
168}
169
170#[derive(Clone, Copy, Debug, Deref, Into, Deserialize, Serialize, nil_num::F64Ops)]
171pub struct WorldSpeed(f64);
172
173impl_f64_newtype!(WorldSpeed, min = 0.1, max = 10.0, default = 1.0);
174
175#[derive(Clone, Copy, Debug, Deref, Into, Deserialize, Serialize, nil_num::F64Ops)]
176pub struct WorldUnitSpeed(f64);
177
178impl_f64_newtype!(WorldUnitSpeed, min = 0.1, max = 10.0, default = 1.0);
179
180#[derive(Clone, Copy, Debug, Deref, Into, Deserialize, Serialize, nil_num::F64Ops)]
181pub struct BotDensity(f64);
182
183impl_f64_newtype!(
184  BotDensity,
185  min = 0.0,
186  max = 3.0,
187  default = if cfg!(target_os = "android") { 1.0 } else { 2.0 }
188);
189
190/// Proportion of bots that will have an advanced start with higher level infrastructure.
191#[derive(Clone, Copy, Debug, Deref, Into, Deserialize, Serialize, nil_num::F64Ops)]
192pub struct BotAdvancedStartRatio(f64);
193
194impl_f64_newtype!(BotAdvancedStartRatio, min = 0.0, max = 1.0, default = 0.2);