FlyByDancing wrote: Tue Jan 03, 2023 4:18 am
Hello,
Not sure if this has been established in Factorio on this forum before. Was looking around, and found some things, but it didn't answer my question.
I have some local functions in the control.lua file. It takes a while to process when the function runs on large maps. Thinking about how to optimize.
1) Should I refactor the function to save the data (in chunks) to an array?
If there is even a slight chance that you'll have to cope with a huge amount of entities at once (e.g. if your mod deals with enemy units, trees, transport belts etc.), or if you must act on a smaller group of entities on every tick, you definitely should try to distribute the workload between several ticks. Just group your entities by whatever makes sense (e.g. by chunk position, unit_number, force, etc.).
2) if yes, does that array need to be global in order to pass it to do work in other ticks / ups of the game?
You should cache as much as possible. Calling game.surface.find_entities_filtered on every tick will slow down everything. Call it once in on_init or on_configuration_changed to initialize your list, then listen to on_built_entity, on_entity_cloned, script_raised_built, and script_raised_revive to add new entities to your lists, and to on_player_mined_entity, on_robot_mined_entity, on_entity_died, and script_raised_destroy to remove them.
By the way, it is not enough that you use global variables for your lists. Instead, you should store them in the global table of your mod (e.g. global.my_entities, global.chunks[x][y], …) so that the mod can be safely used in multiplayer games, without causing desyncs.
3) any additional pointers or examples?
Autodrive allows you to control vehicles automatically, with or without a player inside. Additional features (automatic reloading of vehicle fuel or weapons from the trunk, opening gates, shooting enemies etc.) are available when "sensors" are added to a vehicle's grid. When I add a vehicle to the list, I store a value tick_distributor = entity.unit_number % table_size(sensors) with its data.
In the on_tick event, I have something like this:
Code: Select all
local function tick_vehicle(state)
local tick = game.tick + state.tick_distributor
local cron_ammo = active_sensors.ammo and (tick % 180 == 0)
local cron_enemy = active_sensors.enemy and state.panic or (tick % 30 == 0)
local cron_follow = active_sensors.follow and (tick % 30 == 0)
…
if cron_ammo then … end
if cron_enemy then … end
if cron_follow then … end
end
script.on_event(defines.events.on_tick, function(event)
for v_id, v_data in global.vehicles do
tick_vehicle(v_data)
end
end)
The value state.tick_distributor ensures that tick will not be the same for every vehicle, so it creates as many vehicle groups as there are sensor prototypes (currently 9). The cron_* values are for finetuning -- I don't want to check all sensors each time the code is run for a given vehicle, so I only run the code if the vehicle actually has that sensor in its grid. Also, I run the more important functions on every 30th tick, and things that are less crucial only once per 60, 120, or 180 ticks.