Advertisement
wolfe_br

Mekanism Induction Matrix Manager v2 (Portable Receiver)

Jun 24th, 2023 (edited)
1,449
1
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.61 KB | Gaming | 1 0
  1. --[[
  2.   Wolfe's Mekanism Induction Matrix Monitor v2 (Portable Receiver)
  3.   Usage: Install into Portable Computer with Modem. Requires another computer transmitting matrix data over rednet to work.
  4.   Installation: pastebin run tiaLnvXp install
  5.   Configuration: Edit the "config" file, refer to the comments below for what each field means
  6. ]]
  7.  
  8. -- Default settings, do not change
  9. local options = {
  10.   -- Unique identifier for the destination matrix on rednet
  11.   rednet_identifier = '',
  12.  
  13.   -- Energy type being displayed (J, FE)
  14.   energy_type = 'FE',
  15.  
  16.   -- Output debug data to the computer's internal display
  17.   debug = true,
  18. }
  19.  
  20. --------------------------------------------------
  21. --- Internal variables, DO NOT CHANGE
  22. --------------------------------------------------
  23.  
  24. --- This will be used as the installer source (Pastebin)
  25. local INSTALLER_ID = 'tiaLnvXp'
  26.  
  27. --- Supported energy suffixes
  28. local energy_suffixes = { 'k', 'M', 'G', 'T', 'P' }
  29.  
  30. --- Supported time periods when converting seconds
  31. local time_periods = {
  32.   { 'weeks', 604800 },
  33.   { 'days', 86400 },
  34.   { 'hours', 3600 },
  35.   { 'minutes', 60 },
  36.   { 'seconds', 1 },
  37. }
  38.  
  39. --- This is our Induction Matrix, we'll auto-detect it later
  40. local induction_matrix = nil
  41.  
  42. --- This is our Modem, we'll auto-detect it later
  43. local modem = nil
  44.  
  45. --- Prefix used for rednet channels
  46. local rednet_prefix = 'WL_Mek_Matrix'
  47.  
  48. --------------------------------------------------
  49. --- Helper functions
  50. --------------------------------------------------
  51.  
  52. --- Reads a file's contents
  53. ---@return string
  54. function file_read (file)
  55.   local handle = fs.open(file, 'r')
  56.   local data = handle.readAll()
  57.   handle.close()
  58.   return data
  59. end
  60.  
  61. --- Writes data to a file (overrides existing data)
  62. function file_write (file, data)
  63.   local handle = fs.open(file, 'w')
  64.   handle.write(data)
  65.   handle.close()
  66. end
  67.  
  68. --- Holds the current buffer of data being printed
  69. local machine_term = term.current()
  70. local print_buffer = {}
  71.  
  72. --- Writes data to the output monitor buffer
  73. function print_r (text)
  74.   table.insert(print_buffer, text)
  75. end
  76.  
  77. --- Writes formatted data to the output monitor buffer
  78. function print_f (format, ...)
  79.   print_r(string.format(format, ...))
  80. end
  81.  
  82. --- Writes the buffer into the output monitor
  83. function print_flush ()
  84.   -- Clears terminal
  85.   term.clear()
  86.   term.setCursorPos(1, 1)
  87.  
  88.   -- Writes new data
  89.   print(table.concat(print_buffer or {}, '\n'))
  90.  
  91.   -- Clears buffer
  92.   print_buffer = {}
  93. end
  94.  
  95. --- Writes debug info to the machine
  96. function debug (...)
  97.   if options.debug then
  98.     print(...)
  99.   end
  100. end
  101.  
  102. --- Rounds a number with N decimals
  103. function round_decimal (number, decimals)
  104.   local multiplier = math.pow(10, decimals or 0)
  105.   return math.floor(number * multiplier) / multiplier
  106. end
  107.  
  108. --- Rounds a percentage (0..1) to a number of decimals
  109. function round_percentage (number, decimals)
  110.   return ('%s%%'):format(round_decimal(100 * number, decimals or 1))
  111. end
  112.  
  113. --- The current energy type
  114. local energy_type = 'J'
  115.  
  116. --- Converts energy values
  117. local energy_convert = function (energy) return energy end
  118. if mekanismEnergyHelper and mekanismEnergyHelper[('joulesTo%s'):format(options.energy_type)] then
  119.   energy_type = options.energy_type
  120.   energy_convert = mekanismEnergyHelper[('joulesTo%s'):format(options.energy_type)]
  121. end
  122.  
  123. --- Prints an energy value
  124. local energy_string = function (energy, decimals)
  125.   local prefix = ''
  126.   local suffix = ''
  127.  
  128.   -- Prepares a prefix for negative numbers
  129.   if energy < 0 then
  130.     prefix = '-'
  131.   end
  132.  
  133.   -- We need a positive number here for calculating multipliers (k, M, G, T), we'll add the minus later, we also convert it to the right unit
  134.   local amount = energy_convert(math.abs(energy))
  135.  
  136.   -- Finds the proper suffix/multiplier
  137.   for _, multiplier in pairs(energy_suffixes) do
  138.     -- Stops when amount is less than 1000
  139.     if amount < 1000 then
  140.       break
  141.     end
  142.  
  143.     -- Updates suffix and amount to new value
  144.     amount = amount / 1000
  145.     suffix = multiplier
  146.   end
  147.  
  148.   -- Returns the formatted string
  149.   return ('%s%s%s%s'):format(prefix, round_decimal(amount, decimals or 1), suffix, energy_type)
  150. end
  151.  
  152. --- Generates an ETA string when given a number of seconds
  153. function eta_string (seconds)
  154.   -- Makes sure we're only dealing with integers
  155.   seconds = math.floor(seconds)
  156.  
  157.   -- Processes time periods
  158.   local time = {}
  159.   for _, period in pairs(time_periods) do
  160.     local count = math.floor(seconds / period[2])
  161.     time[period[1]] = count
  162.     seconds = seconds - (count * period[2])
  163.   end
  164.  
  165.   -- If we have more than 72h worth of storage, switch to week, day, hour format
  166.   if time.weeks > 0 then
  167.     return ('%dwk %dd %dh'):format(time.weeks, time.days, time.hours)
  168.   elseif time.days >= 3 then
  169.     return ('%dd %dh'):format(time.days, time.hours)
  170.   end
  171.  
  172.   -- For all other cases, we'll just use H:MM:SS
  173.   return ('%d:%02d:%02d'):format(time.hours, time.minutes, time.seconds)
  174. end
  175.  
  176. --- Prints the Induction Matrix information
  177. function print_matrix_info (matrix_info)
  178.   print_r('Ind.Matrix Monitor')
  179.   print_r('------------------')
  180.   print_r('')
  181.   print_f('Power : %s', energy_string(matrix_info.energy_stored))
  182.   print_f('Limit : %s', energy_string(matrix_info.energy_capacity))
  183.   print_f('Charge: %s', round_percentage(matrix_info.energy_percentage))
  184.   print_r('')
  185.   print_f('Input : %s/t', energy_string(matrix_info.io_input))
  186.   print_f('Output: %s/t', energy_string(matrix_info.io_output))
  187.   print_f('Max IO: %s/t', energy_string(matrix_info.io_capacity))
  188.   print_r('')
  189.  
  190.   -- If we have negative value here, we'll save a character by removing the space so it fits same line
  191.   if matrix_info.change_amount < 0 then
  192.     print_f('Change:%s/s', energy_string(matrix_info.change_amount_per_second))
  193.   else
  194.     print_f('Change: %s/s', energy_string(matrix_info.change_amount_per_second))
  195.   end
  196.  
  197.   -- Charge/discharge status
  198.   print_r('Status:')
  199.   if matrix_info.is_charging then
  200.     print_f('Charg. %s', eta_string((matrix_info.energy_capacity - matrix_info.energy_stored) / matrix_info.change_amount_per_second))
  201.   elseif matrix_info.is_discharging then
  202.     print_f('Disch. %s', eta_string(matrix_info.energy_stored / math.abs(matrix_info.change_amount_per_second)))
  203.   else
  204.     print_r('Idle')
  205.   end
  206. end
  207.  
  208. --------------------------------------------------
  209. --- Program initialization
  210. --------------------------------------------------
  211.  
  212. args = {...}
  213.  
  214. -- Loads custom options from filesystem
  215. if fs.exists('config') then
  216.   debug('Loading settings from "config" file...')
  217.  
  218.   -- Reads custom options
  219.   local custom_options = textutils.unserialize(file_read('config'))
  220.  
  221.   -- Overrides each of the existing options
  222.   for k, v in pairs(custom_options) do
  223.     options[k] = v
  224.   end
  225. end
  226.  
  227. -- Writes back config file
  228. print('Updating config file...')
  229. file_write('config', textutils.serialize(options))
  230.  
  231. -- Handles special case when "install" is executed from the pastebin
  232. if 'install' == args[1] then
  233.   print('Installing Matrix Monitor (Receiver Module)...')
  234.  
  235.   -- Are we on first install? If so, we'll run open the config for editing later
  236.   local has_existing_install = fs.exists('startup.lua')
  237.  
  238.   -- Removes existing version
  239.   if fs.exists('startup.lua') then
  240.     fs.delete('startup.lua')
  241.   end
  242.  
  243.   -- Downloads script from Pastebin
  244.   shell.run('pastebin', 'get', INSTALLER_ID, 'startup.lua')
  245.  
  246.   -- Runs config editor
  247.   if not has_existing_install then
  248.     print('Opening config file for editing...')
  249.     sleep(2.5)
  250.     shell.run('edit', 'config')
  251.   end
  252.  
  253.   -- Reboots the computer after everything is done
  254.   print('Install complete! Restarting computer...')
  255.   sleep(2.5)
  256.   os.reboot()
  257. end
  258.  
  259. -- Detects peripherals
  260. modem = peripheral.find('modem')
  261.  
  262. --- The rednet channel/protocol we'll be using
  263. local rednet_channel = nil
  264.  
  265. -- Makes sure we have a connected modem
  266. if modem then
  267.   if not options.rednet_identifier or options.rednet_identifier == '' then
  268.     error('Modem has been found, but no wireless identifier found on configs!')
  269.   end
  270.  
  271.   peripheral.find('modem', rednet.open)
  272.   debug('Connected to rednet!')
  273.   rednet_channel = ('%s#%s'):format(rednet_prefix, options.rednet_identifier)
  274. else
  275.   error('No modem detected!')
  276. end
  277.  
  278. --------------------------------------------------
  279. --- Main runtime
  280. --------------------------------------------------
  281.  
  282. debug('Entering main loop...')
  283.  
  284. term.clear()
  285.  
  286. while true do
  287.   -- Receives next update
  288.   local id, message = rednet.receive(rednet_channel)
  289.  
  290.   -- Parses message
  291.   local matrix_info = textutils.unserialize(message)
  292.  
  293.   -- Prints the matrix information
  294.   print_matrix_info(matrix_info)
  295.  
  296.   -- Outputs text to screen
  297.   print_flush()
  298. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement