[DONE}get signal and set recipe in assembler and chemical

Place to get help with not working mods / modding interface.
User avatar
LuziferSenpai
Filter Inserter
Filter Inserter
Posts: 393
Joined: Tue Jul 08, 2014 10:06 am
Contact:

[DONE}get signal and set recipe in assembler and chemical

Post 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

Code: Select all

entity.recipe = recipe
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
Last edited by LuziferSenpai on Sun Sep 11, 2016 1:39 pm, edited 1 time in total.
Coding is awesome!
Animes are love!
Factorio is life!

My MODs:
Click

Greetz,

Senpai
User avatar
aubergine18
Smart Inserter
Smart Inserter
Posts: 1264
Joined: Fri Jul 22, 2016 8:51 pm
Contact:

Re: get signal and set recipe in assembler and chemical

Post 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.
Better forum search for modders: Enclose your search term in quotes, eg. "font_color" or "custom-input" - it prevents the forum search from splitting on hypens and underscores, resulting in much more accurate results.
User avatar
LuziferSenpai
Filter Inserter
Filter Inserter
Posts: 393
Joined: Tue Jul 08, 2014 10:06 am
Contact:

Re: get signal and set recipe in assembler and chemical

Post 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.
Coding is awesome!
Animes are love!
Factorio is life!

My MODs:
Click

Greetz,

Senpai
User avatar
aubergine18
Smart Inserter
Smart Inserter
Posts: 1264
Joined: Fri Jul 22, 2016 8:51 pm
Contact:

Re: get signal and set recipe in assembler and chemical

Post 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.
Last edited by aubergine18 on Sat Sep 10, 2016 3:12 pm, edited 1 time in total.
Better forum search for modders: Enclose your search term in quotes, eg. "font_color" or "custom-input" - it prevents the forum search from splitting on hypens and underscores, resulting in much more accurate results.
User avatar
LuziferSenpai
Filter Inserter
Filter Inserter
Posts: 393
Joined: Tue Jul 08, 2014 10:06 am
Contact:

Re: get signal and set recipe in assembler and chemical

Post 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.
Coding is awesome!
Animes are love!
Factorio is life!

My MODs:
Click

Greetz,

Senpai
User avatar
aubergine18
Smart Inserter
Smart Inserter
Posts: 1264
Joined: Fri Jul 22, 2016 8:51 pm
Contact:

Re: get signal and set recipe in assembler and chemical

Post 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?
Better forum search for modders: Enclose your search term in quotes, eg. "font_color" or "custom-input" - it prevents the forum search from splitting on hypens and underscores, resulting in much more accurate results.
User avatar
LuziferSenpai
Filter Inserter
Filter Inserter
Posts: 393
Joined: Tue Jul 08, 2014 10:06 am
Contact:

Re: get signal and set recipe in assembler and chemical

Post 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.
Coding is awesome!
Animes are love!
Factorio is life!

My MODs:
Click

Greetz,

Senpai
Post Reply

Return to “Modding help”