View difference between Paste ID: jkWNxGCn and a1Wnmhp8
SHOW: | | - or go back to the newest paste.
1
--[[ 
2-
Version 3.2.0
2+
Version 3.2.1
3
Recent Changes:
4
1. Now has session persistence! Just type "quarry -restore"
5
   and your turtle will pick up where it left off
6
2. New Argument: startY to help stop it from getting stuck on those nasty sheep!
7
3. Most directional functions take care of invert. Exception is turtle.detect
8
]]
9
--[[ToDo:
10
1. Actually get the rednet send back and forth to work
11
3. Send basic commands from receiver program e.g. Stop
12
6. Add in rednet stuff
13
7. Massive update for rednet program
14
]]
15
--Defining things
16
_G.civilTable = {}; civilTable = nil; setmetatable(civilTable, {__index = _G}); setfenv(1,civilTable)
17
-------Defaults for Arguments----------
18
--Arguments assignable by text
19
x,y,z = 3,3,3 --These are just in case tonumber fails
20
inverted = false --False goes from top down, true goes from bottom up [Default false] 
21
rednetEnabled = false --Default rednet on or off  [Default false]
22
--Arguments assignable by tArgs
23
dropSide = "front" --Side it will eject to when full or done [Default "front"]
24
careAboutResources = true --Will not stop mining once inventory full if false [Default true]
25
doCheckFuel = true --Perform fuel check [Default true]
26
doRefuel = false --Whenever it comes to start location will attempt to refuel from inventory [Default false]
27
invCheckFreq = 10 --Will check for inventory full every <-- moved spaces [Default 10]
28
keepOpen = 1 --How many inventory slots it will attempt to keep open at all times [Default 1]
29
fuelSafety = "moderate" --How much fuel it will ask for: safe, moderate, and loose [Default moderate]
30
saveFile = "Civil_Quarry_Restore" --Where it saves restore data [Default "Civil_Quarry_Restore"]
31
doBackup = true --If it will keep backups for session persistence [Default true]
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
gpsEnabled = false -- If option is enabled, will attempt to find position via GPS api [Default false]
34
gpsTimeout = 3 --The number of seconds the program will wait to get GPS coords. Not in arguments [Default 3]
35
logging = true --Whether or not the turtle will log mining runs. [Default ...still deciding]
36
logFolder = "Quarry_Logs" --What folder the turtle will store logs in [Default "Quarry_Logs"]
37
logExtension = "" --The extension of the file (e.g. ".txt") [Default ""]
38
--Standard number slots for fuel (you shouldn't care)
39
fuelTable = { --Will add in this amount of fuel to requirement.
40
safe = 1000,
41
moderate = 200,
42
loose = 0 } --Default 1000, 200, 0
43
--Standard rednet channels
44
channels = {
45
send = os.getComputerID()  ,
46
receive = os.getComputerID() + 100 ,
47
confirm = "Confirm"
48
}
49
50
local help_paragraph = [[
51
-DEFAULT: This will ignore all arguments and prompts and use defaults
52
-vanilla: This will ignore all arguments except for dimensions
53
-dim: [num] [num] [num] This sets the dimensions of the quarry
54
-invert: [t/f] This sets whether invert is true or false
55
-rednet: [t/f] This sets whether it will attempt to make a rednet connection
56
-sendChannel: [num] This sets the channel the turtle will attempt to send on
57
-receiveChannel: [num] This sets the channel the turtle will attempt to receive on
58
-doRefuel: Changes whether or not the turtle will refuel itself with coal when fuel is low (opposite of written config)
59
-doCheckFuel: Changes whether or not the turtle will check its fuel level before running (opposite of written config)
60
-chest: [chest side] Changes what side turtle will output to
61
-startY: [num] Tells the turtle what y coordinate it starts at, to make bedrock checking more accurate (hopefully)
62
-keepOpen: [num] How many slots of the inventory turtle will try to keep open (Will then auto-empty)
63
-invCheckFreq: [num] How many blocks before full inventory checks
64
-saveFile: [word] Changes where the turtle saves its backup to.
65
-doBackup: [t/f] Whether or not the turtle will backup its current position to a file.
66
-restore: Turtle will check for a save file. If found will ignore all other arguments.
67
-fuelSafety: [safe/moderate/loose] How much extra fuel the turtle will request at startup
68
-GPS: Will toggle whether gps is on or not.
69
  You must have a valid GPS network set up for this to work. It will take its starting location from this and its first position.
70
  It will then store these values in its progress file in case your turtle stops for any reason.
71
  On startup, the turtle will calculate its current position based on a new gps locate.
72
-log: Turns logging on if not already on.
73
  Will publish reports of mining runs to its own folder for later reading
74
Smart Fueling System: As of 3.2.0, the turtle uses a new smart fueling system
75
  With this new system you can shift click in as many stacks of fuel as you want, and it will take stacks of fuel at a time
76
  This makes fueling for large jobs on new turtles much, much faster.
77
Examples [1]:
78
 The minimum amount necessary to start a turtle automatically would be one of these two
79
 ---------
80
 quarry -dim 3 3 3 -invert false -rednet false
81
 ---------
82
 quarry -dim 3 3 3 -vanilla
83
 ---------
84
 or, if you actually wanted a 3x3x3 then
85
 ---------
86
 quarry -DEFAULT
87
Examples [2]: 
88
 If you wanted start a quarry that has 
89
 rednet on channels 500 and 501, outputs 
90
 to a chest below itself, is inverted,
91
 and has the dimesions 5x5x21, then here
92
 is what you would type: (Remember that
93
 order does not matter)
94
 ----------
95
 quarry -receiveChannel 501 -sendChannel 500 -invert true -dim 5 5 21 -chest bottom -rednet true
96
Examples [2] (cont.):
97
 Now, this may be very long, but it is meant for people who want to make automated quarries with
98
 the same settings every time (or with variable setting)
99
Examples [3]:
100
 If you are playing softcore then you
101
 can do
102
 ---------
103
 quarry -doCheckFuel false
104
 ---------
105
 Followed by any other arguments
106
Tips:
107
 You don't actually have to type out "false" or "true" if you don't want. It actaully just checks if the first
108
 letter is "t", so you (usually) don't have to put anything at all. Putting the whole word just helps with clarity
109
Internal Config: 
110
 At the top of the program, right below the changelog is a written config. Anything not specified by arguments
111
 will be taken from here. If you have a quarry setup you use a lot, you could just edit the config and then
112
 type in the following:
113
 ----------
114
 quarry -DEFAULT
115
]]
116
117
--Parsing help for display
118
--[[The way the help table works:
119
All help indexes are numbered. There is a help[i].title that contains the title,
120
and the other lines are in help[i][1] - help[i][#help[i] ]
121
Different lines (e.g. other than first) start with a space.
122
As of now, the words are not wrapped, fix that later]]
123
local help = {}
124
local i = 0
125
local titlePattern = ".-%:" --Find the beginning of the line, then characters, then a ":"
126
local textPattern = "%:.+" --Find a ":", then characters until the end of the line
127
for a in help_paragraph:gmatch("\n?.-\n") do --Matches in between newlines
128
local current = string.sub(a,1,-2).."" --Concatenate Trick
129
if string.sub(current,1,1) ~= " " then
130
i = i + 1
131
help[i] = {}
132
help[i].title = string.sub(string.match(current, titlePattern),1,-2)..""
133
help[i][1] = string.sub(string.match(current,textPattern) or " ",3,-1)
134
elseif string.sub(current,1,1) == " " then
135
table.insert(help[i], string.sub(current,2, -1).."")
136
end
137
end
138
139
140
local supportsRednet = (peripheral.wrap("right") ~= nil)
141
142
local tArgs = {...}
143
--You don't care about these
144
      xPos,yPos,zPos,facing,percent,mined,moved,relxPos, rowCheck, connected, isInPath, layersDone, attacked, endRow, startY
145
    = 0,   1,   1,   0,     0,      0,    0,    1,       "right",  false,     true,     1,          0,        0,      0
146
147
local totals = {cobble = 0, fuel = 0, other = 0} -- Total for display (cannot go inside function)
148
local function count() --Done any time inventory dropped and at end
149
slot = {}        --1: Cobble 2: Fuel 3:Other
150
for i=1, 16 do   --[1] is type, [2] is number
151
slot[i] = {}
152
slot[i][2] = turtle.getItemCount(i)
153
end
154
slot[1][1] = 1   -- = Assumes Cobble/Main
155
for i=1, 16 do   --Cobble Check
156
turtle.select(i)
157
if turtle.compareTo(1)  then
158
slot[i][1] = 1
159
totals.cobble = totals.cobble + slot[i][2]
160
elseif turtle.refuel(0) then
161
slot[i][1] = 2
162
totals.fuel = totals.fuel + slot[i][2]
163
else
164
slot[i][1] = 3
165
totals.other = totals.other + slot[i][2]
166
end
167
end
168
turtle.select(1)
169
end
170
171
172
do --Common variable name...
173
local flag = turtle.getFuelLevel() ~= "Unlimited"
174
turtle.getFuelLevel = function() --Unlimited screws up my calculations
175
if not flag then --Also, this may or may not screw it up for other programs that run...
176
  return getFuel()
177
else
178
  return math.huge --Lol... Should work for my purposes
179
end
180
end
181
end
182
local checkFuel = turtle.getFuelLevel --Just an alias for backwards compat
183
local getFuel = turtle.getFuelLevel
184
185
 -----------------------------------------------------------------
186
--Input Phase
187
local function screen(xPos,yPos)
188
xPos, yPos = xPos or 1, yPos or 1
189
term.setCursorPos(xPos,yPos); term.clear(); end
190
local function screenLine(xPos,yPos)
191
term.setCursorPos(xPos,yPos); term.clearLine(); end
192
193
screen(1,1)
194
print("----- Welcome to Quarry! -----")
195
print("")
196
197
local sides = {top = "top", right = "right", left = "left", bottom = "bottom", front = "front"} --Used to whitelist sides
198
local errorT = {num = "Numbers not recognized", zero = "Variable is out of range", word = "String failed assertion" }
199
local changedT = {}
200
changedT.new = function(key, value) changedT[#changedT+1] = {[key] = value} end
201
changedT.getPair = function(i) for a, b in pairs(changedT[i]) do return a, b end end
202
local function capitalize(text) return (string.upper(string.sub(text,1,1))..string.sub(text,2,-1)) end
203
local function assert(condition, message, section) section = section or "[Blank]"; if condition then return condition else error("Error: "..message.."\nin section "..section, 0) end end
204
local function checkNum(number, section) return assert(tonumber(number),errorT.num, section) end
205
tArgs.checkStart = function(num) tArgs[tArgs[num]] = num end
206
for i=1, #tArgs do tArgs.checkStart(i) end
207
208
--Check if it is a turtle
209
if not turtle then
210
  print("This is not a turtle, you must be looking for the \"Companion Rednet Program\" \nCheck My forum thread for that")
211
  print("Press 'q' to quit, or any other key to start help ")
212
  if ({os.pullEvent("char")})[2] ~= "q" then tArgs.help = true else error("",0) end
213
end
214
215
216
if tArgs["help"] or tArgs["-help"] or tArgs["-?"] or tArgs["?"] then
217
print("You have selected help, press any key to continue"); print("Use arrow keys to naviate, q to quit"); os.pullEvent("key")
218
local pos = 1
219
local key = 0
220
while pos <= #help and key ~= keys.q do
221
if pos < 1 then pos = 1 end
222
screen(1,1) 
223
print(help[pos].title)
224
for a=1, #help[pos] do print(help[pos][a]) end
225
repeat
226
_, key = os.pullEvent("key")
227
until key == 200 or key == 208 or key == keys.q
228
if key == 200 then pos = pos - 1 end
229
if key == 208 then pos = pos + 1 end
230
end
231
error("",0)
232
end
233
234
--Saving
235
if tArgs["doBackup"] then doBackup = (string.lower(string.sub(tArgs[tArgs["doBackup"]+1],1,1)) ~= "f") end
236
if tArgs["saveFile"] then saveFile = tArgs[tArgs["saveFile"]+1] or saveFile end
237
238
local restoreFound = false
239
if tArgs["-restore"] or tArgs["-resume"] then
240
restoreFound = fs.exists(saveFile)
241
if restoreFound then
242
os.run(getfenv(1),saveFile)
243
if gpsEnabled then --If it had saved gps coordinates
244
  print("Found GPS Start Coordinates") 
245
  local currLoc = {gps.locate(gpsTimeout)}
246
  if #currLoc > 0 and #gpsStartPos > 0 and #gpsSecondPos > 0 then --Cover all the different positions I'm using
247
    print("GPS Position Successfully Read")
248
    if currLoc[1] == gpsStartPos[1] and currLoc[3] == gpsStartPos[3] then --X coord, y coord, z coord in that order
249
      xPos, yPos, zPos = 0,1,1
250
      if facing ~= 0 then turnTo(0) end
251
      print("Is at start")
252
    else
253
      if inverted then --yPos setting
254
      ------------------------------------------------FIX THIS
255
      end
256
      local function copyTable(tab) local toRet = {}; for a, b in pairs(tab) do toRet[a] = b end; return toRet end
257
      local a, b = copyTable(gpsStartPos), copyTable(gpsSecondPos) --For convenience
258
      if b[3] - a[3] == -1 then--If went north (-Z)
259
        a[1] = a[1] - 1 --Shift x one to west to create a "zero"
260
        xPos, zPos = -currLoc[3] + a[3], currLoc[1] + -a[1]
261
      elseif b[1] - a[1] == 1 then--If went east (+X)
262
        a[3] = a[3] - 1 --Shift z up one to north to create a "zero"
263
        xPos, zPos = currLoc[1] + -a[1], currLoc[3] + -a[3]
264
      elseif b[3] - a[3] == 1 then--If went south (+Z)
265
        a[1] = a[1] + 1 --Shift x one to east to create a "zero"
266
        xPos, zPos = currLoc[3] + a[3], -currLoc[1] + a[3]
267
      elseif b[1] - a[1] == -1 then--If went west (-X)
268
        a[3] = a[3] + 1 --Shift z down one to south to create a "zero"
269
        xPos, zPos = -currLoc[1] + a[1], -currLoc[3] + a[3]
270
      else
271
        print("Improper Coordinates")
272
        print("GPS Locate Failed, Using Standard Methods")        ----Maybe clean this up a bit to use flags instead.
273
      end  
274
    end
275
    print("X Pos: ",xPos)
276
    print("Y Pos: ",yPos)
277
    print("Z Pos: ",zPos)
278
    print("Facing: ",facing)
279
  else
280
    print("GPS Locate Failed, Using Standard Methods")
281
  end    
282
print("Restore File read successfully. Starting in 3"); sleep(3)
283
end
284
end
285
else
286
  originalFuel = checkFuel() --For use in logging. To see how much fuel is REALLY used
287
end
288
289
if not (tArgs["-DEFAULT"] or restoreFound) then 
290
  --Just a note, the whole error checking section here was more of an
291
  --experiment than anything else. If its ever changed in the future,
292
  --it would probably be for the better.
293
local section = "Dimensions"
294
--Dimesnions
295
if tArgs["-dim"] then local num = tArgs["-dim"];
296
x = checkNum(tArgs[num + 1],section); z = checkNum(tArgs[num + 2],section); y = checkNum(tArgs[num + 3],section)
297
else
298
print("What dimensions?")
299
print("")
300
--This will protect from negatives, letters, and decimals
301
term.write("Length: ")
302
x = math.floor(math.abs(tonumber(io.read()) or x))
303
term.write("Width: ")
304
z = math.floor(math.abs(tonumber(io.read()) or z))
305
term.write("Height: ")
306
y = math.floor(math.abs(tonumber(io.read()) or y))
307
end
308
changedT.new("x",x); changedT.new("z",z); changedT.new("y",y)
309
assert(x~=0, errorT.zero, section); assert(z~=0, errorT.zero, section); assert(y~=0, errorT.zero, section)
310
assert(not(x == 1 and y == 1 and z == 1) ,"1, 1, 1 dosen't work well at all, try again", section)
311
if not tArgs["-vanilla"] then
312
--Invert
313
if tArgs["-invert"] then
314
inverted = (string.lower(string.sub(tArgs[tArgs["-invert"]+1] or "",1,1)) == "t") else
315
term.write("Inverted? ")
316
inverted = (string.lower(string.sub(io.read(),1,1)) == "y")
317
end
318
changedT.new("Inverted", inverted)
319
--Rednet
320
if supportsRednet then
321
if tArgs["-rednet"] then 
322
rednetEnabled = (string.lower(string.sub(tArgs[tArgs["-rednet"]+1] or "",1,1)) == "t")
323
else term.write("Rednet? "); rednetEnabled = (string.lower(string.sub(io.read(),1,1)) == "y")
324
if (tArgs["-GPS"] or tArgs["-gps"]) and not restoreFound and not gpsEnabled then --The not gps enabled makes it so it is toggled
325
gpsStartPos = {gps.locate(gpsTimeout)} --Stores position in array
326
gpsEnabled = #gpsStartPos > 0 --Checks if location received properly
327
changedT.new("GPS Location Services", gpsEnabled)
328
end
329
changedT.new("Rednet Enabled", rednetEnabled)
330
end
331
if tArgs["-sendChannel"] then
332
channels.send = assert(tonumber(tArgs[tArgs["-sendChannel"]+1]), errorT.num)
333
assert(channels.send > 0 and channels.send < 65535, errorT.zero)
334
changedT.new("Send Channel",channels.send) end
335
if tArgs["-receiveChannel"] then
336
channels.receive = assert(tonumber(tArgs[tArgs["-receiveChannel"]+1]), errorT.num)
337
assert(channels.receive > 0 and channels.receive < 65535 and channels.receive ~= channels.send, errorT.zero)
338
changedT.new("Receive Channel",channels.receive) end
339
end
340
--Fuel
341
if tArgs["-doRefuel"] then doRefuel = not doRefuel; changedT.new("Do Refuel",doRefuel) end
342
if turtle.getFuelLevel() == "unlimited" then
343
  doCheckFuel = false
344
else
345
  if tArgs["-doCheckFuel"] then
346
  doCheckFuel = (string.lower(string.sub(tArgs[tArgs["-doCheckFuel"]+1] or "",1,1)) == "t"); changedT.new("Do Check Fuel", doCheckFuel) end
347
end
348
if tArgs["-chest"] then
349
dropSide = sides[tArgs[tArgs["-chest"]+1]] or dropSide; changedT.new("Chest Side",dropSide) end
350
if tArgs["-fuelSafety"] then local loc = tArgs[tArgs["-fuelSafety"]+1]
351
  if fuelTable[loc] then
352
    fuelSafety = loc; changedT.new("Fuel Check Safety", fuelSafety)
353
  end
354
end
355
--Logging
356
logging = (tArgs["-log"] and true) or logging --The and will set it to true if value, or its original value if nil
357
if logging then changedT.new("Logging",logging) end
358
if tArgs["-logFolder"] then logFolder = tArgs[tArgs["-logFolder"]+1] or logFolder; changedT.new("Log Folder",logFolder) end
359
if tArgs["-logExtension"] then logExtension = tArgs[tArgs["-logExtension"]+1] or logExtension; changedT.new("Log Extension",logExtension) end
360
--Misc
361
if tArgs["-startY"] then
362
startY = math.abs(math.floor(checkNum(tArgs[tArgs["-startY"]+1],"Start Y")))
363
changedT.new("Start Y Position",startY) end
364
assert(startY >= 0, errorT.zero, "StartY")
365
if tArgs["-invCheckFreq"] then
366
invCheckFreq = math.abs(math.floor(checkNum(tArgs[tArgs["-invCheckFreq"]+1],"Inventory Check Frequency")))
367
changedT.new("Inventory Check Frequency",invCheckFreq) end
368
assert(invCheckFreq ~= 0, errorT.zero, "Inventory Check Frequency")
369
if tArgs["-keepOpen"] then
370
keepOpen = math.abs(math.floor(checkNum(tArgs[tArgs["-keepOpen"]+1],"Open Slots")))
371
changedT.new("Slots to keep open", keepOpen) end
372
assert(keepOpen ~= 0 and keepOpen < 16, errorT.zero, "Open Slots")
373
if tArgs["-ignoreResources"] then careAboutResources = false; changedT.new("Ignore Resources?", not careAboutResources) end
374
if tArgs["-saveFile"] then saveFile = tArgs[tArgs["-saveFile"]+1] changedT.new("Save File", saveFile) end
375
assert(#saveFile >= 2,errorT.word, "Save File")
376
end; end --First end is for vanilla, second is for DEFAULT
377
378
local function saveProgress(extras) --Session persistence
379
if doBackup then
380
local file = fs.open(saveFile,"w")
381
for a,b in pairs(getfenv(1)) do
382
if type(b) == "string" then b = "\""..b.."\"" end
383
if type(b) == "table" and a~="modem" then b = textutils.serialize(b) end
384
if type(b) ~= "function" then
385
file.write(a.." = "..tostring(b).."\n")
386
end
387
end
388
file.write("doCheckFuel = false\n") --It has already used fuel, so calculation unnesesary
389
if type(extras) == "table" then
390
  for a, b in pairs(extras) do
391
    file.write(a.." = "..tostring(b))
392
  end
393
end
394
file.close()
395
end
396
end
397
398
local area = x*z
399
local volume = x*y*z
400
local lastHeight = y%3
401
local dispY = y
402
y = math.floor(y/3)*3
403
local yMult = y/3 + math.ceil(lastHeight/2) --This is basically a smart y/3 for movement
404
local moveVolume = (area * yMult) --Kept for display percent
405
--Calculating Needed Fuel--
406
local exStack = numberOfStacksPerRun --Expected stacks of items before full
407
neededFuel = yMult * x * z + --This is volume it will run through
408
      dispY*(2+1/(64*exStack)) + --This is simplified and includes the y to get up times up and down + how many times it will drop stuff off
409
      (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
410
      --Original equation: x*z*y/3 + y * 2 + (x+z) * y/3 + (x + z + y) * (1/64*8)
411
neededFuel = math.ceil(neededFuel)
412
413
--Getting Fuel
414
if doCheckFuel and checkFuel() < neededFuel then
415
neededFuel = neededFuel + fuelTable[fuelSafety] --For safety
416
  print("Not enough fuel")
417
  print("Current: ",checkFuel()," Needed: ",neededFuel)
418
  print("Starting SmartFuel")
419
  sleep(1) --So they can read everything.
420
  term.clear()
421
  local oneFuel, neededFuelItems
422
  local currSlot = 0
423
  local function output(text, x, y) --For displaying fuel
424
    currX, currY = term.getCursorPos()
425
    term.setCursorPos(x,y)
426
    term.clearLine()
427
    term.write(text)
428
    term.setCursorPos(currX,currY)
429
    end
430
  local function roundTo(num, target) --For stacks of fuel
431
    if num >= target then return target else return num end
432
  end
433
  local function updateScreen()
434
    output("Welcome to SmartFuel! Now Refueling...", 1,1)
435
    output("Currently taking fuel from slot "..currSlot,1,2)
436
    output("Current single fuel: "..tostring(oneFuel or 0),1,3)
437
    output("Current estimate of needed fuel: ",1,4)
438
    output("Single Items: "..math.floor(neededFuelItems or 0),4,5)
439
    output("Stacks:       "..math.ceil((neededFuelItems or 0) / 64),4,6)
440
    output("Needed Fuel: "..tostring(neededFuel),1,12)
441
    output("Current Fuel: "..tostring(checkFuel()),1,13)
442
  end
443
  while checkFuel() <= neededFuel do
444
    currSlot = currSlot + 1
445
    turtle.select(currSlot)
446
    updateScreen()
447
    while turtle.getItemCount(currSlot) == 0 do sleep(1.5) end
448
    repeat
449
      local previous = checkFuel()
450
      turtle.refuel(1)
451
      oneFuel = checkFuel() - previous
452
      updateScreen()
453
    until (oneFuel or 0) > 0 --Not an if to prevent errors if fuel taken out prematurely.
454
    neededFuelItems = (neededFuel - checkFuel()) / oneFuel
455
    turtle.refuel(roundTo(neededFuelItems, 64)) --Change because can only think about 64 at once.
456
    if turtle.getItemCount(roundTo(currSlot + 1, 16)) == 0 then --Resets if no more fuel
457
      currSlot = 0
458
    end
459
  end
460
-- local neededFuel = moveVolume + (math.floor(volume / (64 * 8)) * (x+dispY+z)) --Standard move plus dropping off supplies
461
                             -- --How many times come back to start| * If it were at the very far side
462
-- neededFuel = neededFuel + fuelTable[fuelSafety]
463
-- if neededFuel < 100 then neededFuel = 100; end
464
-- if checkFuel() < neededFuel then
465
-- screen(1,1)
466
-- print("More Fuel Needed")
467
-- print("Current Fuel: ",checkFuel()," Needed: ",neededFuel)
468
-- print("Place fuel in Bottom Right")
469
-- while turtle.getItemCount(16) == 0 do
470
  -- sleep(1)
471
-- end
472
-- turtle.select(16)
473
-- while checkFuel() < neededFuel do
474
-- if not turtle.refuel(1) then
475
-- term.clearLine()
476
-- print("Still too little fuel")
477
-- term.clearLine()
478
-- print("Insert more fuel to resume")
479
-- while turtle.getItemCount(16) == 0 do
480
  -- sleep(1)
481
-- end
482
-- end
483
-- local x,y = term.getCursorPos()
484
-- print(checkFuel().." Fuel")
485
-- term.setCursorPos(x,y)
486
-- end
487
-- print(checkFuel().." Units of Fuel")
488
-- sleep(3)
489
-- turtle.select(1)
490
-- end
491
end
492
--Initial Rednet Handshake
493
if rednetEnabled then
494
screen(1,1)
495
print("Rednet is Enabled")
496
print("The Channel to open is "..channels.send)
497
modem = peripheral.wrap("right")
498
modem.open(channels.receive)
499
local i = 0
500
repeat
501
local id = os.startTimer(3)
502
i=i+1
503
print("Sending Initial Message "..i)
504
modem.transmit(channels.send, channels.receive, "{ 'Initial' }")
505
local message
506
repeat
507
local event, idCheck, channel,_,locMessage, distance = os.pullEvent()
508
message = locMessage
509
until (event == "timer" and idCheck == id) or (event == "modem_message" and channel == channels.receive and message == channels.confirm)
510
until message == channels.confirm
511
connected = true
512
print("Connection Confirmed!")
513
sleep(1.5)
514
end
515
local function biometrics(sendChannel)
516
local commands = { Confirm = "Confirm" }
517
local toSend = { ["x"] = x, ["y"] = (y/3 + math.ceil(lastHeight/2)), ["z"] = z, --The y calc is weird...
518
    ["xPos"] = xPos, ["yPos"] = yPos, ["zPos"] = zPos, 
519
    ["percent"] = percent, ["mined" ]= mined, 
520
    ["fuel"] = checkFuel(), ["moved"] = moved, 
521
    ["remainingBlocks"] = (volume-mined), ["ID"] = os.getComputerID(),
522
    ["isInPath"] = isInPath, --Whether it is going back to start
523
    ["volume"] = volume, ["area"] = area}
524
modem.transmit(channels.send, channels.receive, textutils.serialize(toSend))
525
id = os.startTimer(0.1)
526
local event, message
527
repeat
528
local locEvent, idCheck, confirm, _, locMessage, distance = os.pullEvent()
529
event, message = locEvent, locMessage
530
until (event == "timer" and idCheck == id) or (event == "modem_message" and confirm == channels.receive)
531
if event == "modem_message" then connected = true else connected = false end
532
--Stuff to do for different commands
533
end
534
--Showing changes to settings
535
screen(1,1)
536
print("Your selected settings:")
537
if #changedT == 0 then
538
print("Completely Default")
539
else
540
for i=1, #changedT do
541
local title, value = changedT.getPair(i)
542
print(capitalize(title)..": ",value)
543
end
544
end
545
print("\nStarting in 3"); sleep(1); print("2"); sleep(1); print("1"); sleep(1.5) --Dramatic pause at end
546
547
548
549
----------------------------------------------------------------
550
--Define ALL THE FUNCTIONS
551
function display() --This is just the last screen that displays at the end
552
screen(1,1)
553
print("Total Blocks Mined: "..mined)
554
print("Current Fuel Level: "..turtle.getFuelLevel())
555
print("Cobble: "..totals.cobble)
556
print("Usable Fuel: "..totals.fuel)
557
print("Other: "..totals.other)
558
if rednetEnabled then
559
print("")
560
print("Sent Stop Message")
561
finalTable = {{["Mined: "] = mined}, {["Cobble: "] = totals.cobble}, {["Fuel: "] = totals.fuel},
562
    {["Other: "] = totals.other}, {["Fuel: "] = checkFuel()} }
563
modem.transmit(channels.send,channels.receive,"stop")
564
modem.transmit(channels.send,channels.receive,textutils.serialize(finalTable))
565
modem.close(channels.receive)
566
end
567
if doBackup then fs.delete(saveFile) end
568
end
569
function updateDisplay() --Runs in Mine(), display information to the screen in a certain place
570
screen(1,1)
571
print("Blocks Mined")
572
print(mined)
573
print("Percent Complete")
574
print(percent.."%")
575
print("Fuel")
576
print(checkFuel())
577
if rednetEnabled then
578
screenLine(1,7)
579
print("Connected: "..tostring(connected))
580
end
581
end
582
function logMiningRun(textExtension, extras) --Logging mining runs
583
if logging then
584
local number
585
if not fs.isDir(logFolder) then
586
  fs.delete(logFolder)
587
  fs.makeDir(logFolder)
588
  number = 1
589
else
590
  local i = 0
591
  repeat
592
    i = i + 1
593
  until not fs.exists(logFolder.."/Quarry_Log_"..tostring(i)..(textExtension or ""))
594
  number = i
595
end
596
handle = fs.open(logFolder.."/Quarry_Log_"..tostring(number)..(textExtension or ""),"w")
597
local function write(...)
598
  for a, b in ipairs({...}) do
599
    handle.write(tostring(b))
600
  end
601
  handle.write("\n")
602
end
603
write("Welcome to the Quarry Logs!")
604
write("Entry Number: ",number)
605
write("Dimensions (X Z Y): ",x," ",z," ", dispY)
606
write("Blocks Mined: ", mined)
607
write("  Cobble: ", totals.cobble)
608
write("  Usable Fuel: ", totals.fuel)
609
write("  Other: ",totals.other)
610
write("Total Fuel Used: ",  originalFuel- checkFuel())
611
write("Expected Fuel Use: ", neededFuel)
612
handle.close()
613
end
614
end
615
function isFull(slots)
616
  slots = slots or 16
617
  local numUsed = 0
618
  sleep(0)
619
  for i=1, slots do
620
    if turtle.getItemCount(i) > 0 then numUsed = numUsed + 1 end
621
  end
622
  if numUsed >= slots then
623
    return true 
624
  end
625
  return false
626
end
627
function dig(doAdd, func)
628
  doAdd = doAdd or true
629
  func = func or turtle.dig
630
  if func() then
631
    if doAdd then
632
      mined = mined + 1
633
    end
634
    return true
635
  end
636
  return false
637
end
638
function digUp(doAdd)
639
    return dig(doAdd,turtle.digUp)
640
end
641
function digDown(doAdd)
642
    return dig(doAdd,turtle.digDown)
643
end
644
function relativeXCalc()
645
  if rowCheck == "right" then relxPos = xPos else relxPos = (x-xPos)+1 end
646
end
647
function forward(doAdd)
648
  if doAdd == nil then doAdd = true end
649
  if turtle.forward() then
650
    if doAdd then
651
      moved = moved + 1
652
    end
653
   if facing == 0 then
654
      xPos = xPos + 1
655
    elseif facing == 1 then
656
      zPos = zPos + 1
657
    elseif facing == 2 then
658
      xPos = xPos - 1
659
    elseif facing == 3 then
660
      zPos = zPos - 1
661
    else
662
      error("Function forward, facing should be 0 - 3, got "..tostring(facing),2)
663
    end
664
    relativeXCalc()
665
    return true
666
  end
667
  return false
668
end
669
function up(sneak)
670
  sneak = sneak or 1
671
  if inverted and sneak == 1 then
672
    down(-1)
673
  else
674
    while not turtle.up() do
675
      if not digUp() then
676
        attackUp()
677
        sleep(0.5)
678
      end
679
    end
680
    yPos = yPos - sneak --Oh! I feel so clever
681
  end                   --This works because inverted :)
682
end
683
function down(sneak)
684
  sneak = sneak or 1
685
  local count = 0
686
  if inverted and sneak == 1 then
687
    up(-1)
688
  else
689
    while not turtle.down() do
690
      count = count + 1
691
      if not digDown() then
692
        attackDown()
693
        sleep(0.2)
694
      end
695
      if count > 20 then bedrock() end
696
    end
697
    yPos = yPos + sneak
698
  end
699
end
700
function right(num)
701
  num = num or 1
702
  for i=1, num do facingF(1); saveProgress(); turtle.turnRight() end
703
end
704
function left(num)
705
  num = num or 1
706
  for i=1, num do facingF(-1); saveProgress(); turtle.turnLeft() end
707
end
708
function attack(doAdd, func)
709
  doAdd = doAdd or true
710
  func = func or turtle.attack
711
  if func() then
712
    if doAdd then 
713
      attacked = attacked + 1
714
    end
715
    return true
716
  end
717
  return false
718
end
719
function attackUp(doAdd)
720
  if inverted then
721
    return attack(doAdd, turtle.attackDown)
722
  else
723
    return attack(doAdd, turtle.attackUp)
724
  end
725
end
726
function attackDown(doAdd)
727
  if inverted then
728
    return attack(doAdd, turtle.attackUp)
729
  else
730
    return attack(doAdd, turtle.attackDown)
731
  end
732
end
733
734
735
function mine(doDigDown, doDigUp, outOfPath,doCheckInv) -- Basic Move Forward
736
if doCheckInv == nil then doCheckInv = true end
737
if doDigDown == nil then doDigDown = true end
738
if doDigUp == nil then doDigUp = true end
739
if outOfPath == nil then outOfPath = false end
740
if inverted then
741
  doDigUp, doDigDown = doDigDown, doDigUp --Just switch the two if inverted
742
end
743
if doRefuel and checkFuel() <= fuelTable[fuelSafety]/2 then
744
  for i=1, 16 do
745
  if turtle.getItemCount(i) > 0 then
746
    turtle.select(i)
747
    if checkFuel() < 200 + fuelTable[fuelSafety] then
748
      turtle.refuel()
749
    end
750
  end
751
  end
752
end
753
local count = 0
754
while not forward(not outOfPath) do
755
  sleep(0) --Calls coroutine.yield to prevent errors
756
  count = count + 1
757
  if not dig() then
758
    attack()
759
  end
760
  if count > 10 then
761
    attack()
762
    sleep(0.2)
763
  end
764
  if count > 50 then
765
    if turtle.getFuelLevel() == 0 then --Don't worry about inf fuel because I modified this function
766
      saveProgress()
767
      error("No more fuel",0)
768
    elseif yPos > (startY-7) then --If it is near bedrock
769
      bedrock()
770
    else --Otherwise just sleep for a bit to avoid sheeps
771
      sleep(1)
772
    end
773
  end
774
end
775
local tab = {} --This registers a change in the saveProgress file
776
if facing == 0 then --I do this because when it restores, it always
777
  tab.xPos = xPos + 1-- Thinks it is one position back, for some reason
778
elseif facing == 1 then-- This overwrites that.
779
  tab.zPos = zPos + 1
780
elseif facing == 2 then
781
  tab.xPos = xPos - 1
782
elseif facing == 3 then
783
  tab.zPos = zPos - 1
784
end
785
saveProgress(tab)
786
if doDigUp then
787
while turtle.detectUp() do 
788
  sleep(0) --Calls coroutine.yield
789
  if not digUp() then
790
    attackUp()
791
    count = count + 1
792
  end
793
  if count > 50 and yPos > (startY-7) then --Same deal with bedrock as above
794
    bedrock()
795
  end
796
  end
797
end
798
if doDigDown then
799
 digDown()
800
end
801
percent = math.ceil(moved/moveVolume*100)
802
updateDisplay()
803
isInPath = (not outOfPath) --For rednet
804
if doCheckInv and careAboutResources then
805
if moved%invCheckFreq == 0 then
806
 if isFull(16-keepOpen) then dropOff() end
807
end; end
808
if rednetEnabled then biometrics() end
809
end
810
--Direction: Front = 0, Right = 1, Back = 2, Left = 3
811
function facingF(num)
812
facing = facing + num
813
if facing > 3 then facing = 0 end
814
if facing < 0 then facing = 3 end
815
end
816
817
function turnTo(num, dir)
818
  num = num or facing
819
  dir = dir or "left"
820
  while facing ~= num do
821
    if dir == "left" then
822
      left()
823
    elseif dir == "right" then
824
      right()
825
    else
826
      error("TurnTo: Left or Right expected, got "..tosrting(dir))
827
      end
828
  end
829
end
830
function goto(x,z,y, toFace)
831
--Will first go to desired z pos, then x pos, y pos varies
832
x = x or 1; y = y or 1; z = z or 1; toFace = toFace or facing
833
gotoX,gotoY,gotoZ,gotoFacing = xPos,yPos,zPos,facing --For use in session persistence
834
if yPos > y then --Will go up first if below position
835
  while yPos~=y do up() end
836
end
837
if zPos > z then
838
  turnTo(3)
839
elseif zPos < z then 
840
  turnTo(1)
841
end
842
while zPos ~= z do mine(false,false,true,false) end
843
if xPos > x then
844
  turnTo(2)
845
elseif xPos < x then
846
  turnTo(0)
847
end
848
while xPos ~= x do mine(false,false,true,false) end
849
if yPos < y then --Will go down after if above position
850
  while yPos~=y do down() end
851
end
852
turnTo(toFace,"right")
853
saveProgress()
854
gotoX,gotoY,gotoZ,gotoFacing = nil
855
end
856
function drop(side, final, allowSkip)
857
side = sides[side] or "front"    --The final number means that it will
858
if final then final = 0 else final = 1 end --drop a whole stack at the end
859
local allowSkip = allowSkip or (final == 0) --This will allow drop(side,t/f, rednetConnected)
860
count()
861
if doRefuel then
862
  for i=1, 16 do
863
    if slot[i][1] == 2 then
864
      turtle.select(i); turtle.refuel()
865
    end
866
  end
867
  turtle.select(1)
868
end
869
if side == "right" then turnTo(1) end
870
if side == "left" then turnTo(3) end
871
local whereDetect, whereDrop1, whereDropAll
872
local _1 = slot[1][2] - final --All but one if final, all if not final
873
if side == "top" then
874
whereDetect = turtle.detectUp ; whereDrop = turtle.dropUp
875
elseif side == "bottom" then
876
whereDetect = turtle.detectDown ; whereDrop = turtle.dropDown
877
else
878
whereDetect = turtle.detect; whereDrop = turtle.drop
879
end
880
local function waitDrop(val) --This will just drop, but wait if it can't
881
  val = val or 64
882
  local try = 1
883
  while not whereDrop(val) do
884
    print("Chest Full, Try "..try)
885
    try = try + 1
886
    sleep(2)
887
  end
888
end
889
repeat
890
local detected = whereDetect()
891
if detected then
892
  waitDrop(_1)
893
  for i=2, 16 do
894
    if turtle.getItemCount(i) > 0 then
895
      turtle.select(i)
896
      waitDrop()
897
    end
898
  end
899
elseif not allowSkip then
900
  print("Waiting for chest placement place a chest to continue")
901
  while not whereDetect() do
902
    sleep(1)
903
  end
904
end
905
until detected or allowSkip
906
if not allowSkip then totals.cobble = totals.cobble - 1 end
907
turtle.select(1)
908
turnTo(0)
909
end
910
function dropOff() --Not local because called in mine()
911
local currX,currZ,currY,currFacing = xPos, zPos, yPos, facing
912
goto(0,1,1,2)
913
drop(dropSide,false)
914
mine(false,false,true, false)
915
goto(1,1,1, 0)
916
goto(currX,currZ,currY,currFacing)
917
end
918
function bedrock()
919
if checkFuel() == 0 then error("No Fuel",0) end
920
local origin = {x = xPos, y = yPos, z = zPos}
921
print("Bedrock Detected")
922
if turtle.detectUp() then
923
print("Block Above")
924
local var
925
if facing == 0 then var = 2 elseif facing == 2 then var = 0 else error("Was facing left or right on bedrock") end
926
goto(xPos,zPos,yPos,var)
927
for i=1, relxPos do mine(true,true); end
928
end
929
goto(0,1,1,2)
930
drop(dropSide, true)
931
display()
932
print("\nFound bedrock at these coordinates: ")
933
print(origin.x," Was position in row\n",origin.z," Was row in layer\n",origin.y," Blocks down from start")
934
error("",0)
935
end
936
-------------------------------------------------------------------------------------
937
--Pre-Mining Stuff dealing with session persistence
938
local doDigDown, doDigUp = (lastHeight ~= 1), false --Used in lastHeight
939
if not restoreFound then 
940
--Check if it is a mining turtle
941
if not isMiningTurtle then
942
  local a, b = turtle.dig()
943
  if a then mined = mined + 1; isMiningTurtle = true
944
  elseif b == "Nothing to dig with" then 
945
    print("This is not a mining turtle. To make a mining turtle, craft me together with a diamond pickaxe")
946
    error("",0)
947
  end
948
end
949
while not turtle.forward() do end
950
else digUp(); digDown() end --Get it into the quarry
951
if gpsEnabled and not restoreFound then --The initial locate is done in the arguments. This is so I can figure out what quadrant the turtle is in.
952
  gpsSecondPos = {gps.locate(gpsTimeout)} --Note: Does not run this if it has already been restarted.
953
end
954
if restoreFound then
955
  if gotoX then
956
    goto(gotoX,gotoZ,gotoY,gotoFacing)
957
  end
958
  local func
959
  if rowCheck == "left" then func = right else func = left end
960
  if endRow == 1 then
961
    mine()
962
    func()
963
  elseif endRow == 2 then
964
    func()
965
  end
966
end
967
if y ~= 0 and not restoreFound then down() end
968
--Mining Loops
969
turtle.select(1)
970
while layersDone <= y do -------------Height---------
971
moved = moved + 1 --To account for the first position in row as "moved"
972
if not restoreFound then rowCheck = "right" end
973
relativeXCalc()
974
while zPos <= z do -------------Width----------
975
while relxPos < x do ------------Length---------
976
mine()
977
end ---------------Length End-------
978
if zPos ~= z then
979
local func
980
if rowCheck == "right" and zPos ~= z then --Swithcing to next row
981
  func = right; rowCheck = "left"; else func = left; rowCheck = "right" end --Which way to turn
982
  func()
983
  endRow = 1
984
  mine()
985
  endRow = 2
986
  func()
987
  endRow = 0
988
else break
989
end
990
end ---------------Width End--------
991
goto(1,1,yPos,0)
992
if yPos+1 ~= y then 
993
  for i=1, 3 do down() end
994
end
995
layersDone = layersDone + 3
996
restoreFound = false --This is done so that rowCheck works properly upon restore
997
end ---------------Height End-------
998
if lastHeight ~= 0 then ---------LAST ROW--------- (copied from above)
999
moved = moved + 1 --To account for the first position in row as "moved"
1000
if y ~= 0 then --If the basic y == 2 or 1
1001
  for i=1, 2 do down() end
1002
end 
1003
if not restoreFound then rowCheck = "right" end
1004
relativeXCalc()
1005
while zPos <= z do -------------Width----------
1006
while relxPos < x do ------------Length---------
1007
mine(doDigDown,doDigUp)
1008
end ---------------Length End-------
1009
if zPos ~= z then
1010
local func
1011
if rowCheck == "right" and zPos ~= z then --Swithcing to next row
1012
  func = right; rowCheck = "left"; else func = left; rowCheck = "right" end --Which way to turn
1013
  func()
1014
  endRow = 1
1015
  mine(doDigDown,doDigUp)
1016
  endRow = 2
1017
  func()
1018
  endRow = 0
1019
else break
1020
end
1021
end ---------------Width End--------
1022
goto(1,1,yPos,0)
1023
end
1024
if doDigDown then
1025
  if inverted then
1026
    digUp()
1027
  else
1028
    digDown()
1029
  end
1030
end
1031
goto(0,1,1,2)
1032
1033
--Output to a chest or sit there
1034
drop(dropSide, true)
1035
--Display was moved above to be used in bedrock function
1036
display()
1037
--Log current mining run
1038
logMiningRun(logExtension)
1039
1040
--Cleanup
1041
turtle.getFuelLevel = getFuel