diff --git a/src/minecartevents/apis/minecartevents b/src/minecartevents/modules/minecartevents.lua similarity index 72% rename from src/minecartevents/apis/minecartevents rename to src/minecartevents/modules/minecartevents.lua index db39f69..41dbe5c 100644 --- a/src/minecartevents/apis/minecartevents +++ b/src/minecartevents/modules/minecartevents.lua @@ -1,29 +1,32 @@ -os.loadAPI("apis/util") -os.loadAPI("apis/events") +local util = require("util") +local events = require("events") +local minecartevents = {} local eventHandlers = util.initializeGlobalTable("minecartEventHandlers") local lastMinecartEvent = util.initializeGlobalTable("lastMinecartEvent") -function registerMinecartHandler(handler) +function minecartevents.registerMinecartHandler(handler) eventHandlers["minecart"] = handler end -function handleMinecartEvent(eventName, detector, minecartType, minecartName, ...) +function minecartevents.handleMinecartEvent(eventName, detector, minecartType, minecartName, ...) local timestamp = os.clock() -- The entire point of this library is to eliminate the duplicate minecarts events that the digital detector sometimes fires. if lastMinecartEvent.minecartName == minecartName and lastMinecartEvent.minecartType == minecartType and (timestamp - lastMinecartEvent.timestamp) < 1 then return end - + -- Setting timers doesn't seem to work here (the timer event is never fired), so we use timestamps instead. lastMinecartEvent.minecartName = minecartName lastMinecartEvent.minecartType = minecartType lastMinecartEvent.timestamp = timestamp - + local handler = eventHandlers["minecart"] if handler ~= nil then return handler(eventName, detector, minecartType, minecartName, ...) end end -events.registerHandler("minecart", handleMinecartEvent) \ No newline at end of file +events.registerHandler("minecart", minecartevents.handleMinecartEvent) + +return minecartevents diff --git a/src/railnetwork/apis/railnetwork b/src/railnetwork/modules/railnetwork.lua similarity index 64% rename from src/railnetwork/apis/railnetwork rename to src/railnetwork/modules/railnetwork.lua index d614b8c..dabc084 100644 --- a/src/railnetwork/apis/railnetwork +++ b/src/railnetwork/modules/railnetwork.lua @@ -1,14 +1,16 @@ -os.loadAPI("apis/graph") +package.path = package.path .. ";/modules/?;/modules/?.lua;/modules/?/init.lua" +local graph = require("graph") +local railnetwork = {} -- TODO: Make this into an object with a metatable. -function formatLocation(location) +function railnetwork.railnetwork.formatLocation(location) if location then return string.format("%s@%i", location.line, location.position) end return "???" end -function parseLocation(text) +function railnetwork.parseLocation(text) local line, position = text:match("^(.+)@(.+)$") position = tonumber(position) if line ~= nil and position ~= nil then @@ -16,11 +18,11 @@ function parseLocation(text) end end -function locationsMatch(a, b) +function railnetwork.locationsMatch(a, b) return a.line == b.line and a.position == b.position end -function distanceBetween(a, b) +function railnetwork.distanceBetween(a, b) if a.line == b.line then return math.abs(a.position - b.position) end @@ -28,38 +30,38 @@ function distanceBetween(a, b) end local RailNetwork = {} -function RailNetwork:addNode(id, node) +function railnetwork.RailNetwork:addNode(id, node) self.nodes[id] = node self:clearGraph() end -function RailNetwork:removeNode(id) +function railnetwork.RailNetwork:removeNode(id) self.nodes[id] = nil self:clearGraph() end -function RailNetwork:addLine(id, line) +function railnetwork.RailNetwork:addLine(id, line) self.lines[id] = line self:clearGraph() end -function RailNetwork:removeLine(id) +function railnetwork.RailNetwork:removeLine(id) self.lines[id] = nil self:clearGraph() end -function RailNetwork:clearGraph() +function railnetwork.RailNetwork:clearGraph() self.graph = nil self.lineNodes = nil self.tags = nil end -function RailNetwork:buildGraph() +function railnetwork.RailNetwork:buildGraph() if self.graph then return end local lines = {} - local function establishNode(location, node) + function railnetwork.establishNode(location, node) local lineName = location.line local line = lines[lineName] if not line then @@ -68,36 +70,36 @@ function RailNetwork:buildGraph() end local existing = line[location.position] if node and existing and existing.edges then - error(string.format("Conflicting nodes defined at %s", formatLocation(location))) + error(string.format("Conflicting nodes defined at %s", railnetwork.railnetwork.formatLocation(location))) end line[location.position] = node or existing or {location = location} return line[location.position] end local allTags = {} - local function establishTags(tags) + function railnetwork.establishTags(tags) for tag in pairs(tags or {}) do allTags[tag] = true end end - for id, line in pairs(self.lines) do - establishTags(line.tags) + for _, line in pairs(self.lines) do + railnetwork.establishTags(line.tags) end - for id, node in pairs(self.nodes) do + for _, node in pairs(self.nodes) do node.edges = {} for _, connection in pairs(node.connections or {}) do - establishNode(connection.location) - establishTags(connection.tags) - connection.destination = formatLocation(connection.location) - connection.distance = connection.distance or distanceBetween(node.location, connection.location) + railnetwork.establishNode(connection.location) + railnetwork.establishTags(connection.tags) + connection.destination = railnetwork.railnetwork.formatLocation(connection.location) + connection.distance = connection.distance or railnetwork.distanceBetween(node.location, connection.location) if node.location.line == connection.location.line and self.lines[node.location.line] then connection.inheritedTags = self.lines[node.location.line].tags end table.insert(node.edges, connection) end - establishNode(node.location, node) + railnetwork.establishNode(node.location, node) end local graph = {} @@ -110,28 +112,28 @@ function RailNetwork:buildGraph() local sorted = {} local positions = {} locationsByLine[line] = positions - for position, node in pairs(lineNodes) do + for _, node in pairs(lineNodes) do table.insert(sorted, node) end - table.sort(sorted, function(a, b) + table.sort(sorted, function(a, b) return a.location.position < b.location.position end) for index, node in ipairs(sorted) do - graph[formatLocation(node.location)] = node + graph[railnetwork.railnetwork.formatLocation(node.location)] = node table.insert(positions, node.location) node.edges = node.edges or {} -- If direction is not set or is 0, we assume the line does not continue beyond this point. local direction = node.location.direction if direction and direction > 0 and index < #sorted then table.insert(node.edges, { - destination = formatLocation(sorted[index + 1].location), - distance = distanceBetween(node.location, sorted[index + 1].location), + destination = railnetwork.railnetwork.formatLocation(sorted[index + 1].location), + distance = railnetwork.distanceBetween(node.location, sorted[index + 1].location), inheritedTags = lineTags }) elseif direction and direction < 0 and index > 1 then table.insert(node.edges, { - destination = formatLocation(sorted[index - 1].location), - distance = distanceBetween(node.location, sorted[index - 1].location), + destination = railnetwork.railnetwork.formatLocation(sorted[index - 1].location), + distance = railnetwork.distanceBetween(node.location, sorted[index - 1].location), inheritedTags = lineTags }) end @@ -143,7 +145,7 @@ function RailNetwork:buildGraph() self.tags = allTags end -function RailNetwork:findClosestNode(location) +function railnetwork.RailNetwork:findClosestNode(location) if not location then return nil, "Location not specified" end @@ -154,7 +156,7 @@ function RailNetwork:findClosestNode(location) return nil, "Position not specified" end self:buildGraph() - if self.graph[formatLocation(location)] then + if self.graph[railnetwork.railnetwork.formatLocation(location)] then return location end local line = self.lineNodes[location.line] @@ -165,7 +167,7 @@ function RailNetwork:findClosestNode(location) if line[1].direction and line[1].direction < 0 then return line[1] else - return nil, string.format("Inaccessible location %s: first position %i on this line does not connect here", formatLocation(location), line[1].position) + return nil, string.format("Inaccessible location %s: first position %i on this line does not connect here", railnetwork.railnetwork.formatLocation(location), line[1].position) end end for index, lineLocation in ipairs(line) do @@ -181,7 +183,7 @@ function RailNetwork:findClosestNode(location) elseif nextLocation.direction and nextLocation.direction < 0 then return nextLocation else - return nil, string.format("Inaccessible location %s: neighboring positions %i and %i on this line do not connect here", formatLocation(location), lineLocation.position, nextLocation.position) + return nil, string.format("Inaccessible location %s: neighboring positions %i and %i on this line do not connect here", railnetwork.railnetwork.formatLocation(location), lineLocation.position, nextLocation.position) end end else @@ -189,23 +191,23 @@ function RailNetwork:findClosestNode(location) if lineLocation.direction and lineLocation.direction > 0 then return lineLocation else - return nil, string.format("Inaccessible location %s: last position %i on this line does not connect here", formatLocation(location), lineLocation.position) - end + return nil, string.format("Inaccessible location %s: last position %i on this line does not connect here", railnetwork.railnetwork.formatLocation(location), lineLocation.position) + end end end end end -function RailNetwork:findRoute(trip) +function railnetwork.RailNetwork:findRoute(trip) local originNode, originError = self:findClosestNode(trip.origin) if not originNode then - return nil, string.format("Unable to find rail network location for origin %s: %s", formatLocation(trip.origin), originError) + return nil, string.format("Unable to find rail network location for origin %s: %s", railnetwork.railnetwork.formatLocation(trip.origin), originError) end local destinationNode, destinationError = self:findClosestNode(trip.destination) if not destinationNode then - return nil, string.format("Unable to find rail network location for destination %s: %s", formatLocation(trip.destination), destinationError) + return nil, string.format("Unable to find rail network location for destination %s: %s", railnetwork.railnetwork.formatLocation(trip.destination), destinationError) end - local function edgeWeight(edge) + function railnetwork.edgeWeight(edge) local distance = edge.distance or 1 if trip.tags then local edgeTags = edge.tags or {} @@ -220,30 +222,30 @@ function RailNetwork:findRoute(trip) end return distance end - local path = graph.shortestPath(self.graph, {origin = formatLocation(originNode), destination = formatLocation(destinationNode)}, edgeWeight) + local path = graph.shortestPath(self.graph, {origin = railnetwork.formatLocation(originNode), destination = railnetwork.formatLocation(destinationNode)}, railnetwork.edgeWeight) if not path then - return nil, string.format("No path exists between origin %s and destination %s; did you misconfigure a switch or station?", formatLocation(originNode), formatLocation(destinationNode)) + return nil, string.format("No path exists between origin %s and destination %s; did you misconfigure a switch or station?", railnetwork.formatLocation(originNode), railnetwork.formatLocation(destinationNode)) end - if not locationsMatch(trip.origin, originNode) then + if not railnetwork.locationsMatch(trip.origin, originNode) then -- Add an edge for the segment between the origin and the first location in the network. - path.origin = formatLocation(trip.origin) + path.origin = railnetwork.formatLocation(trip.origin) table.insert(path.edges, 1, { - edge = {destination = formatLocation(originNode)}, + edge = {destination = railnetwork.formatLocation(originNode)}, weight = 1 }) end - if not locationsMatch(trip.destination, destinationNode) then + if not railnetwork.locationsMatch(trip.destination, destinationNode) then -- Add an edge for the segment between the last location in the network and the final destination. - path.destination = formatLocation(trip.destination) + path.destination = railnetwork.formatLocation(trip.destination) table.insert(path.edges, { - edge = {destination = formatLocation(trip.destination)}, + edge = {destination = railnetwork.formatLocation(trip.destination)}, weight = 1 }) end return path end -local function routeMatches(a, b) +function railnetwork._routeMatches(a, b) if #a.edges ~= #b.edges then return false end @@ -255,22 +257,22 @@ local function routeMatches(a, b) return true end -local function findMatchingRoute(routes, route) +function railnetwork.findMatchingRoute(routes, route) for key, existing in pairs(routes) do - if routeMatches(existing, route) then + if railnetwork._routeMatches(existing, route) then return key, existing end end end -function RailNetwork:findRoutes(trip, tagWeight) +function railnetwork.RailNetwork:findRoutes(trip, tagWeight) self:buildGraph() local routes = {} - local function addRoute(trip, tripTags) + function railnetwork.addRoute(trip, tripTags) trip.tags = tripTags - local route, routeError = self:findRoute(trip) + local route, routeError = self:findRoute(trip) -- TODO: Handle errors if route then - local key = findMatchingRoute(routes, route) + local key = railnetwork.findMatchingRoute(routes, route) if key then table.insert(key, tripTags) else @@ -280,10 +282,10 @@ function RailNetwork:findRoutes(trip, tagWeight) trip.tags = nil end - addRoute(trip, {}) + railnetwork.addRoute(trip, {}) tagWeight = tagWeight or 2 for tag in pairs(self.tags) do - addRoute(trip, {[tag] = tagWeight}) + railnetwork.addRoute(trip, {[tag] = tagWeight}) end return routes end @@ -292,6 +294,8 @@ local metatable = { __index = RailNetwork } -function new() +function railnetwork.new() return setmetatable({lines = {}, nodes = {}}, metatable) -end \ No newline at end of file +end + +return railnetwork diff --git a/src/railrouter/.manifest b/src/railrouter/.manifest index 4569ee2..ecd3f85 100644 --- a/src/railrouter/.manifest +++ b/src/railrouter/.manifest @@ -7,6 +7,7 @@ {name = "dns"}, {name = "serializer"}, {name = "railnetwork"}, - {name = "amber-autoupdater"} + {name = "amber-autoupdater"}, + [name = "startupmgr"}, } -} \ No newline at end of file +} diff --git a/src/railrouter/startup b/src/railrouter/modules/railrouter.lua similarity index 65% rename from src/railrouter/startup rename to src/railrouter/modules/railrouter.lua index 8fdec7a..4aa0616 100644 --- a/src/railrouter/startup +++ b/src/railrouter/modules/railrouter.lua @@ -1,12 +1,14 @@ -os.loadAPI("apis/log") -os.loadAPI("apis/events") -os.loadAPI("apis/net") -os.loadAPI("apis/dns") -os.loadAPI("apis/serializer") -os.loadAPI("apis/railnetwork") -os.loadAPI("apis/autoupdater") - -function getStationComputerId(station, feature) +package.path = package.path .. ";/modules/?;/modules/?.lua;/modules/?/init.lua" +local log = require("log") +local events = require("events") +local net = require("net") +local dns = require("dns") +local serializer = require("serializer") +local railnetwork = require("railnetwork") +local autoupdater = require("autoupdater") +local railrouter = {} + +function railrouter.getStationComputerId(station, feature) local station = stations[station] if station == nil then return nil @@ -18,9 +20,9 @@ function getStationComputerId(station, feature) return featureConfig.computerId end -function notifyNewRequest(request) +function railrouter.notifyNewRequest(request) print(string.format("Sending new %s request to station %i", request.class, request.source)) - local computerId = getStationComputerId(request.source, request.class) + local computerId = railrouter.getStationComputerId(request.source, request.class) if computerId == nil then log.err(string.format("Sending request to station %i but %s computer ID not found; discarding request", request.source, request.class)) return @@ -28,31 +30,31 @@ function notifyNewRequest(request) net.sendMessage(computerId, "newRequest", request) end -function mergeTables(a, b) +function railrouter.mergeTables(a, b) for key, value in pairs(b) do if a[key] == nil or type(a[key]) ~= "table" or type(value) ~= "table" then a[key] = value else - mergeTables(a[key], value) + railrouter.mergeTables(a[key], value) end end end -function updateStation(station) +function railrouter.updateStation(station) log.info(string.format("Updating station %i", station.stationId)) if stations[station.stationId] == nil then stations[station.stationId] = {} end - mergeTables(stations[station.stationId], station) - addStationToNetwork(station) - stationsChanged() + railrouter.mergeTables(stations[station.stationId], station) + railrouter.addStationToNetwork(station) + railrouter.stationsChanged() end -function stationsChanged() +function railrouter.stationsChanged() serializer.writeToFile("stations", stations) - + for id in pairs(stations) do - local computerId = getStationComputerId(id, "passenger") + local computerId = railrouter.getStationComputerId(id, "passenger") if computerId ~= nil then log.info(string.format("Sending station update to %i at station %i", computerId, id)) net.sendMessage(computerId, "stationUpdate", stations) @@ -60,20 +62,20 @@ function stationsChanged() end end -function sendStationList(args, sender) +function railrouter.sendStationList(_, sender) log.info(string.format("Sending station list to %i", sender)) net.sendMessage(sender, "stationUpdate", stations) end -function removeStation(station) +function railrouter.removeStation(station) log.info(string.format("Removing station %i", station.stationId)) stations[station.stationId] = nil - network:removeNode(getStationNode(station.stationId, false)) - network:removeNode(getStationNode(station.stationId, true)) - stationsChanged() + network:removeNode(railrouter.getStationNode(station.stationId, false)) + network:removeNode(railrouter.getStationNode(station.stationId, true)) + railrouter.stationsChanged() end -function validateTrip(trip) +function railrouter.validateTrip(trip) if trip.origin and trip.destination then local routes = network:findRoutes(trip) if next(routes) then @@ -86,10 +88,10 @@ function validateTrip(trip) return network:findClosestNode(trip.destination) end -function checkTrip(trip) +function railrouter.checkTrip(trip) log.info(string.format("New trip: %s at %s departing for %s", trip.type, railnetwork.formatLocation(trip.origin), railnetwork.formatLocation(trip.destination))) - - local result, tripError = validateTrip(trip) + + local result, tripError = railrouter.validateTrip(trip) if result then net.sendMessage(trip.computerId, "allowDeparture", trip) else @@ -99,22 +101,22 @@ function checkTrip(trip) end end -function registerTrip(trip) +function railrouter.registerTrip(trip) log.info(string.format("Departed: %s at %s in %s departing for %s", trip.type, railnetwork.formatLocation(trip.origin), trip.minecartName, railnetwork.formatLocation(trip.destination))) - + trips[trip.minecartName] = trip serializer.writeToFile("trips", trips) end -function minecartDetected(detection) +function railrouter.minecartDetected(detection) log.info(string.format("Minecart detected: %s at %s", detection.minecartName, railnetwork.formatLocation(detection.location))) - + local trip = trips[detection.minecartName] if trip == nil then log.warn(string.format("No trip active for %s; ignoring detection", detection.minecartName)) return end - + if railnetwork.locationsMatch(trip.destination, detection.location) then log.info(string.format("Trip to %s completed for %s", railnetwork.formatLocation(trip.destination), detection.minecartName)) trips[detection.minecartName] = nil @@ -124,7 +126,7 @@ function minecartDetected(detection) trip.lastKnownLocation = detection.location serializer.writeToFile("trips", trips) - + if detection.switchId == nil then -- There's nothing to do here if this location is not a switch. return @@ -141,33 +143,33 @@ function minecartDetected(detection) log.warn(string.format("Ignoring detection: %s", pathError)) return end - + local edge = path.edges[1] if edge == nil then log.warn(string.format("Ignoring detection: Path to destination %s is empty", railnetwork.formatLocation(trip.destination))) return end - + local switchState = edge.edge.switchState or false log.info(string.format("Setting switch %i to %s", detection.switchId, tostring(switchState))) net.sendMessage(switch.computerId, "setSwitch", {state = switchState}) end -function switchOnline(switch) +function railrouter.switchOnline(switch) log.info(string.format("Switch %i online", switch.id)) switches[switch.id] = switch serializer.writeToFile("switches", switches) - addSwitchToNetwork(switch) + railrouter.addSwitchToNetwork(switch) end -function switchOffline(switch) +function railrouter.switchOffline(switch) log.info(string.format("Switch %i offline", switch.id)) switches[switch.id] = nil serializer.writeToFile("switches", switches) - network:removeNode(getSwitchNode(switch.id)) + network:removeNode(railrouter.getSwitchNode(switch.id)) end -function getStationNode(id, departing) +function railrouter.getStationNode(id, departing) local nodeType = "arrive" if departing then nodeType = "depart" @@ -175,76 +177,76 @@ function getStationNode(id, departing) return string.format("S%i-%s", id, nodeType) end -function getSwitchNode(id) +function railrouter.getSwitchNode(id) return string.format("T%i", id) end -function getSwitchConnection(location, switchState) +function railrouter.getSwitchConnection(location, switchState) if location then return { location = location.location or location, -- For backwards compatibility with older switches switchState = switchState, distance = location.distance, - tags = location.tags + tags = location.tags, } end end -function addSwitchToNetwork(switch) +function railrouter.addSwitchToNetwork(switch) if switch.continuesTo and switch.location.direction then error(string.format("Switch %i defines both continuesTo and location.direction; drop one of these to resolve the conflict", switch.id)) end if not switch.divergesTo then error(string.format("Switch %i does not define divergesTo", switch.id)) end - network:addNode(getSwitchNode(switch.id), { + network:addNode(railrouter.getSwitchNode(switch.id), { location = switch.location, - connections = {getSwitchConnection(switch.divergesTo, true), getSwitchConnection(switch.continuesTo, false)} + connections = {railrouter.getSwitchConnection(switch.divergesTo, true), railrouter.getSwitchConnection(switch.continuesTo, false)}, }) end -function addStationToNetwork(station) +function railrouter.addStationToNetwork(station) if not station.features.passenger then return end if station.features.passenger.cartsIn then - network:addNode(getStationNode(station.stationId, false), {location = station.features.passenger.cartsIn.location}) + network:addNode(railrouter.getStationNode(station.stationId, false), {location = station.features.passenger.cartsIn.location}) end if station.features.passenger.cartsOut then - network:addNode(getStationNode(station.stationId, true), {location = station.features.passenger.cartsOut.location}) + network:addNode(railrouter.getStationNode(station.stationId, true), {location = station.features.passenger.cartsOut.location}) end end -function buildRailNetwork() +function railrouter.buildRailNetwork() network = railnetwork.new() for _, switch in pairs(switches) do - addSwitchToNetwork(switch) + railrouter.addSwitchToNetwork(switch) end for _, station in pairs(stations) do - addStationToNetwork(station) + railrouter.addStationToNetwork(station) end for id, line in pairs(lines) do network:addLine(id, line) end end -function onStartup() +function railrouter.onStartup() trips = serializer.readFromFile("trips") switches = serializer.readFromFile("switches") stations = serializer.readFromFile("stations") lines = serializer.readFromFile("lines") - buildRailNetwork() - net.registerMessageHandler("newRequest", notifyNewRequest) - net.registerMessageHandler("stationOnline", updateStation) - net.registerMessageHandler("stationOffline", removeStation) - net.registerMessageHandler("newTrip", checkTrip) - net.registerMessageHandler("tripDeparted", registerTrip) + railnetwork.buildRailNetwork() + net.registerMessageHandler("newRequest", railnetwork.notifyNewRequest) + net.registerMessageHandler("stationOnline", railnetwork.updateStation) + net.registerMessageHandler("stationOffline", railnetwork.removeStation) + net.registerMessageHandler("newTrip", railnetwork.checkTrip) + net.registerMessageHandler("tripDeparted", railnetwork.registerTrip) net.registerMessageHandler("minecartDetected", minecartDetected) - net.registerMessageHandler("switchOnline", switchOnline) - net.registerMessageHandler("switchOffline", switchOffline) - net.registerRawMessageHandler("getStations", sendStationList) + net.registerMessageHandler("switchOnline", railnetwork.switchOnline) + net.registerMessageHandler("switchOffline", railnetwork.switchOffline) + net.registerRawMessageHandler("getStations", railnetwork.sendStationList) autoupdater.initialize() - + dofile("config") log.info(string.format("RailRouterOS: Listening on %s...", net.openModem(config.modem))) dns.register("railrouter") @@ -252,4 +254,5 @@ function onStartup() events.runMessageLoop() end -onStartup() \ No newline at end of file +return railrouter + diff --git a/src/railrouter/startup.d/90-railrouter.lua b/src/railrouter/startup.d/90-railrouter.lua new file mode 100644 index 0000000..68b7fa1 --- /dev/null +++ b/src/railrouter/startup.d/90-railrouter.lua @@ -0,0 +1,4 @@ +package.path = package.path .. ";/modules/?;/modules/?.lua;/modules/?/init.lua" +local railrouter = require("railrouter") + +railrouter.onStartup() diff --git a/src/railstation/.manifest b/src/railstation/.manifest index 90d90d6..dd26e84 100644 --- a/src/railstation/.manifest +++ b/src/railstation/.manifest @@ -10,6 +10,7 @@ {name = "graph"}, {name = "railnetwork"}, {name = "autostartup"}, - {name = "amber-autoupdater"} + {name = "amber-autoupdater"}, + {name = "startupmgr"} } -} \ No newline at end of file +} diff --git a/src/railstation/startup b/src/railstation/modules/railstation.lua similarity index 71% rename from src/railstation/startup rename to src/railstation/modules/railstation.lua index bd5b5b9..7c4306b 100644 --- a/src/railstation/startup +++ b/src/railstation/modules/railstation.lua @@ -1,15 +1,17 @@ -os.loadAPI("apis/events") -os.loadAPI("apis/net") -os.loadAPI("apis/serializer") -os.loadAPI("apis/wire") -os.loadAPI("apis/minecartevents") -os.loadAPI("apis/input") -os.loadAPI("apis/graph") -os.loadAPI("apis/railnetwork") -os.loadAPI("apis/autostartup") -os.loadAPI("apis/autoupdater") +package.path = package.path .. ";/modules/?;/modules/?.lua;/modules/?/init.lua" +local events = require("events") +local net = require("net") +local serializer = require("serializer") +local wire = require("wire") +local minecartevents = require("minecartevents") +local input = require("input") +local graph = require("graph") +local railnetwork = require("railnetwork") +local autostartup = require("autostartup") +local autoupdater = require("autoupdater") +local railstation = {} -function requestDeparture(destination) +function railstation.requestDeparture(destination) local trip = { type = "passenger", computerId = os.computerID(), @@ -21,12 +23,12 @@ function requestDeparture(destination) net.sendMessage(config.router, "newTrip", trip) end -function rejectDeparture(trip) +function railstation.rejectDeparture(trip) print(string.format("Departure rejected: %s", trip.rejectionReason)) - delayedWriteHeader() + railstation.delayedWriteHeader() end -function formatTags(tags) +function railstation.formatTags(tags) local parts = {} for tag, enabled in pairs(tags) do local part = tag @@ -41,17 +43,17 @@ function formatTags(tags) return "normal" end -function formatRouteTags(tags) +function railstation.formatRouteTags(tags) local parts = {} for _, tags in ipairs(tags) do - table.insert(parts, formatTags(tags)) + table.insert(parts, railstation.formatTags(tags)) end return table.concat(parts, "; ") end -function selectDepartureRoute(trip) +function railstation.selectDepartureRoute(trip) if not trip.routes then - handleDeparture(trip) + railstation.handleDeparture(trip) return end local routeOptions = {} @@ -61,15 +63,15 @@ function selectDepartureRoute(trip) if #routeOptions == 1 then local key, route = next(trip.routes) print(string.format("Only one route to %s (%s); preparing departure: %s", - railnetwork.formatLocation(trip.destination), formatRouteTags(routeOptions[1]), graph.formatPath(route))) + railnetwork.formatLocation(trip.destination), railstation.formatRouteTags(routeOptions[1]), graph.formatPath(route))) trip.routes = nil - handleDeparture(trip) + railstation.handleDeparture(trip) return end local selected = input.menu({ prompt = "Select your route:", items = routeOptions, - formatter = formatRouteTags + formatter = railstation.formatRouteTags }) if not selected then return @@ -77,20 +79,20 @@ function selectDepartureRoute(trip) print(string.format("Preparing departure: %s", graph.formatPath(trip.routes[selected]))) trip.routes = nil trip.tags = selected[1] - handleDeparture(trip) + railstation.handleDeparture(trip) end -function handleDeparture(trip) +function railstation.handleDeparture(trip) if trip.type ~= "passenger" then print(string.format("ERROR: Unrecognized departure type %s; ignoring", trip.type)) return end - + if config.features.passenger.cartsOut.minecartName then trip.minecartName = config.features.passenger.cartsOut.minecartName net.sendMessage(config.router, "tripDeparted", trip) print(string.format("Please place your %s cart on the rails and take off now. Travel safely and have a great day!", trip.minecartName)) - delayedWriteHeader() + railstation.delayedWriteHeader() return end @@ -107,7 +109,7 @@ function handleDeparture(trip) pendingTrip = trip end -function writeHeader() +function railstation.writeHeader() term.clear() term.setCursorPos(1, 1) print(string.format("RailStationOS: Listening on %s...", config.modem)) @@ -119,7 +121,7 @@ function writeHeader() print("Press L to dispense liquid.") end -function getStationInput(prompt, filter) +function railstation.getStationInput(prompt, filter) while true do print("Enter " .. prompt .. " or 0 to cancel:") for i = 1, #stations do @@ -145,7 +147,7 @@ function getStationInput(prompt, filter) end end -function getNumericInput(prompt) +function railstation.getNumericInput(prompt) -- TODO: Use input.request instead here. while true do print("Enter " .. prompt .. " or 0 to cancel:") @@ -161,7 +163,7 @@ function getNumericInput(prompt) end end -function handleDepartureRequest() +function railstation.handleDepartureRequest() for _, station in ipairs(stations) do print(string.format("%i = %s", station.stationId, station.stationName)) end @@ -182,25 +184,25 @@ function handleDepartureRequest() invalidPrompt = "Invalid destination." }) if destination == nil then - writeHeader() + railstation.writeHeader() return end - - requestDeparture(destination) + + railstation.requestDeparture(destination) end -function handleLavaRequest() - local origin = getStationInput("the station to dispense the lava from", +function railstation.handleLavaRequest() + local origin = railstation.getStationInput("the station to dispense the lava from", function(station) - return stations[station].features.lava ~= nil and + return stations[station].features.lava ~= nil and stations[station].features.lava.cartsOut ~= nil end) if origin == nil then - writeHeader() + railstation.writeHeader() return end - - local destination = getStationInput("the station to deliver the lava to", + + local destination = railstation.getStationInput("the station to deliver the lava to", function(station) if station == origin then return false @@ -210,40 +212,40 @@ function handleLavaRequest() end end) if destination == nil then - writeHeader() + railstation.writeHeader() return end - - local count = getNumericInput("the number of tank carts to deliver") + + local count = railstation.getNumericInput("the number of tank carts to deliver") if count == nil then - writeHeader() + railstation.writeHeader() return end - + local request = { - class = "lava", + class = "lava", source = origin, - destination = destination, - requestType = "lava", + destination = destination, + requestType = "lava", count = count } net.sendMessage(config.router, "newRequest", request) - + print("Lava request sent. Have a great day!") - delayedWriteHeader() + railstation.delayedWriteHeader() end -function delayedWriteHeader() - events.setTimer(5, writeHeader) +function railstation.delayedWriteHeader() + events.setTimer(5, railstation.writeHeader) end -function handleStationUpdate(data) +function railstation.handleStationUpdate(data) stations = data serializer.writeToFile("stations", stations) print("Station list updated.") end -function minecartDetected(eventName, detector, minecartType, minecartName) +function railstation.minecartDetected(eventName, detector, minecartType, minecartName) if detector == config.features.passenger.cartsIn.detector then print(string.format("New arrival: %s", minecartName)) local msg = { @@ -266,23 +268,23 @@ function minecartDetected(eventName, detector, minecartType, minecartName) pendingTrip.minecartType = minecartType net.sendMessage(config.router, "tripDeparted", pendingTrip) pendingTrip = nil - - delayedWriteHeader() + + railstation.delayedWriteHeader() end end -function onStartup() +function railstation.onStartup() autoupdater.initialize() - net.registerMessageHandler("allowDeparture", selectDepartureRoute) - net.registerMessageHandler("rejectDeparture", rejectDeparture) - net.registerMessageHandler("stationUpdate", handleStationUpdate) + net.registerMessageHandler("allowDeparture", railstation.selectDepartureRoute) + net.registerMessageHandler("rejectDeparture", railstation.rejectDeparture) + net.registerMessageHandler("stationUpdate", railstation.handleStationUpdate) minecartevents.registerMinecartHandler(minecartDetected) events.registerHandler("char", function(evt, pressed) if pressed == "d" then - handleDepartureRequest() + railstation.handleDepartureRequest() end if pressed == "l" then - handleLavaRequest() + railstation.handleLavaRequest() end if pressed == "u" then autoupdater.updatePackages(true) @@ -294,8 +296,8 @@ function onStartup() config.modem = net.openModem(config.modem) stations = serializer.readFromFile("stations") - writeHeader() - + railstation.writeHeader() + autostartup.waitForDependencies({{type = "dns", address = config.router}}) if config.stationId == nil then print("Requesting station list...") @@ -304,8 +306,8 @@ function onStartup() net.sendMessage(config.router, "stationOnline", config) print(string.format("Station %i online", config.stationId)) end - + events.runMessageLoop() end -onStartup() \ No newline at end of file +return railstation diff --git a/src/railstation/startup.d/90-railstation.lua b/src/railstation/startup.d/90-railstation.lua new file mode 100644 index 0000000..6a5ca3c --- /dev/null +++ b/src/railstation/startup.d/90-railstation.lua @@ -0,0 +1,4 @@ +package.path = package.path .. ";/modules/?;/modules/?.lua;/modules/?/init.lua" +local railstation = require("railstation") + +railstation.onStartup() diff --git a/src/railswitch/.manifest b/src/railswitch/.manifest index 7e04b9b..c9cd89a 100644 --- a/src/railswitch/.manifest +++ b/src/railswitch/.manifest @@ -8,6 +8,7 @@ {name = "minecartevents"}, {name = "railnetwork"}, {name = "autostartup"}, - {name = "amber-autoupdater"} + {name = "amber-autoupdater"}, + {name = "startupmgr"} } -} \ No newline at end of file +} diff --git a/src/railswitch/startup b/src/railswitch/modules/railswitch.lua similarity index 64% rename from src/railswitch/startup rename to src/railswitch/modules/railswitch.lua index e0b6017..dd948e2 100644 --- a/src/railswitch/startup +++ b/src/railswitch/modules/railswitch.lua @@ -1,13 +1,15 @@ -os.loadAPI("apis/events") -os.loadAPI("apis/net") -os.loadAPI("apis/serializer") -os.loadAPI("apis/wire") -os.loadAPI("apis/minecartevents") -os.loadAPI("apis/railnetwork") -os.loadAPI("apis/autostartup") -os.loadAPI("apis/autoupdater") +package.path = package.path .. ";/modules/?;/modules/?.lua;/modules/?/init.lua" +local events = require("events") +local net = require("net") +local serializer = require("serializer") +local wire = require("wire") +local minecartevents = require("minecartevents") +local railnetwork = require("railnetwork") +local autostartup = require("autostartup") +local autoupdater = require("autoupdater") +local railswitch = {} -function setSwitchOutput(value) +function railswitch.setSwitchOutput(value) print(string.format("Setting switch to %s", tostring(value))) wire.setOutput(config.switch, value) if config.slowTrack ~= nil then @@ -15,14 +17,14 @@ function setSwitchOutput(value) end end -function setSwitch(update) +function railswitch.setSwitch(update) local value = update.state - setSwitchOutput(value) + railswitch.setSwitchOutput(value) state.switch = value serializer.writeToFile("state", state) end -function minecartDetected(eventName, detector, minecartType, minecartName) +function railswitch.minecartDetected(eventName, detector, minecartType, minecartName) print(string.format("Minecart detected: %s", minecartName)) local msg = { switchId = config.switchId, @@ -33,8 +35,8 @@ function minecartDetected(eventName, detector, minecartType, minecartName) net.sendMessage("railrouter://", "minecartDetected", msg) end -function onStartup() - net.registerMessageHandler("setSwitch", setSwitch) +function railswitch.onStartup() + net.registerMessageHandler("setSwitch", railswitch.setSwitch) events.registerHandler("char", function(evt, pressed) if pressed == "d" then net.sendMessage(config.router, "switchOffline", {id = config.switchId}) @@ -45,19 +47,19 @@ function onStartup() autoupdater.updatePackages(true) end end) - minecartevents.registerMinecartHandler(minecartDetected) + minecartevents.registerMinecartHandler(railswitch.minecartDetected) autoupdater.initialize() - + dofile("config") - print(string.format("RailSwitchOS: Switch %i (%s) listening on %s...", + print(string.format("RailSwitchOS: Switch %i (%s) listening on %s...", config.switchId, railnetwork.formatLocation(config.location), net.openModem(config.modem))) state = serializer.readFromFile("state") if state.switch == nil then state.switch = false end - setSwitchOutput(state.switch) - + railswitch.setSwitchOutput(state.switch) + autostartup.waitForDependencies({{type = "dns", address = config.router}}) net.sendMessage(config.router, "switchOnline", { id = config.switchId, @@ -67,8 +69,8 @@ function onStartup() divergesTo = config.divergesTo }) print(string.format("Switch %i online", config.switchId)) - + events.runMessageLoop() end -onStartup() \ No newline at end of file +return railswitch diff --git a/src/railswitch/startup.d/90-railswitch.lua b/src/railswitch/startup.d/90-railswitch.lua new file mode 100644 index 0000000..3329cae --- /dev/null +++ b/src/railswitch/startup.d/90-railswitch.lua @@ -0,0 +1,4 @@ +package.path = package.path .. ";/modules/?;/modules/?.lua;/modules/?/init.lua" +local railswitch = require("railswitch") + +railswitch.onStartup()