homm5_scaner/entity/
art.rs

1use serde::{Serialize, Deserialize};
2use super::{Scan, Output, FileStructure, CollectFiles};
3use quick_xml::{Reader, events::Event};
4use std::collections::HashMap;
5use homm5_types::art::AdvMapArtifactShared;
6
7impl Output for AdvMapArtifactShared {
8    type ID = u16;
9
10    fn to_lua(&self, id: Option<Self::ID>) -> String {
11        let is_sellable = if self.CanBeGeneratedToSell == true {"1"} else {"nil"};
12        format!(
13            "\t[{}] = {{
14        is_sellable = {},
15        name = \"{}\",
16        desc = \"{}\",
17        icon = \"{}\",
18        cost = {},
19        slot = {},
20        type = {}
21    }},\n", 
22            id.unwrap() - 1,
23            is_sellable,
24            self.NameFileRef.as_ref().unwrap().href.as_ref().unwrap_or(&String::new()), 
25            self.DescriptionFileRef.as_ref().unwrap().href.as_ref().unwrap_or(&String::new()),
26            self.Icon.as_ref().unwrap().href.as_ref().unwrap_or(&String::new()),
27            self.CostOfGold,
28            self.Slot,
29            self.Type
30        )
31    }
32
33    fn to_json(&self) -> String {
34        serde_json::to_string_pretty(self).unwrap()
35    }
36}
37
38#[derive(Debug, Serialize, Deserialize)]
39#[allow(non_snake_case)]
40pub struct ArtObject {
41    pub ID: String,
42    pub obj: Option<String>
43}
44
45#[derive(Debug, Serialize, Deserialize)]
46pub struct ArtObjects {
47    #[serde(rename = "Item")]
48    pub arts: Vec<ArtObject>
49}
50
51pub struct ArtFileCollector {}
52
53impl CollectFiles for ArtFileCollector {
54    fn collect(&self, files: &HashMap<String, FileStructure>, collected_files: &mut Vec<(String, FileStructure)>) {
55        let arts_xdb = files.iter()
56            .find(|f| f.0 == "GameMechanics/RefTables/Artifacts.xdb".to_lowercase().as_str())
57            .unwrap();
58        //collected_files.push((arts_xdb.0.clone(), arts_xdb.1.clone()));
59        let mut buf = Vec::new();
60        let mut reader = Reader::from_str(arts_xdb.1.content.as_str());
61        reader.trim_text(true);
62        reader.expand_empty_elements(true);
63        loop {
64            match reader.read_event_into(&mut buf) {
65                Err(e) => panic!("Error at position {}: {:?}", reader.buffer_position(), e),
66                Ok(Event::Eof) => break,
67                Ok(Event::Start(e)) => {
68                    match e.name().as_ref() {
69                        b"obj" => {
70                            let end = e.to_end().into_owned();
71                            let text = reader.read_text(end.name()).unwrap().to_string();
72                            let text = format!("<obj>{}</obj>", text);
73                            collected_files.push(("GameMechanics/RefTables/Artifacts.xdb".to_lowercase(), FileStructure{
74                                pak: arts_xdb.1.pak.clone(),
75                                modified: arts_xdb.1.modified,
76                                content: text
77                            }));
78                        }
79                        _=> {}
80                    }
81                }
82                _ => ()
83            }
84            buf.clear();
85        }
86    }
87}
88
89pub struct ArtScaner {
90    pub id: u16,
91}
92
93impl Scan<u16> for ArtScaner {
94    fn get_id(&self) -> Option<u16> {
95        Some(self.id)
96    }
97
98    #[allow(unused_variables)]
99    fn scan(&mut self, file_key: &String, entity: &String, files: &HashMap<String, FileStructure>) -> Option<Box<dyn Output<ID = u16>>> {
100        let art_de: Result<AdvMapArtifactShared, quick_xml::DeError> = quick_xml::de::from_str(entity);
101        match art_de {
102            Ok(art) => {
103                self.id += 1;
104                Some(Box::new(art))
105            }
106            Err(e) => {
107                println!("error deserializing artifact {}", e.to_string());
108                None
109            }
110        }
111    }
112}