Advertisement
TimTheToaster

Untitled

Oct 29th, 2019
1,809
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.92 KB | None | 0 0
  1. -- Config
  2.  
  3. local maxUsedSlotsPerCell = 55
  4. local paddingPercent = 100
  5.  
  6. local systemDriveNames = {
  7. "appliedenergistics2:drive_28",
  8. "appliedenergistics2:drive_25",
  9. }
  10. local workspaceNames = {
  11. ioPort = "appliedenergistics2:io_port_8",
  12. interface = "appliedenergistics2:interface_7",
  13. chest = "appliedenergistics2:chest_7",
  14. drives = {
  15. "appliedenergistics2:drive_31",
  16. "appliedenergistics2:drive_30",
  17. }
  18. }
  19.  
  20. local capacityByName = {
  21. ["appliedenergistics2:storage_cell_1k"] = 1024,
  22. ["appliedenergistics2:storage_cell_4k"] = 4096,
  23. ["appliedenergistics2:storage_cell_16k"] = 16384,
  24. ["appliedenergistics2:storage_cell_64k"] = 65536
  25. }
  26.  
  27. -- /Config
  28.  
  29. -- Util Functions
  30.  
  31. local clock = os.clock
  32. local function sleep(n) -- seconds
  33. local t0 = clock()
  34. while clock() - t0 <= n do end
  35. end
  36.  
  37. local function map(array, func)
  38. local new_array = {}
  39. for i,v in pairs(array) do
  40. new_array[i] = func(v, i)
  41. end
  42. return new_array
  43. end
  44.  
  45. local function values(obj)
  46. local result = {}
  47. for _, v in pairs(obj) do
  48. table.insert(result, v)
  49. end
  50. return result
  51. end
  52.  
  53. local function groupBy(array, prop)
  54. local result = {}
  55. for _, element in pairs(array) do
  56. if element[prop] ~= nil then
  57. if result[element[prop]] == nil then
  58. result[element[prop]] = {}
  59. end
  60. table.insert(result[element[prop]], element)
  61. end
  62. end
  63. return result
  64. end
  65.  
  66. -- /Util Functions
  67.  
  68. -- Peripherals
  69.  
  70. local systemDrives = map(systemDriveNames, function(driveName)
  71. return peripheral.wrap(driveName)
  72. end)
  73. local workspace = {
  74. ioPort = peripheral.wrap(workspaceNames.ioPort),
  75. interface = peripheral.wrap(workspaceNames.interface),
  76. chest = peripheral.wrap(workspaceNames.chest),
  77. drives = map(workspaceNames.drives, function(driveName)
  78. return peripheral.wrap(driveName)
  79. end)
  80. }
  81.  
  82. -- /Peripherals
  83.  
  84. -- Classes
  85.  
  86. -- Cell
  87.  
  88. local cells = {}
  89. local additionallyRequiredCells = {}
  90. local Cell = {}
  91. Cell.__index = Cell
  92.  
  93. Cell.capacities = (function()
  94. local capacities = values(capacityByName)
  95. table.sort(capacities, function(a, b) return a < b end)
  96. return capacities
  97. end)()
  98.  
  99. function Cell.sortByUnusedBytesDesc(a, b)
  100. return b:getNumUnusedBytes() < a:getNumUnusedBytes()
  101. end
  102.  
  103. function Cell.sortByCapacity(a, b)
  104. return a.capacity < b.capacity
  105. end
  106.  
  107. function Cell.sortByCapacityDesc(a, b)
  108. return b.capacity < a.capacity
  109. end
  110.  
  111. function Cell.loadAll()
  112. for driveNum, systemDrive in ipairs(systemDrives) do
  113. local systemCells = systemDrive.list()
  114. local toSlotNum = 1
  115. for _, cell in pairs(systemCells) do
  116. table.insert(cells, Cell.new(capacityByName[cell.name], driveNum, toSlotNum))
  117. toSlotNum = toSlotNum + 1
  118. end
  119. end
  120. table.remove(cells, #cells)
  121. end
  122.  
  123. function Cell.new(capacity, driveNum, slotNum)
  124. local self = setmetatable({}, Cell)
  125. self.capacity = capacity
  126. self.driveNum = driveNum
  127. self.slotNum = slotNum
  128. self.inventory = {}
  129. return self
  130. end
  131.  
  132. function Cell.getSmallestCellNeededForStack(stack)
  133. for _, capacity in ipairs(Cell.capacities) do
  134. local cell = Cell.new(capacity)
  135. if cell:hasSpaceFor(stack) then
  136. return cell
  137. end
  138. end
  139. end
  140.  
  141. function Cell:getNumUsedBytes()
  142. local bytesUsed = 0
  143. for _, stackData in pairs(self.inventory) do
  144. bytesUsed = bytesUsed + self:getBytesForStack(stackData)
  145. end
  146. return bytesUsed
  147. end
  148.  
  149. function Cell:add(stack)
  150. table.insert(self.inventory, stack)
  151. if self:getNumUsedBytes() > self.capacity then
  152. error("Unexpected error: inventory has exceeded capacity")
  153. end
  154. end
  155.  
  156. function Cell:getBytesForStack(stack)
  157. return (self.capacity / 128) + math.ceil(stack.count / 8)
  158. end
  159.  
  160. function Cell:hasSpaceFor(stack)
  161. local bytesUsed = self:getNumUsedBytes()
  162. local hasEnoughBytes = bytesUsed + self:getBytesForStack(stack) < self.capacity
  163. local hasEnoughSlots = self:getNumUnusedSlots() > 0
  164. return hasEnoughBytes and hasEnoughSlots
  165. end
  166.  
  167. function Cell:getNumUnusedBytes()
  168. return self.capacity - self:getNumUsedBytes()
  169. end
  170.  
  171. function Cell:getNumUnusedSlots()
  172. return maxUsedSlotsPerCell - #self.inventory
  173. end
  174.  
  175. function Cell:clearAndPutInWorkspaceChest()
  176. local drive = workspace.drives[self.driveNum]
  177. drive.pushItems(workspaceNames.ioPort, self.slotNum)
  178. while workspace.ioPort.list()[7] == nil do
  179. sleep(0.1)
  180. end
  181. workspace.ioPort.pushItems(workspaceNames.chest, 7)
  182. end
  183.  
  184. function Cell:exportInventoryToWorkspaceChest()
  185. for _, stack in ipairs(self.inventory) do
  186. stack:exportToWorkspaceChest()
  187. end
  188. end
  189.  
  190. local outputDrives = {}
  191. for _, drive in pairs(systemDrives) do
  192. table.insert(outputDrives, drive)
  193. end
  194. local currentOutputDrive = table.remove(outputDrives, 1)
  195. function Cell:moveBackToSystem()
  196. currentOutputDrive.pullItems(workspaceNames.chest, 2)
  197. if #currentOutputDrive.list() == 10 then
  198. currentOutputDrive = table.remove(outputDrives, 1)
  199. end
  200. end
  201.  
  202. -- Stack
  203.  
  204. local stacks = {}
  205. local Stack = {}
  206. Stack.__index = Stack
  207.  
  208. function Stack.sortByCountDesc(a, b)
  209. return b.count < a.count
  210. end
  211.  
  212. function Stack.loadAll()
  213. local handledItemTypes = {}
  214. local allItemTypes = workspace.interface.listAvailableItems()
  215. for _, itemType in pairs(allItemTypes) do
  216. if handledItemTypes[itemType.name] == nil then
  217. handledItemTypes[itemType.name] = 1
  218. local ccStacks = workspace.interface.findItems(itemType.name)
  219. for _, ccStack in pairs(ccStacks) do
  220. table.insert(stacks, Stack.new(ccStack))
  221. end
  222. end
  223. end
  224. end
  225.  
  226. function Stack.new(ccStack)
  227. local self = setmetatable({}, Stack)
  228. self.ccStack = ccStack
  229. self.metadata = ccStack.getMetadata()
  230. self.displayName = self.metadata.displayName
  231. self.count = (1+paddingPercent/100)*self.metadata.count
  232. return self
  233. end
  234.  
  235. function Stack:addToCellWithLargestUnusuedSpace()
  236. table.sort(cells, Cell.sortByUnusedBytesDesc)
  237. for _, cell in ipairs(cells) do
  238. if cell:hasSpaceFor(self) then
  239. cell:add(self)
  240. return
  241. end
  242. end
  243. local newCell = Cell.getSmallestCellNeededForStack(self)
  244. newCell:add(self)
  245. table.insert(cells, newCell)
  246. table.insert(additionallyRequiredCells, newCell)
  247. error("No cell found to add stack to")
  248. end
  249.  
  250. function Stack:exportAllToWorkspaceChest()
  251. local amountToExport = self.metadata.count
  252. print(" Exporting "..amountToExport.." "..self.displayName.."...")
  253. local amountExported = 0
  254. while amountExported < amountToExport do
  255. amountExported = amountExported + self.ccStack.export(workspaceNames.chest)
  256. end
  257. end
  258.  
  259. -- /Classes
  260.  
  261. -- Main
  262.  
  263. print("Scanning for cells...")
  264. Cell.loadAll()
  265.  
  266. print("Moving cells to workspace...")
  267. local function moveDrivesFromSystemToWorkspace()
  268. for driveNum, systemDrive in ipairs(systemDrives) do
  269. local systemCells = systemDrive.list()
  270. for fromSlotNum, _ in pairs(systemCells) do
  271. systemDrive.pushItems(workspaceNames.drives[driveNum], fromSlotNum)
  272. end
  273. end
  274. end
  275.  
  276. moveDrivesFromSystemToWorkspace()
  277.  
  278. print("Scanning for stacks...")
  279. Stack.loadAll()
  280.  
  281. print("Planning...")
  282. table.sort(stacks, Stack.sortByCountDesc)
  283. for _, stack in ipairs(stacks) do
  284. stack:addToCellWithLargestUnusuedSpace()
  285. end
  286.  
  287. if #additionallyRequiredCells > 0 then
  288. print("Needed cells:")
  289. local requiredCellsByCapacity = groupBy(additionallyRequiredCells, 'capacity')
  290. for _, capacity in ipairs(Cell.capacities) do
  291. if requiredCellsByCapacity[capacity] ~= nil and #requiredCellsByCapacity[capacity] > 0 then
  292. print(" "..#requiredCellsByCapacity[capacity].." "..(capacity/1024).."k cells")
  293. end
  294. end
  295. error("Add the above cells to continue")
  296. end
  297.  
  298. print("Executing plan...")
  299.  
  300. table.sort(cells, Cell.sortByCapacity)
  301.  
  302. for _, cell in ipairs(cells) do
  303. print("clearing and putting in workspace...")
  304. cell:clearAndPutInWorkspaceChest()
  305. print("moving stacks to chest...")
  306. for _, stack in ipairs(cell.inventory) do
  307. stack:exportAllToWorkspaceChest()
  308. end
  309. print("moving cell back to system...")
  310. cell:moveBackToSystem()
  311. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement