oxygengine_overworld/resources/
quests.rs

1use crate::resources::market::{Currency, MarketItemId};
2use oxygengine_core::id::ID;
3use std::collections::{HashMap, HashSet};
4
5pub type ObjectiveId = ID<Objective<()>>;
6pub type QuestId = ID<Quest<(), ()>>;
7
8#[derive(Debug, Clone)]
9pub struct Objective<T>
10where
11    T: std::fmt::Debug + Clone + Send + Sync,
12{
13    pub data: T,
14}
15
16impl<T> Default for Objective<T>
17where
18    T: std::fmt::Debug + Default + Clone + Send + Sync,
19{
20    fn default() -> Self {
21        Self {
22            data: Default::default(),
23        }
24    }
25}
26
27#[derive(Debug, Clone)]
28pub enum QuestReward<V>
29where
30    V: Currency + std::fmt::Debug + Clone + Send + Sync,
31{
32    MarketItem(MarketItemId),
33    Currency(V),
34}
35
36#[derive(Debug, Clone)]
37pub struct Quest<T, V>
38where
39    T: std::fmt::Debug + Clone + Send + Sync,
40    V: Currency + std::fmt::Debug + Clone + Send + Sync,
41{
42    pub data: T,
43    pub objectives: HashSet<ObjectiveId>,
44    pub rewards: Vec<QuestReward<V>>,
45}
46
47impl<T, V> Default for Quest<T, V>
48where
49    T: std::fmt::Debug + Default + Clone + Send + Sync,
50    V: Currency + std::fmt::Debug + Clone + Send + Sync,
51{
52    fn default() -> Self {
53        Self {
54            data: Default::default(),
55            objectives: Default::default(),
56            rewards: Default::default(),
57        }
58    }
59}
60
61impl<T, V> Quest<T, V>
62where
63    T: std::fmt::Debug + Clone + Send + Sync,
64    V: Currency + std::fmt::Debug + Clone + Send + Sync,
65{
66    pub fn new(data: T) -> Self {
67        Self {
68            data,
69            objectives: Default::default(),
70            rewards: Default::default(),
71        }
72    }
73
74    pub fn with_objective(mut self, id: ObjectiveId) -> Self {
75        self.objectives.insert(id);
76        self
77    }
78
79    pub fn with_reward(mut self, reward: QuestReward<V>) -> Self {
80        self.rewards.push(reward);
81        self
82    }
83}
84
85#[derive(Debug, Clone)]
86pub struct QuestsDatabase<Q, B, V>
87where
88    Q: std::fmt::Debug + Clone + Send + Sync,
89    B: std::fmt::Debug + Clone + Send + Sync,
90    V: Currency + std::fmt::Debug + Clone + Send + Sync,
91{
92    objectives: HashMap<ObjectiveId, Objective<B>>,
93    quests: HashMap<QuestId, Quest<Q, V>>,
94}
95
96impl<Q, B, V> Default for QuestsDatabase<Q, B, V>
97where
98    Q: std::fmt::Debug + Clone + Send + Sync,
99    B: std::fmt::Debug + Clone + Send + Sync,
100    V: Currency + std::fmt::Debug + Clone + Send + Sync,
101{
102    fn default() -> Self {
103        Self {
104            objectives: Default::default(),
105            quests: Default::default(),
106        }
107    }
108}
109
110impl<Q, B, V> QuestsDatabase<Q, B, V>
111where
112    Q: std::fmt::Debug + Clone + Send + Sync,
113    B: std::fmt::Debug + Clone + Send + Sync,
114    V: Currency + std::fmt::Debug + Clone + Send + Sync,
115{
116    pub fn register_objective(&mut self, item: Objective<B>) -> ObjectiveId {
117        let id = ObjectiveId::new();
118        self.objectives.insert(id, item);
119        id
120    }
121
122    pub fn register_many_objectives<'a>(
123        &'a mut self,
124        iter: impl Iterator<Item = Objective<B>> + 'a,
125    ) -> impl Iterator<Item = ObjectiveId> + 'a {
126        let reserve = iter.size_hint();
127        let reserve = reserve.1.unwrap_or(reserve.0);
128        self.objectives.reserve(reserve);
129        iter.map(|item| self.register_objective(item))
130    }
131
132    pub fn unregister_objective(&mut self, id: ObjectiveId) -> Option<Objective<B>> {
133        if let Some(objective) = self.objectives.remove(&id) {
134            for quest in self.quests.values_mut() {
135                quest.objectives.remove(&id);
136            }
137            return Some(objective);
138        }
139        None
140    }
141
142    pub fn unregister_many_objectives<'a>(
143        &'a mut self,
144        iter: impl Iterator<Item = ObjectiveId> + 'a,
145    ) -> impl Iterator<Item = Objective<B>> + 'a {
146        iter.filter_map(|id| self.unregister_objective(id))
147    }
148
149    pub fn objectives(&self) -> impl Iterator<Item = (ObjectiveId, &Objective<B>)> {
150        self.objectives
151            .iter()
152            .map(|(id, objective)| (*id, objective))
153    }
154
155    pub fn objective(&self, id: ObjectiveId) -> Option<&Objective<B>> {
156        self.objectives.get(&id)
157    }
158
159    pub fn objective_mut(&mut self, id: ObjectiveId) -> Option<&mut Objective<B>> {
160        self.objectives.get_mut(&id)
161    }
162
163    pub fn find_objectives(
164        &self,
165        iter: impl Iterator<Item = ObjectiveId>,
166    ) -> impl Iterator<Item = (ObjectiveId, &Objective<B>)> {
167        iter.filter_map(|id| self.objective(id).map(|objective| (id, objective)))
168    }
169
170    pub fn contains_objective(&self, id: ObjectiveId) -> bool {
171        self.objectives.contains_key(&id)
172    }
173
174    pub fn objective_id(&self, data: &B) -> Option<ObjectiveId>
175    where
176        B: PartialEq,
177    {
178        self.objectives
179            .iter()
180            .find(|(_, objective)| &objective.data == data)
181            .map(|(id, _)| *id)
182    }
183
184    pub fn register_quest(&mut self, item: Quest<Q, V>) -> QuestId {
185        let id = QuestId::new();
186        self.quests.insert(id, item);
187        id
188    }
189
190    pub fn register_many_quests<'a>(
191        &'a mut self,
192        iter: impl Iterator<Item = Quest<Q, V>> + 'a,
193    ) -> impl Iterator<Item = QuestId> + 'a {
194        let reserve = iter.size_hint();
195        let reserve = reserve.1.unwrap_or(reserve.0);
196        self.quests.reserve(reserve);
197        iter.map(|item| self.register_quest(item))
198    }
199
200    pub fn unregister_quest(&mut self, id: QuestId) -> Option<Quest<Q, V>> {
201        self.quests.remove(&id)
202    }
203
204    pub fn unregister_many_quests<'a>(
205        &'a mut self,
206        iter: impl Iterator<Item = QuestId> + 'a,
207    ) -> impl Iterator<Item = Quest<Q, V>> + 'a {
208        iter.filter_map(|id| self.unregister_quest(id))
209    }
210
211    pub fn quests(&self) -> impl Iterator<Item = (QuestId, &Quest<Q, V>)> {
212        self.quests.iter().map(|(id, quest)| (*id, quest))
213    }
214
215    pub fn quest(&self, id: QuestId) -> Option<&Quest<Q, V>> {
216        self.quests.get(&id)
217    }
218
219    pub fn quest_mut(&mut self, id: QuestId) -> Option<&mut Quest<Q, V>> {
220        self.quests.get_mut(&id)
221    }
222
223    pub fn find_quests(
224        &self,
225        iter: impl Iterator<Item = QuestId>,
226    ) -> impl Iterator<Item = (QuestId, &Quest<Q, V>)> {
227        iter.filter_map(|id| self.quest(id).map(|quest| (id, quest)))
228    }
229
230    pub fn contains_quest(&self, id: QuestId) -> bool {
231        self.quests.contains_key(&id)
232    }
233
234    pub fn quest_id(&self, data: &Q) -> Option<QuestId>
235    where
236        Q: PartialEq,
237    {
238        self.quests
239            .iter()
240            .find(|(_, quest)| &quest.data == data)
241            .map(|(id, _)| *id)
242    }
243}