diff --git a/src/game/object.rs b/src/game/object.rs index 51fcd59..da7a2c5 100644 --- a/src/game/object.rs +++ b/src/game/object.rs @@ -822,6 +822,11 @@ impl Object { } } +pub struct ObjectGraph { + pub root: Handle, + pub objects: SecondaryMap, +} + pub struct Objects { tile_grid: TileGrid, frm_db: Rc, @@ -1046,7 +1051,35 @@ impl Objects { r } + pub fn insert_graph(&mut self, graph: ObjectGraph) -> Handle { + let mut handle_map = SecondaryMap::new(); + + for (h, o) in graph.objects { + let o = self.insert(o); + assert!(handle_map.insert(h, o).is_none()); + } + + let root = handle_map[graph.root]; + self.fix_handles(root, &|h| handle_map[h]); + + root + } + + fn fix_handles(&self, obj: Handle, map: &impl Fn(Handle) -> Handle) { + let mut obj = self.get_mut(obj); + for item in &mut obj.inventory.items { + item.object = map(item.object); + self.fix_handles(item.object, map); + } + } + pub fn remove(&mut self, obj: Handle) -> Object { + let r = self.remove0(obj); + assert!(r.inventory.items.is_empty(), "use remove_deep()"); + r + } + + fn remove0(&mut self, obj: Handle) -> Object { if self.dude == Some(obj) { self.dude = None; } @@ -1058,6 +1091,23 @@ impl Objects { r } + pub fn remove_deep(&mut self, root: Handle) -> ObjectGraph { + let mut objects = SecondaryMap::new(); + self.remove_deep0(root, &mut objects); + ObjectGraph { + root, + objects, + } + } + + fn remove_deep0(&mut self, objh: Handle, objs: &mut SecondaryMap) { + let obj = self.remove0(objh); + for item in &obj.inventory.items { + self.remove_deep0(item.object, objs); + } + assert!(objs.insert(objh, obj).is_none()); + } + pub fn at(&self, pos: EPoint) -> &Vec { self.by_pos[pos.elevation as usize] .get(pos.point.x as usize, pos.point.y as usize) diff --git a/src/game/state.rs b/src/game/state.rs index de81dd9..75a24b9 100644 --- a/src/game/state.rs +++ b/src/game/state.rs @@ -228,8 +228,7 @@ impl GameState { let mut dude_obj = { let mut world = self.world.borrow_mut(); let dude_obj = world.objects().dude(); - let mut dude_obj = world.objects_mut().remove(dude_obj); - dude_obj.inventory.items.clear(); + let dude_obj = world.objects_mut().remove_deep(dude_obj); world.clear(); dude_obj }; @@ -282,13 +281,16 @@ impl GameState { world.set_sqr_tiles(map.sqr_tiles); - dude_obj.direction = map.entrance_direction; - dude_obj.set_light_emitter(LightEmitter { - intensity: 0x10000, - radius: 4, - }); - dude_obj.set_pos(Some(map.entrance)); - let dude_obj = world.objects_mut().insert(dude_obj); + { + let mut dude_obj = dude_obj.objects.get_mut(dude_obj.root).unwrap(); + dude_obj.direction = map.entrance_direction; + dude_obj.set_light_emitter(LightEmitter { + intensity: 0x10000, + radius: 4, + }); + dude_obj.set_pos(Some(map.entrance)); + } + let dude_obj = world.objects_mut().insert_graph(dude_obj); world.objects_mut().make_standing(dude_obj);