Shaka01

recipeRecorder 2024 - dependancy download

Dec 3rd, 2024 (edited)
38
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 13.24 KB | None | 0 0
  1. -- Recipe Recorder Program with Graphical Display and Duplicate Check
  2. local turtleName = "turtle_2"
  3. local fromInventories = {}
  4. -- Load API
  5. if not fs.exists("API") then
  6.     shell.run("pastebin", "get", "EzkfU5ZM", "API")
  7. end
  8. shaka = require("API")
  9. fromInventories = shaka.readFile("inventories")
  10. -- Fixed slots
  11. local inputSlots = {5, 6, 7, 9, 10, 11, 13, 14, 15}
  12. local outputSlot = 16
  13. local readyToGo = false
  14. local errorCheck = false
  15. local filename = "items_list.lua"
  16. local duplicates = false
  17.  
  18. -- Function to check if a table contains a value
  19. local function containsValue(tbl, value)
  20.     for _, v in ipairs(tbl) do
  21.         if v == value then
  22.             return true
  23.         end
  24.     end
  25.     return false
  26. end
  27.  
  28. local function getInventories()
  29.     if not wiredModem then
  30.         print("No wired modem detected. Cannot fetch inventories.")
  31.         return
  32.     end
  33.  
  34.     local remotePeripherals = wiredModem.getNamesRemote()
  35.     for _, inventoryName in ipairs(remotePeripherals) do
  36.         if inventoryName and not shaka.stringFind(inventoryName, "turtle") and not shaka.stringFind(inventoryName, "computer") then
  37.             if not tableContains(fromInventories, inventoryName) then
  38.                 table.insert(fromInventories, inventoryName)
  39.             end
  40.         end
  41.     end
  42.     shaka.writeFile("inventories", fromInventories)
  43. end
  44. getInventories()
  45. -- Function to read the state of the slots
  46. local function getSlotStates()
  47.     local states = {}
  48.     for slot = 1, 16 do
  49.         states[slot] = turtle.getItemDetail(slot) ~= nil
  50.     end
  51.     return states
  52. end
  53.  
  54. -- Function to read the list from the file
  55. local function readList()
  56.     local list = {}
  57.     if fs.exists(filename) then
  58.         local file = fs.open(filename, "r")  -- Open file in read mode
  59.         local content = file.readAll()  -- Read the content of the file
  60.         file.close()
  61.  
  62.         -- Check if content is valid
  63.         if content then
  64.             -- Deserialize the content into a Lua table
  65.             local success, result = pcall(load("return " .. content))
  66.             if success and type(result) == "table" then
  67.                 list = result  -- Assign the loaded table to 'list'
  68.                 print("List loaded successfully.")  -- Debugging line
  69.             else
  70.                 print("Error: Loaded content is not a valid table.")  -- Debugging line
  71.             end
  72.         end
  73.     else
  74.         print("File not found.")  -- Debugging line if file doesn't exist
  75.     end
  76.     return list
  77. end
  78.  
  79. -- Adjusted function to make the grid fit better
  80. local function drawDisplay(states)
  81.     term.clear()
  82.     term.setCursorPos(1, 1)
  83.  
  84.     -- Define grid layout with 1 row per slot
  85.     local grid = {
  86.         {1, 2, 3, 4},
  87.         {5, 6, 7, 8},
  88.         {9, 10, 11, 12},
  89.         {13, 14, 15, 16},
  90.     }
  91.  
  92.     local squareSize = 3        -- Square size reduced to 3 for better fit
  93.     local columnSpacing = 1     -- Small space between columns
  94.     local rowSpacing = 0        -- Reduced space between rows to 0 for a tighter fit
  95.  
  96.     -- Draw the grid with small spacing
  97.     for rowIndex, row in ipairs(grid) do
  98.         for colIndex, slot in ipairs(row) do
  99.             local x = (colIndex - 1) * (squareSize + columnSpacing) + 2
  100.             local y = (rowIndex - 1) * (squareSize + rowSpacing) + 2
  101.  
  102.             term.setCursorPos(x, y)
  103.  
  104.             -- Determine square color
  105.             if containsValue(inputSlots, slot) then
  106.                 term.setBackgroundColor(states[slot] and colors.green or colors.lightGray)
  107.             elseif slot == outputSlot then
  108.                 term.setBackgroundColor(states[slot] and colors.cyan or colors.orange)
  109.             else
  110.                 term.setBackgroundColor(states[slot] and colors.red or colors.gray)
  111.             end
  112.  
  113.             -- Draw the square (3 spaces wide and tall)
  114.             term.write(string.rep(" ", squareSize)) -- 3 spaces wide for the square
  115.             term.setCursorPos(x, y + 1)
  116.             term.write(string.rep(" ", squareSize)) -- 3 spaces tall for the square
  117.             term.setBackgroundColor(colors.black) -- Reset color
  118.         end
  119.     end
  120.  
  121.     -- Move the explanation back to the bottom
  122.     term.setCursorPos(22, 11)
  123.     term.setTextColor(colors.cyan)
  124.     write("Input")
  125.     term.setCursorPos(22, 12)  -- Position the explanation at the bottom
  126.     term.setTextColor(colors.blue)
  127.     write("Output")
  128.    
  129.     term.setCursorPos(22, 3)
  130.     term.setTextColor(colors.green)
  131.     write("C to save recipe")  
  132.  
  133.     term.setCursorPos(22, 5)
  134.     term.setTextColor(colors.orange)
  135.     write("Q to quit") 
  136. end
  137.  
  138.  
  139.  
  140.  
  141.  
  142. -- Function to load existing recipes
  143. local function loadRecipes(filePath)
  144.     if fs.exists(filePath) then
  145.         local file = fs.open(filePath, "r")
  146.         local content = file.readAll()
  147.         file.close()
  148.         if content and content ~= "" then
  149.             return textutils.unserialize(content) or {}
  150.         end
  151.     end
  152.     return {}
  153. end
  154.  
  155. -- Function to check for duplicate recipes
  156. local function isDuplicateRecipe(outputItem, recipes)
  157.     for _, recipe in ipairs(recipes) do
  158.         local existingOutput = recipe.output[1]
  159.         if existingOutput.name == outputItem.name and existingOutput.count == outputItem.count then
  160.             return true
  161.         end
  162.     end
  163.     return false
  164. end
  165.  
  166. -- Function to record a crafting recipe
  167. local function recordRecipe(inputItems, outputItem)
  168.     local recipe = {
  169.         input = inputItems,
  170.         output = {
  171.             {
  172.                 name = outputItem.name,
  173.                 count = outputItem.count,
  174.             },
  175.         },
  176.     }
  177.  
  178.     -- File path for recipes
  179.     local filePath = "recipes/recipes.lua"
  180.  
  181.     -- Load existing recipes
  182.     local recipes = loadRecipes(filePath)
  183.  
  184.     -- Check for duplicates
  185.     if isDuplicateRecipe(outputItem, recipes) then
  186.         shaka.clearScreen()
  187.         term.setTextColor(colors.red)
  188.         print("This recipe already exists.\nSkipping save.")
  189.         sleep(1)
  190.         drawDisplay(getSlotStates())
  191.         duplicates = true
  192.         return
  193.     end
  194.  
  195.     -- Add the new recipe to the recipes table
  196.     table.insert(recipes, recipe)
  197.  
  198.     -- Save the updated recipes back to the file
  199.     local file = fs.open(filePath, "w")
  200.     file.write(textutils.serialize(recipes))
  201.     file.close()
  202.     -- shaka.clearScreen()
  203.     -- print("Recipe saved for "..outputItem.name)
  204.     -- sleep(1)
  205.     -- drawDisplay(getSlotStates())
  206. end
  207.  
  208. -- Function to read items from fixed slots
  209. local function getInputItems()
  210.     local inputItems = {}
  211.     for _, slot in ipairs(inputSlots) do
  212.         local item = turtle.getItemDetail(slot)
  213.         if item then
  214.             table.insert(inputItems, {slot = slot, name = item.name})
  215.         else
  216.             table.insert(inputItems, {slot = slot, type = "empty"})
  217.         end
  218.     end
  219.     return inputItems
  220. end
  221.  
  222. -- Function to read item from the fixed output slot
  223. local function getOutputItem()
  224.     local item = turtle.getItemDetail(outputSlot)
  225.     if item then
  226.         return {slot = outputSlot, name = item.name, count = item.count}
  227.     else
  228.         return nil
  229.     end
  230. end
  231.  
  232. -- Function to create a recipe
  233. local function createRecipe()
  234.     local inputItems = getInputItems()
  235.     local outputItem = getOutputItem()
  236.  
  237.     if not outputItem then
  238.         shaka.clearScreen()
  239.         print("Error: No item in output slot (16). Place the resulting item there.")
  240.         sleep(2)
  241.         errorCheck = true
  242.         drawDisplay(getSlotStates())
  243.         return
  244.     end
  245.  
  246.     local emptyInputs = true
  247.     for _, item in ipairs(inputItems) do
  248.         if item.name then
  249.             emptyInputs = false
  250.             break
  251.         end
  252.     end
  253.  
  254.     if emptyInputs then
  255.         shaka.clearScreen()
  256.         print("Error: No items in input slots (5, 6, 7, 9, 10, 11, 13, 14, 15). Place the input items there.")
  257.         sleep(2)
  258.         errorCheck = true
  259.         drawDisplay(getSlotStates())
  260.         return
  261.     end
  262.  
  263.     recordRecipe(inputItems, outputItem)
  264. end
  265.  
  266. function findAvailableDrop(slot)
  267.   local tasks = {}
  268.   for i = 1, #fromInventories do
  269.     local invWrap = peripheral.wrap(fromInventories[i])
  270.     tasks[#tasks+1] = function()
  271.       invWrap.pullItems(turtleName, slot)
  272.     end
  273.   end
  274.   parallel.waitForAll(unpack(tasks))
  275. end
  276.  
  277.  
  278. function dropInventory()
  279.   local tasks = {}
  280.   for i = 1, 16 do
  281.     if turtle.getItemCount(i) > 0 then
  282.       tasks[#tasks+1] = function()
  283.         repeat
  284.           findAvailableDrop(i)
  285.         until turtle.getItemCount(i) == 0
  286.       end
  287.     end
  288.   end
  289.   parallel.waitForAll(unpack(tasks))
  290. end
  291.  
  292.  
  293. function proceedAfterCraft()
  294.     if duplicates == true then
  295.         return
  296.     end
  297.     local product = getOutputItem()
  298.  
  299.     -- Handle case where product might be nil
  300.     if not product or not product.name then
  301.         error("No product found. Unable to proceed.")
  302.     end
  303.  
  304.     local options = {
  305.         "- Add item to autocraft list",
  306.         "- Record next recipe",
  307.     }
  308.     local selected = 1
  309.  
  310.     -- Function to render the UI
  311.     local function renderUI()
  312.         shaka.clearScreen()
  313.         setTextStyle(colors.gray, colors.green)
  314.         term.clearLine()
  315.         shaka.centerText("Added recipe for:")
  316.  
  317.         -- Display product name
  318.         setTextStyle(colors.gray, colors.green)
  319.         term.setCursorPos(1, 3)
  320.         shaka.centerText(shaka.prettyName(product.name))
  321.  
  322.         -- Display options
  323.         for i, option in ipairs(options) do
  324.             if i == selected then
  325.                 setTextStyle(colors.black, colors.yellow) -- Highlight selected option
  326.             else
  327.                 setTextStyle(colors.black, colors.lightGray) -- Normal style
  328.             end
  329.             term.setCursorPos(1, 5 + i)
  330.             print(option)
  331.         end
  332.     end
  333.  
  334.     -- Function to handle input
  335.     local function handleInput()
  336.         while true do
  337.             local event, param1, param2, param3 = os.pullEvent()
  338.  
  339.             if event == "key" then
  340.                 local key = param1
  341.                 if key == keys.w or key == keys.up then
  342.                     selected = selected - 1
  343.                     if selected < 1 then
  344.                         selected = #options
  345.                     end
  346.                     renderUI()
  347.                 elseif key == keys.s or key == keys.down then
  348.                     selected = selected + 1
  349.                     if selected > #options then
  350.                         selected = 1
  351.                     end
  352.                     renderUI()
  353.                 elseif key == keys.enter or key == keys.space then
  354.                     return selected
  355.                 end
  356.             elseif event == "mouse_scroll" then
  357.                 local direction = param1
  358.                 selected = selected + direction
  359.                 if selected < 1 then
  360.                     selected = #options
  361.                 elseif selected > #options then
  362.                     selected = 1
  363.                 end
  364.                 renderUI()
  365.             elseif event == "mouse_click" then
  366.                 local button, x, y = param1, param2, param3
  367.                 for i = 1, #options do
  368.                     if y == 4 + i then -- Check if the click is on an option
  369.                         selected = i
  370.                         renderUI()
  371.                         if button == 1 then -- Left-click confirms
  372.                             return selected
  373.                         end
  374.                     end
  375.                 end
  376.             end
  377.         end
  378.     end
  379.  
  380.     -- Helper function for setting text style
  381.     function setTextStyle(background, text)
  382.         shaka.changeColors(background, text)
  383.     end
  384.  
  385.     -- Initial render and input loop
  386.     renderUI()
  387.     local choice = handleInput()
  388.  
  389.     -- Act based on the choice
  390.     if choice == 1 then
  391.         local craftList = shaka.readFile(filename)
  392.         shaka.changeColors(colors.gray, colors.white)
  393.         term.clearLine()
  394.         shaka.nextLine()
  395.        
  396.         shaka.changeColors(colors.black, colors.white)
  397.         write("Amount:")
  398.         shaka.changeColors(colors.black, colors.yellow)
  399.         local amount = tonumber(read())
  400.         if amount ~= nil then
  401.             table.insert(craftList, {name = product.name, amount = amount})
  402.             shaka.changeColors(colors.black, colors.green)
  403.             print("Added ", shaka.prettyName(product.name), " x ", amount)
  404.             shaka.writeFile(filename, craftList)
  405.             dropInventory()
  406.             sleep(1)
  407.             drawDisplay(getSlotStates())
  408.         else
  409.             term.setTextColor(colors.red)
  410.             print("Invalid entry, try again.")
  411.             sleep(1)
  412.             proceedAfterCraft()
  413.         end
  414.     elseif choice == 2 then
  415.         print("Recording next recipe...")
  416.         dropInventory()
  417.         sleep(1)
  418.         drawDisplay(getSlotStates())
  419.         -- Add functionality for this choice
  420.     end
  421. end
  422.  
  423. -- Function to monitor inventory changes and handle input
  424. local function monitorAndSave()
  425.     while true do
  426.         local event, key = os.pullEvent()
  427.  
  428.         if event == "turtle_inventory" then
  429.             local states = getSlotStates()
  430.             drawDisplay(states)
  431.         elseif event == "key" then
  432.             if key == keys.c or key == keys.enter then
  433.                 duplicates = false
  434.                 createRecipe()
  435.                 if errorCheck == false then
  436.                     proceedAfterCraft()
  437.                 end
  438.             elseif key == keys.q then
  439.                 os.reboot()
  440.                 break
  441.             end
  442.         end
  443.     end
  444. end
  445.  
  446. -- Main function
  447. local function main()
  448.     drawDisplay(getSlotStates())
  449.     monitorAndSave()
  450. end
  451.  
  452. -- Execute the main function
  453. main()
  454. -- proceedAfterCraft()
Add Comment
Please, Sign In to add comment