Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- Version 3.2.1
- Recent Changes:
- 1. Now has session persistence! Just type "quarry -restore"
- and your turtle will pick up where it left off
- 2. New Argument: startY to help stop it from getting stuck on those nasty sheep!
- 3. Most directional functions take care of invert. Exception is turtle.detect
- ]]
- --[[ToDo:
- 1. Actually get the rednet send back and forth to work
- 3. Send basic commands from receiver program e.g. Stop
- 6. Add in rednet stuff
- 7. Massive update for rednet program
- ]]
- --Defining things
- _G.civilTable = {}; civilTable = nil; setmetatable(civilTable, {__index = _G}); setfenv(1,civilTable)
- -------Defaults for Arguments----------
- --Arguments assignable by text
- x,y,z = 3,3,3 --These are just in case tonumber fails
- inverted = false --False goes from top down, true goes from bottom up [Default false]
- rednetEnabled = false --Default rednet on or off [Default false]
- --Arguments assignable by tArgs
- dropSide = "front" --Side it will eject to when full or done [Default "front"]
- careAboutResources = true --Will not stop mining once inventory full if false [Default true]
- doCheckFuel = true --Perform fuel check [Default true]
- doRefuel = false --Whenever it comes to start location will attempt to refuel from inventory [Default false]
- invCheckFreq = 10 --Will check for inventory full every <-- moved spaces [Default 10]
- keepOpen = 1 --How many inventory slots it will attempt to keep open at all times [Default 1]
- fuelSafety = "moderate" --How much fuel it will ask for: safe, moderate, and loose [Default moderate]
- saveFile = "Civil_Quarry_Restore" --Where it saves restore data [Default "Civil_Quarry_Restore"]
- doBackup = true --If it will keep backups for session persistence [Default true]
- numberOfStacksPerRun = 8 --How many stacks (number of items) the turtle expects (on average) to have before it must dump off. Not in arguments. [Default 8]
- gpsEnabled = false -- If option is enabled, will attempt to find position via GPS api [Default false]
- gpsTimeout = 3 --The number of seconds the program will wait to get GPS coords. Not in arguments [Default 3]
- logging = true --Whether or not the turtle will log mining runs. [Default ...still deciding]
- logFolder = "Quarry_Logs" --What folder the turtle will store logs in [Default "Quarry_Logs"]
- logExtension = "" --The extension of the file (e.g. ".txt") [Default ""]
- --Standard number slots for fuel (you shouldn't care)
- fuelTable = { --Will add in this amount of fuel to requirement.
- safe = 1000,
- moderate = 200,
- loose = 0 } --Default 1000, 200, 0
- --Standard rednet channels
- channels = {
- send = os.getComputerID() ,
- receive = os.getComputerID() + 100 ,
- confirm = "Confirm"
- }
- local help_paragraph = [[
- -DEFAULT: This will ignore all arguments and prompts and use defaults
- -vanilla: This will ignore all arguments except for dimensions
- -dim: [num] [num] [num] This sets the dimensions of the quarry
- -invert: [t/f] This sets whether invert is true or false
- -rednet: [t/f] This sets whether it will attempt to make a rednet connection
- -sendChannel: [num] This sets the channel the turtle will attempt to send on
- -receiveChannel: [num] This sets the channel the turtle will attempt to receive on
- -doRefuel: Changes whether or not the turtle will refuel itself with coal when fuel is low (opposite of written config)
- -doCheckFuel: Changes whether or not the turtle will check its fuel level before running (opposite of written config)
- -chest: [chest side] Changes what side turtle will output to
- -startY: [num] Tells the turtle what y coordinate it starts at, to make bedrock checking more accurate (hopefully)
- -keepOpen: [num] How many slots of the inventory turtle will try to keep open (Will then auto-empty)
- -invCheckFreq: [num] How many blocks before full inventory checks
- -saveFile: [word] Changes where the turtle saves its backup to.
- -doBackup: [t/f] Whether or not the turtle will backup its current position to a file.
- -restore: Turtle will check for a save file. If found will ignore all other arguments.
- -fuelSafety: [safe/moderate/loose] How much extra fuel the turtle will request at startup
- -GPS: Will toggle whether gps is on or not.
- You must have a valid GPS network set up for this to work. It will take its starting location from this and its first position.
- It will then store these values in its progress file in case your turtle stops for any reason.
- On startup, the turtle will calculate its current position based on a new gps locate.
- -log: Turns logging on if not already on.
- Will publish reports of mining runs to its own folder for later reading
- Smart Fueling System: As of 3.2.0, the turtle uses a new smart fueling system
- With this new system you can shift click in as many stacks of fuel as you want, and it will take stacks of fuel at a time
- This makes fueling for large jobs on new turtles much, much faster.
- Examples [1]:
- The minimum amount necessary to start a turtle automatically would be one of these two
- ---------
- quarry -dim 3 3 3 -invert false -rednet false
- ---------
- quarry -dim 3 3 3 -vanilla
- ---------
- or, if you actually wanted a 3x3x3 then
- ---------
- quarry -DEFAULT
- Examples [2]:
- If you wanted start a quarry that has
- rednet on channels 500 and 501, outputs
- to a chest below itself, is inverted,
- and has the dimesions 5x5x21, then here
- is what you would type: (Remember that
- order does not matter)
- ----------
- quarry -receiveChannel 501 -sendChannel 500 -invert true -dim 5 5 21 -chest bottom -rednet true
- Examples [2] (cont.):
- Now, this may be very long, but it is meant for people who want to make automated quarries with
- the same settings every time (or with variable setting)
- Examples [3]:
- If you are playing softcore then you
- can do
- ---------
- quarry -doCheckFuel false
- ---------
- Followed by any other arguments
- Tips:
- You don't actually have to type out "false" or "true" if you don't want. It actaully just checks if the first
- letter is "t", so you (usually) don't have to put anything at all. Putting the whole word just helps with clarity
- Internal Config:
- At the top of the program, right below the changelog is a written config. Anything not specified by arguments
- will be taken from here. If you have a quarry setup you use a lot, you could just edit the config and then
- type in the following:
- ----------
- quarry -DEFAULT
- ]]
- --Parsing help for display
- --[[The way the help table works:
- All help indexes are numbered. There is a help[i].title that contains the title,
- and the other lines are in help[i][1] - help[i][#help[i] ]
- Different lines (e.g. other than first) start with a space.
- As of now, the words are not wrapped, fix that later]]
- local help = {}
- local i = 0
- local titlePattern = ".-%:" --Find the beginning of the line, then characters, then a ":"
- local textPattern = "%:.+" --Find a ":", then characters until the end of the line
- for a in help_paragraph:gmatch("\n?.-\n") do --Matches in between newlines
- local current = string.sub(a,1,-2).."" --Concatenate Trick
- if string.sub(current,1,1) ~= " " then
- i = i + 1
- help[i] = {}
- help[i].title = string.sub(string.match(current, titlePattern),1,-2)..""
- help[i][1] = string.sub(string.match(current,textPattern) or " ",3,-1)
- elseif string.sub(current,1,1) == " " then
- table.insert(help[i], string.sub(current,2, -1).."")
- end
- end
- local supportsRednet = (peripheral.wrap("right") ~= nil)
- local tArgs = {...}
- --You don't care about these
- xPos,yPos,zPos,facing,percent,mined,moved,relxPos, rowCheck, connected, isInPath, layersDone, attacked, endRow, startY
- = 0, 1, 1, 0, 0, 0, 0, 1, "right", false, true, 1, 0, 0, 0
- local totals = {cobble = 0, fuel = 0, other = 0} -- Total for display (cannot go inside function)
- local function count() --Done any time inventory dropped and at end
- slot = {} --1: Cobble 2: Fuel 3:Other
- for i=1, 16 do --[1] is type, [2] is number
- slot[i] = {}
- slot[i][2] = turtle.getItemCount(i)
- end
- slot[1][1] = 1 -- = Assumes Cobble/Main
- for i=1, 16 do --Cobble Check
- turtle.select(i)
- if turtle.compareTo(1) then
- slot[i][1] = 1
- totals.cobble = totals.cobble + slot[i][2]
- elseif turtle.refuel(0) then
- slot[i][1] = 2
- totals.fuel = totals.fuel + slot[i][2]
- else
- slot[i][1] = 3
- totals.other = totals.other + slot[i][2]
- end
- end
- turtle.select(1)
- end
- local getFuel = turtle.getFuelLevel
- do --Common variable name...
- local flag = turtle.getFuelLevel() == "Unlimited"
- turtle.getFuelLevel = function() --Unlimited screws up my calculations
- if not flag then --Also, this may or may not screw it up for other programs that run...
- return getFuel()
- else
- return math.huge --Lol... Should work for my purposes
- end
- end
- end
- local checkFuel = turtle.getFuelLevel --Just an alias for backwards compat
- -----------------------------------------------------------------
- --Input Phase
- local function screen(xPos,yPos)
- xPos, yPos = xPos or 1, yPos or 1
- term.setCursorPos(xPos,yPos); term.clear(); end
- local function screenLine(xPos,yPos)
- term.setCursorPos(xPos,yPos); term.clearLine(); end
- screen(1,1)
- print("----- Welcome to Quarry! -----")
- print("")
- local sides = {top = "top", right = "right", left = "left", bottom = "bottom", front = "front"} --Used to whitelist sides
- local errorT = {num = "Numbers not recognized", zero = "Variable is out of range", word = "String failed assertion" }
- local changedT = {}
- changedT.new = function(key, value) changedT[#changedT+1] = {[key] = value} end
- changedT.getPair = function(i) for a, b in pairs(changedT[i]) do return a, b end end
- local function capitalize(text) return (string.upper(string.sub(text,1,1))..string.sub(text,2,-1)) end
- local function assert(condition, message, section) section = section or "[Blank]"; if condition then return condition else error("Error: "..message.."\nin section "..section, 0) end end
- local function checkNum(number, section) return assert(tonumber(number),errorT.num, section) end
- tArgs.checkStart = function(num) tArgs[tArgs[num]] = num end
- for i=1, #tArgs do tArgs.checkStart(i) end
- --Check if it is a turtle
- if not turtle then
- print("This is not a turtle, you must be looking for the \"Companion Rednet Program\" \nCheck My forum thread for that")
- print("Press 'q' to quit, or any other key to start help ")
- if ({os.pullEvent("char")})[2] ~= "q" then tArgs.help = true else error("",0) end
- end
- if tArgs["help"] or tArgs["-help"] or tArgs["-?"] or tArgs["?"] then
- print("You have selected help, press any key to continue"); print("Use arrow keys to naviate, q to quit"); os.pullEvent("key")
- local pos = 1
- local key = 0
- while pos <= #help and key ~= keys.q do
- if pos < 1 then pos = 1 end
- screen(1,1)
- print(help[pos].title)
- for a=1, #help[pos] do print(help[pos][a]) end
- repeat
- _, key = os.pullEvent("key")
- until key == 200 or key == 208 or key == keys.q
- if key == 200 then pos = pos - 1 end
- if key == 208 then pos = pos + 1 end
- end
- error("",0)
- end
- --Saving
- if tArgs["doBackup"] then doBackup = (string.lower(string.sub(tArgs[tArgs["doBackup"]+1],1,1)) ~= "f") end
- if tArgs["saveFile"] then saveFile = tArgs[tArgs["saveFile"]+1] or saveFile end
- local restoreFound = false
- if tArgs["-restore"] or tArgs["-resume"] then
- restoreFound = fs.exists(saveFile)
- if restoreFound then
- os.run(getfenv(1),saveFile)
- if gpsEnabled then --If it had saved gps coordinates
- print("Found GPS Start Coordinates")
- local currLoc = {gps.locate(gpsTimeout)}
- if #currLoc > 0 and #gpsStartPos > 0 and #gpsSecondPos > 0 then --Cover all the different positions I'm using
- print("GPS Position Successfully Read")
- if currLoc[1] == gpsStartPos[1] and currLoc[3] == gpsStartPos[3] then --X coord, y coord, z coord in that order
- xPos, yPos, zPos = 0,1,1
- if facing ~= 0 then turnTo(0) end
- print("Is at start")
- else
- if inverted then --yPos setting
- ------------------------------------------------FIX THIS
- end
- local function copyTable(tab) local toRet = {}; for a, b in pairs(tab) do toRet[a] = b end; return toRet end
- local a, b = copyTable(gpsStartPos), copyTable(gpsSecondPos) --For convenience
- if b[3] - a[3] == -1 then--If went north (-Z)
- a[1] = a[1] - 1 --Shift x one to west to create a "zero"
- xPos, zPos = -currLoc[3] + a[3], currLoc[1] + -a[1]
- elseif b[1] - a[1] == 1 then--If went east (+X)
- a[3] = a[3] - 1 --Shift z up one to north to create a "zero"
- xPos, zPos = currLoc[1] + -a[1], currLoc[3] + -a[3]
- elseif b[3] - a[3] == 1 then--If went south (+Z)
- a[1] = a[1] + 1 --Shift x one to east to create a "zero"
- xPos, zPos = currLoc[3] + a[3], -currLoc[1] + a[3]
- elseif b[1] - a[1] == -1 then--If went west (-X)
- a[3] = a[3] + 1 --Shift z down one to south to create a "zero"
- xPos, zPos = -currLoc[1] + a[1], -currLoc[3] + a[3]
- else
- print("Improper Coordinates")
- print("GPS Locate Failed, Using Standard Methods") ----Maybe clean this up a bit to use flags instead.
- end
- end
- print("X Pos: ",xPos)
- print("Y Pos: ",yPos)
- print("Z Pos: ",zPos)
- print("Facing: ",facing)
- else
- print("GPS Locate Failed, Using Standard Methods")
- end
- print("Restore File read successfully. Starting in 3"); sleep(3)
- end
- end
- else
- originalFuel = checkFuel() --For use in logging. To see how much fuel is REALLY used
- end
- if not (tArgs["-DEFAULT"] or restoreFound) then
- --Just a note, the whole error checking section here was more of an
- --experiment than anything else. If its ever changed in the future,
- --it would probably be for the better.
- local section = "Dimensions"
- --Dimesnions
- if tArgs["-dim"] then local num = tArgs["-dim"];
- x = checkNum(tArgs[num + 1],section); z = checkNum(tArgs[num + 2],section); y = checkNum(tArgs[num + 3],section)
- else
- print("What dimensions?")
- print("")
- --This will protect from negatives, letters, and decimals
- term.write("Length: ")
- x = math.floor(math.abs(tonumber(io.read()) or x))
- term.write("Width: ")
- z = math.floor(math.abs(tonumber(io.read()) or z))
- term.write("Height: ")
- y = math.floor(math.abs(tonumber(io.read()) or y))
- end
- changedT.new("x",x); changedT.new("z",z); changedT.new("y",y)
- assert(x~=0, errorT.zero, section); assert(z~=0, errorT.zero, section); assert(y~=0, errorT.zero, section)
- assert(not(x == 1 and y == 1 and z == 1) ,"1, 1, 1 dosen't work well at all, try again", section)
- if not tArgs["-vanilla"] then
- --Invert
- if tArgs["-invert"] then
- inverted = (string.lower(string.sub(tArgs[tArgs["-invert"]+1] or "",1,1)) == "t") else
- term.write("Inverted? ")
- inverted = (string.lower(string.sub(io.read(),1,1)) == "y")
- end
- changedT.new("Inverted", inverted)
- --Rednet
- if supportsRednet then
- if tArgs["-rednet"] then
- rednetEnabled = (string.lower(string.sub(tArgs[tArgs["-rednet"]+1] or "",1,1)) == "t")
- else term.write("Rednet? "); rednetEnabled = (string.lower(string.sub(io.read(),1,1)) == "y")
- if (tArgs["-GPS"] or tArgs["-gps"]) and not restoreFound and not gpsEnabled then --The not gps enabled makes it so it is toggled
- gpsStartPos = {gps.locate(gpsTimeout)} --Stores position in array
- gpsEnabled = #gpsStartPos > 0 --Checks if location received properly
- changedT.new("GPS Location Services", gpsEnabled)
- end
- changedT.new("Rednet Enabled", rednetEnabled)
- end
- if tArgs["-sendChannel"] then
- channels.send = assert(tonumber(tArgs[tArgs["-sendChannel"]+1]), errorT.num)
- assert(channels.send > 0 and channels.send < 65535, errorT.zero)
- changedT.new("Send Channel",channels.send) end
- if tArgs["-receiveChannel"] then
- channels.receive = assert(tonumber(tArgs[tArgs["-receiveChannel"]+1]), errorT.num)
- assert(channels.receive > 0 and channels.receive < 65535 and channels.receive ~= channels.send, errorT.zero)
- changedT.new("Receive Channel",channels.receive) end
- end
- --Fuel
- if tArgs["-doRefuel"] then doRefuel = not doRefuel; changedT.new("Do Refuel",doRefuel) end
- if turtle.getFuelLevel() == "unlimited" then
- doCheckFuel = false
- else
- if tArgs["-doCheckFuel"] then
- doCheckFuel = (string.lower(string.sub(tArgs[tArgs["-doCheckFuel"]+1] or "",1,1)) == "t"); changedT.new("Do Check Fuel", doCheckFuel) end
- end
- if tArgs["-chest"] then
- dropSide = sides[tArgs[tArgs["-chest"]+1]] or dropSide; changedT.new("Chest Side",dropSide) end
- if tArgs["-fuelSafety"] then local loc = tArgs[tArgs["-fuelSafety"]+1]
- if fuelTable[loc] then
- fuelSafety = loc; changedT.new("Fuel Check Safety", fuelSafety)
- end
- end
- --Logging
- logging = (tArgs["-log"] and true) or logging --The and will set it to true if value, or its original value if nil
- if logging then changedT.new("Logging",logging) end
- if tArgs["-logFolder"] then logFolder = tArgs[tArgs["-logFolder"]+1] or logFolder; changedT.new("Log Folder",logFolder) end
- if tArgs["-logExtension"] then logExtension = tArgs[tArgs["-logExtension"]+1] or logExtension; changedT.new("Log Extension",logExtension) end
- --Misc
- if tArgs["-startY"] then
- startY = math.abs(math.floor(checkNum(tArgs[tArgs["-startY"]+1],"Start Y")))
- changedT.new("Start Y Position",startY) end
- assert(startY >= 0, errorT.zero, "StartY")
- if tArgs["-invCheckFreq"] then
- invCheckFreq = math.abs(math.floor(checkNum(tArgs[tArgs["-invCheckFreq"]+1],"Inventory Check Frequency")))
- changedT.new("Inventory Check Frequency",invCheckFreq) end
- assert(invCheckFreq ~= 0, errorT.zero, "Inventory Check Frequency")
- if tArgs["-keepOpen"] then
- keepOpen = math.abs(math.floor(checkNum(tArgs[tArgs["-keepOpen"]+1],"Open Slots")))
- changedT.new("Slots to keep open", keepOpen) end
- assert(keepOpen ~= 0 and keepOpen < 16, errorT.zero, "Open Slots")
- if tArgs["-ignoreResources"] then careAboutResources = false; changedT.new("Ignore Resources?", not careAboutResources) end
- if tArgs["-saveFile"] then saveFile = tArgs[tArgs["-saveFile"]+1] changedT.new("Save File", saveFile) end
- assert(#saveFile >= 2,errorT.word, "Save File")
- end; end --First end is for vanilla, second is for DEFAULT
- local function saveProgress(extras) --Session persistence
- if doBackup then
- local file = fs.open(saveFile,"w")
- for a,b in pairs(getfenv(1)) do
- if type(b) == "string" then b = "\""..b.."\"" end
- if type(b) == "table" and a~="modem" then b = textutils.serialize(b) end
- if type(b) ~= "function" then
- file.write(a.." = "..tostring(b).."\n")
- end
- end
- file.write("doCheckFuel = false\n") --It has already used fuel, so calculation unnesesary
- if type(extras) == "table" then
- for a, b in pairs(extras) do
- file.write(a.." = "..tostring(b))
- end
- end
- file.close()
- end
- end
- local area = x*z
- local volume = x*y*z
- local lastHeight = y%3
- local dispY = y
- y = math.floor(y/3)*3
- local yMult = y/3 + math.ceil(lastHeight/2) --This is basically a smart y/3 for movement
- local moveVolume = (area * yMult) --Kept for display percent
- --Calculating Needed Fuel--
- local exStack = numberOfStacksPerRun --Expected stacks of items before full
- neededFuel = yMult * x * z + --This is volume it will run through
- dispY*(2+1/(64*exStack)) + --This is simplified and includes the y to get up times up and down + how many times it will drop stuff off
- (x+z)*(yMult + 1/(64*exStack)) --Simplified as well: It is getting to start of row plus getting to start of row how many times will drop off stuff
- --Original equation: x*z*y/3 + y * 2 + (x+z) * y/3 + (x + z + y) * (1/64*8)
- neededFuel = math.ceil(neededFuel)
- --Getting Fuel
- if doCheckFuel and checkFuel() < neededFuel then
- neededFuel = neededFuel + fuelTable[fuelSafety] --For safety
- print("Not enough fuel")
- print("Current: ",checkFuel()," Needed: ",neededFuel)
- print("Starting SmartFuel...")
- sleep(2) --So they can read everything.
- term.clear()
- local oneFuel, neededFuelItems
- local currSlot = 0
- local function output(text, x, y) --For displaying fuel
- currX, currY = term.getCursorPos()
- term.setCursorPos(x,y)
- term.clearLine()
- term.write(text)
- term.setCursorPos(currX,currY)
- end
- local function roundTo(num, target) --For stacks of fuel
- if num >= target then return target elseif num < 0 then return 0 else return num end
- end
- local function updateScreen()
- output("Welcome to SmartFuel! Now Refueling...", 1,1)
- output("Currently taking fuel from slot "..currSlot,1,2)
- output("Current single fuel: "..tostring(oneFuel or 0),1,3)
- output("Current estimate of needed fuel: ",1,4)
- output("Single Items: "..math.floor(neededFuelItems or 0),4,5)
- output("Stacks: "..math.ceil((neededFuelItems or 0) / 64),4,6)
- output("Needed Fuel: "..tostring(neededFuel),1,12)
- output("Current Fuel: "..tostring(checkFuel()),1,13)
- end
- while checkFuel() <= neededFuel do
- currSlot = currSlot + 1
- turtle.select(currSlot)
- updateScreen()
- while turtle.getItemCount(currSlot) == 0 do sleep(1.5) end
- repeat
- local previous = checkFuel()
- turtle.refuel(1)
- oneFuel = checkFuel() - previous
- updateScreen()
- until (oneFuel or 0) > 0 --Not an if to prevent errors if fuel taken out prematurely.
- neededFuelItems = (neededFuel - checkFuel()) / oneFuel
- turtle.refuel(roundTo(neededFuelItems, 64)) --Change because can only think about 64 at once.
- if turtle.getItemCount(roundTo(currSlot + 1, 16)) == 0 then --Resets if no more fuel
- currSlot = 0
- end
- end
- -- local neededFuel = moveVolume + (math.floor(volume / (64 * 8)) * (x+dispY+z)) --Standard move plus dropping off supplies
- -- --How many times come back to start| * If it were at the very far side
- -- neededFuel = neededFuel + fuelTable[fuelSafety]
- -- if neededFuel < 100 then neededFuel = 100; end
- -- if checkFuel() < neededFuel then
- -- screen(1,1)
- -- print("More Fuel Needed")
- -- print("Current Fuel: ",checkFuel()," Needed: ",neededFuel)
- -- print("Place fuel in Bottom Right")
- -- while turtle.getItemCount(16) == 0 do
- -- sleep(1)
- -- end
- -- turtle.select(16)
- -- while checkFuel() < neededFuel do
- -- if not turtle.refuel(1) then
- -- term.clearLine()
- -- print("Still too little fuel")
- -- term.clearLine()
- -- print("Insert more fuel to resume")
- -- while turtle.getItemCount(16) == 0 do
- -- sleep(1)
- -- end
- -- end
- -- local x,y = term.getCursorPos()
- -- print(checkFuel().." Fuel")
- -- term.setCursorPos(x,y)
- -- end
- -- print(checkFuel().." Units of Fuel")
- -- sleep(3)
- -- turtle.select(1)
- -- end
- end
- --Initial Rednet Handshake
- if rednetEnabled then
- screen(1,1)
- print("Rednet is Enabled")
- print("The Channel to open is "..channels.send)
- modem = peripheral.wrap("right")
- modem.open(channels.receive)
- local i = 0
- repeat
- local id = os.startTimer(3)
- i=i+1
- print("Sending Initial Message "..i)
- modem.transmit(channels.send, channels.receive, "{ 'Initial' }")
- local message
- repeat
- local event, idCheck, channel,_,locMessage, distance = os.pullEvent()
- message = locMessage
- until (event == "timer" and idCheck == id) or (event == "modem_message" and channel == channels.receive and message == channels.confirm)
- until message == channels.confirm
- connected = true
- print("Connection Confirmed!")
- sleep(1.5)
- end
- local function biometrics(sendChannel)
- local commands = { Confirm = "Confirm" }
- local toSend = { ["x"] = x, ["y"] = (y/3 + math.ceil(lastHeight/2)), ["z"] = z, --The y calc is weird...
- ["xPos"] = xPos, ["yPos"] = yPos, ["zPos"] = zPos,
- ["percent"] = percent, ["mined" ]= mined,
- ["fuel"] = checkFuel(), ["moved"] = moved,
- ["remainingBlocks"] = (volume-mined), ["ID"] = os.getComputerID(),
- ["isInPath"] = isInPath, --Whether it is going back to start
- ["volume"] = volume, ["area"] = area}
- modem.transmit(channels.send, channels.receive, textutils.serialize(toSend))
- id = os.startTimer(0.1)
- local event, message
- repeat
- local locEvent, idCheck, confirm, _, locMessage, distance = os.pullEvent()
- event, message = locEvent, locMessage
- until (event == "timer" and idCheck == id) or (event == "modem_message" and confirm == channels.receive)
- if event == "modem_message" then connected = true else connected = false end
- --Stuff to do for different commands
- end
- --Showing changes to settings
- screen(1,1)
- print("Your selected settings:")
- if #changedT == 0 then
- print("Completely Default")
- else
- for i=1, #changedT do
- local title, value = changedT.getPair(i)
- print(capitalize(title)..": ",value)
- end
- end
- print("\nStarting in 3"); sleep(1); print("2"); sleep(1); print("1"); sleep(1.5) --Dramatic pause at end
- ----------------------------------------------------------------
- --Define ALL THE FUNCTIONS
- function display() --This is just the last screen that displays at the end
- screen(1,1)
- print("Total Blocks Mined: "..mined)
- print("Current Fuel Level: "..turtle.getFuelLevel())
- print("Cobble: "..totals.cobble)
- print("Usable Fuel: "..totals.fuel)
- print("Other: "..totals.other)
- if rednetEnabled then
- print("")
- print("Sent Stop Message")
- finalTable = {{["Mined: "] = mined}, {["Cobble: "] = totals.cobble}, {["Fuel: "] = totals.fuel},
- {["Other: "] = totals.other}, {["Fuel: "] = checkFuel()} }
- modem.transmit(channels.send,channels.receive,"stop")
- modem.transmit(channels.send,channels.receive,textutils.serialize(finalTable))
- modem.close(channels.receive)
- end
- if doBackup then fs.delete(saveFile) end
- end
- function updateDisplay() --Runs in Mine(), display information to the screen in a certain place
- screen(1,1)
- print("Blocks Mined")
- print(mined)
- print("Percent Complete")
- print(percent.."%")
- print("Fuel")
- print(checkFuel())
- if rednetEnabled then
- screenLine(1,7)
- print("Connected: "..tostring(connected))
- end
- end
- function logMiningRun(textExtension, extras) --Logging mining runs
- if logging then
- local number
- if not fs.isDir(logFolder) then
- fs.delete(logFolder)
- fs.makeDir(logFolder)
- number = 1
- else
- local i = 0
- repeat
- i = i + 1
- until not fs.exists(logFolder.."/Quarry_Log_"..tostring(i)..(textExtension or ""))
- number = i
- end
- handle = fs.open(logFolder.."/Quarry_Log_"..tostring(number)..(textExtension or ""),"w")
- local function write(...)
- for a, b in ipairs({...}) do
- handle.write(tostring(b))
- end
- handle.write("\n")
- end
- write("Welcome to the Quarry Logs!")
- write("Entry Number: ",number)
- write("Dimensions (X Z Y): ",x," ",z," ", dispY)
- write("Blocks Mined: ", mined)
- write(" Cobble: ", totals.cobble)
- write(" Usable Fuel: ", totals.fuel)
- write(" Other: ",totals.other)
- write("Total Fuel Used: ", originalFuel- checkFuel())
- write("Expected Fuel Use: ", neededFuel)
- handle.close()
- end
- end
- function isFull(slots)
- slots = slots or 16
- local numUsed = 0
- sleep(0)
- for i=1, slots do
- if turtle.getItemCount(i) > 0 then numUsed = numUsed + 1 end
- end
- if numUsed >= slots then
- return true
- end
- return false
- end
- function dig(doAdd, func)
- doAdd = doAdd or true
- func = func or turtle.dig
- if func() then
- if doAdd then
- mined = mined + 1
- end
- return true
- end
- return false
- end
- function digUp(doAdd)
- return dig(doAdd,turtle.digUp)
- end
- function digDown(doAdd)
- return dig(doAdd,turtle.digDown)
- end
- function relativeXCalc()
- if rowCheck == "right" then relxPos = xPos else relxPos = (x-xPos)+1 end
- end
- function forward(doAdd)
- if doAdd == nil then doAdd = true end
- if turtle.forward() then
- if doAdd then
- moved = moved + 1
- end
- if facing == 0 then
- xPos = xPos + 1
- elseif facing == 1 then
- zPos = zPos + 1
- elseif facing == 2 then
- xPos = xPos - 1
- elseif facing == 3 then
- zPos = zPos - 1
- else
- error("Function forward, facing should be 0 - 3, got "..tostring(facing),2)
- end
- relativeXCalc()
- return true
- end
- return false
- end
- function up(sneak)
- sneak = sneak or 1
- if inverted and sneak == 1 then
- down(-1)
- else
- while not turtle.up() do
- if not digUp() then
- attackUp()
- sleep(0.5)
- end
- end
- yPos = yPos - sneak --Oh! I feel so clever
- end --This works because inverted :)
- end
- function down(sneak)
- sneak = sneak or 1
- local count = 0
- if inverted and sneak == 1 then
- up(-1)
- else
- while not turtle.down() do
- count = count + 1
- if not digDown() then
- attackDown()
- sleep(0.2)
- end
- if count > 20 then bedrock() end
- end
- yPos = yPos + sneak
- end
- end
- function right(num)
- num = num or 1
- for i=1, num do facingF(1); saveProgress(); turtle.turnRight() end
- end
- function left(num)
- num = num or 1
- for i=1, num do facingF(-1); saveProgress(); turtle.turnLeft() end
- end
- function attack(doAdd, func)
- doAdd = doAdd or true
- func = func or turtle.attack
- if func() then
- if doAdd then
- attacked = attacked + 1
- end
- return true
- end
- return false
- end
- function attackUp(doAdd)
- if inverted then
- return attack(doAdd, turtle.attackDown)
- else
- return attack(doAdd, turtle.attackUp)
- end
- end
- function attackDown(doAdd)
- if inverted then
- return attack(doAdd, turtle.attackUp)
- else
- return attack(doAdd, turtle.attackDown)
- end
- end
- function mine(doDigDown, doDigUp, outOfPath,doCheckInv) -- Basic Move Forward
- if doCheckInv == nil then doCheckInv = true end
- if doDigDown == nil then doDigDown = true end
- if doDigUp == nil then doDigUp = true end
- if outOfPath == nil then outOfPath = false end
- if inverted then
- doDigUp, doDigDown = doDigDown, doDigUp --Just switch the two if inverted
- end
- if doRefuel and checkFuel() <= fuelTable[fuelSafety]/2 then
- for i=1, 16 do
- if turtle.getItemCount(i) > 0 then
- turtle.select(i)
- if checkFuel() < 200 + fuelTable[fuelSafety] then
- turtle.refuel()
- end
- end
- end
- end
- local count = 0
- while not forward(not outOfPath) do
- sleep(0) --Calls coroutine.yield to prevent errors
- count = count + 1
- if not dig() then
- attack()
- end
- if count > 10 then
- attack()
- sleep(0.2)
- end
- if count > 50 then
- if turtle.getFuelLevel() == 0 then --Don't worry about inf fuel because I modified this function
- saveProgress({doCheckFuel = true})
- error("No more fuel",0)
- elseif yPos > (startY-7) then --If it is near bedrock
- bedrock()
- else --Otherwise just sleep for a bit to avoid sheeps
- sleep(1)
- end
- end
- end
- local tab = {} --This registers a change in the saveProgress file
- if facing == 0 then --I do this because when it restores, it always
- tab.xPos = xPos + 1-- Thinks it is one position back, for some reason
- elseif facing == 1 then-- This overwrites that.
- tab.zPos = zPos + 1
- elseif facing == 2 then
- tab.xPos = xPos - 1
- elseif facing == 3 then
- tab.zPos = zPos - 1
- end
- saveProgress(tab)
- if doDigUp then
- while turtle.detectUp() do
- sleep(0) --Calls coroutine.yield
- if not digUp() then
- attackUp()
- count = count + 1
- end
- if count > 50 and yPos > (startY-7) then --Same deal with bedrock as above
- bedrock()
- end
- end
- end
- if doDigDown then
- digDown()
- end
- percent = math.ceil(moved/moveVolume*100)
- updateDisplay()
- isInPath = (not outOfPath) --For rednet
- if doCheckInv and careAboutResources then
- if moved%invCheckFreq == 0 then
- if isFull(16-keepOpen) then dropOff() end
- end; end
- if rednetEnabled then biometrics() end
- end
- --Direction: Front = 0, Right = 1, Back = 2, Left = 3
- function facingF(num)
- facing = facing + num
- if facing > 3 then facing = 0 end
- if facing < 0 then facing = 3 end
- end
- function turnTo(num, dir)
- num = num or facing
- dir = dir or "left"
- while facing ~= num do
- if dir == "left" then
- left()
- elseif dir == "right" then
- right()
- else
- error("TurnTo: Left or Right expected, got "..tosrting(dir))
- end
- end
- end
- function goto(x,z,y, toFace)
- --Will first go to desired z pos, then x pos, y pos varies
- x = x or 1; y = y or 1; z = z or 1; toFace = toFace or facing
- gotoX,gotoY,gotoZ,gotoFacing = xPos,yPos,zPos,facing --For use in session persistence
- if yPos > y then --Will go up first if below position
- while yPos~=y do up() end
- end
- if zPos > z then
- turnTo(3)
- elseif zPos < z then
- turnTo(1)
- end
- while zPos ~= z do mine(false,false,true,false) end
- if xPos > x then
- turnTo(2)
- elseif xPos < x then
- turnTo(0)
- end
- while xPos ~= x do mine(false,false,true,false) end
- if yPos < y then --Will go down after if above position
- while yPos~=y do down() end
- end
- turnTo(toFace,"right")
- saveProgress()
- gotoX,gotoY,gotoZ,gotoFacing = nil
- end
- function drop(side, final, allowSkip)
- side = sides[side] or "front" --The final number means that it will
- if final then final = 0 else final = 1 end --drop a whole stack at the end
- local allowSkip = allowSkip or (final == 0) --This will allow drop(side,t/f, rednetConnected)
- count()
- if doRefuel then
- for i=1, 16 do
- if slot[i][1] == 2 then
- turtle.select(i); turtle.refuel()
- end
- end
- turtle.select(1)
- end
- if side == "right" then turnTo(1) end
- if side == "left" then turnTo(3) end
- local whereDetect, whereDrop1, whereDropAll
- local _1 = slot[1][2] - final --All but one if final, all if not final
- if side == "top" then
- whereDetect = turtle.detectUp ; whereDrop = turtle.dropUp
- elseif side == "bottom" then
- whereDetect = turtle.detectDown ; whereDrop = turtle.dropDown
- else
- whereDetect = turtle.detect; whereDrop = turtle.drop
- end
- local function waitDrop(val) --This will just drop, but wait if it can't
- val = val or 64
- local try = 1
- while not whereDrop(val) do
- print("Chest Full, Try "..try)
- try = try + 1
- sleep(2)
- end
- end
- repeat
- local detected = whereDetect()
- if detected then
- waitDrop(_1)
- for i=2, 16 do
- if turtle.getItemCount(i) > 0 then
- turtle.select(i)
- waitDrop()
- end
- end
- elseif not allowSkip then
- print("Waiting for chest placement place a chest to continue")
- while not whereDetect() do
- sleep(1)
- end
- end
- until detected or allowSkip
- if not allowSkip then totals.cobble = totals.cobble - 1 end
- turtle.select(1)
- turnTo(0)
- end
- function dropOff() --Not local because called in mine()
- local currX,currZ,currY,currFacing = xPos, zPos, yPos, facing
- goto(0,1,1,2)
- drop(dropSide,false)
- mine(false,false,true, false)
- goto(1,1,1, 0)
- goto(currX,currZ,currY,currFacing)
- end
- function bedrock()
- if checkFuel() == 0 then error("No Fuel",0) end
- local origin = {x = xPos, y = yPos, z = zPos}
- print("Bedrock Detected")
- if turtle.detectUp() then
- print("Block Above")
- local var
- if facing == 0 then var = 2 elseif facing == 2 then var = 0 else error("Was facing left or right on bedrock") end
- goto(xPos,zPos,yPos,var)
- for i=1, relxPos do mine(true,true); end
- end
- goto(0,1,1,2)
- drop(dropSide, true)
- display()
- print("\nFound bedrock at these coordinates: ")
- print(origin.x," Was position in row\n",origin.z," Was row in layer\n",origin.y," Blocks down from start")
- error("",0)
- end
- -------------------------------------------------------------------------------------
- --Pre-Mining Stuff dealing with session persistence
- local doDigDown, doDigUp = (lastHeight ~= 1), false --Used in lastHeight
- if not restoreFound then
- --Check if it is a mining turtle
- if not isMiningTurtle then
- local a, b = turtle.dig()
- if a then mined = mined + 1; isMiningTurtle = true
- elseif b == "Nothing to dig with" then
- print("This is not a mining turtle. To make a mining turtle, craft me together with a diamond pickaxe")
- error("",0)
- end
- end
- else digUp(); digDown() end --Get it into the quarry
- if gpsEnabled and not restoreFound then --The initial locate is done in the arguments. This is so I can figure out what quadrant the turtle is in.
- gpsSecondPos = {gps.locate(gpsTimeout)} --Note: Does not run this if it has already been restarted.
- end
- if restoreFound then
- if gotoX then
- goto(gotoX,gotoZ,gotoY,gotoFacing)
- end
- local func
- if rowCheck == "left" then func = right else func = left end
- if endRow == 1 then
- mine()
- func()
- elseif endRow == 2 then
- func()
- end
- end
- if y ~= 0 and not restoreFound then down() end
- --Mining Loops
- turtle.select(1)
- while layersDone <= y do -------------Height---------
- moved = moved + 1 --To account for the first position in row as "moved"
- if not restoreFound then rowCheck = "right" end
- relativeXCalc()
- while zPos <= z do -------------Width----------
- while relxPos < x do ------------Length---------
- mine()
- end ---------------Length End-------
- if zPos ~= z then
- local func
- if rowCheck == "right" and zPos ~= z then --Swithcing to next row
- func = right; rowCheck = "left"; else func = left; rowCheck = "right" end --Which way to turn
- func()
- endRow = 1
- mine()
- endRow = 2
- func()
- endRow = 0
- else break
- end
- end ---------------Width End--------
- goto(1,1,yPos,0)
- if yPos+1 ~= y then
- for i=1, 3 do down() end
- end
- layersDone = layersDone + 3
- restoreFound = false --This is done so that rowCheck works properly upon restore
- end ---------------Height End-------
- if lastHeight ~= 0 then ---------LAST ROW--------- (copied from above)
- moved = moved + 1 --To account for the first position in row as "moved"
- if y ~= 0 then --If the basic y == 2 or 1
- for i=1, 2 do down() end
- end
- if not restoreFound then rowCheck = "right" end
- relativeXCalc()
- while zPos <= z do -------------Width----------
- while relxPos < x do ------------Length---------
- mine(doDigDown,doDigUp)
- end ---------------Length End-------
- if zPos ~= z then
- local func
- if rowCheck == "right" and zPos ~= z then --Swithcing to next row
- func = right; rowCheck = "left"; else func = left; rowCheck = "right" end --Which way to turn
- func()
- endRow = 1
- mine(doDigDown,doDigUp)
- endRow = 2
- func()
- endRow = 0
- else break
- end
- end ---------------Width End--------
- goto(1,1,yPos,0)
- end
- if doDigDown then
- if inverted then
- digUp()
- else
- digDown()
- end
- end
- goto(0,1,1,2)
- --Output to a chest or sit there
- drop(dropSide, true)
- --Display was moved above to be used in bedrock function
- display()
- --Log current mining run
- logMiningRun(logExtension)
- --Cleanup
- turtle.getFuelLevel = getFuel
Add Comment
Please, Sign In to add comment