Re: help with making a harvester
Posted: Sat May 10, 2014 6:23 pm
				
				Ok thanks for the fast reply. 
			

they are 'bound' to the collision box, so you could change the collision box of the refinery but that's the only way I really know of...McSpiffy wrote:Is there any way to make the inserters reach in a normal way or no?
FreeER wrote:...of course you could have the control.lua transfer the ore when you are close to a refinery (as if you were 'dumping' the ore into it), rather than using inserters.
oh, right that makes sense tooMcSpiffy wrote:I wanted to make taking the ore out of the refinery faster.
 
 
 though you should be able to approximate it with code if you wanted (check every second or so if the refinery has items in it's inventory if so remove x amount and create an item entity with a stack of that name and x amount at a position relative to the refinery's position).
 though you should be able to approximate it with code if you wanted (check every second or so if the refinery has items in it's inventory if so remove x amount and create an item entity with a stack of that name and x amount at a position relative to the refinery's position).Code: Select all
game.onevent(defines.events.onputitem, function(event)
	if event.onputitem.name == "refinery"  then
		game.createentity{name = "stone",}
	end
end)Code: Select all
 game.createentity{name="stone", position=event.position}ok I will try this do you have any pointers or guide lines I should follow to attempt this. I'm starting to feel like I'm not very good at thisFreeER wrote: Well...sorry for wasting your time with that ideathough you should be able to approximate it with code if you wanted (check every second or so if the refinery has items in it's inventory if so remove x amount and create an item entity with a stack of that name and x amount at a position relative to the refinery's position).

Code: Select all
game.onevent(defines.events.ontick, function()
  if game.tick % 60 == 0 then
	if game.container.name == "refinery" then
		local storageItem = game.container.getinventory(1)
		local itemAmount = 7 -- stack size
		if item.name > 0 then
			game.container.remove{name = item.name, count = itemAmount}
			game.createentity{name = name= "storageItem", position = {game.container.name == "refinery", 2}, count = itemAmount}
		end	
	end
  end
end)
Don't worry, it takes a bit of time to really understand it but after you do you'll be fine (obviously...McSpiffy wrote:I'm starting to feel like I'm not very good at this
 ).
).Code: Select all
game.oninit(function() --create refineries table on new game
  if not glob.refineries then glob.refineries = {} end
end)
game.onload(function()
  --create refineries table on load (if it does not exist)
  if not glob.refineries then glob.refineries = {} end
end)
game.onevent(defines.events.onbuiltentity, function(event)
  if event.createdentity.name = "refinery" then
    table.insert(glob.refineries, event.createdentity) 
  end
end)
game.onevent(defines.events.ontick, function()
  if game.tick % 60 == 0 then
    for index, refinery in ipairs(glob.refineries) do
      if refinery.valid then
        if refinery.getitemcount() > 0 then -- if the refinery has items
          -- the inventory number may be wrong... the [1] selects 
          -- the first item stack in the inventory
          local item = refinery.getinventory(1)[1] 
          local itemAmount = 7 -- stack size
          -- make item.count reflect the amount we are inserting/removing
          -- only checking for > because we don't want to insert more if
          -- if there are actually less than itemAmount in the refinery
          if item.count > itemAmount then item.count = itemAmount end 
          -- you'll probably need to play with these number to get it to
          -- place where you want it to...
          -- there is also refinery.direction which tells you whether
          -- the refinery is pointing north, south etc. so if you get
          -- ambitious you can try to make it place the output to the
          -- same relative side rather than always in one direction...
          local storagePos = {refinery.position.x + 5, refinery.position.y + 5}
          -- get any entities at that storagePosition
          local storageEntities = game.findentities(storagePos) 
          local storageEntity = false -- temp bool
          for _, entity in ipairs(storageEntities) do
            if entity.caninsert(item) then
              storageEntity = entity -- save a reference to this entity
              break -- and break out of the loop
            end
          end
          if storageEntity then -- if an entity that we can place the item into was found
            storageEntity.insert(item)
            refinery.remove(item)
          -- no entities at all (just an else statement would allow dropping them even if there was, say, a wall there
          elseif storageEntities == nil then
            -- just place the item on the ground
            game.createentity{name="item-on-ground", position=storagePos, stack=item}
            refinery.remove(item)
          end
        end
      else -- not a valid refinery anymore
        table.remove(glob.refineries, index) -- remove from table
      end
    end
  end
end)Code: Select all
 local storageEntities = game.findentities(storagePos) 
Code: Select all
local storageEntities = game.findentities(getBoundingBox(storagePos, 1))Code: Select all
local item
for _, slot in pairs(refinery.getinventory(1)) do -- find the first slot with an item instead of assuming the first slot
  if slot then -- if the inventory slot has something in it
    item = slot -- set item to hold the same item stack
    break
  end
end
Code: Select all
require "defines" -- has a bunch of defined constants for events and inventory, etc. the file itself is data\core\lualib\defines.lua
--//	Harvester	//--
game.onevent(defines.events.ontick, function() --tell game we want to do stuff every tick (60 times per second)
  if game.tick % 60 == 0 then -- do this only once per second, you can decrease 60 if needed...but it'd probably be better to increase the amount of ore being removed
    if game.player.vehicle and game.player.vehicle.name == "harvester" then -- if the player is in a vehicle and it is a harvester
      local ore = game.findentitiesfiltered{type = "resource", area=getBoundingBox(game.player.vehicle.position, 2)} -- get a table of the ore within a (square) radius of 10 around the harvester, thankfully that was fairly easy, change the '10' to any value you think is appropriate, the 'type = "resource"' might allow it to 'mine' trees as well...if so and you didn't want that you'd need to have multiple tables and instead search using 'name = "name_of_ores"'
      local oreAmount = 1 -- amount of ore to mine from each resource spot
      for _, ore in ipairs(ore) do -- loop through those ores
		if ore.name ~= "crude-oil" and ore.name:sub(-4) ~= "tree" then
			if game.player.vehicle.caninsert{name = ore.name, count = oreAmount} then -- if the harvester is not full
				if ore.amount >= oreAmount then -- if there is more than enough ore
					ore.amount = ore.amount - oreAmount -- decrement the ore by oreAmount
					game.player.vehicle.insert{name = ore.name, count = oreAmount} -- and insert it into the harvester
				else -- if the amount of ore left is not greater than or equal to what we want to remove, just remove all of it (without the else, it'd leave any spots less than oreAmount...which would be somewhat annoying lol)
					game.player.vehicle.insert{name = ore.name, count = ore.amount} -- insert first so that we don't need a local variable to store the amount
					ore.amount = 0 -- then just set ore amount to 0 instead doing ore.amount = ore.amount - ore.amount (cause that looks silly :))
				end
			  end
			end
		end
    end
		--auto coal placement into burner from trunk
	if game.player.vehicle and game.player.vehicle.name == "harvester" then
		local burnerCoal = game.player.vehicle.getinventory(1)
		local trunkCoal = game.player.vehicle.getinventory(2)
		-- notice that I combined these since you won't do anything if only one is true
	if burnerCoal.getitemcount() <= 19 and trunkCoal.getitemcount("coal") > 0  then
		trunkCoal.remove({name="coal", count="1"})
		burnerCoal.insert({name="coal", count="1"})
		end
		end
	end
	end) -- end anonymous function and onevent/ontick call5
function getBoundingBox(position, radius)
		return {{position.x - radius, position.y-radius}, {position.x + radius, position.y + radius}}
		end
--//	Refinery	//--
game.oninit(function() --create refineries table on new game
  if not glob.refineries then glob.refineries = {} end
end)
game.onload(function()
  --create refineries table on load (if it does not exist)
  if not glob.refineries then glob.refineries = {} end
end)
game.onevent(defines.events.onbuiltentity, function(event)
  if event.createdentity.name == "refinery" then
    table.insert(glob.refineries, event.createdentity) 
  end
end)
game.onevent(defines.events.ontick, function()
  if game.tick % 60 == 0 then
    for index, refinery in ipairs(glob.refineries) do
      if refinery.valid then
        if refinery.getitemcount() > 0 then -- if the refinery has items
          -- the inventory number may be wrong... the [1] selects 
          -- the first item stack in the inventory
          local item = refinery.getinventory(1)[1] 
          local itemAmount = 1 -- stack size
          -- make item.count reflect the amount we are inserting/removing
          -- only checking for > because we don't want to insert more if
          -- if there are actually less than itemAmount in the refinery
          if item.count > itemAmount then item.count = itemAmount end 
          -- you'll probably need to play with these number to get it to
          -- place where you want it to...
          -- there is also refinery.direction which tells you whether
          -- the refinery is pointing north, south etc. so if you get
          -- ambitious you can try to make it place the output to the
          -- same relative side rather than always in one direction...
          local storagePos = {refinery.position.x + 0, refinery.position.y + 5 }
          -- get any entities at that storagePosition
          local storageEntities = game.findentities(getBoundingBox(storagePos, 1))
          local storageEntity = false -- temp bool
          for _, entity in ipairs(storageEntities) do
            if entity.caninsert(item) then
              storageEntity = entity -- save a reference to this entity
              break -- and break out of the loop
            end
          end
          if storageEntity then -- if an entity that we can place the item into was found
            storageEntity.insert(item)
            refinery.remove(item)
          -- no entities at all (just an else statement would allow dropping them even if there was, say, a wall there
          elseif storageEntities == nil then
            -- just place the item on the ground
            game.createentity{name="item-on-ground", position=storagePos, stack=item}
            refinery.remove(item)
          end
        end
      else -- not a valid refinery anymore
        table.remove(glob.refineries, index) -- remove from table
      end
    end
  end
end)
 )...but it should be fine, I hope...
)...but it should be fine, I hope...Code: Select all
require "defines" -- has a bunch of defined constants for events and inventory, etc. the file itself is data\core\lualib\defines.lua
game.oninit(function() --create refineries table on new game
  if not glob.refineries then glob.refineries = {} end
end)
game.onload(function()
  --create refineries table on load (if it does not exist)
  if not glob.refineries then glob.refineries = {} end
end)
-- store each built refinery in the glob.refineries table
game.onevent(defines.events.onbuiltentity, function(event)
  if event.createdentity.name == "refinery" then
    table.insert(glob.refineries, event.createdentity)
  end
end)
--//   Harvester   //--
game.onevent(defines.events.ontick, function() --tell game we want to do stuff every tick (60 times per second)
  if game.tick % 60 == 0 then -- do this only once per second, you can decrease 60 if needed...but it'd probably be better to increase the amount of ore being removed
    if game.player.vehicle and game.player.vehicle.name == "harvester" then -- if the player is in a vehicle and it is a harvester
      local ore = game.findentitiesfiltered{type = "resource", area=getBoundingBox(game.player.vehicle.position, 2)} -- get a table of the ore within a (square) radius of 10 around the harvester, thankfully that was fairly easy, change the '10' to any value you think is appropriate, the 'type = "resource"' might allow it to 'mine' trees as well...if so and you didn't want that you'd need to have multiple tables and instead search using 'name = "name_of_ores"'
      local oreAmount = 7 -- amount of ore to mine from each resource spot
      for _, ore in ipairs(ore) do -- loop through those ores
        if ore.name ~= "crude-oil" and ore.name:sub(-4) ~= "tree" then
          if game.player.vehicle.caninsert{name = ore.name, count = oreAmount} then -- if the harvester is not full
            if ore.amount >= oreAmount then -- if there is more than enough ore
              ore.amount = ore.amount - oreAmount -- decrement the ore by oreAmount
              game.player.vehicle.insert{name = ore.name, count = oreAmount} -- and insert it into the harvester
            else -- if the amount of ore left is not greater than or equal to what we want to remove, just remove all of it (without the else, it'd leave any spots less than oreAmount...which would be somewhat annoying lol)
              game.player.vehicle.insert{name = ore.name, count = ore.amount} -- insert first so that we don't need a local variable to store the amount
              ore.amount = 0 -- then just set ore amount to 0 instead doing ore.amount = ore.amount - ore.amount (cause that looks silly :))
            end
          end
        end
      end
    end
    --auto coal placement into burner from trunk
    if game.player.vehicle and game.player.vehicle.name == "harvester" then
      local burnerCoal = game.player.vehicle.getinventory(1)
      local trunkCoal = game.player.vehicle.getinventory(2)
      -- notice that I combined these since you won't do anything if only one is true
      if burnerCoal.getitemcount() <= 19 and trunkCoal.getitemcount("coal") > 0  then
        trunkCoal.remove({name="coal", count="1"})
        burnerCoal.insert({name="coal", count="1"})
      end
    end
    -- start of refinery code
    for index, refinery in ipairs(glob.refineries) do
      if refinery.valid then
        if refinery.getitemcount() > 0 then -- if the refinery has items
          -- the inventory number may be wrong... the [1] selects
          -- the first item stack in the inventory
          local item
          -- bit of a 'hack' here...
          -- the bug did occur where just selecting the first inventory
          -- would be nil fairly quickly...but the for loop I posted
          -- on the forums didn't work because the slot is 'userdata'
          -- and you can not index userdata...
          -- so I use getcontents() which returns a regular lua table
          -- but it returns it indexed by the item name...and that's
          -- one of the pieces of info that we actually need to get back
          -- soo here's a for loop that simply selects whatever lua gives
          -- back first (since associative arrays have no guarenteed order)
          -- and uses that as the 'first' item
          for name, count in pairs(refinery.getinventory(defines.inventory.chest).getcontents()) do
            item = {name=name, count=count}
            break
          end
          local itemAmount = 7 -- stack size
          -- make item.count reflect the amount we are inserting/removing
          -- only checking for > because we don't want to insert more if
          -- if there are actually less than itemAmount in the refinery
          if item.count > itemAmount then item.count = itemAmount end
          -- you'll probably need to play with these number to get it to
          -- place where you want it to...
          -- there is also refinery.direction which tells you whether
          -- the refinery is pointing north, south etc. so if you get
          -- ambitious you can try to make it place the output to the
          -- same relative side rather than always in one direction...
          local storagePos = {x = refinery.position.x + 0, y = refinery.position.y + 5 }
          -- get any entities at that storagePosition
          local storageEntities = game.findentities(getBoundingBox(storagePos, 1))
          local storageEntity = false -- temp bool
          for _, entity in ipairs(storageEntities) do
            if entity.caninsert(item) then
              storageEntity = entity -- save a reference to this entity
              break -- and break out of the loop
            end
          end
          if storageEntity then -- if an entity that we can place the item into was found
            storageEntity.insert(item)
            refinery.getinventory(defines.inventory.chest).remove(item)
            -- no entities at all (just an else statement would allow dropping them even if there was, say, a wall there
          elseif #storageEntities == 0 then
            -- just place the item on the ground
            game.createentity{name="item-on-ground", position=storagePos, stack=item}
            refinery.getinventory(defines.inventory.chest).remove(item)
          end
        end
      else -- not a valid refinery anymore
        table.remove(glob.refineries, index) -- remove from table
      end
    end -- end of refinery code
  end -- end of ontick%60
end) -- end anonymous function and onevent/ontick calls
function getBoundingBox(position, radius)
  return {{position.x - radius, position.y - radius}, {position.x + radius, position.y + radius}}
end