· 5 years ago · Jun 05, 2020, 02:34 PM
1--[[
2Version 3.3.3
3Recent Changes:
4 Fixed invert. Now works
5 Fixed GPS. Now works
6 Fixed bug stopping rednet from working.
7 New Internals: Made event system and consolidated mining loops
8 New Restarting Logic!
9 As long as position is recorded properly, it should always restart properly
10 New Argument logic!
11 Arguments are much more modular for me to make, and they are no longer case-sensitive. Improved items changed interface
12 New Arguments!
13 -enderChest [t/f or slot number] You can now use an enderchest! Try it out. There are directions
14 -startDown [number] The quarry will now start this many blocks down from its starting point (or up if invert). Great for getting diamonds and things from surface. Chest should still be placed on the top (or use ender chest)
15 -manualPos [xPos] [zPos] [yPos] [facing] Turtle ever gotten it's position wrong, but you don't want to reset? Use this! Check "quarry -help" for changes
16 Renamed several arguments
17 Arguments are no longer ignored if you use "-default", you just won't be prompted for anything.
18 Boolean (t/f) arguments now accept "yes" as well as "true"
19 Fixed small issue in GPS location that may have broken it.
20]]
21--Defining things
22civilTable = nil; _G.civilTable = {}; setmetatable(civilTable, {__index = _G}); setfenv(1,civilTable)
23-------Defaults for Arguments----------
24--Arguments assignable by text
25x,y,z = 3,3,3 --These are just in case tonumber fails
26inverted = false --False goes from top down, true goes from bottom up [Default false]
27rednetEnabled = false --Default rednet on or off [Default false]
28--Arguments assignable by tArgs
29dropSide = "front" --Side it will eject to when full or done [Default "front"]
30careAboutResources = true --Will not stop mining once inventory full if false [Default true]
31doCheckFuel = true --Perform fuel check [Default true]
32doRefuel = false --Whenever it comes to start location will attempt to refuel from inventory [Default false]
33invCheckFreq = 10 --Will check for inventory full every <-- moved spaces [Default 10]
34keepOpen = 1 --How many inventory slots it will attempt to keep open at all times [Default 1]
35fuelSafety = "moderate" --How much fuel it will ask for: safe, moderate, and loose [Default moderate]
36saveFile = "Civil_Quarry_Restore" --Where it saves restore data [Default "Civil_Quarry_Restore"]
37doBackup = true --If it will keep backups for session persistence [Default true]
38numberOfStacksPerRun = 8 --How many stacks (number of items) the turtle expects (on average) to have before it must dump off. Not in arguments. [Default 8]
39gpsEnabled = false -- If option is enabled, will attempt to find position via GPS api [Default false]
40gpsTimeout = 3 --The number of seconds the program will wait to get GPS coords. Not in arguments [Default 3]
41logging = true --Whether or not the turtle will log mining runs. [Default ...still deciding]
42logFolder = "Quarry_Logs" --What folder the turtle will store logs in [Default "Quarry_Logs"]
43logExtension = "" --The extension of the file (e.g. ".txt") [Default ""]
44startDown = 0 --How many blocks to start down from the top of the mine [Default 0]
45enderChestEnabled = false --Whether or not to use an ender chest [Default false]
46enderChestSlot = 16 --What slot to put the ender chest in [Default 16]
47--Standard number slots for fuel (you shouldn't care)
48fuelTable = { --Will add in this amount of fuel to requirement.
49safe = 1000,
50moderate = 200,
51loose = 0 } --Default 1000, 200, 0
52--Standard rednet channels
53channels = {
54send = os.getComputerID() ,
55receive = os.getComputerID() + 100 ,
56confirm = "Confirm"
57}
58
59local help_paragraph = [[
60Welcome!: Welcome to quarry help. Below are help entries for all parameters. Examples and tips are at the bottom.
61-Default: This will force no prompts. If you use this and nothing else, only defaults will be used.
62-dim: [length] [width] [height] This sets the dimensions for the quarry
63-invert: [t/f] If true, quarry will be inverted (go up instead of down)
64-rednet: [t/f] If true and you have a wireless modem on the turtle, will attempt to make a rednet connection for sending important information to a screen
65-restore / -resume: If your quarry stopped in the middle of its run, use this to resume at the point where the turtle was. Not guarenteed to work properly. For more accurate location finding, check out the -GPS parameter
66-doRefuel: [t/f] If true, the turtle will refuel itself with coal and planks it finds on its mining run
67-doCheckFuel: [t/f] If you for some reason don't want the program to check fuel usage, set to false. This is honestly a hold-over from when the refueling algorithm was awful...
68-chest: [side] This specifies what side the chest at the end will be on. You can say "top", "bottom", "front", "left", or "right"
69-enderChest: This one is special. If you use "-enderChest true" then it will use an enderChest in the default slot. However, you can also do "-enderChest [slot]" then it will take the ender chest from whatever slot you tell it to. Like 7... or 14... or whatever.
70-GPS: [force] If you use "-GPS" and there is a GPS network, then the turtle will record its first two positions to precisly calculate its position if it has to restart. This will only take two GPS readings
71-sendChannel: [number] This is what channel your turtle will send rednet messages on
72-receiveChannel: [number] This is what channel your turtle will receive rednet messages on
73-startY: [current Y coord] Randomly encountering bedrock? This is the parameter for you! Just give it what y coordinate you are at right now. If it is not within bedrock range, it will never say it found bedrock
74-logging: [t/f] If true, will record information about its mining run in a folder at the end of the mining run
75-doBackup: [t/f] If false, will not back up important information and cannot restore, but will not make an annoying file (Actually I don't really know why anyone would use this...)
76-saveFile: [word] This is what the backup file will be called
77-logFolder: [word] The folder that quarry logs will be stored in
78-logExtension: [word] The extension given to each quarry log (e.g. ".txt" or ".notepad" or whatever)
79-invCheckFreq: [number] This is how often the turtle will check if it has the proper amount of slots open
80-keepOpen: [number] This is the number of the slots the turtle will make sure are open. It will check every invCheckFreq blocks
81-careAboutResources: [t/f] Who cares about the materials! If set to false, it will just keep mining when its inventory is full
82-startDown: [number] If you set this, the turtle will go down this many blocks from the start before starting its quarry
83 =
84 C _ |
85 |
86 |
87 |
88 |_ _ _ _ >
89-manualPos: [xPos] [zPos] [yPos] [facing] This is for advanced use. If the server reset when the turtle was in the middle of a 100x100x100 quarry, fear not, you can now manually set the position of the turtle. yPos is always positive. The turtle's starting position is 0, 1, 1, 0. Facing is measured 0 - 3. 0 is forward, and it progresses clockwise. Example- "-manualPos 65 30 30 2"
90-help: Thats what this is :D
91Examples: Everything below is examples and tips for use
92Important Note:
93 None of the above parameters are necessary. They all have default values, and the above are just if you want to change them.
94Examples [1]:
95 Want to just start a quarry from the interface, without going through menus? It's easy! Just use some parameters. Assume you called the program "quarry." To start a 10x6x3 quarry, you just type in "quarry -dim 10 6 3 -default".
96 You just told it to start a quarry with dimensions 10x6x3, and "-default" means it won't prompt you about invert or rednet. Wasn't that easy?
97Examples [2]:
98 Okay, so you've got the basics of this now, so if you want, you can type in really long strings of stuff to make the quarry do exactly what you want. Now, say you want a 40x20x9, but you want it to go down to diamond level, and you're on the surface (at y = 64). You also want it to send rednet messages to your computer so you can see how its doing.
99Examples [2] [cont.]:
100 Oh yeah! You also want it to use an ender chest in slot 12 and restart if the server crashes. Yeah, you can do that. You would type
101 "quarry -dim 40x20x9 -invert false -startDown 45 -rednet true -enderChest 12 -restore"
102 BAM. Now you can just let that turtle do it's thing
103Tips:
104 The order of the parameters doesn't matter. "quarry -invert false -rednet true" is the same as "quarry -rednet true -invert false"
105
106 Capitalization doesn't matter. "quarry -iNVErt FALSe" does the same thing as "quarry -invert false"
107Tips [cont.]:
108 For [t/f] parameters, you can also use "yes" and "no" so "quarry -invert yes"
109
110 For [t/f] parameters, it only cares about the first letter. So you can use "quarry -invert t" or "quarry -invert y"
111Tips [cont.]:
112 If you are playing with fuel turned off, the program will automatically change settings for you so you don't have to :D
113
114 If you want, you can load this program onto a computer, and use "quarry -help" so you can have help with the parameters whenever you want.
115Internal Config:
116 At the top of this program is an internal configuration file. If there is some setup that you use all the time, you can just change the config value at the top and run "quarry -default" for a quick setup.
117
118 You can also use this if there are settings that you don't like the default value of.
119]]
120
121--Parsing help for display
122--[[The way the help table works:
123All help indexes are numbered. There is a help[i].title that contains the title,
124and the other lines are in help[i][1] - help[i][#help[i] ]
125Different lines (e.g. other than first) start with a space.
126As of now, the words are not wrapped, fix that later]]
127local help = {}
128local i = 0
129local titlePattern = ".-%:" --Find the beginning of the line, then characters, then a ":"
130local textPattern = "%:.+" --Find a ":", then characters until the end of the line
131for a in help_paragraph:gmatch("\n?.-\n") do --Matches in between newlines
132local current = string.sub(a,1,-2).."" --Concatenate Trick
133if string.sub(current,1,1) ~= " " then
134i = i + 1
135help[i] = {}
136help[i].title = string.sub(string.match(current, titlePattern),1,-2)..""
137help[i][1] = string.sub(string.match(current,textPattern) or " ",3,-1)
138elseif string.sub(current,1,1) == " " then
139table.insert(help[i], string.sub(current,2, -1).."")
140end
141end
142
143
144local supportsRednet = (peripheral.wrap("right") ~= nil)
145
146local tArgs = {...}
147--You don't care about these
148 xPos,yPos,zPos,facing,percent,mined,moved,relxPos, rowCheck, connected, isInPath, layersDone, attacked, startY
149 = 0, 1, 1, 0, 0, 0, 0, 1, "right", false, true, 1, 0, 0
150
151local totals = {cobble = 0, fuel = 0, other = 0} -- Total for display (cannot go inside function)
152local function count() --Done any time inventory dropped and at end
153slot = {} --1: Cobble 2: Fuel 3:Other
154for i=1, 16 do --[1] is type, [2] is number
155slot[i] = {}
156slot[i][2] = turtle.getItemCount(i)
157end
158slot[1][1] = 1 -- = Assumes Cobble/Main
159for i=1, 16 do --Cobble Check
160turtle.select(i)
161if turtle.compareTo(1) then
162slot[i][1] = 1
163totals.cobble = totals.cobble + slot[i][2]
164elseif turtle.refuel(0) then
165slot[i][1] = 2
166totals.fuel = totals.fuel + slot[i][2]
167else
168slot[i][1] = 3
169totals.other = totals.other + slot[i][2]
170end
171end
172turtle.select(1)
173end
174
175local getFuel = turtle.getFuelLevel --This is for cleanup at the end
176do --Common variable name...
177local flag = turtle.getFuelLevel() == "unlimited"--Unlimited screws up my calculations
178if flag then --Fuel is disabled
179 turtle.getFuelLevel = function() return math.huge end --Infinite Fuel
180end --There is no "else" because it will already return the regular getFuel
181end
182local checkFuel = turtle.getFuelLevel --Just an alias for backwards compat
183
184 -----------------------------------------------------------------
185--Input Phase
186local function screen(xPos,yPos)
187xPos, yPos = xPos or 1, yPos or 1
188term.setCursorPos(xPos,yPos); term.clear(); end
189local function screenLine(xPos,yPos)
190term.setCursorPos(xPos,yPos); term.clearLine(); end
191
192screen(1,1)
193print("----- Welcome to Quarry! -----")
194print("")
195
196local sides = {top = "top", right = "right", left = "left", bottom = "bottom", front = "front"} --Used to whitelist sides
197local changedT, tArgsWithUpper = {}, {}
198changedT.new = function(key, value) table.insert(changedT,{key, value}) end --Numeric list of lists
199local function capitalize(text) return (string.upper(string.sub(text,1,1))..string.sub(text,2,-1)) end
200for i=1, #tArgs do tArgsWithUpper[i] = tArgs[i]; tArgsWithUpper[tArgsWithUpper[i]] = i; tArgs[i] = tArgs[i]:lower(); tArgs[tArgs[i]] = i end --My signature key-value pair system, now with upper
201
202local restoreFound, restoreFoundSwitch = false --Initializing so they are in scope
203function addParam(name, displayText, formatString, forcePrompt, trigger, variableOverride) --To anyone that doesn't understand this very well, probably not your best idea to go in here.
204 if trigger == nil then trigger = true end --Defaults to being able to run
205 if not trigger then return end --This is what the trigger is for. Will not run if trigger not there
206 if restoreFoundSwitch or tArgs["-default"] then forcePrompt = false end --Don't want to prompt if these
207 local toGetText = name:lower() --Because all params are now lowered
208 local formatType = formatString:match("^%a+"):lower() or error("Format String Unknown: "..formatString) --Type of format string
209 local args = formatString:sub(({formatString:find(formatType)})[2] + 2).."" --Everything in formatString but the type and space
210 local variable = variableOverride or name --Goes first to the override for name
211 local func = loadstring("return "..variable)
212 setfenv(func,getfenv(1))
213 local originalValue = assert(func)() --This is the default value, for checking to add to changed table
214 if originalValue == nil then error("From addParam, \""..variable.."\" returned nil",2) end --I may have gotten a wrong variable name
215 local givenValue, toRet --Initializing for use
216 if tArgs["-"..toGetText] then
217 givenValue = tArgsWithUpper[tArgs["-"..toGetText]+1] --This is the value after the desired parameter
218 elseif forcePrompt then
219 write(displayText.."? ")
220 givenValue = io.read()
221 end
222 if formatType == "force" then --This is the one exception. Should return true if givenValue is nothing
223 toRet = (tArgs["-"..toGetText] and true) or false --Will return true if param exists, otherwise false
224 end
225 if not (givenValue or toRet) then return end --Don't do anything if you aren't given anything. Leave it as default, except for "force"
226 if formatType == "boolean" then --All the format strings will be basically be put through a switch statement
227 toRet = givenValue:sub(1,1):lower() == "y" or givenValue:sub(1,1):lower() == "t" --Accepts true or yes
228 if formatString == "boolean special" then
229 toRet = givenValue:sub(1,1):lower() ~= "n" and givenValue:sub(1,1):lower() ~= "f" --Accepts anything but false or no
230 end
231 elseif formatType == "string" then
232 toRet = givenValue:match("^[%w%.]+") --Basically anything not a space or control character etc
233 elseif formatType == "number" then
234 toRet = tonumber(givenValue) --Note this is a local, not the above so we don't change anything
235 if not toRet then return end --We need a number... Otherwise compare errors
236 toRet = math.abs(math.floor(toRet)) --Get proper integers
237 local startNum, endNum = formatString:match("(%d+)%-(%d+)") --Gets range of numbers
238 startNum, endNum = tonumber(startNum), tonumber(endNum)
239 if not ((toRet >= startNum) and (toRet <= endNum)) then return end --Can't use these
240 elseif formatType == "side" then
241 local exclusionTab = {} --Ignore the wizardry here. Just getting arguments without format string
242 for a in args:gmatch("%S+") do exclusionTab[a] = true end --This makes a list of the sides to not include
243 if not exclusionTab[givenValue] then toRet = sides[givenValue] end --If side is not excluded
244 elseif formatType == "list" then
245 toRet = {}
246 for a in args:gmatch("[^,]") do
247 table.insert(toRet,a)
248 end
249 elseif formatType == "force" then --Do nothing, everything is already done
250 else error("Improper formatType",2)
251 end
252 if toRet == nil then return end --Don't want to set variables to nil... That's bad
253 tempParam = toRet --This is what loadstring will see :D
254 local func = loadstring(variable.." = tempParam")
255 setfenv(func, getfenv(1))
256 func()
257 tempParam = nil --Cleanup of global
258 if toRet ~= originalValue then
259 changedT.new(displayText, tostring(toRet))
260 end
261 return toRet
262end
263
264--Check if it is a turtle
265if not(turtle or tArgs["help"] or tArgs["-help"] or tArgs["-?"] or tArgs["?"]) then
266 print("This is not a turtle, you might be looking for the \"Companion Rednet Program\" \nCheck My forum thread for that")
267 print("Press 'q' to quit, or any other key to start help ")
268 if ({os.pullEvent("char")})[2] ~= "q" then tArgs.help = true else error("",0) end
269end
270
271
272if tArgs["help"] or tArgs["-help"] or tArgs["-?"] or tArgs["?"] then
273print("You have selected help, press any key to continue"); print("Use arrow keys to naviate, q to quit"); os.pullEvent("key")
274local pos = 1
275local key = 0
276while pos <= #help and key ~= keys.q do
277if pos < 1 then pos = 1 end
278screen(1,1)
279print(help[pos].title)
280for a=1, #help[pos] do print(help[pos][a]) end
281repeat
282_, key = os.pullEvent("key")
283until key == 200 or key == 208 or key == keys.q
284if key == 200 then pos = pos - 1 end
285if key == 208 then pos = pos + 1 end
286end
287error("",0)
288end
289
290--Saving
291addParam("doBackup", "Backup Save File", "boolean")
292addParam("saveFile", "Save File Name", "string")
293
294restoreFound = fs.exists(saveFile)
295restoreFoundSwitch = (tArgs["-restore"] or tArgs["-resume"]) and restoreFound
296if restoreFoundSwitch then
297 local file = fs.open(saveFile,"r")
298 local test = file.readAll() ~= ""
299 file.close()
300 if test then
301 os.run(getfenv(1),saveFile)
302 if gpsEnabled then --If it had saved gps coordinates
303 print("Found GPS Start Coordinates")
304 local currLoc = {gps.locate(gpsTimeout)} or {}
305 if #currLoc > 0 and #gpsStartPos > 0 and #gpsSecondPos > 0 then --Cover all the different positions I'm using
306 print("GPS Position Successfully Read")
307 if currLoc[1] == gpsStartPos[1] and currLoc[3] == gpsStartPos[3] then --X coord, y coord, z coord in that order
308 xPos, yPos, zPos = 0,1,1
309 if facing ~= 0 then turnTo(0) end
310 print("Is at start")
311 else
312 if inverted then --yPos setting
313 ------------------------------------------------FIX THIS
314 end
315 local function copyTable(tab) local toRet = {}; for a, b in pairs(tab) do toRet[a] = b end; return toRet end
316 local a, b = copyTable(gpsStartPos), copyTable(gpsSecondPos) --For convenience
317 if b[3] - a[3] == -1 then--If went north (-Z)
318 a[1] = a[1] - 1 --Shift x one to west to create a "zero"
319 xPos, zPos = -currLoc[3] + a[3], currLoc[1] + -a[1]
320 elseif b[1] - a[1] == 1 then--If went east (+X)
321 a[3] = a[3] - 1 --Shift z up one to north to create a "zero"
322 xPos, zPos = currLoc[1] + -a[1], currLoc[3] + -a[3]
323 elseif b[3] - a[3] == 1 then--If went south (+Z)
324 a[1] = a[1] + 1 --Shift x one to east to create a "zero"
325 xPos, zPos = currLoc[3] + a[3], -currLoc[1] + a[3]
326 elseif b[1] - a[1] == -1 then--If went west (-X)
327 a[3] = a[3] + 1 --Shift z down one to south to create a "zero"
328 xPos, zPos = -currLoc[1] + a[1], -currLoc[3] + a[3]
329 else
330 print("Improper Coordinates")
331 print("GPS Locate Failed, Using Standard Methods") ----Maybe clean this up a bit to use flags instead.
332 end
333 end
334 print("X Pos: ",xPos)
335 print("Y Pos: ",yPos)
336 print("Z Pos: ",zPos)
337 print("Facing: ",facing)
338 else
339 print("GPS Locate Failed, Using Standard Methods")
340 end
341 print("Restore File read successfully. Starting in 3"); sleep(3)
342 end
343 else
344 fs.delete(saveFile)
345 print("Restore file was empty, sorry, aborting")
346 error("",0)
347 end
348else --If turtle is just starting
349 events = {} --This is the event queue :D
350 originalFuel = checkFuel() --For use in logging. To see how much fuel is REALLY used
351end
352
353--Dimesnions
354if tArgs["-dim"] then local num = tArgs["-dim"];
355x = tonumber(tArgs[num + 1]) or x; z = tonumber(tArgs[num + 2]) or z; y = tonumber(tArgs[num + 3]) or y
356elseif not (tArgs["-default"] or restoreFoundSwitch) then
357print("What dimensions?")
358print("")
359--This will protect from negatives, letters, and decimals
360term.write("Length? ")
361x = math.floor(math.abs(tonumber(io.read()) or x))
362term.write("Width? ")
363z = math.floor(math.abs(tonumber(io.read()) or z))
364term.write("Height? ")
365y = math.floor(math.abs(tonumber(io.read()) or y))
366changedT.new("Length",x); changedT.new("Width",z); changedT.new("Height",y)
367end
368--Invert
369addParam("invert", "Inverted","boolean", true, nil, "inverted")
370addParam("startDown","Start Down","number 1-256")
371--Inventory
372addParam("chest", "Chest Drop Side", "side front", nil, nil, "dropSide")
373addParam("enderChest","Ender Chest Enabled","boolean special", nil, nil, "enderChestEnabled") --This will accept anything (including numbers) thats not "f" or "n"
374addParam("enderChest", "Ender Chest Slot", "number 1-16", nil, nil, "enderChestSlot") --This will get the number slot if given
375--Rednet
376addParam("rednet", "Rednet Enabled","boolean",true, supportsRednet, "rednetEnabled")
377addParam("gps", "GPS Location Services", "force", nil, (not restoreFoundSwitch) and supportsRednet, "gpsEnabled" ) --Has these triggers so that does not record position if restarted.
378if gpsEnabled and not restoreFoundSwitch then
379 gpsStartPos = {gps.locate(gpsTimeout)} --Stores position in array
380 gpsEnabled = #gpsStartPos > 0 --Checks if location received properly. If not, position is not saved
381end
382addParam("sendChannel", "Rednet Send Channel", "number 1-65535", false, supportsRednet, "channels.send")
383addParam("receiveChannel","Rednet Receive Channel", "number 1-65535", false, supportsRednet, "channels.receive")
384--Fuel
385addParam("doRefuel", "Refuel from Inventory","boolean", nil, turtle.getFuelLevel() ~= math.huge) --math.huge due to my changes
386addParam("doCheckFuel", "Check Fuel", "boolean", nil, turtle.getFuelLevel() ~= math.huge)
387--Logging
388addParam("logging", "Logging", "boolean")
389addParam("logFolder", "Log Folder", "string")
390addParam("logExtension","Log Extension", "string")
391--Misc
392addParam("startY", "Start Y","number 1-256")
393addParam("invCheckFreq","Inventory Check Frequency","number 1-342")
394addParam("keepOpen", "Slots to Keep Open", "number 1-15")
395addParam("careAboutResources", "Care About Resources","boolean")
396--Manual Position
397if tArgs["-manualpos"] then --Gives current coordinates in xPos,zPos,yPos, facing
398 local a = tArgs["-manualpos"]
399 xPos, zPos, yPos, facing = tonumber(tArgs[a+1]) or xPos, tonumber(tArgs[a+2]) or zPos, tonumber(tArgs[a+3]) or yPos, tonumber(tArgs[a+4]) or facing
400 changedT.new("xPos",xPos); changedT.new("zPos",zPos); changedT.new("yPos",yPos); changedT.new("facing",facing)
401 restoreFoundSwitch = true --So it doesn't do beginning of quarry behavior
402end
403
404local function saveProgress(extras) --Session persistence
405exclusions = { modem = true, }
406if doBackup then
407local toWrite = ""
408for a,b in pairs(getfenv(1)) do
409 if not exclusions[a] then
410 --print(a ," ", b, " ", type(b)) --Debug
411 if type(b) == "string" then b = "\""..b.."\"" end
412 if type(b) == "table" then b = textutils.serialize(b) end
413 if type(b) ~= "function" then
414 toWrite = toWrite..a.." = "..tostring(b).."\n"
415 end
416 end
417end
418toWrite = toWrite.."doCheckFuel = false\n" --It has already used fuel, so calculation unnesesary
419local file
420repeat
421 file = fs.open(saveFile,"w")
422until file --WHY DOES IT SAY ATTEMPT TO INDEX NIL!!!
423file.write(toWrite)
424if type(extras) == "table" then
425 for a, b in pairs(extras) do
426 file.write(a.." = "..tostring(b))
427 end
428end
429file.close()
430end
431end
432
433local area = x*z
434local volume = x*y*z
435local lastHeight = y%3
436layers = math.ceil(y/3)
437local yMult = layers --This is basically a smart y/3 for movement
438local moveVolume = (area * yMult) --Kept for display percent
439--Calculating Needed Fuel--
440local exStack = numberOfStacksPerRun --Expected stacks of items before full
441neededFuel = yMult * x * z + --This is volume it will run through
442 (startDown + y)*(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
443 (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
444 --Original equation: x*z*y/3 + y * 2 + (x+z) * y/3 + (x + z + y) * (1/64*8)
445neededFuel = math.ceil(neededFuel)
446
447--Getting Fuel
448if doCheckFuel and checkFuel() < neededFuel then
449neededFuel = neededFuel + fuelTable[fuelSafety] --For safety
450 print("Not enough fuel")
451 print("Current: ",checkFuel()," Needed: ",neededFuel)
452 print("Starting SmartFuel...")
453 sleep(2) --So they can read everything.
454 term.clear()
455 local oneFuel, neededFuelItems
456 local currSlot = 0
457 local function output(text, x, y) --For displaying fuel
458 local currX, currY = term.getCursorPos()
459 term.setCursorPos(x,y)
460 term.clearLine()
461 term.write(text)
462 term.setCursorPos(currX,currY)
463 end
464 local function roundTo(num, target) --For stacks of fuel
465 if num >= target then return target elseif num < 0 then return 0 else return num end
466 end
467 local function updateScreen()
468 output("Welcome to SmartFuel! Now Refueling...", 1,1)
469 output("Currently taking fuel from slot "..currSlot,1,2)
470 output("Current single fuel: "..tostring(oneFuel or 0),1,3)
471 output("Current estimate of needed fuel: ",1,4)
472 output("Single Items: "..math.ceil(neededFuelItems or 0),4,5)
473 output("Stacks: "..math.ceil((neededFuelItems or 0) / 64),4,6)
474 output("Needed Fuel: "..tostring(neededFuel),1,12)
475 output("Current Fuel: "..tostring(checkFuel()),1,13)
476 end
477 while checkFuel() <= neededFuel do
478 currSlot = currSlot + 1
479 turtle.select(currSlot)
480 updateScreen()
481 while turtle.getItemCount(currSlot) == 0 do sleep(1.5) end
482 repeat
483 local previous = checkFuel()
484 turtle.refuel(1)
485 oneFuel = checkFuel() - previous
486 updateScreen()
487 until (oneFuel or 0) > 0 --Not an if to prevent errors if fuel taken out prematurely.
488 neededFuelItems = (neededFuel - checkFuel()) / oneFuel
489 turtle.refuel(math.ceil(roundTo(neededFuelItems, 64))) --Change because can only think about 64 at once.
490 if turtle.getItemCount(roundTo(currSlot + 1, 16)) == 0 then --Resets if no more fuel
491 currSlot = 0
492 end
493 neededFuelItems = (neededFuel - checkFuel()) / oneFuel
494 end
495end
496--Ender Chest Obtaining
497if enderChestEnabled then
498 while turtle.getItemCount(enderChestSlot) ~= 1 do
499 screen(1,1)
500 print("You have decided to use an Ender Chest!")
501 print("Please place one Ender Chest in slot ",enderChestSlot)
502 sleep(1)
503 end
504 print("Ender Chest in slot ",enderChestSlot, " checks out")
505 sleep(2)
506end
507--Initial Rednet Handshake
508if rednetEnabled then
509screen(1,1)
510print("Rednet is Enabled")
511print("The Channel to open is "..channels.send)
512modem = peripheral.wrap("right")
513modem.open(channels.receive)
514local i = 0
515repeat
516local id = os.startTimer(3)
517i=i+1
518print("Sending Initial Message "..i)
519modem.transmit(channels.send, channels.receive, "{ 'Initial' }")
520local message
521repeat
522local event, idCheck, channel,_,locMessage, distance = os.pullEvent()
523message = locMessage
524until (event == "timer" and idCheck == id) or (event == "modem_message" and channel == channels.receive and message == channels.confirm)
525until message == channels.confirm
526connected = true
527print("Connection Confirmed!")
528sleep(1.5)
529end
530local function biometrics(sendChannel)
531local commands = { Confirm = "Confirm" }
532local toSend = { ["x"] = x, ["y"] = (layers), ["z"] = z, --The y calc is weird...
533 ["xPos"] = xPos, ["yPos"] = yPos, ["zPos"] = zPos,
534 ["percent"] = percent, ["mined" ]= mined,
535 ["fuel"] = checkFuel(), ["moved"] = moved,
536 ["remainingBlocks"] = (volume-mined), ["ID"] = os.getComputerID(),
537 ["isInPath"] = isInPath, --Whether it is going back to start
538 ["volume"] = volume, ["area"] = area}
539modem.transmit(channels.send, channels.receive, textutils.serialize(toSend))
540id = os.startTimer(0.1)
541local event, message
542repeat
543local locEvent, idCheck, confirm, _, locMessage, distance = os.pullEvent()
544event, message = locEvent, locMessage
545until (event == "timer" and idCheck == id) or (event == "modem_message" and confirm == channels.receive)
546if event == "modem_message" then connected = true else connected = false end
547--Stuff to do for different commands
548end
549--Showing changes to settings
550screen(1,1)
551print("Your selected settings:")
552if #changedT == 0 then
553print("Completely Default")
554else
555for i=1, #changedT do
556print(changedT[i][1],": ",changedT[i][2]) --Name and Value
557end
558end
559print("\nStarting in 3"); sleep(1); print("2"); sleep(1); print("1"); sleep(1.5) --Dramatic pause at end
560
561
562
563----------------------------------------------------------------
564--Define ALL THE FUNCTIONS
565function eventAdd(...)
566 return table.insert(events,1, {...}) or true
567end
568function eventGet(pos)
569 return events[tonumber(pos) or #events]
570end
571function eventPop(pos)
572 return table.remove(events,tonumber(pos) or #events) or false --This will return value popped, tonumber returns nil if fail, so default to end
573end
574function eventRun(value, ...)
575 local argsList = {...}
576 if type(value) == "string" then
577 if value:sub(-1) ~= ")" then --So supports both "up()" and "up"
578 value = value .. "("
579 for a, b in pairs(argsList) do --Appending arguments
580 local toAppend
581 if type(b) == "table" then toAppend = textutils.serialize(b)
582 elseif type(b) == "string" then toAppend = "\""..tostring(b).."\"" --They weren't getting strings around them
583 else toAppend = tostring(b) end
584 value = value .. (toAppend or "true") .. ", "
585 end
586 if value:sub(-1) ~= "(" then --If no args, do not want to cut off
587 value = value:sub(1,-3)..""
588 end
589 value = value .. ")"
590 end
591 --print(value) --Debug
592 local func = loadstring(value)
593 setfenv(func, getfenv(1))
594 return func()
595 end
596end
597
598function runAllEvents()
599 while #events > 0 do
600 local toRun = eventGet()
601 --print(toRun[1]) --Debug
602 eventRun(unpack(toRun))
603 eventPop()
604 end
605end
606
607function display() --This is just the last screen that displays at the end
608screen(1,1)
609print("Total Blocks Mined: "..mined)
610print("Current Fuel Level: "..turtle.getFuelLevel())
611print("Cobble: "..totals.cobble)
612print("Usable Fuel: "..totals.fuel)
613print("Other: "..totals.other)
614if rednetEnabled then
615print("")
616print("Sent Stop Message")
617finalTable = {{["Mined: "] = mined}, {["Cobble: "] = totals.cobble}, {["Fuel: "] = totals.fuel},
618 {["Other: "] = totals.other}, {["Fuel: "] = checkFuel()} }
619modem.transmit(channels.send,channels.receive,"stop")
620modem.transmit(channels.send,channels.receive,textutils.serialize(finalTable))
621modem.close(channels.receive)
622end
623if doBackup then fs.delete(saveFile) end
624end
625function updateDisplay() --Runs in Mine(), display information to the screen in a certain place
626screen(1,1)
627print("Blocks Mined")
628print(mined)
629print("Percent Complete")
630print(percent.."%")
631print("Fuel")
632print(checkFuel())
633 -- screen(1,1)
634 -- print("Xpos: ")
635 -- print(xPos)
636 -- print("RelXPos: ")
637 -- print(relxPos)
638 -- print("Z Pos: ")
639 -- print(zPos)
640 -- print("Y pos: ")
641 -- print(yPos)
642if rednetEnabled then
643screenLine(1,7)
644print("Connected: "..tostring(connected))
645end
646end
647function logMiningRun(textExtension, extras) --Logging mining runs
648if logging then
649local number
650if not fs.isDir(logFolder) then
651 fs.delete(logFolder)
652 fs.makeDir(logFolder)
653 number = 1
654else
655 local i = 0
656 repeat
657 i = i + 1
658 until not fs.exists(logFolder.."/Quarry_Log_"..tostring(i)..(textExtension or ""))
659 number = i
660end
661handle = fs.open(logFolder.."/Quarry_Log_"..tostring(number)..(textExtension or ""),"w")
662local function write(...)
663 for a, b in ipairs({...}) do
664 handle.write(tostring(b))
665 end
666 handle.write("\n")
667end
668write("Welcome to the Quarry Logs!")
669write("Entry Number: ",number)
670write("Dimensions (X Z Y): ",x," ",z," ", y)
671write("Blocks Mined: ", mined)
672write(" Cobble: ", totals.cobble)
673write(" Usable Fuel: ", totals.fuel)
674write(" Other: ",totals.other)
675write("Total Fuel Used: ", (originalFuel or (neededFuel + checkFuel()))- checkFuel()) --Protect against errors with some precision
676write("Expected Fuel Use: ", neededFuel)
677handle.close()
678end
679end
680function isFull(slots)
681 slots = slots or 16
682 local numUsed = 0
683 sleep(0)
684 for i=1, 16 do
685 if turtle.getItemCount(i) > 0 then numUsed = numUsed + 1 end
686 end
687 if numUsed > slots then
688 return true
689 end
690 return false
691end
692function dig(doAdd, func)
693 doAdd = doAdd or true
694 func = func or turtle.dig
695 if func() then
696 if doAdd then
697 mined = mined + 1
698 end
699 return true
700 end
701 return false
702end
703if not inverted then --Regular functions :) I switch definitions for optimizatoin (I thinK)
704 function digUp(doAdd)
705 return dig(doAdd,turtle.digUp)
706 end
707 function digDown(doAdd)
708 return dig(doAdd,turtle.digDown)
709 end
710else
711 function digDown(doAdd)
712 return dig(doAdd,turtle.digUp)
713 end
714 function digUp(doAdd)
715 return dig(doAdd,turtle.digDown)
716 end
717end
718function relativeXCalc()
719 if rowCheck == "right" then relxPos = xPos else relxPos = (x-xPos)+1 end
720end
721function forward(doAdd)
722 if doAdd == nil then doAdd = true end
723 if turtle.forward() then
724 if doAdd then
725 moved = moved + 1
726 end
727 if facing == 0 then
728 xPos = xPos + 1
729 elseif facing == 1 then
730 zPos = zPos + 1
731 elseif facing == 2 then
732 xPos = xPos - 1
733 elseif facing == 3 then
734 zPos = zPos - 1
735 else
736 error("Function forward, facing should be 0 - 3, got "..tostring(facing),2)
737 end
738 relativeXCalc()
739 return true
740 end
741 return false
742end
743function up(sneak)
744 sneak = sneak or 1
745 if inverted and sneak == 1 then
746 down(-1)
747 else
748 while not turtle.up() do --Absolute dig, not relative
749 if not dig(true, turtle.digUp) then
750 attackUp()
751 sleep(0.5)
752 end
753 end
754 yPos = yPos - sneak --Oh! I feel so clever
755 end --This works because inverted :)
756 saveProgress()
757end
758function down(sneak)
759 sneak = sneak or 1
760 local count = 0
761 if inverted and sneak == 1 then
762 up(-1)
763 else
764 while not turtle.down() do
765 count = count + 1
766 if not dig(true, turtle.digDown) then --This is absolute dig down, not relative
767 attackDown()
768 sleep(0.2)
769 end
770 if count > 20 then bedrock() end
771 end
772 yPos = yPos + sneak
773 end
774 saveProgress()
775end
776function right(num)
777 num = num or 1
778 for i=1, num do facing = coterminal(facing+1); saveProgress(); turtle.turnRight() end
779end
780function left(num)
781 num = num or 1
782 for i=1, num do facing = coterminal(facing-1); saveProgress(); turtle.turnLeft() end
783end
784function attack(doAdd, func)
785 doAdd = doAdd or true
786 func = func or turtle.attack
787 if func() then
788 if doAdd then
789 attacked = attacked + 1
790 end
791 return true
792 end
793 return false
794end
795function attackUp(doAdd)
796 if inverted then
797 return attack(doAdd, turtle.attackDown)
798 else
799 return attack(doAdd, turtle.attackUp)
800 end
801end
802function attackDown(doAdd)
803 if inverted then
804 return attack(doAdd, turtle.attackUp)
805 else
806 return attack(doAdd, turtle.attackDown)
807 end
808end
809
810
811function mine(doDigDown, doDigUp, outOfPath,doCheckInv) -- Basic Move Forward
812if doCheckInv == nil then doCheckInv = true end
813if doDigDown == nil then doDigDown = true end
814if doDigUp == nil then doDigUp = true end
815if outOfPath == nil then outOfPath = false end
816if inverted then
817 doDigUp, doDigDown = doDigDown, doDigUp --Just Switch the two if inverted
818end
819if doRefuel and checkFuel() <= fuelTable[fuelSafety]/2 then
820 for i=1, 16 do
821 if turtle.getItemCount(i) > 0 then
822 turtle.select(i)
823 if checkFuel() < 200 + fuelTable[fuelSafety] then
824 turtle.refuel()
825 end
826 end
827 end
828end
829local count = 0
830while not forward(not outOfPath) do
831 sleep(0) --Calls coroutine.yield to prevent errors
832 count = count + 1
833 if not dig() then
834 attack()
835 end
836 if count > 10 then
837 attack()
838 sleep(0.2)
839 end
840 if count > 50 then
841 if turtle.getFuelLevel() == 0 then --Don't worry about inf fuel because I modified this function
842 saveProgress({doCheckFuel = true})
843 error("No more fuel",0)
844 elseif yPos > (startY-7) then --If it is near bedrock
845 bedrock()
846 else --Otherwise just sleep for a bit to avoid sheeps
847 sleep(1)
848 end
849 end
850end
851checkSanity() --Not kidding... This is necessary
852saveProgress(tab)
853if doDigUp then
854while turtle.detectUp() do
855 sleep(0) --Calls coroutine.yield
856 if not dig(true,turtle.digUp) then --This needs to be an absolute, because we are switching doDigUp/Down
857 attackUp()
858 count = count + 1
859 end
860 if count > 50 and yPos > (startY-7) then --Same deal with bedrock as above
861 bedrock()
862 end
863 end
864end
865if doDigDown then
866 dig(true,turtle.digDown) --This needs to be absolute as well
867end
868percent = math.ceil(moved/moveVolume*100)
869updateDisplay()
870isInPath = (not outOfPath) --For rednet
871if doCheckInv and careAboutResources then
872if moved%invCheckFreq == 0 then
873 if isFull(16-keepOpen) then dropOff() end
874end; end
875if rednetEnabled then biometrics() end
876end
877--Insanity Checking
878function checkSanity()
879 if isInPath and not (facing == 0 or facing == 2) and #events == 0 then --If mining and not facing proper direction and not in a turn
880 turnTo(0)
881 rowCheck = "right"
882 end
883 if xPos < 0 or xPos > x or zPos < 0 or zPos > z or yPos < 0 then
884 saveProgress()
885 print("Oops. Detected that quarry was outside of predefined boundaries.")
886 print("Please go to my forum thread and report this with a short description of what happened")
887 print("If you could also run \"pastebin put Civil_Quarry_Restore\" and give me that code it would be great")
888 error("",0)
889 end
890end
891
892local function fromBoolean(input) --Like a calculator
893if input then return 1 end
894return 0
895end
896local function multBoolean(first,second) --Boolean multiplication
897return (fromBoolean(first) * fromBoolean(second)) == 1
898end
899function coterminal(num, limit) --I knew this would come in handy :D
900limit = limit or 4 --This is for facing
901return math.abs((limit*fromBoolean(num < 0))-(math.abs(num)%limit))
902end
903if tArgs["-manualpos"] then
904 facing = coterminal(facing) --Done to improve support for "-manualPos"
905 if facing == 0 then rowCheck = "right" elseif facing == 2 then rowCheck = "left" end --Ditto
906 relativeXCalc() --Ditto
907end
908
909--Direction: Front = 0, Right = 1, Back = 2, Left = 3
910
911function turnTo(num)
912 num = num or facing
913 num = coterminal(num) --Prevent errors
914 local turnRight = true
915 if facing-num == 1 or facing-num == -3 then turnRight = false end --0 - 1 = -3, 1 - 0 = 1, 2 - 1 = 1
916 while facing ~= num do --The above is used to smartly turn
917 if turnRight then
918 right()
919 else
920 left()
921 end
922 end
923end
924function goto(x,z,y, toFace)
925--Will first go to desired z pos, then x pos, y pos varies
926x = x or 1; y = y or 1; z = z or 1; toFace = toFace or facing
927if yPos > y then --Will go up first if below position
928 while yPos~=y do up() end
929end
930if zPos > z then
931 turnTo(3)
932elseif zPos < z then
933 turnTo(1)
934end
935while zPos ~= z do mine(false,false,true,false) end
936if xPos > x then
937 turnTo(2)
938elseif xPos < x then
939 turnTo(0)
940end
941while xPos ~= x do mine(false,false,true,false) end
942if yPos < y then --Will go down after if above position
943 while yPos~=y do down() end
944end
945turnTo(toFace,"right")
946saveProgress()
947end
948function drop(side, final, allowSkip)
949side = sides[side] or "front" --The final number means that it will
950if final then final = 0 else final = 1 end --drop a whole stack at the end
951local allowSkip = allowSkip or (final == 0) --This will allow drop(side,t/f, rednetConnected)
952count()
953if doRefuel then
954 for i=1, 16 do
955 if slot[i][1] == 2 then
956 turtle.select(i); turtle.refuel()
957 end
958 end
959 turtle.select(1)
960end
961if side == "right" then turnTo(1) end
962if side == "left" then turnTo(3) end
963local whereDetect, whereDrop1, whereDropAll
964local _1 = slot[1][2] - final --All but one if final, all if not final
965if side == "top" then
966whereDetect = turtle.detectUp ; whereDrop = turtle.dropUp
967elseif side == "bottom" then
968whereDetect = turtle.detectDown ; whereDrop = turtle.dropDown
969else
970whereDetect = turtle.detect; whereDrop = turtle.drop
971end
972local function waitDrop(val) --This will just drop, but wait if it can't
973 val = val or 64
974 local try = 1
975 while not whereDrop(val) do
976 print("Chest Full, Try "..try)
977 try = try + 1
978 sleep(2)
979 end
980end
981repeat
982local detected = whereDetect()
983if detected then
984 waitDrop(_1)
985 for i=1, 2 do --This is so I quit flipping missing items when chests are partially filled
986 for i=2, 16 do
987 if turtle.getItemCount(i) > 0 then
988 turtle.select(i)
989 waitDrop(nil, i)
990 end
991 end
992 end
993elseif not allowSkip then
994 print("Waiting for chest placement place a chest to continue")
995 while not whereDetect() do
996 sleep(1)
997 end
998end
999until detected or allowSkip
1000if not allowSkip then totals.cobble = totals.cobble - 1 end
1001turtle.select(1)
1002end
1003function dropOff() --Not local because called in mine()
1004local currX,currZ,currY,currFacing = xPos, zPos, yPos, facing
1005if careAboutResources and not enderChestEnabled then --Regularly
1006eventAdd("goto", 1,1,currY,2) --Need this step for "-startDown"
1007eventAdd("goto(0,1,1,2)")
1008eventAdd("drop", dropSide,false)
1009eventAdd("turnTo(0)")
1010eventAdd("mine",false,false,true,false)
1011eventAdd("goto(1,1,1, 0)")
1012eventAdd("goto", 1, 1, currY, 0)
1013eventAdd("goto", currX,currZ,currY,currFacing)
1014elseif careAboutResources then --If using an enderChest
1015eventAdd("turnTo",currFacing-2)
1016eventAdd("dig",false)
1017eventAdd("turtle.select",enderChestSlot)
1018eventAdd("turtle.place")
1019eventAdd("drop","front",false)
1020eventAdd("turtle.select", enderChestSlot)
1021eventAdd("dig",false)
1022eventAdd("turnTo",currFacing)
1023eventAdd("turtle.select(1)")
1024end
1025runAllEvents()
1026return true
1027end
1028function bedrock()
1029if checkFuel() == 0 then error("No Fuel",0) end
1030local origin = {x = xPos, y = yPos, z = zPos}
1031print("Bedrock Detected")
1032if turtle.detectUp() then
1033print("Block Above")
1034local var
1035if facing == 0 then var = 2 elseif facing == 2 then var = 0 else error("Was facing left or right on bedrock") end
1036goto(xPos,zPos,yPos,var)
1037for i=1, relxPos do mine(true,true); end
1038end
1039goto(0,1,1,2)
1040drop(dropSide, true)
1041turnTo(0)
1042display()
1043print("\nFound bedrock at these coordinates: ")
1044print(origin.x," Was position in row\n",origin.z," Was row in layer\n",origin.y," Blocks down from start")
1045error("",0)
1046end
1047
1048function endOfRowTurn(startZ, wasFacing, mineFunctionTable)
1049local halfFacing = 1
1050local toFace = coterminal(wasFacing + 2) --Opposite side
1051if zPos == startZ then
1052 if facing ~= halfFacing then turnTo(halfFacing) end
1053 mine(unpack(mineFunctionTable or {}))
1054end
1055if facing ~= toFace then
1056 turnTo(toFace)
1057end
1058end
1059
1060-------------------------------------------------------------------------------------
1061--Pre-Mining Stuff dealing with session persistence
1062runAllEvents()
1063if toQuit then error("",0) end --This means that it was stopped coming for its last drop
1064
1065local doDigDown, doDigUp = (lastHeight ~= 1), (lastHeight == 0) --Used in lastHeight
1066if not restoreFoundSwitch then --Regularly
1067 --Check if it is a mining turtle
1068 if not isMiningTurtle then
1069 local a, b = turtle.dig()
1070 if a then mined = mined + 1; isMiningTurtle = true
1071 elseif b == "Nothing to dig with" then
1072 print("This is not a mining turtle. To make a mining turtle, craft me together with a diamond pickaxe")
1073 error("",0)
1074 end
1075 end
1076 mine(false,false,true) --Get into quarry by going forward one
1077 if gpsEnabled and not restoreFoundSwitch then --The initial locate is done in the arguments. This is so I can figure out what quadrant the turtle is in.
1078 gpsSecondPos = {gps.locate(gpsTimeout)} --Note: Does not run this if it has already been restarted.
1079end
1080 for i = 1, startDown do
1081 eventAdd("down") --Add a bunch of down events to get to where it needs to be.
1082 end
1083 runAllEvents()
1084 if not(y == 1 or y == 2) then down() end --Go down. If y is one or two, it doesn't need to do this.
1085else --restore found
1086 if doDigDown then digDown() end
1087 if doDigUp then digUp() end --Get blocks missed before stopped
1088end
1089--Mining Loops--------------------------------------------------------------------------
1090turtle.select(1)
1091while layersDone <= layers do -------------Height---------
1092local lastLayer = layersDone == layers --If this is the last layer
1093local secondToLastLayer = (layersDone + 1) == layers --This is for the going down at the end of a layer.
1094moved = moved + 1 --To account for the first position in row as "moved"
1095if doDigDown then digDown() end --This is because it doesn't mine first block in layer
1096if not restoreFoundSwitch then rowCheck = "right" end
1097relativeXCalc()
1098while zPos <= z do -------------Width----------
1099while relxPos < x do ------------Length---------
1100mine(not lastLayer or (doDigDown and lastLayer), not lastLayer or (doDigUp and lastLayer)) --This will be the idiom that I use for the mine function
1101end ---------------Length End-------
1102if zPos ~= z then --If not on last row of section
1103 local func
1104 if rowCheck == "right" then --Swithcing to next row
1105 func = "right"; rowCheck = "left"; else func = "left"; rowCheck = "right" end --Which way to turn
1106 eventAdd("endOfRowTurn", zPos, facing , {not lastLayer or (doDigDown and lastLayer), not lastLayer or (doDigUp and lastLayer)}) --The table is passed to the mine function
1107 runAllEvents()
1108else break
1109end
1110end ---------------Width End--------
1111eventAdd("goto",1,1,yPos,0) --Goto start of layer
1112runAllEvents()
1113if not lastLayer then --If there is another layer
1114 for i=1, 2+fromBoolean(not(lastHeight~=0 and secondToLastLayer)) do down() end --The fromBoolean stuff means that if lastheight is 1 and last and layer, will only go down two
1115end
1116layersDone = layersDone + 1
1117restoreFoundSwitch = false --This is done so that rowCheck works properly upon restore
1118end ---------------Height End-------
1119
1120eventAdd("goto",1,1,yPos,2) --Allows for startDown variable
1121eventAdd("goto",0,1,1,2)
1122
1123--Output to a chest or sit there
1124if enderChestEnabled and not turtle.detect() then
1125 eventAdd("turtle.select",enderChestSlot)
1126 eventAdd("turtle.place")
1127 eventAdd("turtle.select(1)")
1128end
1129eventAdd("drop",dropSide, true)
1130eventAdd("turnTo(0)")
1131
1132--Display was moved above to be used in bedrock function
1133eventAdd("display")
1134--Log current mining run
1135eventAdd("logMiningRun",logExtension)
1136toQuit = true --I'll use this flag to clean up
1137runAllEvents()
1138--Cleanup
1139turtle.getFuelLevel = getFuel