Page 1 of 1

clone_entities

Posted: Tue Nov 13, 2018 11:42 pm
by Boodals
I want to clone a bunch of entities. They are typically grouped together, but not necessarily in an area that clone_area would work well on (as there may be many entities that I do not want to clone in the same area). The conditions on whether or not to clone a specific entity is complex, and so should be done on the lua side. I do not want to clone entities individually, as that would be many, many API calls, and I would have to make sure to clone entities in a specific order (which is already done in clone_area) (eg clone rails before cloning trains).

Code: Select all

surface.clone_entities(
{
	entities (array of Entity to clone)
	destination_offset (Vector, how far to move the entities)
	destination_surface (SurfaceSpecification, optional, defaults to the same surface)
})
If an entity on a different surface is given, just treat it like it's on the same surface, it shouldn't matter. Or if that can't be done for whatever reason, just throw an error or don't clone it.
It should return an array of Entity with the same indexes as the array that was passed into the function, with nils (or maybe false so that the # operator works?) where entities could not be cloned.
on_entity_cloned should be raised for each entity that was cloned.

Additionally, parameters similar to find_entities_filtered could be added to find the entities/tiles, which would essentially combine surface.clone_multiple({ entities = surface.find_entities_filtered({ ... }), ... }) into a single API call. However the overhead of cloning a bunch of entities is going to far outweigh the additional API call so it really isn't necessary.

ps: thx 4 on_entity_cloned

Re: clone_entities

Posted: Wed Nov 14, 2018 11:41 am
by Rseding91
Boodals wrote: Tue Nov 13, 2018 11:42 pm It should return an array of Entity with the same indexes as the array that was passed into the function, with nils (or maybe false so that the # operator works?) where entities could not be cloned.
Is that useful at all if the on_entity_cloned event is fired with the cloned-from and cloned-to entities? It has non-trivial overhead to return that much data into the Lua state if nobody is going to ever read it.

Re: clone_entities

Posted: Thu Nov 15, 2018 5:47 pm
by Boodals
I've gone back and forth on my answer, and i'm still debating it, but I think it should be fairly easy to just use on_entity_cloned.
I could do something like this:

Code: Select all

local isCloning = false
local function doClone(surface, entities, offset)
    isCloning = true
    surface.clone_entities({entities = entities, destination_offset = offset})
    isCloning = false
end
script.on_event(defines.events.on_entity_cloned, function(event)
    if isCloning then
        doExtraStuff()
    end
end)

I guess my answer is; if the overhead of returning the data is significant compared to the overhead of actually cloning the entities, then dont bother. A lot of times it won't be needed. When it is needed, we can work around it (especially if on_entity_cloned is called in the same order as the entities array passed in, but I doubt it would be considering the cloning order).

However a better solution would be to have an additional optional parameter, which is the array to populate the entities with. If it is nil, then don't pass the data to lua, otherwise insert the cloned entities into the table.

Re: clone_entities

Posted: Thu Nov 15, 2018 6:35 pm
by Rseding91
The order of entity cloning is based off the order they *have* to be cloned and then the order that they where given.

So, rails always come before any rolling stock entity.

Re: clone_entities

Posted: Thu Nov 15, 2018 9:24 pm
by Boodals
I was thinking maybe you could do something like this to build the array of cloned entities in the same order.

Code: Select all

local sourceEntities
local clonedEntities
local function doClone(surface, entities, offset)
    sourceEntities = entities
    clonedEntities = { }
    surface.clone_entities({ entities = entities, destination_offset = offset })
end
script.on_event(defines.events.on_entity_cloned, function(event)
    local index = #clonedEntities + 1
    assert(sourceEntities[index] == event.source) --This will fail because the order entities are cloned in isn't always the order they are passed in as
    clonedEntities[index] = event.destination
end)
But yeah that wouldn't work.

Will the idea for the optional parameter to get the cloned entities array work?

Edit: Oh hey its in the implemented forum. yay!

Re: clone_entities

Posted: Fri Nov 16, 2018 2:05 am
by Rseding91
Boodals wrote: Thu Nov 15, 2018 9:24 pm Will the idea for the optional parameter to get the cloned entities array work?
No, the event includes both the source entity and the cloned result so I don't see why you would ever need to know what position it was in the original array of entities cloned.