Advertisement
April_The_Sergal

Untitled

Nov 22nd, 2024
9
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.41 KB | None | 0 0
  1. --- Farm Controller ---
  2. --- Updated by cdbab
  3. --- DateTime: 11/22/2024
  4.  
  5. local LOCAL_ID = "CONTROLLER"
  6. local PROTOCOL = "mobfarm"
  7. local nodes = {} -- List of registered nodes
  8. local buttonPage = 1
  9. local buttonsPerPage = 6
  10. local monitor = peripheral.wrap("right")
  11. rednet.open("back")
  12. rednet.host(PROTOCOL, LOCAL_ID)
  13.  
  14. -- Utility Functions
  15. local function generateMessageUID()
  16. local timestamp = os.epoch("utc")
  17. local randomValue = math.random(1000, 9999)
  18. return string.format("%d-%d-%d", os.getComputerID(), timestamp, randomValue)
  19. end
  20.  
  21. local function sendAndValidateCom(destID, packet, timeout, retries, uid_)
  22. local uid = generateMessageUID()
  23. if uid_ then uid = uid_ end
  24. packet.uid = uid
  25. local attempts = 0
  26.  
  27. repeat
  28. attempts = attempts + 1
  29. rednet.send(destID, packet, PROTOCOL)
  30. local id, message = rednet.receive(PROTOCOL, timeout)
  31.  
  32. if id == destID and message and message.uid == uid and message.data == "ack" then
  33. return true
  34. end
  35. until attempts >= retries
  36.  
  37. return false
  38. end
  39.  
  40. local function updateNodeList()
  41. -- Retrieve nodes via protocol lookup
  42. local discoveredNodes = { rednet.lookup(PROTOCOL) }
  43.  
  44. -- Add missing nodes with a handshake
  45. for _, nodeID in pairs(discoveredNodes) do
  46. local found = false
  47. for _, node in ipairs(nodes) do
  48. if node.id == nodeID then
  49. found = true
  50. break
  51. end
  52. end
  53. if not found then
  54. rednet.send(nodeID, { request = "handshake" }, PROTOCOL)
  55. end
  56. end
  57. end
  58.  
  59. local function formatHostname(hostname)
  60. -- Split the hostname by the underscore
  61. local parts = {}
  62. for part in string.gmatch(hostname, "([^_]+)") do
  63. table.insert(parts, part)
  64. end
  65.  
  66. -- Format the label as "Type Farm Number"
  67. if #parts == 2 then
  68. return parts[1] .. " Farm " .. parts[2]
  69. else
  70. return hostname -- Fallback in case of unexpected format
  71. end
  72. end
  73.  
  74. -- Monitor Rendering
  75. local function drawMonitor()
  76. monitor.clear()
  77. local width, height = monitor.getSize()
  78.  
  79. -- Storage Section
  80. local storageXStart = math.floor(width * 0.6)
  81. local barWidth = math.floor(width * 0.35)
  82. local barY = 2
  83. for i, node in ipairs(nodes) do
  84. local percent = node.storage or 0
  85. local barLength = math.floor(barWidth * (percent / 100))
  86. local barColor = colors.green
  87. if percent > 90 then barColor = colors.red
  88. elseif percent > 70 then barColor = colors.orange
  89. elseif percent > 50 then barColor = colors.yellow
  90. end
  91.  
  92. monitor.setCursorPos(storageXStart, barY)
  93. monitor.write(string.format("Storage %d: %d%%", i, percent))
  94. monitor.setCursorPos(storageXStart, barY + 1)
  95. monitor.setBackgroundColor(barColor)
  96. monitor.write(string.rep(" ", barLength))
  97. monitor.setBackgroundColor(colors.black)
  98. barY = barY + 3
  99. end
  100.  
  101. -- XP Section
  102. local xpStored = 0
  103. for _, node in ipairs(nodes) do
  104. if node.type == "XP" then xpStored = node.xp or 0 end
  105. end
  106. monitor.setCursorPos(storageXStart, barY)
  107. monitor.write(string.format("XP Stored: %d", xpStored))
  108.  
  109. -- Button Group Section
  110. local buttonXStart = 3
  111. local buttonWidth = math.floor((width * 0.4) / 2) - 2
  112. local buttonHeight = 3
  113. local pageStart = (buttonPage - 1) * buttonsPerPage + 1
  114. local pageEnd = math.min(pageStart + buttonsPerPage - 1, #nodes)
  115.  
  116. local y = 3
  117. for i = pageStart, pageEnd do
  118. local node = nodes[i]
  119. local buttonColor = node.status == "Running" and colors.red or colors.green
  120. monitor.setBackgroundColor(buttonColor)
  121. local x = ((i - pageStart) % 2 == 0) and buttonXStart + buttonWidth + 2 or buttonXStart
  122.  
  123. monitor.setCursorPos(x, y)
  124. monitor.write(" " .. node.label .. " ")
  125. monitor.setCursorPos(x, y + 1)
  126. monitor.write(" " .. node.status .. " ")
  127. monitor.setBackgroundColor(colors.black)
  128.  
  129. if i % 2 == 0 then y = y + buttonHeight + 1 end
  130. end
  131.  
  132. -- Pagination Section
  133. monitor.setCursorPos(2, height - 1)
  134. for i = 1, math.ceil(#nodes / buttonsPerPage) do
  135. local color = (i == buttonPage) and colors.green or colors.white
  136. monitor.setTextColor(color)
  137. monitor.write(tostring(i) .. " ")
  138. end
  139. monitor.setTextColor(colors.white)
  140.  
  141. -- Navigation Arrows
  142. monitor.setCursorPos(1, height - 1)
  143. monitor.setTextColor(buttonPage > 1 and colors.green or colors.gray)
  144. monitor.write("<")
  145.  
  146. monitor.setCursorPos(width, height - 1)
  147. monitor.setTextColor(buttonPage < math.ceil(#nodes / buttonsPerPage) and colors.green or colors.gray)
  148. monitor.write(">")
  149. monitor.setTextColor(colors.white)
  150. end
  151.  
  152. -- Button Handling
  153. local function handleButtonClick(x, y)
  154. -- Check if < or > is clicked
  155. local width, height = monitor.getSize()
  156. if y == height - 1 then
  157. if x == 1 and buttonPage > 1 then
  158. buttonPage = buttonPage - 1
  159. elseif x == width and buttonPage < math.ceil(#nodes / buttonsPerPage) then
  160. buttonPage = buttonPage + 1
  161. end
  162. drawMonitor()
  163. return
  164. end
  165.  
  166. -- Check button group
  167. local buttonXStart = 3
  168. local buttonWidth = math.floor((width * 0.4) / 2) - 2
  169. local buttonHeight = 3
  170. local pageStart = (buttonPage - 1) * buttonsPerPage + 1
  171. local pageEnd = math.min(pageStart + buttonsPerPage - 1, #nodes)
  172.  
  173. local yIndex = 3
  174. for i = pageStart, pageEnd do
  175. local xStart = ((i - pageStart) % 2 == 0) and buttonXStart + buttonWidth + 2 or buttonXStart
  176. if x >= xStart and x <= xStart + buttonWidth and y >= yIndex and y <= yIndex + buttonHeight then
  177. local node = nodes[i]
  178. rednet.send(node.id, { request = "toggle" }, PROTOCOL)
  179. return -- Exit after sending the toggle request
  180. end
  181. if i % 2 == 0 then yIndex = yIndex + buttonHeight + 1 end
  182. end
  183. end
  184.  
  185. -- Main Network Watcher
  186. local function networkWatcher()
  187. while true do
  188. local id, msg = rednet.receive(PROTOCOL)
  189. if type(msg) == "table" and id and msg.data == "init" then
  190. local packet = nil
  191. packet.data = "ack"
  192. sendAndValidateCom(id, packet, 5, 3, msg.uid)
  193. local exists = false
  194. for _, node in ipairs(nodes) do
  195. if node.hostName == msg.hostName then
  196. exists = true
  197. break
  198. end
  199. end
  200. if not exists then
  201. table.insert(nodes, { id = id, hostName = msg.hostName, status = "Stopped", type = msg.hostName:match("XP") and "XP" or "MOB", label = formatHostname(msg.hostName) })
  202. end
  203. elseif type(msg) == "table" and id and msg.data == "status" then
  204. for _, node in ipairs(nodes) do
  205. if node.id == id then
  206. node.status = msg.status
  207. node.storage = msg.storage
  208. node.xp = msg.xp
  209. end
  210. end
  211. end
  212. drawMonitor()
  213. end
  214. end
  215.  
  216. -- Initialize
  217. math.randomseed(os.time())
  218. updateNodeList()
  219. drawMonitor()
  220. parallel.waitForAll(networkWatcher, function()
  221. while true do
  222. local event, side, x, y = os.pullEvent("monitor_touch")
  223. handleButtonClick(x, y)
  224. end
  225. end)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement