Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- This script is based on the code of Plorntus (http://turtlescripts.com/project/gjdh0m-Auto-multimining-bot-quarry)
- -- Custom Variables Changable.
- local port = "right"
- local timeOutOnRednet = 2
- local limitSize = 64 -- Maximum size of the quarry (64 is the recommended)
- -- DO NOT CHANGE ANYTHING BELOW
- rednet.open(port)
- -- These are XYZ values relative to the quarry. At default they will all be 0 as quarry is at 0,0
- local qu_x = 0
- local qu_y = 0
- local qu_z = -1
- -- permanent variables, do not change
- local facing = 2 -- my facing direction
- local tmove = 0 -- how many steps I moved since last refuel
- local fuelFor = 0 -- how many steps I can move with last refuel
- local doneFirstLane = false
- local currentLane = {}
- local mainbot = false
- local w,h = term.getSize()
- local text = {}
- function checkFuel (blocksNeeded)
- if turtle.getFuelLevel() < blocksNeeded then
- local moreFuel = true
- local fuelNeeded = blocksNeeded - turtle.getFuelLevel()
- while fuelNeeded > 0 do
- if turtle.refuel(1) == false then
- if takeItems("front") == false then
- return false
- end
- end
- fuelNeeded = blocksNeeded - turtle.getFuelLevel()
- end
- turtle.drop()
- fuelFor = turtle.getFuelLevel()
- tmove = 0
- return true
- else
- return true
- end
- return false
- end
- function split(sstr, pattern)
- local t = {}
- local fpat = "(.-)" .. pattern
- local last_end = 1
- local s, e, cap = sstr:find(fpat, 1)
- while s do
- if s ~= 1 or cap ~= "" then
- table.insert(t,cap)
- end
- last_end = e+1
- s, e, cap = sstr:find(fpat, last_end)
- end
- if last_end <= #sstr then
- cap = sstr:sub(last_end)
- table.insert(t, cap)
- end
- return t
- end
- -- Terminal Drawning
- function printP(str)
- table.insert(text,str)
- if table.getn(text) > h then
- table.remove(text,1)
- end
- drawFuelLevel()
- end
- function drawFuelLevel()
- term.clear()
- local fuelLevel = turtle.getFuelLevel()
- local fuel = " Fuel: " .. fuelLevel
- term.setCursorPos(w - #fuel+1, 1)
- term.write(fuel)
- local pos = " Pos:"..qu_x..","..qu_y..","..qu_z
- term.setCursorPos(w - #pos+1,2)
- term.write(pos)
- local mov = " Moved:"..tmove
- term.setCursorPos(w - #mov+1,3)
- term.write(mov)
- local ffor = " Had:"..fuelFor
- term.setCursorPos(w - #ffor+1,4)
- term.write(ffor)
- for k=table.getn(text),1,-1 do
- term.setCursorPos(1,k)
- term.write(text[k])
- end
- end
- -- Terminal Drawning end
- -- Function finds and sets up with the nearest quarry
- function setupToNearestQuarry ()
- local smallestDis = 0
- local ownerID = 0
- rednet.broadcast("CCQuarry LOCATE")
- local startedTime = os.clock()
- while (os.clock() - startedTime) <= timeOutOnRednet do
- local id, mess, dis = rednet.receive(timeOutOnRednet)
- if (mess == "CCQuarry PING") then
- if ownerID == 0 or smallestDis > dis then
- smallestDis = dis
- ownerID = id
- end
- end
- end
- if (smallestDis == 0) then
- return false
- else return ownerID end
- end
- function checkIfMainBotWithQuarry (qid)
- local setupInformation = sendAndGetResponse(qid,"SETUP","")
- if setupInformation ~= false then
- if setupInformation[3] == "MAINBOT" then
- return true
- elseif setupInformation == "SLAVE" then
- return false
- end
- else
- -- general failure
- turtle.up()
- turtle.digUp()
- turtle.up()
- endWithError("1")
- end
- end
- -- Turning functions
- function turn(direction)
- if direction == "left" or direction == "right" then
- local d = 0
- if direction == "left" then d = 1; turtle.turnLeft() else d = -1; turtle.turnRight() end
- facing = facing + d
- if (facing == -1) then facing = 3 elseif (facing == 4) then facing = 0 end
- return true
- end
- return false
- end
- -- Function turns to the specified facing location.
- function turnToN (face)
- if face == facing then return true end
- local lOrR = (facing - face + 4) % 4
- if lOrR > 2 then
- turn("left")
- elseif lOrR < 2 then
- turn("right")
- else
- turn("left")
- turn("left")
- end
- return true
- end
- function turnTo (nesw)
- if nesw == "north" then
- turnToN(0)
- elseif nesw == "south" then
- turnToN(2)
- elseif nesw == "west" then
- turnToN(1)
- elseif nesw == "east" then
- turnToN(3)
- end
- end
- -- Turning functions end
- -- Move functions
- function move (dir)
- if dir == "up" then
- if turtle.up() then
- qu_y = qu_y + 1
- tmove = tmove + 1
- drawFuelLevel()
- return true
- else
- return false
- end
- elseif dir == "down" then
- if turtle.down() then
- qu_y = qu_y - 1
- tmove = tmove + 1
- drawFuelLevel()
- return true
- else
- return false
- end
- elseif dir == "north" or dir == "south" or dir == "west" or dir == "east" then
- turnTo(dir)
- local moved = turtle.forward()
- if moved then
- tmove = tmove + 1
- drawFuelLevel()
- if dir == "north" then qu_z = qu_z + 1 elseif dir == "south" then qu_z = qu_z - 1 elseif dir == "west" then qu_x = qu_x - 1 elseif dir == "east" then qu_x = qu_x + 1 end
- return true
- else
- return false
- end
- end
- return false
- end
- function moveTo (targetX, targetZ,forever)
- local way = "west"
- if targetX > qu_x then
- way = "east"
- end
- while targetX ~= qu_x do
- if move(way) == false and forever == false then
- return false
- end
- end
- way = "south"
- if targetZ > qu_z then
- way = "north"
- end
- while targetZ ~= qu_z do
- if move(way) == false and forever == false then
- return false
- end
- end
- return true
- end
- -- Move functions end
- function doMainbotFunctions(qid)
- local lengthOfCurrentQuarry = 0
- local widthOfCurrentQuarry = 1
- -- Setting new orientation without using turn functions so we get our 0 point.
- for side = 1, 4, 1 do
- if turtle.detect() == false then
- break
- end
- turtle.turnLeft()
- if side == 4 then
- endWithError("2")
- end
- end
- facing = 0
- turnTo("east")
- while not checkFuel((limitSize * 2) + 32) do
- -- we couldn't see any fuel to get, let's wait for someone to fuel me up
- -- TODO send message to PC informing problem
- printP("Need more fuel. Add more fuel then type to continue");
- read()
- end
- -- Give extra fuel just in case!
- while move("north") do
- lengthOfCurrentQuarry = lengthOfCurrentQuarry + 1
- if (lengthOfCurrentQuarry >= limitSize) then
- break
- end
- end
- sendMessage(qid, "LENGTH", lengthOfCurrentQuarry)
- for a = 2, lengthOfCurrentQuarry, 1 do
- move("south")
- end
- while move("east") do
- widthOfCurrentQuarry = widthOfCurrentQuarry + 1
- if (widthOfCurrentQuarry >= limitSize) then
- break
- end
- end
- sendMessage(qid, "WIDTH", widthOfCurrentQuarry)
- printP("Quarry is "..lengthOfCurrentQuarry.. " long and ".. widthOfCurrentQuarry.." wide")
- for a = 2, widthOfCurrentQuarry, 1 do
- move("west")
- end
- moveTo(-1,0,true)
- turnTo("south")
- local items = checkChangedSlot({}, false)
- while takeItems("front") do end
- local changedItems = checkChangedSlot(items, true)
- moveTo(0,0,true)
- turnTo("south")
- setupNewBots(changedItems, qid)
- move("south")
- end
- function waitForBotToMove()
- while turtle.detect() do sleep(0.1) end
- return true
- end
- -- Function assumes it is positioned in the correct location
- function setupNewBots (arr, qid)
- sendMessage(qid, "STARTUP", "")
- for botSlot = 1, table.getn(arr), 1 do
- turtle.select(arr[botSlot])
- while (turtle.getItemCount(arr[botSlot]) ~= 0) do
- turtle.place()
- sendMessage(qid, "TURNONBOT","")
- waitForBotToMove()
- end
- end
- sendMessage(qid, "DONESTARTUP", "")
- end
- function endWithError (number)
- printP("Ending with error code:"..number".")
- os.exit()
- end
- -- Function assumes there will be a response... if not youre fucked!
- function sendAndGetResponse (recid, messageID, message)
- sendMessage(recid,messageID,message)
- local startedTime = os.clock()
- while (os.clock() - startedTime) <= timeOutOnRednet do
- local id, mess, dis = rednet.receive(timeOutOnRednet)
- if mess ~= nil and (id == recid or recid == 0) then
- local splitMessage = split(mess, " ")
- if (splitMessage[1] == "CCQuarry") then
- if (splitMessage[2] == messageID) then
- return splitMessage
- end
- end
- end
- end
- return false
- end
- function sendAndGetResponseNoTimeout (recid, messageID, message)
- sendMessage(recid,messageID,message)
- while true do
- local id, mess, dis = rednet.receive()
- if mess ~= nil and (id == recid or recid == 0) then
- local splitMessage = split(mess, " ")
- if splitMessage[1] == "CCQuarry" and splitMessage[2] == messageID then
- return splitMessage
- end
- end
- end
- -- I assume this will never be reached but just in case >.>
- return false
- end
- function waitForResponseNoTimeout (recid,messageID)
- while true do
- local id, mess, dis = rednet.receive()
- if mess ~= nil and (id == recid or recid == 0) then
- local splitMessage = split(mess, " ")
- if splitMessage[1] == "CCQuarry" and splitMessage[2] == messageID then
- return splitMessage
- end
- end
- end
- -- I assume this will never be reached but just in case >.>
- return false
- end
- function sendMessage (qid, messageID, message)
- rednet.send(qid,"CCQuarry "..messageID.." "..message)
- end
- -- Function returns array of the slots it placed the items from or false if could not take items
- function takeItems (direction)
- if direction ~= "up" and direction ~= "down" and direction ~= "front" then endWithError("3"); end
- local emptySlot = getNextEmptySlot()
- local checkArr = {}
- if (emptySlot ~= false) then
- turtle.select(emptySlot)
- else
- checkArr = checkChangedSlot({}, false)
- end
- local success = false
- if direction == "up" then
- success = turtle.suckUp()
- elseif direction == "down" then
- success = turtle.suckDown()
- else
- success = turtle.suck()
- end
- if success then
- if emptySlot ~= false then return {emptySlot}
- else
- return checkChangedSlot(checkArr, true)
- end
- else return false; end
- end
- -- Function gives an array of all the slots and their counts if secondCheck is false and array is just a blank array
- -- If secondCheck is true it expects the array and loops through until it finds changes. It will return an array of changed slots
- -- Useful for when you take from an inventory and it fills a slot up you can find where it put it.
- function checkChangedSlot (array, secondCheck)
- local newArr = {}
- if secondCheck == false then
- for a = 1, 16, 1 do
- newArr[a] = turtle.getItemCount(a)
- end
- return newArr
- else
- if table.getn(array) == 16 then
- for a = 1, 16, 1 do
- if array[a] ~= turtle.getItemCount(a) then
- newArr[(table.getn(newArr) + 1)] = a
- end
- end
- return newArr
- else
- printP("Array given to checkChangedSlot is not 16 in length. Cannot continue.")
- end
- end
- end
- function getNextEmptySlot ()
- for a = 1, 16, 1 do
- if turtle.getItemCount(a) == 0 then
- return a
- end
- end
- return false
- end
- function getWorkingLane (qid)
- local dd = sendAndGetResponseNoTimeout(qid, "LANE","")
- return dd
- end
- local attempedOverflow = false
- function moveQueuePlace(p)
- local didmove = true
- -- first get into the waiting lane only if we are at working lane
- if qu_y == 0 then
- didmove = move("up") and didmove
- end
- -- only try to go there if our queue position is in front
- if p < qu_z then
- didmove = moveTo(currentLane[1]-1,p,false) and didmove
- if didmove == false then
- -- we couldn't get into waiting lane, so just stay at working lane
- if qu_y == 1 and attempedOverflow == false then
- -- get into overflow lane if we were in service lane
- attempedOverflow = true
- while move("up") == false do end
- end
- -- try to get in position (in both working lane and overflow lane)
- didmove = moveTo(currentLane[1]-1,p,false)
- if didmove == false then
- -- we ran out of options, we tried on all 3 lanes, let's get out of the overflowlane if that's the case
- if qu_y == 2 then
- while move("down") == false do end
- end
- end
- end
- end
- end
- function waitToGoService (qid)
- -- ask for our position in the queue
- local resp = sendAndGetResponseNoTimeout(qid, "QUEUE", "")
- if resp[3] == "0" then
- printP("I'm off to service")
- else
- keepWaiting(qid,false)
- end
- end
- function keepWaiting (qid)
- local wait = true
- local resp
- while wait == true do
- resp = waitForResponseNoTimeout(qid,"QUEUE")
- local pos = tonumber(resp[3])
- if pos > 0 then
- if pos < qu_z then
- moveQueuePlace(pos)
- end
- else
- wait = false
- end
- end
- end
- function requestQueuePosition (qid)
- -- grab a resposonse from pc
- local resp = sendAndGetResponseNoTimeout(qid, "QUEUE", "")
- local po = tonumber(resp[3])
- if po > 0 then
- printP("I'm at "..resp[3].." in queue")
- moveQueuePlace(po)
- printP("Waiting for service")
- waitToGoService(qid)
- else
- printP("Nobody in front of me!")
- end
- attempedOverflow = false
- end
- function unload()
- -- go to pit stop
- if moveTo(0,-1,false) == false then
- move("up")
- moveTo(0,-1,true)
- end
- while move("down") == true do end
- -- unload items
- turnTo("west")
- for inv = 1, 16, 1 do
- turtle.select(inv)
- turtle.drop()
- end
- return true
- end
- function startDigging(qid)
- turtle.digDown()
- while move("down") or turtle.digDown() do end
- while qu_y ~= 0 do
- if move("up") == false then
- turtle.digUp()
- end
- end
- end
- function processLane (qid)
- local getCurrLane = ""
- if doneFirstLane == false and mainbot == true then
- -- just tell the mainbot to get the first lane
- getCurrLane = split("CCQuarry LANE 1 1"," ")
- doneFirstLane = true
- else
- getCurrLane = getWorkingLane(qid)
- end
- if getCurrLane ~= false then
- if getCurrLane[3] ~= "ENDLANE" then
- -- identify the lane where I should work
- currentLane[1] = getCurrLane[3] + 0
- currentLane[2] = getCurrLane[4] + 0
- printP("Current lane ".. currentLane[1] .. " , "..currentLane[2])
- printP("Refueling")
- -- refuel the turtle
- turnTo("east")
- checkFuel(10 + currentLane[1] * 2 + currentLane[2] * 2 + 256)
- printP("Ready, going to work")
- -- go to moving lane
- move("up")
- sendMessage(qid, "DONESERVICE", "")
- move("up")
- move("up")
- -- go tomy lane and work
- while moveTo(currentLane[1] - 1, currentLane[2] - 1,false) == false do
- turtle.dig()
- end
- move("down")
- move("down")
- startDigging(qid)
- printP("Digging done")
- -- grab my position in the queue
- requestQueuePosition(qid)
- printP("Unloading items")
- unload()
- printP("Lane completed")
- return true
- else
- return false
- end
- else
- endWithError("1")
- end
- end
- -- grab the nearest quarry
- local MasterID = setupToNearestQuarry()
- printP("Starting Up 1")
- if MasterID ~= false then
- mainbot = checkIfMainBotWithQuarry (MasterID)
- if mainbot then doMainbotFunctions(MasterID) end
- while processLane(MasterID) do end
- printP("Job finished")
- -- grab the turtle above if any
- move("up")
- move("up")
- turtle.digUp()
- turtle.suckUp()
- move("up")
- sendMessage(MasterID, "DONESERVICE", "")
- else
- endWithError("4")
- end
Add Comment
Please, Sign In to add comment