homm5_scaner/entity/
hero.rs1use crate::{
2 entity::{Scan, Output, configure_path, CollectFiles},
3 pak::FileStructure
4};
5use quick_xml::{Reader, events::Event};
6use std::collections::HashMap;
7use homm5_types::{common::FileRef, hero::AdvMapHeroShared};
8
9impl Output for AdvMapHeroShared {
10 type ID = String;
11 fn to_lua(&self, _id: Option<String>) -> String {
12 let is_scenario_lua = if self.ScenarioHero == true {"1"} else {"nil"};
13 format!(
14 "\t[\"{}\"] = {{
15 is_scenario = {},
16 hero_class = {},
17 spec = {},
18 spec_name = \"{}\",
19 spec_desc = \"{}\",
20 spec_icon = \"{}\",
21 icon = \"{}\",
22 town = {},
23 name = \"{}\",
24 bio = \"{}\"
25 }},\n",
26 self.InternalName,
27 is_scenario_lua,
28 self.Class,
29 self.Specialization,
30 self.SpecializationNameFileRef.as_ref().unwrap().href.as_ref().unwrap_or(&String::new()),
31 self.SpecializationDescFileRef.as_ref().unwrap().href.as_ref().unwrap_or(&String::new()),
32 self.SpecializationIcon.as_ref().unwrap().href.as_ref().unwrap_or(&String::new()),
33 self.FaceTexture.as_ref().unwrap().href.as_ref().unwrap_or(&String::new()),
34 self.TownType,
35 self.Editable.NameFileRef.as_ref().unwrap().href.as_ref().unwrap_or(&String::new()),
36 self.Editable.BiographyFileRef.as_ref().unwrap().href.as_ref().unwrap_or(&String::new())
37 )
38 }
39
40 fn to_json(&self) -> String {
41 serde_json::to_string_pretty(self).unwrap()
42 }
43}
44
45pub struct HeroFileCollector {}
46
47impl CollectFiles for HeroFileCollector {
48 fn collect(&self, files: &HashMap<String, FileStructure>, collected_files: &mut Vec<(String, FileStructure)>) {
49 files.iter()
50 .filter(|f| {
51 f.1.content.contains("AdvMapHeroShared") && f.1.content.contains("ScenarioHero")
52 })
53 .for_each(|f| {
54 collected_files.push((f.0.clone(), f.1.clone()))
55 });
56 }
57}
58
59pub struct HeroScaner {}
60
61impl Scan<String> for HeroScaner {
62 fn scan(&mut self, file_key: &String, entity: &String, files: &HashMap<String, FileStructure>) -> Option<Box<dyn Output<ID = String>>> {
63 let mut buf = Vec::new();
64 let mut reader = Reader::from_str(entity);
65 reader.trim_text(true);
66 reader.expand_empty_elements(true);
67 loop {
68 match reader.read_event_into(&mut buf) {
69 Err(e) => panic!("Error at position {}: {:?}", reader.buffer_position(), e),
70 Ok(Event::Eof) => break None,
71 Ok(Event::Start(e)) => {
72 match e.name().as_ref() {
73 b"AdvMapHeroShared" => {
74 let end = e.to_end().into_owned();
75 let possible_text = reader.read_text(end.name());
76 match possible_text {
77 Ok(text) => {
78 let text = text.to_string();
79 let de_res: Result<AdvMapHeroShared, quick_xml::DeError> = quick_xml::de::from_str(&format!("<AdvMapHeroShared>{}</AdvMapHeroShared>", text));
80 match de_res {
81 Ok(mut hero) => {
82 let spec_name = configure_path(hero.SpecializationNameFileRef.as_ref().unwrap().href.as_ref(), file_key, files);
83 let spec_desc = configure_path(hero.SpecializationDescFileRef.as_ref().unwrap().href.as_ref(), file_key, files);
84 let spec_icon = configure_path(
85 Some(&hero.SpecializationIcon.as_ref().unwrap().href.as_ref()
86 .unwrap_or(&String::new()).replace("#xpointer(/Texture)", "")),
87 file_key,
88 files
89 );
90 let icon = configure_path(
91 Some(&hero.FaceTexture.as_ref().unwrap().href.as_ref()
92 .unwrap_or(&String::new()).replace("#xpointer(/Texture)", "")),
93 file_key,
94 files
95 );
96 let name = configure_path(hero.Editable.NameFileRef.as_ref().unwrap().href.as_ref(), file_key, files);
97 let bio = configure_path(hero.Editable.BiographyFileRef.as_ref().unwrap().href.as_ref(), file_key, files);
98 hero.SpecializationNameFileRef = Some(FileRef { href: Some(spec_name) });
99 hero.SpecializationDescFileRef = Some(FileRef { href: Some(spec_desc) });
100 hero.SpecializationIcon = Some(FileRef { href: Some(spec_icon) });
101 hero.FaceTexture = Some(FileRef { href: Some(icon) });
102 hero.Editable.NameFileRef = Some(FileRef { href: Some(name) });
103 hero.Editable.BiographyFileRef = Some(FileRef { href: Some(bio) });
104 break Some(Box::new(hero));
105 }
106 Err(e) => {
107 println!("error while deserializing {:?}", e.to_string());
108 }
109 }
110 },
111 Err(e) => println!("error reading file content: {}, {}", file_key, e.to_string())
112 }
113 }
114 _=> {}
115 }
116 }
117 _ => ()
118 }
119 buf.clear();
120 }
121 }
122
123 fn get_id(&self) -> Option<String> {
124 None
125 }
126
127}