Advertisement
gur111

central_server.lua

Jun 21st, 2025 (edited)
478
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 11.90 KB | None | 0 0
  1. -- pastebin ID: Qky674zS
  2. -- URL: https://pastebin.com/Qky674zS
  3.  
  4.  
  5. -- Central Server: GPS Host + Simple Mainframe Server
  6. -- Runs GPS host and a basic listening server in parallel
  7.  
  8. -- Default GPS coordinates (fallback if GPS not available)
  9. local DEFAULT_GPS_X = -401
  10. local DEFAULT_GPS_Y = 66
  11. local DEFAULT_GPS_Z = -1007
  12.  
  13. -- Actual GPS coordinates (will be determined at startup)
  14. local GPS_X, GPS_Y, GPS_Z
  15.  
  16. -- Turtle location tracking
  17. local turtleLocations = {}
  18. local LOCATIONS_FILE = "turtle_locations.json"
  19.  
  20. -- Precious block tracking
  21. local preciousReports = {}
  22. local PRECIOUS_FILE = "precious_reports.json"
  23.  
  24. -- Function to save turtle locations to disk
  25. local function saveLocations()
  26.     local file = fs.open(LOCATIONS_FILE, "w")
  27.     if file then
  28.         file.write(textutils.serialize(turtleLocations))
  29.         file.close()
  30.     end
  31. end
  32.  
  33. -- Function to load turtle locations from disk
  34. local function loadLocations()
  35.     if fs.exists(LOCATIONS_FILE) then
  36.         local file = fs.open(LOCATIONS_FILE, "r")
  37.         if file then
  38.             local data = file.readAll()
  39.             file.close()
  40.             if data and data ~= "" then
  41.                 turtleLocations = textutils.unserialize(data) or {}
  42.                 print("Mainframe: Loaded " .. #turtleLocations .. " turtle locations from disk")
  43.             end
  44.         end
  45.     end
  46. end
  47.  
  48. -- Function to save precious block reports to disk
  49. local function savePreciousReports()
  50.     local file = fs.open(PRECIOUS_FILE, "w")
  51.     if file then
  52.         file.write(textutils.serialize(preciousReports))
  53.         file.close()
  54.     end
  55. end
  56.  
  57. -- Function to load precious block reports from disk
  58. local function loadPreciousReports()
  59.     if fs.exists(PRECIOUS_FILE) then
  60.         local file = fs.open(PRECIOUS_FILE, "r")
  61.         if file then
  62.             local data = file.readAll()
  63.             file.close()
  64.             if data and data ~= "" then
  65.                 preciousReports = textutils.unserialize(data) or {}
  66.                 local totalReports = 0
  67.                 for turtleId, reports in pairs(preciousReports) do
  68.                     totalReports = totalReports + #reports
  69.                 end
  70.                 print("Mainframe: Loaded " .. totalReports .. " precious block reports from disk")
  71.             end
  72.         end
  73.     end
  74. end
  75.  
  76. -- Function to calculate 3D distance between two points
  77. local function calculateDistance(x1, y1, z1, x2, y2, z2)
  78.     return math.sqrt((x2 - x1)^2 + (y2 - y1)^2 + (z2 - z1)^2)
  79. end
  80.  
  81. -- Function to clean block name by removing everything before ':'
  82. local function cleanBlockName(blockName)
  83.     if not blockName then return "unknown" end
  84.     local colonPos = string.find(blockName, ":")
  85.     if colonPos then
  86.         return string.sub(blockName, colonPos + 1)
  87.     else
  88.         return blockName
  89.     end
  90. end
  91.  
  92. -- Function to open modem for the mainframe server
  93. local function openModem()
  94.     local sides = {"left", "right", "top", "bottom", "front", "back"}
  95.     for _, side in ipairs(sides) do
  96.         if peripheral.getType(side) == "modem" then
  97.             rednet.open(side)
  98.             print("Mainframe: Modem opened on " .. side)
  99.             return true
  100.         end
  101.     end
  102.     return false
  103. end
  104.  
  105. -- Function to determine GPS coordinates
  106. local function determineGPSCoordinates()
  107.     print("Central Server: Attempting to get GPS coordinates...")
  108.     local x, y, z = gps.locate(5) -- Wait up to 5 seconds for GPS fix
  109.  
  110.     if x and y and z then
  111.         GPS_X, GPS_Y, GPS_Z = x, y, z
  112.         print("Central Server: GPS coordinates obtained: (" .. GPS_X .. ", " .. GPS_Y .. ", " .. GPS_Z .. ")")
  113.     else
  114.         GPS_X, GPS_Y, GPS_Z = DEFAULT_GPS_X, DEFAULT_GPS_Y, DEFAULT_GPS_Z
  115.         print("Central Server: GPS not available, using default coordinates: (" .. GPS_X .. ", " .. GPS_Y .. ", " .. GPS_Z .. ")")
  116.     end
  117. end
  118.  
  119. -- GPS Host function
  120. local function runGPSHost()
  121.     print("GPS Host: Starting at coordinates (" .. GPS_X .. ", " .. GPS_Y .. ", " .. GPS_Z .. ")")
  122.     shell.run("gps", "host", GPS_X, GPS_Y, GPS_Z)
  123. end
  124.  
  125. -- Simple mainframe server function
  126. local function runMainframeServer()
  127.     if not openModem() then
  128.         print("Mainframe: No modem found!")
  129.         return
  130.     end
  131.  
  132.     -- Load existing location data and precious reports
  133.     loadLocations()
  134.     loadPreciousReports()
  135.     print("Mainframe: Listening for turtle reports...")
  136.  
  137.     while true do
  138.         local senderId, message = rednet.receive()
  139.         print("Mainframe: Received from turtle " .. senderId .. ": " .. tostring(message))
  140.  
  141.         -- Handle different message types
  142.         if message == "discover_mainframe" then
  143.             -- Respond to mainframe discovery broadcasts
  144.             rednet.send(senderId, "mainframe_here")
  145.             print("Mainframe: Responded to discovery request from " .. senderId)
  146.         elseif type(message) == "table" then
  147.             if message.type == "location" and message.x and message.y and message.z then
  148.                 -- Store turtle location
  149.                 turtleLocations[senderId] = {
  150.                     x = message.x,
  151.                     y = message.y,
  152.                     z = message.z,
  153.                     timestamp = os.date("%Y-%m-%d %H:%M:%S")
  154.                 }
  155.                 saveLocations() -- Persist to disk
  156.                 print("Mainframe: Updated location for turtle " .. senderId .. " to (" .. message.x .. ", " .. message.y .. ", " .. message.z .. ")")
  157.                 -- No acknowledgment sent back to turtle
  158.             elseif message.type == "precious" and message.blockName and message.x and message.y and message.z then
  159.                 -- Store precious block report (avoid duplicates)
  160.                 if not preciousReports[senderId] then
  161.                     preciousReports[senderId] = {}
  162.                 end
  163.  
  164.                 -- Check for duplicate report (same turtle, same block, within 2 blocks distance)
  165.                 local isDuplicate = false
  166.                 for _, report in ipairs(preciousReports[senderId]) do
  167.                     if report.blockName == message.blockName then
  168.                         local distance = calculateDistance(report.x, report.y, report.z, message.x, message.y, message.z)
  169.                         if distance < 2 then
  170.                             isDuplicate = true
  171.                             break
  172.                         end
  173.                     end
  174.                 end
  175.  
  176.                 if not isDuplicate then
  177.                     local cleanedBlockName = cleanBlockName(message.blockName)
  178.                     table.insert(preciousReports[senderId], {
  179.                         blockName = message.blockName, -- Store original for duplicate checking
  180.                         cleanedBlockName = cleanedBlockName, -- Store cleaned for display
  181.                         x = message.x,
  182.                         y = message.y,
  183.                         z = message.z,
  184.                         timestamp = os.date("%Y-%m-%d %H:%M:%S")
  185.                     })
  186.                     savePreciousReports() -- Persist to disk
  187.                     print("Mainframe: Precious block report from turtle " .. senderId .. ": " .. cleanedBlockName .. " at (" .. message.x .. ", " .. message.y .. ", " .. message.z .. ")")
  188.                     -- No acknowledgment sent back to turtle
  189.                 else
  190.                     -- Don't send acknowledgment for duplicate reports either
  191.                     print("Mainframe: Duplicate precious block report ignored from turtle " .. senderId)
  192.                 end
  193.             else
  194.                 -- Echo other table messages back
  195.                 rednet.send(senderId, "Echo: " .. textutils.serialize(message))
  196.             end
  197.         elseif message == "get_locations" then
  198.             -- Send back all turtle locations
  199.             rednet.send(senderId, turtleLocations)
  200.         elseif type(message) == "string" and (message == "get_precious" or message:match("^get_precious$") or message:match("^get_precious %-%-timestamp$")) then
  201.             -- Send back all precious block reports
  202.             local showTimestamp = string.find(message, "--timestamp") ~= nil
  203.  
  204.             local allFormattedReports = {}
  205.             for turtleId, reports in pairs(preciousReports) do
  206.                 local turtleReports = {}
  207.                 for _, report in ipairs(reports) do
  208.                     local displayName = report.cleanedBlockName or cleanBlockName(report.blockName)
  209.                     local reportStr = displayName .. " at (" .. report.x .. ", " .. report.y .. ", " .. report.z .. ")"
  210.                     if showTimestamp then
  211.                         reportStr = reportStr .. " [" .. report.timestamp .. "]"
  212.                     end
  213.                     table.insert(turtleReports, reportStr)
  214.                 end
  215.                 if #turtleReports > 0 then
  216.                     allFormattedReports["turtle_" .. turtleId] = turtleReports
  217.                 end
  218.             end
  219.             rednet.send(senderId, allFormattedReports)
  220.         elseif type(message) == "string" and message:match("^get_location ") then
  221.             -- Get location for specific turtle
  222.             local targetId = tonumber(message:match("get_location (%d+)"))
  223.             if targetId and turtleLocations[targetId] then
  224.                 rednet.send(senderId, turtleLocations[targetId])
  225.             else
  226.                 rednet.send(senderId, "Turtle not found or no location data")
  227.             end
  228.         elseif type(message) == "string" and message:match("^get_precious ") then
  229.             -- Get precious reports for specific turtle
  230.             local parts = {}
  231.             for part in message:gmatch("%S+") do
  232.                 table.insert(parts, part)
  233.             end
  234.  
  235.             local targetId = tonumber(parts[2])
  236.             local showTimestamp = false
  237.  
  238.             -- Check for --timestamp flag
  239.             for i = 3, #parts do
  240.                 if parts[i] == "--timestamp" then
  241.                     showTimestamp = true
  242.                     break
  243.                 end
  244.             end
  245.  
  246.             if targetId and preciousReports[targetId] then
  247.                 local formattedReports = {}
  248.                 for _, report in ipairs(preciousReports[targetId]) do
  249.                     local displayName = report.cleanedBlockName or cleanBlockName(report.blockName)
  250.                     local reportStr = displayName .. " at (" .. report.x .. ", " .. report.y .. ", " .. report.z .. ")"
  251.                     if showTimestamp then
  252.                         reportStr = reportStr .. " [" .. report.timestamp .. "]"
  253.                     end
  254.                     table.insert(formattedReports, reportStr)
  255.                 end
  256.                 rednet.send(senderId, formattedReports)
  257.             else
  258.                 rednet.send(senderId, "No precious block reports for turtle " .. (targetId or "unknown"))
  259.             end
  260.         elseif type(message) == "string" and message:match("^scrub_precious ") then
  261.             -- Clear precious reports for specific turtle
  262.             local targetId = tonumber(message:match("scrub_precious (%d+)"))
  263.             if targetId then
  264.                 local count = preciousReports[targetId] and #preciousReports[targetId] or 0
  265.                 preciousReports[targetId] = nil
  266.                 savePreciousReports()
  267.                 print("Mainframe: Scrubbed " .. count .. " precious block reports for turtle " .. targetId)
  268.                 rednet.send(senderId, "Scrubbed " .. count .. " precious block reports for turtle " .. targetId)
  269.             else
  270.                 rednet.send(senderId, "Invalid turtle ID for scrub command")
  271.             end
  272.         else
  273.             -- Echo the message back
  274.             rednet.send(senderId, "Echo: " .. tostring(message))
  275.         end
  276.     end
  277. end
  278.  
  279. -- Main execution
  280. print("=== Central Server Starting ===")
  281.  
  282. -- Determine GPS coordinates first
  283. determineGPSCoordinates()
  284.  
  285. print("Running GPS Host and Mainframe Server in parallel...")
  286.  
  287. -- Run both services in parallel
  288. parallel.waitForAll(runGPSHost, runMainframeServer)
  289.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement