djcproductions

matrixcentered

Jun 18th, 2023 (edited)
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.55 KB | None | 0 0
  1. --[[
  2.   Wolfe's Mekanism Induction Matrix Monitor
  3.   Usage: Put computer with code near an Induction Port and a monitor (2x3 array should work fine) and run.
  4.   Configuration: You can add a file called "config" with the options below, or append them to the command when running it via terminal:
  5.     energy_type = 'FE' -- Energy type you want to use
  6.     update_frequency = 1 -- Update frequency, in seconds
  7.     text_scale = 1 -- The text scale on the monitor, use 0.5 if you want to run on less displays
  8.     side_monitor = 'right' -- Hardcodes which side the monitor should be, defaults to auto-detection
  9.     side_inductor = 'back' -- Hardcodes which side the Induction Port should be, defaults to auto-detection
  10. ]]
  11.  
  12. --
  13. -- Usage: Put computer near an Induction Port and a monitor , set the sides below and run.
  14.  
  15. -- Default settings
  16. options = {
  17.   energy_type = 'FE',
  18.   update_frequency = 1,
  19.   text_scale = 1,
  20. }
  21.  
  22. -- Loads custom options from file (if available)
  23. if fs.exists('config') then
  24.   -- Opens the file for reading
  25.   local handle = fs.open('config')
  26.  
  27.   -- Reads configs
  28.   raw_options = {}
  29.   local line = handle.readLine()
  30.   while line do
  31.     table.insert(raw_options, line)
  32.     line = handle.readLine()
  33.   end
  34.  
  35.   -- Sets custom options
  36.   custom_options = string.format('{%s}', table.concat(raw_options, '\n,'))
  37.  
  38.   -- Closes the handle properly
  39.   handle.close()
  40. end
  41.  
  42. -- Sets up progress bar
  43.  
  44. local function progressbar(percent,x,y,w,h,fg,bg)
  45.   local filled_w = math.floor(w*(percent/100))
  46.   local rest = math.floor(w-filled_w)
  47.   local color_fg = ("%x"):format(math.log(fg,2))
  48.   local color_bg = ("%x"):format(math.log(bg,2))
  49.   for sl=1,h do
  50.     term.setCursorPos(x,sl+y-1)
  51.     term.blit(
  52.       (" "):rep(w),
  53.       ("f"):rep(w),
  54.       color_fg:rep(filled_w) .. color_bg:rep(rest)
  55.     )
  56.   end
  57. end
  58.  
  59. -- Gets custom settings via arguments
  60. args = {...}
  61. if args and #args > 0 then
  62.   -- Parses custom settings from args
  63.   custom_options = string.format('{%s}', table.concat(args, '\n,'))
  64. end
  65.  
  66. -- Detects custom options
  67. if custom_options then
  68.   -- Debug only
  69.   print('Running with custom options:')
  70.  
  71.   -- Makes sure we're dealing with a table to prevent code injection
  72.   if '{' == custom_options:sub(1, 1) then
  73.     -- Parses the object
  74.     custom_options, err = loadstring(string.format('return %s', custom_options))
  75.  
  76.     -- Handles invalid object
  77.     if not custom_options then
  78.       print('Invalid options:')
  79.       print(err)
  80.     else
  81.       -- Replaces settings
  82.       for k, v in pairs(custom_options()) do
  83.         print(string.format('%s = %s', k, v))
  84.         options[k] = v
  85.       end
  86.     end
  87.   end
  88. end
  89.  
  90. -- Auto-detects sides
  91. for _, side in pairs(peripheral.getNames()) do
  92.   -- Auto-detects monitor
  93.   if 'monitor' == peripheral.getType(side) and (not options.side_monitor) then
  94.     options.side_monitor = side
  95.   end
  96.  
  97.   -- Auto-detects Induction Port
  98.   if 'inductionPort' == peripheral.getType(side) and (not options.side_inductor) then
  99.     options.side_inductor = side
  100.   end
  101. end
  102.  
  103. -- Connects to Peripherals
  104. monitor = peripheral.wrap(options.side_monitor)
  105.  
  106. -- Queues a new print command to be sent
  107. buffer = {}
  108. function queue (text)
  109.   table.insert(buffer, text)
  110. end
  111.  
  112. -- Queues a new print command with string.format
  113. function queuef (fmt, ...)
  114.   queue(string.format(fmt, ...))
  115. end
  116.  
  117. -- Flushes (prints) buffer content
  118. function queue_flush (percent)
  119.   -- Clears terminal
  120.   term.setBackgroundColor(colors.black)
  121.   term.clear()
  122.   term.setCursorPos(1, 1)
  123. progressbar(percent,8,4,12,1,colors.green,colors.black)
  124.  
  125.   -- Writes new data
  126.   local w, h = term.getSize()
  127. local y_offset = math.ceil(h / 2 - #buffer / 2) - 2
  128. for y, line in ipairs(buffer) do
  129.   term.setCursorPos(
  130.     math.ceil(w / 2 - #line / 2),
  131.     y + y_offset
  132.   )
  133.   term.write(line)
  134. end
  135. buffer = {}
  136. end
  137.  
  138. -- Formats time
  139. function time (secs)
  140.   -- Prepare value
  141.   secs = math.floor(secs)
  142.  
  143.   -- Days
  144.   local weeks = math.floor(secs / 604800)
  145.   secs = secs - (604800 * weeks)
  146.  
  147.   -- Days
  148.   local days = math.floor(secs / 86400)
  149.   secs = secs - (86400 * days)
  150.  
  151.   -- Hours
  152.   local hours = math.floor(secs / 3600)
  153.   secs = secs - (3600 * hours)
  154.  
  155.   -- Minutes
  156.   local mins = math.floor(secs / 60)
  157.   secs = secs - (60 * mins)
  158.  
  159.   -- If we have more than 72h worth of storage, switch to week, day, hour format
  160.   if weeks > 0 then
  161.     return string.format('%dwk %dd %dh', weeks, days, hours)
  162.   elseif days >= 3 then
  163.     return string.format('%dd %dh', days, hours)
  164.   end
  165.  
  166.   -- Formatting to have trailing zeros on H:MM:SS
  167.   return string.format('%d:%02d:%02d', hours, mins, secs)
  168. end
  169.  
  170. -- Rounds number
  171. function rnd (val, dec)
  172.   local X = math.pow(10, dec)
  173.   return math.floor(val * X) / X
  174. end
  175.  
  176. -- Converts to percentage
  177. function pct (val, dec)
  178.   return rnd(100 * val, dec or 1) .. '%'
  179. end
  180.  
  181. -- Converts to readable power
  182. function pwr (val, dec)
  183.   local pre = ''
  184.   local suf = ''
  185.  
  186.   local is_neg = false
  187.   if val < 0 then
  188.     pre = '-'
  189.     is_neg = true
  190.     val = -val
  191.   end
  192.  
  193.   val = energy_function(val)
  194.  
  195.   if val > 1000 then
  196.     suf = 'k'
  197.     val = val / 1000
  198.   end
  199.  
  200.   if val > 1000 then
  201.     suf = 'M'
  202.     val = val / 1000
  203.   end
  204.  
  205.   if val > 1000 then
  206.     suf = 'G'
  207.     val = val / 1000
  208.   end
  209.  
  210.   if val > 1000 then
  211.     suf = 'T'
  212.     val = val / 1000
  213.   end
  214.  
  215.   return string.format('%s%s%s%s', pre, rnd(val, dec or 1), suf, energy_type)
  216. end
  217.  
  218. -- Checks induction port
  219. function check_connection ()
  220.   return inductor and inductor.getEnergy and inductor.getLastInput
  221. end
  222.  
  223. -- Detects energy type, sets energy function
  224. energy_type = options.energy_type
  225. energy_function = mekanismEnergyHelper[string.format('joulesTo%s', energy_type)]
  226.  
  227. -- Function not found, use default Joules and a stub
  228. if not energy_function then
  229.   energy_type = 'J'
  230.   energy_function = function (val) return val end
  231. end
  232.  
  233. -- Starts monitor
  234. term.redirect(monitor)
  235. monitor.setTextScale(options.text_scale)
  236.  
  237. -- Checks if Inductor Port is missing or multiblock not ready
  238. inductor = peripheral.wrap(options.side_inductor)
  239. while not check_connection() do
  240.   -- Writes error message
  241.   queue('Ind.Port not found')
  242.   queue('Check connections.')
  243.   queue('Waiting...')
  244.  
  245.   -- Prints
  246.   queue_flush(0)
  247.  
  248.   -- Wait for next update
  249.   os.sleep(options.update_frequency)
  250.  
  251.   -- Tries to detect port
  252.   if not options.side_inductor then
  253.     for _, side in pairs(peripheral.getNames()) do
  254.       -- Tries to find an induction port
  255.       if 'inductionPort' == peripheral.getType(side) then
  256.         options.side_inductor = side
  257.         inductor = peripheral.wrap(options.side_inductor)
  258.       end
  259.     end
  260.   else
  261.     -- Try again on pre-set port
  262.     inductor = peripheral.wrap(options.side_inductor)
  263.   end
  264. end
  265.  
  266. -- Initializes balance
  267. balance = inductor.getEnergy()
  268. while true do
  269.   local status, err = pcall(function ()
  270.     -- Main script
  271.     queue('Ind.Matrix Monitor')
  272.     queue('------------------')
  273.     queue('')
  274.     queuef('Power : %s', pwr(inductor.getEnergy()))
  275.     queuef('Limit : %s', pwr(inductor.getMaxEnergy()))
  276.     queuef('Charge: %s', pct(inductor.getEnergyFilledPercentage()))
  277.     queue('')
  278.     queue('')
  279.     queuef('Input : %s', pwr(inductor.getLastInput()))
  280.     queuef('Output: %s', pwr(inductor.getLastOutput()))
  281.     queuef('Max IO: %s/t', pwr(inductor.getTransferCap()))
  282.     queue('')
  283.    
  284.     -- Power balance per second
  285.     local balance_last = balance
  286.     balance = inductor.getEnergy()
  287.     local balance_change = (balance - balance_last) / options.update_frequency
  288.    
  289.  
  290.     -- Status (charged/depleted in)
  291.     queue('Status:')
  292.     if balance_change > 0 then
  293.       -- Charging
  294.       local remaining_charge = inductor.getMaxEnergy() - inductor.getEnergy()
  295.       local seconds_remaining = remaining_charge / balance_change
  296.       queuef('Charg. %s', time(seconds_remaining))
  297.     elseif balance_change < 0 then
  298.       -- Discharging
  299.       local remaining_charge = inductor.getEnergy()
  300.       local seconds_remaining = remaining_charge / -balance_change
  301.       queuef('Disch. %s', time(seconds_remaining))
  302.     else
  303.       -- No changes, so we won't be charged or depleted, rare.
  304.       queue('Idle')
  305.     end
  306.   end)
  307.  
  308.   -- Checks for errors (might be disconnected)
  309.   if not status then
  310.     -- Clears buffer first
  311.     buffer = {}
  312.  
  313.     -- Shows error message
  314.     queue('Error reading data')
  315.     queue('Check connections.')
  316.     queue('------------------')
  317.     queue(err)
  318.   end
  319.  
  320.   -- Prints
  321.   queue_flush(inductor.getEnergyFilledPercentage())
  322.  
  323.   -- Wait for next update
  324.   os.sleep(options.update_frequency)
  325. end
Advertisement
Add Comment
Please, Sign In to add comment