steel_core/player/advancement/
progress.rs1use rustc_hash::FxHashMap;
3use serde::{Deserialize, Serialize};
4use std::borrow::Cow;
5use std::time::SystemTime;
6use steel_registry::advancement::AdvancementRequirement;
7use steel_registry::advancement::registry::AdvancementRef;
8
9#[derive(Debug, Default, Clone)]
11pub struct AdvancementProgressMap {
12 map: FxHashMap<AdvancementRef, usize>,
14 order: Vec<(AdvancementRef, AdvancementProgress)>,
15}
16
17impl AdvancementProgressMap {
18 #[must_use]
20 pub fn get_mut_or_start_progress(
21 &mut self,
22 advancement: AdvancementRef,
23 ) -> &mut AdvancementProgress {
24 let idx = self.map.entry(advancement).or_insert_with(|| {
25 let mut progress = AdvancementProgress::default();
26 progress.update(advancement.requirements());
27 self.order.push((advancement, progress));
28 self.order.len() - 1
29 });
30 if let Some(progress) = self.order.get_mut(*idx) {
31 &mut progress.1
32 } else {
33 unreachable!("Index {} not found in order vector", idx);
34 }
35 }
36
37 pub fn start_progress(
39 &mut self,
40 advancement: AdvancementRef,
41 mut progress: AdvancementProgress,
42 ) {
43 progress.update(advancement.requirements());
44 if let Some(&idx) = self.map.get(&advancement) {
45 self.order[idx].1 = progress;
46 } else {
47 let idx = self.order.len();
48 self.order.push((advancement, progress));
49 self.map.insert(advancement, idx);
50 }
51 }
52
53 #[inline]
55 pub fn clear(&mut self) {
56 self.map.clear();
57 self.order.clear();
58 }
59
60 #[inline]
62 pub fn insert(&mut self, advancement: AdvancementRef, progress: AdvancementProgress) {
63 self.order.push((advancement, progress));
64 self.map.insert(advancement, self.order.len() - 1);
65 }
66
67 #[must_use]
69 #[inline]
70 pub fn len(&self) -> usize {
71 self.map.len()
72 }
73
74 #[must_use]
76 #[inline]
77 pub fn is_empty(&self) -> bool {
78 self.map.is_empty()
79 }
80
81 #[must_use]
83 #[inline]
84 pub fn has_progress(&self, advancement: AdvancementRef) -> bool {
85 self.map.contains_key(&advancement)
86 }
87
88 #[must_use]
90 #[inline]
91 pub fn get_progress(&self, advancement: AdvancementRef) -> Option<&AdvancementProgress> {
92 self.map.get(&advancement).map(|&i| &self.order[i].1)
93 }
94
95 pub fn iter(&self) -> impl Iterator<Item = &(AdvancementRef, AdvancementProgress)> {
97 self.order.iter()
98 }
99}
100
101#[derive(Debug, Clone, Default)]
106pub struct AdvancementProgress {
107 criteria: FxHashMap<Cow<'static, str>, CriterionProgress>,
109 requirements: AdvancementRequirement,
111}
112
113impl AdvancementProgress {
114 #[must_use]
117 pub fn new(criteria: FxHashMap<Cow<'static, str>, CriterionProgress>) -> AdvancementProgress {
118 Self {
119 criteria,
120 requirements: AdvancementRequirement::default(),
121 }
122 }
123
124 #[must_use]
126 pub const fn criteria(&self) -> &FxHashMap<Cow<'static, str>, CriterionProgress> {
127 &self.criteria
128 }
129
130 #[must_use]
132 pub fn is_done(&self) -> bool {
133 self.requirements.test(|s| self.is_criterion_done(s))
134 }
135
136 fn is_criterion_done(&self, criterion: &str) -> bool {
138 self.criteria
139 .get(criterion)
140 .is_some_and(CriterionProgress::is_done)
141 }
142
143 #[must_use]
145 pub fn has_progress(&self) -> bool {
146 for value in self.criteria.values() {
147 if value.is_done() {
148 return true;
149 }
150 }
151 false
152 }
153
154 pub fn grant_progress(&mut self, name: &str) -> bool {
156 if let Some(value) = self.criteria.get_mut(name)
157 && !value.is_done()
158 {
159 value.grant();
160 true
161 } else {
162 false
163 }
164 }
165
166 pub fn revoke_progress(&mut self, name: &str) -> bool {
168 if let Some(value) = self.criteria.get_mut(name)
169 && value.is_done()
170 {
171 value.revoke();
172 true
173 } else {
174 false
175 }
176 }
177
178 pub fn update(&mut self, requirements: &AdvancementRequirement) {
180 let names = requirements.names();
181 self.criteria.retain(|key, _criterion| names.contains(key));
182 for name in names {
183 self.criteria.entry(name).or_default();
184 }
185 self.requirements = requirements.clone();
186 }
187
188 #[inline]
190 pub(crate) fn get_remaining_criteria(&self) -> impl Iterator<Item = &str> {
191 self.criteria
192 .iter()
193 .filter(|&(_id, criterion)| !criterion.is_done())
194 .map(|(id, _criterion)| &**id)
195 }
196
197 #[inline]
199 pub(crate) fn get_completed_criteria(&self) -> impl Iterator<Item = &str> {
200 self.criteria
201 .iter()
202 .filter(|&(_id, criterion)| criterion.is_done())
203 .map(|(id, _criterion)| &**id)
204 }
205}
206#[derive(Clone, Serialize, Deserialize, Debug, Default)]
208pub struct CriterionProgress(pub Option<SystemTime>);
209
210impl CriterionProgress {
211 pub fn grant(&mut self) {
213 self.0 = Some(SystemTime::now());
214 }
215
216 pub const fn revoke(&mut self) {
218 self.0 = None;
219 }
220
221 #[must_use]
223 pub const fn is_done(&self) -> bool {
224 self.0.is_some()
225 }
226}