diff --git a/game/src/edit/mod.rs b/game/src/edit/mod.rs index 125fccaf89..ff40fd5151 100644 --- a/game/src/edit/mod.rs +++ b/game/src/edit/mod.rs @@ -447,57 +447,59 @@ impl LoadEdits { impl State for LoadEdits { fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Transition { match self.composite.event(ctx) { - Outcome::Clicked(x) => match x.as_ref() { - "close" => Transition::Pop, - "Start over with blank edits" => { - apply_map_edits(ctx, app, MapEdits::new()); - Transition::Pop - } - name => { - // TODO Kind of a hack. If it ends with .json, it's already a path. Otherwise - // it's a result from the menu. - let path = if name.ends_with(".json") { - name.to_string() - } else { - abstutil::path_edits(app.primary.map.get_name(), name) - }; - - match abstutil::maybe_read_json::( - path.clone(), - &mut Timer::throwaway(), - ) - .map_err(|err| err.to_string()) - .and_then(|perma| PermanentMapEdits::from_permanent(perma, &app.primary.map)) - .and_then(|edits| { - if self.mode.allows(&edits) { - Ok(edits) + Outcome::Clicked(x) => { + match x.as_ref() { + "close" => Transition::Pop, + "Start over with blank edits" => { + apply_map_edits(ctx, app, MapEdits::new()); + Transition::Pop + } + path => { + // TODO Kind of a hack. If it ends with .json, it's already a path. + // Otherwise it's a result from the menu. + let path = if path.ends_with(".json") { + path.to_string() } else { - Err( - "The current gameplay mode restricts edits. These edits have a \ - banned command." - .to_string(), - ) + abstutil::path_edits(app.primary.map.get_name(), path) + }; + + match MapEdits::load( + &app.primary.map, + path.clone(), + &mut Timer::throwaway(), + ) + .and_then(|edits| { + if self.mode.allows(&edits) { + Ok(edits) + } else { + Err( + "The current gameplay mode restricts edits. These edits have \ + a banned command." + .to_string(), + ) + } + }) { + Ok(edits) => { + apply_map_edits(ctx, app, edits); + Transition::Pop + } + // TODO Hack. Have to replace ourselves, because the Menu might be + // invalidated now that something was chosen. + Err(err) => Transition::Multi(vec![ + Transition::Replace(LoadEdits::new(ctx, app, self.mode.clone())), + // TODO Menu draws at a weird Z-order to deal with tooltips, so now + // the menu underneath bleeds + // through + Transition::Push(PopupMsg::new( + ctx, + "Error", + vec![format!("Can't load {}", path), err.clone()], + )), + ]), } - }) { - Ok(edits) => { - apply_map_edits(ctx, app, edits); - Transition::Pop - } - // TODO Hack. Have to replace ourselves, because the Menu might be - // invalidated now that something was chosen. - Err(err) => Transition::Multi(vec![ - Transition::Replace(LoadEdits::new(ctx, app, self.mode.clone())), - // TODO Menu draws at a weird Z-order to deal with tooltips, so now the - // menu underneath bleeds through - Transition::Push(PopupMsg::new( - ctx, - "Error", - vec![format!("Can't load {}", path), err.clone()], - )), - ]), } } - }, + } _ => Transition::Keep, } } diff --git a/game/src/game.rs b/game/src/game.rs index 00e803a679..8f85612667 100644 --- a/game/src/game.rs +++ b/game/src/game.rs @@ -52,8 +52,12 @@ impl Game { if let Some(edits_name) = start_with_edits { // TODO Maybe loading screen let mut timer = abstutil::Timer::new("apply initial edits"); - let edits = - map_model::MapEdits::load(&app.primary.map, &edits_name, &mut timer).unwrap(); + let edits = map_model::MapEdits::load( + &app.primary.map, + abstutil::path_edits(app.primary.map.get_name(), &edits_name), + &mut timer, + ) + .unwrap(); crate::edit::apply_map_edits(ctx, &mut app, edits); app.primary .map diff --git a/game/src/pregame.rs b/game/src/pregame.rs index 6bb303ae75..f1da51ba47 100644 --- a/game/src/pregame.rs +++ b/game/src/pregame.rs @@ -331,6 +331,9 @@ impl Proposals { let mut proposals = HashMap::new(); let mut buttons = Vec::new(); let mut current_tab = Vec::new(); + // If a proposal has fallen out of date, it'll be skipped with an error logged. Since these + // are under version control, much more likely to notice when they break (or we could add a + // step to data/regen.sh). for (name, edits) in abstutil::load_all_objects::(abstutil::path("system/proposals")) { diff --git a/map_model/src/edits/mod.rs b/map_model/src/edits/mod.rs index e073d4a6f6..a91b54c1f5 100644 --- a/map_model/src/edits/mod.rs +++ b/map_model/src/edits/mod.rs @@ -96,12 +96,10 @@ impl MapEdits { } } - pub fn load(map: &Map, edits_name: &str, timer: &mut Timer) -> Result { - if edits_name == "untitled edits" { - return Ok(MapEdits::new()); - } + pub fn load(map: &Map, path: String, timer: &mut Timer) -> Result { + // TODO If this fails, attempt to upgrade an older version of the edit format. PermanentMapEdits::from_permanent( - abstutil::read_json(abstutil::path_edits(map.get_name(), edits_name), timer), + abstutil::maybe_read_json(path, timer).map_err(|x| x.to_string())?, map, ) } diff --git a/sim/src/make/load.rs b/sim/src/make/load.rs index 89b8c4eddb..ad6517d33c 100644 --- a/sim/src/make/load.rs +++ b/sim/src/make/load.rs @@ -82,7 +82,15 @@ impl SimFlags { let mut map = Map::new(abstutil::path_map(&sim.map_name), timer); if sim.edits_name != "untitled edits" { - map.must_apply_edits(MapEdits::load(&map, &sim.edits_name, timer).unwrap(), timer); + map.must_apply_edits( + MapEdits::load( + &map, + abstutil::path_edits(map.get_name(), &sim.edits_name), + timer, + ) + .unwrap(), + timer, + ); map.recalculate_pathfinding_after_edits(timer); } sim.restore_paths(&map, timer);