homm5_scaner/entity/
spell.rs1use super::{configure_path, CollectFiles, FileObjects, FileStructure, Output, Scan};
2use quick_xml::{Reader, events::Event};
3use std::collections::HashMap;
4use homm5_types::{common::FileRef, spell::SpellShared};
5
6impl Output for SpellShared {
7 type ID = u16;
8 fn to_lua(&self, id: Option<Self::ID>) -> String {
9 let is_aimed = if self.IsAimed == true {"1"} else {"nil"};
10 let is_area = if self.IsAreaAttack == true {"1"} else {"nil"};
11 format!(
12 "\t[{}] = {{
13 name = \"{}\",
14 desc = \"{}\",
15 icon = \"{}\",
16 school = {},
17 level = {},
18 is_aimed = {},
19 is_area = {}
20 }},\n",
21 id.unwrap(),
22 self.NameFileRef.as_ref().unwrap().href.as_ref().unwrap_or(&String::new()),
23 self.LongDescriptionFileRef.as_ref().unwrap().href.as_ref().unwrap_or(&String::new()),
24 self.Texture.as_ref().unwrap().href.as_ref().unwrap_or(&String::new()),
25 self.MagicSchool,
26 self.Level,
27 is_aimed,
28 is_area
29 )
30 }
31
32 fn to_json(&self) -> String {
33 serde_json::to_string_pretty(self).unwrap()
34 }
35}
36
37pub struct SpellFileCollector {
38}
39
40impl CollectFiles for SpellFileCollector {
41 fn collect(&self, files: &HashMap<String, FileStructure>, collected_files: &mut Vec<(String, FileStructure)>) {
42 let spells_xdb = files.iter()
43 .find(|f| f.0 == "GameMechanics/RefTables/UndividedSpells.xdb".to_lowercase().as_str())
44 .unwrap();
45 let mut buf = Vec::new();
46 let mut reader = Reader::from_str(spells_xdb.1.content.as_str());
47 reader.trim_text(true);
48 reader.expand_empty_elements(true);
49 loop {
50 match reader.read_event_into(&mut buf) {
51 Err(e) => panic!("Error at position {}: {:?}", reader.buffer_position(), e),
52 Ok(Event::Eof) => break,
53 Ok(Event::Start(e)) => {
54 match e.name().as_ref() {
55 b"objects" => {
56 let end = e.to_end().into_owned();
57 let text = reader.read_text(end.name()).unwrap().to_string();
58 let text = format!("<objects>{}</objects>", text);
59 let spells_de: Result<FileObjects, quick_xml::DeError> = quick_xml::de::from_str(&text);
60 match spells_de {
61 Ok(spells) => {
62 for spell in spells.objects {
63 match spell.Obj {
64 Some(obj) => {
65 match obj.href.as_ref() {
66 Some(href) => {
67 let spell_key = href
68 .replace("#xpointer(/Spell)", "")
69 .trim_start_matches("/")
70 .to_lowercase();
71 let spell_entity = files.get(&spell_key);
72 match spell_entity {
73 Some(entity) => {
74 collected_files.push((spell_key.clone(), entity.clone()));
75 },
76 None => println!("Key {} is not in files", &spell_key)
77 }
78 },
79 None => {}
80 }
81 }
82 None => {}
83 }
84 }
85 },
86 Err(e) => println!("Error deserializing spells.xdb, {}", e.to_string())
87 }
88 }
89 _=> {}
90 }
91 }
92 _ => ()
93 }
94 buf.clear();
95 }
96 }
97}
98
99pub struct SpellScaner {
100 pub id: u16
101}
102
103impl Scan<u16> for SpellScaner {
104 fn scan(&mut self, file_key: &String, entity: &String, files: &HashMap<String, FileStructure>) -> Option<Box<dyn Output<ID = u16>>> {
105 let mut buf = Vec::new();
106 let mut reader = Reader::from_str(entity);
107 reader.trim_text(true);
108 reader.expand_empty_elements(true);
109 loop {
110 match reader.read_event_into(&mut buf) {
111 Err(e) => panic!("Error at position {}: {:?}", reader.buffer_position(), e),
112 Ok(Event::Eof) => break None,
113 Ok(Event::Start(e)) => {
114 match e.name().as_ref() {
115 b"Spell" => {
116 let end = e.to_end().into_owned();
117 let possible_text = reader.read_text(end.name());
118 match possible_text {
119 Ok(text) => {
120 let text = text.to_string();
121 let de_res: Result<SpellShared, quick_xml::DeError> = quick_xml::de::from_str(
122 &format!("<Spell>{}</Spell>", text)
123 );
124 match de_res {
125 Ok(mut spell) => {
126 let name = configure_path(spell.NameFileRef.as_ref().unwrap().href.as_ref(), file_key, files);
127 let desc = configure_path(spell.LongDescriptionFileRef.as_ref().unwrap().href.as_ref(), file_key, files);
128 let icon_key = spell.Texture.as_ref().unwrap().href.as_ref().unwrap_or(&String::new())
129 .replace("#xpointer(/Texture)", "")
130 .to_lowercase();
131 let icon = configure_path(Some(&icon_key), file_key, files);
132 spell.NameFileRef = Some(FileRef { href: Some(name) });
133 spell.LongDescriptionFileRef = Some(FileRef { href: Some(desc) });
134 spell.Texture = Some(FileRef { href: Some(icon) });
135 self.id+=1;
136 break Some(Box::new(spell));
137 }
138 Err(e) => {
139 println!("error while deserializing file key {}, {:?}", file_key, e.to_string());
140 }
141 }
142 },
143 Err(_e) => println!("error reading file content: {}", file_key)
144 }
145 }
146 _=> {}
147 }
148 }
149 _ => ()
150 }
151 buf.clear();
152 }
153 }
154
155 fn get_id(&self) -> Option<u16> {
156 Some(self.id)
157 }
158}