Is it possible for an entity to be removed from a world without raising an event?
I have a reoccurring bug in my mod where essential entities seemingly disappear during or before on_configuration_changed without my mod detecting them and updating.
My mod has code that must be run when specific entities are at all removed from the world, or else the mod will crash later. What do I have to do to guarantee that that code gets run on removal. I would like to see the list of events I need to listen to, to double check I got them all, and I would like to know anything else I need to check for.
Entity removed without raising an event
-
- Inserter
- Posts: 29
- Joined: Mon Sep 13, 2021 6:53 pm
- Contact:
Re: Entity removed without raising an event
Yes. Any entities destroyed by script using LuaEntity::destroy won't raise any events by default, unless raise_destroy=true is passed in that function call. Players placing waterfill under an entity is one other common one that destroys entities without raising events (though it is now fortunately solvable). Another example is if a surface were to get deleted that has a bunch of entities. You won't get any of the "standard" removal events for those entities that got deleted along with it.
The "standard" entity-removal events that you want to listen to are on_entity_died, on_player_mined_entity, on_robot_mined_entity, and script_raised_destroy. In these four events, you'll have access to the entity right before it gets destroyed.mami wrote: ↑Tue Jan 03, 2023 9:07 pm My mod has code that must be run when specific entities are at all removed from the world, or else the mod will crash later. What do I have to do to guarantee that that code gets run on removal. I would like to see the list of events I need to listen to, to double check I got them all, and I would like to know anything else I need to check for.
There is one special event, on_entity_destroyed, that works a little differently. It fires within 1–2 ticks after entity removal so you won't get a valid entity as part of event data. Instead you'll get the registration_number and the entity's unit_number if it has one. In order for this event to fire for your entities, you have to have pre-registered them using register_on_entity_destroyed.
While that event might solve most of your issues, it's still not perfect because of the 1–2 ticks it might take for it to fire. Ultimately, there's no real substitute to verifying the validity of any LuaEntity you stored a reference to in global before trying to access it. Once you do come across an invalid entity there, you ought to have a way of skipping it and/or removing it from your data structures.
Re: Entity removed without raising an event
to clarify, is on_entity_destroyed guaranteed to fire after removal no matter what?
Re: Entity removed without raising an event
Also if I come across an invalid entity in global, is there a safe way to figure out what its unit_number was? A large part of why I can't use that solution, at least not easily and efficiently, is because I have some data structures that are indexed by the unit_number that need to be updated about the removed entity.
-
- Inserter
- Posts: 29
- Joined: Mon Sep 13, 2021 6:53 pm
- Contact:
Re: Entity removed without raising an event
Yes, it is guaranteed to fire no matter what made your entity stop existing. The caveat is that it could take 1–2 ticks before the event fires and you have to register each entity you want that event to be raised for. Note that you will also be getting events for entities that other mods have registered in the same way.
Not from an invalid entity, no. You'll want to set up your data structures in such a way that whenever you're iterating over any group of entities, you know exactly what saved data they map to. If you're iterating over entity references that are stored directly in a table, you'll usually want that table to be indexed by unit_number for that reason.mami wrote: ↑Wed Jan 04, 2023 4:02 am Also if I come across an invalid entity in global, is there a safe way to figure out what its unit_number was? A large part of why I can't use that solution, at least not easily and efficiently, is because I have some data structures that are indexed by the unit_number that need to be updated about the removed entity.