You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

74 lines
1.7 KiB

  1. use std::collections::HashSet;
  2. use std::env::{current_dir, current_exe};
  3. use std::fs::File;
  4. use std::ops::Deref;
  5. use log::info;
  6. use vfs::{
  7. impls::{overlay::OverlayFS, physical::PhysicalFS},
  8. VfsPath,
  9. };
  10. use vfs_zip::ZipReadOnly as ZipFS;
  11. use crate::Error;
  12. #[derive(Clone)]
  13. pub struct Vfs(pub VfsPath);
  14. impl Vfs {
  15. pub fn new() -> Result<Self, Error> {
  16. let dirs = vec![
  17. current_exe()
  18. .ok()
  19. .as_ref()
  20. .and_then(|p| p.parent())
  21. .map(|p| p.to_owned()),
  22. current_exe()
  23. .ok()
  24. .as_ref()
  25. .and_then(|p| p.parent())
  26. .map(|p| p.join("space-crush")),
  27. current_dir().ok(),
  28. current_dir().ok().map(|p| p.join("space-crush")),
  29. ]
  30. .into_iter()
  31. .filter_map(|d| d);
  32. let mut paths = HashSet::new();
  33. let mut layers = Vec::new();
  34. for dir in dirs.clone() {
  35. if paths.insert(dir.clone()) {
  36. info!("Adding layer to VFS: {}", dir.display());
  37. let layer = VfsPath::new(PhysicalFS::new(dir));
  38. layers.push(layer);
  39. }
  40. }
  41. for dir in dirs {
  42. let path = dir.join("resources.bin");
  43. if path.is_file() && paths.insert(path.to_owned()) {
  44. info!("Adding layer to VFS: {}", dir.display());
  45. let zip = File::open(path)?;
  46. let layer = VfsPath::new(ZipFS::new_relaxed(zip)?);
  47. layers.push(layer);
  48. }
  49. }
  50. Ok(Self(VfsPath::new(OverlayFS::new(&layers))))
  51. }
  52. }
  53. impl Deref for Vfs {
  54. type Target = VfsPath;
  55. fn deref(&self) -> &Self::Target {
  56. &self.0
  57. }
  58. }