aboutsummaryrefslogtreecommitdiff
path: root/azalea-entity/src/plugin
diff options
context:
space:
mode:
authormat <git@matdoes.dev>2025-03-13 20:13:58 +0000
committermat <git@matdoes.dev>2025-03-13 20:13:58 +0000
commit7a192acc99358818c2f90cf4e2b8b236f91cfbf7 (patch)
treecf632093809a4e06eaf651399c365c137fb6cdd8 /azalea-entity/src/plugin
parente9a5df2e875fe845e098781a0bde4b6d8c0786f1 (diff)
downloadazalea-drasl-7a192acc99358818c2f90cf4e2b8b236f91cfbf7.tar.xz
properly remove from the EntityIdIndex component on despawn
Diffstat (limited to 'azalea-entity/src/plugin')
-rw-r--r--azalea-entity/src/plugin/indexing.rs57
1 files changed, 43 insertions, 14 deletions
diff --git a/azalea-entity/src/plugin/indexing.rs b/azalea-entity/src/plugin/indexing.rs
index fefecb06..4e0902e7 100644
--- a/azalea-entity/src/plugin/indexing.rs
+++ b/azalea-entity/src/plugin/indexing.rs
@@ -23,19 +23,6 @@ pub struct EntityUuidIndex {
/// An index of entities by their UUIDs
entity_by_uuid: HashMap<Uuid, Entity>,
}
-
-/// An index of Minecraft entity IDs to Azalea ECS entities. This is a
-/// `Component` so local players can keep track of entity IDs independently from
-/// the instance.
-///
-/// If you need a per-instance instead of per-client version of this, you can
-/// use [`Instance::entity_by_id`].
-#[derive(Component, Default)]
-pub struct EntityIdIndex {
- /// An index of entities by their MinecraftEntityId
- entity_by_id: IntMap<MinecraftEntityId, Entity>,
-}
-
impl EntityUuidIndex {
pub fn new() -> Self {
Self {
@@ -60,6 +47,19 @@ impl EntityUuidIndex {
}
}
+/// An index of Minecraft entity IDs to Azalea ECS entities. This is a
+/// `Component` so local players can keep track of entity IDs independently from
+/// the instance.
+///
+/// If you need a per-instance instead of per-client version of this, you can
+/// use [`Instance::entity_by_id`].
+#[derive(Component, Default)]
+pub struct EntityIdIndex {
+ /// An index of entities by their MinecraftEntityId
+ entity_by_id: IntMap<MinecraftEntityId, Entity>,
+ id_by_entity: HashMap<Entity, MinecraftEntityId>,
+}
+
impl EntityIdIndex {
pub fn get(&self, id: MinecraftEntityId) -> Option<Entity> {
self.entity_by_id.get(&id).copied()
@@ -68,13 +68,31 @@ impl EntityIdIndex {
pub fn contains_key(&self, id: MinecraftEntityId) -> bool {
self.entity_by_id.contains_key(&id)
}
+ pub fn contains_ecs_entity(&self, id: Entity) -> bool {
+ self.id_by_entity.contains_key(&id)
+ }
pub fn insert(&mut self, id: MinecraftEntityId, entity: Entity) {
self.entity_by_id.insert(id, entity);
+ self.id_by_entity.insert(entity, id);
}
pub fn remove(&mut self, id: MinecraftEntityId) -> Option<Entity> {
- self.entity_by_id.remove(&id)
+ if let Some(entity) = self.entity_by_id.remove(&id) {
+ self.id_by_entity.remove(&entity);
+ Some(entity)
+ } else {
+ None
+ }
+ }
+
+ pub fn remove_by_ecs_entity(&mut self, entity: Entity) -> Option<MinecraftEntityId> {
+ if let Some(id) = self.id_by_entity.remove(&entity) {
+ self.entity_by_id.remove(&id);
+ Some(id)
+ } else {
+ None
+ }
}
}
@@ -154,6 +172,7 @@ pub fn remove_despawned_entities_from_indexes(
),
(Changed<LoadedBy>, Without<LocalEntity>),
>,
+ mut entity_id_index_query: Query<&mut EntityIdIndex>,
) {
for (entity, uuid, minecraft_id, position, instance_name, loaded_by) in &query {
let Some(instance_lock) = instance_container.get(instance_name) else {
@@ -207,6 +226,16 @@ pub fn remove_despawned_entities_from_indexes(
if instance.entity_by_id.remove(minecraft_id).is_none() {
warn!("Tried to remove entity {entity:?} from the id index but it was not there.");
}
+
+ // remove it from every client's EntityIdIndex
+ for mut entity_id_index in entity_id_index_query.iter_mut() {
+ if entity_id_index.remove_by_ecs_entity(entity).is_none() {
+ debug!(
+ "Tried to remove entity {entity:?} from the id index but it was not there. This may be expected if you're in a shared instance."
+ );
+ }
+ }
+
// and now remove the entity from the ecs
commands.entity(entity).despawn();
debug!("Despawned entity {entity:?} because it was not loaded by anything.");