use crate::{error::S2ProtocolError, read_mpq};
use nom_mpq::MPQ;
use serde::{Deserialize, Serialize};
use tracing::instrument;
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct T3Terrain {
#[serde(rename = "heightMap", default)]
pub height_map: HeightMap,
}
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct HeightMap {
#[serde(rename = "rampList", default)]
ramp_list: Vec<Ramp>,
}
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct Ramp {
pub dir: u8,
pub hi: u8,
pub lo: u8,
#[serde(rename = "@leftLo", default)]
pub left_lo: String,
#[serde(rename = "@leftHi", default)]
pub left_hi: String,
#[serde(rename = "@rightLo", default)]
pub right_lo: String,
#[serde(rename = "@rightHi", default)]
pub right_hi: String,
pub base: String,
pub mid: String,
pub cid: usize,
#[serde(rename = "@leftLoVar", default)]
pub left_lo_var: u32,
#[serde(rename = "@leftHiVar", default)]
pub left_hi_var: u32,
#[serde(rename = "@rightLoVar", default)]
pub right_lo_var: u32,
#[serde(rename = "@rightHiVar", default)]
pub right_hi_var: u32,
}
#[instrument]
pub fn try_get_t3_height_map_from_mpq(
cache_handle_fname: &str,
) -> Result<T3Terrain, S2ProtocolError> {
let (mpq, cache_contents) = read_mpq(cache_handle_fname)?;
for (file, _file_size) in mpq.get_files(&cache_contents)? {
if file == "t3Terrain.xml" {
return Ok(serde_xml_rs::from_str::<T3Terrain>(&file)?);
}
}
Ok(T3Terrain::default())
}
impl T3Terrain {
#[instrument(level = "debug", skip(file_contents))]
pub fn parse(file_contents: &[u8]) -> Result<Self, S2ProtocolError> {
let str_content = str::from_utf8(file_contents)?;
Ok(serde_xml_rs::from_str::<T3Terrain>(str_content)?)
}
#[instrument(level = "debug", skip(mpq, file_contents))]
pub fn from_mpq(mpq: &MPQ, file_contents: &[u8]) -> Result<Self, S2ProtocolError> {
let (_, t3_terrain_sector) =
mpq.read_mpq_file_sector("t3Terrain.xml", false, file_contents)?;
let t3_terrain = Self::parse(&t3_terrain_sector)?;
Ok(t3_terrain)
}
}