Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --crafts items per request
- --requests are made by the stockpile brain
- --change this to your turtle's name
- local target = "turtle_unconfigured"
- --save with ctrl s
- --exit with ctrl e
- -----------------------------------
- if target == "turtle_unconfigured" then
- term.clear()
- term.setCursorPos(1,1)
- print("Please add name of turtle!")
- sleep(2)
- shell.run("edit", "startup")
- os.reboot()
- end
- --initialize
- local craftingRecipes = {}
- local file = fs.open("craftingRecipes", "r")
- local recipeNames = {}
- mainItem = true
- if fs.exists("scrollItems") == false then
- shell.run("pastebin", "get", "s1F8FVrJ", "scrollItems")
- end
- if fs.exists("recipeRecorder") == false then
- shell.run("pastebin", "get", "JvsrKViR", "recipeRecorder")
- end
- if fs.exists("API") == false then
- shell.run("pastebin", "get", "EzkfU5ZM", "API")
- end
- shaka = require("API")
- avSlots = {5, 6, 7, 9, 10, 11, 13, 14, 15, 16}
- ---load recipes
- if file then
- craftingRecipes = textutils.unserialize(file.readAll())
- file.close()
- end
- for k, v in pairs(craftingRecipes) do
- table.insert(recipeNames, k)
- end
- -- Connect peripherals
- local sides = {"left", "right", "top", "bottom", "front", "back"}
- for i, side in ipairs(sides) do
- local device = peripheral.getType(side)
- if device == "modem" then
- modem = peripheral.wrap(side)
- if modem.isWireless() then
- wirelessModem = peripheral.wrap(side)
- rednet.open(side)
- else
- wiredModem = peripheral.wrap(side)
- rednet.close(side)
- end
- elseif device == "monitor" then
- monitor = peripheral.wrap(side)
- end
- end
- --initialize inventories
- targetInv = peripheral.wrap(target)
- function tableContains(t, item)
- for _, value in pairs(t) do
- if value == item then
- return true
- end
- end
- return false
- end
- --get computer id of brain
- if not fs.exists("brainID") then
- rednet.broadcast("wassap", "giefIDplz")
- local sender, msg, protocol = rednet.receive("disBeID", 1)
- if msg then
- shaka.writeFile("brainID", sender)
- -- os.reboot()
- else
- term.clear()
- term.setTextColor(colors.orange)
- shaka.centerText("No Brain available!", 5)
- term.setTextColor(colors.yellow)
- shaka.centerText("Are you sure it is turned on?", 7)
- os.pullEvent("key")
- os.reboot()
- end
- end
- brain = shaka.readFile("brainID")
- function getInventories()
- fromInventories = {}
- if fs.exists("inventories") then
- fromInventories = shaka.readFile("inventories")
- end
- local inventories = wiredModem.getNamesRemote()
- for _, inventoryName in ipairs(inventories) do
- if shaka.stringFind(inventoryName, "turtle") == false and inventoryName ~= nil and shaka.stringFind(inventoryName, "computer") == false then
- if not tableContains(fromInventories, inventoryName) then
- -- print(fromInventories[inventoryName], inventoryName)
- -- sleep(1)
- table.insert(fromInventories, inventoryName)
- end
- end
- end
- shaka.writeFile("inventories", fromInventories)
- end
- getInventories()
- local function scanInventory(itemName) -- returns the total amount of a certain item in all inventories
- local items = {}
- local tasks = {}
- local tasks2 = {}
- local invCounts = {}
- local filteredInventories = {}
- for i = 1, #fromInventories do
- tasks[#tasks+1] = function()
- local invWrap = peripheral.wrap(fromInventories[i])
- if invWrap == nil then
- return -- skip this inventory and move on to the next one
- else
- table.insert(filteredInventories, fromInventories[i])
- end
- local invCount = 0
- for k, v in pairs(invWrap.list()) do
- tasks2[#tasks2+1] = function()
- if v.name == itemName then
- invCount = invCount + v.count
- end
- end
- end
- parallel.waitForAll(unpack(tasks2))
- invCounts[fromInventories[i]] = invCount
- tasks2 = {} -- clear tasks2 after each inventory
- end
- end
- parallel.waitForAll(unpack(tasks))
- shaka.writeFile("inventories", filteredInventories)
- fromInventories = shaka.readFile("inventories")
- for i = 1, #fromInventories do
- if invCounts[fromInventories[i]] ~= nil then
- items[itemName] = (items[itemName] or 0) + invCounts[fromInventories[i]]
- end
- end
- return items[itemName] or 0
- end
- function findAndMoveItems(itemToSearch, toInventory, toInventorySlot, count)
- local searchSuccess = false
- local searchers = {}
- local itemsMoved = 0 -- keep track of how many items have been moved so far
- for i = 1, #fromInventories do
- searchers[i] = function()
- local invWrap = peripheral.wrap(fromInventories[i])
- for slot, item in pairs(invWrap.list()) do
- if item.name == itemToSearch then
- local availableCount = item.count
- if availableCount >= count - itemsMoved then
- local movedItem = invWrap.pushItems(toInventory, slot, count - itemsMoved, toInventorySlot)
- if movedItem > 0 then
- itemsMoved = itemsMoved + movedItem -- update itemsMoved
- if itemsMoved == count then
- searchSuccess = true
- break
- end
- end
- end
- end
- end
- end
- end
- for _, searcher in ipairs(searchers) do
- parallel.waitForAny(searcher)
- if searchSuccess then
- break
- end
- end
- end
- function requestAndSortItems(craftingRequest)
- local recipeName = craftingRequest
- local recipe = craftingRecipes[recipeName]
- local keyCount = recipe.keyCount
- if makeSureItemsAvailable(recipeName) == false then
- return false
- end
- local tasks = {}
- for ingredient, ingredientData in pairs(recipe) do
- if ingredient ~= "keyCount" then
- for j, data in ipairs(ingredientData) do
- tasks[#tasks+1] = function()
- findAndMoveItems(ingredient, target, data.slot, 1)
- end
- end
- end
- end
- parallel.waitForAll(unpack(tasks))
- return true
- end
- function split(s, delimiter)
- result = {};
- for match in (s..delimiter):gmatch("(.-)"..delimiter) do
- table.insert(result, match);
- end
- return result;
- end
- function findAvailableDrop(slot)
- local tasks = {}
- for i = 1, #fromInventories do
- local invWrap = peripheral.wrap(fromInventories[i])
- tasks[#tasks+1] = function()
- invWrap.pullItems(target, slot)
- end
- end
- parallel.waitForAll(unpack(tasks))
- end
- function dropInventory()
- local tasks = {}
- for i = 1, 16 do
- if turtle.getItemCount(i) > 0 then
- tasks[#tasks+1] = function()
- repeat
- findAvailableDrop(i)
- until turtle.getItemCount(i) == 0
- end
- end
- end
- parallel.waitForAll(unpack(tasks))
- end
- function broadcastItems(craftingRecipes) --- informs brain about all available crafting recipes
- for itemName, itemData in pairs(craftingRecipes) do
- rednet.broadcast("saveItem " ..itemName, "stockpileupdate")
- end
- print("All recipes transmitted to Stockpile Brain.")
- end
- function getRecipeIngredients(recipeName, craftingRecipes)
- local ingredients = {}
- local recipe = craftingRecipes[recipeName]
- for ingredientName, ingredientData in pairs(recipe) do
- if ingredientName ~= "keyCount" then
- for i, ingredient in ipairs(ingredientData) do
- ingredients[ingredientName] = (ingredients[ingredientName] or 0) + ingredient.count
- end
- end
- end
- return ingredients
- end
- function isItemAvailableAsRecipe(recipes, itemName)
- for recipeName, recipe in pairs(recipes) do
- if recipeName == itemName then
- return true
- end
- end
- return false
- end
- function getKeyCount(itemName)
- local recipe = craftingRecipes[itemName]
- if recipe ~= nil then
- for ingredientName, ingredientData in pairs(recipe) do
- if ingredientName == "keyCount" then
- return ingredientData
- end
- end
- else
- monitor.setTextScale(0.5)
- monitor.setBackgroundColor(colors.red)
- monitor.setTextColor(colors.black)
- monitor.clear()
- monitor.setCursorPos(1,1)
- monitor.write("Recipe for " ..itemName)
- monitor.setCursorPos(1,2)
- monitor.write("is not known to me.")
- monitor.setCursorPos(1, 4)
- monitor.write("Please teach me or stop requesting.")
- shell.run("recipeRecorder")
- end
- end
- function makeSureItemsAvailable(item)
- local wantedItem = getRecipeIngredients(item, craftingRecipes)
- for key, value in pairs(wantedItem) do
- message = scanInventory(key)
- if tonumber(message) < value then
- return false
- end
- end
- return true
- end
- function askItemAvailability(item)
- local wantedItem = getRecipeIngredients(item, craftingRecipes)
- for key, value in pairs(wantedItem) do
- canItemBeCrafted = isItemAvailableAsRecipe(craftingRecipes, key)
- message = scanInventory(key)
- if tonumber(message) >= value then
- --skip
- elseif canItemBeCrafted == true then
- numberOfMissing = value - tonumber(message)
- local keyCount = getKeyCount(key)
- nextLine()
- monitor.setTextColor(colors.orange)
- monitor.setTextColor(colors.green)
- monitor.setCursorPos(1, 4)
- monitor.clearLine()
- monitor.write("Missing ingredients:")
- nextLine()
- monitor.clearLine()
- screenKey = string.match(key, ":(.*)")
- screenKey = string.gsub(screenKey, "_", " ")
- monitor.write("Crafting " ..screenKey.. ".")
- if mainItem == true then
- missingMainItem = math.ceil(numberOfMissing/keyCount)
- end
- start = 1
- craftReps = math.ceil(missingMainItem/keyCount)
- for i = start, craftReps do
- if requestAndSortItems(key) == false then
- mainItem = false
- askItemAvailability(key)
- break
- else
- mainItem = true
- end
- turtle.craft()
- dropInventory()
- break
- end
- else
- clearScreen()
- term.clear()
- term.setCursorPos(1,1)
- term.setTextColor(colors.red)
- monitor.setTextColor(colors.yellow)
- monitor.write(key)
- nextLine()
- monitor.setTextColor(colors.red)
- monitor.write("not available.")
- nextLine()
- nextLine()
- monitor.write("Can't craft ")
- nextLine()
- monitor.setTextColor(colors.yellow)
- monitor.write(item.. ".")
- -- get the width and height of the monitor
- local monitorWidth, monitorHeight = monitor.getSize()
- -- calculate the necessary dimensions for the window
- local textWidth = string.len(key.. " missing!") + 2 -- add 2 to account for padding
- local textHeight = 1
- local windowWidth = math.min(textWidth, monitorWidth)
- local windowHeight = math.min(textHeight, monitorHeight)
- local windowX = 1
- local windowY = 7
- -- create the window
- local my_window = window.create(monitor, windowX, windowY, windowWidth, windowHeight)
- my_window.setBackgroundColor(colors.red)
- my_window.setTextColor(colors.black)
- my_window.clear()
- my_window.setCursorPos(1,1)
- my_window.write(key.. " missing!")
- print("Item\n"..key.."\nnot available to craft\n" ..item.. ".")
- sleep(1)
- break
- end
- end
- end
- function nextLine()
- x, y = monitor.getCursorPos()
- monitor.setCursorPos(1, y + 1)
- end
- function clearScreen()
- monitor.setCursorPos(1, 1)
- monitor.clear()
- end
- function keyExists(table, key)
- for k, v in pairs(table) do
- if k == key then
- return true
- end
- end
- return false
- end
- function finishIt(itemToCraft)
- if keyExists(craftingRecipes, itemToCraft) == false then
- clearScreen()
- monitor.setTextColor(colors.red)
- monitor.write("No recipe saved for")
- nextLine()
- monitor.write(itemToCraft)
- event, key = os.pullEvent("key")
- os.reboot()
- end
- monitor.setCursorPos(1,1)
- monitor.clearLine()
- monitor.setTextColor(colors.yellow)
- monitor.write("Crafting ")
- screenItem = string.match(itemToCraft, ":(.*)")
- screenItem = string.gsub(screenItem, "_", " ")
- monitor.setTextColor(colors.lightBlue)
- local keyInfoz = getKeyCount(itemToCraft)
- monitor.write(screenItem.. ": " ..craftTracker * keyInfoz)
- local craftPercent = 100 - math.ceil((craftTracker / math.ceil(countToCraft/divideBy)) * 100)
- displayLoadingBar(monitor, craftPercent)
- askItemAvailability(itemToCraft) --<-------------
- if makeSureItemsAvailable(itemToCraft) == true then
- monitor.setCursorPos(1, 4)
- monitor.clearLine()
- monitor.setTextColor(colors.green)
- monitor.write("Crafting requested item.")
- nextLine()
- monitor.clearLine()
- requestAndSortItems(itemToCraft)
- if turtle.craft() then
- local item = turtle.getItemDetail(1)
- if item ~= nil and item.name == itemToCraft then
- finishedForReal = true
- craftTracker = craftTracker - 1
- else
- finishedForReal = false
- end
- end
- dropInventory()
- else
- finishIt(itemToCraft)
- end
- end
- function displayLoadingBar(monitor, percent)
- monitor.setTextColor(colors.gray)
- local width = monitor.getSize()
- local barWidth = math.min(math.floor(width * percent / 100), width - 2)
- if percent >= 80 then
- monitor.setTextColor(colors.lime)
- elseif percent >= 70 then
- monitor.setTextColor(colors.green)
- elseif percent >= 40 then
- monitor.setTextColor(colors.yellow)
- elseif percent >= 15 then
- monitor.setTextColor(colors.orange)
- else
- monitor.setTextColor(colors.red)
- end
- monitor.setCursorPos(1,8)
- monitor.write("[")
- for i=1,barWidth do
- monitor.write("=")
- end
- for i=barWidth+1,width-2 do
- monitor.write(" ")
- end
- monitor.write("]")
- monitor.setCursorPos(1, 9)
- monitor.write(tostring(math.floor(percent)) .. "%")
- end
- function deleteRecipe(name)
- term.clear()
- term.setCursorPos(1,1)
- term.setTextColor(colors.white)
- for itemName, recipe in pairs(craftingRecipes) do
- -- print(itemName)
- if string.find(itemName, name) then
- term.setTextColor(colors.red)
- print("Final confirmation for:\n")
- term.setTextColor(colors.white)
- print(itemName .. ".\n")
- term.setTextColor(colors.orange)
- print("\nDelete? (y/n)\n")
- local response = io.read()
- if response == "y" then
- craftingRecipes[itemName] = nil
- file = fs.open("craftingRecipes", "w")
- file.write(textutils.serialize(craftingRecipes))
- file.close()
- term.setTextColor(colors.red)
- local id = os.getComputerID()
- local msg = table.concat({id, itemName, "0"}, " ")
- rednet.send(brain, msg, "tableChange")
- local sender, message, protocol = rednet.receive("tableConfirm", 1)
- if message then
- print("\nDeleted on brain and turtle.")
- else
- print("\nRecipe deleted on turtle only.")
- end
- sleep(2)
- os.reboot()
- else
- term.setTextColor(colors.green)
- print("Deletion cancelled.")
- sleep(1)
- os.reboot()
- end
- end
- end
- print("No recipe found with the given name.")
- end
- function search_item(item, tableName)
- term.clear()
- term.setCursorPos(1,1)
- term.setTextColor(colors.lightGray)
- local file = fs.open("craftingRecipes", "r")
- if file then
- craftingRecipes = textutils.unserialize(file.readAll())
- file.close()
- end
- local matches = {}
- for key, value in pairs(tableName) do
- if string.find(key, item) then
- table.insert(matches, key)
- end
- end
- if #matches == 0 then
- print("Item not found.")
- sleep(1)
- os.reboot()
- return nil
- elseif #matches == 1 then
- deleteRecipe(matches[1])
- return value
- else
- term.setTextColor(colors.white)
- print("Multiple items match the search criteria:")
- term.setTextColor(colors.lightGray)
- for i, match in ipairs(matches) do
- print(i .. ". " .. match)
- end
- term.setTextColor(colors.orange)
- print("Which item would you like to delete? (Enter the number)")
- local choice = tonumber(read())
- if choice and matches[choice] then
- deleteRecipe(matches[choice])
- os.reboot()
- return tableName[matches[choice]]
- else
- term.setTextColor(colors.red)
- print("Invalid choice.")
- sleep(1)
- os.reboot()
- return nil
- end
- end
- end
- function craftstuff()
- if protocol == "stockpile" then
- monitor.setTextScale(0.5)
- availableItems = {}
- dropInventory()
- finishIt(itemToCraft)
- dropInventory()
- end
- end
- function enterKey()
- term.clear()
- term.setCursorPos(1,1)
- term.setTextColor(colors.lightGray)
- print("Enter name of item to search for:\n")
- term.setTextColor(colors.lime)
- searchedItem = read()
- searchedItem = string.gsub(searchedItem, "%s", "")
- if searchedItem ~= "" then
- search_item(searchedItem, craftingRecipes)
- else
- term.setTextColor(colors.red)
- print("Search can't be empty. Try again.")
- sleep(1)
- enterKey()
- end
- end
- function centerText(monitor, y, text)
- local w, h = monitor.getSize()
- local x = math.floor((w - string.len(text) + 2) / 2)
- monitor.setCursorPos(x , y)
- print(text)
- end
- function manualSortTable(t)
- local selected = 1
- local quit = false
- while not quit do
- -- clear screen and print current state of table
- term.clear()
- term.setCursorPos(1, 1)
- shaka.changeColors(colors.gray, colors.white)
- term.clearLine()
- print("Deselect[Enter], Save['S'], Reset['R']")
- shaka.changeColors(colors.black, colors.white)
- term.setCursorPos(1, 3)
- for i, v in ipairs(t) do
- if i == selected then
- term.setBackgroundColor(colors.yellow)
- term.setTextColor(colors.black)
- print(i.."> " .. v)
- term.setBackgroundColor(colors.black)
- term.setTextColor(colors.white)
- else
- print(i.." " .. v)
- end
- end
- -- wait for user input
- local event, key = os.pullEvent("key")
- if key == keys.enter then
- if selected ~= nil then
- while selected do
- -- redraw the table with the current selection
- term.clear()
- term.setCursorPos(1, 1)
- shaka.changeColors(colors.gray, colors.white)
- term.clearLine()
- print("Select[Enter], Save['S'], Reset['R']")
- shaka.changeColors(colors.black, colors.white)
- term.setCursorPos(1, 3)
- for i, v in ipairs(t) do
- if i == selected then
- term.setBackgroundColor(colors.black)
- term.setTextColor(colors.yellow)
- print(i.."> " .. v)
- term.setTextColor(colors.white)
- else
- print(i.." " .. v)
- end
- end
- -- wait for user input to move the selection
- local event2, key2 = os.pullEvent("key")
- if key2 == keys.up then
- if selected > 1 then
- selected = selected - 1
- end
- elseif key2 == keys.down then
- if selected < #t then
- selected = selected + 1
- end
- elseif key2 == keys.enter then
- -- break out of the selection loop
- break
- elseif key2 == keys.s then
- return
- elseif key2 == keys.r then
- fs.delete("inventories")
- getInventories()
- manualSortTable(fromInventories)
- return
- end
- end
- end
- elseif key == keys.up then
- -- move selection up
- if selected and selected > 1 then
- t[selected], t[selected - 1] = t[selected - 1], t[selected]
- selected = selected - 1
- end
- elseif key == keys.down then
- -- move selection down
- if selected and selected < #t then
- t[selected], t[selected + 1] = t[selected + 1], t[selected]
- selected = selected + 1
- end
- elseif key == keys.s then
- -- quit the function
- quit = true
- elseif key == keys.r then
- fs.delete("inventories")
- getInventories()
- manualSortTable(fromInventories)
- return
- end
- end
- end
- function showMenuOptions()
- term.clear()
- term.setCursorPos(1,1)
- shaka.changeColors(colors.lightGray, colors.black)
- term.clearLine()
- print("'Enter' to search for items.\n")
- shaka.changeColors(colors.black, colors.white)
- print("'C' to save a new crafting recipe.\n")
- term.setTextColor(colors.gray)
- print("'U' to send all known recipes to brain.\n")
- print("'O' to change the access order of connected inventories.")
- end
- showMenuOptions()
- while true do
- monitor.setTextScale(1)
- monitor.setBackgroundColor(colors.black)
- clearScreen()
- monitor.setTextColor(colors.gray)
- monitor.write("Currently waiting")
- nextLine()
- monitor.write("for requests.")
- eventData = {os.pullEvent()}
- event = eventData[1]
- key = eventData[2] -- computer id
- message = eventData[3]
- protocol = eventData[4]
- if event == "rednet_message" and key == brain then
- if protocol == "stockpile" then
- split(message, " ")
- itemToCraft = tostring(result[1])
- countToCraft = tonumber(result[2])
- wantedTotalCount = tonumber(result[3])
- divideBy = getKeyCount(itemToCraft)
- craftTracker = math.ceil(countToCraft/divideBy)
- term.clear()
- term.setCursorPos(1, 1)
- centerText(term, 5, "Menu currently not available.")
- centerText(term, 6, "Busy doing stuff.")
- for i = 1, math.ceil(countToCraft/divideBy) do
- craftstuff()
- if scanInventory(itemToCraft) >= wantedTotalCount then
- break
- end
- end
- showMenuOptions()
- end
- elseif event == "key" then
- monitor.setTextScale(1)
- clearScreen()
- monitor.setTextColor(colors.gray)
- monitor.write("Idling.")
- nextLine()
- monitor.clearLine()
- if key == keys.s then
- shell.run("scrollItems")
- elseif key == keys.c then
- shell.run("recipeRecorder")
- elseif key == keys.u then
- broadcastItems(craftingRecipes)
- elseif key == keys.enter then
- enterKey()
- elseif key == keys.o then
- manualSortTable(fromInventories)
- shaka.writeFile("inventories", fromInventories)
- os.reboot()
- end
- elseif event == "mouse_click" then
- if protocol == 1 then
- enterKey()
- elseif protocol == 100 then
- shell.run("scrollItems")
- elseif protocol == 3 then
- shell.run("recipeRecorder")
- elseif protocol == 5 then
- broadcastItems(craftingRecipes)
- elseif protocol == 7 or protocol == 8 then
- manualSortTable(fromInventories)
- shaka.writeFile("inventories", fromInventories)
- os.reboot()
- end
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement