296 lines
8.2 KiB
Lua
296 lines
8.2 KiB
Lua
-- set system seed
|
|
math.randomseed(os.time())
|
|
|
|
-- system options/components
|
|
local system = {}
|
|
|
|
|
|
function set_converter(options)
|
|
return mekanismEnergyHelper[
|
|
string.format('joulesTo%s', options.unit)
|
|
]
|
|
end
|
|
|
|
-- convert number to compact form (1000 => 1k)
|
|
function compact_number(number)
|
|
local units = {'k', 'M', 'G', 'T'}
|
|
local index = 0
|
|
|
|
-- scale number, increment unit index
|
|
while number >= 1000 do
|
|
number = number / 1000
|
|
index = index + 1
|
|
end
|
|
|
|
-- keep 2 decimals, add units
|
|
return string.format('%.2f %s', number, units[index] or ' ')
|
|
end
|
|
|
|
-- format number with energy (/transfer) units
|
|
function format_energy(options, number, transfer)
|
|
local energy = number
|
|
|
|
-- compact number
|
|
if options.compact then
|
|
energy = compact_number(number)
|
|
else
|
|
energy = energy .. ' '
|
|
end
|
|
|
|
-- append transfer unit
|
|
local t_unit = ' '
|
|
if transfer or false then
|
|
t_unit = '/t'
|
|
end
|
|
|
|
-- build string
|
|
return energy .. options.unit .. t_unit
|
|
end
|
|
|
|
-- format percentages as number with two decimals and padded unit
|
|
function format_percent(options, number, mult)
|
|
-- multiply by default
|
|
local percent = number
|
|
if mult == nil or mult == true then
|
|
percent = number * 100
|
|
end
|
|
|
|
return string.format('%.2f ', percent) .. '% ' .. string.rep(' ', #(options.unit or ''))
|
|
end
|
|
|
|
-- format temperature as number with two decimals and padded unit
|
|
function format_temp(options, number)
|
|
local temperature = number
|
|
|
|
-- compact number
|
|
if options.compact then temperature = compact_number(number)
|
|
else temperature = string.format('%.2f ', temperature) end
|
|
|
|
-- build string
|
|
return temperature .. 'K ' .. string.rep(' ', #(options.unit or ''))
|
|
end
|
|
|
|
-- format liquids as compact number and padded unit
|
|
function format_liquid(options, number, transfer)
|
|
local liquid = number
|
|
|
|
-- compact number
|
|
if options.compact then
|
|
liquid = compact_number(number)
|
|
else
|
|
liquid = liquid .. ' '
|
|
end
|
|
|
|
-- append transfer unit
|
|
local t_unit = ' '
|
|
if transfer or false then
|
|
t_unit = '/t'
|
|
end
|
|
|
|
return liquid .. 'mB' .. t_unit
|
|
end
|
|
|
|
function find_peripheral_component(name)
|
|
for _, side in pairs(peripheral.getNames()) do
|
|
if peripheral.getType(side) == name then
|
|
return peripheral.wrap(side)
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
-- scan for system components
|
|
function scan_components(name)
|
|
-- try finding with peripherals
|
|
local component = find_peripheral_component(name)
|
|
local modem = find_peripheral_component('modem')
|
|
|
|
-- check if components were found
|
|
local found_component = not component
|
|
local found_modem = not modem
|
|
-- output corresponding error messages
|
|
if found_component or found_modem then
|
|
print('Invalid configuration detected!')
|
|
if found_component then print('Main component not found!') end
|
|
if found_modem then print('Modem not found!') end
|
|
end
|
|
|
|
-- return component data
|
|
local success = not (found_component or found_modem)
|
|
return {
|
|
success = success,
|
|
main = component,
|
|
modem = modem,
|
|
}
|
|
end
|
|
|
|
-- split string by delimiter
|
|
function split_string(text, delimiter)
|
|
local result = {}
|
|
for match in (text .. delimiter):gmatch('(.-)' .. delimiter) do
|
|
table.insert(result, match)
|
|
end
|
|
return result
|
|
end
|
|
|
|
-- initialize ender modem
|
|
function init_modem(options)
|
|
system.channel = nil
|
|
-- open initializer port
|
|
system.modem.open(1)
|
|
|
|
-- try initializing communication
|
|
local count = 1
|
|
while true do
|
|
local channel = math.random(2, 1 + options.channels)
|
|
-- open reply channel
|
|
system.modem.open(channel)
|
|
system.modem.transmit(1, channel, options.name)
|
|
|
|
term.setCursorPos(1, 6)
|
|
print('\nTry #' .. count)
|
|
print('Trying channel ' .. channel .. string.rep(' ', #tostring(1 + options.channels)))
|
|
-- increment try-counter
|
|
count = count + 1
|
|
|
|
-- wait for response
|
|
local timer_id = os.startTimer(options.timeout)
|
|
while true do
|
|
local event, _, senderChannel, _, message, _ = os.pullEvent()
|
|
|
|
if event == 'modem_message' and senderChannel == channel then
|
|
local result = split_string(message, ' ')
|
|
-- save channel for communication
|
|
if result[1] == 'ready' then
|
|
system.width = tonumber(result[2])
|
|
system.channel = channel
|
|
-- cancel timer on success
|
|
os.cancelTimer(timer_id)
|
|
-- already in use; reset channel
|
|
elseif message == 'used' then
|
|
system.modem.close(channel)
|
|
end
|
|
break
|
|
-- retry on timeout
|
|
elseif event == 'timer' then break end
|
|
end
|
|
|
|
-- success condition
|
|
if system.channel then break end
|
|
end
|
|
|
|
-- close initializer port
|
|
system.modem.close(1)
|
|
end
|
|
|
|
-- scan for components and retry on fail
|
|
function wait_for_components(options)
|
|
system.timeout = false
|
|
local count = 1
|
|
-- fixed print out
|
|
term.clear()
|
|
term.setCursorPos(1, 1)
|
|
print('Scanning for valid configuration:')
|
|
while true do
|
|
-- reset terminal
|
|
term.setCursorPos(1, 2)
|
|
-- output retry count
|
|
print('Try #' .. count .. '\n')
|
|
count = count + 1
|
|
|
|
-- scan for components
|
|
local components = scan_components(options.port)
|
|
if components.success then
|
|
-- output success message
|
|
print('Success!')
|
|
print('Trying to connect to receiver . . .')
|
|
-- set system components
|
|
system.main = components.main
|
|
system.modem = components.modem
|
|
init_modem(options)
|
|
print('\nSuccess!')
|
|
return true
|
|
end
|
|
|
|
-- components not found, wait to retry
|
|
print('Failed!')
|
|
os.sleep(options.timeout)
|
|
end
|
|
end
|
|
|
|
-- queue message for transfer
|
|
function message(buffer, text)
|
|
table.insert(buffer, text)
|
|
end
|
|
|
|
-- output aligned string by padding whitespaces in the middle of it to reach width
|
|
function message_aligned(buffer, text, value, width)
|
|
local str = tostring(value)
|
|
local length = width - #str
|
|
message(buffer, string.format("%-" .. length .. "s%s", text, value))
|
|
end
|
|
|
|
-- transmit buffered messages over ender modem
|
|
function transmit_messages(options, buffer)
|
|
system.modem.transmit(system.channel, system.channel, table.concat(buffer, '\n'))
|
|
|
|
local timer_id = os.startTimer(options.timeout)
|
|
while true do
|
|
local event, _, senderChannel, _, message, _ = os.pullEvent()
|
|
|
|
-- respond to corresponding message only
|
|
if event == 'modem_message' and senderChannel == system.channel and message == 'ok' then
|
|
-- cancel timer on success
|
|
os.cancelTimer(timer_id)
|
|
return
|
|
-- cancel on timeout
|
|
elseif event == 'timer' then
|
|
system.timeout = true
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
function respond_print(options, name)
|
|
-- buffer for messages
|
|
local buffer = {}
|
|
-- generate messages in buffer
|
|
execute_funcs(system.width, system.main, buffer, name)
|
|
-- transmit messages in form of buffer
|
|
if #buffer > 0 then transmit_messages(options, buffer) end
|
|
end
|
|
|
|
function event_listener(options)
|
|
while true do
|
|
local _, _, senderChannel, _, message, _ = os.pullEvent('modem_message')
|
|
|
|
-- respond to corresponding message only
|
|
if senderChannel == system.channel then
|
|
-- send main display message
|
|
respond_print(options, message)
|
|
end
|
|
end
|
|
end
|
|
|
|
function execute_funcs(width, component, buffer, name)
|
|
for key, func in pairs(system.funcs) do
|
|
if type(func) == "function" and key == name then
|
|
func(width, component, buffer)
|
|
end
|
|
end
|
|
end
|
|
|
|
function run_client(options, funcs)
|
|
-- save response functions
|
|
system.funcs = funcs
|
|
|
|
-- get components and run permanently
|
|
while wait_for_components(options) do
|
|
-- reset terminal
|
|
term.clear()
|
|
-- run while all components are detected
|
|
while scan_components(options.port).success and (not system.timeout) do
|
|
event_listener(options)
|
|
end
|
|
end
|
|
end |