Advertisement
Guest User

startup.orig

a guest
Jun 30th, 2016
54
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 60.64 KB | None | 0 0
  1. -- Setup an 8 wide by 4 high monitor
  2. -- For FTB TPPI 1.0.4
  3.  
  4. -- All credit goes to rseding91 for making this
  5. -- https://www.youtube.com/user/rseding91
  6. -- See the following video for setup
  7. -- https://www.youtube.com/watch?v=RTBkjYJEdQc
  8. -- Tanks to bdog (bdog111) who modified the Code for later CC-Version
  9.  
  10. if (fs.exists("button") == true) then
  11.     print("Button API detected")
  12. else
  13.     print("Downloading button API")
  14.     shell.run("pastebin get HGYkrNnU button")
  15. end
  16.  
  17. os.loadAPI("button")
  18. local m = peripheral.wrap("back")
  19. button.startup("back")
  20. local run = true
  21. local disableFillRedstoneDirection = "right"
  22. local redstoneWaitTicks = 3
  23. local alchemicalFurnaceFromChestDirection = "auto"
  24. local essentia
  25. local essentiasCount = 58
  26. local emptyJars
  27. local totalJars
  28. local fillAmount
  29. local fillEssentia
  30. local fillAvailableSpace
  31. local topOffJarsEssentiaList
  32. local fillAllTo64EssentiaList
  33. local fillAllTo128EssentiaList
  34. local chests = {}
  35. local aspectAnalyzers = {}
  36. local chestAspects
  37. local distributeBurnRequests = true
  38.  
  39.  
  40.  
  41. -- Print debug output during startup: 0 = off, 1 = summary debug, 2 = everything
  42. -- Errors are still shown regardless of the debug output level.
  43. local debugOutput = 1
  44. local padding = "                                                                                                    "
  45. local numberPadding = 3
  46.  
  47. -- If true, the more intensive portions of this script sleep between each action
  48. -- If false, the script runs at maximum speed
  49. local serverFriendly = true
  50.  
  51. --[[
  52.  
  53.     --Locations and colors of different visuals displayed on the monitor.--
  54.    
  55.     * Auto positioning is done per-item depending on where it normally sits in relation
  56.     to the other items. For the final position of a control see the setAutoDetectVariables() function below.
  57.    
  58.     ** Virtually every "auto" set location for the main display is relative to the essentiaX/Y locations. essentiaX = "auto" will
  59.     center the display on the monitor or if it can't be centered due to being too small it will be left-aligned.
  60.    
  61.     ** Virtually every "auto" set location for the refill essentia display is relative to the refillScreenX/Y locations.
  62.     refillScreenX = "auto" will center the display on the monitor or if it can't be centered due to being too small it will be left-aligned.
  63.    
  64.     ** If a location isn't default to "auto" it does not currently support auto positioning.
  65.    
  66.     * Any location or color that defaults to "auto" can be manually specified if that's desired. However, no error
  67.     checking is done to make sure the manual positions are valid.
  68.    
  69.     * Button height is calculated as 1 characters height. A button with the height of 1 will be the height of the button text.
  70.    
  71.     * The inactive colors are the colors used during normal display. Active colors are during button presses.
  72. --]]
  73.  
  74. local essentiaColumnWidth = 19
  75. local essentiaColumnHeight = 17
  76. local essentiaColumnSpacing = 2
  77. local essentiaX = "auto"
  78. local essentiaY = 1
  79.  
  80. local refreshButtonX = "auto"
  81. local refreshButtonY = "auto"
  82. local refreshButtonWidth = 19
  83. local refreshButtonHeight = 2
  84.  
  85. local topoffAllButtonX = "auto"
  86. local topoffAllButtonY = "auto"
  87. local topoffAllButtonWidth = 19
  88. local topoffAllButtonHeight = 2
  89.  
  90. local emptyJarsX = "auto"
  91. local emptyJarsY = "auto"
  92.  
  93. local totalJarsX = "auto"
  94. local totalJarsY = "auto"
  95.  
  96. local refillScreenX = "auto"
  97. local refillScreenY = 1
  98.  
  99. local fillAllTo64ButtonX = "auto"
  100. local fillAllTo64ButtonY = "auto"
  101. local fillAllTo64ButtonWidth = 18
  102. local fillAllTo64ButtonHeight = 2
  103.  
  104. local fillAllTo128ButtonX = "auto"
  105. local fillAllTo128ButtonY = "auto"
  106. local fillAllTo128ButtonWidth = 18
  107. local fillAllTo128ButtonHeight = 2
  108.  
  109. local otherOptionsButtonX = "auto"
  110. local otherOptionsButtonY = "auto"
  111. local otherOptionsButtonWidth = 18
  112. local otherOptionsButtonHeight = 2
  113.  
  114. local essentiaTopOffJarsX = "auto"
  115. local essentiaTopOffJarsY = 5
  116.  
  117. local essentiaTopOffLabelX = "auto"
  118. local essentiaTopOffLabelY = 2
  119.  
  120. local essentiaFillAllTo64X = "auto"
  121. local essentiaFillAllTo64Y = 5
  122.  
  123. local essentiaFillAllTo64LabelX = "auto"
  124. local essentiaFillAllTo64LabelY = 2
  125.  
  126. local essentiaFillAllTo128X = "auto"
  127. local essentiaFillAllTo128Y = 5
  128.  
  129. local essentiaFillAllTo128LabelX = "auto"
  130. local essentiaFillAllTo128LabelY = 2
  131.  
  132. local cancelTopOffJarsButtonX = "auto"
  133. local cancelTopOffJarsButtonY = "auto"
  134. local cancelTopOffJarsButtonWidth = 19
  135. local cancelTopOffJarsButtonHeight = 2
  136.  
  137. local beginTopOffJarsFillButtonX = "auto"
  138. local beginTopOffJarsFillButtonY = "auto"
  139. local beginTopOffJarsFillButtonWidth = 19
  140. local beginTopOffJarsFillButtonHeight = 2
  141.  
  142. local cancelFillAllTo64ButtonX = "auto"
  143. local cancelFillAllTo64ButtonY = "auto"
  144. local cancelFillAllTo64ButtonWidth = 19
  145. local cancelFillAllTo64ButtonHeight = 2
  146.  
  147. local beginFillAllTo64ButtonX = "auto"
  148. local beginFillAllTo64ButtonY = "auto"
  149. local beginFillAllTo64ButtonWidth = 19
  150. local beginFillAllTo64ButtonHeight = 2
  151.  
  152. local cancelFillAllTo128ButtonX = "auto"
  153. local cancelFillAllTo128ButtonY = "auto"
  154. local cancelFillAllTo128ButtonWidth = 19
  155. local cancelFillAllTo128ButtonHeight = 2
  156.  
  157. local beginFillAllTo128ButtonX = "auto"
  158. local beginFillAllTo128ButtonY = "auto"
  159. local beginFillAllTo128ButtonWidth = 19
  160. local beginFillAllTo128ButtonHeight = 2
  161.  
  162. local burnScreenLabelX = "auto"
  163. local burnScreenLabelY = 3
  164.  
  165. local burnScreenBeanLabelX = 6
  166. local burnScreenBeanLabelY = 10
  167.  
  168. local burnScreenStatusX = 6
  169. local burnScreenStatusY = 13
  170.  
  171. local burnScreenBeanTextLabel = "Currently bean type: "
  172. local burnScreenStatusTextLabel = "Current status: "
  173.  
  174.  
  175. local monBackColor = colors.black
  176.  
  177. local essentiaInactiveTextColorEmpty = colors.gray
  178. local essentiaInactiveTextColorLow = colors.red
  179. local essentiaInactiveTextColorMedium = colors.lime
  180. local essentiaInactiveTextColorHigh = colors.green
  181. local essentiaInactiveBackColor = monBackColor
  182. local essentiaActiveTextColor = colors.white
  183. local essentiaActiveBackColor = colors.yellow
  184.  
  185. local refreshActiveBackColor = colors.lime
  186. local refreshInactiveBackColor = colors.blue
  187. local refreshActiveTextColor = colors.white
  188. local refreshInactiveTextColor = colors.white
  189.  
  190. local topoffAllJarsActiveTextColor = colors.white
  191. local topoffAllJarsInactiveTextColor = colors.white
  192. local topoffAllJarsActiveBackColor = colors.lime
  193. local topoffAllJarsInactiveBackColor = colors.blue
  194.  
  195. local fillAllTo64InactiveTextColor = colors.white
  196. local fillAllTo64ActiveTextColor = colors.white
  197. local fillAllTo64InactiveBackColor = colors.blue
  198. local fillAllTo64ActiveBackColor = colors.lime
  199.  
  200. local fillAllTo128InactiveTextColor = colors.white
  201. local fillAllTo128ActiveTextColor = colors.white
  202. local fillAllTo128InactiveBackColor = colors.blue
  203. local fillAllTo128ActiveBackColor = colors.lime
  204.  
  205. local refillButtonsInactiveBackColor = colors.blue
  206. local refillButtonsActiveBackColor = colors.lime
  207. local refillButtonsInactiveTextColor = colors.white
  208. local refillButtonsActiveTextColor = colors.white
  209.  
  210. local otherOptionsButtonInactiveBackColor = colors.blue
  211. local otherOptionsButtonActiveBackColor = colors.lime
  212. local otherOptionsButtonInactiveTextColor = colors.white
  213. local otherOptionsButtonActiveTextColor = colors.white
  214.  
  215. local cancelTopOffJarsButtonInactiveBackColor = colors.blue
  216. local cancelTopOffJarsButtonActiveBackColor = colors.lime
  217. local cancelTopOffJarsButtonInactiveTextColor = colors.white
  218. local cancelTopOffJarsButtonActiveTextColor = colors.white
  219.  
  220. local beginTopOffJarsFillButtonInactiveBackColor = colors.blue
  221. local beginTopOffJarsFillButtonActiveBackColor = colors.lime
  222. local beginTopOffJarsFillButtonInactiveTextColor = colors.white
  223. local beginTopOffJarsFillButtonActiveTextColor = colors.white
  224.  
  225. local cancelFillAllTo64ButtonInactiveBackColor = colors.blue
  226. local cancelFillAllTo64ButtonActiveBackColor = colors.lime
  227. local cancelFillAllTo64ButtonInactiveTextColor = colors.white
  228. local cancelFillAllTo64ButtonActiveTextColor = colors.white
  229.  
  230. local beginFillAllTo64ButtonInactiveBackColor = colors.blue
  231. local beginFillAllTo64ButtonActiveBackColor = colors.lime
  232. local beginFillAllTo64ButtonInactiveTextColor = colors.white
  233. local beginFillAllTo64ButtonActiveTextColor = colors.white
  234.  
  235. local cancelFillAllTo128ButtonInactiveBackColor = colors.blue
  236. local cancelFillAllTo128ButtonActiveBackColor = colors.lime
  237. local cancelFillAllTo128ButtonInactiveTextColor = colors.white
  238. local cancelFillAllTo128ButtonActiveTextColor = colors.white
  239.  
  240. local beginFillAllTo128ButtonInactiveBackColor = colors.blue
  241. local beginFillAllTo128ButtonActiveBackColor = colors.lime
  242. local beginFillAllTo128ButtonInactiveTextColor = colors.white
  243. local beginFillAllTo128ButtonActiveTextColor = colors.white
  244.  
  245.  
  246. local emptyJarsTextColor = colors.white
  247. local emptyJarsBackColor = monBackColor
  248.  
  249. local totalJarsTextColor = colors.white
  250. local totalJarsBackColor = monBackColor
  251.  
  252. local refillLabelTextColor = colors.white
  253. local refillCurrentAmountTextColor = colors.white
  254. local refillAddingAmountTextColor = colors.green
  255.  
  256. local topOffAllJarsEssentiaBackColor = monBackColor
  257. local topOffAllJarsEssentiaTextColorZero = essentiaInactiveTextColorEmpty
  258. local topOffAllJarsEssentiaTextColorNonZero = colors.white
  259.  
  260. local topOffAllJarsEssentiaLabelBackColor = monBackColor
  261. local topOffAllJarsEssentiaLabelTextColor = colors.white
  262.  
  263. local fillAllTo64EssentiaBackColor = monBackColor
  264. local fillAllTo64EssentiaTextColorZero = essentiaInactiveTextColorEmpty
  265. local fillAllTo64EssentiaTextColorNonZero = essentiaInactiveTextColorMedium
  266.  
  267. local fillAllTo64EssentiaLabelBackColor = monBackColor
  268. local fillAllTo64EssentiaLabelTextColor = colors.white
  269.  
  270. local fillAllTo128EssentiaBackColor = monBackColor
  271. local fillAllTo128EssentiaTextColorZero = essentiaInactiveTextColorEmpty
  272. local fillAllTo128EssentiaTextColorNonZero = essentiaInactiveTextColorHigh
  273.  
  274. local fillAllTo128EssentiaLabelBackColor = monBackColor
  275. local fillAllTo128EssentiaLabelTextColor = colors.white
  276.  
  277.  
  278. local burnScreenStatusBackColor = monBackColor
  279. local burnScreenStatusTextColor = colors.white
  280. local burnScreenBeanLabelBackColor = monBackColor
  281. local burnScreenBeanLabelTextColor = colors.white
  282. local burnScreenLabelBackColor = monBackColor
  283. local burnScreenLabelTextColor = colors.white
  284. local burnScreenBorderColor = colors.blue
  285.  
  286.  
  287.  
  288.  
  289. function setAutoDetectVariables()
  290.     local monWidth
  291.     local monHeight
  292.    
  293.     monWidth,monHeight = m.getSize()
  294.    
  295.     if (alchemicalFurnaceFromChestDirection ~= "auto") then
  296.         if (alchemicalFurnaceFromChestDirection ~= "north"
  297.             and alchemicalFurnaceFromChestDirection ~= "south"
  298.             and alchemicalFurnaceFromChestDirection ~= "east"
  299.             and alchemicalFurnaceFromChestDirection ~= "west") then
  300.            
  301.             print("Invalid alchemical furnace from chest direction. !!RESTART REQUIRED!!")
  302.             while (true) do
  303.                 sleep(60)
  304.             end
  305.         end
  306.     end
  307.    
  308.     if (essentiaX == "auto") then
  309.         -- Centers the essentia display on the monitor horizontally
  310.         essentiaX = math.floor((monWidth - ((math.ceil(essentiasCount / essentiaColumnHeight) * (essentiaColumnWidth + essentiaColumnSpacing)) - essentiaColumnSpacing)) / 2) + 1
  311.        
  312.         -- The monitor is too small
  313.         if (essentiaX < 1) then
  314.             print("The monitor is too small width wise to display all the needed main screen information correctly.")
  315.            
  316.             essentiaX = 1
  317.         end
  318.     end
  319.    
  320.     if (refreshButtonX == "auto") then
  321.         -- Centers the refresh button on the monitor horizontally
  322.         refreshButtonX = essentiaX + math.floor(((math.ceil(essentiasCount / essentiaColumnHeight) * (essentiaColumnWidth + essentiaColumnSpacing)) - essentiaColumnSpacing) / 2) -  math.ceil(refreshButtonWidth / 2) + 1
  323.     end
  324.    
  325.     if (refreshButtonY == "auto") then
  326.         -- Puts the refresh button directly below the essentia list
  327.         refreshButtonY = essentiaY + essentiaColumnHeight + 1
  328.     end
  329.    
  330.     if (topoffAllButtonX == "auto") then
  331.         -- Puts the top off all button in line with the refresh button
  332.         topoffAllButtonX = essentiaX + math.floor(((math.ceil(essentiasCount / essentiaColumnHeight) * (essentiaColumnWidth + essentiaColumnSpacing)) - essentiaColumnSpacing) / 2) -  math.ceil(topoffAllButtonWidth / 2) + 1
  333.     end
  334.    
  335.     if (topoffAllButtonY == "auto") then
  336.         -- Puts the top off all button directly below the refresh button
  337.         topoffAllButtonY = refreshButtonY + refreshButtonHeight + 2
  338.     end
  339.    
  340.     if (fillAllTo64ButtonX == "auto") then
  341.         -- Puts the fill all to 64 button directly to the right of the refresh button
  342.         fillAllTo64ButtonX = refreshButtonX + refreshButtonWidth + 2
  343.     end
  344.    
  345.     if (fillAllTo64ButtonY == "auto") then
  346.         -- Puts the fill all to 64 button in line with the refresh button
  347.         fillAllTo64ButtonY = refreshButtonY
  348.     end
  349.    
  350.     if (fillAllTo128ButtonX == "auto") then
  351.         -- Puts the fill all to 64 button directly to the right of the fill all to 64 button
  352.         fillAllTo128ButtonX = fillAllTo64ButtonX
  353.     end
  354.    
  355.     if (fillAllTo128ButtonY == "auto") then
  356.         -- Puts the fill all to 64 button directly below the fill all to 64 button
  357.         fillAllTo128ButtonY = fillAllTo64ButtonY + fillAllTo64ButtonHeight + 2
  358.     end
  359.    
  360.     if (otherOptionsButtonX == "auto") then
  361.         -- Puts the other button directly to the left of the top off all jars button
  362.         otherOptionsButtonX = topoffAllButtonX - otherOptionsButtonWidth - 2
  363.     end
  364.    
  365.     if (otherOptionsButtonY == "auto") then
  366.         -- Puts the other button at the same level as the top off all button
  367.         otherOptionsButtonY = topoffAllButtonY
  368.     end
  369.    
  370.     if (emptyJarsX == "auto") then
  371.         emptyJarsX = essentiaX + 1
  372.     end
  373.  
  374.     if (emptyJarsY == "auto") then
  375.         emptyJarsY = essentiaY + essentiaColumnHeight + 1
  376.     end
  377.    
  378.     if (totalJarsX == "auto") then
  379.         totalJarsX = emptyJarsX
  380.     end
  381.    
  382.     if (totalJarsY == "auto") then
  383.         totalJarsY = emptyJarsY + 1
  384.     end
  385.    
  386.     if (refillScreenX == "auto") then
  387.         -- Centers the refill screen on the monitor - the refill screen is 41 pixels wide hard coded
  388.         refillScreenX = math.floor((monWidth - 41) / 2) + 1
  389.        
  390.         -- The monitor is too small
  391.         if (refillScreenX < 1) then
  392.             print("The monitor is too small width wise to display all the needed refill screen information correctly.")
  393.            
  394.             refillScreenX = 1
  395.         end
  396.     end
  397.    
  398.     if (essentiaTopOffJarsX == "auto") then
  399.         -- Centers the top off all essentia display on the monitor horizontally
  400.         essentiaTopOffJarsX = math.floor((monWidth - ((math.ceil(essentiasCount / essentiaColumnHeight) * (essentiaColumnWidth + essentiaColumnSpacing)) - essentiaColumnSpacing)) / 2) + 1
  401.        
  402.         -- The monitor is too small
  403.         if (essentiaTopOffJarsX < 1) then
  404.             print("The monitor is too small width wise to display all the needed top off all screen information correctly.")
  405.            
  406.             essentiaTopOffJarsX = 1
  407.         end
  408.     end
  409.    
  410.     if (essentiaTopOffLabelX == "auto") then
  411.         essentiaTopOffLabelX = essentiaTopOffJarsX + math.floor(((math.ceil(essentiasCount / essentiaColumnHeight) * (essentiaColumnWidth + essentiaColumnSpacing)) - essentiaColumnSpacing) / 2) -  math.ceil(string.len("Top off jars fill request") / 2)
  412.     end
  413.    
  414.     if (cancelTopOffJarsButtonX == "auto") then
  415.         cancelTopOffJarsButtonX = math.floor((monWidth / 2) - cancelTopOffJarsButtonWidth) + 1
  416.     end
  417.    
  418.     if (cancelTopOffJarsButtonY == "auto") then
  419.         cancelTopOffJarsButtonY = essentiaTopOffJarsY + essentiaColumnHeight + 1
  420.     end
  421.    
  422.     if (beginTopOffJarsFillButtonX == "auto") then
  423.         beginTopOffJarsFillButtonX = math.floor((monWidth / 2)) + 2
  424.     end
  425.    
  426.     if (beginTopOffJarsFillButtonY == "auto") then
  427.         beginTopOffJarsFillButtonY = essentiaTopOffJarsY + essentiaColumnHeight + 1
  428.     end
  429.    
  430.    
  431.     if (essentiaFillAllTo64X == "auto") then
  432.         -- Centers the top off all essentia display on the monitor horizontally
  433.         essentiaFillAllTo64X = math.floor((monWidth - ((math.ceil(essentiasCount / essentiaColumnHeight) * (essentiaColumnWidth + essentiaColumnSpacing)) - essentiaColumnSpacing)) / 2) + 1
  434.        
  435.         -- The monitor is too small
  436.         if (essentiaFillAllTo64X < 1) then
  437.             print("The monitor is too small width wise to display all the needed fill all to 64 screen information correctly.")
  438.            
  439.             essentiaFillAllTo64X = 1
  440.         end
  441.     end
  442.    
  443.     if (essentiaFillAllTo64LabelX == "auto") then
  444.         essentiaFillAllTo64LabelX = essentiaFillAllTo64X + math.floor(((math.ceil(essentiasCount / essentiaColumnHeight) * (essentiaColumnWidth + essentiaColumnSpacing)) - essentiaColumnSpacing) / 2) -  math.ceil(string.len("Fill all jars to 64 request") / 2) + 1
  445.     end
  446.    
  447.     if (cancelFillAllTo64ButtonX == "auto") then
  448.         cancelFillAllTo64ButtonX = math.floor((monWidth / 2) - cancelFillAllTo64ButtonWidth) + 1
  449.     end
  450.    
  451.     if (cancelFillAllTo64ButtonY == "auto") then
  452.         cancelFillAllTo64ButtonY = essentiaFillAllTo64Y + essentiaColumnHeight + 1
  453.     end
  454.    
  455.     if (beginFillAllTo64ButtonX == "auto") then
  456.         beginFillAllTo64ButtonX = math.floor((monWidth / 2)) + 2
  457.     end
  458.    
  459.     if (beginFillAllTo64ButtonY == "auto") then
  460.         beginFillAllTo64ButtonY = essentiaFillAllTo64Y + essentiaColumnHeight + 1
  461.     end
  462.    
  463.    
  464.     if (essentiaFillAllTo128X == "auto") then
  465.         -- Centers the top off all essentia display on the monitor horizontally
  466.         essentiaFillAllTo128X = math.floor((monWidth - ((math.ceil(essentiasCount / essentiaColumnHeight) * (essentiaColumnWidth + essentiaColumnSpacing)) - essentiaColumnSpacing)) / 2) + 1
  467.        
  468.         -- The monitor is too small
  469.         if (essentiaFillAllTo128X < 1) then
  470.             print("The monitor is too small width wise to display all the needed fill all to 128 screen information correctly.")
  471.            
  472.             essentiaFillAllTo128X = 1
  473.         end
  474.     end
  475.    
  476.     if (essentiaFillAllTo128LabelX == "auto") then
  477.         essentiaFillAllTo128LabelX = essentiaFillAllTo128X + math.floor(((math.ceil(essentiasCount / essentiaColumnHeight) * (essentiaColumnWidth + essentiaColumnSpacing)) - essentiaColumnSpacing) / 2) -  math.ceil(string.len("Fill all jars to 128 request") / 2) + 1
  478.     end
  479.    
  480.     if (cancelFillAllTo128ButtonX == "auto") then
  481.         cancelFillAllTo128ButtonX = math.floor((monWidth / 2) - cancelFillAllTo128ButtonWidth) + 1
  482.     end
  483.    
  484.     if (cancelFillAllTo128ButtonY == "auto") then
  485.         cancelFillAllTo128ButtonY = essentiaFillAllTo128Y + essentiaColumnHeight + 1
  486.     end
  487.    
  488.     if (beginFillAllTo128ButtonX == "auto") then
  489.         beginFillAllTo128ButtonX = math.floor((monWidth / 2)) + 2
  490.     end
  491.    
  492.     if (beginFillAllTo128ButtonY == "auto") then
  493.         beginFillAllTo128ButtonY = essentiaFillAllTo128Y + essentiaColumnHeight + 1
  494.     end
  495.    
  496.     if (burnScreenLabelX == "auto") then
  497.         burnScreenLabelX = math.floor((monWidth / 2) - (string.len("Burn request information") / 2)) + 1
  498.     end
  499.    
  500.     if (serverFriendly == true) then
  501.         serverFriendly = .05
  502.     else
  503.         serverFriendly = 0
  504.     end
  505. end
  506.  
  507. function sortEss(t)
  508.     local keys = {}
  509.     local k, i
  510.  
  511.     for k in pairs(t) do
  512.         keys[#keys+1] = k
  513.     end
  514.     table.sort(keys)
  515.  
  516.     i = 0
  517.     return function()
  518.         i = i + 1
  519.         if keys[i] then
  520.             return keys[i], t[keys[i]]
  521.         end
  522.     end
  523. end
  524.  
  525. function scanJars()
  526.     local myEmptyJars = 0
  527.     local myTotalJars = 0
  528.     local jars = {}
  529.     local jarID = 1
  530.     local aspect
  531.     local aspectCount
  532.     local i, j
  533.    
  534.     for i,j in ipairs(peripheral.getNames()) do
  535.         if (peripheral.getType(j) == "tt_aspectContainer") then
  536.             aspect = peripheral.call(j, "getAspects")
  537.             aspect = aspect[1]
  538.            
  539.             aspectCount = peripheral.call(j, "getAspectCount", aspect)
  540.            
  541.             if (aspectCount > 0) then
  542.                 jars[jarID] = {}
  543.                 jars[jarID]["aspect"] = aspect
  544.                 jars[jarID]["count"] = aspectCount
  545.                 jarID = jarID + 1
  546.                 myTotalJars = myTotalJars + 1
  547.             elseif (aspectCount == 0) then
  548.                 myEmptyJars = myEmptyJars + 1
  549.                 myTotalJars = myTotalJars + 1
  550.             end
  551.         end
  552.     end
  553.    
  554.     emptyJars = myEmptyJars
  555.     totalJars = myTotalJars
  556.    
  557.     return jars
  558. end
  559.  
  560. function updateEssentia()
  561.     local myJars
  562.     local myEssentia
  563.     local i, j
  564.    
  565.     myJars = scanJars()
  566.     myEssentia = essentiaList()
  567.    
  568.     for i in pairs(myJars) do
  569.         myEssentia[myJars[i]["aspect"]] = myEssentia[myJars[i]["aspect"]] + myJars[i]["count"]
  570.     end
  571.    
  572.     for i,j in sortEss(myEssentia) do
  573.         if (essentia[i] ~= j) then
  574.             essentia[i] = j
  575.         end
  576.     end
  577. end
  578.  
  579. function printEssentia()
  580.     local inactiveTextColor
  581.     local buttonName
  582.     local x, y
  583.     local i, j
  584.    
  585.     x = essentiaX
  586.     y = essentiaY
  587.    
  588.     for i,j in sortEss(essentia) do
  589.         inactiveTextColor = getEssentiaColor(j)
  590.        
  591.         buttonName = i .. string.sub(padding, 1, essentiaColumnWidth - (string.len(i) + string.len(pad(j)))) .. pad(j)
  592.         button.addButton(buttonName, essentiaButton, buttonName, x, y, essentiaColumnWidth, 0, essentiaInactiveBackColor, essentiaActiveBackColor, inactiveTextColor, essentiaActiveTextColor)
  593.        
  594.         if (y < (essentiaY + essentiaColumnHeight - 1)) then
  595.             y = y + 1
  596.         else
  597.             y = essentiaY
  598.             x = x + essentiaColumnWidth + essentiaColumnSpacing
  599.         end
  600.     end
  601. end
  602.  
  603. function getEssentiaColor(currentEssentiaAmount)
  604.     local myColor
  605.    
  606.     if (currentEssentiaAmount == 0) then
  607.         myColor = essentiaInactiveTextColorEmpty
  608.     elseif (currentEssentiaAmount <= 20) then
  609.         myColor = essentiaInactiveTextColorLow
  610.     elseif (currentEssentiaAmount < 100 and currentEssentiaAmount > 20) then
  611.         myColor = essentiaInactiveTextColorMedium
  612.     else
  613.         myColor = essentiaInactiveTextColorHigh
  614.     end
  615.    
  616.     return myColor
  617. end
  618.  
  619. function printEmptyJars()
  620.     m.setTextColor(emptyJarsTextColor)
  621.     m.setBackgroundColor(emptyJarsBackColor)
  622.    
  623.     m.setCursorPos(emptyJarsX, emptyJarsY)
  624.     m.write("Empty jars:" .. string.sub(padding, 1, essentiaColumnWidth - (string.len("Empty jars:") + string.len(pad(emptyJars))) - 1) .. pad(emptyJars))
  625. end
  626.  
  627. function printTotalJars()
  628.     m.setTextColor(totalJarsTextColor)
  629.     m.setBackgroundColor(totalJarsBackColor)
  630.    
  631.     m.setCursorPos(totalJarsX, totalJarsY)
  632.     m.write("Total jars:" .. string.sub(padding, 1, essentiaColumnWidth - (string.len("Total jars:") + string.len(pad(totalJars))) - 1) .. pad(totalJars))
  633. end
  634.  
  635. function pad(number, amount)
  636.     local myPadding = "000000"
  637.     local paddingRequired = 0
  638.    
  639.     if not (amount) then
  640.         amount = numberPadding
  641.     end
  642.    
  643.     paddingRequired = amount - string.len(tostring(number))
  644.  
  645.     if (paddingRequired ~= 0 and paddingRequired > 0) then
  646.         return string.sub(myPadding, 1, paddingRequired) .. tostring(number)
  647.     end
  648.    
  649.     return tostring(number)
  650. end
  651.  
  652. function getClick()
  653.     local event
  654.     local side
  655.     local x,y
  656.    
  657.     event,side,x,y = os.pullEvent()
  658.    
  659.     if (event == "monitor_touch") then
  660.         button.checkxy(x,y)
  661.     end
  662. end
  663.  
  664. function refresh(buttonToFlash)
  665.     -- Flash the refresh button
  666.     if (buttonToFlash) then
  667.         button.flash(buttonToFlash)
  668.     end
  669.    
  670.     -- Clear the screen and button list
  671.     m.setBackgroundColor(monBackColor)
  672.     m.clear()
  673.     button.clear()
  674.    
  675.     -- Scan and print the essentias
  676.     updateEssentia()
  677.     printEssentia()
  678.    
  679.     -- Print the number of empty jars
  680.     printEmptyJars()
  681.    
  682.     -- Print the number of jars
  683.     printTotalJars()
  684.    
  685.     -- Create the refresh button
  686.     addRefreshButton()
  687.    
  688.     -- Create the top off all jars button
  689.     addTopoffAllJarsButton()
  690.    
  691.     -- Create the fill all to 64 button
  692.     addFillAllTo64Button()
  693.    
  694.     -- Create the fill all to 128 button
  695.     addFillAllTo128Button()
  696.    
  697.     -- Create the other button
  698.     addOtherOptionsButton()
  699.    
  700.     -- Draw all the buttons on the screen
  701.     button.drawButtons()
  702. end
  703.  
  704. function addRefreshButton()
  705.     button.addButton("Refresh", refresh, "Refresh", refreshButtonX, refreshButtonY, refreshButtonWidth, refreshButtonHeight, refreshInactiveBackColor, refreshActiveBackColor, refreshInactiveTextColor, refreshActiveTextColor)
  706. end
  707.  
  708. function addTopoffAllJarsButton()
  709.     button.addButton("Top off all jars", topoffAllJars, "Top off all jars", topoffAllButtonX, topoffAllButtonY, topoffAllButtonWidth, topoffAllButtonHeight, topoffAllJarsInactiveBackColor, topoffAllJarsActiveBackColor, topoffAllJarsInactiveTextColor, topoffAllJarsActiveTextColor)
  710. end
  711.  
  712. function addFillAllTo64Button()
  713.     button.addButton("Fill all to 64", fillAllTo64, "Fill all to 64", fillAllTo64ButtonX, fillAllTo64ButtonY, fillAllTo64ButtonWidth, fillAllTo64ButtonHeight, fillAllTo64InactiveBackColor, fillAllTo64ActiveBackColor, fillAllTo64InactiveTextColor, fillAllTo64ActiveTextColor)
  714. end
  715.  
  716. function addFillAllTo128Button()
  717.     button.addButton("Fill all to 128", fillAllTo128, "Fill all to 128", fillAllTo128ButtonX, fillAllTo128ButtonY, fillAllTo128ButtonWidth, fillAllTo128ButtonHeight, fillAllTo128InactiveBackColor, fillAllTo128ActiveBackColor, fillAllTo128InactiveTextColor, fillAllTo128ActiveTextColor)
  718. end
  719.  
  720. function addOtherOptionsButton()
  721.     button.addButton("Reboot", otherOptions, "Reboot", otherOptionsButtonX, otherOptionsButtonY, otherOptionsButtonWidth, otherOptionsButtonHeight, otherOptionsButtonInactiveBackColor, otherOptionsButtonActiveBackColor, otherOptionsButtonInactiveTextColor, otherOptionsButtonActiveTextColor)
  722. end
  723.  
  724. function otherOptions(buttonName)
  725.     button.flash(buttonName)
  726.     os.reboot()
  727. end
  728.  
  729. function fillAllTo64(buttonName)
  730.     local aspect
  731.     local count
  732.     local essentiaToFill
  733.     local haveEssentiaToFill
  734.     local myEmptyJars
  735.    
  736.     -- The button is erased if jars to top off are found else it's toggled back below.
  737.     button.toggleButton(buttonName, true)
  738.     sleep(.15)
  739.    
  740.     essentiaToFill = essentiaList()
  741.     myEmptyJars = emptyJars
  742.     haveEssentiaToFill = false
  743.    
  744.     -- Update the list of essentias in all jars
  745.     updateEssentia()
  746.    
  747.     -- Checks each jar to see if any of them aren't full.
  748.     for aspect,count in pairs(essentia) do
  749.         if (count < 64) then
  750.             if (count == 0) then
  751.                 myEmptyJars = myEmptyJars - 1
  752.             end
  753.            
  754.             essentiaToFill[aspect] = 64 - count
  755.             haveEssentiaToFill = true
  756.         end
  757.     end
  758.    
  759.     if (haveEssentiaToFill == true) then
  760.         -- Not all essentia is at 64 or more, display the found essentias and confirm filling.
  761.         showFillAllTo64(essentiaToFill, myEmptyJars)
  762.     else
  763.         -- All essentia are above 64, rename the button and hold the text for a second so it can be read before reverting to the normal text and color.
  764.         button.renameButton(buttonName, "All jars at 64", true)
  765.         sleep(2.5)
  766.         button.toggleButton("All jars at 64", false)
  767.         button.renameButton("All jars at 64", buttonName, true)
  768.     end
  769. end
  770.  
  771. function showFillAllTo64(essentiaList, emptyJarsAfterFill)
  772.     local x, y
  773.     local myEssentia
  774.     local amount
  775.     local errorText
  776.    
  777.     fillAllTo64EssentiaList = essentiaList
  778.    
  779.     -- Clear the screen and button list
  780.     m.setBackgroundColor(monBackColor)
  781.     m.clear()
  782.     button.clear()
  783.    
  784.     x = essentiaFillAllTo64X
  785.     y = essentiaFillAllTo64Y
  786.    
  787.     m.setBackgroundColor(fillAllTo64EssentiaLabelBackColor)
  788.     m.setTextColor(fillAllTo64EssentiaLabelTextColor)
  789.    
  790.     m.setCursorPos(essentiaFillAllTo64LabelX, essentiaFillAllTo64LabelY)
  791.     m.write("Fill all jars to 64 request")
  792.    
  793.     m.setBackgroundColor(fillAllTo64EssentiaBackColor)
  794.    
  795.     for myEssentia,amount in sortEss(essentiaList) do
  796.         if (amount == 0) then
  797.             m.setTextColor(fillAllTo64EssentiaTextColorZero)
  798.         else
  799.             m.setTextColor(fillAllTo64EssentiaTextColorNonZero)
  800.         end
  801.        
  802.         m.setCursorPos(x, y)
  803.         m.write(string.upper(string.sub(myEssentia, 1, 1)) .. string.sub(myEssentia, 2) .. string.sub(padding, 1, essentiaColumnWidth - (string.len(myEssentia) + string.len(pad(amount)))) .. pad(amount))
  804.        
  805.         if (y < (essentiaFillAllTo64Y + essentiaColumnHeight - 1)) then
  806.             y = y + 1
  807.         else
  808.             y = essentiaFillAllTo64Y
  809.             x = x + essentiaColumnWidth + essentiaColumnSpacing
  810.         end
  811.     end
  812.    
  813.     button.addButton("Cancel filling", cancelFillAllTo64Button, "Cancel filling", cancelFillAllTo64ButtonX, cancelFillAllTo64ButtonY, cancelFillAllTo64ButtonWidth, cancelFillAllTo64ButtonHeight, cancelFillAllTo64ButtonInactiveBackColor, cancelFillAllTo64ButtonActiveBackColor, cancelFillAllTo64ButtonInactiveTextColor, cancelFillAllTo64ButtonActiveTextColor)
  814.     button.addButton("Begin filling", beginFillAllTo64Button, "Begin filling", beginFillAllTo64ButtonX, beginFillAllTo64ButtonY, beginFillAllTo64ButtonWidth, beginFillAllTo64ButtonHeight, beginFillAllTo64ButtonInactiveBackColor, beginFillAllTo64ButtonActiveBackColor, beginFillAllTo64ButtonInactiveTextColor, beginFillAllTo64ButtonActiveTextColor)
  815.    
  816.     if (emptyJarsAfterFill < 0) then
  817.         errorText = "NOT ENOUGH EMPTY JARS; HAVE " .. emptyJars .. " NEED "  .. (emptyJars - emptyJarsAfterFill)
  818.         m.setCursorPos(essentiaFillAllTo64LabelX + math.floor(string.len("Fill all jars to 64 request") / 2) - math.floor(string.len(errorText) / 2), essentiaFillAllTo64LabelY + 1)
  819.         m.setTextColor(colors.red)
  820.         m.write(errorText)
  821.         button.disableButton("Begin filling")
  822.     end
  823.    
  824.     button.drawButtons()
  825. end
  826.  
  827. function fillAllTo128(buttonName)
  828.     local aspect
  829.     local count
  830.     local essentiaToFill
  831.     local haveEssentiaToFill
  832.     local myEmptyJars
  833.     local myJars
  834.     local jar
  835.     local essentiaJarCount
  836.    
  837.     -- The button is erased if jars to top off are found else it's toggled back below.
  838.     button.toggleButton(buttonName, true)
  839.     sleep(.15)
  840.    
  841.     essentiaToFill = essentiaList()
  842.     essentiaJarCount = essentiaList()
  843.     myJars = scanJars()
  844.     myEmptyJars = emptyJars
  845.     haveEssentiaToFill = false
  846.    
  847.     -- Count how many jars of each aspect exist
  848.     for jar in pairs(myJars) do
  849.         essentiaJarCount[myJars[jar]["aspect"]] = essentiaJarCount[myJars[jar]["aspect"]] + 1
  850.     end
  851.    
  852.     -- Update the list of essentias in all jars
  853.     updateEssentia()
  854.    
  855.     -- Checks each jar to see if any of them aren't full.
  856.     for aspect,count in pairs(essentia) do
  857.         if (count < 128) then
  858.             if (count == 0) then
  859.                 myEmptyJars = myEmptyJars - 2
  860.             else
  861.                 if (essentiaJarCount[aspect] == 1) then
  862.                     if (count <= 64) then -- if it's above 64 the jar is probably an advanced thaumaturgy jar that holds 256
  863.                         myEmptyJars = myEmptyJars - 1
  864.                     end
  865.                 end
  866.             end
  867.            
  868.             essentiaToFill[aspect] = 128 - count
  869.             haveEssentiaToFill = true
  870.         end
  871.     end
  872.    
  873.     if (haveEssentiaToFill == true) then
  874.         -- Jars have been found that aren't full, display the found jars and confirm filling.
  875.         showFillAllTo128(essentiaToFill, myEmptyJars)
  876.     else
  877.         -- All essentia are above 128, rename the button and hold the text for a second so it can be read before reverting to the normal text and color.
  878.         button.renameButton(buttonName, "All jars at 128", true)
  879.         sleep(2.5)
  880.         button.toggleButton("All jars at 128", false)
  881.         button.renameButton("All jars at 128", buttonName, true)
  882.     end
  883. end
  884.  
  885. function showFillAllTo128(essentiaList, emptyJarsAfterFill)
  886.     local x, y
  887.     local myEssentia
  888.     local amount
  889.     local errorText
  890.    
  891.     fillAllTo128EssentiaList = essentiaList
  892.    
  893.     -- Clear the screen and button list
  894.     m.setBackgroundColor(monBackColor)
  895.     m.clear()
  896.     button.clear()
  897.    
  898.     x = essentiaFillAllTo128X
  899.     y = essentiaFillAllTo128Y
  900.    
  901.     m.setBackgroundColor(fillAllTo128EssentiaLabelBackColor)
  902.     m.setTextColor(fillAllTo128EssentiaLabelTextColor)
  903.     m.setCursorPos(essentiaFillAllTo128LabelX, essentiaFillAllTo128LabelY)
  904.     m.write("Fill all jars to 128 request")
  905.    
  906.     m.setBackgroundColor(fillAllTo128EssentiaBackColor)
  907.    
  908.     for myEssentia,amount in sortEss(essentiaList) do
  909.         if (amount == 0) then
  910.             m.setTextColor(fillAllTo128EssentiaTextColorZero)
  911.         else
  912.             m.setTextColor(fillAllTo128EssentiaTextColorNonZero)
  913.         end
  914.        
  915.         m.setCursorPos(x, y)
  916.         m.write(string.upper(string.sub(myEssentia, 1, 1)) .. string.sub(myEssentia, 2) .. string.sub(padding, 1, essentiaColumnWidth - (string.len(myEssentia) + string.len(pad(amount)))) .. pad(amount))
  917.        
  918.         if (y < (essentiaFillAllTo128Y + essentiaColumnHeight - 1)) then
  919.             y = y + 1
  920.         else
  921.             y = essentiaFillAllTo128Y
  922.             x = x + essentiaColumnWidth + essentiaColumnSpacing
  923.         end
  924.     end
  925.    
  926.     button.addButton("Cancel filling", cancelFillAllTo128Button, "Cancel filling", cancelFillAllTo128ButtonX, cancelFillAllTo128ButtonY, cancelFillAllTo128ButtonWidth, cancelFillAllTo128ButtonHeight, cancelFillAllTo128ButtonInactiveBackColor, cancelFillAllTo128ButtonActiveBackColor, cancelFillAllTo128ButtonInactiveTextColor, cancelFillAllTo128ButtonActiveTextColor)
  927.     button.addButton("Begin filling", beginFillAllTo128Button, "Begin filling", beginFillAllTo128ButtonX, beginFillAllTo128ButtonY, beginFillAllTo128ButtonWidth, beginFillAllTo128ButtonHeight, beginFillAllTo128ButtonInactiveBackColor, beginFillAllTo128ButtonActiveBackColor, beginFillAllTo128ButtonInactiveTextColor, beginFillAllTo128ButtonActiveTextColor)
  928.    
  929.     if (emptyJarsAfterFill < 0) then
  930.         errorText = "NOT ENOUGH EMPTY JARS; HAVE " .. emptyJars .. " NEED "  .. (emptyJars - emptyJarsAfterFill)
  931.        
  932.         m.setCursorPos(essentiaFillAllTo128LabelX + math.floor(string.len("Fill all jars to 128 request") / 2) - math.floor(string.len(errorText) / 2), essentiaFillAllTo128LabelY + 1)
  933.         m.setTextColor(colors.red)
  934.         m.write(errorText)
  935.         button.disableButton("Begin filling")
  936.     end
  937.    
  938.     button.drawButtons()
  939. end
  940.  
  941. function topoffAllJars(buttonName)
  942.     local myJars
  943.     local jar
  944.     local essentiaToFill
  945.     local haveEssentiaToFill
  946.    
  947.     -- The button is erased if jars to top off are found else it's toggled back below.
  948.     button.toggleButton(buttonName, true)
  949.     sleep(.15)
  950.    
  951.     -- Get a table of all the essentia jars
  952.     myJars = scanJars()
  953.     essentiaToFill = essentiaList()
  954.     haveEssentiaToFill = false
  955.    
  956.     -- Checks each jar to see if any of them aren't full.
  957.     for jar in pairs(myJars) do
  958.         if (myJars[jar]["count"] < 64) then
  959.             essentiaToFill[myJars[jar]["aspect"]] = essentiaToFill[myJars[jar]["aspect"]] + (64 - myJars[jar]["count"])
  960.             haveEssentiaToFill = true
  961.         elseif (myJars[jar]["count"] > 64) then -- Advanced Thaumaturgy jars hold 256
  962.             essentiaToFill[myJars[jar]["aspect"]] = essentiaToFill[myJars[jar]["aspect"]] + (256 - myJars[jar]["count"])
  963.             haveEssentiaToFill = true
  964.         end
  965.     end
  966.    
  967.     if (haveEssentiaToFill == true) then
  968.         -- Jars have been found that aren't full, display the found jars and confirm filling.
  969.         showTopOffAllJars(essentiaToFill)
  970.     else
  971.         -- No jars are found, rename the button and hold the text for a second so it can be read before reverting to the normal text and color.
  972.         button.renameButton(buttonName, "All jars full", true)
  973.         sleep(2.5)
  974.         button.toggleButton("All jars full", false)
  975.         button.renameButton("All jars full", buttonName, true)
  976.     end
  977. end
  978.  
  979. function showTopOffAllJars(essentiaList)
  980.     local x, y
  981.     local myEssentia
  982.     local essentiaText
  983.     local amount
  984.    
  985.     topOffJarsEssentiaList = essentiaList
  986.    
  987.     -- Clear the screen and button list
  988.     m.setBackgroundColor(monBackColor)
  989.     m.clear()
  990.     button.clear()
  991.    
  992.     x = essentiaTopOffJarsX
  993.     y = essentiaTopOffJarsY
  994.    
  995.     m.setBackgroundColor(topOffAllJarsEssentiaLabelBackColor)
  996.     m.setTextColor(topOffAllJarsEssentiaLabelTextColor)
  997.     m.setCursorPos(essentiaTopOffLabelX, essentiaTopOffLabelY)
  998.     m.write("Top off jars fill request")
  999.    
  1000.     m.setBackgroundColor(topOffAllJarsEssentiaBackColor)
  1001.    
  1002.     for myEssentia,amount in sortEss(essentiaList) do
  1003.         if (amount == 0) then
  1004.             m.setTextColor(topOffAllJarsEssentiaTextColorZero)
  1005.         else
  1006.             m.setTextColor(topOffAllJarsEssentiaTextColorNonZero)
  1007.         end
  1008.        
  1009.         m.setCursorPos(x, y)
  1010.         m.write(string.upper(string.sub(myEssentia, 1, 1)) .. string.sub(myEssentia, 2) .. string.sub(padding, 1, essentiaColumnWidth - (string.len(myEssentia) + string.len(pad(amount)))) .. pad(amount))
  1011.        
  1012.         if (y < (essentiaTopOffJarsY + essentiaColumnHeight - 1)) then
  1013.             y = y + 1
  1014.         else
  1015.             y = essentiaTopOffJarsY
  1016.             x = x + essentiaColumnWidth + essentiaColumnSpacing
  1017.         end
  1018.     end
  1019.    
  1020.     button.addButton("Cancel filling", cancelTopOffJarsButton, "Cancel filling", cancelTopOffJarsButtonX, cancelTopOffJarsButtonY, cancelTopOffJarsButtonWidth, cancelTopOffJarsButtonHeight, cancelTopOffJarsButtonInactiveBackColor, cancelTopOffJarsButtonActiveBackColor, cancelTopOffJarsButtonInactiveTextColor, cancelTopOffJarsButtonActiveTextColor)
  1021.     button.addButton("Begin filling", beginTopOffJarsFillButton, "Begin filling", beginTopOffJarsFillButtonX, beginTopOffJarsFillButtonY, beginTopOffJarsFillButtonWidth, beginTopOffJarsFillButtonHeight, beginTopOffJarsFillButtonInactiveBackColor, beginTopOffJarsFillButtonActiveBackColor, beginTopOffJarsFillButtonInactiveTextColor, beginTopOffJarsFillButtonActiveTextColor)
  1022.    
  1023.     button.drawButtons()
  1024. end
  1025.  
  1026. function cancelTopOffJarsButton(buttonName)
  1027.     button.flash(buttonName)
  1028.     topOffJarsEssentiaList = nil
  1029.     refresh()
  1030. end
  1031.  
  1032. function beginTopOffJarsFillButton(buttonName)
  1033.     local beanType
  1034.     local amountToBurn
  1035.     local burnCount
  1036.    
  1037.     button.flash(buttonName)
  1038.    
  1039.     drawBurnMainScreen()
  1040.     allBurnResults = {}
  1041.     for beanType,amountToBurn in sortEss(topOffJarsEssentiaList) do
  1042.         if (amountToBurn ~= 0) then
  1043.             updateBurnBeanType(beanType)
  1044.             burnCount = burnBeans(beanType, amountToBurn)
  1045.            
  1046.            
  1047.             print("")
  1048.             print(beanType)
  1049.             print("Burned: " .. burnCount)
  1050.            
  1051.             if (burnCount == -100) then
  1052.                 print(translateBurnResultToText(burnCount))
  1053.                 break
  1054.             end
  1055.         end
  1056.     end
  1057.    
  1058.     refresh()
  1059. end
  1060.  
  1061. function cancelFillAllTo64Button(buttonName)
  1062.     button.flash(buttonName)
  1063.     fillAllTo64EssentiaList = nil
  1064.     refresh()
  1065. end
  1066.  
  1067. function beginFillAllTo64Button(buttonName)
  1068.     local beanType
  1069.     local amountToBurn
  1070.     local burnCount
  1071.    
  1072.     button.flash(buttonName)
  1073.    
  1074.     drawBurnMainScreen()
  1075.     allBurnResults = {}
  1076.     for beanType,amountToBurn in sortEss(fillAllTo64EssentiaList) do
  1077.         if (amountToBurn ~= 0) then
  1078.             updateBurnBeanType(beanType)
  1079.             burnCount = burnBeans(beanType, amountToBurn)
  1080.            
  1081.            
  1082.             print("")
  1083.             print(beanType)
  1084.             print("Burned: " .. burnCount)
  1085.            
  1086.             if (burnCount == -100) then
  1087.                 print(translateBurnResultToText(burnCount))
  1088.                 break
  1089.             end
  1090.         end
  1091.     end
  1092.    
  1093.     refresh()
  1094. end
  1095.  
  1096. function cancelFillAllTo128Button(buttonName)
  1097.     button.flash(buttonName)
  1098.     fillAllTo128EssentiaList = nil
  1099.     refresh()
  1100. end
  1101.  
  1102. function beginFillAllTo128Button(buttonName)
  1103.     local beanType
  1104.     local amountToBurn
  1105.     local burnCount
  1106.     local bk, bv
  1107.    
  1108.     button.flash(buttonName)
  1109.    
  1110.     drawBurnMainScreen()
  1111.     for beanType,amountToBurn in sortEss(fillAllTo128EssentiaList) do
  1112.         if (amountToBurn ~= 0) then
  1113.             updateBurnBeanType(beanType)
  1114.             burnCount = burnBeans(beanType, amountToBurn)
  1115.            
  1116.             print("")
  1117.             print(beanType)
  1118.             print("Burned: " .. burnCount)
  1119.            
  1120.             if (burnCount == -100) then
  1121.                 print(translateBurnResultToText(burnCount))
  1122.                 break
  1123.             end
  1124.         end
  1125.     end
  1126.    
  1127.     refresh()
  1128. end
  1129.  
  1130. function essentiaButton(which)
  1131.     local buttonEssentiaName
  1132.     local availableEssentiaSpace = 0
  1133.     local myJars
  1134.     local essentiaCount = 0
  1135.     local i
  1136.    
  1137.     myJars = scanJars()
  1138.     button.flash(which)
  1139.     buttonEssentiaName = string.sub(which, 1, string.find(which, " ") - 1)
  1140.    
  1141.     for i in pairs(myJars) do
  1142.         if (myJars[i]["aspect"] == buttonEssentiaName) then
  1143.             availableEssentiaSpace = availableEssentiaSpace + (64 - myJars[i]["count"])
  1144.             essentiaCount = essentiaCount + myJars[i]["count"]
  1145.         end
  1146.     end
  1147.    
  1148.     showRefillEssentia(buttonEssentiaName, essentiaCount, availableEssentiaSpace)
  1149. end
  1150.  
  1151. function showRefillEssentia(essentiaName, essentiaCount, availableEssentiaSpace)
  1152.     local fillingText
  1153.    
  1154.     fillEssentia =  essentiaName
  1155.     fillCurrentAmount = essentiaCount
  1156.     fillAmount = 0
  1157.     fillAvailableSpace = availableEssentiaSpace
  1158.    
  1159.     button.clear()
  1160.     m.setBackgroundColor(monBackColor)
  1161.     m.clear()
  1162.    
  1163.     m.setTextColor(refillLabelTextColor)
  1164.     fillingText = "Refilling: " .. string.upper(string.sub(fillEssentia, 1, 1)) .. string.sub(fillEssentia, 2)
  1165.     m.setCursorPos(refillScreenX + math.floor((41 - string.len(fillingText)) / 2), refillScreenY)
  1166.     m.write(fillingText)
  1167.    
  1168.     if (fillAvailableSpace == 0 and emptyJars == 0) then
  1169.         m.setCursorPos(refillScreenX + math.floor((41 - string.len("ALL JARS USED OR FULL")) / 2), refillScreenY + 1)
  1170.         m.setTextColor(colors.red)
  1171.         m.write("ALL JARS USED OR FULL")
  1172.     end
  1173.    
  1174.    
  1175.     m.setTextColor(refillCurrentAmountTextColor)
  1176.     m.setCursorPos(refillScreenX, refillScreenY + 2)
  1177.     m.write("Currently contains:" .. string.sub(padding, 1, 41 - (string.len("Currently contains:") + string.len(pad(fillCurrentAmount)))) .. pad(fillCurrentAmount))
  1178.    
  1179.     m.setTextColor(refillAddingAmountTextColor)
  1180.     m.setCursorPos(refillScreenX, refillScreenY + 3)
  1181.     m.write("Currently adding:" .. string.sub(padding, 1, 41 - (string.len("Currently adding:") + string.len(pad(fillAmount)))) .. pad(fillAmount))
  1182.    
  1183.     m.setTextColor(getEssentiaColor(fillCurrentAmount))
  1184.     m.setCursorPos(refillScreenX, refillScreenY + 4)
  1185.     m.write("Total after filling:" .. string.sub(padding, 1, 41 - (string.len("Total after filling:") + string.len(pad(fillCurrentAmount)))) .. pad(fillCurrentAmount))
  1186.    
  1187.     button.addButton("+1", addEssentia, "+1", refillScreenX, refillScreenY + 6, 10, 2, refillButtonsInactiveBackColor, refillButtonsActiveBackColor, refillButtonsInactiveTextColor, refillButtonsActiveTextColor)
  1188.     button.addButton("+5", addEssentia, "+5", refillScreenX + 11, refillScreenY + 6, 9, 2, refillButtonsInactiveBackColor, refillButtonsActiveBackColor, refillButtonsInactiveTextColor, refillButtonsActiveTextColor)
  1189.     button.addButton("+10", addEssentia, "+10", refillScreenX + 21, refillScreenY + 6, 9, 2, refillButtonsInactiveBackColor, refillButtonsActiveBackColor, refillButtonsInactiveTextColor, refillButtonsActiveTextColor)
  1190.     button.addButton("+64", addEssentia, "+64", refillScreenX + 31, refillScreenY + 6, 10, 2, refillButtonsInactiveBackColor, refillButtonsActiveBackColor, refillButtonsInactiveTextColor, refillButtonsActiveTextColor)
  1191.    
  1192.     button.addButton("-1", addEssentia, "-1", refillScreenX, refillScreenY + 10, 10, 2, refillButtonsInactiveBackColor, refillButtonsActiveBackColor, refillButtonsInactiveTextColor, refillButtonsActiveTextColor)
  1193.     button.addButton("-5", addEssentia, "-5", refillScreenX + 11, refillScreenY + 10, 9, 2, refillButtonsInactiveBackColor, refillButtonsActiveBackColor, refillButtonsInactiveTextColor, refillButtonsActiveTextColor)
  1194.     button.addButton("-10", addEssentia, "-10", refillScreenX + 21, refillScreenY + 10, 9, 2, refillButtonsInactiveBackColor, refillButtonsActiveBackColor, refillButtonsInactiveTextColor, refillButtonsActiveTextColor)
  1195.     button.addButton("-64", addEssentia, "-64", refillScreenX + 31, refillScreenY + 10, 10, 2, refillButtonsInactiveBackColor, refillButtonsActiveBackColor, refillButtonsInactiveTextColor, refillButtonsActiveTextColor)
  1196.    
  1197.     button.addButton("Top off jar(s)", addEssentia, "Top off jar(s)", refillScreenX, refillScreenY + 14, 20, 2, refillButtonsInactiveBackColor, refillButtonsActiveBackColor, refillButtonsInactiveTextColor, refillButtonsActiveTextColor)
  1198.     button.addButton("Max fill", addEssentia, "Max fill", refillScreenX + 21, refillScreenY + 14, 20, 2, refillButtonsInactiveBackColor, refillButtonsActiveBackColor, refillButtonsInactiveTextColor, refillButtonsActiveTextColor)
  1199.    
  1200.     button.addButton("Cancel filling", refresh, "Cancel filling", refillScreenX, refillScreenY + 18, 41, 2, refillButtonsInactiveBackColor, refillButtonsActiveBackColor, refillButtonsInactiveTextColor, refillButtonsActiveTextColor)
  1201.    
  1202.     button.addButton("Begin filling", buttonBeginRefill, "Begin filling", refillScreenX, refillScreenY + 22, 41, 2, refillButtonsInactiveBackColor, refillButtonsActiveBackColor, refillButtonsInactiveTextColor, refillButtonsActiveTextColor)
  1203.    
  1204.     button.drawButtons()
  1205. end
  1206.  
  1207. function addEssentia(amount)
  1208.     local myFillAmount
  1209.    
  1210.     myFillAmount = fillAmount
  1211.    
  1212.     --print(fillAmount .. " before")
  1213.    
  1214.     button.flash(amount)
  1215.    
  1216.     if (amount == "Top off jar(s)") then
  1217.         fillAmount = fillAvailableSpace
  1218.     elseif (amount == "Max fill") then
  1219.         fillAmount = fillAvailableSpace + (emptyJars * 64)
  1220.     else
  1221.         fillAmount = fillAmount + tonumber(amount)
  1222.     end
  1223.    
  1224.     if (fillAmount < 0) then
  1225.         --print(fillAmount .. " is less than 0 - setting to 0")
  1226.         fillAmount = 0
  1227.     elseif (fillAmount > fillAvailableSpace) then
  1228.         if (emptyJars > 0) then
  1229.             if (fillAmount > (fillAvailableSpace + (emptyJars * 64))) then
  1230.                 fillAmount = fillAvailableSpace + (emptyJars * 64)
  1231.             end
  1232.         else
  1233.             fillAmount = fillAvailableSpace
  1234.         end
  1235.     end
  1236.    
  1237.     if (fillAmount ~= myFillAmount) then
  1238.         m.setBackgroundColor(monBackColor)
  1239.        
  1240.         m.setTextColor(refillAddingAmountTextColor)
  1241.         m.setCursorPos(refillScreenX, refillScreenY + 3)
  1242.         m.write("Currently adding:" .. string.sub(padding, 1, 41 - (string.len("Currently adding:") + string.len(pad(fillAmount)))) .. pad(fillAmount))
  1243.        
  1244.         m.setTextColor(getEssentiaColor(fillCurrentAmount + fillAmount))
  1245.         m.setCursorPos(refillScreenX, refillScreenY + 4)
  1246.         m.write("Total after filling:" .. string.sub(padding, 1, 41 - (string.len("Total after filling:") + string.len(pad(fillCurrentAmount + fillAmount)))) .. pad(fillCurrentAmount + fillAmount))
  1247.     end
  1248. end
  1249.  
  1250. -- Standard refill button
  1251. function buttonBeginRefill(buttonName)
  1252.     local burnCount
  1253.    
  1254.     button.flash(buttonName)
  1255.    
  1256.     if (fillAmount ~= 0) then
  1257.         drawBurnMainScreen()
  1258.         updateBurnBeanType(fillEssentia)
  1259.         burnCount = burnBeans(fillEssentia, fillAmount)
  1260.        
  1261.         print("")
  1262.         print("Burned: " .. burnCount)
  1263.        
  1264.         print(translateBurnResultToText(burnCount))
  1265.     end
  1266.    
  1267.     refresh()
  1268. end
  1269.  
  1270. function translateBurnResultToText(burnResult)
  1271.     if (burnResult == -100) then
  1272.         return "Aborted"
  1273.     end
  1274. end
  1275.  
  1276. maximumLength = 0
  1277.  
  1278. function updateBurnStatus(newStatus)
  1279.     local monWidth, monHeight
  1280.     local pos
  1281.     local writeWidth
  1282.     local y
  1283.    
  1284.     monWidth, monHeight = m.getSize()
  1285.     writeWidth = monWidth - 10
  1286.     pos = 1
  1287.    
  1288.     for y = 0, 3 do
  1289.         m.setCursorPos(burnScreenStatusX, y + burnScreenStatusY + 2)
  1290.         m.write(string.sub(padding, 1, writeWidth))
  1291.         m.setCursorPos(burnScreenStatusX, y + burnScreenStatusY + 2)
  1292.         m.write(string.sub(newStatus, pos, writeWidth + pos - 1))
  1293.         pos = pos + writeWidth
  1294.     end
  1295. end
  1296.  
  1297. function updateBurnBeanType(newBean)
  1298.     m.setCursorPos(burnScreenBeanLabelX + string.len(burnScreenBeanTextLabel) + 1, burnScreenBeanLabelY)
  1299.     m.write(string.upper(string.sub(newBean, 1, 1)) .. string.sub(newBean, 2) .. string.sub(padding, 1, 15 - string.len(newBean)))
  1300. end
  1301.  
  1302. function drawBurnMainScreen()
  1303.     local monWidth
  1304.     local monHeight
  1305.     local x, y
  1306.    
  1307.     -- Clears the screen before creating the information burn screen
  1308.     button.clear()
  1309.     m.setBackgroundColor(monBackColor)
  1310.     m.clear()
  1311.    
  1312.     -- Draws the border on the screen
  1313.     monWidth,monHeight = m.getSize()
  1314.     m.setBackgroundColor(burnScreenBorderColor)
  1315.    
  1316.     m.setCursorPos(1, 1)
  1317.     m.write(string.sub(padding, 1, monWidth))
  1318.     m.setCursorPos(1, monHeight)
  1319.     m.write(string.sub(padding, 1, monWidth))
  1320.    
  1321.     for y = 0, monHeight do
  1322.         m.setCursorPos(1, y)
  1323.         m.write("  ")
  1324.         m.setCursorPos(monWidth - 1, y)
  1325.         m.write("  ")
  1326.     end
  1327.    
  1328.     -- Draws the label text
  1329.     m.setBackgroundColor(burnScreenLabelBackColor)
  1330.     m.setTextColor(burnScreenLabelTextColor)
  1331.     m.setCursorPos(burnScreenLabelX, burnScreenLabelY)
  1332.     m.write("Burn request information")
  1333.    
  1334.     m.setBackgroundColor(burnScreenBeanLabelBackColor)
  1335.     m.setTextColor(burnScreenBeanLabelTextColor)
  1336.     m.setCursorPos(burnScreenBeanLabelX, burnScreenBeanLabelY)
  1337.     m.write(burnScreenBeanTextLabel)
  1338.    
  1339.     m.setBackgroundColor(burnScreenBeanLabelBackColor)
  1340.     m.setTextColor(burnScreenBeanLabelTextColor)
  1341.     m.setCursorPos(burnScreenStatusX, burnScreenStatusY)
  1342.     m.write(burnScreenStatusTextLabel)
  1343. end
  1344.  
  1345.  
  1346.  
  1347.  
  1348.  
  1349.  
  1350.  
  1351.  
  1352.  
  1353.  
  1354.  
  1355.  
  1356.  
  1357.  
  1358.  
  1359.  
  1360.  
  1361.  
  1362.  
  1363.  
  1364.  
  1365.  
  1366.  
  1367.  
  1368.  
  1369.  
  1370.  
  1371.  
  1372.  
  1373.  
  1374.  
  1375.  
  1376.  
  1377.  
  1378.  
  1379.  
  1380.  
  1381.  
  1382.  
  1383.  
  1384.  
  1385.  
  1386.  
  1387.  
  1388.  
  1389.  
  1390.  
  1391.  
  1392.  
  1393.  
  1394.  
  1395.  
  1396.  
  1397.  
  1398.  
  1399.  
  1400.  
  1401.  
  1402.  
  1403.  
  1404.  
  1405.  
  1406.  
  1407. --[[
  1408.  
  1409.     The functions below are used to track mana beans in connected chests and put them in the alchemical furnaces.
  1410.  
  1411. --]]
  1412.  
  1413. function executeBurn(chest, beanType, amount, returnIfStuck)
  1414.     local amountBurned
  1415.     local stack
  1416.     local slot
  1417.     local direction
  1418.     local directions
  1419.     local aspect
  1420.     local count
  1421.     local validBeanCount
  1422.     local waitingForBeans
  1423.     local amountToBurn
  1424.     local waitingForFurnace
  1425.    
  1426.     -- No beans for this type have ever been found.
  1427.     if (chests[chest][beanType] == nil) then
  1428.         return 0
  1429.     end
  1430.    
  1431.     if (returnIfStuck ~= false and returnIfStuck ~= true) then
  1432.         returnIfStuck = false
  1433.     end
  1434.    
  1435.     updateBurnStatus("attempting to burn beans")
  1436.    
  1437.     if (alchemicalFurnaceFromChestDirection == "auto") then
  1438.         directions = validFurnaceDirections()
  1439.     else
  1440.         directions = {[alchemicalFurnaceFromChestDirection] = true}
  1441.     end
  1442.    
  1443.     amountToBurn = amount
  1444.     waitingForBeans = 0
  1445.     waitingForFurnace = 0
  1446.    
  1447.     while (amountToBurn > 0) do
  1448.         amountBurned = 0
  1449.         for slot in pairs(chests[chest][beanType]) do
  1450.             stack = peripheral.call(chests[chest]["peripheral name"], "getStackInSlot", slot)
  1451.            
  1452.             if (stack ~= nil and stack.qty > 2) then
  1453.                 count = amountToBurn - amountBurned
  1454.                
  1455.                 if (count > (stack.qty - 2)) then
  1456.                     count = stack.qty - 2
  1457.                     waitingForBeans = 0
  1458.                 end
  1459.             else
  1460.                 count = 0
  1461.             end
  1462.            
  1463.             if (count ~= 0) then
  1464.                 while (count > 0) do
  1465.                     for direction in pairs(directions) do
  1466.                         if (count > 0) then
  1467.                             burned = peripheral.call(chests[chest]["peripheral name"], "pushItemIntoSlot", direction, slot, count, 1)
  1468.                             count = count - burned
  1469.                             amountBurned = amountBurned + burned
  1470.                            
  1471.                             if (burned ~= 0) then
  1472.                                 waitingForFurnace = 0
  1473.                             end
  1474.                            
  1475.                             sleep(serverFriendly)
  1476.                         end
  1477.                     end
  1478.                    
  1479.                     if (count > 0) then
  1480.                         -- Failed to put all the beans into the attached furnace(s)
  1481.                         if (waitingForFurnace == 1 and returnIfStuck == true) then
  1482.                             return amount - (amountToBurn - amountBurned)
  1483.                         elseif (waitingForFurnace == 0) then
  1484.                             print("Furnace(s) full, waiting for furnace(s) to have room...")
  1485.                             updateBurnStatus("furnace(s) full, waiting for them to have room")
  1486.                         end
  1487.                        
  1488.                         waitingForFurnace = 1
  1489.                         sleep(1)
  1490.                     end
  1491.                 end
  1492.             else
  1493.                 sleep(serverFriendly)
  1494.             end
  1495.         end
  1496.        
  1497.         if (amountBurned == 0) then
  1498.             -- Out of beans
  1499.             if (waitingForBeans == 1 and returnIfStuck == true) then
  1500.                 return amount - (amountToBurn - amountBurned)
  1501.             elseif (waitingForBeans == 0) then
  1502.                 print("Out of bean type " .. beanType .. " in chest " .. chests[chest]["peripheral name"] .. ". There needs to be more than 2 beans (in a given stack) to burn them...")
  1503.                 updateBurnStatus("out of " .. beanType .. " in chest " .. chests[chest]["peripheral name"] .. " - waiting for refill")
  1504.             end
  1505.            
  1506.             waitingForBeans = 1
  1507.             --enableRefill()
  1508.             sleep(1)
  1509.             --disableRefill()
  1510.         else
  1511.             waitingForBeans = 0
  1512.         end
  1513.        
  1514.         amountToBurn = amountToBurn - amountBurned
  1515.     end
  1516.    
  1517.     -- This should always calculate to amount but just in case it doesn't, it's not set static.
  1518.     return (amount - amountToBurn)
  1519. end
  1520.  
  1521. function validFurnaceDirections()
  1522.     return {["north"] = true, ["south"] = true, ["east"] = true, ["west"] = true}
  1523. end
  1524.  
  1525. function burnBeans(beanType, amount)
  1526.     local remainingAmount
  1527.     local ci
  1528.     local continue
  1529.     local amountBurned
  1530.     local amountToBurn
  1531.     local chestsWithAspect
  1532.    
  1533.     amountBurned = 0
  1534.     remainingAmount = amount
  1535.     chestsWithAspect = {}
  1536.     chestsBurnResult = {}
  1537.    
  1538.     if (chestAspects[beanType] == 0) then
  1539.         -- No chests contain the bean type
  1540.         return 0, nil
  1541.     else
  1542.         for ci in pairs(chests) do
  1543.             if (chests[ci][beanType] ~= nil) then
  1544.                 chestsWithAspect[ci] = true
  1545.             end
  1546.         end
  1547.        
  1548.         if (distributeBurnRequests == true) then
  1549.             continue = true
  1550.            
  1551.             while (continue) do
  1552.                 for ci in pairs(chestsWithAspect) do
  1553.                     if (rs.getInput("left") == true) then
  1554.                         return -100
  1555.                     end
  1556.                     amountToBurn = 64
  1557.                    
  1558.                     if ((remainingAmount - amountToBurn) < 0) then
  1559.                         amountToBurn = remainingAmount
  1560.                     end
  1561.                    
  1562.                     amountBurned = executeBurn(ci, beanType, amountToBurn, true)
  1563.                     remainingAmount = remainingAmount - amountBurned
  1564.                    
  1565.                     if (remainingAmount <= 0) then
  1566.                         continue = false
  1567.                         break
  1568.                     end
  1569.                 end
  1570.                
  1571.                 if (continue == true) then
  1572.                     sleep(5)
  1573.                 end
  1574.             end
  1575.         else
  1576.             for ci in pairs(chestsWithAspect) do
  1577.                 amountBurned = executeBurn(ci, beanType, remainingAmount)
  1578.                
  1579.                 remainingAmount = remainingAmount - amountBurned
  1580.                
  1581.                 if (remainingAmount <= 0) then
  1582.                     break
  1583.                 end
  1584.             end
  1585.         end
  1586.     end
  1587.    
  1588.     return (amount - remainingAmount)
  1589. end
  1590.  
  1591. function getValidChestNames()
  1592.     local chests = {
  1593.         ["container_chest"] = true,
  1594.         ["iron"] = true,
  1595.         ["gold"] = true,
  1596.         ["diamond"] = true,
  1597.         ["crystal"] = true,
  1598.         ["obsidian"] = true,
  1599.         ["copper"] = true,
  1600.         ["silver"] = true
  1601.         }
  1602.    
  1603.     return chests
  1604. end
  1605.  
  1606. function findChestsAndAnalyzers()
  1607.     local i, j
  1608.     local peripheralType
  1609.     local validChestNames
  1610.     local myChestID
  1611.     local myAnalyzerID
  1612.    
  1613.     validChestNames = getValidChestNames()
  1614.     myChestId = 1
  1615.     myAnalyzerID = 1
  1616.    
  1617.     for i,j in ipairs(peripheral.getNames()) do
  1618.         peripheralType = peripheral.getType(j)
  1619.        
  1620.         if (validChestNames[peripheralType] == true) then
  1621.             if (debugOutput > 1) then
  1622.                 print("Valid chest found: " .. peripheralType .. " size: " .. peripheral.call(j, "getInventorySize"))
  1623.             end
  1624.            
  1625.             chests[myChestId] = {}
  1626.             chests[myChestId]["peripheral name"] = j
  1627.             myChestId = myChestId + 1
  1628.         elseif (peripheralType == "tt_aspectanalyzer") then
  1629.             if (debugOutput > 1) then
  1630.                 print("Aspect analyzer found: " .. j)
  1631.             end
  1632.            
  1633.             aspectAnalyzers[myAnalyzerID] = {}
  1634.             aspectAnalyzers[myAnalyzerID]["peripheral name"] = j
  1635.             myAnalyzerID = myAnalyzerID + 1
  1636.         end
  1637.     end
  1638. end
  1639.  
  1640. function printChestAspects()
  1641.     local ci
  1642.     local e, s, i
  1643.     local myEssentias
  1644.     local chestEssentia
  1645.    
  1646.     myEssentias = essentiaList()
  1647.    
  1648.     for ci in pairs(chests) do
  1649.         chestEssentia = ""
  1650.        
  1651.         for e, i in pairs(chests[ci]) do
  1652.             if not (string.find(e, " ")) then
  1653.                 for s in pairs(i) do
  1654.                     chestEssentia = chestEssentia .. e .. ":" .. s .. ", "
  1655.                 end
  1656.             end
  1657.         end
  1658.        
  1659.         if (chestEssentia ~= nil) then
  1660.             print("Chest " .. ci .. ": " .. string.sub(chestEssentia, 1, string.len(chestEssentia) - 2))
  1661.         end
  1662.        
  1663.         print("")
  1664.     end
  1665.    
  1666.     for ci in pairs(chests) do
  1667.         print("Chest: " .. ci .. " analyze time: " .. chests[ci]["analyze time"])
  1668.     end
  1669. end
  1670.  
  1671. function analyzeChestsContents()
  1672.     local ci
  1673.     local e
  1674.     local slot
  1675.     local chestContents
  1676.     local aspect
  1677.     local count
  1678.     local startTime
  1679.     local endTime
  1680.     local missingAspects
  1681.    
  1682.     chestAspects = essentiaList()
  1683.    
  1684.     for ci in pairs(chests) do
  1685.         if (debugOutput > 1) then
  1686.             print("Analyzing chest contents " .. ci)
  1687.         end
  1688.        
  1689.         chestContents = peripheral.call(chests[ci]["peripheral name"], "getAllStacks")
  1690.         startTime = os.clock()
  1691.         for slot in pairs(chestContents) do
  1692.             if (chestContents[slot].name == "Mana Bean") then
  1693.                 aspect,count = scanItemInSlot(chests[ci]["aspect analyzer"], chests[ci]["peripheral name"], slot, chestContents[slot].qty)
  1694.                
  1695.                 if (aspect ~= nil) then
  1696.                     if (chests[ci][aspect] == nil) then
  1697.                         chests[ci][aspect] = {}
  1698.                     end
  1699.                    
  1700.                     chests[ci][aspect][slot] = true
  1701.                     chestAspects[aspect] = 1
  1702.                    
  1703.                     if (debugOutput > 1) then
  1704.                         print("Found mana bean in chest " .. ci .. " slot " .. slot .. " of aspect type " .. aspect)
  1705.                     end
  1706.                 else
  1707.                     print("Mana bean in chest " .. ci .. " slot " .. slot .. " needs refilling; only " .. count .. " left.")
  1708.                 end
  1709.             end
  1710.         end
  1711.        
  1712.         chests[ci]["analyze time"] = os.clock() - startTime
  1713.        
  1714.         if (debugOutput > 0) then
  1715.             print("Time to analyze chest " .. ci .. " " .. (os.clock() - startTime))
  1716.         end
  1717.     end
  1718.    
  1719.     missingAspects = ""
  1720.     for e in pairs(chestAspects) do
  1721.         if (chestAspects[e] == 0) then
  1722.             if (missingAspects ~= "") then
  1723.                 missingAspects = missingAspects .. ", "
  1724.             end
  1725.            
  1726.             missingAspects = missingAspects .. e
  1727.         end
  1728.     end
  1729.    
  1730.     if (missingAspects ~= "") then
  1731.         print("WARNING: Not every aspect was found in the connected chests. You won't be able to refill them unless they're added to the chest(s).")
  1732.         print("")
  1733.         print("Missing aspects: " .. missingAspects)
  1734.     end
  1735. end
  1736.  
  1737. function scanItemInSlot(aspectAnalyzer, chest, slot, quantity)
  1738.     local aspect
  1739.     local stack
  1740.    
  1741.     if (quantity == nil) then
  1742.         stack = peripheral.call(chest, "getStackInSlot", slot)
  1743.         if (stack ~= nil) then
  1744.             quantity = stack.qty
  1745.         else
  1746.             quantity = 0
  1747.         end
  1748.     end
  1749.    
  1750.     if (quantity <= 2) then
  1751.         return nil, quantity
  1752.     end
  1753.    
  1754.     if (peripheral.call(chest, "pushItemIntoSlot", "down", slot, 1, 1) == 0) then
  1755.         print("Failed to push mana bean from chest " .. chest .. " slot " .. slot .. " into aspect analyzer. Program halted. !!RESTART REQUIRED!!")
  1756.        
  1757.         -- Something went wrong, wait for human intervention.
  1758.         while (true) do
  1759.             sleep(60)
  1760.         end
  1761.     end
  1762.    
  1763.     aspect = peripheral.call(aspectAnalyzer, "getAspects")
  1764.    
  1765.     if (peripheral.call(chest, "pullItemIntoSlot", "down", 1, 1, slot) == 0) then
  1766.         print("Failed to pull mana bean from aspect analyzer " .. aspectAnalyzer .. " back into chest " .. chest .. " slot " .. slot .. ". Program halted. !!RESTART REQUIRED!!")
  1767.        
  1768.         -- Something went wrong, wait for human intervention.
  1769.         while (true) do
  1770.             sleep(60)
  1771.         end
  1772.     end
  1773.    
  1774.     return aspect, quantity
  1775. end
  1776.  
  1777. function matchChestsWithAnalyzer()
  1778.     local ci
  1779.     local ai
  1780.     local hasItem
  1781.     local chestContents
  1782.     local slot
  1783.     local foundSlot
  1784.     local itemStack
  1785.    
  1786.     -- Checks to make sure none of the analyzers have any items in them
  1787.     for ai in pairs (aspectAnalyzers) do
  1788.         hasItem = peripheral.call(aspectAnalyzers[ai]["peripheral name"], "hasItem")
  1789.         if (hasItem) then
  1790.             print("One of the aspect analyzer(s) has an item in it. All aspect analyzer should be empty.")
  1791.            
  1792.             while (hasItem) do
  1793.                 sleep(1)
  1794.                 hasItem = peripheral.call(aspectAnalyzers[ai]["peripheral name"], "hasItem")
  1795.             end
  1796.         end
  1797.     end
  1798.    
  1799.    
  1800.     for ci in pairs(chests) do
  1801.         chestContents = peripheral.call(chests[ci]["peripheral name"], "getAllStacks")
  1802.         foundSlot = false
  1803.        
  1804.         -- See if the chest contains anything and record the slot of any item if it does.
  1805.         for slot in pairs(chestContents) do
  1806.             if (chestContents[slot].name == "Mana Bean") then
  1807.                 foundSlot = slot
  1808.                 break
  1809.             end
  1810.         end
  1811.        
  1812.         -- Something went wrong, try to get it fixed.
  1813.         if not (foundSlot) then
  1814.             print("No beans found in chest: " .. chests[ci]["peripheral name"] .. " at least one bean type needs to be present during startup. Please put some beans in the chest.")
  1815.             print("")
  1816.            
  1817.             while not (foundSlot) do
  1818.                 sleep(5)
  1819.                 chestContents = peripheral.call(chests[ci]["peripheral name"], "getAllStacks")
  1820.                
  1821.                 for slot in pairs(chestContents) do
  1822.                     if (chestContents[slot].name == "Mana Bean") then
  1823.                         foundSlot = slot
  1824.                         break
  1825.                     end
  1826.                 end
  1827.             end
  1828.            
  1829.             print("Found mana bean in chest slot: " .. foundSlot)
  1830.             print("")
  1831.         end
  1832.        
  1833.        
  1834.         -- Put one of the random items from the chest into the aspect analyzer above it.
  1835.         if not (peripheral.call(chests[ci]["peripheral name"], "pushItemIntoSlot", "down", foundSlot, 1, 1)) then
  1836.             print("Failed to put item from chest " .. chests[ci]["peripheral name"] .. " slot " .. foundSlot .. " into aspect analyzer. Make sure everything in the chest is a mana bean.")
  1837.             print("")
  1838.             sleep(1)
  1839.            
  1840.             while not (peripheral.call(chests[ci]["peripheral name"], "pushItemIntoSlot", "down", foundSlot, 1, 1)) do
  1841.                 sleep(1)
  1842.             end
  1843.         end
  1844.        
  1845.        
  1846.         -- Scan through the aspect analyzers and find which one has the item in it.
  1847.         for ai in pairs (aspectAnalyzers) do
  1848.             hasItem = peripheral.call(aspectAnalyzers[ai]["peripheral name"], "hasItem")
  1849.            
  1850.             if (hasItem) then
  1851.                 if not (peripheral.call(chests[ci]["peripheral name"], "pullItemIntoSlot", "down", 1, 1, foundSlot)) then
  1852.                     print("Failed to pull the item back out of the aspect analyzer. Make sure the redstone signal from the computer is disabling refilling of the chests during startup. !!RESTART REQUIRED!!")
  1853.                    
  1854.                     -- This is too difficult to explain how to recover from. Wait for human intervention.
  1855.                     while (true) do
  1856.                         sleep(60)
  1857.                     end
  1858.                 end
  1859.                
  1860.                 chests[ci]["aspect analyzer"] = aspectAnalyzers[ai]["peripheral name"]
  1861.                
  1862.                 if (debugOutput) then
  1863.                     print("Matched chest: " .. chests[ci]["peripheral name"] .. " with aspect analyzer: " .. aspectAnalyzers[ai]["peripheral name"])
  1864.                     print("")
  1865.                 end
  1866.                
  1867.                 break
  1868.             end
  1869.         end
  1870.        
  1871.         if not (hasItem) then
  1872.             print("Failed to match chest " .. chests[ci]["peripheral name"] .. " with any connected aspect analyzer. Make sure all chests have aspect analyzers below them and all chests and aspect analyzers have peripherals/proxies connected and enabled. !!RESTART REQUIRED!!")
  1873.            
  1874.             -- Some part of the peripheral configuration is wrong and needs to be fixed. Wait for human intervention.
  1875.             while (true) do
  1876.                 sleep(60)
  1877.             end
  1878.         end
  1879.     end
  1880. end
  1881.  
  1882. function disableRefill()
  1883.     rs.setOutput(disableFillRedstoneDirection, false)
  1884.     redstone.setBundledOutput(disableFillRedstoneDirection, colors.white)
  1885.     sleep(redstoneWaitTicks * .05)
  1886. end
  1887.  
  1888. function enableRefill(skipSleep)
  1889.     rs.setOutput(disableFillRedstoneDirection, true)
  1890.     redstone.setBundledOutput(disableFillRedstoneDirection, 0)
  1891.    
  1892.     if (skipSleep ~= true) then
  1893.         sleep(redstoneWaitTicks * .05)
  1894.     end
  1895. end
  1896.  
  1897. function essentiaList()
  1898.     local essentias
  1899.    
  1900.     essentias = {
  1901.         ["aer"] = 0,
  1902.         ["alienis"] = 0,
  1903.         ["aqua"] = 0,
  1904.         ["arbor"] = 0,
  1905.         ["auram"] = 0,
  1906.         ["bestia"] = 0,
  1907.         ["cognitio"] = 0,
  1908.         ["corpus"] = 0,
  1909.         ["exanimis"] = 0,
  1910.         ["fabrico"] = 0,
  1911.         ["fames"] = 0,
  1912.         ["gelum"] = 0,
  1913.         ["herba"] = 0,
  1914.         ["humanus"] = 0,
  1915.         ["ignis"] = 0,
  1916.         ["instrumentum"] = 0,
  1917.         ["iter"] = 0,
  1918.         ["limus"] = 0,
  1919.         ["lucrum"] = 0,
  1920.         ["lux"] = 0,
  1921.         ["machina"] = 0,
  1922.         ["messis"] = 0,
  1923.         ["metallum"] = 0,
  1924.         ["meto"] = 0,
  1925.         ["mortuus"] = 0,
  1926.         ["motus"] = 0,
  1927.         ["ordo"] = 0,
  1928.         ["pannus"] = 0,
  1929.         ["perditio"] = 0,
  1930.         ["perfodio"] = 0,
  1931.         ["permutatio"] = 0,
  1932.         ["potentia"] = 0,
  1933.         ["praecantatio"] = 0,
  1934.         ["sano"] = 0,
  1935.         ["sensus"] = 0,
  1936.         ["spiritus"] = 0,
  1937.         ["telum"] = 0,
  1938.         ["tempestas"] = 0,
  1939.         ["tempus"] = 0,
  1940.         ["tenebrae"] = 0,
  1941.         ["terra"] = 0,
  1942.         ["tutamen"] = 0,
  1943.         ["vacuos"] = 0,
  1944.         ["venenum"] = 0,
  1945.         ["victus"] = 0,
  1946.         ["vinculum"] = 0,
  1947.         ["vitium"] = 0,
  1948.         ["vitreus"] = 0,
  1949.         ["volatus"] = 0
  1950.     }
  1951.    
  1952.     return essentias
  1953. end
  1954.  
  1955.  
  1956. m.clear()
  1957. m.setCursorPos(1, 1)
  1958. term.redirect(m)
  1959. print("Analyzing chests, watch the computer for more information.")
  1960. print("")
  1961. print("The monitor will refresh once chest analysis is finished.")
  1962. print("")
  1963. term.current()
  1964. essentia = essentiaList()
  1965. setAutoDetectVariables()
  1966.  
  1967. disableRefill()
  1968. findChestsAndAnalyzers()
  1969. matchChestsWithAnalyzer()
  1970. analyzeChestsContents()
  1971. enableRefill()
  1972.  
  1973. print("")
  1974. print("Chest analysis finished. Showing interface.")
  1975. sleep(1)
  1976.  
  1977.  
  1978. refresh()
  1979.  
  1980.  
  1981. while (run) do
  1982.     -- uses os.pullevent so this isn't triggered constantly
  1983.     getClick()
  1984. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement