From d4427832f098a3197be40219830627dc50e1f5de Mon Sep 17 00:00:00 2001 From: Maxicarlos08 Date: Fri, 29 Sep 2023 22:33:24 +0200 Subject: [PATCH] Update rtsim vehicle position on unload --- server/src/lib.rs | 8 ++++---- server/src/rtsim/mod.rs | 19 ++++++++++++++++++- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/server/src/lib.rs b/server/src/lib.rs index ce54a4e997..477abcf774 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -861,7 +861,7 @@ impl Server { None => terrain.get_key_real(chunk_key).is_none(), } }) - .map(|(entity, _, _, _, _)| entity) + .map(|(entity, pos, _, _, _)| (entity, pos.0)) .collect::>() }; @@ -869,14 +869,14 @@ impl Server { let rtsim_vehicles = self.state.ecs().read_storage::(); // Assimilate entities that are part of the real-time world simulation - for entity in &to_delete { + for (entity, pos) in &to_delete { #[cfg(feature = "worldgen")] if let Some(rtsim_entity) = rtsim_entities.get(*entity) { rtsim.hook_rtsim_entity_unload(*rtsim_entity); } #[cfg(feature = "worldgen")] if let Some(rtsim_vehicle) = rtsim_vehicles.get(*entity) { - rtsim.hook_rtsim_vehicle_unload(*rtsim_vehicle); + rtsim.hook_rtsim_vehicle_unload(*rtsim_vehicle, *pos); } } } @@ -884,7 +884,7 @@ impl Server { drop(rtsim); // Actually perform entity deletion - for entity in to_delete { + for (entity, _) in to_delete { if let Err(e) = self.state.delete_entity_recorded(entity) { error!(?e, "Failed to delete agent outside the terrain"); } diff --git a/server/src/rtsim/mod.rs b/server/src/rtsim/mod.rs index d92dc95369..cf30cb1546 100644 --- a/server/src/rtsim/mod.rs +++ b/server/src/rtsim/mod.rs @@ -194,9 +194,26 @@ impl RtSim { .unwrap_or(true) } - pub fn hook_rtsim_vehicle_unload(&mut self, entity: RtSimVehicle) { + pub fn hook_rtsim_vehicle_unload(&mut self, entity: RtSimVehicle, pos: Vec3) { let data = self.state.get_data_mut(); if let Some(vehicle) = data.npcs.vehicles.get_mut(entity.0) { + // If we do not update the vehicle's position here the following bug will occur: + // -- tick start, rtsim system hasn't ran yet + // The server filters out any entities that have left the player's view + // distance, including this ship. These entities are then removed from the ECS, + // except for RtSim riders which are set to SimulationMode::Simulated (the + // rtsim system is responsible for cleaning this up). + // However when the RtSim system runs afterwards, it detects that the position + // of the *previous* tick is still in view distance! (positions for + // rtsim2 vehiclces are only updated for entities present in the + // ECS, but the ship was just removed). + // Now the ship is loaded again (in the same tick), and a new captain + // with it (note that the old one hasn't been despawned, just set to + // SimulationMode::Simulated wich is overwritten in the vehicle loading + // anyways). + // Result: The ship stays in loaded for one more tick and we now have 2 captains + // (one unmanaged by RtSim, having the default unloading behaviour) + vehicle.wpos = pos; vehicle.mode = SimulationMode::Simulated; if let Some(Actor::Npc(npc)) = vehicle.driver { if let Some(npc) = data.npcs.get_mut(npc) {