Update rtsim vehicle position on unload

This commit is contained in:
Maxicarlos08 2023-09-29 22:33:24 +02:00
parent 91a7cf796d
commit d4427832f0
No known key found for this signature in database
2 changed files with 22 additions and 5 deletions

View File

@ -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::<Vec<_>>()
};
@ -869,14 +869,14 @@ impl Server {
let rtsim_vehicles = self.state.ecs().read_storage::<RtSimVehicle>();
// 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");
}

View File

@ -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<f32>) {
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) {