[2.0.76] calling create_entity with fast_replace = true

Bugs that are actually features.
User avatar
hgschmie
Fast Inserter
Fast Inserter
Posts: 214
Joined: Tue Feb 06, 2024 5:18 am
Contact:

[2.0.76] calling create_entity with fast_replace = true

Post by hgschmie »

(Followup to my own post)

After having some discussions with @_CodeGreen, I believe that the current behavior of create_entity when fast replacing an entity is a bug. There are valid reasons to not use apply_upgrade() to upgrade an entity but use create_entity with fast replace and in that case, the game fires different events:

- when using apply_upgrade():

- script_raised_destroy for old entity
- script_raised_built for new entity
- on_object_destroyed for old entity

- when using create_entity with fast_replace = true

- script_raised_built for new entity
- on_object_destroyed for old entity

but no "script_raised_destroyed" for the old entity that was fast replaced.


hgschmie wrote: Wed May 06, 2026 4:12 am I have a mod (https://mods.factorio.com/mod/miniloader-redux) where each entity relies on creation/deletion events to maintain internal state. This works fine in the regular game.

I register on_built_entity, on_robot_built_entity, on_space_platform_built_entity, script_raised_built, script_raised_revive as creation events. Each does the same: create an instance of my mod entity around the entity in the event.
I register on_player_mined_entity, on_robot_mined_entity, on_space_platform_mined_entity, script_raised_destroy as deletion events. Same here: If that entity gets destroyed, take the mod entity and its internal pieces down.

In addition, I also register the entity with script.register_on_object_destroyed() and catch the on_object_destroyed event.

In the normal game, when a user uses the upgrade planner, I receive:

- on_robot_mined_entity event for the old entity
- on_robot_built_entity event for the new entity
- on_object_destroyed for the old entity

If a player uses fast replacement (pasting a new entity over the old one), I receive:

- on_player_mined_entity for the old entity
- on_built_entity for the new entity
- on_object_destroyed for the old entity

Now, there is a mod (Blueprint Sandboxes, https://mods.factorio.com/mod/blueprint-sandboxes), which seems to be pretty popular. It creates a magic surface where entities can be built (for interesting values of "built"; It seems that it actually places ghosts which then get revived). If an entity on this surface is either fast-replaced or the upgrade planner is used, it does this:

Code: Select all

-- here entity is valid and should be upgraded
        local targetEntity, targetQuality = entity.get_upgrade_target()

        local options = {
            name = targetEntity.name,
            position = entity.position,
            direction = entity.direction,
            quality = targetQuality,
            force = entity.force,
            fast_replace = true,
            spill = false,
            raise_built = true,
        }

        local result = entity.surface.create_entity(options)
In that case, I receive

- script_raised_built for the new entity
- on_object_destroyed for the old entity

Most importantly I do not receive any destroy event. As fast replacing (same as upgrading) in all other scenarios sends a mined_entity event before sending a built_entity event, I would have expected that in this scenario (raise_built = true and fast_replace = true), the engine would e.g. send out script_raised_destroy. Right now, the creation of the "upgraded" or "fast replaced" entity fails for me because the internal entities can not be created on top of each other.

So I guess, this is 50% asking for clarification, 50% bug report. I believe the engine *should* raise script_raised_destroy IFF create_entity is called with raise_built and fast_replace both being true *and* it is actually fast-replacing an entity (same position and surface and fast-replaceable). Otherwise, custom entities (such as mine) get confused because the "regular" 'destroy old, create new' event sequence does not happen.
Rseding91
Factorio Staff
Factorio Staff
Posts: 17169
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: [2.0.76] calling create_entity with fast_replace = true

Post by Rseding91 »

Thanks for the report. These two functions are two different code paths and as such there's no reason they can't fire different events.
If you want to get ahold of me I'm almost always on Discord.
User avatar
hgschmie
Fast Inserter
Fast Inserter
Posts: 214
Joined: Tue Feb 06, 2024 5:18 am
Contact:

Re: [2.0.76] calling create_entity with fast_replace = true

Post by hgschmie »

Hi,

Thanks for the response. I assumed that these are two code paths. However, from a mod author PoV, these are “replace one entity with another” operations that look different.

Would it be possible to add that additional event or is that a major change? Because it would make life for a lot of mods so much simpler if there were not a single code path where it is impossible to get a destroy event.

Thanks for considering.
Rseding91
Factorio Staff
Factorio Staff
Posts: 17169
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: [2.0.76] calling create_entity with fast_replace = true

Post by Rseding91 »

on_object_destroyed exists for these exact scenarios.
If you want to get ahold of me I'm almost always on Discord.
User avatar
hgschmie
Fast Inserter
Fast Inserter
Posts: 214
Joined: Tue Feb 06, 2024 5:18 am
Contact:

Re: [2.0.76] calling create_entity with fast_replace = true

Post by hgschmie »

I understand that but it requires cooperation from the mod to register the entity and the events are fired in the wrong order.

apply_update fires the destroy event first, then the create event. When using on_object_destroyed, it fires the create event first, then on_object_destroyed. Without the destroy event first, the create event tries to create internal entities which collides with the entities that would have been deleted by receiving the destroy event first.

Really, if we could get the raised_script_destroyed for the old entity before the raised_script_created (which is what apply_update does), this would remove a ton of complexity in managing fast-replace updates.
Post Reply

Return to “Not a bug”