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