Efficiency and Chunking of mod data

Place to get help with not working mods / modding interface.
FlyByDancing
Manual Inserter
Manual Inserter
Posts: 1
Joined: Tue Jan 03, 2023 4:11 am
Contact:

Efficiency and Chunking of mod data

Post by FlyByDancing »

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?

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?

3) any additional pointers or examples?
Pi-C
Smart Inserter
Smart Inserter
Posts: 1758
Joined: Sun Oct 14, 2018 8:13 am
Contact:

Re: Efficiency and Chunking of mod data

Post by Pi-C »

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.
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!
Post Reply

Return to “Modding help”