Advertisement
Sophisticasean

interface chest control.lua

Aug 29th, 2016
159
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 28.02 KB | None | 0 0
  1. require "util"
  2.  
  3. -- Belts lanes have 4 slots: yellow 36 ticks, red 18 ticks, blue 12 ticks
  4. -- Ticks to clear a slot 9, 4.5, 3
  5. -- Splitters/underground 2 slots: need twice the tick rate
  6. -- Red splitter/underground do some magic -- cuase technically they should have a gap
  7. -- Should take 9 ticks for 2 items to clear out of the way, but on splitter/underground they dissapear ahead of schedule.
  8. -- On red splitter/underground belt they alternate sending items on tick 0, 6, 18, 24, 30 = 9 average
  9.  
  10. local chestThrottle = 6
  11. local railCheckThrottle = chestThrottle * 15
  12. local voidThrottle = chestThrottle * 20
  13. local energy_per_action = 8000
  14. local idleDraw = 500
  15.  
  16. local beltBalancerThrottle = 12
  17.  
  18. -- Internal Use
  19. local dataVersion = 14
  20.  
  21. -- How many a chest can pull from a belt lane 0-8
  22. local inputMultiplier = 8
  23. -- Inventory to Inventory transfer stack size
  24. local maxStackSize = 4
  25.  
  26. -- Cardinal Directions
  27. local NORTH = defines.direction.north
  28. local EAST = defines.direction.east
  29. local SOUTH = defines.direction.south
  30. local WEST = defines.direction.west
  31.  
  32. -- Optimal places on a belt to place item
  33. local beltPositions = {0, .182, .463, .744}
  34. local splitterPositions = {0, .28}
  35.  
  36. -- Adjacent tiles
  37. function areaNorth(position) return {{position.x - 0.5, position.y - 1.5},{position.x + 0.5, position.y - 0.5}} end
  38. function areaSouth(position) return {{position.x - 0.5, position.y + 0.5},{position.x + 0.5, position.y + 1.5}} end
  39. function areaEast(position)  return {{position.x + 0.5, position.y - 0.5},{position.x + 1.5, position.y + 0.5}} end
  40. function areaWest(position)  return {{position.x - 1.5, position.y - 0.5},{position.x - 0.5, position.y + 0.5}} end
  41.  
  42. -- Area around tile
  43. function getBoundingBox(position, radius)
  44.     return {{x=position.x-radius-.5,y=position.y-radius-.5},{x=position.x+radius+.5,y=position.y+radius+.5}}
  45. end
  46.  
  47. -- Area around tile
  48. function getBoundingBoxX(position, radius)
  49.     return {{x=position.x-radius-.5,y=position.y-.5},{x=position.x+radius+.5,y=position.y+.5}}
  50. end
  51.  
  52.  
  53. -- Area around tile
  54. function getBoundingBoxY(position, radius)
  55.     return {{x=position.x-.5,y=position.y-radius-.5},{x=position.x+.5,y=position.y+radius+.5}}
  56. end
  57.  
  58.  
  59. -------------------
  60. function InterfaceChest_Initialize()
  61.     if global.InterfaceChest_MasterList == nil then
  62.         global.InterfaceChest_MasterList = {}
  63.     end
  64.    
  65.     if global.InterfaceChest_DataVersion == nil then
  66.         global.InterfaceChest_DataVersion = 0
  67.     end
  68.  
  69.     if global.InterfaceBelt_MasterList == nil then
  70.         global.InterfaceBelt_MasterList = {}
  71.     end
  72.    
  73.     if global.InterfaceBelt_DataVersion == nil then
  74.         global.InterfaceBelt_DataVersion = 0
  75.     end
  76. end
  77.  
  78. -------------------
  79. function getKey (entity)
  80.     return "if_x" .. entity.position.x .. "y".. entity.position.y .. entity.surface.index
  81. end
  82.  
  83. function InterfaceChest_Create(event)
  84.     local entity = event.created_entity
  85.     if isInterfaceChest(entity) then
  86.         local modTick = game.tick % chestThrottle
  87.         local key = getKey(entity)
  88.         if global.InterfaceChest_MasterList[modTick] == nil then
  89.             global.InterfaceChest_MasterList[modTick] = {}
  90.         end
  91.         global.InterfaceChest_MasterList[modTick][key] = updateInterfaceChest(entity)
  92.         --debugPrint("Interface Chest created: " .. key)
  93.     end
  94.  
  95.     if entity.name == "interface-belt-balancer" then
  96.         local key = getKey(entity)
  97.         local modTick = game.tick % beltBalancerThrottle
  98.         if global.InterfaceBelt_MasterList[modTick] == nil then
  99.             global.InterfaceBelt_MasterList[modTick] = {}
  100.         end
  101.         global.InterfaceBelt_MasterList[modTick][key] = entity
  102.         --debugPrint("Interface Belt count: " .. key)
  103.     end
  104.  
  105.     if isTransport(entity) or isInventory(entity) or entity.type == "straight-rail" then
  106.         scheduleUpdate(entity, 3)
  107.     end
  108. end
  109.  
  110. -------------------
  111. function InterfaceChest_Rotated(event)
  112.     local entity = event.entity
  113.     if isTransport(entity) or isInventory(entity) or entity.type == "straight-rail" then
  114.         scheduleUpdate(entity, 3)
  115.     end
  116. end
  117.  
  118. function InterfaceChest_Mined(event)
  119.     local entity = event.entity
  120.     if isTransport(entity) or isInventory(entity) or entity.type == "straight-rail" then
  121.         scheduleUpdate(entity, 3)
  122.     end
  123. end
  124.  
  125. -------------------
  126. function scheduleUpdate (entity, range)
  127.     local entities = entity.surface.find_entities(getBoundingBox(entity.position, range))
  128.     for index=1, #entities do
  129.         if isInterfaceChest( entities[index]) then
  130.             local chest = entities[index]
  131.             if chest and chest.valid then
  132.                 for modTick=0, chestThrottle-1 do
  133.                     if global.InterfaceChest_MasterList[modTick][getKey(chest)] then
  134.                         global.InterfaceChest_MasterList[modTick][getKey(chest)].dirty = true
  135.                     end
  136.                 end
  137.             end
  138.         end
  139.     end
  140. end
  141.  
  142. -------------------
  143. function InterfaceBelt_RunStep()
  144.     if global.InterfaceBelt_DataVersion ~= dataVersion then
  145.         -- Initialize
  146.         InterfaceChest_Initialize()
  147.  
  148.         local beltBalancer = game.surfaces[1].find_entities_filtered{area={{-10000, -10000},{10000, 10000}}, name="interface-belt-balancer"}
  149.        
  150.         local masterList = {}
  151.         for index=0, beltBalancerThrottle-1 do
  152.             masterList[index] = {}
  153.         end
  154.        
  155.         for index=1, #beltBalancer do
  156.             local entity = beltBalancer[index]
  157.             local modTick = math.random(beltBalancerThrottle) - 1
  158.             masterList[modTick][getKey(entity)] = entity
  159.         end
  160.  
  161.         global.InterfaceBelt_MasterList = masterList
  162.         global.InterfaceBelt_DataVersion = dataVersion
  163.  
  164.     else
  165.         local modTick = game.tick % beltBalancerThrottle
  166.         local masterList = global.InterfaceBelt_MasterList[modTick]
  167.         if masterList then
  168.             for index, value in pairs(masterList) do
  169.                 local belt = value
  170.                 if belt and belt.valid then
  171.                     local left = belt.get_transport_line(1)
  172.                     local right = belt.get_transport_line(2)
  173.                     balanceBelt(right, left)
  174.                     balanceBelt(left, right)
  175.                 else
  176.                     global.InterfaceBelt_MasterList[modTick][index] = nil
  177.                 end
  178.             end
  179.         end
  180.     end
  181. end
  182.  
  183. function balanceBelt (source, target)
  184.     local action = false
  185.     for item, size in pairs(source.get_contents()) do
  186.         local diff = size - target.get_item_count(item)
  187.         local itemstack = {name=item, count=1}
  188.         if diff > 2 and size > 2 then
  189.             if target.insert_at(beltPositions[1], itemstack) then
  190.                 source.remove_item(itemstack)
  191.                 action = true
  192.             end
  193.             if target.insert_at(beltPositions[2], itemstack) then
  194.                 source.remove_item(itemstack)
  195.                 action = true
  196.             end
  197.         elseif diff > 1 and size > 1 then
  198.             if target.insert_at(beltPositions[1], itemstack) then
  199.                 source.remove_item(itemstack)
  200.                 action = true
  201.             end
  202.         end
  203.     end
  204.     return action
  205. end
  206.  
  207. -------------------
  208. function InterfaceChest_RunStep(event)
  209.     if global.InterfaceChest_DataVersion ~= dataVersion then
  210.        
  211.         -- Initialize
  212.         InterfaceChest_Initialize()
  213.  
  214.         -- Find all this mod's chests and index them
  215.         trashCan = {}
  216.         for index=1,#game.surfaces do
  217.             local temp = game.surfaces[index].find_entities_filtered{area={{-10000, -10000},{10000, 10000}}, name="interface-chest-trash"}
  218.             for k,v in pairs(temp) do table.insert(trashCan, v) end
  219.         end
  220.  
  221.         interfaceChests = {}
  222.         for index=1,#game.surfaces do
  223.             local temp = game.surfaces[index].find_entities_filtered{area={{-10000, -10000},{10000, 10000}}, name="interface-chest"}
  224.             for k,v in pairs(temp) do table.insert(interfaceChests, v) end
  225.         end
  226.  
  227.         local masterList = {}
  228.         for index=0, chestThrottle-1 do
  229.             masterList[index] = {}
  230.         end
  231.  
  232.         for index=1, #trashCan do
  233.             local modTick = math.random(chestThrottle) - 1
  234.             local chest = trashCan[index]
  235.             masterList[modTick][getKey(chest)] = updateInterfaceChest(chest)
  236.         end
  237.  
  238.         for index=1, #interfaceChests do
  239.             local modTick = math.random(chestThrottle) - 1
  240.             local chest = interfaceChests[index]
  241.             masterList[modTick][getKey(chest)] = updateInterfaceChest(chest)
  242.         end
  243.  
  244.         global.InterfaceChest_MasterList = masterList
  245.         global.InterfaceChest_DataVersion = dataVersion
  246.     else
  247.         InterfaceBelt_RunStep()
  248.         local modTick = game.tick % chestThrottle
  249.         local masterList = global.InterfaceChest_MasterList[modTick]
  250.  
  251.         if masterList then
  252.             for index, value in pairs(masterList) do
  253.                 local interfaceChest = value
  254.                 if interfaceChest.chest and interfaceChest.chest.valid then                
  255.                     if interfaceChest.power == nil or interfaceChest.power.valid == false then
  256.                         interfaceChest = updateInterfaceChest(interfaceChest.chest)
  257.                         global.InterfaceChest_MasterList[modTick][index] = interfaceChest
  258.                         --debugPrint("Create missing power for: " .. index)
  259.                     else
  260.                         if interfaceChest.power and interfaceChest.power.valid and interfaceChest.power.energy >= (idleDraw) then
  261.                             interfaceChest.power.energy = interfaceChest.power.energy - idleDraw
  262.                             if interfaceChest.chest.name == "interface-chest-trash" then
  263.                                 voidChest(interfaceChest, modTick, index)
  264.                             else
  265.                                
  266.                                 -- No good way to check for nearby train, so if on rail check for train
  267.                                 if interfaceChest.onRail and modTick == (game.tick % railCheckThrottle) then
  268.                                     interfaceChest.dirty = true
  269.                                 end
  270.  
  271.                                 local chestPosition = getBoundingBox(interfaceChest.chest.position, 0)
  272.                                 if interfaceChest.dirty then
  273.                                     interfaceChest = updateInterfaceChest(interfaceChest.chest)
  274.                                     global.InterfaceChest_MasterList[index] = interfaceChest
  275.                                 end
  276.  
  277.                             -- Input items Into Chest
  278.                                 for i=1, #interfaceChest.inputBelts do
  279.                                     local belt = interfaceChest.inputBelts[i]
  280.                                     if belt.valid then
  281.                                         if belt.type == "splitter" then
  282.                                             local chestPosition = getBoundingBox(interfaceChest.chest.position, 0)
  283.                                             if (belt.position.x == chestPosition[1].x and belt.position.y < chestPosition[1].y) or (belt.position.x == chestPosition[2].x and belt.position.y > chestPosition[1].y) or (belt.position.y == chestPosition[1].y and belt.position.x > chestPosition[2].x) or (belt.position.y == chestPosition[2].y and belt.position.x < chestPosition[2].x) then
  284.                                                 beltToChest(belt, defines.transport_line.left_split_line, interfaceChest.chest, interfaceChest.power)
  285.                                                 beltToChest(belt, defines.transport_line.right_split_line, interfaceChest.chest, interfaceChest.power)
  286.                                             else
  287.                                                 beltToChest(belt, defines.transport_line.secondary_left_split_line, interfaceChest.chest, interfaceChest.power)
  288.                                                 beltToChest(belt, defines.transport_line.secondary_right_split_line, interfaceChest.chest, interfaceChest.power)
  289.                                             end
  290.                                         else
  291.                                             beltToChest(belt, defines.transport_line.left_line, interfaceChest.chest, interfaceChest.power)
  292.                                             beltToChest(belt, defines.transport_line.right_line, interfaceChest.chest, interfaceChest.power)
  293.                                         end
  294.                                     end
  295.                                 end
  296.  
  297.                                 -- Pull Items from adjacent Inventories
  298.                                 if #interfaceChest.inputBelts == 0 and #interfaceChest.outputBelts > 0 then
  299.                                     for i=1, #interfaceChest.inventories do
  300.                                         local inventory = interfaceChest.inventories[i]
  301.                                         local inventoryIndex = 1
  302.                                         if inventory and inventory.valid then
  303.                                             if inventory.get_output_inventory() and inventory.get_output_inventory().is_empty() == false then
  304.                                                 sourceToTargetInventory(inventory, interfaceChest.chest, interfaceChest.power)
  305.                                             end
  306.                                         end
  307.                                     end
  308.                                 end
  309.  
  310.                                 -- Output items to adjacent Belts
  311.                                 if interfaceChest.chest.get_output_inventory().is_empty() == false then
  312.                                     for i=1, #interfaceChest.outputBelts do
  313.                                         local belt = interfaceChest.outputBelts[i]
  314.                                         if belt.valid then
  315.                                             if belt.type == "splitter" then
  316.                                                 local chestPosition = getBoundingBox(interfaceChest.chest.position, 0)
  317.                                                 if (belt.position.x == chestPosition[1].x and belt.position.y > chestPosition[1].y) or (belt.position.x == chestPosition[2].x and belt.position.y < chestPosition[1].y) or (belt.position.y == chestPosition[1].y and belt.position.x < chestPosition[2].x) or (belt.position.y == chestPosition[2].y and belt.position.x > chestPosition[2].x) then
  318.                                                     chestToBelt(belt, defines.transport_line.left_line, interfaceChest.chest, interfaceChest.power)
  319.                                                     chestToBelt(belt, defines.transport_line.right_line, interfaceChest.chest, interfaceChest.power)
  320.                                                 else
  321.                                                     chestToBelt(belt, defines.transport_line.secondary_left_line, interfaceChest.chest, interfaceChest.power)
  322.                                                     chestToBelt(belt, defines.transport_line.secondary_right_line, interfaceChest.chest, interfaceChest.power)
  323.                                                 end
  324.                                             else
  325.                                                 chestToBelt(belt, defines.transport_line.left_line, interfaceChest.chest, interfaceChest.power)
  326.                                                 chestToBelt(belt, defines.transport_line.right_line, interfaceChest.chest, interfaceChest.power)
  327.                                             end
  328.                                         end
  329.                                     end
  330.                                     -- Output items to adjacent inventories
  331.                                     if #interfaceChest.outputBelts == 0 and #interfaceChest.inputBelts > 0 then
  332.                                         for i=1, #interfaceChest.inventories do
  333.                                             local inventory = interfaceChest.inventories[i]
  334.                                             sourceToTargetInventory(interfaceChest.chest, inventory, interfaceChest.power)
  335.                                         end
  336.                                     end
  337.                                 end
  338.                                
  339.                             end
  340.                         end
  341.                     end
  342.                 else
  343.                     if interfaceChest ~= nil and interfaceChest.power and interfaceChest.power.valid then
  344.                         if interfaceChest.power.destroy() then
  345.                             --debugPrint("Power removed: " ..   index)
  346.                             global.InterfaceChest_MasterList[modTick][index] = nil
  347.                         end
  348.                     end
  349.                     --debugPrint("Loaded: " ..   index)
  350.                 end
  351.             end
  352.         end
  353.     end
  354. end
  355.  
  356. function updateInterfaceChest(chest)
  357.     local center = getBoundingBox(chest.position, 0)
  358.     local entities = chest.surface.find_entities(getBoundingBox(chest.position, 1))
  359.     local entitiesX = chest.surface.find_entities(getBoundingBoxX(chest.position, 1))
  360.     local entitiesY = chest.surface.find_entities(getBoundingBoxY(chest.position, 1))
  361.     local gridTransport = {}
  362.     local gridInventory = {}
  363.     local isRail = false
  364.     local powerSource = nil
  365.  
  366.     for index=1, #entities do
  367.         local entity = entities[index]
  368.         if entity.type ~= "decorative" then
  369.             if isRail == false and entity.type == "straight-rail" then
  370.                 isRail = true
  371.             elseif powerSource == nil and entity.name == "interface-chest-power" and entity.position.x > center[1].x and entity.position.x < center[2].x and entity.position.y > center[1].y and entity.position.y < center[2].y then
  372.                 --debugPrint("Power: " .. entity.position.x .. " > " .. center[1].x .. " and " .. entity.position.x .. " < " ..  center[2].x .. " and " .. entity.position.y .. " > " ..  center[1].y .. " and " .. entity.position.y .. " < " ..  center[2].y)
  373.                 powerSource = entity
  374.             end
  375.         end
  376.     end
  377.    
  378.     for index=1, #entitiesX do
  379.         local entity = entitiesX[index]
  380.         if entity.type ~= "decorative" then
  381.             -- East
  382.             if entity.position.x > center[2].x then
  383.                 if isTransport(entity) then gridTransport.east = entity end
  384.                 if isInventory(entity, isRail) then gridInventory.east = entity end
  385.             -- West
  386.             elseif entity.position.x < center[1].x then
  387.                 if isTransport(entity) then gridTransport.west = entity end
  388.                 if isInventory(entity, isRail) then gridInventory.west = entity end
  389.             end
  390.         end
  391.     end
  392.    
  393.     for index=1, #entitiesY do
  394.         local entity = entitiesY[index]
  395.         if entity.type ~= "decorative" then
  396.             -- North
  397.             if entity.position.y < center[1].y then
  398.                 if isTransport(entity) then gridTransport.north = entity end
  399.                 if isInventory(entity, isRail) then gridInventory.north = entity end
  400.             -- South
  401.             elseif entity.position.y > center[2].y then
  402.                 if isTransport(entity) then gridTransport.south = entity end
  403.                 if isInventory(entity, isRail) then gridInventory.south = entity end
  404.             end
  405.         end
  406.     end
  407.  
  408.     for index=1, #entities do
  409.         local entity = entities[index]
  410.         if entity.type ~= "decorative" then
  411.             -- North West
  412.             if entity.position.x <= center[1].x and entity.position.y <= center[1].y then
  413.                 if isTransport(entity) then gridTransport.northWest = entity end
  414.                 if isTrain(entity, isRail) then gridInventory.northWest = entity end
  415.             -- North East
  416.             elseif entity.position.x >= center[2].x and entity.position.y <= center[1].y then
  417.                 if isTransport(entity) then gridTransport.northEast = entity end
  418.                 if isTrain(entity, isRail) then gridInventory.northEast = entity end
  419.             -- South West
  420.             elseif entity.position.x <= center[1].x and entity.position.y >= center[2].y then
  421.                 if isTransport(entity) then gridTransport.southWest = entity end
  422.                 if isTrain(entity, isRail) then gridInventory.southWest = entity end
  423.             -- South East
  424.             elseif entity.position.x >= center[2].x and entity.position.y >= center[2].y then
  425.                 if isTransport(entity) then gridTransport.southEast = entity end
  426.                 if isTrain(entity, isRail) then gridInventory.southEast = entity end
  427.             end
  428.         end
  429.     end
  430.  
  431.     if powerSource == nil then
  432.         --debugPrint("Create power: " .. serpent.block(chest.position))
  433.         powerSource = chest.surface.create_entity{name="interface-chest-power", position=chest.position, force=chest.force}
  434.     end
  435.  
  436.     return {chest = chest, inputBelts = getInputBelts(gridTransport), outputBelts = getOutputBelts(gridTransport), inventories = getInventories(gridInventory), onRail = isRail, dirty = false, power = powerSource}
  437. end
  438.  
  439. function voidChest(interfaceChest, modTick, index)
  440.     if interfaceChest.chest and interfaceChest.chest.valid and interfaceChest.power and interfaceChest.power.valid and interfaceChest.power.energy >= energy_per_action then
  441.         if interfaceChest.dirty then
  442.             interfaceChest = updateInterfaceChest(interfaceChest.chest)
  443.             global.InterfaceChest_MasterList[modTick][index] = interfaceChest
  444.         end
  445.  
  446.         if modTick == (game.tick % voidThrottle) then
  447.             interfaceChest.chest.get_output_inventory().clear()
  448.             interfaceChest.power.energy = interfaceChest.power.energy - energy_per_action
  449.         end
  450.  
  451.         for i=1, #interfaceChest.inputBelts do
  452.             local belt = interfaceChest.inputBelts[i]
  453.             if belt.valid then
  454.                 if belt.type == "splitter" then
  455.                     if (belt.position.x > interfaceChest.chest.position.x and belt.position.y > interfaceChest.chest.position.y) or (belt.position.x < interfaceChest.chest.position.x and belt.position.y < interfaceChest.chest.position.y) then
  456.                         beltToVoid(belt, defines.transport_line.left_split_line, interfaceChest.power)
  457.                         beltToVoid(belt, defines.transport_line.right_split_line, interfaceChest.power)
  458.                     else
  459.                         beltToVoid(belt, defines.transport_line.secondary_left_split_line, interfaceChest.power)
  460.                         beltToVoid(belt, defines.transport_line.secondary_right_split_line, interfaceChest.power)
  461.                     end
  462.                 else
  463.                     beltToVoid(belt, defines.transport_line.left_line, interfaceChest.power)
  464.                     beltToVoid(belt, defines.transport_line.right_line, interfaceChest.power)
  465.                 end
  466.             end
  467.         end
  468.     end
  469. end
  470.  
  471.  
  472. function beltToVoid(belt, laneNumber, power)
  473.     if power and power.valid and power.energy >= energy_per_action then
  474.         if belt.get_transport_line(laneNumber).can_insert_at(0) == false then
  475.             local items = belt.get_transport_line(laneNumber).get_contents()
  476.             local item = next(items)
  477.             local size = items[item]
  478.             if size then
  479.                 local itemstack = {name=item, count=size}
  480.                 belt.get_transport_line(laneNumber).remove_item(itemstack)
  481.                 power.energy = power.energy - energy_per_action
  482.             end
  483.         end
  484.     end
  485. end
  486.  
  487. function beltToChest(belt, laneNumber, chest, power)
  488.     if chest and chest.valid and power and power.valid and power.energy >= energy_per_action then
  489.         if belt.get_transport_line(laneNumber).can_insert_at(0) == false then
  490.             local lane = belt.get_transport_line(laneNumber)
  491.             local contents = lane.get_contents()
  492.             local item = next(contents)
  493.             local size = contents[item]
  494.             --debugPrint(item .. " " .. size)
  495.             if size then
  496.                 local itemstack = {name=item, count=math.min(inputMultiplier,size)}
  497.                 if chest and chest.valid and chest.can_insert(itemstack) then
  498.                     itemstack.count = chest.insert(itemstack)
  499.                     lane.remove_item(itemstack)
  500.                     power.energy = power.energy - energy_per_action
  501.                 end
  502.             end
  503.         end
  504.     end
  505. end
  506.  
  507. function chestToBelt(belt, laneNumber, chest, power)
  508.     if chest and chest.valid and power and power.valid and power.energy >= energy_per_action then
  509.         local positions = {}
  510.         if belt.type == "transport-belt" then
  511.             positions = beltPositions
  512.         else
  513.             positions = splitterPositions
  514.         end
  515.         if belt.get_transport_line(laneNumber).can_insert_at(positions[1]) then
  516.        
  517.  
  518.            
  519.        
  520.             local inventory = chest.get_output_inventory()
  521.             local contents = inventory.get_contents()
  522.             local item = next(contents)
  523.             local size = contents[item]
  524.             local itemstack = {name=item, count=1}
  525.            
  526.  
  527.            
  528.             if size then
  529.            
  530.             --[[
  531.             --Find Positions 0 to 1
  532.             for i=0, 1000 do
  533.             if belt.get_transport_line(laneNumber).insert_at(i/1000, itemstack) then
  534.                     debugPrint("Inserted: " .. i/1000 .. " tick: " .. game.tick)
  535.                     power.energy = power.energy - energy_per_action
  536.                     inventory.remove({name=item, count=1})
  537.                 end
  538.             end
  539.            
  540.             --Find Positions 1 to 0
  541.             for i=1, 1000 do
  542.             if belt.get_transport_line(laneNumber).insert_at((1001-i)/1000, itemstack) then
  543.                     debugPrint("Inserted: " .. (1001-i)/1000 .. " tick: " .. game.tick)
  544.                     power.energy = power.energy - energy_per_action
  545.                     inventory.remove({name=item, count=1})
  546.                 end
  547.             end
  548.             ]]--
  549.            
  550.                 local toTransfer = math.min(#positions, size)
  551.                 for i=1, toTransfer do
  552.                     if belt.get_transport_line(laneNumber).insert_at(positions[i], itemstack) then
  553.                         --debugPrint("Inserted: " .. positions[i] .. " tick: " .. game.tick)
  554.                         power.energy = power.energy - energy_per_action
  555.                         inventory.remove({name=item, count=1})
  556.                     end
  557.                 end
  558.                
  559.             end
  560.         end
  561.     end
  562. end
  563.  
  564. function sourceToTargetInventory(source, target, power)
  565.     if source and source.valid and power and power.valid and power.energy >= energy_per_action then
  566.         local inventory = source.get_output_inventory()
  567.         local contents = inventory.get_contents()
  568.         local item = next(contents)
  569.         local size = contents[item]
  570.         if size then
  571.             local itemstack = {name=item, count=math.min(maxStackSize,size)}
  572.             if target and target.valid and target.can_insert(itemstack) then
  573.                 itemstack.count = target.insert(itemstack)
  574.                 inventory.remove(itemstack)
  575.                 power.energy = power.energy - energy_per_action
  576.             end
  577.         end
  578.     end
  579. end
  580.  
  581. function getInputBelts(grid)
  582.     local belts = {}
  583.     local belt
  584.  
  585.     -- North
  586.     belt = checkTransportEntity(grid.north, SOUTH, "output")
  587.     if belt then
  588.         belts[#belts+1] = belt
  589.     end
  590.  
  591.     -- South
  592.     belt = checkTransportEntity(grid.south, NORTH, "output")
  593.     if belt then
  594.         belts[#belts+1] = belt
  595.     end
  596.  
  597.     -- East
  598.     belt = checkTransportEntity(grid.east, WEST, "output")
  599.     if belt then
  600.         belts[#belts+1] = belt
  601.     end
  602.  
  603.     -- West
  604.     belt = checkTransportEntity(grid.west, EAST, "output")
  605.     if belt then
  606.         belts[#belts+1] = belt
  607.     end
  608.    
  609.     return belts
  610. end
  611.  
  612. function getOutputBelts(grid)
  613.     local belts = {}
  614.     local belt
  615.     local checkNorth
  616.     local checkEast
  617.     local checkSouth
  618.     local checkWest
  619.    
  620.     -- North
  621.     belt = checkTransportEntity(grid.north, NORTH, "input")
  622.     if belt then
  623.         if belt.type == "transport-belt" then
  624.             checkWest = checkTransportEntity(grid.northWest, EAST, "output")
  625.             checkEast = checkTransportEntity(grid.northEast, WEST, "output")
  626.             if (checkWest and checkEast) or (checkWest == nil and checkEast == nil) then
  627.                 belts[#belts+1] = belt
  628.             end
  629.         else
  630.             belts[#belts+1] = belt
  631.         end
  632.     end
  633.    
  634.     -- South
  635.     belt = checkTransportEntity(grid.south, SOUTH, "input")
  636.     if belt then
  637.         if belt.type == "transport-belt" then
  638.             checkWest = checkTransportEntity(grid.southWest, EAST, "output")
  639.             checkEast = checkTransportEntity(grid.southEast, WEST, "output")
  640.             if (checkWest and checkEast) or (checkWest == nil and checkEast == nil) then
  641.                 belts[#belts+1] = belt
  642.             end
  643.         else
  644.             belts[#belts+1] = belt
  645.         end
  646.     end
  647.    
  648.     -- East
  649.     belt = checkTransportEntity(grid.east, EAST, "input")
  650.     if belt then
  651.         if belt.type == "transport-belt" then
  652.             checkNorth = checkTransportEntity(grid.northEast, SOUTH, "output")
  653.             checkSouth = checkTransportEntity(grid.southEast, NORTH, "output")
  654.             if (checkNorth and checkSouth) or (checkNorth == nil and checkSouth == nil) then
  655.                 belts[#belts+1] = belt
  656.             end
  657.         else
  658.             belts[#belts+1] = belt
  659.         end
  660.     end
  661.  
  662.     -- West
  663.     belt = checkTransportEntity(grid.west, WEST, "input")
  664.     if belt then
  665.         if belt.type == "transport-belt" then
  666.             checkNorth = checkTransportEntity(grid.northWest, SOUTH, "output")
  667.             checkSouth = checkTransportEntity(grid.southWest, NORTH, "output")
  668.             if (checkNorth and checkSouth) or (checkNorth == nil and checkSouth == nil) then
  669.                 belts[#belts+1] = belt
  670.             end
  671.         else
  672.             belts[#belts+1] = belt
  673.         end
  674.     end
  675.    
  676.     return belts
  677. end
  678.  
  679. function getInventories(grid)
  680.     local inventories = {}
  681.     local inventory
  682.  
  683.     -- North
  684.     inventory = grid.north
  685.     if inventory then
  686.         inventories[#inventories+1] = inventory
  687.     end
  688.  
  689.     -- South
  690.     inventory = grid.south
  691.     if inventory then
  692.         inventories[#inventories+1] = inventory
  693.     end
  694.  
  695.     -- East
  696.     inventory = grid.east
  697.     if inventory then
  698.         inventories[#inventories+1] = inventory
  699.     end
  700.  
  701.     --West
  702.     inventory = grid.west
  703.     if inventory then
  704.         inventories[#inventories+1] = inventory
  705.     end
  706.  
  707.     -- North East
  708.     inventory = grid.northEast
  709.     if inventory then
  710.         inventories[#inventories+1] = inventory
  711.     end
  712.  
  713.     -- South East
  714.     inventory = grid.southEast
  715.     if inventory then
  716.         inventories[#inventories+1] = inventory
  717.     end
  718.  
  719.     -- North West
  720.     inventory = grid.northWest
  721.     if inventory then
  722.         inventories[#inventories+1] = inventory
  723.     end
  724.  
  725.     -- South West
  726.     inventory = grid.southWest
  727.     if inventory then
  728.         inventories[#inventories+1] = inventory
  729.     end
  730.  
  731.     return inventories
  732. end
  733.  
  734. function checkTransportEntity(entity, direction, undergroundType)
  735.     if entity and (entity.type ~= "underground-belt" or (entity.type == "underground-belt" and entity.belt_to_ground_type == undergroundType)) and entity.direction == direction then
  736.         return entity
  737.     else
  738.         return nil
  739.     end
  740. end
  741.  
  742. function isInventory (entity, onTrack)
  743.     if entity and entity.name ~= "interface-chest" and entity.type ~= "beacon" and entity.get_output_inventory() ~= nil and (isMoveable(entity) == false or isTrain(entity, onTrack)) then
  744.         return entity
  745.     else
  746.         return nil
  747.     end
  748. end
  749.  
  750. function isMoveable (entity)
  751.     if (entity.type == "cargo-wagon" or entity.type == "locomotive" or entity.type == "car" or entity.type == "player") then
  752.         return true
  753.     else
  754.         return false
  755.     end
  756. end
  757.  
  758. --or (entity.type == "player" and entity.walking_state == false)
  759. function isTrain (entity, onTrack)
  760.     if entity and onTrack and ((entity.type == "cargo-wagon" and entity.train.speed == 0) or (entity.type == "locomotive" and entity.train.speed == 0) or (entity.type == "car" and entity.speed == 0)) then
  761.         return entity
  762.     else
  763.         return nil
  764.     end
  765. end
  766.  
  767. function isTransport (entity)
  768.     if entity and (entity.type == "transport-belt" or entity.type == "splitter" or entity.type == "underground-belt") then
  769.         return entity
  770.     else
  771.         return nil
  772.     end
  773. end
  774.  
  775. function isInterfaceChest (entity)
  776.      if entity.name == "interface-chest" or entity.name == "interface-chest-trash"  then
  777.         return true
  778.      else
  779.         return false
  780.      end
  781. end
  782.  
  783. function debugPrint(thing)
  784.     for _, player in pairs(game.players) do
  785.         player.print(serpent.block(thing))
  786.     end
  787. end
  788.  
  789. -- Once per save
  790. script.on_init(InterfaceChest_Initialize)
  791.  
  792. -- Every Tick
  793. script.on_event(defines.events.on_tick, InterfaceChest_RunStep)
  794.  
  795. -- On create
  796. script.on_event(defines.events.on_built_entity, InterfaceChest_Create)
  797. script.on_event(defines.events.on_robot_built_entity, InterfaceChest_Create)
  798.  
  799. -- On change
  800. script.on_event(defines.events.on_player_rotated_entity, InterfaceChest_Rotated)
  801.  
  802. -- On remove
  803. script.on_event(defines.events.on_preplayer_mined_item, InterfaceChest_Mined)
  804. script.on_event(defines.events.on_robot_pre_mined, InterfaceChest_Mined)
  805.  
  806. script.on_event(defines.events.on_entity_died, function(event)
  807.     local entity = event.entity
  808.     if entity.name == "interface-chest-power" then
  809.         local entities = entity.surface.find_entities(getBoundingBox(entity.position, 0))
  810.         for index=1, #entities do
  811.             if isInterfaceChest( entities[index]) then
  812.                 local chest = entities[index]
  813.                 if chest and chest.valid then
  814.                     --debugPrint("Chest Destoyed: " .. getKey(chest.location))
  815.                     chest.destroy()
  816.                 end
  817.             end
  818.         end
  819.     end
  820. end)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement