From d4427832f098a3197be40219830627dc50e1f5de Mon Sep 17 00:00:00 2001 From: Maxicarlos08 Date: Fri, 29 Sep 2023 22:33:24 +0200 Subject: [PATCH 1/2] 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) { From 99d95ad10526d7b90da34f6b3957ad1045b17d94 Mon Sep 17 00:00:00 2001 From: Maxicarlos08 Date: Sat, 30 Sep 2023 14:11:05 +0200 Subject: [PATCH 2/2] add physics system dependency to RtSim This previously caused a bug where the position of rtsim vehicles was one tick behind causing airships to be loaded once more when being unloaded after leaving the view distance of a player. For more context view the comment removed in the previous commit. --- server/src/lib.rs | 8 ++++---- server/src/rtsim/mod.rs | 23 +++-------------------- 2 files changed, 7 insertions(+), 24 deletions(-) diff --git a/server/src/lib.rs b/server/src/lib.rs index 477abcf774..ce54a4e997 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, pos, _, _, _)| (entity, pos.0)) + .map(|(entity, _, _, _, _)| entity) .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, pos) in &to_delete { + for entity 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, *pos); + rtsim.hook_rtsim_vehicle_unload(*rtsim_vehicle); } } } @@ -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 cf30cb1546..834c72ed15 100644 --- a/server/src/rtsim/mod.rs +++ b/server/src/rtsim/mod.rs @@ -8,7 +8,7 @@ use common::{ mounting::VolumePos, rtsim::{Actor, ChunkResource, RtSimEntity, RtSimVehicle, VehicleId, WorldSettings}, }; -use common_ecs::dispatch; +use common_ecs::{dispatch, System}; use common_state::BlockDiff; use crossbeam_channel::{unbounded, Receiver, Sender}; use enum_map::EnumMap; @@ -194,26 +194,9 @@ impl RtSim { .unwrap_or(true) } - pub fn hook_rtsim_vehicle_unload(&mut self, entity: RtSimVehicle, pos: Vec3) { + pub fn hook_rtsim_vehicle_unload(&mut self, entity: RtSimVehicle) { 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) { @@ -311,5 +294,5 @@ pub struct LoadedChunkState { } pub fn add_server_systems(dispatch_builder: &mut DispatcherBuilder) { - dispatch::(dispatch_builder, &[]); + dispatch::(dispatch_builder, &[&common_systems::phys::Sys::sys_name()]); }