Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Movement
- if not fs.exists("movementApi") then
- shell.run("pastebin", "get", "yykL6u8N", "movementApi")
- end
- os.loadAPI("movementApi")
- -- GPS
- if not fs.exists("gpsApi") then
- shell.run("pastebin", "get", "gKySQWcG", "gpsApi")
- end
- os.loadAPI("gpsApi")
- -- Quarry
- if not fs.exists("digApi") then
- shell.run("pastebin", "get", "Q2RSv5cF", "digApi")
- end
- os.loadAPI("digApi")
- print("V0.2.5")
- local config = {
- homePos = vector.new(0, 0, 0),
- startDir = "s",
- startHeight = 85,
- parkHeight = 85,
- flyHeight = 85,
- masterPc = 0,
- startChunk = {[1] = true, [2] = true},
- currentChunk = {[1] = true, [2] = true},
- quarry = false,
- goingHome = false,
- home = false,
- maxChunks = 128,
- chunks = 0,
- goingMine = true
- }
- local skips = {}
- local stopProgram = false
- local loopRunning
- local turtleMov = movementApi.Movement:new(vector.new(0, 0, 0), "e")
- local turtleGPS = gpsApi.BetterGPS:new(vector.new(0, 0, 0), "e")
- local turtleDig, xPoint, yPoint
- -- Set turtleMovment position and direction
- turtleGPS:locate(10)
- turtleMov.pos = turtleGPS:locate(10)
- turtleMov.dir = turtleGPS:getDir()
- -- Check for enderchest
- local data = turtle.getItemDetail(1)
- if data == nil or string.find(data.name, "EnderStorage") == false then
- turtle.select(1)
- local success, inspectUp = turtle.inspectUp()
- if success and string.find(inspectUp.name, "EnderStorage") then
- if turtle.getItemCount(1) > 0 then
- turtle.dropUp(turtle.getItemCount(1))
- end
- turtle.digUp()
- else
- print("Put an enderchest in slot 1")
- repeat
- data = turtle.getItemDetail(1)
- sleep(0.2)
- until data ~= nil and string.find(data.name, "EnderStorage")
- end
- end
- -- open rednet
- if peripheral.getType("right") == "modem" then
- rednet.open("right")
- elseif peripheral.getType("left") == "modem" then
- rednet.open("left")
- else
- error("Couldn't find a modem on my left or right side")
- end
- -- quarry loop with stop loop
- function digLoop()
- checkSkips()
- -- if busy with quarry, keep going
- if config.quarry then
- -- Check if bot is in
- runQuarry()
- end
- -- main loop
- while true do
- -- Go to correct Z, X & Y
- if turtleMov.pos.z ~= config.flyHeight then
- turtleMov:goToZ(tonumber(config.flyHeight), 'dig', {'computer'})
- end
- xPoint = config.currentChunk[1] * 16
- yPoint = config.currentChunk[2] * 16
- if config.startDir == "e" then
- yPoint = yPoint + 15
- elseif config.startDir == "n" then
- yPoint = yPoint + 15
- xPoint = xPoint + 15
- elseif config.startDir == "w" then
- xPoint = xPoint + 15
- end
- if turtleMov.pos.x ~= xPoint then
- turtleMov:goToX(xPoint, 'dig', {'computer'})
- end
- if turtleMov.pos.y ~= yPoint then
- turtleMov:goToY(yPoint, 'dig', {'computer'})
- end
- if turtleMov.pos.z ~= config.startHeight then
- turtleMov:goToZ(tonumber(config.startHeight), 'dig', {'computer'})
- end
- if config.startDir == "s" then
- turtleMov:face("e")
- elseif config.startDir == "w" then
- turtleMov:face("s")
- elseif config.startDir == "n" then
- turtleMov:face("w")
- elseif config.startDir == "e" then
- turtleMov:face("n")
- end
- config.chunks = config.chunks + 1
- if config.maxChunks + 1 == config.chunks then
- goHome()
- break
- end
- config.quarry = true
- saveConfig()
- runQuarry()
- end
- end
- function stopLoop()
- while not stopProgram do
- sleep(1)
- end
- end
- -- Main quarry loop & rednet loop
- function mainLoop()
- while true do
- if not stopProgram then
- loopRunning = true
- parallel.waitForAny(digLoop, stopLoop)
- print("digLoop stopped")
- loopRunning = false
- end
- sleep(1)
- end
- end
- function pingLoop()
- while true do
- sleep(600)
- sendPing()
- end
- end
- local rednetMessage = {}
- function stopRednetLoopHome()
- print("stopRednetLoopHome")
- local stopRednetHomeMessage = {}
- local message = ""
- while 1 do
- stopRednetHomeMessage = {rednet.receive("swarmbot", 10)}
- if next(stopRednetHomeMessage) ~= nil then
- message = stopRednetHomeMessage[2]
- if message == "pause" then
- rednetMessage = stopRednetHomeMessage
- print("stopping a second rednet loop to pause")
- return
- elseif message == "mine" then
- rednetMessage = stopRednetHomeMessage
- print("stopping a second rednet loop to mine")
- return
- end
- else
- sleep(0.1)
- end
- end
- end
- function stopRednetLoopMine()
- print("stopRednetLoopMine")
- local stopRednetMineMessage = {}
- local message = ""
- while 1 do
- stopRednetMineMessage = {rednet.receive("swarmbot", 10)}
- if next(stopRednetMineMessage) ~= nil then
- message = stopRednetMineMessage[2]
- if message == "pause" then
- rednetMessage = stopRednetMineMessage
- print("stopping a second rednet loop to pause")
- return
- elseif message == "home" then
- rednetMessage = stopRednetMineMessage
- print("stopping a second rednet loop to mine")
- return
- end
- else
- sleep(0.1)
- end
- end
- end
- function rednetLoop()
- print("rednetloop live")
- local paused = false;
- while 1 do
- if next(rednetMessage) == nil then
- rednetMessage = {rednet.receive("swarmbot", 10)}
- end
- local response = {}
- if next(rednetMessage) ~= nil then
- response.senderID = rednetMessage[1]
- response.message = rednetMessage[2]
- rednetMessage = {}
- print("received: " .. textutils.serialise(response.message))
- if response.message == "pause" and not paused then
- if not stopProgram then
- stopProgram = true
- paused = true
- sleep(2.5)
- paused = false
- end
- elseif response.message == "home" then
- if not config.goingHome then
- config.goingHome = true
- stopProgram = true
- sleep(2.5)
- turtleGPS:locate(10)
- turtleMov.pos = turtleGPS:locate(10)
- if turtleMov.pos ~= config.homePos then
- turtleMov.dir = turtleGPS:getDir()
- saveCurrentPos()
- saveConfig()
- parallel.waitForAny(stopRednetLoopHome, goHome)
- print("either done with goHome or stopped")
- end
- end
- elseif response.message == "mine" then
- if not loopRunning and not goingMine then
- config.goingMine = true
- config.home = false
- saveConfig()
- if fs.exists("data/swarm/lastPos") then
- config.goingHome = false
- saveConfig()
- parallel.waitForAny(stopRednetLoopMine, goLastPos)
- print("either done with goLastPos or stopped")
- end
- stopProgram = false
- config.goingMine = false
- saveConfig()
- end
- elseif response.message == "ping" then
- sendPing()
- elseif string.match(response.message, "skip") then
- local skipChunk = string.gsub(response.message, "skip", "")
- skipChunk = string.gsub(skipChunk, " ", "")
- local results = {}
- for match in string.gmatch(skipChunk, "[^,]+") do
- results[#results + 1] = tonumber(match)
- end
- local dontSave = false
- for k,v in pairs(skips) do
- if v[1] == results[1] and v[2] == results[2] then
- dontSave = true
- break
- end
- end
- if not dontSave then
- print("Saving skip")
- skips[#skips + 1] = results
- saveSkip()
- if config.currentChunk[1] == results[1] and config.currentChunk[2] == results[2] then
- if not stopProgram then
- stopProgram = true
- sleep(2.5)
- end
- config.quarry = false
- stopProgram = false
- turtleMov.pos = turtleGPS:locate(10)
- turtleMov.dir = turtleGPS:getDir()
- end
- saveConfig()
- end
- elseif response.message == "update" then
- sleep(10)
- shell.run("rm","digApi")
- shell.run("rm","gpsApi")
- shell.run("rm","movementApi")
- shell.run("rm","swarmBot")
- os.reboot()
- end
- end
- sleep(0.5)
- print('listening for rednet')
- end
- end
- -- Main functions
- function register()
- if not rednet.isOpen("left") and not rednet.isOpen("right") then
- if peripheral.getType("right") == "modem" or peripheral.getType("left") == "modem" then
- rednet.open("left")
- rednet.open("right")
- else
- error("SwarmBot register couldn't open rednet")
- end
- end
- rednet.broadcast("register", "swarmbotRegisterRequest")
- local rawResponse = {rednet.receive("swarmbotRegister", 600)}
- local response = {}
- if next(rawResponse) == nil then
- error("SwarmBot register waited to long for a response")
- else
- rednet.send(rawResponse[1], "OK", "swarmbotRegister")
- if type(rawResponse[1]) ~= "number" then
- error("SwarmBot register response[1] expects to be a number, currently is " .. type(rawResponse[1]))
- elseif type(rawResponse[2]) ~= "table" then
- error("SwarmBot register response[2] expects to be a table, currently is " .. type(rawResponse[2]))
- end
- response.senderID = rawResponse[1]
- response.chunk = rawResponse[2][1]
- response.startHeight = rawResponse[2][2]
- response.parkHeight = rawResponse[2][3]
- response.flyHeight = rawResponse[2][4]
- response.homePos = rawResponse[2][5]
- response.startDir = rawResponse[2][6]
- response.maxChunks = rawResponse[2][7]
- response.skips = rawResponse[2][8]
- return response
- end
- end
- function runQuarry()
- local x = config.currentChunk[1] * 16
- local y = config.currentChunk[2] * 16
- if turtleMov.pos.x >= x and turtleMov.pos.x <= x + 15 and turtleMov.pos.y >= y and turtleMov.pos.y <= y + 15 then
- sendPing()
- turtleDig = digApi.Dig:new(turtleMov.pos, turtleMov.dir, config.startHeight)
- turtleDig:quarryChunk(turtleMov.pos, turtleMov.dir, config.startDir)
- updateChunk()
- turtleGPS:locate(10)
- turtleMov.pos = turtleGPS:locate(10)
- turtleMov.dir = turtleGPS:getDir()
- saveConfig()
- config.quarry = false
- else
- if config.startDir == "s" or config.startDir == "n" then
- turtleMov:goToX(x, "dig", {'computer'})
- turtleMov:goToY(y, "dig", {'computer'})
- else
- turtleMov:goToY(y, "dig", {'computer'})
- turtleMov:goToX(x, "dig", {'computer'})
- end
- runQuarry()
- end
- end
- function updateChunk()
- print("Updating chunk")
- print(textutils.serialise(config.currentChunk))
- if config.startDir == "s" then
- config.currentChunk[1] = config.currentChunk[1] + 1
- elseif config.startDir == "w" then
- config.currentChunk[2] = config.currentChunk[2] + 1
- elseif config.startDir == "n" then
- config.currentChunk[1] = config.currentChunk[1] - 1
- elseif config.startDir == "e" then
- config.currentChunk[2] = config.currentChunk[2] - 1
- else
- error("config.startDir is not n, e, s or w, currently is ", config.startDir)
- end
- print("to")
- print(textutils.serialise(config.currentChunk))
- saveConfig()
- end
- function checkSkips()
- if skips ~= nil and next(skips) ~= nil then
- for k,v in pairs(skips) do
- if config.currentChunk[1] == v[1] and config.currentChunk[2] == v[2] then
- updateChunk()
- break
- end
- end
- end
- end
- -- Functions used by rednet
- function goHome()
- print("go home")
- config.goingHome = true
- sendPing()
- saveConfig()
- if not config.home then
- turtleMov:goToZ(config.flyHeight, 'dig', {'computer'})
- if config.startDir == "s" or config.startDir == "n" then
- turtleMov:goToX(config.homePos, 'dig', {'computer'})
- turtleMov:goToY(config.homePos, 'dig', {'computer'})
- else
- turtleMov:goToY(config.homePos, 'dig', {'computer'})
- turtleMov:goToX(config.homePos, 'dig', {'computer'})
- end
- turtleMov:goToZ(config.homePos, 'dig', {'computer'})
- turtleMov:face(config.startDir)
- config.goingHome = false
- config.home = true
- end
- sendPing()
- saveConfig()
- end
- function goLastPos()
- local lastPost = vector.new()
- local lastDir
- local file = fs.open("data/swarm/lastPos", "r")
- lastPost.x = tonumber(file.readLine())
- lastPost.y = tonumber(file.readLine())
- lastPost.z = tonumber(file.readLine())
- lastDir = file.readLine()
- file.close()
- if lastPost.x ~= nil and lastPost.y ~= nil and lastPost.z ~= nil and lastDir ~= nil then
- turtleMov:goToZ(config.flyHeight, 'dig', {'computer'})
- if config.startDir == "s" or config.startDir == "n" then
- turtleMov:goToY(lastPost.y, 'dig', {'computer'})
- turtleMov:goToX(lastPost.x, 'dig', {'computer'})
- else
- turtleMov:goToX(lastPost.x, 'dig', {'computer'})
- turtleMov:goToY(lastPost.y, 'dig', {'computer'})
- end
- turtleMov:goToZ(lastPost.z, 'dig', {'computer'})
- turtleMov:face(lastDir)
- end
- fs.delete("data/swarm/lastPos")
- config.home = false
- config.goingHome = false
- saveConfig()
- end
- -- Save functions
- function saveConfig()
- local file = fs.open("data/swarm/config", "w")
- -- Make a hard copy..
- local hardCopy = copy(config)
- hardCopy.startChunk = textutils.serialise(hardCopy.startChunk)
- hardCopy.currentChunk = textutils.serialise(hardCopy.currentChunk)
- file.writeLine(textutils.serialize(hardCopy))
- file.close()
- end
- function saveSkip()
- local file = fs.open("data/swarm/skips", "w")
- -- Make a hard copy..
- local hardCopy = copy(skips)
- file.writeLine(textutils.serialize(skips))
- file.close()
- end
- function saveCurrentPos()
- local file = fs.open("data/swarm/lastPos", "w")
- turtleMov.pos = turtleGPS:locate(10)
- turtleMov.dir = turtleGPS:getDir()
- file.writeLine(turtleMov.pos.x)
- file.writeLine(turtleMov.pos.y)
- file.writeLine(turtleMov.pos.z)
- file.writeLine(turtleMov.dir)
- file.close()
- end
- -- hardcopy a obj.
- function copy(obj)
- if type(obj) ~= "table" then
- return obj
- end
- local res = {}
- for k, v in pairs(obj) do
- res[copy(k)] = copy(v)
- end
- return res
- end
- function sendPing()
- local pingResponse = {}
- turtleMov.pos = turtleGPS:locate(10)
- if not turtleMov.pos.x then
- tryHome()
- end
- if not rednet.isOpen("left") and not rednet.isOpen("right") then
- if peripheral.getType("right") == "modem" then
- rednet.open("right")
- elseif peripheral.getType("left") == "modem" then
- rednet.open("left")
- end
- end
- if config.goingHome then
- rednet.send(config.masterPc, "Homing", "swarmbotPing")
- elseif config.home then
- rednet.send(config.masterPc, "Home", "swarmbotPing")
- elseif not config.goingHome and stopProgram then
- rednet.send(config.masterPc, "Pause", "swarmbotPing")
- elseif not stopProgram then
- rednet.send(config.masterPc, turtleGPS:locate(10), "swarmbotPing")
- end
- local done = false
- local tries = 0
- while not done do
- pingResponse = {rednet.receive("swarmbotReceived", 5)}
- if next(pingResponse) ~= nil and tonumber(pingResponse[1]) == tonumber(config.masterPc) then
- done = true
- else
- tries = tries + 1
- if config.goingHome then
- rednet.send(config.masterPc, "Homing", "swarmbotPing")
- elseif config.home then
- rednet.send(config.masterPc, "Home", "swarmbotPing")
- elseif not config.goingHome and stopProgram then
- rednet.send(config.masterPc, "Pause", "swarmbotPing")
- elseif not stopProgram then
- rednet.send(config.masterPc, turtleGPS:locate(10), "swarmbotPing")
- end
- end
- if tries == 50 then
- if config.home == false then
- stopProgram = true
- turtleMov.pos = turtleGPS:locate(10)
- turtleMov.dir = turtleGPS:getDir()
- saveCurrentPos()
- parallel.waitForAny(stopRednetLoopHome, goHome)
- end
- done = true
- end
- sleep(0.5)
- end
- end
- -- If no GPS was found functions
- function saveTryHomeData()
- local file = fs.open("data/swarm/config", "w")
- file.writeLine(textutils.serialize(homeData))
- file.close()
- end
- function checkGps()
- turtleMov.pos = turtleGPS:locate(10)
- if turtleMov.pos.x then
- turtleMov.dir = turtleGPS:getDir()
- return true
- end
- return false
- end
- function tryHome()
- turtle.turnLeft()
- turtle.turnLeft()
- local homeData = {
- forward = 0,
- up = 0,
- }
- if not fs.exists("data/swarm/tryHome") then
- saveTryHomeData()
- else
- local file = fs.open("data/swarm/config", "r")
- local data = file.readAll()
- file.close()
- local homeData = textutils.unserialize(data)
- end
- while true do
- repeat
- if turtle.forward() then
- homeData.forward = homeData.forward + 1
- saveTryHomeData()
- else
- if turtle.up() then
- homeData.up = homeData.up + 1
- saveTryHomeData()
- else
- turtle.digUp()
- end
- end
- if checkGps() then
- goHome()
- break
- end
- until homeData.forward == 100
- if not config.goingHome then
- repeat
- if turtle.back() then
- homeData.forward = homeData.forward - 1
- saveTryHomeData()
- else
- if turtle.up() then
- homeData.up = homeData.up + 1
- saveTryHomeData()
- else
- turtle.digUp()
- end
- end
- until homeData.forward == 0
- repeat
- turtle.down()
- saveTryHomeData()
- homeData.up = homeData.up - 1
- until homeData.up == 0
- turtle.turnLeft()
- end
- sleep(1)
- end
- end
- -- Check for config data
- if fs.exists("data/swarm/config") then
- local file = fs.open("data/swarm/config", "r")
- local data = file.readAll()
- file.close()
- local configLines = textutils.unserialize(data)
- configLines.startChunk = textutils.unserialize(configLines.startChunk)
- configLines.currentChunk = textutils.unserialize(configLines.currentChunk)
- config = configLines
- else
- -- save data
- local registerInfo = register()
- config.masterPc = registerInfo.senderID
- config.startChunk = copy(registerInfo.chunk)
- config.currentChunk = copy(registerInfo.chunk)
- config.startHeight = registerInfo.startHeight
- config.parkHeight = registerInfo.parkHeight
- config.flyHeight = registerInfo.flyHeight
- config.homePos = registerInfo.homePos
- config.startDir = registerInfo.startDir
- config.maxChunks = registerInfo.maxChunks
- skips = registerInfo.skips
- os.setComputerLabel("swarmBot_" .. os.getComputerID())
- saveConfig()
- saveSkip()
- end
- if fs.exists("data/swarm/skips") then
- local file = fs.open("data/swarm/skips", "r")
- local data = file.readAll()
- file.close()
- skips = textutils.unserialize(data)
- end
- -- program
- if config.goingHome then
- stopProgram = true
- parallel.waitForAny(stopRednetLoopHome, goHome)
- elseif config.home then
- stopProgram = true
- elseif fs.exists("data/swarm/lastPos") then
- parallel.waitForAny(stopRednetLoopMine, goLastPos)
- end
- while true do
- print("Main loop started, listening for mainloop, rednetloop and pingloop")
- parallel.waitForAll(mainLoop, rednetLoop, pingLoop)
- turtleGPS:locate(10)
- turtleMov.pos = turtleGPS:locate(10)
- turtleMov.dir = turtleGPS:getDir()
- sleep(1)
- end
Add Comment
Please, Sign In to add comment