Advertisement
April_The_Sergal

Controller

Nov 23rd, 2024 (edited)
193
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 9.05 KB | None | 0 0
  1. -- Controller Script
  2.  
  3. -- Variables
  4. local PROTOCOL = "mobFarm"
  5. local LOCAL_ID = "controller"
  6. -- Mapping between hostName and computerID
  7. local nodeIDs = {}
  8.  
  9. -- Peripherals
  10. peripheral.find("modem", rednet.open)
  11. local monitor = peripheral.find("monitor")
  12.  
  13. -- Host controller as 'controller' on network
  14. rednet.host(PROTOCOL, LOCAL_ID)
  15.  
  16. if not monitor then
  17.     error("Monitor not found!")
  18. end
  19.  
  20. if not rednet.isOpen() then
  21.     error("Rednet is not open! Check the modem.")
  22. end
  23.  
  24. -- Configuration
  25. monitor.setTextScale(0.5)
  26. monitor.clear()
  27. local itemsPerPage = 6
  28. local nodes = {}
  29. local messageBuffer = {}
  30. local currentPage = 1
  31.  
  32. -- Utility Functions
  33. -- Updated addNode Function
  34. local function addNode(hostName, computerID)
  35.     if not nodes[hostName] then
  36.         nodes[hostName] = {
  37.             type = hostName:match("^(%a+)_"),
  38.             id = tonumber(hostName:match("_(%d+)$")),
  39.             status = "UNKNOWN",
  40.         }
  41.         nodeIDs[hostName] = computerID -- Map hostName to computerID
  42.     end
  43. end
  44.  
  45. local function getNodeLabel(hostName)
  46.     local node = nodes[hostName]
  47.     return string.format("%s FARM %d", node.type, node.id)
  48. end
  49.  
  50. -- UI Functions
  51. local function countTableItems(tbl)
  52.     local count = 0
  53.     for _ in pairs(tbl) do
  54.         count = count + 1
  55.     end
  56.     return count
  57. end
  58.  
  59. local function drawButtons()
  60.     monitor.clear() -- Clear the monitor before drawing
  61.     monitor.setCursorPos(1, 1)
  62.     monitor.write("Mob Farm Controller")
  63.  
  64.     local nodeCount = countTableItems(nodes) -- Count nodes manually
  65.  
  66.     if nodeCount == 0 then
  67.         -- If no nodes exist, display a message
  68.         monitor.setCursorPos(2, 3)
  69.         monitor.write("No nodes available")
  70.         monitor.setCursorPos(2, 5)
  71.         monitor.write("Waiting for nodes...")
  72.         return
  73.     end
  74.  
  75.     local x, y = 2, 2
  76.     local startIndex = (currentPage - 1) * itemsPerPage + 1
  77.     local endIndex = math.min(startIndex + itemsPerPage - 1, nodeCount)
  78.  
  79.     --print("startIndex:", startIndex, "endIndex:", endIndex) -- Debug output
  80.  
  81.     local nodeIndex = 1
  82.     for hostName, _ in pairs(nodes) do
  83.         if nodeIndex >= startIndex and nodeIndex <= endIndex then
  84.             local label = getNodeLabel(hostName)
  85.             local status = nodes[hostName].status or "UNKNOWN"
  86.             local color = (status == "RUNNING") and colors.red or colors.green
  87.  
  88.             -- Format the label and status with blit
  89.             local labelText = label .. " (" .. status .. ")"
  90.             local textLength = #labelText
  91.             local foreground = string.rep(colors.toBlit(colors.white), textLength) -- Foreground is white
  92.             local background = string.rep(colors.toBlit(color), textLength)       -- Background based on node status
  93.  
  94.             monitor.setCursorPos(x, y)
  95.             monitor.blit(labelText, foreground, background) -- Write text with foreground and background
  96.  
  97.             y = y + 2 -- Move to the next line
  98.             if y > 15 then
  99.                 x = x + 14
  100.                 y = 2
  101.             end
  102.         end
  103.         nodeIndex = nodeIndex + 1
  104.     end
  105.  
  106.     -- Pagination
  107.     local totalPages = math.ceil(nodeCount / itemsPerPage)
  108.     monitor.setCursorPos(2, 18)
  109.     monitor.write("Page " .. currentPage .. " of " .. totalPages)
  110. end
  111.  
  112. -- Network Functions
  113. -- Discover Nodes (Updated to Pass computerID to addNode)
  114. local function discoverNodes()
  115.     print("Discovering nodes...")
  116.     local computers = {rednet.lookup(PROTOCOL)} -- Get IDs of computers hosting the protocol
  117.     print("Discovered computers:", textutils.serialize(computers)) -- Debug log
  118.  
  119.     if #computers == 0 then
  120.         print("No nodes discovered, awaiting contact from nodes as they come online")
  121.     else
  122.         for _, computerID in pairs(computers) do
  123.             if computerID ~= os.getComputerID() then
  124.                 print("Requesting CLIENT_ID from computer ID: " .. computerID)
  125.                 rednet.send(computerID, { type = "requestId", controllerId = LOCAL_ID }, PROTOCOL)
  126.  
  127.                 local senderId, response = rednet.receive(PROTOCOL, 3) -- 3-second timeout
  128.                 print("Response received:", textutils.serialize(response)) -- Debug log
  129.  
  130.                 if senderId == computerID and response and response.type == "responseId" then
  131.                     local clientId = response.CLIENT_ID -- Read CLIENT_ID from the response
  132.                     print("Received CLIENT_ID: " .. clientId .. " from computer ID: " .. computerID)
  133.                     addNode(clientId, computerID) -- Use CLIENT_ID and computerID in addNode
  134.                     drawButtons() -- Trigger UI update after adding the node
  135.                 else
  136.                     print("No response or invalid response from computer ID: " .. computerID)
  137.                 end
  138.             end
  139.         end
  140.     end
  141. end
  142.  
  143. -- Request Status Update Function
  144. local function requestStatusUpdates()
  145.     while true do
  146.         for hostName, node in pairs(nodes) do
  147.             if node.status == "UNKNOWN" then
  148.                 local computerID = nodeIDs[hostName]
  149.                 if computerID then
  150.                     print("Requesting status update from node: " .. hostName)
  151.                     rednet.send(computerID, { type = "requestStatus" }, PROTOCOL)
  152.                 else
  153.                     print("No computer ID found for node: " .. hostName)
  154.                 end
  155.             end
  156.         end
  157.         sleep(5) -- Wait 5 seconds before rechecking
  158.     end
  159. end
  160.  
  161. -- Handle Incoming Messages (Modified to process status responses)
  162. local function handleIncomingMessage()
  163.     while true do
  164.         local senderId, message = rednet.receive(PROTOCOL)
  165.         table.insert(messageBuffer, { senderId = senderId, message = message })
  166.  
  167.         if message.type == "status" then
  168.             local hostName = message.hostName
  169.             if nodes[hostName] then
  170.                 nodes[hostName].status = message.status
  171.                 print("Updated status for node: " .. hostName .. " to " .. message.status)
  172.             end
  173.         elseif message.type == "handshake" then
  174.             addNode(message.hostName)
  175.             print("Added node: " .. message.hostName)
  176.         elseif message.type == "storageUpdate" then
  177.             nodes[message.hostName].storage = message.storage
  178.         end
  179.     end
  180. end
  181.  
  182. local function toggleNode(hostName)
  183.     if not nodes[hostName] then return end
  184.  
  185.     local currentStatus = nodes[hostName].status
  186.     local newStatus = (currentStatus == "RUNNING") and "STOPPED" or "RUNNING"
  187.  
  188.     local computerID = nodeIDs[hostName]  -- Get the computerID for the node
  189.     print(computerID)
  190.     if not computerID then
  191.         print("No computer ID found for node: " .. hostName)
  192.         return
  193.     end
  194.  
  195.     -- Send the toggle message to the computerID
  196.     rednet.send(computerID, { type = "toggle" }, PROTOCOL)
  197.     nodes[hostName].status = "PENDING"  -- Update the status to "PENDING"
  198. end
  199.  
  200. -- Function to check for mouse click
  201. local function handleMouseClick()
  202.     while true do
  203.         local event, button, x, y = os.pullEvent("monitor_touch")  -- This waits for a mouse click
  204.        
  205.         if event then
  206.             print("Monitor clicked")
  207.         end
  208.  
  209.         -- Check if the click is within the bounds of the buttons
  210.         if x >= 2 and x <= 17 and y >= 2 and y <= 15 then
  211.             -- Calculate startIndex and endIndex
  212.             local nodeCount = countTableItems(nodes) -- Count nodes manually
  213.             local startIndex = (currentPage - 1) * itemsPerPage + 1
  214.             local endIndex = math.min(startIndex + itemsPerPage - 1, nodeCount)
  215.  
  216.             local nodeIndex = 1
  217.             local clickedNode = nil
  218.  
  219.             -- Calculate which button was clicked based on x and y positions
  220.             for hostName, _ in pairs(nodes) do
  221.                 if nodeIndex >= startIndex and nodeIndex <= endIndex then
  222.                     local label = getNodeLabel(hostName)
  223.                     local labelLength = #label + 12 -- Button width (to ensure coverage of full text)
  224.  
  225.                     -- Check if the click is inside the button area (simple check based on the x/y position)
  226.                     if x >= 2 and x <= labelLength and y >= (2 + (nodeIndex - 1) * 2) and y <= (2 + nodeIndex * 2) then
  227.                         clickedNode = hostName
  228.                         break
  229.                     end
  230.                 end
  231.                 nodeIndex = nodeIndex + 1
  232.             end
  233.  
  234.             -- If a node was clicked, toggle it
  235.             if clickedNode then
  236.                 print("Node clicked: " .. clickedNode)
  237.                 toggleNode(clickedNode)
  238.                 drawButtons()  -- Redraw the buttons after toggling
  239.             end
  240.         end
  241.     end
  242. end
  243.  
  244. -- Main Loop
  245. discoverNodes()
  246. parallel.waitForAll(
  247.         handleIncomingMessage,
  248.         requestStatusUpdates,
  249.         handleMouseClick,   -- This listens for mouse clicks and handles them
  250.         function()
  251.             while true do
  252.                 drawButtons()  -- Periodically update the monitor
  253.                 sleep(1)       -- Redraw the monitor every second
  254.             end
  255.         end
  256. )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement