steel_registry/advancement/
registry.rs1use crate::advancement::{Advancement, positioner};
2use rustc_hash::{FxHashMap, FxHashSet};
3use std::fmt::{Debug, Display};
4use std::hash::{Hash, Hasher};
5use std::io::Write;
6use steel_utils::Identifier;
7use steel_utils::serial::WriteTo;
8
9pub type AdvancementRef = &'static Advancement;
10
11#[derive(Debug)]
12pub struct AdvancementNode {
13 children: Vec<usize>,
14 parent: Option<usize>,
15 value: AdvancementRef,
16 x: f32,
17 y: f32,
18}
19
20pub type AdvancementNodeRef = &'static AdvancementNode;
21
22impl WriteTo for AdvancementNodeRef {
23 fn write(&self, writer: &mut impl Write) -> std::io::Result<()> {
24 self.value.write(writer)?;
25 self.x.write(writer)?;
26 self.y.write(writer)
27 }
28}
29
30impl AdvancementNode {
31 pub fn add_child(&mut self, child: usize) {
32 self.children.push(child);
33 }
34
35 #[must_use]
36 pub const fn new(value: AdvancementRef, parent: Option<usize>) -> Self {
37 Self {
38 value,
39 parent,
40 children: Vec::new(),
41 x: 0f32,
42 y: 0f32,
43 }
44 }
45
46 #[inline]
47 #[must_use]
48 pub const fn has_display(&self) -> bool {
49 self.value.display.is_some()
50 }
51
52 #[inline]
53 pub const fn set_location(&mut self, x: f32, y: f32) {
54 self.x = x;
55 self.y = y;
56 }
57
58 #[inline]
59 #[must_use]
60 pub const fn get_location(&self) -> (f32, f32) {
61 (self.x, self.y)
62 }
63
64 #[must_use]
65 #[inline]
66 pub const fn value(&self) -> AdvancementRef {
67 self.value
68 }
69
70 #[must_use]
71 #[inline]
72 pub fn children(&self) -> Vec<usize> {
73 self.children.clone()
74 }
75
76 #[must_use]
77 #[inline]
78 pub const fn parent(&self) -> Option<usize> {
79 self.parent
80 }
81}
82
83impl PartialEq<Self> for AdvancementNode {
84 fn eq(&self, other: &Self) -> bool {
85 self.value == other.value
86 }
87}
88
89impl Eq for AdvancementNode {}
90
91impl Display for AdvancementNode {
92 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93 write!(formatter, "{}", self.value.key)
94 }
95}
96impl Hash for AdvancementNode {
97 fn hash<H: Hasher>(&self, state: &mut H) {
98 self.value.key.hash(state);
99 }
100}
101
102#[derive(Default, Debug)]
117pub struct AdvancementRegistry {
118 pub(crate) advancements: Vec<AdvancementRef>,
119 pub(crate) adv_nodes: Vec<AdvancementNode>,
120 pub(crate) unloaded_advancement: FxHashSet<AdvancementRef>,
121 pub(crate) by_key: FxHashMap<Identifier, usize>,
122 pub(crate) roots: Vec<usize>,
123 pub(crate) tasks: Vec<usize>,
124}
125
126impl AdvancementRegistry {
127 #[must_use]
128 #[inline]
129 pub fn new() -> Self {
130 Self::default()
131 }
132
133 #[must_use]
134 pub fn advancements(&self) -> &[AdvancementRef] {
135 &self.advancements
136 }
137
138 #[must_use]
139 pub fn nodes(&self) -> &[AdvancementNode] {
140 &self.adv_nodes
141 }
142
143 fn register_with_parent(&mut self, advancement: AdvancementRef, parent_idx: Option<usize>) {
144 let id = advancement.key.clone();
145 let node_idx = self.adv_nodes.len();
146 self.adv_nodes
147 .push(AdvancementNode::new(advancement, parent_idx));
148 self.advancements.push(advancement);
149 self.by_key.insert(id, node_idx);
150 if let Some(parent) = parent_idx {
151 let parent_node = self
152 .adv_nodes
153 .get_mut(parent)
154 .expect("unable to get the parent node");
155 parent_node.add_child(node_idx);
156 self.tasks.push(node_idx);
157 } else {
158 self.roots.push(node_idx);
159 }
160 }
161
162 fn try_register(&mut self, advancement: AdvancementRef) -> Option<AdvancementRef> {
163 let parent_id = &advancement.parent;
164 let parent_idx: Option<usize> = match parent_id {
165 Some(id) => match self.by_key.get(id) {
166 Some(node) => Some(*node),
167 None => return Some(advancement),
168 },
169 None => None,
170 };
171 self.register_with_parent(advancement, parent_idx);
172 None
173 }
174
175 fn register_all(&mut self, mut advancements_to_add: Vec<AdvancementRef>) {
176 while !advancements_to_add.is_empty() {
177 let len_before = advancements_to_add.len();
178
179 advancements_to_add = advancements_to_add
180 .into_iter()
181 .filter_map(|advancement| self.try_register(advancement))
182 .collect();
183
184 if advancements_to_add.len() == len_before && !advancements_to_add.is_empty() {
185 eprintln!(
186 "Couldn't load advancements: {:?}",
187 advancements_to_add
188 .iter()
189 .map(|a| &a.key)
190 .collect::<Vec<_>>()
191 );
192 break;
193 }
194 }
195 }
196
197 pub fn register(&mut self, advancement: AdvancementRef) -> bool {
200 self.unloaded_advancement.insert(advancement)
201 }
202
203 #[cfg(test)]
204 pub fn register_without_load(&mut self, advancements: &[AdvancementRef]) {
205 self.register_all(advancements.to_vec());
206 }
207
208 #[must_use]
209 #[inline]
210 pub fn value_by_key(&self, key: &Identifier) -> Option<AdvancementRef> {
211 self.by_key.get(key).map(|idx| self.advancements[*idx])
212 }
213
214 #[must_use]
215 #[inline]
216 pub fn by_key(&self, key: &Identifier) -> Option<&AdvancementNode> {
217 self.by_key
218 .get(key)
219 .and_then(|idx| self.adv_nodes.get(*idx))
220 }
221
222 #[must_use]
223 #[inline]
224 pub fn get_by_idx(&self, idx: usize) -> Option<&AdvancementNode> {
225 self.adv_nodes.get(idx)
226 }
227
228 pub fn iter(&self) -> impl Iterator<Item = (usize, &AdvancementNode)> + '_ {
229 self.adv_nodes.iter().enumerate()
230 }
231
232 pub(crate) fn update_tree(&mut self) {
234 let advancements = self.unloaded_advancement.drain().collect();
235 self.register_all(advancements);
236 for advancement_idx in self.roots.clone() {
237 let node = self.adv_nodes.get(advancement_idx);
238 let Some(node) = node else {
239 eprintln!("unable to get the root node with index {advancement_idx}");
240 return;
241 };
242 if node.has_display() {
243 let res = positioner::run(self, advancement_idx);
244 if let Err(e) = res {
245 eprintln!("{}", e.get_message());
246 }
247 }
248 }
249 }
250
251 #[must_use]
252 pub fn root(&'static self, advancement_node: AdvancementNodeRef) -> AdvancementNodeRef {
253 let mut advancement_node = advancement_node;
254 while let Some(parent) = &advancement_node.parent {
255 advancement_node = &self.adv_nodes[*parent];
256 }
257 advancement_node
258 }
259
260 pub fn remove_unloaded_advancement(&mut self, advancement: &Identifier) {
261 self.unloaded_advancement
262 .retain(|adv| adv.key() != advancement);
263 }
264}