diff options
author | metamuffin <metamuffin@disroot.org> | 2025-03-22 19:48:53 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-03-22 19:48:53 +0100 |
commit | 205aca90d6c21f3dd73b576c06f5ab8c1010772a (patch) | |
tree | 8a5b58c2b1aca919d94bcdb1fe7d4edb91968ca9 /src/assetbundle.rs | |
parent | 2ee2f1af847dbc9f1292baefc9fd652167b9103a (diff) | |
download | unity-tools-205aca90d6c21f3dd73b576c06f5ab8c1010772a.tar unity-tools-205aca90d6c21f3dd73b576c06f5ab8c1010772a.tar.bz2 unity-tools-205aca90d6c21f3dd73b576c06f5ab8c1010772a.tar.zst |
horrible pptr external files system
Diffstat (limited to 'src/assetbundle.rs')
-rw-r--r-- | src/assetbundle.rs | 132 |
1 files changed, 90 insertions, 42 deletions
diff --git a/src/assetbundle.rs b/src/assetbundle.rs index 8f6af15..0af9895 100644 --- a/src/assetbundle.rs +++ b/src/assetbundle.rs @@ -1,81 +1,129 @@ use crate::{ classes::pptr::PPtr, serialized_file::SerializedFile, - unityfs::{NodeReader, UnityFS, block_reader::BlockReader, multi_reader::MultiReader}, + unityfs::{ + NodeReader, UnityFS, block_reader::BlockReader, header::NodeInfo, multi_reader::MultiReader, + }, }; use anyhow::{Context, Result, anyhow}; use log::debug; use std::{ - io::{Read, Seek}, + collections::HashMap, + fs::File, + io::{BufReader, Read, Seek}, marker::PhantomData, + path::Path, + sync::{Arc, Mutex}, }; /// High-level wrapper around UnityFS, SerializedFile and all the classes. pub struct AssetBundle<T> { pub fs: UnityFS<T>, - pub(crate) main: SerializedFile<NodeReader<BlockReader<MultiReader<T>>>>, - pub(crate) shared_assets: Option<SerializedFile<NodeReader<BlockReader<MultiReader<T>>>>>, + pub ser_files: + HashMap<String, Arc<Mutex<SerializedFile<NodeReader<BlockReader<MultiReader<T>>>>>>>, + pub main_file: NodeInfo, + pub default_resources: SerializedFile<BufReader<File>>, } impl<T: Read + Seek> AssetBundle<T> { - pub fn open(inner: T) -> Result<Self> { + pub fn open(inner: T, support_dir: impl AsRef<Path>) -> Result<Self> { let fs = UnityFS::open(inner).context("opening UnityFS")?; - let main_ni = fs + let main_file = fs .find_main_file() - .ok_or(anyhow!("AssetBundle seems to lack main file"))?; - debug!("detected {:?} as main file", main_ni.name); - let main = SerializedFile::read(fs.read(main_ni)?, 0)?; - let shared_assets = if let Some(n) = main.find_fs_shared_assets(&fs) { - debug!("detect {:?} as shared assets", n.name); - Some(SerializedFile::read(fs.read(&n)?, 1)?) - } else { - None - }; + .ok_or(anyhow!("AssetBundle seems to lack main file"))? + .clone(); + debug!("opening default resource file"); + let default_resources = SerializedFile::read( + BufReader::new(File::open( + support_dir.as_ref().join("unity default resources"), + )?), + "Library/unity default resources".to_owned(), + )?; + debug!("detected {:?} as main file", main_file.name); Ok(Self { fs, - main, - shared_assets, + main_file, + default_resources, + ser_files: HashMap::new(), }) } - pub fn all_toplevel(&self) -> impl Iterator<Item = PPtr> { - self.main + pub fn get_fs_file( + &mut self, + node: &NodeInfo, + ) -> Result<Arc<Mutex<SerializedFile<NodeReader<BlockReader<MultiReader<T>>>>>>> { + if !self.ser_files.contains_key(&node.name) { + let file = + SerializedFile::read(self.fs.read(node)?, format!("archive:/{}", node.name))?; + self.ser_files + .insert(node.name.clone(), Arc::new(Mutex::new(file))); + } + Ok(self.ser_files.get(&node.name).unwrap().clone()) + } + + pub fn all_toplevel(&mut self) -> Vec<PPtr> { + let main = self.get_fs_file(&self.main_file.clone()).unwrap(); + let main = main.lock().unwrap(); + let shared_assets = main.find_fs_shared_assets(&self.fs); + let main_obs = main .objects .iter() - .map(|o| (0, o)) - .chain( - self.shared_assets - .as_ref() - .map(|e| e.objects.iter().map(|o| (1, o))) - .into_iter() - .flatten(), - ) - .map(|(si, o)| PPtr { + .map(|o| (main.ecx.clone(), o.to_owned())) + .collect::<Vec<_>>(); + let shared_obs = if let Some(shared_assets) = shared_assets { + let shared = self.get_fs_file(&shared_assets).unwrap(); + let shared = shared.lock().unwrap(); + shared + .objects + .iter() + .map(|o| (shared.ecx.clone(), o.to_owned())) + .collect() + } else { + Vec::new() + }; + + main_obs + .into_iter() + .chain(shared_obs) + .map(|(ecx, o)| PPtr { class: "".to_string(), - source_file: si, + ecx, file_id: 0, path_id: o.path_id, _class: PhantomData, }) + .collect() } - pub fn all_toplevel_of_class(&self, class_name: &str) -> impl Iterator<Item = PPtr> { - self.main + pub fn all_toplevel_of_class(&mut self, class_name: &str) -> Vec<PPtr> { + let main = self.get_fs_file(&self.main_file.clone()).unwrap(); + let main = main.lock().unwrap(); + let shared_assets = main.find_fs_shared_assets(&self.fs); + let main_obs = main .all_objects_of_class(class_name) - .map(|o| (0, o)) - .chain( - self.shared_assets - .as_ref() - .map(|e| e.all_objects_of_class(class_name).map(|o| (1, o))) - .into_iter() - .flatten(), - ) - .map(|(si, o)| PPtr { - class: class_name.to_owned(), - source_file: si, + .map(|o| (main.ecx.clone(), o.to_owned())) + .collect::<Vec<_>>(); + let shared_obs = if let Some(shared_assets) = shared_assets { + let shared = self.get_fs_file(&shared_assets).unwrap(); + let shared = shared.lock().unwrap(); + shared + .all_objects_of_class(class_name) + .map(|o| (shared.ecx.clone(), o.to_owned())) + .collect() + } else { + Vec::new() + }; + + main_obs + .into_iter() + .chain(shared_obs) + .map(|(ecx, o)| PPtr { + class: "".to_string(), + ecx, file_id: 0, path_id: o.path_id, _class: PhantomData, }) + .collect() } } |