Page 1 of 1
[DONE}get signal and set recipe in assembler and chemical
Posted: Sat Sep 10, 2016 6:59 am
by LuziferSenpai
Hey,
i want to get the signals that are on a wire that is attached to a constant combinator.
And than get the strongest signal out of it.
I have written this code:
Code: Select all
local signel = 0
local signal = {}
for i, k in pairs( game[ "virtual-signals" ] ) do
if combi.get_signal( i ) ~= nil then
for p, q in pairs( game.recipes ) do
if i.name == p.name then
if ( entity.name == "assembling-machine-1" and p.category == "crafting" ) then
if combi.get_signal( i ) > signel then
signel = combi.get_signal( i )
signal = { p.name }
end
end
if ( entity.name == "assembling-machine-2" and ( p.category == "crafting" or p.catergoy == "advanced-crafting" or p.category == "crafting-with-fluid" ) ) then
if combi.get_signal( i ) > signel then
signel = combi.get_signal( i )
signal = { p.name }
end
end
if ( entity.name == "assembling-machine-3" and ( p.category == "crafting" or p.catergoy == "advanced-crafting" or p.category == "crafting-with-fluid" ) ) then
if combi.get_signal( i ) > signel then
signel = combi.get_signal( i )
signal = { p.name }
end
end
if ( entity.name == "chemical-plant" and p.category == "chemistry" ) then
if combi.get_signal( i ) > signel then
signel = combi.get_signal( i )
signal = { p.name }
end
end
end
end
end
end
And than i want to set the recipe in a Assembler or Chemical-Plant so i make
right?
Can you pls help me if this is a good method or not? And if not pls help me finding a better way?
I'm working on a CraftingCombinator with that you can set Assembler and Chemical-Plant Recipes with Circuit Network.
Greetz,
Luzifer
Re: get signal and set recipe in assembler and chemical
Posted: Sat Sep 10, 2016 1:36 pm
by aubergine18
I refactored your code to try and make it a bit clearer as to what it's doing:
Code: Select all
-- validation dictionaries
local category = {
basic = {
['crafting'] = true;
},
advanced = {
['crafting'] = true;
['advanced-crafting'] = true;
['crafting-with-fluid'] = true;
},
chemistry = {
['chemistry'] = true;
}
}
local machine = {
['assembling-machine-1'] = category.basic;
['assembling-machine-2'] = category.advanced;
['assembling-machine-3'] = category.advanced;
['chemical-plant'] = category.chemistry;
}
local function getBiggestFor( entity, combi, recipes )
local biggest = { value = 0 }
local current, valid
for signalName in pairs( game.virtual_signal_prototypes ) do
current = combi.get_signal( signalName );
if current then
for recipeName, recipePrototype in pairs( recipes ) do
if recipeName == signalName then
valid = machine[entity.name] and
machine[entity.name][recipePrototype.category]
if valid and current > biggest.value then
biggest.value = current
biggest.name = recipeName
end
end
end--for recipes
end
end--for signals
return biggest
end
Iterating all recipes, within an iteration of all virtual signals, is going to be massively laggy. In addition, you'd have to do this twice per entity-combi pair, once for fluid recipes and once for item recipes. So that's doubling the number of times the virtual signal iteration is geting run per entity-combi pair.
It might be worth starting with a clearer definition of what problem you're trying to solve, and then re-evaluate various ways that problem can be solved.
Re: get signal and set recipe in assembler and chemical
Posted: Sat Sep 10, 2016 2:24 pm
by LuziferSenpai
aubergine18 wrote:I refactored your code to try and make it a bit clearer as to what it's doing:
Code: Select all
-- validation dictionaries
local category = {
basic = {
['crafting'] = true;
},
advanced = {
['crafting'] = true;
['advanced-crafting'] = true;
['crafting-with-fluid'] = true;
},
chemistry = {
['chemistry'] = true;
}
}
local machine = {
['assembling-machine-1'] = category.basic;
['assembling-machine-2'] = category.advanced;
['assembling-machine-3'] = category.advanced;
['chemical-plant'] = category.chemistry;
}
local function getBiggestFor( entity, combi, recipes )
local biggest = { value = 0 }
local current, valid
for signalName in pairs( game.virtual_signal_prototypes ) do
current = combi.get_signal( signalName );
if current then
for recipeName, recipePrototype in pairs( recipes ) do
if recipeName == signalName then
valid = machine[entity.name] and
machine[entity.name][recipePrototype.category]
if valid and current > biggest.value then
biggest.value = current
biggest.name = recipeName
end
end
end--for recipes
end
end--for signals
return biggest
end
Iterating all recipes, within an iteration of all virtual signals, is going to be massively laggy. In addition, you'd have to do this twice per entity-combi pair, once for fluid recipes and once for item recipes. So that's doubling the number of times the virtual signal iteration is geting run per entity-combi pair.
It might be worth starting with a clearer definition of what problem you're trying to solve, and then re-evaluate various ways that problem can be solved.
I want to get the biggest signal to set a Assembling Machine or so to that Recipe. Like you can set requester slots in a requester chest.
Re: get signal and set recipe in assembler and chemical
Posted: Sat Sep 10, 2016 2:42 pm
by aubergine18
So it seems the following sequence of events needs to happen:
Code: Select all
make dictionary of applicable {signal = recipe,...} per entity type
-- account for 'can be built in' metadata
when special combinator placed, add it to a global list:
{ combi, entity, applicableSignals }
remember to remove things form list when destroyed
every 60 ticks do
- iterate list of our combis
- determine biggest applicable signal in combi
- set entity recipe to the recipe associated with the signal
The main thing here is that you want to build dictionary of applicable signals for each of the entity types (assemble machine 1, 2, 3 and the chem plant). ONCE, IN ADVANCE. This will greatly minimise the amount of effort in the tick handler. That list will need refreshing whenever on_configuration_changed event is called.
In the tick handler you only then need to go through short, precompiled list of applicable recipes for entity type, find biggest combi signal, if found set associated recipe on entity.
Re: get signal and set recipe in assembler and chemical
Posted: Sat Sep 10, 2016 2:53 pm
by LuziferSenpai
aubergine18 wrote:So it seems the following sequence of events needs to happen:
Code: Select all
make dictionary of applicable {signal = recipe,...} per entity type
-- account for 'can be built in' metadata
when special combinator placed, add it to a global list:
{ combi, entity, applicableSignals }
remember to remove things form list when destroyed
every 60 ticks do
- iterate list of our combis
- determine biggest applicable signal in combi
- set entity recipe to the recipe associated with the signal
The main thing here is that you want to build dictionary of applicable signals for each of the entity types (assemble machine 1, 2, 3 and the chem plant). ONCE, IN ADVANCE. This will greatly minimise the amount of effort in the tick handler. That list will need refreshing whenever on_configuration_changed event is called.
In the tick handler you only then need to go through short, precompiled list of applicable recipes for entity, find biggest combi signal, if found set associated recipe on entity.
At the moment i have this Code written already:
Code: Select all
local update_interval = 5
local find_entity_interval = 100
script.on_init(function() On_Load() end)
script.on_load(function() On_Load() end)
script.on_event(defines.events.on_built_entity, function(event) On_Built(event) end)
script.on_event(defines.events.on_robot_built_entity, function(event) On_Built(event) end)
script.on_event(defines.events.on_preplayer_mined_item, function(event) On_Removed(event) end)
script.on_event(defines.events.on_robot_pre_mined, function(event) On_Removed(event) end)
script.on_event(defines.events.on_entity_died, function(event) On_Removed(event) end)
function On_Load()
if global.CraftingCombiList ~= nil then
script.on_event(defines.events.on_tick, On_Tick)
end
end
function On_Tick()
if global.CraftingCombiList ~= nil and #global.CraftingCombiList > 0 then
for k, combi in pairs(global.CraftingCombiList) do
if k % find_entity_interval == game.tick % find_entity_interval then
combi.ConnectedEntity = getConnectedEntity(combi.Sensor)
end
if k % update_interval == game.tick % update_interval then
setInventory(combi)
end
end
else
script.on_event(defines.events.on_tick, nil)
end
end
function On_Built( event )
local entity = event.created_entity
if global.CraftingCombiList == nil then
global.CraftingCombiList = {}
script.on_event(defines.events.on_tick, On_Tick)
end
if entity.name == "Crafting-Combinator" then
entity.operable = false
local CraftingCombinator = { Combi = entity, ConnectedEntity = getConnectedEntity(entity) }
table.insert( global.CraftingCombiList, CraftingCombinator )
end
end
function On_Removed( event )
local entity = event.entity
if global.CraftingCombiList ~= nil and entity.name == "Crafting-Combinator" then
for i, combi in ipairs( global.CraftingCombiList ) do
if notNil( combi.Combi, "position" ) then
if combi.Combi.position.x == entity.position.x and combi.Combi.position.y == entity.position.y then
table.remove( global.CraftingCombiList, i )
break
end
end
end
end
end
function notNil( class, var )
value = false
pcall(function()
if class[var] then
value = true
end
end)
return value
end
function getConnectedEntity( combi )
local connectedEntitys = combi.surface.find_entities( { { x = combi.position.x - 1, y = combi.position.y - 1 }, { x = combi.position.x + 1, y = combi.position.y + 1 } } )
for _,entity in ipairs(connectedEntitys) do
if ( entity.valid and entity.type == "assembling-machine" ) then
return entity
end
end
end
function setInventory ( CraftingCombinator )
local combi = CraftingCombinator.Combi
local ConnectedEntity
local inventory = {}
local signals = {}
if connectedEntity == nil then
combi.get_control_behavior().parameters = nil
return
end
if not connectedEntity.valid then
combi.get_control_behavior().parameters = nil
return
end
end
function getSignal ( combi, entity )
local signel = 0
local signal = {}
for i, k in pairs( game[ "virtual-signals" ] ) do
if combi.get_signal( i ) ~= nil then
for p, q in pairs( game.recipes ) do
if i.name == p.name then
if ( entity.name == "assembling-machine-1" and p.category == "crafting" ) then
if combi.get_signal( i ) > signel then
signel = combi.get_signal( i )
signal = { p.name }
end
end
if ( entity.name == "assembling-machine-2" and ( p.category == "crafting" or p.catergoy == "advanced-crafting" or p.category == "crafting-with-fluid" ) ) then
if combi.get_signal( i ) > signel then
signel = combi.get_signal( i )
signal = { p.name }
end
end
if ( entity.name == "assembling-machine-3" and ( p.category == "crafting" or p.catergoy == "advanced-crafting" or p.category == "crafting-with-fluid" ) ) then
if combi.get_signal( i ) > signel then
signel = combi.get_signal( i )
signal = { p.name }
end
end
if ( entity.name == "chemical-plant" and p.category == "chemistry" ) then
if combi.get_signal( i ) > signel then
signel = combi.get_signal( i )
signal = { p.name }
end
end
end
end
end
end
end
I get the near assembler too.
But now i dont know how i can work with your thing.
Re: get signal and set recipe in assembler and chemical
Posted: Sat Sep 10, 2016 3:13 pm
by aubergine18
Does your code even work? Because I can't see anything in API docs for `game[ "virtual-signals" ]` - it should be game.virtual_signal_prototypes ?
Also, how do you know if an assembly machine / chem plant has access to required resources? Or are you also going to have a requestor chest updated so things can be delivered by logic network?
Re: get signal and set recipe in assembler and chemical
Posted: Sat Sep 10, 2016 3:24 pm
by LuziferSenpai
aubergine18 wrote:Does your code even work? Because I can't see anything in API docs for `game[ "virtual-signals" ]` - it should be game.virtual_signal_prototypes ?
Also, how do you know if an assembly machine / chem plant has access to required resources? Or are you also going to have a requestor chest updated so things can be delivered by logic network?
I only set teh recipe not more. The rest you need to handle else where. This MOD only adds the possible to set Recipes in Assemblers.
And i didnt know that it is game.virtual_signal_prototypes.