This repository has been archived on 2026-10-10. You can view files and clone it, but cannot push or open issues or pull requests.
molotov/crates/molotov-core/src/assets/manager.rs

71 lines
2 KiB
Rust

// SPDX-License-Identifier: GPL-3.0-or-later
use super::asset::AssetFile;
use super::dir::AssetDir;
use std::collections::HashMap;
pub struct AssetManager {
base_assets: HashMap<String, Vec<u8>>,
mod_overrides: HashMap<String, Vec<u8>>,
}
impl Default for AssetManager {
fn default() -> Self {
Self::new()
}
}
impl AssetManager {
pub fn new() -> Self {
Self {
base_assets: HashMap::new(),
mod_overrides: HashMap::new(),
}
}
pub fn add_asset(&mut self, path: &str, data: Vec<u8>) {
self.base_assets.insert(path.to_string(), data);
}
pub fn add_mod_override(&mut self, path: &str, data: Vec<u8>) {
self.mod_overrides.insert(path.to_string(), data);
}
pub fn open(&self, filename: &str) -> Option<AssetFile> {
// 1. Check user mod overrides first (non-destructive mod engine)
if let Some(data) = self.mod_overrides.get(filename) {
tracing::info!("AssetManager: redirected '{}' to active user mod", filename);
return Some(AssetFile::new(data.clone()));
}
// 2. Fallback to base asset
if let Some(data) = self.base_assets.get(filename) {
return Some(AssetFile::new(data.clone()));
}
tracing::warn!("AssetManager: asset '{}' not found", filename);
None
}
pub fn open_dir(&self, dir_name: &str) -> AssetDir {
let prefix = if dir_name.is_empty() || dir_name == "." {
"".to_string()
} else if !dir_name.ends_with('/') {
format!("{}/", dir_name)
} else {
dir_name.to_string()
};
let mut files = Vec::new();
for key in self.base_assets.keys().chain(self.mod_overrides.keys()) {
if key.starts_with(&prefix) {
let rest = &key[prefix.len()..];
if !rest.contains('/') {
files.push(rest.to_string());
}
}
}
files.sort();
files.dedup();
AssetDir::new(files)
}
}