Advertisement
Column01

OpenComputers dynamic trader

Jun 5th, 2020
1,778
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 7.58 KB | None | 0 0
  1. local comp = require("component")
  2. local transposer = comp.transposer
  3. local sides = require("sides")
  4.  
  5. local interrupted = false
  6. -- Lists of trades we generate based on the drawers
  7. local trades = {}
  8. -- List of transposers connected to the network
  9. local transposers = {}
  10. -- Trade controller which is used to define trades and their costs
  11. local tradeController = comp.inventory_controller
  12. if tradeController == nil then
  13.     io.stderr:write("ERROR 1: You must attach an Adapter with an inventory controller upgrade in it to assign trades")
  14.     os.exit()
  15. end
  16.  
  17. -- #### CONFIG SECTION ####
  18.  
  19. -- The side of the adapter the trade's drawer controller is placed on.
  20. local tradeControllerSide = sides.up
  21. -- The sides of the transposer for the storage drawer setup to get bought items
  22. local storageSide = sides.up
  23. -- The side of the trash can or inventory to dump items (USE A TRASH CAN)
  24. local trashCanSide = sides.south
  25. -- The input chest side.
  26. local inputChestSide = sides.up
  27. -- The side to output items
  28. local outputChestSide = sides.north
  29.  
  30. -- #### END OF CONFIG SECTION ####
  31.  
  32.  
  33. -- Get the size of the trade controller we want to make
  34. local tradeSizes = tradeController.getInventorySize(tradeControllerSide)
  35. -- Creates a trade table and returns it
  36. local function createTrade(itemToBuy, purchaseItem)
  37.     local tbl = {}
  38.     tbl.item = itemToBuy
  39.     tbl.cost = purchaseItem
  40.     return tbl
  41. end
  42.  
  43. -- Comapres certain asspects of the 2 items
  44. local function compareItems(item1, item2)
  45.     local matches = 0
  46.     if item1.name == item2.name then
  47.         matches = matches + 1
  48.     end
  49.     if item1.damage == item2.damage then
  50.         matches = matches + 1
  51.     end
  52.     if item1.maxDamage == item2.maxDamage then
  53.         matches = matches + 1
  54.     end
  55.     if item1.maxSize == item2.maxSize then
  56.         matches = matches + 1
  57.     end
  58.     if item1.label == item2.label then
  59.         matches = matches + 1
  60.     end
  61.     if matches == 5 then
  62.         return true
  63.     else
  64.         return false
  65.     end
  66. end
  67.  
  68. -- Gets the trade for the item we are selling
  69. local function getTradeForCostItem(costItem)
  70.     for i=1, #trades do
  71.         tradeCostItem = trades[i]["cost"]
  72.         if compareItems(costItem, tradeCostItem) then
  73.             return trades[i]
  74.         end
  75.     end
  76.     return nil
  77. end
  78.  
  79. -- Get's the slot for the item the user is buying. Uses label because
  80. local function getStorageSlotOfItem(item, storageProxy)
  81.     local maxSlots = storageProxy.getInventorySize(storageSide)
  82.     for slot=1, maxSlots do
  83.         itemStack = storageProxy.getStackInSlot(storageSide, slot)
  84.         if itemStack ~= nil then
  85.             if item.label == itemStack.label then
  86.                 return slot
  87.             end
  88.         end
  89.     end
  90.     return nil
  91. end
  92.  
  93. -- Lists all trades.
  94. local function listTrades()
  95.     print("Available Trades:")
  96.     -- Loop over all trades
  97.     for i=1, #trades do
  98.         purchaseItemName = trades[i]["item"].label
  99.         purchaseItemAmount = trades[i]["item"].size
  100.         costItem = trades[i]["cost"].label
  101.         costItemAmount = trades[i]["cost"].size
  102.         print("Item to buy: " .. purchaseItemName .. " x " .. purchaseItemAmount .. " for: " .. costItem .. " x " .. costItemAmount)
  103.     end
  104. end
  105.  
  106. -- Obtain the addresses of all transposers
  107. local function initTransposers()
  108.     for address, name in component.list("transposer", true) do
  109.         --print(name .. " at: " .. address)
  110.         table.insert(transposers, component.proxy(address))
  111.     end
  112.     if #transposers ~= 2  then
  113.         io.stderr:write("ERROR 2: You must have exactly two transposers connected to the system")
  114.         os.exit()
  115.     end
  116. end
  117.  
  118. local function getFirstEmptySlot(side, proxy)
  119.     local maxSlots = proxy.getInventorySize(side)
  120.     for slot=1, maxSlots do
  121.         itemStack = proxy.getStackInSlot(side, slot)
  122.         if itemStack == nil then
  123.             return slot
  124.         end
  125.     end
  126.     io.stderr:write("ERROR 3: No empty slot was found for the inventory on side: " .. side)
  127. end
  128.  
  129. local function removeIfAvailable(item, required, userInputProxy)
  130.     local numItems = 0
  131.     local slotsWithItem = {}
  132.     local maxSlots = userInputProxy.getInventorySize(inputChestSide)
  133.     for slot=1, maxSlots do
  134.         itemStack = userInputProxy.getStackInSlot(inputChestSide, slot)
  135.         if itemStack ~= nil then
  136.             if compareItems(item, itemStack) then
  137.                 table.insert(slotsWithItem, slot)
  138.                 numItems = numItems + itemStack.size
  139.             end
  140.         end
  141.     end
  142.     local removed = 0
  143.     if numItems >= required then
  144.         for i=1, #slotsWithItem do
  145.             slot = slotsWithItem[i]
  146.             itemStack = userInputProxy.getStackInSlot(inputChestSide, slot)
  147.             stackSize = itemStack.size
  148.             -- If the stack contains more than or the right amount of items, remove the required amount and return
  149.             if stackSize >= required then
  150.                 userInputProxy.transferItem(inputChestSide, trashCanSide, required, slot, getFirstEmptySlot(trashCanSide, userInputProxy))
  151.                 return true
  152.             else
  153.                 if removed < required then
  154.                     to_remove = required - removed
  155.                     if to_remove < stackSize then
  156.                         userInputProxy.transferItem(inputChestSide, trashCanSide, to_remove, slot, getFirstEmptySlot(trashCanSide, userInputProxy))
  157.                         return true
  158.                     elseif to_remove >= stackSize then
  159.                         userInputProxy.transferItem(inputChestSide, trashCanSide, stackSize, slot, getFirstEmptySlot(trashCanSide, userInputProxy))
  160.                         removed = removed + stackSize
  161.                     end
  162.                 end
  163.             end
  164.         end
  165.         if removed == required then
  166.             return true
  167.         end
  168.     else
  169.         return false
  170.     end
  171. end
  172.  
  173. local function handleInterrupt()
  174.     interrupted = true
  175.     return false
  176. end
  177.  
  178. -- Loops over items in trade controller to build trades for the shop
  179. for slot=1, tradeSizes do
  180.     itemStack = tradeController.getStackInSlot(tradeControllerSide, slot)
  181.     if itemStack ~= nil then
  182.         if slot % 2 == 0 then
  183.             itemStack2 = tradeController.getStackInSlot(tradeControllerSide, slot + 1)
  184.             if itemStack2 ~= nil then
  185.                 local trade = createTrade(itemStack, itemStack2)
  186.                 table.insert(trades, trade)
  187.             end
  188.         end
  189.     end
  190. end
  191.  
  192. initTransposers()
  193. listTrades()
  194.  
  195. local storageProxy
  196. local userInputProxy
  197.  
  198. -- Obtain which transposer is the storage one
  199. for i=1, #transposers do
  200.     proxy = transposers[i]
  201.     invSize = proxy.getInventorySize(storageSide)
  202.     -- Loop over all slots in the proxy's storage side
  203.     for slot=1, invSize do
  204.         -- Get the item in the current slot
  205.         itemStack = proxy.getStackInSlot(storageSide, slot)
  206.         -- If it's not an empty slot
  207.         if itemStack ~= nil then
  208.             -- Get the size
  209.             size = itemStack.size
  210.             -- If the size is greater than 10000, that likely means it't the provider side of the setup to provide bought items
  211.             if size >= 10000 then
  212.                 -- Set the storage proxy and set the user input proxy.
  213.                 if i == 1 then
  214.                     storageProxy = transposers[1]
  215.                     userInputProxy = transposers[2]
  216.                 else
  217.                     userInputProxy = transposers[1]
  218.                     storageProxy = transposers[2]
  219.                 end
  220.                 break
  221.             end
  222.         end
  223.     end
  224. end
  225.  
  226. event.listen("interrupted", handleInterrupt)
  227.  
  228. while interrupted == false do
  229.     local maxSlots = userInputProxy.getInventorySize(inputChestSide)
  230.     for slot=1, maxSlots do
  231.         itemStack = userInputProxy.getStackInSlot(inputChestSide, slot)
  232.         -- If the item is not nil, get the trade for that item
  233.         if itemStack ~= nil then
  234.             trade = getTradeForCostItem(itemStack)
  235.             -- If there is a valid trade, Retrieve the data from the trade and try to get the storage slot of the item on the provider side
  236.             if trade ~= nil then
  237.                 buyItem = trade.item
  238.                 costItem = trade.cost
  239.                 storageSlot = getStorageSlotOfItem(buyItem, storageProxy)
  240.                 -- If it finds the item in the storage system. Try to transfer the items if they have enough. If they do, give them the purchase item and break the loop to loop over the chest again.
  241.                 if storageSlot ~= nil then
  242.                     test = removeIfAvailable(costItem, costItem.size, userInputProxy)
  243.                     if test == true then
  244.                         storageProxy.transferItem(storageSide, outputChestSide, buyItem.size, storageSlot, getFirstEmptySlot(outputChestSide, storageProxy))
  245.                         break
  246.                     end
  247.                 end
  248.             end
  249.         end
  250.     end
  251.     -- Scan the inventory once a second
  252.     os.sleep(1)
  253. end
  254.  
  255. -- Code that runs at the end of the program after getting interrupted
  256. print("Exiting trade program...")
  257. os.sleep(1)
  258. os.exit()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement