war 0.2.0

A viewer/editor for Darksiders saves, worlds, and scripts
Documentation
use crate::darksiders1::gfc;
use failure::Error;
use std::{
    convert::{TryFrom, TryInto},
    fs,
    io::{Read, Seek},
};

pub struct ResourcePackageInfo {
    pub name_user: String,
    pub path: Option<String>,
    pub permanent_id: i32,
    pub load_time: i32,
    pub category: i32,
    pub permanent_dependencies: Vec<i32>,
}

impl ResourcePackageInfo {
    fn create_package(
        &self,
        directory_manager: &mut gfc::DirectoryManager,
    ) -> Result<impl Read + Seek, Error> {
        let bin_ext = "oppc";
        let base_path = directory_manager.get(gfc::DirectoryManager::MEDIA);
        let package_file = format!(
            "{}/{}.{}",
            base_path.to_str().unwrap(),
            self.name_user,
            bin_ext
        );
        let package_file = fs::File::open(&package_file)?;
        Ok(package_file)
    }

    pub fn load(
        &self,
        directory_manager: &mut gfc::DirectoryManager,
    ) -> Result<Vec<gfc::Resource>, Error> {
        let mut package_file = self.create_package(directory_manager)?;
        gfc::ResourcePackageBin::load(&mut package_file)
    }
}

pub struct ResourcePackageList {
    pub packages: Vec<ResourcePackageInfo>,
    pub next_id: i32,
}

impl TryFrom<&gfc::Value> for ResourcePackageInfo {
    type Error = ();

    fn try_from(value: &gfc::Value) -> Result<Self, Self::Error> {
        let object = value.as_object().ok_or(())?;
        let path = match object.get_property("Path") {
            Some(value) => Some(value.as_hstring().ok_or(())?.to_string()),
            None => None,
        };
        let category = match object.get_property("Category") {
            Some(value) => value.as_int().ok_or(())?,
            None => 0,
        };
        let load_time = match object.get_property("LoadTime") {
            Some(value) => value.as_int().ok_or(())?,
            None => 0,
        };
        let permanent_dependencies = match object.get_property("PermanentDependencies")
        {
            Some(value) => {
                value
                    .as_array()
                    .ok_or(())?
                    .iter()
                    .map(|x| x.as_int().ok_or(()))
                    .collect::<Result<_, _>>()?
            }
            None => Vec::new(),
        };
        Ok(Self {
            name_user: object
                .get_property("NameUser")
                .and_then(gfc::Value::as_hstring)
                .ok_or(())?
                .to_string(),
            path,
            permanent_id: object
                .get_property("PermanentID")
                .and_then(gfc::Value::as_int)
                .ok_or(())?,
            load_time,
            category,
            permanent_dependencies,
        })
    }
}

impl TryFrom<&gfc::Object> for ResourcePackageList {
    type Error = ();

    fn try_from(object: &gfc::Object) -> Result<Self, Self::Error> {
        Ok(Self {
            packages: object
                .get_property("Packages")
                .and_then(gfc::Value::as_array)
                .ok_or(())?
                .iter()
                .map(TryInto::try_into)
                .collect::<Result<_, _>>()?,
            next_id: object
                .get_property("NextID")
                .and_then(gfc::Value::as_int)
                .ok_or(())?,
        })
    }
}