Advertisement
horsemeat

ComputerCraft Redstone Master

Dec 22nd, 2016
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 26.53 KB | None | 0 0
  1. --Computer Craft Master Application for redstone interfacing
  2. --By snipy67
  3. --V1.1
  4. --You will need the Node Application at http://pastebin.com/3sGZ4dB3
  5. --You will need the Router Application in server mode running on the network http://pastebin.com/BuRcCc2n
  6. MONITOR_SIDE = "top"
  7. NODES = {"node0","node1","node2","node3","node4","node5"}
  8. NODES_NAME = {"Node 1","Node 2","Node  3","Node 4","Node 5", "Node 6"}
  9. BUTTON_SIZE_X = 8
  10. BUTTON_SIZE_Y = 4
  11. nodeState = {}
  12. nodePort = {}
  13. nodeSendPort = {}
  14. nodeButtons = {}
  15.  
  16. conPort = {}
  17.  
  18. buttons = {}
  19. buttonsPressed = {}
  20. buttonsPosition = {}
  21. buttonsFunc = {}
  22. drawLinesData = {}
  23. --Computer Craft Router Application
  24. --By snipy67
  25. --V1.0
  26. MASTER_PORT = 1
  27. BROADCAST_PORT = 2
  28.  
  29. --Layer 1
  30. lowLevelListeners = {}
  31. routerComputerId = 0
  32.  
  33. function detectModem()
  34.     return peripheral.find("modem")
  35. end
  36. function lowLevelMessageSplit(message)
  37.     local tab = {}
  38.     local current = ""
  39.     for i = 1, #message, 1 do
  40.         if message:sub(i,i) == ':' then
  41.             table.insert(tab,current)
  42.             current = ""
  43.         else
  44.             current = current .. message:sub(i,i)
  45.         end
  46.     end
  47.     if #current > 0 then
  48.         table.insert(tab,current)
  49.     end
  50.     return tab
  51. end
  52.  
  53. function lowLevelListenerCheckForMethod(modem,port,tab,verbose)
  54.     for k, v in pairs(lowLevelListeners) do
  55.         if v.message == tab[1] then
  56.             if verbose then
  57.                 print("function " .. v.message .. "found")
  58.             end
  59.             if v.func ~= nil then
  60.                 local t = {}
  61.                 t.message = tab[1]
  62.                 t.senderId = tab[2]
  63.                 t.reciverId = tab[3]
  64.                 t.data = tab[4]
  65.                 v.func(t)
  66.                 if t.data ~= nil then
  67.                     local responseText = tab[1] .. "~response:" .. os.getComputerID() .. ":".. tab[2] .. ":".. t.data;
  68.                     modem.transmit(port,port,responseText)
  69.                 else
  70.                     local responseText = tab[1] .. "~response:" .. os.getComputerID() .. ":".. tab[2]
  71.                     modem.transmit(port,port,responseText)
  72.                 end
  73.             else
  74.                 local responseText = tab[1] .. "~response:" .. os.getComputerID() .. ":".. tab[2]
  75.                 modem.transmit(port,port,responseText)
  76.             end
  77.             return true
  78.         else
  79.             if verbose then
  80.                 print("v.message:" .. v.message .. " != tab[1]:"..tab[1])
  81.             end
  82.         end
  83.     end
  84.     return false
  85. end
  86.  
  87. function lowLevelListener(modem,port,verbose)
  88.     while true do
  89.         local event, modemSide, senderChannel, replyChannel, message, senderDistance = os.pullEvent()--listens for a actions
  90.         if event == "modem_message" then--gets the message
  91.             if senderChannel == port then
  92.                 if verbose then
  93.                     print("message recived: " .. message)
  94.                 end
  95.                 local tab = lowLevelMessageSplit(message)
  96.                 if #tab > 2 then
  97.                     if verbose then
  98.                         print("There is more then 2 arguments in the message")
  99.                     end
  100.                     if tonumber(tab[3]) == os.getComputerID() then
  101.                         if verbose then
  102.                             print("id matches")
  103.                         end
  104.                         lowLevelListenerCheckForMethod(modem,port,tab,verbose)
  105.                     elseif tonumber(tab[3]) == -1 then
  106.                         if verbose then
  107.                             print("broadcast")
  108.                         end
  109.                         lowLevelListenerCheckForMethod(modem,port,tab,verbose)
  110.                     end
  111.                 elseif #tab == 2 then
  112.                     lowLevelListenerCheckForMethod(modem,port,tab,verbose)
  113.                 end
  114.             end
  115.         end
  116.     end
  117. end
  118.  
  119. function lowLevelRequest(modem,request,port,maxTimeOut,timeBetweenResend,numberOfResendsBeforeTimeOut,id,data,verbose)
  120.     local str = ""
  121.     if id ~= nil and id ~= -1 then
  122.         str = request .. ":" .. os.getComputerID() .. ":" .. id -- adds the computer id and the id of the reciver
  123.     else
  124.         str = request .. ":" .. os.getComputerID() .. ":" .. -1-- adds the computer id to the requests
  125.     end
  126.    
  127.     if data ~= nil then
  128.         str = str .. ":" .. data
  129.     end
  130.    
  131.     modem.transmit(port,port,str);--transmits the request
  132.     local responseText = request .. "~response"--creates text on how a response will look like
  133.     local count = 0--count is to keep track of how many times the request timed out
  134.     local timer = -1
  135.     if timeBetweenResend > 0 and numberOfResendsBeforeTimeOut > 0 then
  136.         timer = os.startTimer(timeBetweenResend) -- to keep track of the number of seconds before a time out
  137.     end
  138.     local atLeastOne = false--this determines if atleast one computer recived the request
  139.     local timeOutTimer
  140.     if maxTimeOut > 0 then
  141.         timeOutTimer = os.startTimer(maxTimeOut)--this timer is the number of seconds it should wait for return requests
  142.     end
  143.     local all = {} -- this is all the data that will be returned
  144.     all.package = {}--this is where the data from each request is stored
  145.     while true do
  146.         local event, modemSide, senderChannel, replyChannel, message, senderDistance = os.pullEvent()--listens for a actions
  147.         if event == "timer" then--check if the timer is up
  148.             local timerId = modemSide; --modemSide is the timerid when timer event is called (prevents confusion)
  149.             if timerId == timer then--checks if the timer is the timer that handels resends
  150.                 if atLeastOne == false then--checks if there are no records recovered
  151.                     if count ~= numberOfResendsBeforeTimeOut then--check to make sure the count is not at the timeout stage
  152.                         modem.transmit(port,port,str);--transmits the request again
  153.                         count = count + 1 -- adds one to the #of time outs
  154.                         timer = os.startTimer(timeBetweenResend)--resets the timer
  155.                         if verbose then
  156.                             print("Message Transmission failed resending...")
  157.                         end
  158.                     else
  159.                         if verbose then
  160.                             print("Message Transmission failed")
  161.                         end
  162.                         all.sucess = false
  163.                         return all
  164.                     end
  165.                 end
  166.             elseif timerId == timeOutTimer then--this is the maximum amount of time it was going to wait and not it's going to return the data
  167.                 if atLeastone == false then
  168.                     all.sucess = false
  169.                 else
  170.                     all.sucess = true
  171.                 end
  172.                 return all
  173.             end
  174.         elseif event == "modem_message" then--gets the message
  175.             if senderChannel == port then
  176.                 local tab = lowLevelMessageSplit(message)
  177.                 if verbose then
  178.                     print("Modem message: " .. message)
  179.                 end
  180.                 if tab[1] == responseText then
  181.                     if tonumber(tab[3]) == os.getComputerID() then
  182.                         local p = {}
  183.                         p.sucess = true
  184.                         p.tab = tab
  185.                         atLeastOne = true
  186.                         table.insert(all.package,p)
  187.                         if verbose then
  188.                             print("This computer: " .. tab[3] .. ". Request response recived from " .. tab[2])
  189.                         end
  190.                         if timeOutTimer == -1 then
  191.                             all.sucess = true
  192.                             return all;
  193.                         end
  194.                     end
  195.                 end
  196.             end
  197.         end
  198.     end
  199. end
  200.  
  201. MAX_TIME_OUT = 0.8
  202. TIME_BETWEEN_RESENDS = 0.2
  203. NUMBER_OF_RESENDS = 4
  204. VERBOSE = false
  205.  
  206. --easy to use methods
  207. --> the low level lowLevelListener returns true if atleast 1 tramission has been valid and in this case only 1 transmision
  208. function basicListener(modem)
  209.     return lowLevelListener(modem,BROADCAST_PORT,VERBOSE)--this will never finish, it will listen forever
  210. end
  211.  
  212. -->Low level request return
  213. --.sucess
  214. --.package[instance].sucess = true
  215. --.package[instance].tab = tab
  216. function basicBroadcast(modem,request)
  217.    
  218.     return lowLevelRequest(modem,request,BROADCAST_PORT,MAX_TIME_OUT,TIME_BETWEEN_RESENDS,NUMBER_OF_RESENDS,nil,nil,VERBOSE)--A broadcast request which will conenct to everyone
  219. end
  220.  
  221. function basicRequest(modem,request,computer)
  222.     return lowLevelRequest(modem,request,BROADCAST_PORT,MAX_TIME_OUT,TIME_BETWEEN_RESENDS,NUMBER_OF_RESENDS,computer,nil,VERBOSE)-- a message for a certian computer
  223. end
  224.  
  225. function basicBroadcastWithData(modem,request,data)
  226.     return lowLevelRequest(modem,request,BROADCAST_PORT,MAX_TIME_OUT,TIME_BETWEEN_RESENDS,NUMBER_OF_RESENDS,nil,data,VERBOSE)-- this a a broadcast with data
  227. end
  228.  
  229. function basicRequestWithData(modem,request,computer,data)
  230.     return lowLevelRequest(modem,request,BROADCAST_PORT,MAX_TIME_OUT,TIME_BETWEEN_RESENDS,NUMBER_OF_RESENDS,computer,data,VERBOSE) -- this is a message for a certian computer with data
  231. end
  232.  
  233. function addActionListener(message,func)
  234.     --function parameters required (data)
  235.     --.message -- the message that was transmitted
  236.     --.senderId -- the sender of the message
  237.     --.reciverId -- the reciver of the message
  238.     --.data -- the data that might have been passed along
  239.     local tab = {}
  240.     tab.message = message
  241.     tab.func = func
  242.     table.insert(lowLevelListeners,tab)
  243.     return #lowLevelListeners
  244. end
  245.  
  246. function removeActionListener(index)
  247.     table.remove(lowLevelListeners,index)
  248. end
  249. --End Of Layer 1
  250.  
  251. --Routeing layer
  252. portsTaken = {}
  253. computerId = {}
  254.  
  255. function openBroadcastNode(modem)
  256.     portsTaken[BROADCAST_PORT] = true
  257.     modem.open(BROADCAST_PORT)
  258. end
  259.  
  260. function portInit(modem)
  261.     for i = 1, 128, 1 do
  262.         portsTaken[i] = false
  263.         if modem.isOpen(i) then
  264.             modem.close(i)
  265.         end
  266.     end
  267. end
  268.  
  269. function findEmptyPort(modem)
  270.     for i = 1,128, 1 do
  271.         if portsTaken[i] == false then
  272.             return i
  273.         end
  274.     end
  275.     return -1
  276. end
  277.  
  278. function routerServer(modem)
  279.     portInit(modem)
  280.     openBroadcastNode(modem)
  281.     local requestRoute = function(data)
  282.         local port = findEmptyPort(modem)
  283.         computerId[port] = data.senderId
  284.         portsTaken[port] = true
  285.         data.data = tostring(port)
  286.         print("Port Found: " .. port)
  287.     end
  288.     addActionListener("addport",requestRoute)
  289.     local deleteRoute = function(data)
  290.         local port = tonumber(data.data)
  291.         if port ~= nil or port ~= -1 then
  292.             if data.senderId == computerId[port] then
  293.                 computerId[data.senderId] = -1
  294.                 portsTaken[port] = false
  295.                 data.data = "true"
  296.                 print("Port Deleted: " .. port)
  297.             else
  298.                 data.data = "false"
  299.             end
  300.         end    
  301.     end
  302.     addActionListener("removeport",deleteRoute)
  303.     addActionListener("ping",nil)
  304.     basicListener(modem)
  305. end
  306.  
  307. function deletePort(modem,port)
  308.     local d = basicBroadcastWithData(modem,"removeport",tostring(port))
  309.     for k, v in pairs(d.package) do
  310.         if #v.tab > 3 then
  311.             local state = v.tab[4]
  312.             if state ~=nil then
  313.                 if state == "true" then
  314.                     return true
  315.                 else
  316.                     return false
  317.                 end
  318.             end
  319.         end
  320.     end
  321.     print("router error")
  322.     return false
  323. end
  324.  
  325. function getRouterPort(modem)
  326.     local d = basicRequest(modem,"addport",routerComputerId)
  327.     for k, v in pairs(d.package) do
  328.         if #v.tab > 3 then
  329.             local p = v.tab[4]
  330.             if p ~= nil and p ~= "" then
  331.                 return tonumber(p)
  332.             end
  333.         end
  334.     end
  335.     print("router error")
  336.     return -1
  337. end
  338.  
  339. function routerInit(modem)
  340.     portInit(modem)
  341.     openBroadcastNode(modem)
  342.     local d = basicBroadcast(modem,"ping")
  343.     if d.sucess then
  344.         if #d.package > 0 then
  345.             local id = -1
  346.             for k, v in pairs(d.package) do
  347.                 if id == -1 or id == tonumber(v.tab[2]) then
  348.                     id = tonumber(v.tab[2])
  349.                     if id ~= -1 and id < 128 then
  350.                         routerComputerId = id
  351.                         return true
  352.                     end
  353.                 else
  354.                     print("Too many routers")
  355.                     return false
  356.                 end
  357.             end
  358.             print("unknown router Error")
  359.             return false
  360.         elseif #d.package == 0 then
  361.             print("No Routers detected")
  362.             return false
  363.         else
  364.             return false
  365.         end
  366.     else
  367.         print("Router not found")
  368.         return false
  369.     end
  370. end
  371. --End of routeing layer
  372. --begining of master layer core
  373. function splitText(text)
  374.     local textSplit = {}
  375.     local current = ""
  376.     for i = 1, #text, 1 do
  377.         local currentCharecter = text:sub(i,i)
  378.         if currentCharecter == '\n' then
  379.             table.insert(textSplit,current)
  380.             current = ""
  381.            
  382.         else
  383.             current = current .. currentCharecter
  384.         end
  385.     end
  386.     if current ~= ""  then
  387.         table.insert(textSplit,current)
  388.         current = ""
  389.     end
  390.     return textSplit
  391. end
  392.  
  393. function writeCenter(monitor,text,ypos)
  394.     local xSize, ySize = monitor.getSize()
  395.     monitor.setCursorPos((xSize / 2) - ((#text / 2) - 1),ypos)
  396.     monitor.write(text)
  397. end
  398.  
  399. function draw(monitor)
  400.     monitor.clear()
  401.     monitor.setBackgroundColor(colors.lightGray)
  402.     monitor.setTextColor(colors.lightBlue)
  403.     monitor.setTextScale(1)
  404.     drawButtons(monitor)
  405.     drawLines(monitor)
  406.     --writeCenter(monitor,"Electrial Transformer Controller",1)
  407. end
  408.  
  409. function drawButtons(monitor)
  410.     for k, v in pairs(buttons) do
  411.         drawButton(monitor,v)
  412.     end
  413. end
  414.  
  415. function drawButton(monitor,button)
  416.     local originalColor = monitor.getBackgroundColor()
  417.     if button["state"] == true then --sets the color based on it's state
  418.         monitor.setBackgroundColor(button["color2"])
  419.     else
  420.         monitor.setBackgroundColor(button["color1"])
  421.     end
  422.    
  423.     local xMiddle = math.floor(button["xSize"] / 2)--calculates the middle horizontally
  424.     local yMiddle = math.floor(button["ySize"] / 2)--calculates the middle vertically
  425.    
  426.     local text = splitText(button["text"])--this searchs for linebreaks and then seperates them into seperate tables
  427.     local textSizeHalfNotRounded = (#text / 2)
  428.     local textSizeHalf = math.floor(textSizeHalfNotRounded)
  429.    
  430.     local yExit = 0
  431.    
  432.     if (textSizeHalf == textSizeHalfNotRounded) then
  433.         yExit = (yMiddle + (textSizeHalf - 1)) + button["y"] --calculates where the y exit point is
  434.     else
  435.         yExit = (yMiddle + textSizeHalf) + button["y"]
  436.     end
  437.    
  438.     local yEntry = (yMiddle - textSizeHalf) + button["y"]--calculates where the y entry point is
  439.    
  440.     local xMax = button["x"] + button["xSize"]
  441.     local yMax = button["y"] + button["ySize"]
  442.    
  443.     for i = button["y"],yMax,1 do -- loops from the top to the bottom of the label
  444.         monitor.setCursorPos(button["x"],i) -- sets the position of the cursor
  445.         if i >= yEntry and i <= yExit then--checks to see if the y is at the line where the text goes
  446.             local textIndex = (i - yEntry) + 1--calculates what index text is at based on the yPos
  447.             local xEntry = button["x"] + (xMiddle - ((#text[textIndex] / 2)))--Finds the xEntry point based off the y
  448.             for j = button["x"],xMax,1 do -- loops from side to side of the label
  449.                 if j >= xEntry and j < xEntry + #text[textIndex] then-- portCheck if the charecters are within x entry
  450.                     local index = (j - xEntry) + 1--gets the index of the current charecter
  451.                     local textOut = text[textIndex]:sub(index,index)--prints out the charecter
  452.                     monitor.write(textOut)
  453.                 else
  454.                     monitor.write(" ")
  455.                 end
  456.             end
  457.         else
  458.             for j = button["x"],xMax,1 do -- loops from side to side of the label
  459.                 monitor.write(" ")--writes blank
  460.             end
  461.         end
  462.     end
  463.     monitor.setBackgroundColor(originalColor)
  464. end
  465.  
  466. function addButton(text,x,y,xSize,ySize,color1,color2,func)
  467.     local button = {}
  468.     button["text"] = text
  469.     button["state"] = false
  470.     button["x"] = x
  471.     button["y"] = y
  472.     button["xSize"] = xSize
  473.     button["ySize"] = ySize
  474.     button["color1"] = color1
  475.     button["color2"] = color2
  476.     button["func"] = func
  477.     table.insert(buttons,button)
  478.     return #buttons
  479. end
  480.  
  481. function removeButton(index)
  482.     table.remove(buttons,index)
  483. end
  484.  
  485. function removeAllButtons()
  486.     if #buttons ~= 0 then
  487.         buttons = {}
  488.     end
  489. end
  490.  
  491. function GetNumberOfDigits(number)
  492.     if number > 0 then
  493.         return math.log10(number) + 1
  494.     else
  495.         return 1
  496.     end
  497. end
  498.  
  499. function allNodesPresent()
  500.     for k, v in pairs(NODES) do
  501.         if nodeState[v] == nil or nodeState[v] == false then
  502.             return false
  503.         end
  504.     end
  505.     return true
  506. end
  507.  
  508. function checkIfNode(message)
  509.     for k, v in pairs(NODES) do
  510.         if message == v then
  511.             return true
  512.         end
  513.     end
  514.     return false
  515. end
  516.  
  517. function isNodePort(channel)
  518.     for k, v in pairs(nodePort) do
  519.         if channel == tonumber(v) then
  520.             return k
  521.         end
  522.     end
  523.     return -1
  524. end
  525.  
  526. function listen(monitor,modem)
  527.     while true do
  528.         local event, modemSide, senderChannel, replyChannel, message, senderDistance = os.pullEvent()
  529.         if event == "modem_message" then
  530.             if senderChannel == 1 then
  531.                 if message == "~connect~" then
  532.                     print("Connection request recived")
  533.                     local port = getRouterPort(modem)
  534.                     if port ~= -1 then
  535.                         modem.open(port)
  536.                         conPort[port] = replyChannel
  537.                         print("connection established. returned response port: " .. port)
  538.                         modem.transmit(replyChannel,port,"~connected~")
  539.                     else
  540.                         print("a device could not connect to the server, can't find valid port")
  541.                         modem.transmit(replyChannel,1,"~connection-error~")
  542.                     end
  543.                 end
  544.             else
  545.                 if conPort[senderChannel] ~= nil then
  546.                     local index = isNodePort(senderChannel)
  547.                     --local index = conPort[senderChannel]
  548.                     if index ~= -1 then
  549.                         if message == "~close-connection" then
  550.                             print("closeing connection")
  551.                             closeConnection(index,monitor,modem,false)
  552.                         end
  553.                     else
  554.                         if checkIfNode(message) == true then
  555.                             print("Node Connecting")
  556.                             if nodeState[message] == nil or nodeState[message] == false then
  557.                                 nodeState[message] = true
  558.                                 nodePort[message] = senderChannel
  559.                                 nodeSendPort[message] = replyChannel
  560.                                 buttons[nodeButtons[message]]["state"] = true
  561.                                 modem.transmit(replyChannel,senderChannel,"~NodeAccepted~")
  562.                                 print("Node Accepted")
  563.                                 draw(monitor)
  564.                                 if allNodesPresent() then
  565.                                     addActiveButtons(monitor)
  566.                                     activateAlreadyPressedButtons(monitor,modem)
  567.                                     onAllNodesPresent()
  568.                                 end
  569.                                 draw(monitor)
  570.                             else
  571.                                 print("Node Not Accepted")
  572.                                 modem.transmit(replyChannel,senderChannel,"~NodeNotAccepted~")
  573.                             end
  574.                         else
  575.                             modem.transmit(replyChannel,senderChannel,"~NodeNotAccepted~")
  576.                         end
  577.                     end
  578.                 end
  579.             end
  580.         elseif event == "monitor_touch" then
  581.             local x = senderChannel
  582.             local y = replyChannel
  583.            
  584.             for k, v in pairs(buttons) do
  585.                 local xMax = v["x"] + v["xSize"]
  586.                 local yMax = v["y"] + v["ySize"]
  587.                 if x >= v["x"] and x <= xMax and y >= v["y"] and y <= yMax then
  588.                     v["func"](monitor,modem,v)
  589.                     break
  590.                 end
  591.             end
  592.         elseif event == "key" then
  593.             local key = modemSide
  594.             local held = senderChannel
  595.             if key == 31 then
  596.                
  597.                 print("closeing connections")
  598.                
  599.                 closeConnectionAll(monitor,modem,true)
  600.                 print("closeing program")
  601.                
  602.                 break
  603.             end
  604.         end
  605.     end
  606. end
  607.  
  608. function transmitMessage(messageForTransmission,index,monitor,modem)
  609.     if nodeState[index] == true then
  610.         local timer = os.startTimer(1)
  611.         local loop = 0     
  612.         modem.transmit(nodeSendPort[index],nodePort[index],messageForTransmission)
  613.         while true do
  614.             local event, modemSide, senderChannel, replyChannel, message, senderDistance = os.pullEvent()
  615.            
  616.             if event == "timer" then
  617.                 if modemSide == timer then
  618.                     print("Connection failed, retransmitting")
  619.                     if loop >= 5 then
  620.                         print("Connection failed, assumeing node is shutdown, shuting down system...")
  621.                         closeConnection(index,monitor,modem,false)
  622.                         return false
  623.                     else
  624.                         modem.transmit(nodeSendPort[index],nodePort[index],messageForTransmission)
  625.                         timer = os.startTimer(0.5)
  626.                         loop = loop + 1
  627.                     end
  628.                 end
  629.             elseif event == "modem_message" then
  630.                 if senderChannel == nodePort[index] and replyChannel == nodeSendPort[index] then
  631.                     if message == "~Operation-Complete~" then
  632.                         break
  633.                     elseif message == "~close-connection~" then
  634.                         closeConnection(index,monitor,modem,false)
  635.                         return false
  636.                     end
  637.                 end
  638.             end
  639.         end
  640.     end
  641.     return true
  642. end
  643.  
  644. function closeConnection(index,monitor,modem,transmit)
  645.     local nodesPresent = allNodesPresent()
  646.     if transmit then
  647.         transmitMessage("~close-connection~",index,monitor,modem)
  648.     end
  649.     nodeState[index] = false
  650.     modem.close(nodePort[index])
  651.     buttons[nodeButtons[index]]["state"] = false
  652.     if nodesPresent then
  653.         transmitMessageToAll("redstone-off",monitor,modem)
  654.         saveState()
  655.         onAllNodesNotPresent()
  656.         addNodes(monitor)
  657.     end
  658.     deletePort(modem,conPort[index])
  659.     conPort[index] = -1
  660.     draw(monitor)
  661. end
  662.  
  663. function closeConnectionAll(monitor,modem,transmit)
  664.     for k, v in pairs(NODES) do
  665.         if nodeState[v] == true then
  666.             closeConnection(v,monitor,modem,transmit)
  667.         end
  668.     end
  669. end
  670.  
  671. function transmitMessageToAll(message,monitor,modem)
  672.     for k, v in pairs(NODES) do
  673.         if nodeState[v] then
  674.             local state = transmitMessage(message,v,monitor,modem)
  675.             if message ~= "~close-connection~" and state == false then
  676.                 break
  677.             end
  678.         end
  679.     end
  680. end
  681. function activateAlreadyPressedButtons(monitor,modem)
  682.     for k, v in pairs(NODES) do
  683.         loadButtonState(monitor,modem,v,buttonsPressed[v])
  684.     end
  685. end
  686. function addActiveButtons(modem)
  687.     nodeButtons = {}
  688.     removeAllButtons()
  689.     for k, v in pairs(NODES) do
  690.         nodeButtons[v] = addButton(NODES_NAME[k] .. "\noff",buttonsPosition[v].x,buttonsPosition[v].y,BUTTON_SIZE_X,BUTTON_SIZE_Y,colors.red,colors.green,buttonsFunc[v])
  691.     end
  692. end
  693.  
  694. function nodeFunctions()
  695.     local nodeFunc = {}
  696.     for k, v in pairs(NODES) do
  697.         nodeFunc[v] = function(monitor,modem,button)
  698.         end
  699.     end
  700.     return nodeFunc
  701. end
  702.  
  703.  
  704. function SetConnectedNodesColor()
  705.     for k, v in pairs(NODES) do
  706.         if nodeState[v] ~= nil then
  707.             buttons[nodeButtons[v]]["state"] = nodeState[v]
  708.         end    
  709.     end
  710. end
  711. function addNodes(monitor)
  712.     nodeButtons = {}
  713.     local nodeFunc = nodeFunctions()
  714.     removeAllButtons()
  715.     for k, v in pairs(NODES) do
  716.         nodeButtons[v] = addButton(NODES_NAME[k],buttonsPosition[v].x,buttonsPosition[v].y,BUTTON_SIZE_X,BUTTON_SIZE_Y,colors.red,colors.green,nodeFunc[v])
  717.     end
  718.     SetConnectedNodesColor()
  719. end
  720. function calculateButtonPositions(monitor)
  721.     local buttonsPos = {}
  722.     local xPos = 2
  723.     local yPos = 9
  724.     for k, v in pairs(NODES) do
  725.         local buttonPos = {}
  726.         buttonPos.x = xPos
  727.         buttonPos.y = yPos
  728.         buttonsPos[v] = buttonPos
  729.         if (xPos + 10) < monitor.getSize() then
  730.             xPos = xPos + 10
  731.         else
  732.             xPos = 2
  733.             yPos = yPos + 6
  734.         end
  735.     end
  736.     buttonsPosition = buttonsPos
  737. end
  738. function placeButtonManually(index,x,y)
  739.     local buttonPos = {}
  740.     buttonPos.x = x
  741.     buttonPos.y = y
  742.     buttonsPosition[index] = buttonPos
  743. end
  744. function drawLine(monitor,x,y,xSize,ySize,color)
  745.     local originalColor = monitor.getBackgroundColor()
  746.     monitor.setBackgroundColor(color)
  747.     local xMax = x + xSize
  748.     local yMax = y + ySize
  749.  
  750.     for i = y,yMax,1 do
  751.         monitor.setCursorPos(x,i)
  752.         for j = x,xMax,1 do
  753.             monitor.write(" ")
  754.         end
  755.     end
  756.     monitor.setBackgroundColor(originalColor)
  757. end
  758. function drawLines(monitor)
  759.     --this is where you can place any lines you want drawn
  760.     for k, v in pairs(drawLinesData) do
  761.         drawLine(monitor,v.x,v.y,v.xSize,v.ySize,v.color)
  762.     end
  763. end
  764. function addLine(index,x,y,xSize,ySize,color)
  765.     local item = {}
  766.     item.x = x
  767.     item.y = y
  768.     item.xSize = xSize
  769.     item.ySize = ySize
  770.     item.color = color
  771.     drawLinesData[index] = item
  772. end
  773. function loadButtonState(monitor,modem,index,state)
  774.     if state == true then
  775.         local button = buttons[nodeButtons[index]]
  776.         button["state"] = true
  777.         local text = splitText(button["text"])
  778.         button["text"] = ""
  779.         for i = 1,#text - 1 do
  780.             button["text"] = button["text"] .. text[i] .. "\n"
  781.         end
  782.         button["text"] = button["text"] .. "on"
  783.         transmitMessage("redstone-on",index,monitor,modem)
  784.     end
  785.     draw(monitor)
  786. end
  787. function addButtonActionFunction(index,func)
  788.     buttonsFunc[index] = function(monitor,modem,button)
  789.         if button["state"] == false then
  790.             button["state"] = true
  791.             buttonsPressed[index] = true
  792.             local text = splitText(button["text"])
  793.             button["text"] = ""
  794.             for i = 1,#text - 1 do
  795.                 button["text"] = button["text"] .. text[i] .. "\n"
  796.             end
  797.             button["text"] = button["text"] .. "on"
  798.             transmitMessage("redstone-on",index,monitor,modem)
  799.             if func ~= nil then
  800.                 func(monitor,modem,button,true)
  801.             end
  802.             saveState()
  803.         else
  804.             button["state"] = false
  805.             buttonsPressed[index] = false
  806.             local text = splitText(button["text"])
  807.             button["text"] = ""
  808.             for i = 1, #text - 1 do
  809.                 button["text"] = button["text"] .. text[i] .. "\n"
  810.             end
  811.             button["text"] = button["text"] .. "off"
  812.             transmitMessage("redstone-off",index,monitor,modem)
  813.             if func ~= nil then
  814.                 func(monitor,modem,button,false)
  815.             end
  816.             saveState()
  817.         end
  818.         draw(monitor)
  819.     end
  820. end
  821. function generateDefaultButtonActions()
  822.     for k, v in pairs(NODES) do
  823.         addButtonActionFunction(v,nil)
  824.     end
  825. end
  826. function loadState()
  827.     local f = io.open("latest_state.txt", "r")
  828.     local map = {}
  829.     if f then
  830.         local s = f:read("*a")
  831.         f:close()
  832.         local k = ""
  833.         local v = ""
  834.         local state = false
  835.         local failed = false
  836.         for i = 1, #s, 1 do
  837.             if s:sub(i,i) == ':' then
  838.                 if state == false then
  839.                     state = true
  840.                 else
  841.                     print("io exception, too many :")
  842.                     failed = true
  843.                     break
  844.                 end
  845.             elseif s:sub(i,i) == ',' then
  846.                 if state == true then
  847.                     state = false
  848.                     if v == "true" then
  849.                         map[k] = true
  850.                     elseif v == "false" then
  851.                         map[k] = false
  852.                     else
  853.                         print("result is not true or false")
  854.                         failed = true
  855.                         break
  856.                     end
  857.                     k = ""
  858.                     v = ""
  859.                 else
  860.                     print("io exception, no key")
  861.                     failed = true
  862.                     break
  863.                 end
  864.             else
  865.                 if state then
  866.                     v = v .. s:sub(i,i)
  867.                 else
  868.                     k = k .. s:sub(i,i)
  869.                 end
  870.             end
  871.         end
  872.  
  873.         if failed == false then
  874.             if #map == #NODES then
  875.                 for k, v in pairs(NODES) do
  876.                     if map[v] == nil then
  877.                         failed = true
  878.                         break
  879.                     end
  880.                 end
  881.             else
  882.                 failed = true
  883.             end
  884.         end
  885.     end
  886.     return map
  887. end
  888.  
  889. function saveState()
  890.     local file = io.open("latest_state.txt" , "w")
  891.    
  892.     for k, v in pairs(buttonsPressed) do
  893.         file:write(k .. ":" .. tostring(v) .. ",")
  894.     end
  895.    
  896.     file:flush()
  897.     file:close()
  898. end
  899.  
  900. --end of Master Layers core
  901. --begining of Master Layers config layer
  902. function onAllNodesPresent()
  903.     --allows you to config what happends when all nodes become present
  904. end
  905.  
  906. function onAllNodesNotPresent()
  907.     --allows you to config what happends when one node leaves when all nodes were present
  908.     --drawLinesData["test"].color = colors.red
  909. end
  910.  
  911. function setupButtonActionsManually()
  912.     --if you want to customize what happends when you select a button
  913.     --Example:addButtonActionFunction(index,func<(monitor,modem,button,newState)>)
  914.     --[[addButtonActionFunction("node0",function(monitor,modem,button,newState)
  915.         if newState then
  916.             drawLinesData["test"].color = colors.green
  917.         else
  918.             drawLinesData["test"].color = colors.red
  919.         end
  920.     end)
  921.     addButtonActionFunction("node1",nil)
  922.     addButtonActionFunction("node2",nil)
  923.     addButtonActionFunction("node3",nil)
  924.     addButtonActionFunction("node4",nil)
  925.     addButtonActionFunction("node5",nil)]]--
  926. end
  927.  
  928.  
  929. function setupLines()
  930.     --addLine("test",3,8,3,0,colors.red)
  931. end
  932.  
  933. function placeButtonsManually()
  934.     --if you want to setup a custom button configuration you can do it here
  935.     --example: placeButtonManually("NAME_OF_NODE",x,y)
  936.     --[[--node0
  937.     placeButtonManually("node0",2,2)
  938.     --node1
  939.     placeButtonManually("node1",17,2)
  940.     --node2
  941.     placeButtonManually("node2",32,2)
  942.     --node3
  943.     placeButtonManually("node3",2,13)
  944.     --node4
  945.     placeButtonManually("node4",17,13)
  946.     --node5
  947.     placeButtonManually("node5",32,13)]]--
  948. end
  949.  
  950. function drawMonitor()
  951.     local monitor = peripheral.wrap(MONITOR_SIDE)
  952.    
  953.     --setup
  954.     generateDefaultButtonActions() -- this will generate the default actions which turns then green to red
  955.     calculateButtonPositions(monitor) -- this will place the buttons automaticly based on the monitor
  956.     --setupButtonActionsManually()
  957.     --placeButtonsManually()
  958.     setupLines()
  959.    
  960.     addNodes(monitor)
  961.    
  962.     draw(monitor)
  963.     return monitor
  964. end
  965. --end of master Layer config
  966. function runMaster()
  967.     local modem = detectModem()
  968.     routerInit(modem)
  969.     modem.open(MASTER_PORT)
  970.     local monitor = drawMonitor()
  971.     buttonsPressed = loadState()
  972.    
  973.     listen(monitor,modem)
  974. end
  975.  
  976. runMaster()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement