Skip to main content

nil_core/resources/
diff.rs

1// Copyright (C) Call of Nil contributors
2// SPDX-License-Identifier: AGPL-3.0-only
3
4use super::{Food, Iron, Resources, Stone, Wood};
5use crate::error::Result;
6use derive_more::Display;
7use nil_util::{ConstDeref, F64Math};
8use serde::{Deserialize, Serialize};
9use std::cmp::Ordering;
10use std::ops::{Add, AddAssign, Sub, SubAssign};
11
12#[derive(Copy, Debug, Deserialize, Serialize)]
13#[derive_const(Clone, Default, PartialEq, Eq, PartialOrd, Ord)]
14#[serde(default, rename_all = "camelCase")]
15#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
16pub struct ResourcesDiff {
17  pub food: FoodDiff,
18  pub iron: IronDiff,
19  pub stone: StoneDiff,
20  pub wood: WoodDiff,
21}
22
23impl TryFrom<Resources> for ResourcesDiff {
24  type Error = crate::error::Error;
25
26  fn try_from(value: Resources) -> Result<Self> {
27    Ok(Self {
28      food: FoodDiff::try_from(value.food)?,
29      iron: IronDiff::try_from(value.iron)?,
30      stone: StoneDiff::try_from(value.stone)?,
31      wood: WoodDiff::try_from(value.wood)?,
32    })
33  }
34}
35
36const impl Add for ResourcesDiff {
37  type Output = Self;
38
39  fn add(self, rhs: Self) -> Self {
40    Self {
41      food: self.food + rhs.food,
42      iron: self.iron + rhs.iron,
43      stone: self.stone + rhs.stone,
44      wood: self.wood + rhs.wood,
45    }
46  }
47}
48
49const impl Add<Resources> for ResourcesDiff {
50  type Output = Self;
51
52  fn add(self, rhs: Resources) -> Self {
53    Self {
54      food: self.food + rhs.food,
55      iron: self.iron + rhs.iron,
56      stone: self.stone + rhs.stone,
57      wood: self.wood + rhs.wood,
58    }
59  }
60}
61
62const impl Add<ResourcesDiff> for Resources {
63  type Output = Self;
64
65  fn add(self, rhs: ResourcesDiff) -> Self {
66    Self {
67      food: self.food + rhs.food,
68      iron: self.iron + rhs.iron,
69      stone: self.stone + rhs.stone,
70      wood: self.wood + rhs.wood,
71    }
72  }
73}
74
75const impl AddAssign for ResourcesDiff {
76  fn add_assign(&mut self, rhs: Self) {
77    *self = Self {
78      food: self.food + rhs.food,
79      iron: self.iron + rhs.iron,
80      stone: self.stone + rhs.stone,
81      wood: self.wood + rhs.wood,
82    };
83  }
84}
85
86const impl AddAssign<Resources> for ResourcesDiff {
87  fn add_assign(&mut self, rhs: Resources) {
88    *self = Self {
89      food: self.food + rhs.food,
90      iron: self.iron + rhs.iron,
91      stone: self.stone + rhs.stone,
92      wood: self.wood + rhs.wood,
93    };
94  }
95}
96
97const impl AddAssign<ResourcesDiff> for Resources {
98  fn add_assign(&mut self, rhs: ResourcesDiff) {
99    *self = Self {
100      food: self.food + rhs.food,
101      iron: self.iron + rhs.iron,
102      stone: self.stone + rhs.stone,
103      wood: self.wood + rhs.wood,
104    };
105  }
106}
107
108const impl Sub for ResourcesDiff {
109  type Output = Self;
110
111  fn sub(self, rhs: Self) -> Self {
112    Self {
113      food: self.food - rhs.food,
114      iron: self.iron - rhs.iron,
115      stone: self.stone - rhs.stone,
116      wood: self.wood - rhs.wood,
117    }
118  }
119}
120
121const impl Sub<ResourcesDiff> for Resources {
122  type Output = Self;
123
124  fn sub(self, rhs: ResourcesDiff) -> Self {
125    Self {
126      food: self.food - rhs.food,
127      iron: self.iron - rhs.iron,
128      stone: self.stone - rhs.stone,
129      wood: self.wood - rhs.wood,
130    }
131  }
132}
133
134const impl SubAssign for ResourcesDiff {
135  fn sub_assign(&mut self, rhs: Self) {
136    *self = Self {
137      food: self.food - rhs.food,
138      iron: self.iron - rhs.iron,
139      stone: self.stone - rhs.stone,
140      wood: self.wood - rhs.wood,
141    };
142  }
143}
144
145const impl SubAssign<Resources> for ResourcesDiff {
146  fn sub_assign(&mut self, rhs: Resources) {
147    *self = Self {
148      food: self.food - rhs.food,
149      iron: self.iron - rhs.iron,
150      stone: self.stone - rhs.stone,
151      wood: self.wood - rhs.wood,
152    };
153  }
154}
155
156const impl SubAssign<ResourcesDiff> for Resources {
157  fn sub_assign(&mut self, rhs: ResourcesDiff) {
158    *self = Self {
159      food: self.food - rhs.food,
160      iron: self.iron - rhs.iron,
161      stone: self.stone - rhs.stone,
162      wood: self.wood - rhs.wood,
163    };
164  }
165}
166
167macro_rules! decl_resource_diff {
168  ($($resource:ident),+ $(,)?) => {
169    paste::paste! {
170      $(
171        #[derive(Copy, Debug, Display, Deserialize, Serialize, ConstDeref, F64Math)]
172        #[derive_const(Clone, Default, PartialEq, Eq, PartialOrd, Ord)]
173        #[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
174        pub struct [<$resource Diff>](i32);
175
176        impl [<$resource Diff>] {
177          #[inline]
178          pub const fn new(value: i32) -> Self {
179            Self(value)
180          }
181
182          #[inline]
183          pub const fn zero() -> Self {
184            Self(0)
185          }
186        }
187
188        const impl From<[<$resource Diff>]> for f64 {
189          fn from(value: [<$resource Diff>]) -> Self {
190            f64::from(value.0)
191          }
192        }
193
194        impl TryFrom<$resource> for [<$resource Diff>] {
195          type Error = $crate::error::Error;
196
197          fn try_from(value: $resource) -> Result<Self> {
198            Ok(Self(value.try_into()?))
199          }
200        }
201
202        const impl PartialEq<i32> for [<$resource Diff>] {
203          fn eq(&self, other: &i32) -> bool {
204            self.0.eq(other)
205          }
206        }
207
208        const impl PartialOrd<i32> for [<$resource Diff>] {
209          fn partial_cmp(&self, other: &i32) -> Option<Ordering> {
210            self.0.partial_cmp(other)
211          }
212        }
213
214        const impl Add for [<$resource Diff>] {
215          type Output = Self;
216
217          fn add(self, rhs: Self) -> Self {
218            Self(self.0.saturating_add(rhs.0))
219          }
220        }
221
222        const impl Add<$resource> for [<$resource Diff>] {
223          type Output = Self;
224
225          fn add(self, rhs: $resource) -> Self {
226            Self(self.0.saturating_add_unsigned(rhs.0))
227          }
228        }
229
230        const impl Add<[<$resource Diff>]> for $resource {
231          type Output = Self;
232
233          fn add(self, rhs: [<$resource Diff>]) -> Self {
234            Self(self.0.saturating_add_signed(rhs.0))
235          }
236        }
237
238        const impl Add<i32> for [<$resource Diff>] {
239          type Output = Self;
240
241          fn add(self, rhs: i32) -> Self {
242            Self(self.0.saturating_add(rhs))
243          }
244        }
245
246        const impl Add<u32> for [<$resource Diff>] {
247          type Output = Self;
248
249          fn add(self, rhs: u32) -> Self {
250            Self(self.0.saturating_add_unsigned(rhs))
251          }
252        }
253
254        const impl AddAssign for [<$resource Diff>] {
255          fn add_assign(&mut self, rhs: Self) {
256            *self = *self + rhs;
257          }
258        }
259
260        const impl AddAssign<$resource> for [<$resource Diff>] {
261          fn add_assign(&mut self, rhs: $resource) {
262            *self = *self + rhs;
263          }
264        }
265
266        const impl AddAssign<[<$resource Diff>]> for $resource {
267          fn add_assign(&mut self, rhs: [<$resource Diff>]) {
268            *self = *self + rhs;
269          }
270        }
271
272        const impl AddAssign<i32> for [<$resource Diff>] {
273          fn add_assign(&mut self, rhs: i32) {
274            *self = *self + rhs;
275          }
276        }
277
278        const impl AddAssign<u32> for [<$resource Diff>] {
279          fn add_assign(&mut self, rhs: u32) {
280            *self = *self + rhs;
281          }
282        }
283
284        const impl Sub for [<$resource Diff>] {
285          type Output = Self;
286
287          fn sub(self, rhs: Self) -> Self {
288            Self(self.0.saturating_sub(rhs.0))
289          }
290        }
291
292        const impl Sub<$resource> for [<$resource Diff>] {
293          type Output = Self;
294
295          fn sub(self, rhs: $resource) -> Self {
296            Self(self.0.saturating_sub_unsigned(rhs.0))
297          }
298        }
299
300        const impl Sub<[<$resource Diff>]> for $resource {
301          type Output = Self;
302
303          fn sub(self, rhs: [<$resource Diff>]) -> Self {
304            Self(self.0.saturating_sub_signed(rhs.0))
305          }
306        }
307
308        const impl Sub<i32> for [<$resource Diff>] {
309          type Output = Self;
310
311          fn sub(self, rhs: i32) -> Self {
312            Self(self.0.saturating_sub(rhs))
313          }
314        }
315
316        const impl Sub<u32> for [<$resource Diff>] {
317          type Output = Self;
318
319          fn sub(self, rhs: u32) -> Self {
320            Self(self.0.saturating_sub_unsigned(rhs))
321          }
322        }
323
324        const impl SubAssign for [<$resource Diff>] {
325          fn sub_assign(&mut self, rhs: Self) {
326            *self = *self - rhs;
327          }
328        }
329
330        const impl SubAssign<$resource> for [<$resource Diff>] {
331          fn sub_assign(&mut self, rhs: $resource) {
332            *self = *self - rhs;
333          }
334        }
335
336        const impl SubAssign<[<$resource Diff>]> for $resource {
337          fn sub_assign(&mut self, rhs: [<$resource Diff>]) {
338            *self = *self - rhs;
339          }
340        }
341
342        const impl SubAssign<i32> for [<$resource Diff>] {
343          fn sub_assign(&mut self, rhs: i32) {
344            *self = *self - rhs;
345          }
346        }
347
348        const impl SubAssign<u32> for [<$resource Diff>] {
349          fn sub_assign(&mut self, rhs: u32) {
350            *self = *self - rhs;
351          }
352        }
353      )+
354    }
355  }
356}
357
358decl_resource_diff!(Food, Iron, Stone, Wood);