Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --Station Program:
- -- Keeps track of trains at each track
- -- Can choose which train to dispatch
- --Constants:
- local ticketMachine = peripheral.wrap("back")
- local mon
- local mon_x, mon_y
- local note_block
- local stationDisplayOffset = 0
- local RedstoneSide = "bottom"
- rednet.open("front")
- --Station Name:
- local STATION_NAME
- --Station Dest:
- local STATION_DEST
- --Server Computer ID:
- local SERVER_ID
- --File to hold station data:
- local STATION_FILE = "stations"
- --Protocols:
- local METADATA_PROT = "md"
- local METADATA_RQ = "rq"
- local UPDATE_PROT = "ud"
- local UPDATE_RQ = "rq"
- local DISPATCH_PROT = "dp"
- local REQUEST_PROT = "rq"
- local STATION_LIST_PROT = "sl"
- local STATION_LIST_RQ = "rq"
- local REBOOT_PROT = "rb"
- local REBOOT_RQ = "rb"
- --Data on each track available for control.
- local tracks
- --Data for every station in the network, for dispatch choices.
- local stations
- --Returns the number of items in a table.
- function tableSize(tbl)
- local count = 0
- for i in pairs(tbl) do count = count + 1 end
- return count
- end
- --Gets the information of a train at a specific track.
- function scanTrainAtTrack(trackNumber)
- local trainData = {}
- local ids = tracks[trackNumber].sensor.getMinecartIds()
- for i in pairs(ids) do
- local success, rawdata = pcall(tracks[trackNumber].sensor.getMinecartData, ids[i])
- if (success) then
- local data = rawdata.all()
- --Test if the locomotive is numbered, and check that it is above this sensor.
- if ((string.len(data.name) < 4) and (data.position.x < 1) and (data.position.z < 1) and (data.position.x > -1) and (data.position.z > -1)) then
- tracks[trackNumber].train = tonumber(data.name)
- return
- end
- end
- end
- tracks[trackNumber].train = -1
- end
- --Scans all tracks and saves the data to the trains table.
- function scanAllTracks()
- for i in pairs(tracks) do
- scanTrainAtTrack(i)
- end
- end
- --Handles ticket creation failure.
- function onTicketMachineFailure()
- print("Unable to create ticket.")
- end
- --Creates a ticket for a destination and sends it to a train, the train departs.
- function dispatchTrack(dest, trackNumber)
- local success = ticketMachine.createTicket(dest, 1)
- if (not success) then
- onTicketMachineFailure()
- return
- end
- rs.setBundledOutput(RedstoneSide, tracks[trackNumber].ticketColor)
- os.sleep(1)
- rs.setBundledOutput(RedstoneSide, 0)
- print("Train "..tracks[trackNumber].train.." dispatched to "..dest..".")
- end
- --Dispatches the given train by ID
- function dispatchTrain(dest, trainId)
- for i in pairs(tracks) do
- if (tracks[i].train == trainId) then
- dispatchTrack(dest, i)
- end
- end
- end
- --Dispatches the first train available to leave.
- function dispatchFirstAvailableTrain(dest)
- for i in pairs(tracks) do
- if (tracks[i].train ~= -1) then
- dispatchTrack(dest, i)
- return
- end
- end
- print("No train available to dispatch.")
- end
- --Sends station name, dest, ID, and track number to the server, upon request.
- function sendMetadata()
- rednet.send(SERVER_ID, {name = STATION_NAME, dest = STATION_DEST, id = os.getComputerID(), trackCount = tableSize(tracks)}, METADATA_PROT)
- print("Metadata sent to the server.")
- end
- --Sends an updated list of trains at this station to the server.
- function sendUpdate()
- local trains = {}
- for i in pairs(tracks) do
- if (tracks[i].train ~= -1) then
- table.insert(trains, tracks[i].train)
- end
- end
- rednet.send(SERVER_ID, trains, UPDATE_PROT)
- print("Update sent to server.")
- end
- --Sends a request to the server to send a train to a new destination.
- function sendRequest(dest)
- rednet.send(SERVER_ID, dest, REQUEST_PROT)
- print("Sent request for a train to "..dest)
- end
- --Initializes the station.
- function init()
- term.clear()
- term.setCursorPos(1,1)
- print("Initializing station...")
- local f = fs.open("station_config", "r")
- local config = textutils.unserialize(f.readAll())
- f.close()
- STATION_NAME = config.name
- STATION_DEST = config.dest
- SERVER_ID = config.server_id
- mon = peripheral.wrap(config.monitor_id)
- note_block = peripheral.wrap(config.note_block_id)
- mon_x, mon_y = mon.getSize()
- tracks = config.tracks
- for i in pairs(tracks) do
- tracks[i].sensor = peripheral.wrap(tracks[i].sensor_id)
- end
- sendMetadata()
- scanAllTracks()
- printTrains()
- sendUpdate()
- end
- --Sets up the monitor display.
- function initMonitor()
- mon.setBackgroundColor(colors.white)
- mon.clear()
- mon.setCursorPos(1,1)
- mon.setTextColor(colors.lightGray)
- mon.setBackgroundColor(colors.black)
- for i = 1, mon_x do
- mon.setCursorPos(i,1)
- mon.write(" ")
- end
- mon.setCursorPos(1,1)
- mon.write(STATION_NAME)
- mon.setCursorPos(mon_x-1,2)
- mon.setTextColor(colors.white)
- mon.setBackgroundColor(colors.lime)
- mon.write("/\\")
- mon.setBackgroundColor(colors.red)
- mon.setCursorPos(mon_x-1,3)
- mon.write("\\/")
- mon.setTextColor(colors.gray)
- mon.setBackgroundColor(colors.white)
- mon.setCursorPos(1,2)
- mon.write("Click a station to depart.")
- mon.setCursorPos(1,3)
- mon.write("Departing Track: ")
- loadStationList()
- displayStations()
- end
- --Displays the destinations on the screen.
- function displayStations()
- mon.setBackgroundColor(colors.white)
- for i=4,mon_y do
- for k=1,mon_x do
- mon.setCursorPos(k,i)
- mon.write(" ")
- end
- end
- for i=1,mon_y-4 do
- mon.setCursorPos(1,i+3)
- if (i % 2 == 0) then
- mon.setTextColor(colors.lightBlue)
- mon.setBackgroundColor(colors.gray)
- else
- mon.setTextColor(colors.blue)
- mon.setBackgroundColor(colors.lightGray)
- end
- if (i+stationDisplayOffset <= tableSize(stations)) then
- for i=1,mon_x do mon.write(" ") end
- mon.setCursorPos(1,i+3)
- if (stations[i+stationDisplayOffset].dest == STATION_DEST) then
- mon.setTextColor(colors.magenta)
- end
- mon.write(stations[i+stationDisplayOffset].name)
- end
- end
- end
- --Displays the list of trains at this station.
- function printTrains()
- print("Trains:")
- for i in pairs(tracks) do
- if (tracks[i].train ~= -1) then
- print(" Track: "..i.." Train: "..tracks[i].train)
- end
- end
- end
- --Saves the list of stations to a file.
- function saveStationList()
- local f = fs.open(STATION_FILE, "w")
- f.write(textutils.serialize(stations))
- f.close()
- end
- --Reads the stations list from a file.
- function loadStationList()
- if (not fs.exists(STATION_FILE)) then
- local f = fs.open(STATION_FILE, "w")
- f.write("{}")
- f.close()
- stations = {}
- requestStationList()
- else
- local f = fs.open(STATION_FILE, "r")
- stations = textutils.unserialize(f.readAll())
- f.close()
- end
- end
- --What to do if the server updates the stations list:
- function onStationListReceived(newStationList)
- stations = newStationList
- saveStationList()
- displayStations()
- print(" Received updated stations list.")
- end
- --Ask the server for a copy of the stations list.
- function requestStationList()
- rednet.send(SERVER_ID, STATION_LIST_RQ, STATION_LIST_PROT)
- print("Requested stations list.")
- end
- --Handles monitor touch events and what to do.
- function onMonitorTouch(x,y)
- --Check if the user clicked one of the arrows.
- if ((y < 4) and (x > mon_x-2)) then
- if (y == 2 and stationDisplayOffset > 0) then
- --Clicked up
- stationDisplayOffset = stationDisplayOffset - 1
- elseif (y == 3 and stationDisplayOffset < tableSize(stations)-1) then
- --Clicked down.
- stationDisplayOffset = stationDisplayOffset + 1
- end
- displayStations()
- elseif (y > 3) then
- --Clicked on a station.
- if (stations[y-3+stationDisplayOffset].dest ~= STATION_DEST) then
- sendRequest(stations[y-3+stationDisplayOffset].dest)
- end
- end
- end
- --Handles dispatch requests.
- function onDispatchRequestReceived(msg)
- mon.setCursorPos(19,3)
- mon.setTextColor(colors.lime)
- mon.setBackgroundColor(colors.white)
- for i in pairs(tracks) do
- if (tracks[i].train == msg[2]) then
- mon.write(tonumber(string.format("%." .. (0) .. "f", i)))
- note_block.setPitch(20)
- for k=1,i do
- note_block.triggerNote()
- os.sleep(0.4)
- end
- os.sleep(1)
- end
- end
- dispatchTrain(msg[1],msg[2])
- end
- --What to do after a train has been detected leaving.
- function onTrainDeparture(trackNumber)
- mon.setBackgroundColor(colors.white)
- mon.setCursorPos(19,3)
- mon.write(" ")
- tracks[trackNumber].train = -1
- end
- --Listens for events. Main event handler.
- function eventHandler()
- local event,p1,p2,p3,p4,p5 = os.pullEvent()
- if (event == "rednet_message") then
- if (p3 == METADATA_PROT and p2 == METADATA_RQ) then
- sendMetadata()
- sendUpdate()
- elseif (p3 == UPDATE_PROT and p2 == UPDATE_RQ) then
- sendUpdate()
- elseif (p3 == DISPATCH_PROT) then
- --Dispatch message: destination and train id
- onDispatchRequestReceived(p2)
- elseif (p3 == STATION_LIST_PROT) then
- --Update list of stations.
- onStationListReceived(p2)
- elseif (p3 == REBOOT_PROT and p2 == REBOOT_RQ) then
- os.reboot()
- end
- elseif (event == "redstone") then
- for i in pairs(tracks) do
- --Test if a train arrived.
- if (tracks[i].train == -1 and rs.testBundledInput(RedstoneSide, tracks[i].detectorColor)) then
- scanTrainAtTrack(i)
- sendUpdate()
- --Test if a train left.
- elseif (tracks[i].train ~= -1 and rs.testBundledInput(RedstoneSide, tracks[i].detectorColor) == false) then
- onTrainDeparture(i)
- end
- end
- elseif (event == "monitor_touch") then
- onMonitorTouch(p2,p3)
- end
- end
- --Main Loop:
- init()
- initMonitor()
- while (true) do
- eventHandler()
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement