despawn with volume mount

This commit is contained in:
Isse 2023-11-15 11:57:52 +01:00
parent 7856aac713
commit e0e7fe499d
2 changed files with 38 additions and 38 deletions

View File

@ -72,6 +72,8 @@ use common::{
cmd::ServerChatCommand,
comp,
event::{EventBus, ServerEvent},
link::Is,
mounting::{Volume, VolumeRider},
region::RegionMap,
resources::{BattleMode, GameMode, Time, TimeOfDay},
rtsim::RtSimEntity,
@ -844,7 +846,6 @@ impl Server {
self.state.delete_component::<Anchor>(entity);
}
let mut rtsim = self.state.ecs().write_resource::<rtsim::RtSim>();
// Remove NPCs that are outside the view distances of all players
// This is done by removing NPCs in unloaded chunks
let to_delete = {
@ -854,12 +855,28 @@ impl Server {
&self.state.ecs().read_storage::<comp::Pos>(),
!&self.state.ecs().read_storage::<comp::Presence>(),
self.state.ecs().read_storage::<Anchor>().maybe(),
self.state.ecs().read_storage::<RtSimEntity>().maybe(),
self.state.ecs().read_storage::<Is<VolumeRider>>().maybe(),
)
.join()
.filter(|(_, pos, _, anchor, rtsim_entity)| {
let chunk_key = terrain.pos_key(pos.0.map(|e| e.floor() as i32));
let unload = match anchor {
.filter(|(_, pos, _, anchor, is_volume_rider)| {
let pos = is_volume_rider
.and_then(|is_volume_rider| match is_volume_rider.pos.kind {
Volume::Terrain => None,
Volume::Entity(e) => {
let e = self.state.ecs().entity_from_uid(e)?;
let pos = self
.state
.ecs()
.read_storage::<comp::Pos>()
.get(e)
.copied()?;
Some(pos.0)
},
})
.unwrap_or(pos.0);
let chunk_key = terrain.pos_key(pos.map(|e| e.floor() as i32));
match anchor {
Some(Anchor::Chunk(hc)) => {
// Check if both this chunk and the NPCs `home_chunk` is unloaded. If
// so, we delete them. We check for
@ -870,28 +887,22 @@ impl Server {
},
Some(Anchor::Entity(entity)) => !self.state.ecs().is_alive(*entity),
None => terrain.get_key_real(chunk_key).is_none(),
};
if unload {
// For rtsim entities we only want to unload if assimilation succeeds
if let Some(rtsim_entity) = rtsim_entity {
#[cfg(feature = "worldgen")]
let res = rtsim.hook_rtsim_entity_unload(**rtsim_entity);
#[cfg(not(feature = "worldgen"))]
let res = true;
res
} else {
true
}
} else {
false
}
})
.map(|(entity, _, _, _, _)| entity)
.collect::<Vec<_>>()
};
drop(rtsim);
#[cfg(feature = "worldgen")]
{
let mut rtsim = self.state.ecs().write_resource::<rtsim::RtSim>();
let rtsim_entities = self.state.ecs().read_storage();
for entity in &to_delete {
if let Some(rtsim_entity) = rtsim_entities.get(*entity) {
rtsim.hook_rtsim_entity_unload(*rtsim_entity);
}
}
}
// Actually perform entity deletion
for entity in to_delete {

View File

@ -176,26 +176,15 @@ impl RtSim {
.emit(event::OnBlockChange { changes }, world, index);
}
pub fn hook_rtsim_entity_unload(&mut self, entity: RtSimEntity) -> bool {
pub fn hook_rtsim_entity_unload(&mut self, entity: RtSimEntity) {
let data = self.state.get_data_mut();
if data.npcs.mounts.get_mount_link(entity.0).is_none() {
if let Some(npc) = data.npcs.get_mut(entity.0) {
if matches!(npc.mode, SimulationMode::Simulated) {
error!("Unloaded already unloaded entity");
}
npc.mode = SimulationMode::Simulated;
}
if let Some(steerer) = data.npcs.mounts.get_steerer_link(entity.0) && let Actor::Npc(npc) = steerer.rider
&& let Some(npc) = data.npcs.get_mut(npc) {
if matches!(npc.mode, SimulationMode::Simulated) {
error!("Unloaded already unloaded steerer entity");
}
npc.mode = SimulationMode::Simulated;
}
true
} else {
false
}
}
pub fn hook_rtsim_actor_death(