Advertisement
theTANCO

simplecounter.lua

Jul 27th, 2022 (edited)
1,015
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -- CC Tweaked Forums: https://forums.computercraft.cc/index.php?topic=458.0
  2. local count = {}
  3. local increment = {index = 0, count = -1, max = -1}
  4. local scrollPos = 0
  5. local Vector2 = function(x, y)
  6.     return {x = x, y = y}
  7. end
  8. local size = Vector2(term.getSize())
  9.  
  10. if fs.exists("simplecounter.txt") then -- Checks if counter data exists and loads it.
  11.     local f = fs.open("simplecounter.txt","r")
  12.     count = textutils.unserialize(f.readAll())
  13.     f.close()
  14. end
  15. local saveCount = function() -- Saves counter data to a file.
  16.     local f = fs.open("simplecounter.txt","w")
  17.     f.write(textutils.serialize(count))
  18.     f.close()
  19. end
  20.  
  21. local drawLine = function(index) -- Draws all counter properties.
  22.     term.setCursorPos(1, index-scrollPos)
  23.     local str = "x R " .. string.char(24) .. string.char(25) .. " L -+" .. count[index].count .. "/M" -- Text for delete, rename, reposition, lock, count up/down, max, and max up/down buttons, and the count itself, and "/" (for count/max).
  24.     local textColor = "fff" -- Text color for lock button and surrounding spaces.
  25.     local backColor = "8f8f88f8f88" .. string.rep("0", string.len(count[index].count)) .. "f8" -- Background color for all buttons up to count up/down.
  26.     if index == #count then -- Text color for the down reposition button.
  27.         textColor = "7" .. textColor -- Gray if at the bottom of the list; can't move this counter down anymore.
  28.     else
  29.         textColor = "f" .. textColor -- Black if not at the bottom of the list.
  30.     end
  31.     if index == 1 then -- Text color for the up reposition button and the space before.
  32.         textColor = "f7" .. textColor -- Button is gray if at the top of the list; can't move this counter up anymore.
  33.     else
  34.         textColor = "ff" .. textColor -- Black if not at the top of the list.
  35.     end
  36.     if count[index].locked then -- Text color for the remainder of the buttons as well as the count itself.
  37.         textColor = "7f7" .. textColor .. "77" .. string.rep("f", string.len(count[index].count)) .. "07" -- Gray if this counter is locked.
  38.     else
  39.         textColor = "fff" .. textColor .. "ff" .. string.rep("f", string.len(count[index].count)) .. "0f" -- Black if this counter is not locked
  40.     end
  41.     if count[index].max then -- Draws the max number and percentage if the max number is enabled.
  42.         local percent = math.floor(count[index].count/count[index].max*100000)/1000 -- The percentage of count/max.
  43.         str = str .. "-+" .. count[index].max .. " " .. percent .. "%"
  44.         if count[index].locked then
  45.             textColor = textColor .. "77"
  46.         else
  47.             textColor = textColor .. "ff"
  48.         end
  49.         textColor = textColor .. string.rep("f", string.len(count[index].max)) .. "f" .. string.rep("4", string.len(percent)) .. "4"
  50.         backColor = backColor .. "88" .. string.rep("0", string.len(count[index].max)) .. "f" .. string.rep("f", string.len(percent)) .. "f"
  51.     end
  52.     str = str .. " " .. count[index].name -- Text, text color, and background color for the counter name.
  53.     textColor = textColor .. "f" .. string.rep("0", count[index].name:len())
  54.     backColor = backColor .. "f" .. string.rep("f", count[index].name:len())
  55.     str = str .. string.rep(" ", size.x-str:len()) -- Text, text color, background color for the empty space after the counter name.
  56.     textColor = textColor .. string.rep("f", size.x-textColor:len())
  57.     backColor = backColor .. string.rep("f", size.x-backColor:len())
  58.     term.blit(str, textColor, backColor) -- Draws the above data to the screen.
  59. end
  60. local drawAll = function() -- Draws the whole screen.
  61.     for a = 1, size.y do
  62.         if a+scrollPos <= #count then
  63.             drawLine(a+scrollPos)
  64.         elseif a+scrollPos > #count then
  65.             term.setCursorPos(1, a)
  66.             term.setBackgroundColor(colors.black)
  67.             term.clearLine()
  68.             if a+scrollPos == #count+1 then
  69.                 term.blit("Add Exit", "ffffffff", "888f8888")
  70.             end
  71.         end
  72.     end
  73. end
  74.  
  75. local editName = function(name) -- Enters a name for a new or existing counter.
  76.     term.setBackgroundColor(colors.black)
  77.     term.clear()
  78.     term.setCursorPos(1, 1)
  79.     term.setTextColor(colors.yellow)
  80.     term.write(name)
  81.     term.setCursorPos(1, 2)
  82.     term.setTextColor(colors.white)
  83.     term.write("New Name: ")
  84.     return read()
  85. end
  86.  
  87. local addSub = function(index, key, dir) -- Adds or subtracts the count or max values by the increment amount.
  88.     local anti = ""
  89.     if key == "count" then
  90.         anti = "max"
  91.     else
  92.         anti = "count"
  93.     end
  94.     if increment[key] < 1 then
  95.         increment[key] = 1
  96.     end
  97.     increment[anti] = -1
  98.     count[index][key] = count[index][key] + increment[key] * dir
  99.     if string.len(math.abs(count[index][key])) < string.len(increment[key]) then -- Moves the selected digit if the number is smaller than the increment amount.
  100.         increment[key] = 10 ^ (string.len(math.abs(count[index][key])) - 1)
  101.     end
  102.     saveCount()
  103.     drawLine(index)
  104. end
  105.  
  106. local selectDigit = function(index, key, digit) -- Selects the clicked digit and the increment buttons will increment that digit.
  107.     local anti = ""
  108.     if key == "count" then
  109.         anti = "max"
  110.     else
  111.         anti = "count"
  112.     end
  113.     if digit > 1 and count[index][key] < 0 then
  114.         digit = digit + 1
  115.     end
  116.     if digit == string.len(math.abs(count[index][key]))+1 then
  117.         increment[key] = 0 -- If the space after the number is clicked, it sets the cursor to where keyboard input can add numbers to the end.
  118.     else
  119.         increment[key] = 10 ^ (string.len(math.abs(count[index][key])) - digit)
  120.     end
  121.     increment[anti] = -1
  122. end
  123.  
  124. local changeIndex = function(dir) -- Processes changing which counter the cursor is on when pressing the up or down keys.
  125.     repeat -- Scans the counters in the given direction until it either reaches the top or bottom of the list or finds a counter that's not locked.
  126.         increment.index = increment.index + dir
  127.     until increment.index == 0 or increment.index > #count or not count[increment.index].locked
  128.     if increment.index == 0 or increment.index > #count then -- If an unlocked counter is not found the cursor is turned off.
  129.         increment = {index = 0, count = -1, max = -1}
  130.     elseif increment.index > 0 and increment.count < 0 and increment.max < 0 then
  131.         increment.count = 0
  132.     end
  133.     if increment.count > -1 and string.len(increment.count) > string.len(math.abs(count[increment.index].count)) then -- This ensures the cursor is within the digits of the selected counter.
  134.         increment.count = 10 ^ (string.len(math.abs(count[increment.index].count)) - 1)
  135.     elseif increment.max > -1 then
  136.         if count[increment.index].max then -- This ensures the cursor is within the digits of the max of the selected counter.
  137.             if string.len(increment.max) > string.len(math.abs(count[increment.index].max)) then
  138.                 increment.max = 10 ^ (string.len(math.abs(count[increment.index].count)) - 1)
  139.             end
  140.         else -- If the max is disabled, the cursor will move to the count.
  141.             increment.max = -1
  142.             increment.count = 0
  143.         end
  144.     end
  145. end
  146.  
  147. local deleteNum = function(index, key, space) -- This processes when the backspace or delete keys are pressed and the cursor is enabled.
  148.     local digit = string.len(count[index][key]) - string.len(increment[key]) -- Locates where on the number the cursor is located.
  149.     if increment[key] == 0 then
  150.         digit = string.len(count[index][key])
  151.     end
  152.     if (space == 0 and digit > 0) or (space == 1 and digit < string.len(count[index][key])) then -- Check if backspace is pressed and the cursor is not at the very start of the number, or if delete is pressed and the cursor is not at the very end of the number.
  153.         if string.len(math.abs(count[index][key])) == 1 then -- If the number is single digit when deleted, it is set to 0.
  154.             count[index][key] = 0
  155.         elseif digit == 0 then -- If delete (but not backspace) is pressed, deleted the first digit in the number.
  156.             count[index][key] = tonumber(string.sub(count[index][key], digit+1+space, string.len(count[index][key])))
  157.         elseif digit == string.len(count[index][key]) then -- If backspace (but not delete) is pressed, delete the last digit in the number.
  158.             count[index][key] = tonumber(string.sub(count[index][key], 0, digit-1+space))
  159.         else -- If delete is pressed, delete the current digit. If backspace is pressed, delete the previous digit.
  160.             count[index][key] = tonumber(string.sub(count[index][key], 0, digit-1+space) .. string.sub(count[index][key], digit+1+space, string.len(count[index][key])))
  161.         end
  162.         if string.len(increment[key]) > string.len(math.abs(count[index][key])) then -- Ensures that the increment value is still within the boundaries of the selected number.
  163.             increment[key] = 10 ^ (string.len(math.abs(count[index][key])) - 1)
  164.         end
  165.         if space == 1 then -- Decreases the increment value when delete is pressed.
  166.             if increment[key] == 1 then
  167.                 increment[key] = 0
  168.             else
  169.                 increment[key] = increment[key] / 10
  170.             end
  171.         end
  172.         saveCount()
  173.         drawLine(index)
  174.     end
  175. end
  176.  
  177. drawAll()
  178. while true do
  179.     if increment.index > 0 then -- Draws the cursor blink over whichever digit is being incremented or decremented if it is so.
  180.         if increment.count > -1 then
  181.             if increment.count > 0 then
  182.                 term.setCursorPos(12+string.len(count[increment.index].count)-string.len(increment.count), increment.index-scrollPos)
  183.                 term.setTextColor(colors.black)
  184.             else
  185.                 term.setCursorPos(12+string.len(count[increment.index].count), increment.index-scrollPos)
  186.                 term.setTextColor(colors.white)
  187.             end
  188.             term.setCursorBlink(true)
  189.         elseif count[increment.index].max and increment.max > -1 then
  190.             if increment.max > 0 then
  191.                 term.setCursorPos(16+string.len(count[increment.index].count)+string.len(count[increment.index].max)-string.len(increment.max), increment.index-scrollPos)
  192.                 term.setTextColor(colors.black)
  193.             else
  194.                 term.setCursorPos(16+string.len(count[increment.index].count)+string.len(count[increment.index].max), increment.index-scrollPos)
  195.                 term.setTextColor(colors.white)
  196.             end
  197.             term.setCursorBlink(true)
  198.         end
  199.     end
  200.  
  201.     local event = {os.pullEvent()}
  202.     term.setCursorBlink(false)
  203.     if event[1] == "mouse_click" then
  204.         local clickPos = event[4] + scrollPos
  205.         if clickPos == #count+1 then
  206.             if event[3] >= 1 and event[3] <= 3 then -- Adds a counter to the list.
  207.                 table.insert(count, #count+1, {count=0, name=editName("New Counter"), locked=false})
  208.                 saveCount()
  209.                 drawAll()
  210.             elseif event[3] >= 5 and event[3] <= 8 then -- Exits the program.
  211.                 term.setBackgroundColor(colors.black)
  212.                 term.setTextColor(colors.white)
  213.                 term.clear()
  214.                 term.setCursorPos(1, 1)
  215.                 error()
  216.             end
  217.             increment = {index = 0, count = -1, max = -1}
  218.         elseif clickPos <= #count then -- Something on a counter is clicked.
  219.             increment.index = clickPos
  220.             if event[3] == 1 and not count[clickPos].locked then -- Deletes the counter if the counter is not locked.
  221.                 increment = {index = 0, count = -1, max = -1}
  222.                 table.remove(count, clickPos)
  223.                 term.setBackgroundColor(colors.black)
  224.                 term.clear()
  225.                 saveCount()
  226.                 drawAll()
  227.             elseif event[3] == 3 and not count[clickPos].locked then -- Renames the counter if the counter is not locked.
  228.                 increment = {index = 0, count = -1, max = -1}
  229.                 count[clickPos].name = editName(count[clickPos].name)
  230.                 saveCount()
  231.                 drawAll()
  232.             elseif event[3] == 5 and clickPos ~= 1 then -- Moves the counter up in the list if it is not at the top of the list. Locking does not affect this function.
  233.                 increment = {index = 0, count = -1, max = -1}
  234.                 table.insert(count, clickPos-1, count[clickPos])
  235.                 table.remove(count, clickPos+1)
  236.                 saveCount()
  237.                 drawLine(clickPos)
  238.                 drawLine(clickPos-1)
  239.             elseif event[3] == 6 and clickPos ~= #count then -- Moves the counter down in the list if it is not at the bottom of the list. Locking does not affect this function.
  240.                 increment = {index = 0, count = -1, max = -1}
  241.                 table.insert(count, clickPos+2, count[clickPos])
  242.                 table.remove(count, clickPos)
  243.                 saveCount()
  244.                 drawLine(clickPos)
  245.                 drawLine(clickPos+1)
  246.             elseif event[3] == 8 then -- Locks or unlocks the counter. Locking prevents accidentally deleting or changing the counter.
  247.                 increment = {index = 0, count = -1, max = -1}
  248.                 if count[clickPos].locked then
  249.                     count[clickPos].locked = false
  250.                 else
  251.                     count[clickPos].locked = true
  252.                 end
  253.                 saveCount()
  254.                 drawLine(clickPos)
  255.             elseif event[3] == 10 and not count[clickPos].locked then -- Decrements the count if the counter is not locked.
  256.                 addSub(clickPos, "count", -1)
  257.             elseif event[3] == 11 and not count[clickPos].locked then -- Increments the count if the counter is not locked.
  258.                 addSub(clickPos, "count", 1)
  259.             elseif event[3] >= 12 and event[3] <= 12+string.len(count[clickPos].count) and not count[clickPos].locked then -- If the count number is clicked, it selects the clicked digit and the increment buttons will increment that digit. Will do nothing if the counter is locked.
  260.                 selectDigit(clickPos, "count", event[3] - 11)
  261.             elseif event[3] == 13+string.len(count[clickPos].count) and not count[clickPos].locked then -- Toggles the max value if the counter is not locked.
  262.                 increment = {index = 0, count = -1, max = -1}
  263.                 if count[clickPos].max then
  264.                     count[clickPos].max = nil
  265.                 else
  266.                     count[clickPos].max = 0
  267.                 end
  268.                 saveCount()
  269.                 drawLine(clickPos)
  270.             elseif event[3] == 14+string.len(count[clickPos].count) and count[clickPos].max and not count[clickPos].locked then -- Decrements the max value if it is enabled and the counter is not locked.
  271.                 addSub(clickPos, "max", -1)
  272.             elseif event[3] == 15+string.len(count[clickPos].count) and count[clickPos].max and not count[clickPos].locked then -- Increments the max value if it is enabled and the counter is not locked.
  273.                 addSub(clickPos, "max", 1)
  274.             elseif count[clickPos].max and event[3] >= 16+string.len(count[clickPos].count) and event[3] <= 16+string.len(count[clickPos].count)+string.len(count[clickPos].max) and not count[clickPos].locked then -- If the max number is clicked, it selects the clicked digit and the increment buttons will increment that digit. Will do nothing if the counter is locked.
  275.                 selectDigit(clickPos, "max", event[3] - string.len(count[clickPos].count) - 15)
  276.             else
  277.                 increment = {index = 0, count = -1, max = -1}
  278.             end
  279.         else
  280.             increment = {index = 0, count = -1, max = -1}
  281.         end
  282.     elseif event[1] == "mouse_scroll" then -- Scrolls the list with the mouse wheel.
  283.         if (event[2] == -1 and scrollPos > 0) or (event[2] == 1 and scrollPos+size.y-1 <= #count) then
  284.             scrollPos = scrollPos + event[2]
  285.             drawAll()
  286.         end
  287.     elseif event[1] == "char" and increment.index > 0 then
  288.         if event[2] == "-" then -- Toggles the selected number between positive and negative.
  289.             if increment.count > -1 then
  290.                 count[increment.index].count = count[increment.index].count * -1
  291.                 saveCount()
  292.                 drawLine(increment.index)
  293.             elseif increment.max > -1 then
  294.                 count[increment.index].max = count[increment.index].max * -1
  295.                 saveCount()
  296.                 drawLine(increment.index)
  297.             end
  298.         elseif tonumber(event[2]) then -- Inserts the input number into the selected number.
  299.             if increment.count > -1 then
  300.                 local digit = string.len(count[increment.index].count) - string.len(increment.count)
  301.                 if increment.count == 0 then
  302.                     digit = string.len(count[increment.index].count)
  303.                 end
  304.                 count[increment.index].count = tonumber(string.sub(count[increment.index].count, 0, digit) .. event[2] .. string.sub(count[increment.index].count, digit+1, string.len(count[increment.index].count)+1))
  305.                 saveCount()
  306.                 drawLine(increment.index)
  307.             elseif increment.max > -1 then
  308.                 local digit = string.len(count[increment.index].max) - string.len(increment.max)
  309.                 if increment.max == 0 then
  310.                     digit = string.len(count[increment.index].max)
  311.                 end
  312.                 count[increment.index].max = tonumber(string.sub(count[increment.index].max, 0, digit) .. event[2] .. string.sub(count[increment.index].max, digit+1, string.len(count[increment.index].max)+1))
  313.                 saveCount()
  314.                 drawLine(increment.index)
  315.             end
  316.         end
  317.     elseif event[1] == "key" then
  318.         if event[2] == keys.left and increment.index > 0 then -- Move the cursor left along the numbers in the current counter.
  319.             if increment.max == 0 then
  320.                 increment.max = 1
  321.             elseif increment.max > -1 and string.len(increment.max) < string.len(math.abs(count[increment.index].max)) then
  322.                 increment.max = increment.max * 10
  323.             elseif increment.max > -1 and string.len(increment.max) == string.len(math.abs(count[increment.index].max)) then
  324.                 increment.max = -1
  325.                 increment.count = 0
  326.             elseif increment.count == 0 then
  327.                 increment.count = 1
  328.             elseif string.len(increment.count) < string.len(math.abs(count[increment.index].count)) then
  329.                 increment.count = increment.count * 10
  330.             end
  331.         elseif event[2] == keys.right and increment.index > 0 then -- Move the cursor right along the numbers in the current counter. Will not move to the max if max is disabled.
  332.             if increment.count > 1 then
  333.                 increment.count = increment.count / 10
  334.             elseif increment.count == 1 then
  335.                 increment.count = 0
  336.             elseif increment.count == 0 and count[increment.index].max then
  337.                 increment.count = -1
  338.                 increment.max = 10 ^ (string.len(math.abs(count[increment.index].max)) - 1)
  339.             elseif increment.max > 1 then
  340.                 increment.max = increment.max / 10
  341.             elseif increment.max == 1 then
  342.                 increment.max = 0
  343.             end
  344.         elseif event[2] == keys.up and increment.index > 0 then -- Scans for the previous unlocked counter or deselects the counter.
  345.             changeIndex(-1)
  346.         elseif event[2] == keys.down and increment.index <= #count then -- Scans for the next unlocked counter or deselects the counter.
  347.             changeIndex(1)
  348.         elseif event[2] == keys.backspace and increment.index > 0 then -- Deletes the previous digit in the selected number.
  349.             if increment.count > -1 then
  350.                 deleteNum(increment.index, "count", 0)
  351.             elseif increment.max > -1 then
  352.                 deleteNum(increment.index, "max", 0)
  353.             end
  354.         elseif event[2] == keys.delete and increment.index > 0 then -- Deletes the current digit in the selected number.
  355.             if increment.count > -1 then
  356.                 deleteNum(increment.index, "count", 1)
  357.             elseif increment.max > -1 then
  358.                 deleteNum(increment.index, "max", 1)
  359.             end
  360.         elseif event[2] == keys.home and increment.index > 0 then -- Move the cursor to the start of the selected counter.
  361.             if increment.max > -1 and (increment.max == 0 or string.len(increment.max) < string.len(math.abs(count[increment.index].max))) then -- If max is selected, moves the cursor to the start of the max.
  362.                 increment.max = 10 ^ (string.len(math.abs(count[increment.index].max)) - 1)
  363.             else -- If the cursor is at the start of the max or is in counter, moves the cursor to the start of the counter.
  364.                 increment.max = -1
  365.                 increment.count = 10 ^ (string.len(math.abs(count[increment.index].count)) - 1)
  366.             end
  367.         elseif event[2] == keys["end"] and increment.index > 0 then -- Moves the cursor to the end of the selected counter.
  368.             if increment.count > -1 and increment.count > 0 then -- If counter is selected, moves the cursor to the end of the counter.
  369.                 increment.count = 0
  370.             else -- If at the end of the counter and max exists, or if max is selected, moves the cursor to the end of the max.
  371.                 if count[increment.index].max then
  372.                     increment.count = -1
  373.                     increment.max = 0
  374.                 end
  375.             end
  376.         end
  377.     elseif event[1] == "term_resize" then
  378.         size = Vector2(term.getSize())
  379.     end
  380. end
  381.  
  382. -- 2022/11/08
  383. --  Fixed a bug not displaying counters correctly when scrolling.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement