Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- This program is to be installed on a computer that controls a single rail
- junction. As a player with a portable computer approaches, that portable
- computer will be sending out a signal containing their route, and this switch
- will decode it and make any adjustments it needs to.
- ]]--
- local CONFIG_FILE = "switch_config.tbl"
- local CHANNEL = 45450
- local config = nil
- local modem = peripheral.wrap("top") or error("Missing top modem")
- if not modem.isWireless() then error("Wireless modem required") end
- modem.open(CHANNEL)
- term.clear()
- term.setCursorPos(1, 1)
- print("Receiving routing commands on channel " .. CHANNEL)
- -- Series of guided inputs for building a configuration file from user input.
- local function configSetupWizard()
- local cfg = {range = 32, switches = {}}
- term.clear()
- term.setCursorPos(1, 1)
- print("Switch Controller Config Setup Wizard")
- print("-------------------------------------")
- print("What range (blocks) does this switch have? Defaults to 32.")
- local rangeStr = io.read()
- if rangeStr then
- local rangeInt = tonumber(rangeStr)
- if rangeInt == nil or rangeInt < 1 or rangeInt > 128 then
- print("Invalid range value. Should be a positive integer number. Got "..rangeStr)
- return nil
- end
- cfg.range = rangeInt
- end
- print("How many switch configurations are there? Usually 1 for each possible path of travel.")
- local switchCountStr = io.read()
- if not switchCountStr then
- print("Invalid switch configuration count.")
- return nil
- end
- local switchCount = tonumber(switchCountStr)
- if switchCount == nil or switchCount < 2 or switchCount > 32 then
- print("Invalid switch configuration count. Expected a positive integer between 2 and 32.")
- return nil
- end
- for i = 1, switchCount do
- local sw = {from = nil, to = nil, controls = {}}
- print("Switch Configuration #"..i..":")
- print("What is name of the branch traffic comes from?")
- sw.from = io.read()
- print("What is the name of the branch traffic goes to?")
- sw.to = io.read()
- print("How many control points are needed for this switch configuration?")
- local controlCountStr = io.read()
- local controlCount = 0
- if controlCountStr then controlCount = tonumber(controlCountStr) end
- if not controlCount or controlCount < 1 then
- print("Invalid control point count. Expected a positive integer.")
- return nil
- end
- for c = 1, controlCount do
- local ctl = {type = "redstone", side = "top", state = true}
- print(" Control Point #"..c..":")
- print(" What type of control is this?")
- print(" 1. redstone")
- print(" 2. redstoneIntegrator")
- local typeStr = io.read()
- if not typeStr or typeStr == "1" or typeStr == "redstone" then
- ctl.type = "redstone"
- print(" What side is redstone output on?")
- ctl.side = io.read()
- print(" What state should the output be? [T/F]")
- local stateStr = io.read()
- ctl.state = stateStr == "T" or stateStr == "True" or stateStr == "t" or stateStr == "true"
- elseif typeStr == "2" or typeStr == "redstoneIntegrator" then
- ctl.type = "redstoneIntegrator"
- print(" What is the peripheral name?")
- ctl.name = io.read()
- print(" What side is output on?")
- ctl.side = io.read()
- print(" What state should the output be? [T/F]")
- local stateStr = io.read()
- ctl.state = stateStr == "T" or stateStr == "True" or stateStr == "t" or stateStr == "true"
- else
- print(" Unsupported control type.")
- return nil
- end
- table.insert(sw.controls, ctl)
- end
- table.insert(cfg.switches, sw)
- end
- local f = io.open(CONFIG_FILE, "w")
- f:write(textutils.serialize(cfg))
- f:close()
- return cfg
- end
- local function loadConfig()
- if fs.exists(CONFIG_FILE) then
- local f = io.open(CONFIG_FILE, "r")
- local cfg = textutils.unserialize(f:read("*a"))
- f:close()
- print("Loaded configuration from file:")
- print(" "..tostring(#cfg.switches).." switch configurations.")
- print(" "..tostring(cfg.range).." block range.")
- return cfg
- else
- print("File "..CONFIG_FILE.." doesn't exist. Start setup wizard? [y/n]")
- local response = io.read()
- if response == "y" or response == "Y" or response == "yes" then
- return configSetupWizard()
- else
- return nil
- end
- end
- end
- local function findSwitchConfiguration(cfg, from, to)
- if from == nil or to == nil then return nil end
- for _, sw in pairs(cfg.switches) do
- if sw.from == from and sw.to == to then return sw end
- end
- return nil
- end
- local function isSwitchConfigurationActive(sw)
- for _, control in pairs(sw.controls) do
- if control.type == "redstone" then
- local state = redstone.getOutput(control.side)
- if state ~= control.state then return false end
- elseif control.type == "redstoneIntegrator" then
- local state = peripheral.call(control.name, "getOutput", control.side)
- if state ~= control.state then return false end
- else
- error("Invalid control type: "..control.type)
- end
- end
- return true
- end
- local function activateSwitchConfiguration(sw)
- print("Activating switch: FROM="..sw.from..", TO="..sw.to)
- for _, control in pairs(sw.controls) do
- if control.type == "redstone" then
- redstone.setOutput(control.side, control.state)
- elseif control.type == "redstoneIntegrator" then
- peripheral.call(control.name, "setOutput", control.side, control.state)
- else
- error("Invalid control type: "..control.type)
- end
- end
- end
- -- Handles incoming rail messages that consist of a list of branch names
- -- that the user would like to traverse.
- local function handleModemMsg(replyChannel, msg)
- -- Ignore invalid messages.
- if not msg or #msg < 2 then return end
- -- Find the switch configuration(s) that pertain to this route.
- for i = 1, #msg - 1 do
- local sw = findSwitchConfiguration(config, msg[i], msg[i+1])
- if sw and not isSwitchConfigurationActive(sw) then
- activateSwitchConfiguration(sw)
- end
- end
- end
- config = loadConfig()
- if not config then
- print("Unable to load configuration. Exiting.")
- return
- end
- while true do
- local event, p1, p2, p3, p4, p5 = os.pullEvent()
- if event == "modem_message" then
- local channel = p2
- local replyChannel = p3
- local msg = p4
- local dist = p5
- if channel == CHANNEL and dist ~= nil and dist < config.range and msg ~= nil then
- handleModemMsg(replyChannel, msg)
- end
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement