ck3_history_extractor/structures/
mod.rs

1use std::{
2    any::type_name,
3    hash::{Hash, Hasher},
4};
5
6use super::{
7    game_data::{GameData, Localizable, LocalizationError},
8    parser::{GameObjectMap, GameRef, GameState, ParsingError},
9    types::{GameId, GameString, Wrapper, WrapperMut},
10};
11
12/// A submodule that provides the [Player] object.
13mod player;
14use derive_more::From;
15pub use player::Player;
16
17/// A submodule that provides the [Character] object.
18mod character;
19pub use character::Character;
20
21/// A submodule that provides the [Faith] object.
22mod faith;
23pub use faith::Faith;
24
25/// A submodule that provides the [Culture] object.
26mod culture;
27pub use culture::Culture;
28
29/// A submodule that provides the [Dynasty] object.
30mod dynasty;
31pub use dynasty::Dynasty;
32
33mod house;
34pub use house::House;
35
36/// A submodule that provides the [Memory] object.
37mod memory;
38pub use memory::Memory;
39
40/// A submodule that provides the [Title] object.
41mod title;
42use serde::Serialize;
43pub use title::Title;
44
45/// A submodule that provides the [LineageNode] object.
46mod lineage;
47pub use lineage::LineageNode;
48
49/// A submodule that provides the [Artifact] object.
50mod artifact;
51pub use artifact::Artifact;
52
53pub trait FromGameObject: GameObjectDerived {
54    fn from_game_object(
55        base: &GameObjectMap,
56        game_state: &mut GameState,
57    ) -> Result<Self, ParsingError>;
58
59    #[allow(unused_variables)]
60    fn finalize(&mut self, reference: &GameRef<Self>) {}
61}
62
63/// A trait for objects that can be created from a [GameObjectMap].
64/// Currently these include: [Character], [Culture], [Dynasty], [Faith], [Memory], [Player], [Title].
65/// The idea is to have uniform interface for the object initialization.
66pub trait GameObjectDerived: Sized {
67    /// Get the name of the object.
68    /// The result of this method depends on the type.
69    fn get_name(&self) -> GameString;
70
71    /// Extends the provided collection with references to other [GameObjectDerived] objects, if any.
72    fn get_references<E: From<EntityRef>, C: Extend<E>>(&self, collection: &mut C);
73}
74
75#[derive(Serialize, Debug)]
76pub struct GameObjectEntity<T: GameObjectDerived> {
77    id: GameId,
78    /* TODO I would for there to be a way to make this NOT an option,
79    naturally this is an option because in the current model we trust structures
80    that the IDs are valid, but sometimes they arent, meaning we cant implement
81    Deref. If we wanted to fix this we would need to have two sets of
82    structures, converting between them in the finalize step but thats a big rework
83    */
84    #[serde(flatten)]
85    entity: Option<T>,
86}
87
88impl<T: GameObjectDerived + FromGameObject> GameObjectEntity<T> {
89    pub fn new(id: GameId) -> Self {
90        Self { id, entity: None }
91    }
92
93    pub fn get_id(&self) -> GameId {
94        self.id
95    }
96
97    /// Get the unique identifier of the object.
98    /// This is a tuple of the id and the type name.
99    pub fn get_unique_identifier(&self) -> (GameId, &'static str) {
100        (self.get_id(), type_name::<T>())
101    }
102
103    pub fn init(
104        &mut self,
105        base: &GameObjectMap,
106        game_state: &mut GameState,
107    ) -> Result<(), ParsingError> {
108        self.entity = Some(T::from_game_object(base, game_state)?);
109        Ok(())
110    }
111
112    pub fn inner(&self) -> Option<&T> {
113        self.entity.as_ref()
114    }
115
116    pub fn inner_mut(&mut self) -> Option<&mut T> {
117        self.entity.as_mut()
118    }
119
120    pub fn replace(&mut self, entity: T) {
121        self.entity.replace(entity);
122    }
123}
124
125impl<T: GameObjectDerived + FromGameObject> PartialEq for GameObjectEntity<T> {
126    fn eq(&self, other: &Self) -> bool {
127        self.get_unique_identifier() == other.get_unique_identifier()
128    }
129}
130
131impl<T: GameObjectDerived + FromGameObject> Eq for GameObjectEntity<T> {}
132
133impl<T: GameObjectDerived + FromGameObject> Hash for GameObjectEntity<T> {
134    fn hash<H: Hasher>(&self, state: &mut H) {
135        self.get_unique_identifier().hash(state);
136    }
137}
138
139impl<T: Localizable + GameObjectDerived + FromGameObject> Localizable for GameRef<T> {
140    fn localize(&mut self, localization: &GameData) -> Result<(), LocalizationError> {
141        if let Some(entity) = self.get_internal_mut().entity.as_mut() {
142            entity.finalize(self);
143            entity.localize(localization)
144        } else {
145            Ok(())
146        }
147    }
148}
149
150impl<T: GameObjectDerived + FromGameObject> PartialEq for GameRef<T> {
151    fn eq(&self, other: &Self) -> bool {
152        if let Ok(a) = self.try_get_internal() {
153            if let Ok(b) = other.try_get_internal() {
154                a.get_unique_identifier() == b.get_unique_identifier()
155            } else {
156                false
157            }
158        } else {
159            false
160        }
161    }
162}
163
164impl<T: GameObjectDerived + FromGameObject> Eq for GameRef<T> {}
165
166impl<T: GameObjectDerived + FromGameObject> Hash for GameRef<T> {
167    fn hash<H: Hasher>(&self, state: &mut H) {
168        if let Ok(internal) = self.try_get_internal() {
169            internal.get_unique_identifier().hash(state);
170        }
171    }
172}
173
174#[derive(From, PartialEq, Eq)]
175pub enum EntityRef {
176    Character(GameRef<Character>),
177    Culture(GameRef<Culture>),
178    Dynasty(GameRef<Dynasty>),
179    House(GameRef<House>),
180    Faith(GameRef<Faith>),
181    Title(GameRef<Title>),
182    Memory(GameRef<Memory>),
183    Artifact(GameRef<Artifact>),
184}
185
186impl Hash for EntityRef {
187    fn hash<H: Hasher>(&self, state: &mut H) {
188        match self {
189            EntityRef::Character(char) => char.get_internal().hash(state),
190            EntityRef::Culture(cul) => cul.get_internal().hash(state),
191            EntityRef::Dynasty(dynasty) => dynasty.get_internal().hash(state),
192            EntityRef::House(house) => house.get_internal().hash(state),
193            EntityRef::Faith(faith) => faith.get_internal().hash(state),
194            EntityRef::Title(title) => title.get_internal().hash(state),
195            EntityRef::Memory(mem) => mem.get_internal().hash(state),
196            EntityRef::Artifact(art) => art.get_internal().hash(state),
197        }
198    }
199}
200
201impl GameObjectDerived for EntityRef {
202    fn get_name(&self) -> GameString {
203        match self {
204            EntityRef::Character(char) => char.get_internal().inner().unwrap().get_name(),
205            EntityRef::Culture(cul) => cul.get_internal().inner().unwrap().get_name(),
206            EntityRef::Dynasty(dynasty) => dynasty.get_internal().inner().unwrap().get_name(),
207            EntityRef::House(house) => house.get_internal().inner().unwrap().get_name(),
208            EntityRef::Faith(faith) => faith.get_internal().inner().unwrap().get_name(),
209            EntityRef::Title(title) => title.get_internal().inner().unwrap().get_name(),
210            EntityRef::Memory(mem) => mem.get_internal().inner().unwrap().get_name(),
211            EntityRef::Artifact(art) => art.get_internal().inner().unwrap().get_name(),
212        }
213    }
214
215    fn get_references<E: From<EntityRef>, C: Extend<E>>(&self, collection: &mut C) {
216        match self {
217            EntityRef::Character(char) => char
218                .get_internal()
219                .inner()
220                .map(|v| v.get_references(collection)),
221            EntityRef::Culture(cul) => cul
222                .get_internal()
223                .inner()
224                .map(|v| v.get_references(collection)),
225            EntityRef::Dynasty(dynasty) => dynasty
226                .get_internal()
227                .inner()
228                .map(|v| v.get_references(collection)),
229            EntityRef::House(house) => house
230                .get_internal()
231                .inner()
232                .map(|v| v.get_references(collection)),
233            EntityRef::Faith(faith) => faith
234                .get_internal()
235                .inner()
236                .map(|v| v.get_references(collection)),
237            EntityRef::Title(title) => title
238                .get_internal()
239                .inner()
240                .map(|v| v.get_references(collection)),
241            EntityRef::Memory(mem) => mem
242                .get_internal()
243                .inner()
244                .map(|v| v.get_references(collection)),
245            EntityRef::Artifact(art) => art
246                .get_internal()
247                .inner()
248                .map(|v| v.get_references(collection)),
249        };
250    }
251}