le_Fish

swarmbotMainPC

May 15th, 2020
674
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.78 KB | None | 0 0
  1. --[[
  2.     This will be the main computer program.
  3.     It wil listen to user inputs to make new swarm robots and
  4.     also listen for the swarm robot positions.
  5.     -- todo
  6.         Create something so we can recall turtle's
  7. ]]
  8. if not fs.exists("digMonitor") then
  9.     shell.run("pastebin", "get", "2RMg3kFa", "digMonitor")
  10. end
  11. os.loadAPI("digMonitor")
  12. if not fs.exists("rnApi") then
  13.     shell.run("pastebin", "get", "HQVEqt0C", "rnApi")
  14. end
  15. os.loadAPI("rnApi")
  16.  
  17. local rn = rnApi.BetterRN:new()
  18. rn:open()
  19.  
  20. local monitor = digMonitor.Mon:new()
  21.  
  22. local swarmBots = {}
  23. local config = {}
  24. local skips = {}
  25.  
  26. function removeDoubles(list)
  27.     local list = list
  28.     local hash = {}
  29.     local res = {}
  30.  
  31.     for _, v in ipairs(list) do
  32.         if (not hash[v]) then
  33.             res[#res + 1] = v -- you could print here instead of saving to result table if you wanted
  34.             hash[v] = true
  35.         end
  36.     end
  37.  
  38.     return res
  39. end
  40.  
  41. if fs.exists("data/config") then
  42.     local file = fs.open("data/config", "r")
  43.     local data = file.readAll()
  44.     file.close()
  45.     config = textutils.unserialize(data)
  46. else
  47.     if not fs.exists("configProgram") then
  48.         shell.run("pastebin", "get", "izEfQHMQ", "configProgram")
  49.     end
  50.     shell.run("configProgram")
  51.     local file = fs.open("data/config", "r")
  52.     local data = file.readAll()
  53.     file.close()
  54.     config = textutils.unserialize(data)
  55. end
  56.  
  57. if fs.exists("data/swarmBots") then
  58.     local file = fs.open("data/swarmBots", "r")
  59.     local data = file.readAll()
  60.     file.close()
  61.     swarmBots = textutils.unserialize(data)
  62.     swarmBots = removeDoubles(swarmBots)
  63.     monitor:setData(swarmBots)
  64.     monitor:showData()
  65. end
  66.  
  67. if fs.exists("data/skips") then
  68.     local file = fs.open("data/skips", "r")
  69.     local data = file.readAll()
  70.     file.close()
  71.     skips = textutils.unserialize(data)
  72. end
  73.  
  74.  
  75. -- Listen for the register command of a bot
  76. function registerBot()
  77.     local response
  78.     -- Fake data
  79.     local newTurtle = {
  80.         [1] = {1, 1},
  81.         [2] = 85,
  82.         [3] = 85,
  83.         [4] = 85,
  84.         [4] = vector.new(1, 1, 1),
  85.         [5] = "s",
  86.         [6] = 128,
  87.         [7] = skips
  88.     }
  89.     response = rn:listen("swarmbotRegisterRequest")
  90.     if next(response) ~= nil then
  91.         newTurtle[1] = calculateNextChunk(calculateStartDir())
  92.         newTurtle[2] = config.startHeight
  93.         newTurtle[3] = config.parkHeight
  94.         newTurtle[4] = config.flyHeight
  95.         newTurtle[5] = calculateHomePos()
  96.         newTurtle[6] = calculateStartDir()
  97.         newTurtle[7] = config.maxLength
  98.         newTurtle[8] = skips
  99.         rn:send(response[1], newTurtle, "swarmbotRegister")
  100.         swarmBots[#swarmBots + 1] = {response[1], "Starting", os.clock()}
  101.         swarmBots = removeDoubles(swarmBots)
  102.         monitor:setData(swarmBots)
  103.         monitor:showData()
  104.         saveSwarmBots()
  105.     end
  106. end
  107. -- Calculate functions needed for registration
  108. function calculateStartDir()
  109.     local number = #swarmBots % #config.directions
  110.     if number == 0 then
  111.         number = #config.directions
  112.     end
  113.     return config.directions[number]
  114. end
  115. function calculateNextChunk(dir)
  116.     local dir = dir:lower()
  117.     if dir ~= "e" and dir ~= "s" and dir ~= "w" and dir ~= "n" then
  118.         error("calculateHomePos direction is not e,s,w or n, currently is " .. dir)
  119.     end
  120.     local number = math.ceil((#swarmBots + 1) / #config.directions)
  121.     if dir == "e" then
  122.         return {config.chunk[1] + number, config.chunk[2]}
  123.     elseif dir == "s" then
  124.         return {config.chunk[1], config.chunk[2] + number}
  125.     elseif dir == "w" then
  126.         return {config.chunk[1] - number, config.chunk[2]}
  127.     elseif dir == "n" then
  128.         return {config.chunk[1], config.chunk[2] - number}
  129.     end
  130. end
  131. function calculateHomePos()
  132.     local pos = vector.new(0, 0, 0)
  133.     pos.x = (config.chunk[1] * 16) + math.floor(#swarmBots % 16)
  134.     pos.y = (config.chunk[2] * 16) + math.floor(#swarmBots / 16)
  135.     pos.z = math.ceil((#swarmBots + 1) / 256) + config.parkHeight
  136.     return pos
  137. end
  138.  
  139. -- Save swarmbot function
  140. function saveSwarmBots()
  141.     local file = fs.open("data/swarmBots", "w")
  142.     -- Make a hard copy..
  143.     local hardCopy = copy(swarmBots)
  144.     file.writeLine(textutils.serialize(hardCopy))
  145.     file.close()
  146. end
  147. function saveSkips()
  148.     local file = fs.open("data/skips", "w")
  149.     -- Make a hard copy..
  150.     print(textutils.serialise(skips))
  151.     file.writeLine(textutils.serialize(skips))
  152.     file.close()
  153. end
  154. -- hardcopy a obj.
  155. function copy(obj)
  156.     if type(obj) ~= "table" then
  157.         return obj
  158.     end
  159.     local res = {}
  160.     for k, v in pairs(obj) do
  161.         res[copy(k)] = copy(v)
  162.     end
  163.     return res
  164. end
  165.  
  166. -- Listen for user inputs
  167. function listenUserInput()
  168.     while true do
  169.         term.clear()
  170.         term.setCursorPos(1, 1)
  171.         print("<Spawn {number}> to start swarmBots")
  172.         print("Put enough mining turtles and enderchests")
  173.         print("<Skip {x,y}> to skip a certain chunk")
  174.         print("<Broadcast {message}> to send message to all swarmBots")
  175.         print("'home' to home all bots")
  176.         print("'mine' to start all bots")
  177.         print("'pause' to pause all bots")
  178.         print("'ping' to ping all bots")
  179.         print("'update' to update all bots")
  180.         readInput()
  181.  
  182.         sleep(1)
  183.     end
  184. end
  185. function readInput()
  186.     input = read()
  187.     if input ~= nil or input ~= "" then
  188.         if string.match(input:lower(), "spawn") and string.match(input, "%d+") then
  189.             local amount = string.match(input, "%d+")
  190.             print("Spawning " .. amount .. " swarmBots")
  191.             placeBots(amount)
  192.         elseif string.match(input:lower(), "skip") and string.match(input, "%d+") then
  193.             local chunk = string.gsub(input:lower(), "skip", "")
  194.             chunk = string.gsub(chunk, " ", "")
  195.             local results = {}
  196.             for match in string.gmatch(chunk, "[^,]+") do
  197.                 results[#results + 1] = tonumber(match)
  198.             end
  199.             local dontSave = false
  200.             for k, v in pairs(skips) do
  201.                 if v[1] == results[1] and v[2] == results[2] then
  202.                     dontSave = true
  203.                     break
  204.                 end
  205.             end
  206.             if not dontSave then
  207.                 skips[#skips + 1] = results
  208.                 saveSkips()
  209.                 local sendTimes = 4
  210.                 if math.ceil(#swarmBots / 3) > sendTimes then
  211.                     sendTimes = math.ceil(#swarmBots / 3)
  212.                 end
  213.                 for i = 1, sendTimes do
  214.                     print("sending " .. sendTimes - i .. " times")
  215.                     rn:broadcast("skip " .. chunk, "swarmbot")
  216.                 end
  217.                 print("Send 'skip " .. chunk .. "' on the 'swarmbot' channel")
  218.                 sleep(2)
  219.             else
  220.                 print("Already skipping " .. chunk)
  221.                 sleep(2)
  222.             end
  223.         elseif
  224.             (string.match(input:lower(), "broadcast") or string.match(input:lower(), "br ")) and
  225.                 (string.match(input:lower(), "home") or string.match(input:lower(), "mine") or
  226.                     string.match(input:lower(), "pause") or
  227.                     string.match(input:lower(), "ping") or string.match(input:lower(), "update"))
  228.          then
  229.             local sendTimes = 5
  230.             -- if math.ceil(#swarmBots / 3) > sendTimes then
  231.             --     sendTimes = math.ceil(#swarmBots / 3)
  232.             -- end
  233.             if string.match(input:lower(), "home") then
  234.                 for i = 1, sendTimes do
  235.                     print("sending " .. sendTimes - i .. " times")
  236.                     rn:broadcast("home", "swarmbot")
  237.                 end
  238.                 print("Send 'home' on the 'swarmbot' channel")
  239.                 sleep(2)
  240.             elseif string.match(input:lower(), "mine") then
  241.                 for i = 1, sendTimes do
  242.                     print("sending " .. sendTimes - i .. " times")
  243.                     rn:broadcast("mine", "swarmbot")
  244.                 end
  245.                 print("Send 'mine' on the 'swarmbot' channel")
  246.                 sleep(2)
  247.             elseif string.match(input:lower(), "pause") then
  248.                 for i = 1, sendTimes do
  249.                     print("sending " .. sendTimes - i .. " times")
  250.                     rn:broadcast("pause", "swarmbot")
  251.                 end
  252.                 print("Send 'pause' on the 'swarmbot' channel")
  253.                 sleep(2)
  254.             elseif string.match(input:lower(), "ping") then
  255.                 for i = 1, sendTimes do
  256.                     print("sending " .. sendTimes - i .. " times")
  257.                     rn:broadcast("ping", "swarmbot")
  258.                 end
  259.                 print("Send 'ping' on the 'swarmbot' channel")
  260.                 sleep(2)
  261.             elseif string.match(input:lower(), "update") then
  262.                 for i = 1, 3 do
  263.                     print("sending " .. 3 - i .. " times")
  264.                     rn:broadcast("update", "swarmbot")
  265.                 end
  266.                 print("Send 'update' on the 'swarmbot' channel")
  267.                 sleep(2)
  268.             end
  269.         else
  270.             print("I didn't understand that..")
  271.         end
  272.     end
  273.     sleep(0.2)
  274. end
  275. function placeBots(amount)
  276.     local amount = tonumber(amount)
  277.     if amount < 1 or amount > 120000 or type(amount) ~= "number" then
  278.         print("Amount is wrong, it is a" .. type(amount) .. "with a value of " .. amount)
  279.         print("(min = 1, max = 120000")
  280.     else
  281.         for i = 1, amount do
  282.             -- Do some checks
  283.             -- Create a bot and place it
  284.             local turtleSlot = 0
  285.             local enderSlot = 0
  286.             while turtleSlot == 0 do
  287.                 for i = 1, 16 do
  288.                     if
  289.                         turtle.getItemDetail(i) and
  290.                             (turtle.getItemDetail(i).name == "ComputerCraft:CC-Turtle" or
  291.                                 turtle.getItemDetail(i).name == "ComputerCraft:CC-TurtleExpanded")
  292.                      then
  293.                         turtleSlot = i
  294.                         break
  295.                     else
  296.                         turtle.suckUp()
  297.                     end
  298.                 end
  299.                 sleep(1)
  300.             end
  301.             while enderSlot == 0 do
  302.                 for i = 1, 16 do
  303.                     if turtle.getItemDetail(i) and turtle.getItemDetail(i).name == "EnderStorage:enderChest" then
  304.                         enderSlot = i
  305.                         break
  306.                     end
  307.                 end
  308.                 sleep(1)
  309.             end
  310.             turtle.select(turtleSlot)
  311.             turtle.place(1)
  312.             turtle.select(enderSlot)
  313.             turtle.drop(1)
  314.             peripheral.call("front", "turnOn")
  315.             registerBot()
  316.             if amount > 1 then
  317.                 print("Placed bot " .. i .. ". " .. amount - i .. " to go.")
  318.                 sleep(2)
  319.             end
  320.         end
  321.     end
  322. end
  323.  
  324. -- Listen for rednet updates
  325. local messages = {}
  326. function listenRednet()
  327.     while true do
  328.         local response = {}
  329.         response = rn:listen("swarmbotPing")
  330.         if next(response) ~= nil then
  331.             rednet.send(response[1], "OK", "swarmbotReceived")
  332.             messages[#messages + 1] = response
  333.             response = nil
  334.         else
  335.             sleep(0.1)
  336.         end
  337.     end
  338. end
  339. function messageController()
  340.     local counter = 0
  341.     while true do
  342.         if next(messages) ~= nil then
  343.             local response = {next(messages)}
  344.             local found = false
  345.             response = response[2]
  346.             for i = 1, #swarmBots do
  347.                 if tonumber(swarmBots[i][1]) == tonumber(response[1]) then
  348.                     swarmBots[i][2] = response[2]
  349.                     swarmBots[i][3] = os.clock()
  350.                     saveSwarmBots()
  351.                     if #messages < 2 or counter == 20 then
  352.                         counter = 0
  353.                         monitor:setData(swarmBots)
  354.                         monitor:showData()
  355.                     end
  356.                     found = true
  357.                     break
  358.                 end
  359.             end
  360.             if found == false then
  361.                 print("Unkown bot: " .. tonumber(response[1]))
  362.             end
  363.             local newMessages = {}
  364.            
  365.             counter = counter + 1
  366.             messages[next(messages)] = nil
  367.             for i = 1,#messages do
  368.                 if messages[i] ~= nil then
  369.                     newMessages[#newMessages+1] = messages[i]
  370.                 end
  371.             end
  372.             messages = newMessages
  373.             response = nil
  374.         else
  375.             sleep(1)
  376.         end
  377.     end
  378. end
  379.  
  380. function listenMonitor()
  381.     monitor:listen()
  382. end
  383. function updateMonitor()
  384.     while 1 do
  385.         monitor:showData()
  386.         sleep(120)
  387.     end
  388. end
  389.  
  390. parallel.waitForAll(listenRednet, messageController, listenUserInput, listenMonitor, updateMonitor)
Add Comment
Please, Sign In to add comment