129 lines
5.4 KiB
Rust
129 lines
5.4 KiB
Rust
//! Map XML Parser
|
|
|
|
use crate::types::Map;
|
|
use super::{parse_attributes, XmlParseError};
|
|
use quick_xml::events::Event;
|
|
use quick_xml::reader::Reader;
|
|
use std::fs::File;
|
|
use std::io::BufReader;
|
|
use std::path::Path;
|
|
|
|
pub fn parse_maps_xml<P: AsRef<Path>>(path: P) -> Result<Vec<Map>, XmlParseError> {
|
|
let file = File::open(path)?;
|
|
let buf_reader = BufReader::new(file);
|
|
let mut reader = Reader::from_reader(buf_reader);
|
|
reader.config_mut().trim_text(true);
|
|
|
|
let mut maps = Vec::new();
|
|
let mut buf = Vec::new();
|
|
|
|
loop {
|
|
match reader.read_event_into(&mut buf) {
|
|
Ok(Event::Start(ref e)) | Ok(Event::Empty(ref e)) => {
|
|
match e.name().as_ref() {
|
|
b"map" => {
|
|
let attrs = parse_attributes(e)?;
|
|
|
|
// Get required attributes
|
|
let scene_id = attrs.get("sceneid")
|
|
.ok_or_else(|| XmlParseError::MissingAttribute("sceneid".to_string()))?
|
|
.clone();
|
|
|
|
let music = attrs.get("music")
|
|
.ok_or_else(|| XmlParseError::MissingAttribute("music".to_string()))?
|
|
.parse::<i32>()
|
|
.map_err(|_| XmlParseError::InvalidAttribute("music".to_string()))?;
|
|
|
|
let ambience = attrs.get("ambience")
|
|
.ok_or_else(|| XmlParseError::MissingAttribute("ambience".to_string()))?
|
|
.parse::<i32>()
|
|
.map_err(|_| XmlParseError::InvalidAttribute("ambience".to_string()))?;
|
|
|
|
let mut map = Map::new(scene_id, music, ambience);
|
|
|
|
// Parse optional attributes
|
|
if let Some(v) = attrs.get("name") {
|
|
map.name = v.clone();
|
|
}
|
|
if let Some(v) = attrs.get("fogcolor") {
|
|
map.fog_color = Some(v.clone());
|
|
}
|
|
if let Some(v) = attrs.get("fogginess") {
|
|
map.fogginess = v.parse().ok();
|
|
}
|
|
if let Some(v) = attrs.get("viewdistance") {
|
|
map.view_distance = v.parse().ok();
|
|
}
|
|
if let Some(v) = attrs.get("npcviewdistance") {
|
|
map.npc_view_distance = v.parse().ok();
|
|
}
|
|
if let Some(v) = attrs.get("sunlight") {
|
|
map.sunlight = v.parse().ok();
|
|
}
|
|
if let Some(v) = attrs.get("suncolor") {
|
|
map.sun_color = Some(v.clone());
|
|
}
|
|
if let Some(v) = attrs.get("ambientcolor") {
|
|
map.ambient_color = Some(v.clone());
|
|
}
|
|
if let Some(v) = attrs.get("indoorsunlight") {
|
|
map.indoor_sunlight = v.parse().ok();
|
|
}
|
|
if let Some(v) = attrs.get("fogstart") {
|
|
map.fog_start = v.parse().ok();
|
|
}
|
|
if attrs.get("indoors").is_some() {
|
|
map.indoors = true;
|
|
}
|
|
if attrs.get("noworldmap").is_some() {
|
|
map.no_world_map = true;
|
|
}
|
|
if attrs.get("nominimap").is_some() {
|
|
map.no_minimap = true;
|
|
}
|
|
if attrs.get("tpdisabled").is_some() {
|
|
map.tp_disabled = true;
|
|
}
|
|
if attrs.get("dontloadnearbyscenes").is_some() {
|
|
map.dont_load_nearby_scenes = true;
|
|
}
|
|
if attrs.get("noborder").is_some() {
|
|
map.no_border = true;
|
|
}
|
|
if attrs.get("borderleft").is_some() {
|
|
map.border_left = true;
|
|
}
|
|
if attrs.get("borderright").is_some() {
|
|
map.border_right = true;
|
|
}
|
|
if attrs.get("borderup").is_some() {
|
|
map.border_up = true;
|
|
}
|
|
if attrs.get("borderdown").is_some() {
|
|
map.border_down = true;
|
|
}
|
|
if let Some(v) = attrs.get("respawnmap") {
|
|
map.respawn_map = Some(v.clone());
|
|
}
|
|
if let Some(v) = attrs.get("connectedmaps") {
|
|
map.connected_maps = Some(v.clone());
|
|
}
|
|
if let Some(v) = attrs.get("comment") {
|
|
map.comment = Some(v.clone());
|
|
}
|
|
|
|
maps.push(map);
|
|
}
|
|
_ => {}
|
|
}
|
|
}
|
|
Ok(Event::Eof) => break,
|
|
Err(e) => return Err(XmlParseError::XmlError(e)),
|
|
_ => {}
|
|
}
|
|
buf.clear();
|
|
}
|
|
|
|
Ok(maps)
|
|
}
|