aboutsummaryrefslogtreecommitdiff
path: root/src/classes/pptr.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/classes/pptr.rs')
-rw-r--r--src/classes/pptr.rs69
1 files changed, 40 insertions, 29 deletions
diff --git a/src/classes/pptr.rs b/src/classes/pptr.rs
index 0e66b5f..5d57c20 100644
--- a/src/classes/pptr.rs
+++ b/src/classes/pptr.rs
@@ -1,13 +1,15 @@
use crate::{
assetbundle::AssetBundle,
object::{Value, parser::FromValue},
+ serialized_file::ExternalsContext,
};
-use anyhow::{Result, anyhow, bail};
+use anyhow::{Context, Result, anyhow, bail};
use log::debug;
use serde::Serialize;
use std::{
io::{Read, Seek},
marker::PhantomData,
+ sync::Arc,
};
#[derive(Debug, Serialize)]
@@ -15,19 +17,15 @@ pub struct PPtr<T = Value> {
#[serde(skip, default)]
pub(crate) _class: PhantomData<T>,
pub class: String,
- pub source_file: usize,
+ #[serde(skip)]
+ pub ecx: Arc<ExternalsContext>,
pub file_id: i32,
pub path_id: i64,
}
impl<T> FromValue for PPtr<T> {
fn from_value(v: Value) -> Result<Self> {
- let Value::Object {
- class,
- fields,
- file,
- } = v
- else {
+ let Value::Object { class, fields, ecx } = v else {
bail!("PPtr expected but not an object")
};
let inner = class
@@ -38,7 +36,7 @@ impl<T> FromValue for PPtr<T> {
Ok(PPtr {
class: inner.to_owned(),
_class: PhantomData,
- source_file: file,
+ ecx,
file_id: fields["m_FileID"]
.as_i32()
.ok_or(anyhow!("PPtr m_FileID is not i32"))?,
@@ -54,7 +52,7 @@ impl<T: FromValue> PPtr<T> {
PPtr {
_class: PhantomData,
class: self.class,
- source_file: self.source_file,
+ ecx: self.ecx.clone(),
file_id: self.file_id,
path_id: self.path_id,
}
@@ -67,32 +65,45 @@ impl<T: FromValue> PPtr<T> {
"loading PPtr<{}> file_id={} path_id={}",
self.class, self.file_id, self.path_id
);
- let main_file = match (self.source_file, self.file_id) {
- (0, 0) => true,
- (0, 1) => false,
- (1, 0) => false,
- _ => unreachable!(),
+ let path = if self.file_id == 0 {
+ &self.ecx.name
+ } else {
+ &self.ecx.externals[self.file_id as usize - 1].path_name
};
- if main_file {
- let ob = bundle
- .main
- .objects
+ if let Some(path) = path.strip_prefix("archive:") {
+ let path = path.split_once("/").unwrap_or(("", path)).1;
+ let ni = bundle
+ .fs
+ .header
+ .nodes()
.iter()
- .find(|o| o.path_id == self.path_id)
- .ok_or(anyhow!("object with path id {} not found", self.path_id))?
- .to_owned();
- bundle.main.read_object(ob)?.parse()
- } else {
- let file = bundle.shared_assets.as_mut().ok_or(anyhow!(
- "shared assets referenced but not included in bundle"
- ))?;
+ .find(|n| n.name == path)
+ .unwrap()
+ .clone();
+ let file = bundle.get_fs_file(&ni).unwrap();
+ let mut file = file.lock().unwrap();
let ob = file
.objects
.iter()
.find(|o| o.path_id == self.path_id)
- .ok_or(anyhow!("object with path id {} not found", self.path_id))?
- .to_owned();
+ .unwrap()
+ .clone();
file.read_object(ob)?.parse()
+ } else if *path == bundle.default_resources.ecx.name {
+ let ob = bundle
+ .default_resources
+ .objects
+ .iter()
+ .find(|o| o.path_id == self.path_id)
+ .unwrap()
+ .clone();
+ bundle
+ .default_resources
+ .read_object(ob)
+ .context("reading object from default res file")?
+ .parse()
+ } else {
+ unreachable!("{path:?}")
}
}
}