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 derive_more::{Deref, Display, Into};
7use serde::{Deserialize, Serialize};
8use std::sync::Arc;
9use uuid::Uuid;
10
11#[derive(Clone, Debug, Deserialize, Serialize)]
12#[serde(rename_all = "camelCase")]
13pub struct WorldConfig {
14  id: WorldId,
15  name: WorldName,
16  locale: Locale,
17  allow_cheats: bool,
18  bot_density: BotDensity,
19  bot_advanced_start_ratio: BotAdvancedStartRatio,
20}
21
22impl WorldConfig {
23  pub fn new(options: &WorldOptions) -> Self {
24    Self {
25      id: WorldId::new(),
26      name: options.name.clone(),
27      locale: options.locale,
28      allow_cheats: options.allow_cheats,
29      bot_density: options.bot_density,
30      bot_advanced_start_ratio: options.bot_advanced_start_ratio,
31    }
32  }
33
34  #[inline]
35  pub fn id(&self) -> WorldId {
36    self.id
37  }
38
39  #[inline]
40  pub fn name(&self) -> WorldName {
41    self.name.clone()
42  }
43
44  #[inline]
45  pub fn locale(&self) -> Locale {
46    self.locale
47  }
48
49  #[inline]
50  pub fn are_cheats_allowed(&self) -> bool {
51    self.allow_cheats
52  }
53
54  #[inline]
55  pub fn bot_density(&self) -> BotDensity {
56    self.bot_density
57  }
58
59  #[inline]
60  pub fn bot_advanced_start_ratio(&self) -> BotAdvancedStartRatio {
61    self.bot_advanced_start_ratio
62  }
63}
64
65#[derive(
66  Clone, Copy, Debug, Deref, Display, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize,
67)]
68pub struct WorldId(Uuid);
69
70impl WorldId {
71  #[must_use]
72  pub fn new() -> Self {
73    Self(Uuid::now_v7())
74  }
75}
76
77impl Default for WorldId {
78  fn default() -> Self {
79    Self::new()
80  }
81}
82
83impl TryFrom<&str> for WorldId {
84  type Error = anyhow::Error;
85
86  fn try_from(value: &str) -> AnyResult<Self> {
87    Ok(Self(Uuid::try_parse(value)?))
88  }
89}
90
91#[derive(Clone, Debug, Deserialize, Serialize)]
92pub struct WorldName(Arc<str>);
93
94impl<T: AsRef<str>> From<T> for WorldName {
95  fn from(value: T) -> Self {
96    Self(Arc::from(value.as_ref()))
97  }
98}
99
100#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize)]
101pub enum Locale {
102  #[default]
103  #[serde(rename = "en-US")]
104  English,
105
106  #[serde(rename = "pt-BR")]
107  Portuguese,
108}
109
110#[derive(Clone, Copy, Debug, Deref, Into, Deserialize, Serialize)]
111pub struct BotDensity(f64);
112
113impl BotDensity {
114  pub const MIN: Self = BotDensity(0.0);
115  pub const MAX: Self = BotDensity(3.0);
116
117  #[inline]
118  pub const fn new(density: f64) -> Self {
119    debug_assert!(density.is_finite());
120    debug_assert!(!density.is_subnormal());
121    Self(density.clamp(Self::MIN.0, Self::MAX.0))
122  }
123}
124
125impl Default for BotDensity {
126  fn default() -> Self {
127    if cfg!(target_os = "android") { Self::new(1.0) } else { Self::new(2.0) }
128  }
129}
130
131/// Proportion of bots that will have an advanced start with higher level infrastructure.
132#[derive(Clone, Copy, Debug, Deref, Into, Deserialize, Serialize)]
133pub struct BotAdvancedStartRatio(f64);
134
135impl BotAdvancedStartRatio {
136  pub const MIN: Self = BotAdvancedStartRatio(0.0);
137  pub const MAX: Self = BotAdvancedStartRatio(1.0);
138
139  #[inline]
140  pub const fn new(ratio: f64) -> Self {
141    debug_assert!(ratio.is_finite());
142    debug_assert!(!ratio.is_subnormal());
143    Self(ratio.clamp(Self::MIN.0, Self::MAX.0))
144  }
145}
146
147impl Default for BotAdvancedStartRatio {
148  fn default() -> Self {
149    Self::new(0.2)
150  }
151}