Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --==============================================================
- --
- -- Trystan Cannon
- -- Ports API for Lieu 10/1/12
- -- ccnet.ddns.me
- --
- -- This API allows for the opening and closing of virtual ports
- -- that act as buffers between incoming rednet messages.
- --==============================================================
- -- Opens all of the available ports in the port config file.
- function openAllPorts()
- local tPorts = loadPorts()
- for nPortIndex, tPortTable in ipairs(tPorts) do
- changePortStatus(tPortTable.nPort, true)
- end
- end
- -- Closes all of the available ports in the port config file.
- function closeAllPorts()
- local tPorts = loadPorts()
- for nPortIndex, tPortTable in ipairs(tPorts) do
- changePortStatus(tPortTable.nPort, false)
- end
- end
- -- Appends the status of a port, or adds a new port with the passed status to the config file.
- function changePortStatus(nPort, bOpen)
- -- Function borrowed from: http://lua-users.org/wiki/SplitJoin
- local function split(str, pat)
- local t = {} -- NOTE: use {n = 0} in Lua-5.0
- local fpat = "(.-)" .. pat
- local last_end = 1
- local s, e, cap = str:find(fpat, 1)
- while s do
- if s ~= 1 or cap ~= "" then
- table.insert(t,cap)
- end
- last_end = e+1
- s, e, cap = str:find(fpat, last_end)
- end
- if last_end <= #str then
- cap = str:sub(last_end)
- table.insert(t, cap)
- end
- return t
- end
- if not fs.isDir(".portConfig") then
- local sNewState = "" -- The new state of the port to be appended to the config file.
- if bOpen then
- sNewState = "open"
- else
- sNewState = "closed"
- end
- local tPorts = loadPorts()
- local nPortID_InTable = nil -- If the port already exists in the port table, this will be its index in the table.
- if #tPorts > 0 then
- nPortID_InTable = checkIfPortExists(nPort, tPorts)
- end
- -- Open the file, get its contents, then separate all of the lines in the file into a table.
- local portConfigFile = fs.open(".portConfig", "r")
- local sPortFileContents = portConfigFile.readAll()
- portConfigFile.close()
- local tLines = split(sPortFileContents, '\n')
- -- If the port already exists as an entry in the port table, open it via its current entry.
- if nPortID_InTable then
- -- Now that we have all of the lines split into a table, append our entry, then repackage the table into the file.
- local nColonPosition = tostring(nPort):len() + 1 -- This is the position of the colon in the entry.
- tLines[nPortID_InTable] = tLines[nPortID_InTable]:sub(1, nColonPosition) .. sNewState
- -- If the port does not already exist, then add it to the table and repackage the file.
- else
- tLines[#tLines+1] = nPort .. ":" .. sNewState
- end
- -- Repackage the table into the file.
- portConfigFile = fs.open(".portConfig", "w")
- for nLine = 1, #tLines do
- portConfigFile.writeLine(tLines[nLine])
- end
- portConfigFile.close()
- return true
- else
- error("Port config file cannot be a directory.")
- end
- end
- -- Checks if the passed port exists in the port table.
- -- IF it does, then it returns the index of the passed port in the port table.
- -- ELSE, then it returns nil.
- function checkIfPortExists(nPort, tPorts)
- for nPortIndex, tPortTable in ipairs(tPorts) do
- if tPortTable.nPort == nPort then
- return nPortIndex
- end
- end
- return nil
- end
- -- Checks if the passed port is open in the most recently loaded ports table.
- -- IF the port is open, returns true.
- -- IF the port is not open OR the port doesn't exist, returns false.
- function checkIfPortIsOpen(nPort, tPorts)
- for nPortIndex, tPortTable in ipairs(tPorts) do
- if tPortTable.nPort == nPort then
- if tPortTable.bOpen then
- return true
- else
- return false
- end
- end
- end
- return false
- end
- -- Loads the ports and their states from the config file located at:
- -- /.portConfig
- -- RETURNS:
- -- A table containing the numbers and states of each port formatted as such:
- -- tPorts[n] = {nPort (number), bOpen (boolean)}
- function loadPorts()
- -- Entries in the port config file should be formatted as such:
- -- portNumber:open/closed
- if fs.exists(".portConfig") and not fs.isDir(".portConfig") then
- -- Get the number of entries in the port config file (the number of lines).
- local portConfigFile = io.open(".portConfig", "r")
- local nLines = 0
- for sLine in portConfigFile:lines() do
- nLines = nLines + 1
- end
- portConfigFile:close()
- -- Now, read all of the lines and parse them into a table.
- -- tPorts[n] = {nPort (number), bOpen (boolean)}
- local tPorts = {}
- portConfigFile = fs.open(".portConfig", "r")
- local sCurrentEntry = "" -- The current entry, or line, being read from the config file.
- local nStatePosition = 0 -- The position of the first number after the colon of the current entry in the string.
- local nCurrentEntry_Port = 0 -- The port number of the current entry.
- local bCurrentEntry_Open = false -- Whether or not the current entry is to be set as open or closed.
- for nLine = 1, nLines do
- -- Read the line out of the config file, then parse it.
- sCurrentEntry = portConfigFile.readLine()
- -- The line should be formatted: portNumber:open/closed.
- -- Get the position of the psotion of the first character after the colon; this should be the position
- -- of the first character of the state of this port.
- nStatePosition = sCurrentEntry:find(":") + 1 -- Add one to the numnber returned so it is one AFTER the colon's position.
- -- Now that we have the position of the state, read the port number and the state of the entry with
- -- a conditional to monitor the boolean value entered into the table.
- nCurrentEntry_Port = tonumber(sCurrentEntry:sub(1, nStatePosition - 2)) -- Get a substring from two BEFORE the position
- -- of the first character of the state to compensate
- -- for the colon.
- bCurrentEntry_Open = sCurrentEntry:sub(nStatePosition, sCurrentEntry:len()) -- Get the state as "open" or "closed" and then
- -- check for the final value using a conditional.
- -- If the current entry's state was "open", then set the boolean value to true.
- if bCurrentEntry_Open == "open" then
- bCurrentEntry_Open = true
- -- If the current entry's state was anything other than "open", then set the boolean value to false.
- else
- bCurrentEntry_Open = false
- end
- -- Finally, insert the newly read and parsed entry into the table.
- table.insert(tPorts, {nPort = nCurrentEntry_Port, bOpen = bCurrentEntry_Open})
- end
- -- Now that all of the ports have been read from the config file, go ahead and return the port table to the calling method.
- portConfigFile.close()
- return tPorts
- else
- return {}
- end
- end
- -- Finds and opens an exsistant modem;
- -- opens the modem if one is found: returns true
- -- returns false if there was no modem found.
- function openExistantModem()
- local tSides = rs.getSides()
- for nSideIndex, sSide in ipairs(tSides) do
- if peripheral.isPresent(sSide) and peripheral.getType(sSide) == "modem" then
- rednet.open(sSide)
- return true
- end
- end
- -- If no modem was found; the loop executed without returning, report
- -- a lock of a modem, and therefore an error.
- return false
- end
- --=NETWORKING METHODS=========================================--
- -- Uses redent.receive to wait for a message. If a message is received then
- -- check if the message contains the port number in the first line.
- -- If this method was called to listen for activity on port 5, then it would
- -- look like this:
- -- Message sent: 5:Super awesome port API you got here, Trystan!
- -- The message would be parsed to the first digit: 5. Then, since the check passes,
- -- the message is parsed into this: Super awesome port API you got here, Trystan!
- -- THIS ONLY OCCURS IF THE PORT IS OPEN!!!
- function receiveOnPort(nPort, nTimeOut)
- local nSender, sMessage = rednet.receive(nTimeOut)
- if checkIfPortIsOpen(nPort, loadPorts()) then
- if sMessage:sub(1, tostring(nPort):len()) == tostring(nPort) then
- return nSender, sMessage:sub(tostring(nPort):len() + 2, sMessage:len()) -- Plus two to compensate for the colon.
- else
- return nil, nil
- end
- else
- return nil, nil
- end
- end
- -- Sends a message to the receiver on the the given port.
- -- Does this by concatenating the port with a colon to the message, then
- -- sending that newly formed string as a message to the tonumber(receiver).
- function sendToPort(nReceiver, nPort, sMessage)
- rednet.send(tonumber(nReceiver), nPort .. ":" .. sMessage)
- end
- --============================================================--
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement