Advertisement
HandieAndy

RailSignal Install Script

Nov 26th, 2021 (edited)
1,749
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.50 KB | None | 0 0
  1. -- Installation script for RailSignal components.
  2. -- By Andrew Lalis.
  3.  
  4. local function tableLength(t)
  5.     local c = 0
  6.     for _ in pairs(t) do
  7.         c = c + 1
  8.     end
  9.     return c
  10. end
  11.  
  12. local function startsWith(str, s)
  13.     return str:find(s, 1, true) == 1
  14. end
  15.  
  16. local function printSep()
  17.     local w, h = term.getSize()
  18.     print(string.rep("-", w))
  19. end
  20.  
  21. local function readNum()
  22.     local num = nil
  23.     repeat
  24.         local s = io.read()
  25.         if s ~= nil then num = tonumber(s) end
  26.         if num == nil then print("Please enter a valid number.") end
  27.     until num ~= nil
  28.     return num
  29. end
  30.  
  31. local function readStr(default)
  32.     while true do
  33.         local str = io.read()
  34.         if str ~= nil and string.len(str) > 0 then
  35.             return str
  36.         elseif default ~= nil then
  37.             return default
  38.         end
  39.     end
  40.     repeat str = io.read() until str ~= nil
  41.     return str
  42. end
  43.  
  44. local function readBool()
  45.     while true do
  46.         local str = io.read()
  47.         if str ~= nil and string.len(str) > 0 then
  48.             str = string.upper(str)
  49.             if str == "Y" or str == "YES" then return true end
  50.             if str == "N" or str == "NO" then return false end
  51.         end
  52.         print("Please enter \"yes\" or \"no\".")
  53.     end
  54. end
  55.  
  56. local function readRedstoneSide()
  57.     while true do
  58.         local str = io.read()
  59.         if str ~= nil and string.len(str) > 0 then
  60.             str = string.lower(str)
  61.             for _, side in pairs(redstone.getSides()) do
  62.                 if str == side then return side end
  63.             end
  64.         end
  65.         print("Please enter a valid side: top, bottom, left, right, front or back.")
  66.     end
  67. end
  68.  
  69. local function choose(choices, required)
  70.     if required == nil then required = true end
  71.     local choiceCount = tableLength(choices)
  72.     local i = 1
  73.     local keys = {}
  74.     for k, value in pairs(choices) do
  75.         keys[i] = k
  76.         i = i + 1
  77.     end
  78.     table.sort(keys)
  79.     for k, v in pairs(keys) do
  80.         local str = choices[v] or v
  81.         print(k .. ") " .. str)
  82.     end
  83.     while true do
  84.         local input = io.read()
  85.         if input ~= nil and string.len(input) > 0 then
  86.             local chosenIndex = tonumber(input)
  87.             if chosenIndex == nil or chosenIndex < 1 or chosenIndex > choiceCount then
  88.                 print("Invalid choice. Please enter a number from 1 to " .. choiceCount .. ".")
  89.             else
  90.                 return keys[chosenIndex]
  91.             end
  92.         elseif not required then
  93.             return nil
  94.         else
  95.             print("Invalid input. Please enter a number from 1 to " .. choiceCount .. ".")
  96.         end
  97.     end
  98. end
  99.  
  100. local function choosePeripheral(pType, excludeNames, required)
  101.     -- Filter to only peripherals starting with the type, and aren't excluded.
  102.     local filter = function(name, p)
  103.         for _, v in pairs(excludeNames) do
  104.             if v == name then return false end
  105.         end
  106.         return startsWith(name, pType)
  107.     end
  108.     local ps = {peripheral.find(pType, filter)}
  109.     local choices = {}
  110.     for k, v in pairs(ps) do
  111.         choices[k] = peripheral.getName(v)
  112.     end
  113.     if tableLength(choices) == 0 then
  114.         print("No valid peripherals of the type " .. pType .. " found. Please ensure they're connected to the network, then try again.")
  115.         return nil
  116.     end
  117.     local choice = choose(choices, required)
  118.     return ps[choice]
  119. end
  120.  
  121. local function createSignalConfig(apiUrl, rsId, usedDetectors, usedMonitors)
  122.     local signal = {}
  123.     print("Enter the signal id.")
  124.     signal["id"] = readNum()
  125.     local resp = http.get(apiUrl .. "/railSystems/" .. rsId .. "/signals/" .. signal.id)
  126.     if resp == nil or resp.getResponseCode() ~= 200 then
  127.         print("Could not find signal with id " .. signal.id .. ".")
  128.         return nil
  129.     end
  130.     local signalData = textutils.unserializeJSON(resp.readAll())
  131.     print("Enter the redstone input side for this signal.")
  132.     signal["redstoneInputSide"] = readRedstoneSide()
  133.     print("Choose the detector for this signal.")
  134.     local det = choosePeripheral("ir_augment_detector", usedDetectors)
  135.     if det == nil then return nil end
  136.     signal["detector"] = peripheral.getName(det)
  137.     table.insert(usedDetectors, signal.detector)
  138.     signal["branches"] = {}
  139.     for k, con in pairs(signalData.branchConnections) do
  140.         print("Choose the monitor that will display the status of the " .. con.direction .. " connection to branch \"" .. con.branch.name .. "\". Leave empty if this connection doesn't have a monitor.")
  141.         local mon = choosePeripheral("monitor", usedMonitors, false)
  142.         local monitorName = nil
  143.         if mon ~= nil then
  144.             monitorName = peripheral.getName(mon)
  145.             table.insert(usedMonitors, monitorName)
  146.         end
  147.         local branch = {
  148.             id = con.branch.id,
  149.             direction = con.direction,
  150.             monitor = monitorName
  151.         }
  152.         table.insert(signal.branches, branch)
  153.     end
  154.     return signal
  155. end
  156.  
  157. -- SIGNAL INSTALL
  158.  
  159. local function downloadSignalScript()
  160.     local shouldDownload = true
  161.     if fs.exists("sig.lua") then
  162.         print("sig.lua already exists. Would you like to overwrite it?")
  163.         if readBool() then
  164.             fs.delete("sig.lua")
  165.         else
  166.             shouldDownload = false
  167.         end
  168.     end
  169.     if shouldDownload then
  170.         print("Downloading signal program...")
  171.         local result = shell.execute("pastebin", "get", "erA3mSfd", "sig.lua")
  172.         if not result then
  173.             print("Error occurred while downloading.")
  174.             return
  175.         end
  176.     end
  177. end
  178.  
  179. local function buildSignalConfig(apiUrl, rsId)
  180.     local config = {}
  181.     config["apiUrl"] = apiUrl
  182.     local wsUrlSuffix = apiUrl:sub(8) .. "/ws-signal"
  183.     if startsWith(apiUrl, "https://") then
  184.         config["wsUrl"] = "wss://" .. wsUrlSuffix
  185.     else
  186.         config["wsUrl"] = "ws://" .. wsUrlSuffix
  187.     end
  188.     config["wsHeader"] = "X-RailSignal-SignalId"
  189.     config["rsId"] = rsId
  190.     config["trainScanInterval"] = 0.5
  191.     config["statusColors"] = {
  192.         FREE = colors.lime,
  193.         OCCUPIED = colors.red,
  194.         ERROR = colors.blue,
  195.         NONE = colors.white
  196.     }
  197.     config["paletteColors"] = {
  198.         [colors.red] = 0xFF0000,
  199.         [colors.lime] = 0x00FF00,
  200.         [colors.blue] = 0x0000FF,
  201.         [colors.white] = 0xFFFFFF
  202.     }
  203.     config["signals"] = {}
  204.     return config
  205. end
  206.  
  207. local function finalizeSignalConfig(config)
  208.     if fs.exists("sig_config.tbl") then
  209.         fs.delete("sig_config.tbl")
  210.     end
  211.     local f = io.open("sig_config.tbl", "w")
  212.     if f == nil then
  213.         print("Could not open sig_config.tbl to write configuration data.")
  214.         return
  215.     end
  216.     f:write(textutils.serialize(config))
  217.     f:close()
  218.     print("Saved signal configuration.")
  219.     if fs.exists("startup.lua") then
  220.         fs.delete("startup.lua")
  221.     end
  222.     local f = io.open("startup.lua", "w")
  223.     if f == nil then
  224.         print("Could not open startup.lua to write startup script.")
  225.         return
  226.     end
  227.     f:write("-- Run RailSignal signal script.\nshell.execute(\"sig\")\n")
  228.     f:close()
  229.     print("Created startup script.")
  230.     print("Starting up signal now...")
  231.     shell.execute("sig")
  232. end
  233.  
  234. local function installSignal(apiUrl, rsId)
  235.     print("Installing RailSignal signal system.")
  236.     downloadSignalScript()
  237.     local config = buildSignalConfig(apiUrl, rsId)
  238.     print("How many signals will this computer manage?")
  239.     local signalCount = choose({1, 2, 3, 4, 5})
  240.     local usedDetectors = {}
  241.     local usedMonitors = {}
  242.     for i = 1, signalCount do
  243.         printSep()
  244.         print("Signal " .. i .. " / " .. signalCount .. ":")
  245.         local signal = createSignalConfig(apiUrl, rsId, usedDetectors, usedMonitors)
  246.         if signal == nil then
  247.             print("Could not create configuration for this signal, would you like to quit?")
  248.             if readBool() then
  249.                 return
  250.             end
  251.         else
  252.             table.insert(config.signals, signal)
  253.         end
  254.     end
  255.     printSep()
  256.     finalizeSignalConfig(config)
  257. end
  258.  
  259. -- MAIN SCRIPT
  260.  
  261. print("RailSignal Installer")
  262. printSep()
  263. print("Please enter the URL of your RailSignal server. Please ensure that it's running during the entirety of the installation. For example, \"http://localhost:8080\" is a valid URL. Leave blank to use that URL.")
  264. local rsUrl = readStr("http://localhost:8080")
  265. local apiUrl = rsUrl .. "/api"
  266. local resp = http.get(apiUrl .. "/status")
  267. if resp == nil or resp.getResponseCode() ~= 200 then
  268.     print("Could not connect to RailSignal API at " .. apiUrl .. "/status" .. " Please check that your RailSignal server is running and that your URL is correct.")
  269.     return
  270. end
  271. print("Successfully connected to the RailSignal API at " .. apiUrl)
  272. printSep()
  273. print("Please enter the id of the rail system to install components to. If no rail system is configured yet, go to " .. rsUrl .. " to create one.")
  274. local rsId = readNum()
  275. local resp = http.get(apiUrl .. "/railSystems/" .. rsId)
  276. if resp == nil or resp.getResponseCode() ~= 200 then
  277.     print("Could not find a rail system with id " .. rsId .. ". Please check that the system exists prior to running the installation.")
  278.     return
  279. end
  280. local railSystem = textutils.unserializeJSON(resp.readAll())
  281. print("Will install for the rail system: " .. railSystem.name)
  282. printSep()
  283. print("What type of system would you like to install?")
  284. local c = choose({signal="Signal"})
  285. printSep()
  286. if c == "signal" then
  287.     installSignal(apiUrl, rsId)
  288. end
  289.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement