use std::collections::HashSet; use std::env::{current_dir, current_exe}; use std::fs::File; use std::ops::Deref; use log::info; use vfs::{ impls::{overlay::OverlayFS, physical::PhysicalFS}, VfsPath, }; use vfs_zip::ZipReadOnly as ZipFS; use crate::Error; #[derive(Clone)] pub struct Vfs(pub VfsPath); impl Vfs { pub fn new() -> Result { let dirs = vec![ current_exe() .ok() .as_ref() .and_then(|p| p.parent()) .map(|p| p.to_owned()), current_exe() .ok() .as_ref() .and_then(|p| p.parent()) .map(|p| p.join("space-crush")), current_dir().ok(), current_dir().ok().map(|p| p.join("space-crush")), ] .into_iter() .filter_map(|d| d); let mut paths = HashSet::new(); let mut layers = Vec::new(); for dir in dirs.clone() { if paths.insert(dir.clone()) { info!("Adding layer to VFS: {}", dir.display()); let layer = VfsPath::new(PhysicalFS::new(dir)); layers.push(layer); } } for dir in dirs { let path = dir.join("resources.bin"); if path.is_file() && paths.insert(path.to_owned()) { info!("Adding layer to VFS: {}", dir.display()); let zip = File::open(path)?; let layer = VfsPath::new(ZipFS::new_relaxed(zip)?); layers.push(layer); } } Ok(Self(VfsPath::new(OverlayFS::new(&layers)))) } } impl Deref for Vfs { type Target = VfsPath; fn deref(&self) -> &Self::Target { &self.0 } }