Advertisement
jille_Jr

CC: Sort chest

Jul 2nd, 2022
848
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 4.24 KB | None | 0 0
  1. ---(( Types ))---
  2.  
  3. ---@class ItemInfoX : ItemInfo
  4. ---@field slot integer
  5.  
  6. ---(( Functions ))---
  7.  
  8. ---@param inv inventory
  9. ---@return table<integer, ItemInfoX>
  10. local function listItems(inv)
  11.   local items = inv.list()
  12.   for key, item in pairs(items) do
  13.     item.slot = key
  14.   end
  15.   return items
  16. end
  17.  
  18. ---@param item ItemInfo
  19. ---@return string
  20. local function getItemNormalizedName(item)
  21.   if item.displayName then
  22.     return item.displayName:lower()
  23.   end
  24.   return select(1, item.name:gsub("[^:]+:", ""))
  25. end
  26.  
  27. ---@param a ItemInfoX
  28. ---@param b ItemInfoX
  29. ---@return boolean
  30. local function compareItems(a, b)
  31.   local nameA = getItemNormalizedName(a)
  32.   local nameB = getItemNormalizedName(b)
  33.   if nameA ~= nameB then
  34.     return nameA < nameB
  35.   end
  36.   if a.count ~= b.count then
  37.     return a.count > b.count
  38.   end
  39.   return a.slot < b.slot
  40. end
  41.  
  42. ---@param unsorted table<integer,ItemInfoX>
  43. local function sortItemsTable(unsorted)
  44.   ---@type ItemInfoX[]
  45.   local items = {}
  46.   for _, item in pairs(unsorted) do
  47.     table.insert(items, item)
  48.   end
  49.   table.sort(items, compareItems)
  50.   return items
  51. end
  52.  
  53. ---@param inv inventory
  54. ---@param state table<integer, ItemInfoX>
  55. local function findEmptySlot(inv, state)
  56.   local nextEmpty = #state + 1
  57.   if nextEmpty > inv.size() then
  58.     error("Failed to find empty slot in inventory")
  59.   end
  60.   return nextEmpty
  61. end
  62.  
  63. ---@param inv inventory
  64. ---@param state table<integer, ItemInfoX>
  65. ---@param fromSlot integer
  66. ---@param toSlot integer
  67. local function moveItems(inv, state, fromSlot, toSlot)
  68.   if not state[fromSlot] then
  69.     error(string.format("move items from slot %d to %d: source slot is empty", fromSlot, toSlot))
  70.   end
  71.   if state[toSlot] then
  72.     error(string.format("move items from slot %d to %d: target slot is not empty", fromSlot, toSlot))
  73.   end
  74.   local invName = peripheral.getName(inv)
  75.   inv.pushItems(invName, fromSlot, nil, toSlot)
  76.   state[toSlot] = state[fromSlot]
  77.   state[fromSlot] = nil
  78.   state[toSlot].slot = toSlot
  79. end
  80.  
  81. ---@param inv inventory
  82. ---@param state table<integer, ItemInfoX>
  83. ---@param item ItemInfoX
  84. ---@param toSlot integer
  85. local function performSortItem(inv, state, item, toSlot)
  86.   if state[toSlot] then
  87.     local empty = findEmptySlot(inv, state)
  88.     moveItems(inv, state, toSlot, empty)
  89.   end
  90.   moveItems(inv, state, item.slot, toSlot)
  91. end
  92.  
  93. ---@param key integer
  94. ---@param item ItemInfoX
  95. ---@return boolean
  96. local function shouldSort(key, item)
  97.   return key ~= item.slot
  98. end
  99.  
  100. ---@param inv inventory
  101. ---@param state table<integer, ItemInfoX>
  102. ---@param sorted ItemInfoX[]
  103. ---@param sortOps integer
  104. local function performSort(inv, state, sorted, sortOps)
  105.   local fgColor = term.getTextColor()
  106.   term.setTextColor(colors.gray)
  107.   local lines = write(string.format("|%s|", string.rep("-", sortOps)))
  108.   term.setTextColor(colors.yellow)
  109.  
  110.   local _, y = term.getCursorPos()
  111.   term.setCursorPos(1, y - lines)
  112.   write("|")
  113.   for key, item in ipairs(sorted) do
  114.     if shouldSort(key, item) then
  115.       performSortItem(inv, state, item, key)
  116.       write("=")
  117.     end
  118.   end
  119.   write("|")
  120.   print()
  121.   term.setTextColor(fgColor)
  122. end
  123.  
  124. ---@param side string?
  125. ---@return inventory
  126. local function findChest(side)
  127.   if side then
  128.     local p = peripheral.wrap(side)
  129.     if not p then
  130.       error(string.format('No peripheral at "%s"', side))
  131.     end
  132.     if not peripheral.hasType(p, "inventory") then
  133.       error(string.format('Peripheral at "%s" is not an "inventory" type', side))
  134.     end
  135.     return p
  136.   end
  137.   if peripheral.hasType("front", "inventory") then
  138.     return peripheral.wrap("front")
  139.   end
  140.   local chest = peripheral.find("inventory")
  141.   return chest
  142. end
  143.  
  144. ---(( Program ))---
  145.  
  146. local chest = findChest(...)
  147.  
  148. if chest == nil then
  149.   print("No inventory peripheral found.")
  150.   return
  151. end
  152.  
  153. local origItems = listItems(chest)
  154. local sortedItems = sortItemsTable(origItems)
  155.  
  156. print(string.format('Sorting "%s" with %d items...', peripheral.getName(chest), #sortedItems))
  157. local sortOps = 0
  158. for key, item in ipairs(sortedItems) do
  159.   if shouldSort(key, item) then
  160.     sortOps = sortOps + 1
  161.   end
  162. end
  163.  
  164. if sortOps == 0 then
  165.   print("Already sorted.")
  166.   return
  167. end
  168.  
  169. performSort(chest, origItems, sortedItems, sortOps)
  170.  
  171. print("Sorting done")
  172.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement