Hooking a non-logistic entity up to the logistics network
Hooking a non-logistic entity up to the logistics network
Lets say you have a regular burner furnace entity. How would one go about adding that to the logistics network as a requester, then having it always request 10 coal that would go into it's fuel and have the player be unable to modify this request.
Thanks in advance
Thanks in advance
Re: Hooking a non-logistic entity up to the logistics network
Code: Select all
/c
request_fuel = function(entity)
if not entity or entity.type ~= "furnace" then return end
local item = "coal"
local add_more = true
for fuel,amount in pairs(entity.get_inventory(defines.inventory.fuel).get_contents()) do
if amount < 10 then
item = fuel
else
add_more = false
end
end
if add_more and entity.surface.count_entities_filtered{name="item-request-proxy", force=entity.force, area=entity.bounding_box} == 0 then
entity.surface.create_entity{name="item-request-proxy", target=entity, force=entity.force, position=entity.position, modules={{item=item, count=10}}}
end
end
request_fuel(game.player.selected)
Re: Hooking a non-logistic entity up to the logistics network
Thanks for the answerDaveMcW wrote:This adds a temporary request for a single furnace. You need to add more logic to always update every furnace on the map.Code: Select all
/c request_fuel = function(entity) if not entity or entity.type ~= "furnace" then return end local item = "coal" local add_more = true for fuel,amount in pairs(entity.get_inventory(defines.inventory.fuel).get_contents()) do if amount < 10 then item = fuel else add_more = false end end if add_more and entity.surface.count_entities_filtered{name="item-request-proxy", force=entity.force, area=entity.bounding_box} == 0 then entity.surface.create_entity{name="item-request-proxy", target=entity, force=entity.force, position=entity.position, modules={{item=item, count=10}}} end end request_fuel(game.player.selected)
So if I understand this correctly this creates a ghost entity that requires 10 coal to be constructed? then that coal is transferred into the furnace in question.
Also is there any way to use logistic bots instead of construction?
Re: Hooking a non-logistic entity up to the logistics network
Not easily. The only way is to create a hidden logistic entity that requests coal (see defines.events.on_built_entity), then code to transfer it to your furnace.Alex99 wrote:Also is there any way to use logistic bots instead of construction?
Re: Hooking a non-logistic entity up to the logistics network
OK I think I can do that, is there an event that I could use that isn't on_tick as that would be pretty bad for ups?DaveMcW wrote:Not easily. The only way is to create a hidden logistic entity that requests coal (see defines.events.on_built_entity), then code to transfer it to your furnace.
- bobingabout
- Smart Inserter
- Posts: 7352
- Joined: Fri May 09, 2014 1:01 pm
- Contact:
Re: Hooking a non-logistic entity up to the logistics network
No, something that is constantly updated must be on the on_tick event. This is one reason why I personally do not include features of this nature in my mods.
There are however some guides around on how to attempt to offset the UPS disruption, such as only checking each chest for requests once a minute, but iterate through this list so that something is checked every tick.
something like
There are however some guides around on how to attempt to offset the UPS disruption, such as only checking each chest for requests once a minute, but iterate through this list so that something is checked every tick.
something like
Code: Select all
for i, entity in pairs(list) do
if game.tick % 3600 == i % 3600 do
Re: Hooking a non-logistic entity up to the logistics network
modulo is expensive in to run twice for every entity every tick.bobingabout wrote:No, something that is constantly updated must be on the on_tick event. This is one reason why I personally do not include features of this nature in my mods.
There are however some guides around on how to attempt to offset the UPS disruption, such as only checking each chest for requests once a minute, but iterate through this list so that something is checked every tick.
something likeCode: Select all
for i, entity in pairs(list) do if game.tick % 3600 == i % 3600 do
It's better to run it only once:
Code: Select all
function OnTick(event)
local tick = game.tick
for i=1, #global.VoidChests do
if (i + tick) % update_interval == 0 then
global.VoidChests[i].get_inventory(defines.inventory.chest).clear()
end
end
end
I've benchmarked that to be 40% faster than above snippet in Void Chest +.
Code: Select all
function OnTick(event)
global.tickCount = global.tickCount or 1
global.chestIndex = global.chestIndex or 1
-- only work if index is within bounds
if global.chestIndex <= #global.VoidChests then
local stopIndex = global.chestIndex + global.VoidChestStride - 1
if stopIndex >= #global.VoidChests then
stopIndex = #global.VoidChests
end
-- log("[VCP] "..global.tickCount.." / "..game.tick.." clearing chest ids "..global.chestIndex.." to "..stopIndex)
for i=global.chestIndex, stopIndex do
global.VoidChests[i].get_inventory(defines.inventory.chest).clear()
end
global.chestIndex = stopIndex + 1
end
-- reset clock and chest index
if global.tickCount < update_interval then
global.tickCount = global.tickCount + 1
else
global.tickCount = 1
global.chestIndex = 1
end
end
My Mods: mods.factorio.com
- eradicator
- Smart Inserter
- Posts: 5211
- Joined: Tue Jul 12, 2016 9:03 am
- Contact:
Re: Hooking a non-logistic entity up to the logistics network
The last time i tried to to a tick-distrubuted update i used a construct like this:Optera wrote: I've benchmarked that to be 40% faster than above snippet in Void Chest +
Code: Select all
local UPDATEDELAY = 60
local function on_tick(event)
local tock = tick % UPDATEDELAY
for index=#global.mystuff-tock,1,-1*UPDATEDELAY do
--stuff
end
end
- one modulo per tick
- only loops through entities that are actually updated
- updates all entities in a fixed time window (aka does not get slower with more entities)
- (con) if new entites are constructed during an updatecycle some will be skipped until the next cycle
I only did some very short tests tho as in my case with very few entities (entity_count < UPDATEDELAY) the numbers seemed to suggest that doing them in bulk every n seconds was faster.
Author of: Belt Planner, Hand Crank Generator, Screenshot Maker, /sudo and more.
Mod support languages: 日本語, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.
Mod support languages: 日本語, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.
Re: Hooking a non-logistic entity up to the logistics network
That's a nifty way of stepping with stride.eradicator wrote:The last time i tried to to a tick-distrubuted update i used a construct like this:Optera wrote: I've benchmarked that to be 40% faster than above snippet in Void Chest +
Features:Code: Select all
local UPDATEDELAY = 60 local function on_tick(event) local tock = tick % UPDATEDELAY for index=#global.mystuff-tock,1,-1*UPDATEDELAY do --stuff end end
It basically walks backwards through the array (because sometimes i need to delete stuff if it becomes invalid, and forward walking screws up the index in that case) and updates every n-th entity.
- one modulo per tick
- only loops through entities that are actually updated
- updates all entities in a fixed time window (aka does not get slower with more entities)
- (con) if new entites are constructed during an updatecycle some will be skipped until the next cycle
I only did some very short tests tho as in my case with very few entities (entity_count < UPDATEDELAY) the numbers seemed to suggest that doing them in bulk every n seconds was faster.
Benchmark results for 480 Void chests using either version as on_tick over 100k ticks:
My current version: avg 11805.281 ms
Your version: avg 11776.126ms
Conclusion:
Your version is 0.25% faster in this benchmark. Both versions may be too fast to be accurately benchmarked with "only" 480 void Chests.
Overall I'd say the wiki should be updated to use your version. It's far more simplistic and unless you have to call different functions depending on accurate execution order your stepping with stride will work perfectly fine.
My Mods: mods.factorio.com
Re: Hooking a non-logistic entity up to the logistics network
Which wiki (page) talks about this?Optera wrote: Overall I'd say the wiki should be updated to use your version. It's far more simplistic and unless you have to call different functions depending on accurate execution order your stepping with stride will work perfectly fine.
I'm an admin over at https://wiki.factorio.com. Feel free to contact me if there's anything wrong (or right) with it.
Re: Hooking a non-logistic entity up to the logistics network
Well if there isn't a guide or wiki page about how to properly create an on_tick handler there should be one.Bilka wrote:Which wiki (page) talks about this?Optera wrote: Overall I'd say the wiki should be updated to use your version. It's far more simplistic and unless you have to call different functions depending on accurate execution order your stepping with stride will work perfectly fine.
I've seen way too many mods wasting a ton of performance due to bad on_tick iteration.
My Mods: mods.factorio.com
- eradicator
- Smart Inserter
- Posts: 5211
- Joined: Tue Jul 12, 2016 9:03 am
- Contact:
Re: Hooking a non-logistic entity up to the logistics network
Thanks (also for the numbers). It's amazing that the difference would be so tiny despite your frequent access to the global table for index management. I guess my intuition about what is expensive and what isn't is pretty bad . Also btw in your code i think you can call .clear_items_inside() directly on the chest entity, which should save the get_inventory call and thus the passing of another reference object over the c++/lua barrier.Optera wrote: That's a nifty way of stepping with stride.
Benchmark results for 480 Void chests using either version as on_tick over 100k ticks:
My current version: avg 11805.281 ms
Your version: avg 11776.126ms
Author of: Belt Planner, Hand Crank Generator, Screenshot Maker, /sudo and more.
Mod support languages: 日本語, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.
Mod support languages: 日本語, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.
Re: Hooking a non-logistic entity up to the logistics network
Thanks, I didn't even know a shortcut like clear_items_inside() existed.eradicator wrote: Thanks (also for the numbers). It's amazing that the difference would be so tiny despite your frequent access to the global table for index management. I guess my intuition about what is expensive and what isn't is pretty bad . Also btw in your code i think you can call .clear_items_inside() directly on the chest entity, which should save the get_inventory call and thus the passing of another reference object over the c++/lua barrier.
Using that instead of get_inventory(defines.inventory.chest).clear() made a much more noticeable difference than the on_tick handlers.
clear_items_inside(): avg 10162.627 ms ~13% faster
I'm surprised how close they are together myself, but then again the slowest part in any of my mods is read or write to entities through the API.
My Mods: mods.factorio.com
Re: Hooking a non-logistic entity up to the logistics network
Want it to be even faster? Save the inventory and work directly on that
global.chest = {ent = ent, inv = ent.get_inventory(defines.inventory.chest)}
global.chest.inv.clear()
global.chest = {ent = ent, inv = ent.get_inventory(defines.inventory.chest)}
global.chest.inv.clear()