Advertisement
djgaven588

Sorting System 2.0

Mar 15th, 2024 (edited)
501
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 26.57 KB | None | 0 0
  1. os.loadAPI("drawLib.lua")
  2.  
  3. rednet.close("right")
  4. rednet.open("right")
  5.  
  6. local currentState = "Idle"
  7.  
  8. local function itemEnchantedOrHighDurability(getItemDetails)
  9.     currentState = "Checking enchant"
  10.     local itemDetails = getItemDetails()
  11.     if itemDetails.enchantments == nil then
  12.         return itemDetails.durability == nil or itemDetails.durability >= 0.9
  13.     end
  14.  
  15.     return true
  16. end
  17.  
  18. local function destroyOverflow()
  19.     return false
  20. end
  21.  
  22. local itemConditions = {
  23.     ["minecraft:golden_sword"] = {
  24.         keep=itemEnchantedOrHighDurability,
  25.     },
  26.     ["minecraft:cobblestone"] = {
  27.         overflow=destroyOverflow
  28.     }
  29. }
  30.  
  31. local itemCategories = {
  32.     ["Building"] = {
  33.         "minecraft:cobblestone",
  34.         "minecraft:spruce_planks",
  35.         "minecraft:spruce_log"
  36.     },
  37.     ["Functional"] = {
  38.         "minecraft:chest",
  39.         "minecraft:spruce_sign",
  40.         "computercraft:wired_modem",
  41.         "computercraft:cable"
  42.     },
  43.     ["Crafting"] = {
  44.         "minecraft:stick"
  45.     }
  46. }
  47.  
  48. local craftingRecipes = {
  49.     ["minecraft:chest"] = {
  50.         [1]="minecraft:spruce_planks",
  51.         [2]="minecraft:spruce_planks",
  52.         [3]="minecraft:spruce_planks",
  53.        
  54.         [4]="minecraft:spruce_planks",
  55.         [5]=nil,
  56.         [6]="minecraft:spruce_planks",
  57.        
  58.         [7]="minecraft:spruce_planks",
  59.         [8]="minecraft:spruce_planks",
  60.         [9]="minecraft:spruce_planks",
  61.         count=1
  62.     },
  63.     ["minecraft:spruce_planks"] = {
  64.         [1]="minecraft:spruce_log",
  65.         count=4
  66.     },
  67.     ["minecraft:spruce_sign"] = {
  68.         [1]="minecraft:spruce_planks",
  69.         [2]="minecraft:spruce_planks",
  70.         [3]="minecraft:spruce_planks",
  71.         [4]="minecraft:spruce_planks",
  72.         [5]="minecraft:spruce_planks",
  73.         [6]="minecraft:spruce_planks",
  74.         [8]="minecraft:stick",
  75.         count=3
  76.     },
  77.     ["minecraft:stick"] = {
  78.         [1]="minecraft:spruce_planks",
  79.         [4]="minecraft:spruce_planks",
  80.         count = 4
  81.     },
  82.     ["computercraft:wired_modem"] = {
  83.         [1]="minecraft:stone",
  84.         [2]="minecraft:stone",
  85.         [3]="minecraft:stone",
  86.         [4]="minecraft:stone",
  87.         [5]="minecraft:redstone",
  88.         [6]="minecraft:stone",
  89.         [7]="minecraft:stone",
  90.         [8]="minecraft:stone",
  91.         [9]="minecraft:stone",
  92.         count = 1
  93.     },
  94.     ["computercraft:cable"] = {
  95.         [2]="minecraft:stone",
  96.         [4]="minecraft:stone",
  97.         [5]="minecraft:redstone",
  98.         [6]="minecraft:stone",
  99.         [8]="minecraft:stone",
  100.         count=6
  101.     }
  102. }
  103.  
  104. local storageConfigs = {
  105.     ["minecraft:chest_9"] = {
  106.         mode="supply"
  107.     },
  108.     ["minecraft:chest_10"] = {
  109.         mode="store",
  110.         storeMode="overflow",
  111.     },
  112.     ["minecraft:chest_11"] = {
  113.         mode="store",
  114.         storeMode="copy",
  115.     },
  116.     ["minecraft:chest_12"] = {
  117.         mode="store",
  118.         storeMode="destroy"
  119.     },
  120.     ["minecraft:chest_13"] = {
  121.         mode="provide",
  122.         provideMode="exact",
  123.         requests = {
  124.             ["minecraft:spruce_sign"]=5
  125.         }
  126.     },
  127.     ["turtle_3"] = {
  128.         mode="crafter",
  129.         craftChest="minecraft:chest_16"
  130.     },
  131.     ["minecraft:chest_14"] = {
  132.         mode="requestOutput"
  133.     },
  134.     ["minecraft:chest_15"] = {
  135.         mode="working"
  136.     },
  137.     ["turtle_1"] = {
  138.         mode="crafter",
  139.         craftChest="minecraft:chest_17"
  140.     },
  141.     ["minecraft:chest_18"] = {
  142.         mode="working"
  143.     }
  144. }
  145.  
  146. local function getItemCondition(name)
  147.     currentState = "Get item condition"
  148.     for itemName,conditions in pairs(itemConditions) do
  149.         if itemName == name then
  150.             return conditions
  151.         end
  152.     end
  153.    
  154.     return nil
  155. end
  156.  
  157. local function getItemRecipes(itemName)
  158.     local result = {}
  159.     for item,recipe in pairs(craftingRecipes) do
  160.         if item == itemName then
  161.             table.insert(result, recipe)
  162.         end
  163.     end
  164.     return result
  165. end
  166.  
  167. local allStores = {}
  168. local function calculateStoreContents(store)
  169.     store.counts = {}
  170.     currentState = "Calculate store contents"
  171.     for slot, item in pairs(store.peripheral.list()) do
  172.         if item ~= nil then
  173.             if store.counts[item.name] == nil then
  174.                 if store.mode == "copy" then
  175.                     store.counts[item.name] = item.count - 1
  176.                 else
  177.                     store.counts[item.name] = item.count
  178.                 end
  179.             else
  180.                 store.counts[item.name] = store.counts[item.name] + item.count
  181.             end
  182.         end
  183.     end
  184.    
  185.     return store
  186. end
  187.  
  188. local function createStore(peripheralName,config)
  189.     currentState = "Create store"
  190.     local displayName = peripheralName
  191.     if config.displayName ~= nil and string.len(config.displayName) > 0 then
  192.         displayName = config.displayName
  193.     end
  194.     local newStore = {
  195.         displayName = displayName,
  196.         peripheral = peripheral.wrap(peripheralName),
  197.         mode = config.storeMode,
  198.         counts = {}
  199.     }
  200.     newStore.canStoreItem = (function(name)
  201.             if config.storeMode == "destroy" then
  202.                 return true
  203.             elseif config.storeMode == "overflow" then
  204.                 return true
  205.             elseif config.storeMode == "copy" then
  206.                 if newStore.counts[name] ~= nil then
  207.                     return true
  208.                 else
  209.                     return false
  210.                 end
  211.             end
  212.         end)
  213.     if newStore.peripheral == nil then
  214.         error("Couldn't find peripheral "..peripheralName)
  215.     end
  216.    
  217.     newStore = calculateStoreContents(newStore)
  218.    
  219.     allStores[peripheralName] = newStore
  220. end
  221.  
  222. -- Get all possible stores for itemName
  223. local function getItemStores(itemName)
  224.     local result = {
  225.         stores = {},
  226.         overflows = {},
  227.         destroys = {}
  228.     }
  229.     for storeName, store in pairs(allStores) do
  230.         if store.canStoreItem(itemName) then
  231.             if store.mode == "copy" then
  232.                 result.stores[storeName] = store
  233.             elseif store.mode == "overflow" then
  234.                 result.overflows[storeName] = store
  235.             elseif store.mode == "destroy" then
  236.                 result.destroys[storeName] = store
  237.             end
  238.         end
  239.     end
  240.    
  241.     return result
  242. end
  243.  
  244. local allSupplies = {}
  245. local function createSupply(peripheralName,config)
  246.     currentState = "Create Supply"
  247.     local displayName = peripheralName
  248.     if config.displayName ~= nil and string.len(config.displayName) > 0 then
  249.         displayName = config.displayName
  250.     end
  251.     local newSupply = {
  252.         displayName = displayName,
  253.         peripheral = peripheral.wrap(peripheralName)
  254.     }
  255.     if newSupply.peripheral == nil then
  256.         error("Couldn't find peripheral "..peripheralName)
  257.     end
  258.     allSupplies[peripheralName] = newSupply
  259. end
  260.  
  261. local allProvides = {}
  262. local function createProvide(peripheralName, config)
  263.     currentState = "Create Provide"
  264.     local displayName = peripheralName
  265.     if config.displayName ~= nil and string.len(config.displayName) > 0 then
  266.         displayName = config.displayName
  267.     end
  268.     local newProvide = {
  269.         displayName = displayName,
  270.         peripheral = peripheral.wrap(peripheralName),
  271.         requests = config.requests,
  272.         mode = config.provideMode
  273.     }
  274.     if newProvide.peripheral == nil then
  275.         error("Couldn't find peripheral "..peripheralName)
  276.     end
  277.     allProvides[peripheralName] = newProvide
  278. end
  279.  
  280. local allCrafters = {}
  281. local function createCrafter(peripheralName, config)
  282.     currentState = "Create crafter"
  283.     local displayName = peripheralName
  284.     if config.displayName ~= nil and string.len(config.displayName) > 0 then
  285.         displayName = config.displayName
  286.     end
  287.     local newCrafter = {
  288.         displayName = displayName,
  289.         peripheral = peripheral.wrap(config.craftChest),
  290.         turtle = peripheral.wrap(peripheralName),
  291.         busy=false,
  292.         crafting=false
  293.     }
  294.     if newCrafter.peripheral == nil then
  295.         error("Couldn't find peripheral "..peripheralName)
  296.     end
  297.     if newCrafter.turtle == nil then
  298.         error("Coudn't find peripheral "..config.turtle)
  299.     end
  300.  
  301.     -- Power cycle turtle
  302.     -- This ensures it is clear before we start crafting
  303.     newCrafter.turtle.shutdown()
  304.     os.sleep(0.1)
  305.     newCrafter.turtle.turnOn()
  306.  
  307.     allCrafters[peripheralName] = newCrafter
  308. end
  309.  
  310. local allRequestOutputs = {}
  311. local function createRequestOutput(peripheralName, config)
  312.     currentState = "Create Request Output"
  313.     local displayName = peripheralName
  314.     if config.displayName ~= nil and string.len(config.displayName) > 0 then
  315.         displayName = config.displayName
  316.     end
  317.     local newRequestOutput = {
  318.         displayName = displayName,
  319.         peripheral = peripheral.wrap(peripheralName)
  320.     }
  321.     allRequestOutputs[peripheralName] = newRequestOutput
  322. end
  323.  
  324. local allWorking = {}
  325. local function createWorking(peripheralName, config)
  326.     currentState = "Create Working"
  327.     local displayName = peripheralName
  328.     if config.displayName ~= nil and string.len(config.displayName) > 0 then
  329.         displayName = config.displayName
  330.     end
  331.     local newWorking = {
  332.         displayName = displayName,
  333.         peripheral = peripheral.wrap(peripheralName),
  334.         busy=false
  335.     }
  336.     allWorking[peripheralName] = newWorking
  337. end
  338.  
  339. -- Put the requested item into the destination from
  340. -- the given sources.
  341. -- Returns the amount retrieved
  342. local function requestItemsToDestination(destination, itemName, itemCount, targetSlot)
  343.     local sources = getItemStores(itemName).stores
  344.     local remainingCount = itemCount
  345.     for sourceName, source in pairs(sources) do
  346.         for slot, item in pairs(source.peripheral.list()) do
  347.             if item.name == itemName then
  348.                 local maxPushCount = remainingCount
  349.                 if source.counts ~= nil and source.counts[itemName] < maxPushCount then
  350.                     maxPushCount = source.counts[itemName]
  351.                 end
  352.                 local pushCount = source.peripheral.pushItems(peripheral.getName(destination.peripheral), slot, maxPushCount, targetSlot)
  353.                 remainingCount = remainingCount - pushCount
  354.                 if source.counts ~= nil then
  355.                     source.counts[itemName] = source.counts[itemName] - pushCount
  356.                 end
  357.                 if remainingCount <= 0 then
  358.                     break
  359.                 end
  360.             end
  361.         end
  362.     end
  363.     return itemCount - remainingCount
  364. end
  365.  
  366. local function sendSlotToDestinations(source,destinations,slot,itemName,count)
  367.     local remainingCount = count
  368.     for destinationName, destination in pairs(destinations) do
  369.         local pushCount = source.peripheral.pushItems(destinationName, slot)
  370.         if source.counts ~= nil then
  371.             source.counts[itemName] = source.counts[itemName] - pushCount
  372.         end
  373.         if destination.counts ~= nil then
  374.             if destination.counts[itemName] == nil then
  375.                 destination.counts[itemName] = pushCount
  376.             else
  377.                 destination.counts[itemName] = destination.counts[itemName] + pushCount
  378.             end
  379.         end
  380.         remainingCount = remainingCount - pushCount
  381.         if remainingCount <= 0 then
  382.             break
  383.         end
  384.     end
  385.    
  386.     return remainingCount
  387. end
  388.  
  389. local function transferItems(source, destination, itemName, itemCount)
  390.     if source == nil or destination == nil or itemName == nil or itemCount == nil then
  391.         error("Transfer items, bad parameters")
  392.     end
  393.     local remainingCount = itemCount
  394.     for slot, item in pairs(source.peripheral.list()) do
  395.         if item.name == itemName then
  396.             local transferCount = source.peripheral.pushItems(peripheral.getName(destination.peripheral), slot, remainingCount)
  397.             if source.counts ~= nil then
  398.                 if source.counts[itemName] ~= nil then
  399.                     source.counts[itemName] = source.counts[itemName] - transferCount
  400.                 end
  401.             end
  402.             if destination.counts ~= nil then
  403.                 if source.counts[itemName] ~= nil then
  404.                     source.counts[itemName] = source.counts[itemName] + transferCount
  405.                 else
  406.                     source.counts[itemName] = transferCount
  407.                 end
  408.             end
  409.             remainingCount = remainingCount - transferCount
  410.             if remainingCount <= 0 then
  411.                 break
  412.             end
  413.         end
  414.     end
  415.  
  416.     return remainingCount <= 0
  417. end
  418.  
  419. local function transferAll(source, destination)
  420.     for slot, item in pairs(source.peripheral.list()) do
  421.             local transferCount = source.peripheral.pushItems(peripheral.getName(destination.peripheral), slot)
  422.             if source.counts ~= nil then
  423.                 if source.counts[item.name] ~= nil then
  424.                     source.counts[item.name] = source.counts[item.name] - transferCount
  425.                 end
  426.             end
  427.             if destination.counts ~= nil then
  428.                 if source.counts[item.name] ~= nil then
  429.                     source.counts[item.name] = source.counts[item.name] + transferCount
  430.                 else
  431.                     source.counts[item.name] = transferCount
  432.                 end
  433.             end
  434.     end
  435. end
  436.  
  437. function craftItem(workingChest, itemName, itemCount)
  438.     currentState = "Crafting item "..itemName.." "..itemCount
  439.     -- Find item recipe
  440.     -- Note: Later this should determine if another
  441.     -- recipe can be used
  442.     local recipes = getItemRecipes(itemName)
  443.     if recipes[1] == nil then
  444.         -- No crafting recipe
  445.         return false
  446.     end
  447.    
  448.     local recipe = recipes[1]
  449.    
  450.     -- Calculate requirements
  451.     local requirements = {}
  452.     for i=1,9,1 do
  453.         local requirement = recipe[i]
  454.         if requirement ~= nil then
  455.             if requirements[requirement] ~= nil then
  456.                 requirements[requirement] = 1 + requirements[requirement]
  457.             else
  458.                 requirements[requirement] = 1
  459.             end
  460.         end
  461.     end
  462.    
  463.     local craftCount = math.ceil(itemCount / recipe.count)
  464.     -- Get all requirements
  465.     for name,count in pairs(requirements) do
  466.         -- Get enough for total requirement
  467.         requirements[name] = math.ceil(count * craftCount)
  468.         if getOrCraftItem(workingChest, name, requirements[name], false, workingChest) == false then
  469.             return false
  470.         end
  471.     end
  472.    
  473.     -- Find a crafter to craft in
  474.     local crafterName, crafter
  475.     for name,craft in pairs(allCrafters) do
  476.         if craft.busy == false then
  477.             crafterName = name
  478.             crafter = craft
  479.         end
  480.     end
  481.    
  482.     -- Failure detection
  483.     -- Note: We should change the busy check
  484.     -- If we already have at least 1 crafter,
  485.     -- just wait until one is ready.
  486.     if crafter == nil then
  487.         error("No crafter found! All in use or none")
  488.     end
  489.    
  490.     -- Mark as busy before send
  491.     -- This ensures it keeps it
  492.     crafter.busy = true
  493.  
  494.     -- Clear crafting chest
  495.     transferAll(crafter, workingChest)
  496.    
  497.     -- Transfer requirements
  498.     currentState = "Transfering crafting requirements"
  499.     for requirement, requirementCount in pairs(requirements) do
  500.         print("Transfer",requirement,requirementCount)
  501.         if transferItems(workingChest, crafter, requirement, requirementCount) == false then
  502.             error("Working chest is missing items?!")
  503.         end
  504.     end
  505.    
  506.     for i=1,craftCount,1 do
  507.         -- Tell crafter to craft
  508.         crafter.crafting = true
  509.         rednet.send(crafter.turtle.getID(), { type="craft", message=recipe })
  510.        
  511.         -- Wait for craft to finish
  512.         while crafter.crafting == true do
  513.             currentState = "Crafting "..itemName.." #"..i.."/"..craftCount * recipe.count
  514.             os.sleep(1/20)
  515.         end
  516.     end
  517.  
  518.     -- Return results to working chest
  519.     transferAll(crafter, workingChest)
  520.  
  521.     crafter.busy = false
  522.  
  523.     return true
  524. end
  525.  
  526. function getOrCraftItem(destination, itemName, itemCount, clear, workingChest)
  527.     local provideChest;
  528.  
  529.     if workingChest == nil then
  530.         for _, working in pairs(allWorking) do
  531.             if working.busy == false then
  532.                 workingChest = working
  533.                 break
  534.             end
  535.         end
  536.     end
  537.  
  538.     for _, provide in pairs(allProvides) do
  539.         provideChest = provide
  540.         break
  541.     end
  542.  
  543.     if workingChest == nil or provideChest == nil then
  544.         error("Missing working or provide chest for get or craft operation")
  545.     end
  546.  
  547.     if clear == true then
  548.         workingChest.busy = true
  549.         transferAll(workingChest, provideChest)
  550.     end
  551.  
  552.     local count = requestItemsToDestination(workingChest, itemName, itemCount)
  553.  
  554.     -- If we already have enough, bail
  555.     if count >= itemCount then
  556.         transferItems(workingChest, destination, itemName, itemCount)
  557.         workingChest.busy = false
  558.         return true
  559.     end
  560.     -- Try crafting item instead
  561.     if craftItem(workingChest, itemName, itemCount) == true then
  562.         transferItems(workingChest, destination, itemName, itemCount)
  563.         if clear == true then
  564.             transferAll(workingChest, provideChest)
  565.             workingChest.busy = false
  566.         end
  567.         return true
  568.     end
  569.  
  570.     print("Failed get or craft",itemName,itemCount,"returning items")
  571.     if clear == true then
  572.         transferAll(workingChest, provideChest)
  573.         workingChest.busy = false
  574.     end
  575.  
  576.     return false
  577. end
  578.  
  579. local function handleItem(source, slot, itemName, itemCount)
  580.     local itemConditions = getItemCondition(itemName)
  581.     local itemStores = getItemStores(itemName)
  582.     local remainingItems = itemCount
  583.     -- If we don't want to keep this item
  584.     if itemConditions ~= nil and
  585.         itemConditions.keep ~= nil and
  586.         itemConditions.keep(
  587.             (function()
  588.                 return source.peripheral.getItemDetail(slot)
  589.             end)) == false then
  590.         -- Find a place to destroy
  591.         remainingItems = sendSlotToDestinations(source, itemStores.destroys, slot, itemName, remainingItems)
  592.         -- If we want to keep this item        
  593.     else
  594.         -- Try and put it away
  595.         remainingItems = sendSlotToDestinations(source, itemStores.stores, slot, itemName, remainingItems)
  596.         -- We have overflow
  597.         if remainingItems > 0 then
  598.             -- Should we throw away overflow
  599.             if itemConditions ~= nil and itemConditions.overflow ~= nil and itemConditions.overflow() == false then
  600.                 remainingItems = sendSlotToDestinations(source, itemStores.destroys, slot, itemName, remainingItems)    
  601.                 -- Overflow
  602.             else
  603.                 remainingItems = sendSlotToDestinations(source, itemStores.overflows, slot, itemName, remainingItems)
  604.                 -- Destroy
  605.                 if remainingItems > 0 then
  606.                     remainingItems = sendSlotToDestinations(source, itemStores.destroys, slot, itemName, remainingItems)
  607.                 end
  608.             end
  609.         end
  610.     end
  611.     return remainingItems
  612. end
  613.  
  614. local function handleSupplies()
  615.     for supplyName, supply in pairs(allSupplies) do
  616.         local itemsToSort = supply.peripheral.list()
  617.        
  618.         -- Sort each slot of supply inventory
  619.         for slot, item in pairs(itemsToSort) do
  620.             if item ~= nil then
  621.                 currentState = "Putting away "..item.name.." "..item.count
  622.                 handleItem(supply, slot, item.name, item.count)
  623.             end
  624.         end
  625.     end
  626. end
  627.  
  628. local function handleProvides()
  629.     for providerName, provider in pairs(allProvides) do
  630.         local counts = {}
  631.         for slot, item in pairs(provider.peripheral.list()) do
  632.             if counts[item.name] == nil then
  633.                 counts[item.name] = item.count
  634.             else
  635.                 counts[item.name] = counts[item.name] + item.count
  636.             end
  637.             if provider.mode == "exact" then
  638.                 if provider.requests[item.name] == nil then
  639.                     handleItem(provider, slot, item.name, item.count)
  640.                 elseif provider.requests[item.name] < counts[item.name] then
  641.                     handleItem(provider, slot, item.name, counts[item.name] - provider.requests[item.name])
  642.                 end
  643.             end
  644.         end
  645.         for requestName, requestCount in pairs(provider.requests) do
  646.             if counts[requestName] == nil then
  647.                 currentState = "Supplying "..requestName.." "..requestCount.." to "..provider.displayName
  648.                 requestItemsToDestination(provider, requestName, requestCount)
  649.             elseif counts[requestName] < requestCount then
  650.                 currentState = "Supplying "..requestName.." "..requestCount.." to "..provider.displayName
  651.                 requestItemsToDestination(provider, requestName, requestCount - counts[requestName])
  652.             end
  653.         end
  654.     end
  655. end
  656.  
  657. local requests = {}
  658. local function createRequest(itemName, itemCount)
  659.     requests[math.random(1,9999999)] = { name=itemName, count=itemCount }
  660. end
  661.  
  662. local function clearRequests()
  663.     requests = {}
  664. end
  665.  
  666. local function handleRequests()
  667.     for i,request in pairs(requests) do
  668.         requests[i] = nil
  669.         currentState = "Handling request "..request.name.." "..request.count
  670.         local requestOutput
  671.         for name, output in pairs(allRequestOutputs) do
  672.             requestOutput = output
  673.         end
  674.  
  675.         if requestOutput == nil then
  676.             error("Need request output to handle request")
  677.         end
  678.  
  679.         local success = getOrCraftItem(requestOutput, request.name, request.count, true)
  680.         print("Request finished", request.name, request.count, "success", success)
  681.         break
  682.     end
  683. end
  684.  
  685. local function sortLoop()
  686.     local crafterCount = 0
  687.     local workingCount = 0
  688.  
  689.     for _, crafter in pairs(allCrafters) do
  690.         crafterCount = crafterCount + 1
  691.     end
  692.     for _, working in pairs(allWorking) do
  693.         workingCount = workingCount + 1
  694.     end
  695.  
  696.     local maxParallelCrafts = math.min(crafterCount, workingCount)
  697.  
  698.     while true do
  699.         currentState = "Idle"
  700.         handleSupplies()
  701.         handleProvides()
  702.         if maxParallelCrafts <= 1 then
  703.             handleRequests()
  704.         elseif maxParallelCrafts <= 2 then
  705.             parallel.waitForAll(handleRequests, handleRequests)
  706.         elseif maxParallelCrafts <= 3 then
  707.             parallel.waitForAll(handleRequests, handleRequests, handleRequests)
  708.         end
  709.     end
  710. end
  711.  
  712. local monitor = peripheral.find("monitor")
  713.  
  714. local currentItemCategory = nil
  715. function uiLoop()
  716.     drawLib.clear()
  717.    
  718.     local cancelQueue = drawLib.createButton(51,2,27,2,"Cancel Queue",
  719.         (function()
  720.             clearRequests()
  721.             print("Cleared requests")
  722.         end),true)
  723.    
  724.     drawLib.addButton(cancelQueue)
  725.    
  726.     local categoryButtons = {}
  727.     local nextCategoryX = 0
  728.     for categoryName,category in pairs(itemCategories) do
  729.         local button = drawLib.createButton(nextCategoryX, 2, string.len(categoryName) + 2, 2, categoryName, nil, true)
  730.         button.action = function()
  731.             currentItemCategory = category
  732.             drawLib.clear()
  733.             drawLib.addButton(cancelQueue)
  734.             for catName,cat in pairs(categoryButtons) do
  735.                 drawLib.addButton(cat)
  736.             end
  737.             local itemCount = 1
  738.             for i,item in ipairs(currentItemCategory) do
  739.                 drawLib.addButton(drawLib.createButton(35,5+itemCount,0,0,"1", function()
  740.                     createRequest(item,1)
  741.                 end,true))
  742.                 drawLib.addButton(drawLib.createButton(37,5+itemCount,0,0,"8", function()
  743.                     createRequest(item,8)
  744.                 end,true))
  745.                 drawLib.addButton(drawLib.createButton(39,5+itemCount,1,0,"16", function()
  746.                     createRequest(item,16)
  747.                 end,true))
  748.                 drawLib.addButton(drawLib.createButton(42,5+itemCount,1,0,"32", function()
  749.                     createRequest(item,32)
  750.                 end,true))
  751.                 drawLib.addButton(drawLib.createButton(45,5+itemCount,1,0,"64", function()
  752.                     createRequest(item,64)
  753.                 end,true))
  754.                 itemCount = itemCount+1
  755.             end
  756.         end
  757.         nextCategoryX = nextCategoryX + string.len(categoryName) + 4
  758.         drawLib.addButton(button)
  759.         categoryButtons[categoryName] = button
  760.     end
  761.    
  762.     monitor.setCursorBlink(false)
  763.     monitor.setTextScale(0.5)
  764.    
  765.     while true do
  766.         monitor.setCursorPos(1,1)
  767.         monitor.setBackgroundColor(colors.black)
  768.         monitor.clear()
  769.         drawLib.render(monitor)
  770.         monitor.setCursorPos(1,1)
  771.         monitor.setBackgroundColor(colors.black)
  772.         monitor.setTextColor(colors.white)
  773.         monitor.write(currentState)
  774.        
  775.         -- Request queue
  776.         monitor.setCursorPos(55,1)
  777.         monitor.write("Request Queue")
  778.         local requestCounter = 1
  779.         for i,request in pairs(requests) do
  780.             monitor.setCursorPos(51,requestCounter+5)
  781.             requestCounter = requestCounter + 1
  782.             monitor.write("["..i.."] "..request.name.." "..request.count)
  783.         end
  784.         -- Item category display
  785.         if currentItemCategory ~= nil then
  786.             for i,item in ipairs(currentItemCategory) do
  787.                 local count = 0
  788.                 local stores = getItemStores(item)
  789.                 for storeName,store in pairs(stores.stores) do
  790.                     if store.counts[item] then
  791.                         count = count + store.counts[item]
  792.                     end
  793.                 end
  794.                 monitor.setCursorPos(1,5 + i)
  795.                 monitor.write(item.." "..count)
  796.             end
  797.         end
  798.        
  799.         -- 10hz update should be fine
  800.         os.sleep(0.1)
  801.     end
  802. end
  803.  
  804. local function net(id, msg, protocol)
  805.     -- Handle crafter notifications
  806.     -- Used to identify busy crafters
  807.     if msg.type == "crafter" then
  808.         for _,crafter in pairs(allCrafters) do
  809.             if crafter.turtle.getID() == id then
  810.                 if msg.message == "craftFinished" then
  811.                     crafter.crafting = false
  812.                 end
  813.             end
  814.         end
  815.     end
  816. end
  817.  
  818. local function eventLoop()
  819.     while true do
  820.         local event, n, x, y = os.pullEvent()
  821.         if event == "monitor_touch" then
  822.             drawLib.onClick(x,y,2)
  823.         elseif event == "rednet_message" then
  824.             net(n,x,y)
  825.         end
  826.     end
  827. end
  828.  
  829. local function initialize()
  830.     currentState = "Initialize"
  831.     monitor.clear()
  832.     monitor.setCursorPos(1,1)
  833.     monitor.setTextColor(colors.white)
  834.     monitor.setBackgroundColor(colors.black)
  835.     monitor.write("Initializing... Please wait")
  836.     allStores = {}
  837.     allSupplies = {}
  838.     allProvides = {}
  839.     allCrafters = {}
  840.     for peripheralName,config in pairs(storageConfigs) do
  841.         if config.mode == "store" then
  842.             createStore(peripheralName, config)
  843.         elseif config.mode == "supply" then
  844.             createSupply(peripheralName, config)
  845.         elseif config.mode == "provide" then
  846.             createProvide(peripheralName, config)
  847.         elseif config.mode == "crafter" then
  848.             createCrafter(peripheralName, config)
  849.         elseif config.mode == "requestOutput" then
  850.             createRequestOutput(peripheralName, config)
  851.         elseif config.mode == "working" then
  852.             createWorking(peripheralName, config)
  853.         end
  854.     end
  855.  
  856.     -- Ensure all systems are initialized and stable!
  857.     -- Primarily for crafters
  858.     os.sleep(6)
  859.  
  860.     parallel.waitForAny(sortLoop, uiLoop, eventLoop)
  861. end
  862.  
  863. initialize()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement