Advertisement
theTANCO

LibAppend.lua

Jun 27th, 2022 (edited)
1,118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 22.45 KB | None | 0 0
  1. -- This is an API to add much needed functions to the global libraries in
  2. --   ComputerCraft Lua. This code will only work in ComputerCraft.
  3. -- To get this program, run the following command:
  4. --   pastebin get Rac6Jxjg "/API/LibAppend.lua"
  5. -- This file must be saved in "/API/" in order for programs that use it to
  6. --   function properly.
  7. -- Add it to your program by including 'dofile("/API/LibAppend.lua")' or
  8. --   'require("/API/LibAppend")' at the top of your code.
  9.  
  10. -- This is so 'require' can be used, even if APIs are loaded with 'dofile'.
  11. require = dofile("/rom/modules/main/cc/require.lua").make(
  12.     setmetatable({}, {__index = _ENV}),
  13.     "/"
  14. )
  15.  
  16. -- This loads the expect module into your program. I don't know why this isn't
  17. --   loaded into the global table by default.
  18. -- expect.expect(arg, value, ...) -> Throws an error if the 'value' isn't any of
  19. --   the given types. You can enter multiple type arguments after 'value'.
  20. -- expect.field(table, index, ...) -> Throws an error if a property of a table
  21. --   isn't any of the given types. 'index' must be a key string and not an index
  22. --   number. You can enter multiple type arguments after 'index'.
  23. -- expect.range(num, min, max) -> Thrown an error if a number is not between two
  24. --   values, inclusive.
  25. expect = require("cc.expect")
  26.  
  27. -- Gets the "name" of the specified color.
  28. colors.name = function(color)
  29.     local colorList = {
  30.         ["0"] = "white",
  31.         ["1"] = "orange",
  32.         ["2"] = "magenta",
  33.         ["3"] = "lightBlue",
  34.         ["4"] = "yellow",
  35.         ["5"] = "lime",
  36.         ["6"] = "pink",
  37.         ["7"] = "gray",
  38.         ["8"] = "lightGray",
  39.         ["9"] = "cyan",
  40.         ["a"] = "purple",
  41.         ["b"] = "blue",
  42.         ["c"] = "brown",
  43.         ["d"] = "green",
  44.         ["e"] = "red",
  45.         ["f"] = "black"
  46.     }
  47.     return colorList[colors.toBlit(expect.expect(1, color, "number"))]
  48. end
  49.  
  50. -- Non-American version of colors.name().
  51. colours.name = function(colour)
  52.     local name = colors.name(colour)
  53.     if name == "gray" or name == "lightGray" then name = name:gsub("ray", "rey") end
  54.     return name
  55. end
  56.  
  57. math.round = function(n)
  58.     return math.floor(n+0.5)
  59. end
  60.  
  61. -- Correctly capitalize the first letter in each sentence in a string.
  62. string.cap = function(s)
  63.     for a = 1, s:len() do
  64.         if a == 1 or s:sub(a-2, a-1) == ". " or s:sub(a-2, a-1) == "? " or s:sub(a-2, a-1) == "! " then
  65.             s = s:sub(1, a-1)..s:sub(a, a):upper()..s:sub(a+1, s:len())
  66.         end
  67.     end
  68.     return s
  69. end
  70.  
  71. -- Capitalizes the first letter in all words.
  72. string.capAll = function(s)
  73.     for a = 1, s:len() do
  74.         if a == 1 or s:sub(a-1, a-1) == " " then
  75.             s = s:sub(1, a-1)..s:sub(a, a):upper()..s:sub(a+1, s:len())
  76.         end
  77.     end
  78.     return s
  79. end
  80.  
  81. string.concat = function(...)
  82.     str = ""
  83.     for _, v in ipairs({...}) do
  84.         str = str .. tostring(v)
  85.     end
  86.     return str
  87. end
  88.  
  89. -- Easily add padding to a string.
  90. -- 'str' is the string to add padding to.
  91. -- 'pad' is the string to use as padding.
  92. -- 's' adds padding to the start of str if the length of str is less than s.
  93. -- 'e' adds padding to the end of str if the length of str is less than e after adding s padding.
  94. string.pad = function(str, pad, s, e)
  95.     str, pad = tostring(str), tostring(pad)
  96.     s, e = tonumber(s) or 0, tonumber(e) or 0
  97.     str = pad:rep(s-str:len()) .. str
  98.     str = str .. pad:rep(e-str:len())
  99.     return str
  100. end
  101.  
  102. -- A single function option for swapping the values of two elements in a table.
  103. -- 't' is the table you want to change.
  104. -- 'i1' and 'i2' are the keys for the elements being swapped.
  105. -- The value of 't[i1]' is set to 't[i2]'.
  106. -- The value of 't[i2]' is set to 't[i1]'.
  107. table.swap = function(t, i1, i2)
  108.     expect.expect(1, t, "table")
  109.     expect.expect(2, i1, "number", "string")
  110.     expect.expect(3, i2, "number", "string")
  111.     e = t[i1]
  112.     t[i1] = t[i2]
  113.     t[i2] = e
  114. end
  115.  
  116. -- Moves elements up or down through an ordered list.
  117. -- 't' is the table you want to change.
  118. -- 'i' is the index of the element being moved.
  119. -- 'n' is how many places the element will move.
  120. -- Only index numbers can be used for i. Strings will not work.
  121. -- To move elements with strings as keys, use 'table.swap'.
  122. table.shift = function(t, i, n)
  123.     expect.expect(1, t, "table")
  124.     expect.expect(2, i, "number")
  125.     expect.expect(3, n, "number")
  126.     repeat
  127.         if n < 0 then
  128.             table.swap(t, i, i-1)
  129.             i = i - 1
  130.         elseif n > 0 then
  131.             table.swap(t, i, i+1)
  132.             i = i + 1
  133.         end
  134.     until i == n
  135.     return i
  136. end
  137.  
  138. -- A combination of term.blit and print.
  139. term.printBlit = function(s, t, b)
  140.     expect.expect(1, s, "string")
  141.     expect.expect(2, t, "string")
  142.     expect.expect(3, b, "string")
  143.     if s:len() ~= t:len() or s:len() ~= b:len() then
  144.         error("Arguments must be the same length", 2)
  145.     end
  146.     term.blit(s, t, b)
  147.     print()
  148. end
  149.  
  150. -- A combination of texutils.slowWrite and term.blit.
  151. textutils.slowBlit = function(s, t, b, d)
  152.     d = d or 20
  153.     expect.expect(1, s, "string")
  154.     expect.expect(2, t, "string")
  155.     expect.expect(3, b, "string")
  156.     if string.len(s) ~= string.len(t) or string.len(s) ~= string.len(b) or string.len(t) ~= string.len(b) then
  157.         error("Arguments #1-3 must be the same length ("..string.len(s)..", "..string.len(t)..", "..string.len(b)..")", 2)
  158.     end
  159.     expect.expect(4, d, "number")
  160.     if d <= 0 then
  161.         error("Text speed must be greater than 0", 2)
  162.     end
  163.  
  164.     local lastSpace = 0
  165.     local lastNL = 0
  166.     local xPos, yPos = term.getCursorPos()
  167.     local xSize, ySize = term.getSize()
  168.     for i = 1, s:len() do
  169.         if s:sub(i, i) == " " then
  170.             lastSpace = i
  171.         end
  172.         if s:sub(i, i) == "\n" then
  173.             lastNL = i
  174.             lastSpace = i
  175.         end
  176.         if xPos+i-lastNL-1 > xSize then
  177.             s = s:sub(1, lastSpace-1).."\n"..s:sub(lastSpace+1, s:len())
  178.             lastNL = lastSpace
  179.             xPos = 1
  180.         end
  181.     end
  182.  
  183.     local currentTextColor = term.getTextColor()
  184.     local currentBackgroundColor = term.getBackgroundColor()
  185.  
  186.     for i = 1, s:len() do
  187.         sleep(1/d)
  188.         term.setTextColor(2^tonumber(t:sub(i, i), 16))
  189.         term.setBackgroundColor(2^tonumber(b:sub(i, i), 16))
  190.         write(s:sub(i, i))
  191.     end
  192.     term.setTextColor(currentTextColor)
  193.     term.setBackgroundColor(currentBackgroundColor)
  194. end
  195.  
  196. -- 'buffer = doubleBuffer.new(parent, ...)' creates double frame buffers and
  197. --   redirects the term to the first buffer.
  198. -- • 'parent' is the term that the buffer will draw to.
  199. -- • '...' is any windows that will be automatically parented to the buffers.
  200. -- 'buffer.swap()' redirects the from the current buffer to the other.
  201. -- 'buffer.resize()' resizes the buffers if the parent term size has changed.
  202. -- 'buffer.parent()' returns the parent term.
  203. -- 'buffer.reset()' redirects back to the parent term.
  204. doubleBuffer = {}
  205. doubleBuffer.new = function(parent, ...)
  206.     local wins = {...}
  207.     local oldTerm = expect.expect(1, parent, "table", "nil") or term.current()
  208.     for k, v in pairs(term.native()) do
  209.         if type(k) == "string" and type(v) == "function"
  210.         and type(oldTerm[k]) ~= "function" then
  211.             error("Redirect object is missing method " .. k .. ".", 2)
  212.         end
  213.     end
  214.     local buffer = {
  215.         [0] = window.create(oldTerm, 1, 1, 1, 1),
  216.         [1] = window.create(oldTerm, 1, 1, 1, 1)
  217.     }
  218.     local win = 1
  219.  
  220.     local winRepos = function(p)
  221.       for i, v in ipairs(wins) do
  222.         local pos = vector.new(v.getPosition())
  223.         local size = vector.new(v.getSize())
  224.         v.reposition(pos.x, pos.y, size.x, size.y, p)
  225.       end
  226.     end
  227.  
  228.     swap = function()
  229.         buffer[win].setVisible(true)
  230.         win = 1 - win
  231.         buffer[win].setVisible(false)
  232.         winRepos(buffer[win])
  233.         return term.redirect(buffer[win])
  234.     end
  235.  
  236.     resize = function()
  237.         local xSize, ySize = term.getSize()
  238.         buffer[0].reposition(1, 1, xSize, ySize)
  239.         buffer[1].reposition(1, 1, xSize, ySize)
  240.         return xSize, ySize
  241.     end
  242.  
  243.     parent = function()
  244.         return oldTerm
  245.     end
  246.  
  247.     reset = function()
  248.         winRepos(oldTerm)
  249.         return term.redirect(oldTerm)
  250.     end
  251.  
  252.     resize()
  253.     swap()
  254.     return {
  255.         swap = swap,
  256.         resize = resize,
  257.         parent = parent,
  258.         reset = reset
  259.     }
  260. end
  261.  
  262. -- Converts decimial number to another base (binary, hexadecimal, etc.)
  263. tobase = function(n, b)
  264.     local code = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" -- 2 - 36 values per digit
  265.     local v = ""
  266.     expect.expect(1, n, "number")
  267.     expect.expect(2, b, "number")
  268.     expect.range(b, 2, 36)
  269.     repeat
  270.         v = code:sub(n%b+1, n%b+1) .. v
  271.         n = math.floor(n/b)
  272.     until n == 0
  273.     return v
  274. end
  275.  
  276. -- This is the vector api completely rewritten to include 2D and 4D vectors, as
  277. -- well as error messages that make it easier to debug.
  278. -- A 2-dimensional vector with 'x' and 'y' values.
  279. -- A 3-dimensional vector with 'x', 'y' and 'z' values.
  280. -- A 4-dimensional vector with 'x', 'y', 'z', and 'w' values.
  281. vector = (function()
  282.     local vect = {}
  283.     local vectors = {[2] = {}, [3] = {}, [4] = {}}
  284.     local checkValue = {}
  285.  
  286.     local err = function(v, t, e)
  287.         if type(v) ~= t then error(e, 5) end
  288.     end
  289.     local checkVector = function(o, d)
  290.         err(o, "table", "expected second operand to be a table (" .. d .. "D vector), got " .. type(o))
  291.     end
  292.     local checkField = function(n, m)
  293.         err(n, "number", "expected '" .. m .. "' of second operand to be a number, got " .. type(n))
  294.     end
  295.     local checkNumber = function(n)
  296.         err(n, "number", "expected second operand to be a number, got " .. type(n))
  297.     end
  298.  
  299.     -- Checks operand values for errors.
  300.     checkValue[2] = function(o)
  301.         checkVector(o, 2)
  302.         checkField(o.x, 'x')
  303.         checkField(o.y, 'y')
  304.     end
  305.     checkValue[3] = function(o)
  306.         checkVector(o, 3)
  307.         checkField(o.x, 'x')
  308.         checkField(o.y, 'y')
  309.         checkField(o.z, 'z')
  310.     end
  311.     checkValue[4] = function(o)
  312.         checkVector(o, 4)
  313.         checkField(o.x, 'x')
  314.         checkField(o.y, 'y')
  315.         checkField(o.z, 'z')
  316.         checkField(o.w, 'w')
  317.     end
  318.  
  319.     -- Adds two vectors together.
  320.     vectors[2].add = function(self, o)
  321.         checkValue[2](o)
  322.         return vect.new(
  323.             self.x + o.x,
  324.             self.y + o.y
  325.         )
  326.     end
  327.     vectors[3].add = function(self, o)
  328.         checkValue[3](o)
  329.         return vect.new(
  330.             self.x + o.x,
  331.             self.y + o.y,
  332.             self.z + o.z
  333.         )
  334.     end
  335.     vectors[4].add = function(self, o)
  336.         checkValue[4](o)
  337.         return vect.new(
  338.             self.x + o.x,
  339.             self.y + o.y,
  340.             self.z + o.z,
  341.             self.w + o.w
  342.         )
  343.     end
  344.  
  345.     -- Subtracts one vector from another.
  346.     vectors[2].sub = function(self, o)
  347.         checkValue[2](o)
  348.         return vect.new(
  349.             self.x - o.x,
  350.             self.y - o.y
  351.         )
  352.     end
  353.     vectors[3].sub = function(self, o)
  354.         checkValue[3](o)
  355.         return vect.new(
  356.             self.x - o.x,
  357.             self.y - o.y,
  358.             self.z - o.z
  359.         )
  360.     end
  361.     vectors[4].sub = function(self, o)
  362.         checkValue[4](o)
  363.         return vect.new(
  364.             self.x - o.x,
  365.             self.y - o.y,
  366.             self.z - o.z,
  367.             self.w - o.w
  368.         )
  369.     end
  370.  
  371.     -- Multiplies a vector by a scalar value.
  372.     vectors[2].mul = function(self, n)
  373.         checkNumber(n)
  374.         return vect.new(
  375.             self.x * n,
  376.             self.y * n
  377.         )
  378.     end
  379.     vectors[3].mul = function(self, n)
  380.         checkNumber(n)
  381.         return vect.new(
  382.             self.x * n,
  383.             self.y * n,
  384.             self.z * n
  385.         )
  386.     end
  387.     vectors[4].mul = function(self, n)
  388.         checkNumber(n)
  389.         return vect.new(
  390.             self.x * n,
  391.             self.y * n,
  392.             self.z * n,
  393.             self.w * n
  394.         )
  395.     end
  396.  
  397.     -- Divides a vector by a scalar value.
  398.     vectors[2].div = function(self, n)
  399.         checkNumber(n)
  400.         return vect.new(
  401.             self.x / n,
  402.             self.y / n
  403.         )
  404.     end
  405.     vectors[3].div = function(self, n)
  406.         checkNumber(n)
  407.         return vect.new(
  408.             self.x / n,
  409.             self.y / n,
  410.             self.z / n
  411.         )
  412.     end
  413.     vectors[4].div = function(self, n)
  414.         checkNumber(n)
  415.         return vect.new(
  416.             self.x / n,
  417.             self.y / n,
  418.             self.z / n,
  419.             self.w / n
  420.         )
  421.     end
  422.  
  423.     -- Negates a vector.
  424.     vectors[2].unm = function(self)
  425.         return vect.new(
  426.             -self.x,
  427.             -self.y
  428.         )
  429.     end
  430.     vectors[3].unm = function(self)
  431.         return vect.new(
  432.             -self.x,
  433.             -self.y,
  434.             -self.z
  435.         )
  436.     end
  437.     vectors[4].unm = function(self)
  438.         return vect.new(
  439.             -self.x,
  440.             -self.y,
  441.             -self.z,
  442.             -self.w
  443.         )
  444.     end
  445.  
  446.     -- Computes the dot product of two vectors.
  447.     vectors[2].dot = function(self, o)
  448.         checkValue[2](o)
  449.         return self.x * o.x + self.y * o.y
  450.     end
  451.     vectors[3].dot = function(self, o)
  452.         checkValue[3](o)
  453.         return self.x * o.x + self.y * o.y + self.z * o.z
  454.     end
  455.     vectors[4].dot = function(self, o)
  456.         checkValue[4](o)
  457.         return self.x * o.x + self.y * o.y + self.z * o.z + self.w * o.w
  458.     end
  459.  
  460.     -- Computes the cross product of two vectors.
  461.     vectors[2].cross = function(self, o)
  462.         checkValue[2](o)
  463.         return vect.new(0, 0)
  464.     end
  465.     vectors[3].cross = function(self, o)
  466.         checkValue[3](o)
  467.         return vect.new(
  468.             self.y * o.z - self.z * o.y,
  469.             self.z * o.x - self.x * o.z,
  470.             self.x * o.y - self.y * o.x
  471.         )
  472.     end
  473.     vectors[4].cross = function(self, o)
  474.         checkValue[4](o)
  475.         local v = vectors[3].cross(self, o)
  476.         return vect.new(v.x, v.y, v.z, 0)
  477.     end
  478.  
  479.     -- Get the length (also called magnitude) of a vector.
  480.     vectors[2].length = function(self)
  481.         return math.sqrt(self.x ^ 2 + self.y ^ 2)
  482.     end
  483.     vectors[3].length = function(self)
  484.         return math.sqrt(self.x ^ 2 + self.y ^ 2 + self.z ^ 2)
  485.     end
  486.     vectors[4].length = function(self)
  487.         return math.sqrt(self.x ^ 2 + self.y ^ 2 + self.z ^ 2 + self.w ^ 2)
  488.     end
  489.  
  490.     -- Computes a vector with the same direction, but of length 1.
  491.     vectors[2].normalize = function(self) return self:mul(1 / self:length()) end
  492.     vectors[3].normalize = function(self) return self:mul(1 / self:length()) end
  493.     vectors[4].normalize = function(self) return self:mul(1 / self:length()) end
  494.  
  495.     -- Construct a vector with each dimension rounded to the nearest value.
  496.     vectors[2].round = function(self, t)
  497.         t = tonumber(t) or 1
  498.         return vect.new(
  499.             math.floor((self.x + t * 0.5) / t) * t,
  500.             math.floor((self.y + t * 0.5) / t) * t
  501.         )
  502.     end
  503.     vectors[3].round = function(self, t)
  504.         t = tonumber(t) or 1
  505.         return vect.new(
  506.             math.floor((self.x + t * 0.5) / t) * t,
  507.             math.floor((self.y + t * 0.5) / t) * t,
  508.             math.floor((self.z + t * 0.5) / t) * t
  509.         )
  510.     end
  511.     vectors[4].round = function(self, t)
  512.         t = tonumber(t) or 1
  513.         return vect.new(
  514.             math.floor((self.x + t * 0.5) / t) * t,
  515.             math.floor((self.y + t * 0.5) / t) * t,
  516.             math.floor((self.z + t * 0.5) / t) * t,
  517.             math.floor((self.w + t * 0.5) / t) * t
  518.         )
  519.     end
  520.  
  521.     -- Converts a vector into a string, for pretty printing.
  522.     vectors[2].tostring = function(self)
  523.         return self.x .. "," .. self.y
  524.     end
  525.     vectors[3].tostring = function(self)
  526.         return self.x .. "," .. self.y .. "," .. self.z
  527.     end
  528.     vectors[4].tostring = function(self)
  529.         return self.x .. "," .. self.y .. "," .. self.z .. "," .. self.w
  530.     end
  531.  
  532.     -- Checks for equality between two vectors.
  533.     vectors[2].eq = function(self, o)
  534.         checkValue[2](o)
  535.         return self.x == o.x and self.y == o.y
  536.     end
  537.     vectors[3].eq = function(self, o)
  538.         checkValue[3](o)
  539.         return self.x == o.x and self.y == o.y and self.z == o.z
  540.     end
  541.     vectors[4].eq = function(self, o)
  542.         checkValue[4](o)
  543.         return self.x == o.x and self.y == o.y and self.z == o.z and self.w == o.w
  544.     end
  545.  
  546.     vect.new = function(x, y, z, w)
  547.         x, y, z, w = tonumber(x) or 0, tonumber(y) or 0, tonumber(z), tonumber(w)
  548.         local dim = 3
  549.  
  550.         if z == nil then dim = dim - 1
  551.         elseif w ~= nil then dim = dim + 1
  552.         end
  553.  
  554.         local main = vectors[dim]
  555.  
  556.         return setmetatable({x = x, y = y, z = z, w = w}, {
  557.             __index = main,
  558.             __add = main.add,
  559.             __sub = main.sub,
  560.             __mul = main.mul,
  561.             __div = main.div,
  562.             __unm = main.unm,
  563.             __tostring = main.tostring,
  564.             __eq = main.eq
  565.         })
  566.     end
  567.  
  568.     return {
  569.         new = vect.new
  570.     }
  571. end)()
  572.  
  573. --[[ The smallest time that the 'sleep' function works is 1/20th of a second.
  574. That means programs can technically only work in 20 frames per second.
  575. However, stuff can be printed to the screen faster than that if the 'sleep'
  576. function is removed, but ComputerCraft programs can only go a little over 6
  577. seconds without sleeping before it throws the 'Too long without yielding' error.
  578. This 'wait' function is my first solution to that problem.
  579.  
  580. This works like the sleep function, but instead of time, it counts ticks. It can
  581. even output a frame rate higher than what you would naturally see on your real
  582. world monitor, but it's not really meant to do that. Setting a tick rate that's
  583. too high will result in errors as detailed below.
  584.  
  585. Use 'wait(n)' with a number argument to loop 'n' ticks per second.
  586. • This function will calculate and return the 'fps' value.
  587. • 20 is the default value for 'n' if no argument is given.
  588. • Enter 1-20 to sleep for '1/n' amount of time. You can also enter decimals
  589.   between 0 and 1 or fractions to sleep for longer than 1 second.
  590. • Enter a number above 20 to set a tick rate faster than 20. Currently this is
  591.   restricted to multiples of 20. This may be fixed in a future update.
  592. • Entering 0 will throw an out of range error.
  593. • Entering a value that is too high may result in the following:
  594.   • You will get the 'Too long without yielding' error.
  595.   • You will get calculation errors with 'fps' and 'frameTime'.
  596.   • Your tick rate will become extremely unstable.
  597.   • You will experience input lag.
  598.   • Peformance varies depending on the speed of your real world CPU.
  599.  
  600. Additional values can also be returned from this function's methods.
  601. • 'wait(n)' or 'wait.fps()' will return the current ticks per second.
  602. • 'wait.ticks()' will return the total number of ticks counted by the function.
  603. • 'wait.startTime()' will return the 'os.clock()' time that the program started.
  604. • 'wait.programClock()' will return the time since the program started.
  605. • 'wait.frameTime(real)' will return one of two values:
  606.   • If 'real' is true or not nil, it will return the average time for 1 tick.
  607.   • If 'real' is false or nil, it will return the same average time rounded to
  608.     the nearest 1/20th of a second to adhere to ComputerCraft's timing system.
  609.  
  610. The best way to use this function is with the parallel API.
  611. • Put 'wait(n)' and whatever else you want to run with it inside an infinite
  612.   loop inside a function.
  613. • Add your created function to 'parallel.waitForAny' with another function
  614.   that's taking user input and/or any other function you want to run with set
  615.   tick rates.
  616.  
  617. Run either of these programs for a proof of concept:
  618. https://pastebin.com/5pgLdX2D
  619. https://pastebin.com/U8DGAmie
  620. ]]
  621. wait = (function()
  622.     local ticks = 0
  623.     local startTime = os.clock()
  624.     local frames = {os.clock()}
  625.     local fps = 0
  626.  
  627.     return setmetatable({
  628.         ticks = function() return ticks end,
  629.         frameTime = function(real)
  630.             local time = os.clock()-frames[1]
  631.             if real then return time / fps
  632.             else return math.round(time / fps * 20) / 20 end
  633.         end,
  634.         startTime = function() return startTime end,
  635.         programClock = function() return os.clock() - startTime end,
  636.         fps = function() return fps end
  637.     }, {
  638.         __call = function(self, n)
  639.             n = tonumber(n) or 20
  640.             if n <= 0 then error("Value out of range, must be greater than 0", 2) end
  641.             ticks = ticks + 1
  642.             frames[#frames+1] = os.clock()
  643.             if n <= 20 then
  644.                 sleep(1/n)
  645.             elseif ticks%math.round(n/20) == 0 then
  646.                 sleep(0.05)
  647.             end
  648.             while os.clock()-frames[1] > 1 and #frames > 1 do
  649.                 table.remove(frames, 1)
  650.             end
  651.             fps =  #frames / (os.clock() - frames[1]) - (math.floor(n/20)-1)
  652.             return fps
  653.         end
  654.     })
  655. end)()
  656.  
  657. -- Check if a specific value is equal to any of multile values.
  658. OR = function(val, ...)
  659.     local returnCode = false
  660.     for _, v in ipairs({...}) do
  661.         returnCode = returnCode or v == val
  662.     end
  663.     return returnCode
  664. end
  665.  
  666. -- Check if a specific value is equal to all of multiple values.
  667. AND = function(val, ...)
  668.     local returnCode = true
  669.     for _, v in ipairs({...}) do
  670.         returnCode = returnCode and v == val
  671.     end
  672.     return returnCode
  673. end
  674.  
  675. -- Check if a number is between two numbers, inclusive or non-inclusive.
  676. isBetween = function(val, low, high, inclusive)
  677.     expect.expect(1, val, "string", "number")
  678.     expect.expect(2, low, "string", "number")
  679.     expect.expect(3, high, "string", "number")
  680.     expect.expect(4, inclusive, "nil", "boolean")
  681.     if inclusive then return val >= low and val <= high
  682.     else return val > low and val < high end
  683. end
  684.  
  685. -- Freezes the program to check values for bug testing.
  686. -- The program will resume when any key is pressed.
  687. bugCheck = function(x, y, s)
  688.     local oldX, oldY = term.getCursorPos()
  689.     term.setCursorPos(x, y)
  690.     term.setBackgroundColor(colors.black)
  691.     term.setTextColor(colors.red)
  692.     write(s)
  693.     os.pullEvent("key")
  694.     term.setCursorPos(oldX, oldY)
  695. end
  696.  
  697. --[[ Changelog
  698.     The changelog has been moved to its own file: https://pastebin.com/2cK0DcBk
  699. ]]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement