From 59ac1f55c35f9d490c903d3909e0bb100f3dde6d Mon Sep 17 00:00:00 2001 From: Ethan O'Brien Date: Fri, 24 Jul 2026 21:16:21 -0500 Subject: [PATCH] Remove mod flag --- src/main.rs | 1 - src/options.rs | 5 +-- src/router/asset_lists.rs | 64 +++------------------------------------ src/runtime.rs | 37 ---------------------- 4 files changed, 6 insertions(+), 101 deletions(-) diff --git a/src/main.rs b/src/main.rs index da47952..cf3fd56 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,6 @@ fn main() -> std::io::Result<()> { let args = ew::get_args(); ew::runtime::update_data_path(&args.path); ew::runtime::update_masterdata_path(&args.masterdata); - ew::runtime::update_mod_paths(&args.mods); ew::run_server(false) } diff --git a/src/options.rs b/src/options.rs index 33fd3f8..d3dfd48 100644 --- a/src/options.rs +++ b/src/options.rs @@ -72,10 +72,7 @@ pub struct Args { pub image_asset_path: String, #[arg(long, default_value = "", help = "Optional directory to load asset lists and master data CSVs from at runtime. Layout mirrors the bundled assets (asset_lists/, csv/, csv-en/). Missing files fall back to the internal copies.")] - pub masterdata: String, - - #[arg(long = "mod", value_name = "DIR", action = clap::ArgAction::Append, help = "Path to a mod directory layered on top of --masterdata + the bundled defaults. May be passed multiple times. Each mod dir mirrors the masterdata layout (asset_lists/, csv/, csv-en/, userdata/) but only needs to include the files it adds rows to. CSV rows merge by primary key (first column), asset_lists entries merge by m_identifier, new_user.json top-level arrays union. Later --mod wins on collisions.")] - pub mods: Vec + pub masterdata: String } pub fn get_args() -> Args { diff --git a/src/router/asset_lists.rs b/src/router/asset_lists.rs index 501a68c..d07d4e7 100644 --- a/src/router/asset_lists.rs +++ b/src/router/asset_lists.rs @@ -7,7 +7,7 @@ use std::sync::Mutex; use crate::include_file; lazy_static! { - static ref MERGED_CACHE: Mutex> = Mutex::new(HashMap::new()); + static ref LIST_CACHE: Mutex> = Mutex::new(HashMap::new()); } pub fn routes(cfg: &mut web::ServiceConfig) { @@ -32,11 +32,11 @@ async fn get(_req: HttpRequest) -> impl Responder { } fn load_list(name: &str) -> String { - if let Some(cached) = MERGED_CACHE.lock().unwrap().get(name) { + if let Some(cached) = LIST_CACHE.lock().unwrap().get(name) { return cached.clone(); } let rel = format!("asset_lists/{}.json", name); - let base = crate::runtime::read_masterdata_file(&rel) + let list = crate::runtime::read_masterdata_file(&rel) .and_then(|b| String::from_utf8(b).ok()) .unwrap_or_else(|| match name { "Bundle" => include_file!("src/router/asset_lists/Bundle.json"), @@ -45,62 +45,8 @@ fn load_list(name: &str) -> String { _ => unreachable!(), }); - let mod_files = crate::runtime::read_mod_files(&rel); - let merged = if mod_files.is_empty() { - base - } else { - merge_asset_list(name, base, mod_files) - }; - MERGED_CACHE.lock().unwrap().insert(name.to_string(), merged.clone()); - merged -} - -fn merge_asset_list(name: &str, base: String, mod_files: Vec<(String, Vec)>) -> String { - let mut root = match jzon::parse(&base) { - Ok(v) => v, - Err(_) => return base, - }; - - let mut by_ident: HashMap = HashMap::new(); - if let jzon::JsonValue::Array(ref arr) = root["m_manifestCollection"] { - for (i, e) in arr.iter().enumerate() { - let id = e["m_identifier"].to_string(); - by_ident.insert(id.to_string(), i); - } - } - - for (mod_dir, bytes) in mod_files { - let Ok(s) = String::from_utf8(bytes) else { continue }; - let Ok(mod_root) = jzon::parse(&s) else { continue }; - let mod_entries = match mod_root["m_manifestCollection"] { - jzon::JsonValue::Array(ref arr) => arr.clone(), - _ => continue, - }; - let mut added = 0usize; - let mut replaced = 0usize; - for entry in mod_entries { - let ident = entry["m_identifier"].as_str().unwrap_or("").to_string(); - if ident.is_empty() { - continue; - } - if let Some(&idx) = by_ident.get(&ident) { - root["m_manifestCollection"][idx] = entry; - replaced += 1; - } else { - let idx = root["m_manifestCollection"].len(); - let _ = root["m_manifestCollection"].push(entry); - by_ident.insert(ident, idx); - added += 1; - } - } - if added > 0 || replaced > 0 { - println!( - "[mod {}] {}.json: +{} new entries, {} replaced", - mod_dir, name, added, replaced - ); - } - } - jzon::stringify(root) + LIST_CACHE.lock().unwrap().insert(name.to_string(), list.clone()); + list } async fn supported() -> impl Responder { diff --git a/src/runtime.rs b/src/runtime.rs index 9c1df6e..6f56d0a 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -9,7 +9,6 @@ lazy_static! { static ref DATAPATH: RwLock = RwLock::new(String::new()); static ref MASTERDATA_PATH: RwLock = RwLock::new(String::new()); static ref MASTERDATA_WARNED: Mutex> = Mutex::new(HashSet::new()); - static ref MOD_PATHS: RwLock> = RwLock::new(Vec::new()); static ref EASTER: RwLock = RwLock::new(false); static ref HOST_CONFIG: RwLock = RwLock::new(HostConfig::default()); } @@ -100,42 +99,6 @@ pub fn get_easter_mode() -> bool { *EASTER.read().unwrap() } -pub fn update_mod_paths(paths: &[String]) { - let cleaned: Vec = paths.iter() - .map(|p| p.trim_end_matches('/').to_string()) - .filter(|p| !p.is_empty()) - .filter_map(|p| { - if Path::new(&p).is_dir() { - Some(p) - } else { - println!("Couldn't find mod directory {} — skipping", p); - None - } - }) - .collect(); - if !cleaned.is_empty() { - println!("Loaded {} mod overlay{}", cleaned.len(), - if cleaned.len() == 1 { "" } else { "s" }); - for p in &cleaned { - println!(" mod: {}", p); - } - } - let mut w = MOD_PATHS.write().unwrap(); - *w = cleaned; -} - -pub fn read_mod_files(rel_path: &str) -> Vec<(String, Vec)> { - let paths = MOD_PATHS.read().unwrap().clone(); - let mut out = Vec::new(); - for p in paths { - let full = format!("{}/{}", p, rel_path); - if let Ok(bytes) = fs::read(&full) { - out.push((p, bytes)); - } - } - out -} - pub fn apply_config_json(json: &str) { let parsed = match jzon::parse(json) { Ok(p) => p,