Advertisement
mikebald

Essentia Filling

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