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