Guest User

Quarry 3.2.1

a guest
Sep 22nd, 2013
5,243
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 37.59 KB | None | 0 0
  1. --[[
  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. local getFuel = turtle.getFuelLevel
  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.  
  184. -----------------------------------------------------------------
  185. --Input Phase
  186. local function screen(xPos,yPos)
  187. xPos, yPos = xPos or 1, yPos or 1
  188. term.setCursorPos(xPos,yPos); term.clear(); end
  189. local function screenLine(xPos,yPos)
  190. term.setCursorPos(xPos,yPos); term.clearLine(); end
  191.  
  192. screen(1,1)
  193. print("----- Welcome to Quarry! -----")
  194. print("")
  195.  
  196. local sides = {top = "top", right = "right", left = "left", bottom = "bottom", front = "front"} --Used to whitelist sides
  197. local errorT = {num = "Numbers not recognized", zero = "Variable is out of range", word = "String failed assertion" }
  198. local changedT = {}
  199. changedT.new = function(key, value) changedT[#changedT+1] = {[key] = value} end
  200. changedT.getPair = function(i) for a, b in pairs(changedT[i]) do return a, b end end
  201. local function capitalize(text) return (string.upper(string.sub(text,1,1))..string.sub(text,2,-1)) end
  202. 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
  203. local function checkNum(number, section) return assert(tonumber(number),errorT.num, section) end
  204. tArgs.checkStart = function(num) tArgs[tArgs[num]] = num end
  205. for i=1, #tArgs do tArgs.checkStart(i) end
  206.  
  207. --Check if it is a turtle
  208. if not turtle then
  209. print("This is not a turtle, you must be looking for the \"Companion Rednet Program\" \nCheck My forum thread for that")
  210. print("Press 'q' to quit, or any other key to start help ")
  211. if ({os.pullEvent("char")})[2] ~= "q" then tArgs.help = true else error("",0) end
  212. end
  213.  
  214.  
  215. if tArgs["help"] or tArgs["-help"] or tArgs["-?"] or tArgs["?"] then
  216. print("You have selected help, press any key to continue"); print("Use arrow keys to naviate, q to quit"); os.pullEvent("key")
  217. local pos = 1
  218. local key = 0
  219. while pos <= #help and key ~= keys.q do
  220. if pos < 1 then pos = 1 end
  221. screen(1,1)
  222. print(help[pos].title)
  223. for a=1, #help[pos] do print(help[pos][a]) end
  224. repeat
  225. _, key = os.pullEvent("key")
  226. until key == 200 or key == 208 or key == keys.q
  227. if key == 200 then pos = pos - 1 end
  228. if key == 208 then pos = pos + 1 end
  229. end
  230. error("",0)
  231. end
  232.  
  233. --Saving
  234. if tArgs["doBackup"] then doBackup = (string.lower(string.sub(tArgs[tArgs["doBackup"]+1],1,1)) ~= "f") end
  235. if tArgs["saveFile"] then saveFile = tArgs[tArgs["saveFile"]+1] or saveFile end
  236.  
  237. local restoreFound = false
  238. if tArgs["-restore"] or tArgs["-resume"] then
  239. restoreFound = fs.exists(saveFile)
  240. if restoreFound then
  241. os.run(getfenv(1),saveFile)
  242. if gpsEnabled then --If it had saved gps coordinates
  243. print("Found GPS Start Coordinates")
  244. local currLoc = {gps.locate(gpsTimeout)}
  245. if #currLoc > 0 and #gpsStartPos > 0 and #gpsSecondPos > 0 then --Cover all the different positions I'm using
  246. print("GPS Position Successfully Read")
  247. if currLoc[1] == gpsStartPos[1] and currLoc[3] == gpsStartPos[3] then --X coord, y coord, z coord in that order
  248. xPos, yPos, zPos = 0,1,1
  249. if facing ~= 0 then turnTo(0) end
  250. print("Is at start")
  251. else
  252. if inverted then --yPos setting
  253. ------------------------------------------------FIX THIS
  254. end
  255. local function copyTable(tab) local toRet = {}; for a, b in pairs(tab) do toRet[a] = b end; return toRet end
  256. local a, b = copyTable(gpsStartPos), copyTable(gpsSecondPos) --For convenience
  257. if b[3] - a[3] == -1 then--If went north (-Z)
  258. a[1] = a[1] - 1 --Shift x one to west to create a "zero"
  259. xPos, zPos = -currLoc[3] + a[3], currLoc[1] + -a[1]
  260. elseif b[1] - a[1] == 1 then--If went east (+X)
  261. a[3] = a[3] - 1 --Shift z up one to north to create a "zero"
  262. xPos, zPos = currLoc[1] + -a[1], currLoc[3] + -a[3]
  263. elseif b[3] - a[3] == 1 then--If went south (+Z)
  264. a[1] = a[1] + 1 --Shift x one to east to create a "zero"
  265. xPos, zPos = currLoc[3] + a[3], -currLoc[1] + a[3]
  266. elseif b[1] - a[1] == -1 then--If went west (-X)
  267. a[3] = a[3] + 1 --Shift z down one to south to create a "zero"
  268. xPos, zPos = -currLoc[1] + a[1], -currLoc[3] + a[3]
  269. else
  270. print("Improper Coordinates")
  271. print("GPS Locate Failed, Using Standard Methods") ----Maybe clean this up a bit to use flags instead.
  272. end
  273. end
  274. print("X Pos: ",xPos)
  275. print("Y Pos: ",yPos)
  276. print("Z Pos: ",zPos)
  277. print("Facing: ",facing)
  278. else
  279. print("GPS Locate Failed, Using Standard Methods")
  280. end
  281. print("Restore File read successfully. Starting in 3"); sleep(3)
  282. end
  283. end
  284. else
  285. originalFuel = checkFuel() --For use in logging. To see how much fuel is REALLY used
  286. end
  287.  
  288. if not (tArgs["-DEFAULT"] or restoreFound) then
  289. --Just a note, the whole error checking section here was more of an
  290. --experiment than anything else. If its ever changed in the future,
  291. --it would probably be for the better.
  292. local section = "Dimensions"
  293. --Dimesnions
  294. if tArgs["-dim"] then local num = tArgs["-dim"];
  295. x = checkNum(tArgs[num + 1],section); z = checkNum(tArgs[num + 2],section); y = checkNum(tArgs[num + 3],section)
  296. else
  297. print("What dimensions?")
  298. print("")
  299. --This will protect from negatives, letters, and decimals
  300. term.write("Length: ")
  301. x = math.floor(math.abs(tonumber(io.read()) or x))
  302. term.write("Width: ")
  303. z = math.floor(math.abs(tonumber(io.read()) or z))
  304. term.write("Height: ")
  305. y = math.floor(math.abs(tonumber(io.read()) or y))
  306. end
  307. changedT.new("x",x); changedT.new("z",z); changedT.new("y",y)
  308. assert(x~=0, errorT.zero, section); assert(z~=0, errorT.zero, section); assert(y~=0, errorT.zero, section)
  309. assert(not(x == 1 and y == 1 and z == 1) ,"1, 1, 1 dosen't work well at all, try again", section)
  310. if not tArgs["-vanilla"] then
  311. --Invert
  312. if tArgs["-invert"] then
  313. inverted = (string.lower(string.sub(tArgs[tArgs["-invert"]+1] or "",1,1)) == "t") else
  314. term.write("Inverted? ")
  315. inverted = (string.lower(string.sub(io.read(),1,1)) == "y")
  316. end
  317. changedT.new("Inverted", inverted)
  318. --Rednet
  319. if supportsRednet then
  320. if tArgs["-rednet"] then
  321. rednetEnabled = (string.lower(string.sub(tArgs[tArgs["-rednet"]+1] or "",1,1)) == "t")
  322. else term.write("Rednet? "); rednetEnabled = (string.lower(string.sub(io.read(),1,1)) == "y")
  323. if (tArgs["-GPS"] or tArgs["-gps"]) and not restoreFound and not gpsEnabled then --The not gps enabled makes it so it is toggled
  324. gpsStartPos = {gps.locate(gpsTimeout)} --Stores position in array
  325. gpsEnabled = #gpsStartPos > 0 --Checks if location received properly
  326. changedT.new("GPS Location Services", gpsEnabled)
  327. end
  328. changedT.new("Rednet Enabled", rednetEnabled)
  329. end
  330. if tArgs["-sendChannel"] then
  331. channels.send = assert(tonumber(tArgs[tArgs["-sendChannel"]+1]), errorT.num)
  332. assert(channels.send > 0 and channels.send < 65535, errorT.zero)
  333. changedT.new("Send Channel",channels.send) end
  334. if tArgs["-receiveChannel"] then
  335. channels.receive = assert(tonumber(tArgs[tArgs["-receiveChannel"]+1]), errorT.num)
  336. assert(channels.receive > 0 and channels.receive < 65535 and channels.receive ~= channels.send, errorT.zero)
  337. changedT.new("Receive Channel",channels.receive) end
  338. end
  339. --Fuel
  340. if tArgs["-doRefuel"] then doRefuel = not doRefuel; changedT.new("Do Refuel",doRefuel) end
  341. if turtle.getFuelLevel() == "unlimited" then
  342. doCheckFuel = false
  343. else
  344. if tArgs["-doCheckFuel"] then
  345. doCheckFuel = (string.lower(string.sub(tArgs[tArgs["-doCheckFuel"]+1] or "",1,1)) == "t"); changedT.new("Do Check Fuel", doCheckFuel) end
  346. end
  347. if tArgs["-chest"] then
  348. dropSide = sides[tArgs[tArgs["-chest"]+1]] or dropSide; changedT.new("Chest Side",dropSide) end
  349. if tArgs["-fuelSafety"] then local loc = tArgs[tArgs["-fuelSafety"]+1]
  350. if fuelTable[loc] then
  351. fuelSafety = loc; changedT.new("Fuel Check Safety", fuelSafety)
  352. end
  353. end
  354. --Logging
  355. logging = (tArgs["-log"] and true) or logging --The and will set it to true if value, or its original value if nil
  356. if logging then changedT.new("Logging",logging) end
  357. if tArgs["-logFolder"] then logFolder = tArgs[tArgs["-logFolder"]+1] or logFolder; changedT.new("Log Folder",logFolder) end
  358. if tArgs["-logExtension"] then logExtension = tArgs[tArgs["-logExtension"]+1] or logExtension; changedT.new("Log Extension",logExtension) end
  359. --Misc
  360. if tArgs["-startY"] then
  361. startY = math.abs(math.floor(checkNum(tArgs[tArgs["-startY"]+1],"Start Y")))
  362. changedT.new("Start Y Position",startY) end
  363. assert(startY >= 0, errorT.zero, "StartY")
  364. if tArgs["-invCheckFreq"] then
  365. invCheckFreq = math.abs(math.floor(checkNum(tArgs[tArgs["-invCheckFreq"]+1],"Inventory Check Frequency")))
  366. changedT.new("Inventory Check Frequency",invCheckFreq) end
  367. assert(invCheckFreq ~= 0, errorT.zero, "Inventory Check Frequency")
  368. if tArgs["-keepOpen"] then
  369. keepOpen = math.abs(math.floor(checkNum(tArgs[tArgs["-keepOpen"]+1],"Open Slots")))
  370. changedT.new("Slots to keep open", keepOpen) end
  371. assert(keepOpen ~= 0 and keepOpen < 16, errorT.zero, "Open Slots")
  372. if tArgs["-ignoreResources"] then careAboutResources = false; changedT.new("Ignore Resources?", not careAboutResources) end
  373. if tArgs["-saveFile"] then saveFile = tArgs[tArgs["-saveFile"]+1] changedT.new("Save File", saveFile) end
  374. assert(#saveFile >= 2,errorT.word, "Save File")
  375. end; end --First end is for vanilla, second is for DEFAULT
  376.  
  377. local function saveProgress(extras) --Session persistence
  378. if doBackup then
  379. local file = fs.open(saveFile,"w")
  380. for a,b in pairs(getfenv(1)) do
  381. if type(b) == "string" then b = "\""..b.."\"" end
  382. if type(b) == "table" and a~="modem" then b = textutils.serialize(b) end
  383. if type(b) ~= "function" then
  384. file.write(a.." = "..tostring(b).."\n")
  385. end
  386. end
  387. file.write("doCheckFuel = false\n") --It has already used fuel, so calculation unnesesary
  388. if type(extras) == "table" then
  389. for a, b in pairs(extras) do
  390. file.write(a.." = "..tostring(b))
  391. end
  392. end
  393. file.close()
  394. end
  395. end
  396.  
  397. local area = x*z
  398. local volume = x*y*z
  399. local lastHeight = y%3
  400. local dispY = y
  401. y = math.floor(y/3)*3
  402. local yMult = y/3 + math.ceil(lastHeight/2) --This is basically a smart y/3 for movement
  403. local moveVolume = (area * yMult) --Kept for display percent
  404. --Calculating Needed Fuel--
  405. local exStack = numberOfStacksPerRun --Expected stacks of items before full
  406. neededFuel = yMult * x * z + --This is volume it will run through
  407. 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
  408. (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
  409. --Original equation: x*z*y/3 + y * 2 + (x+z) * y/3 + (x + z + y) * (1/64*8)
  410. neededFuel = math.ceil(neededFuel)
  411.  
  412. --Getting Fuel
  413. if doCheckFuel and checkFuel() < neededFuel then
  414. neededFuel = neededFuel + fuelTable[fuelSafety] --For safety
  415. print("Not enough fuel")
  416. print("Current: ",checkFuel()," Needed: ",neededFuel)
  417. print("Starting SmartFuel...")
  418. sleep(2) --So they can read everything.
  419. term.clear()
  420. local oneFuel, neededFuelItems
  421. local currSlot = 0
  422. local function output(text, x, y) --For displaying fuel
  423. currX, currY = term.getCursorPos()
  424. term.setCursorPos(x,y)
  425. term.clearLine()
  426. term.write(text)
  427. term.setCursorPos(currX,currY)
  428. end
  429. local function roundTo(num, target) --For stacks of fuel
  430. if num >= target then return target elseif num < 0 then return 0 else return num end
  431. end
  432. local function updateScreen()
  433. output("Welcome to SmartFuel! Now Refueling...", 1,1)
  434. output("Currently taking fuel from slot "..currSlot,1,2)
  435. output("Current single fuel: "..tostring(oneFuel or 0),1,3)
  436. output("Current estimate of needed fuel: ",1,4)
  437. output("Single Items: "..math.floor(neededFuelItems or 0),4,5)
  438. output("Stacks: "..math.ceil((neededFuelItems or 0) / 64),4,6)
  439. output("Needed Fuel: "..tostring(neededFuel),1,12)
  440. output("Current Fuel: "..tostring(checkFuel()),1,13)
  441. end
  442. while checkFuel() <= neededFuel do
  443. currSlot = currSlot + 1
  444. turtle.select(currSlot)
  445. updateScreen()
  446. while turtle.getItemCount(currSlot) == 0 do sleep(1.5) end
  447. repeat
  448. local previous = checkFuel()
  449. turtle.refuel(1)
  450. oneFuel = checkFuel() - previous
  451. updateScreen()
  452. until (oneFuel or 0) > 0 --Not an if to prevent errors if fuel taken out prematurely.
  453. neededFuelItems = (neededFuel - checkFuel()) / oneFuel
  454. turtle.refuel(roundTo(neededFuelItems, 64)) --Change because can only think about 64 at once.
  455. if turtle.getItemCount(roundTo(currSlot + 1, 16)) == 0 then --Resets if no more fuel
  456. currSlot = 0
  457. end
  458. end
  459. -- local neededFuel = moveVolume + (math.floor(volume / (64 * 8)) * (x+dispY+z)) --Standard move plus dropping off supplies
  460. -- --How many times come back to start| * If it were at the very far side
  461. -- neededFuel = neededFuel + fuelTable[fuelSafety]
  462. -- if neededFuel < 100 then neededFuel = 100; end
  463. -- if checkFuel() < neededFuel then
  464. -- screen(1,1)
  465. -- print("More Fuel Needed")
  466. -- print("Current Fuel: ",checkFuel()," Needed: ",neededFuel)
  467. -- print("Place fuel in Bottom Right")
  468. -- while turtle.getItemCount(16) == 0 do
  469. -- sleep(1)
  470. -- end
  471. -- turtle.select(16)
  472. -- while checkFuel() < neededFuel do
  473. -- if not turtle.refuel(1) then
  474. -- term.clearLine()
  475. -- print("Still too little fuel")
  476. -- term.clearLine()
  477. -- print("Insert more fuel to resume")
  478. -- while turtle.getItemCount(16) == 0 do
  479. -- sleep(1)
  480. -- end
  481. -- end
  482. -- local x,y = term.getCursorPos()
  483. -- print(checkFuel().." Fuel")
  484. -- term.setCursorPos(x,y)
  485. -- end
  486. -- print(checkFuel().." Units of Fuel")
  487. -- sleep(3)
  488. -- turtle.select(1)
  489. -- end
  490. end
  491. --Initial Rednet Handshake
  492. if rednetEnabled then
  493. screen(1,1)
  494. print("Rednet is Enabled")
  495. print("The Channel to open is "..channels.send)
  496. modem = peripheral.wrap("right")
  497. modem.open(channels.receive)
  498. local i = 0
  499. repeat
  500. local id = os.startTimer(3)
  501. i=i+1
  502. print("Sending Initial Message "..i)
  503. modem.transmit(channels.send, channels.receive, "{ 'Initial' }")
  504. local message
  505. repeat
  506. local event, idCheck, channel,_,locMessage, distance = os.pullEvent()
  507. message = locMessage
  508. until (event == "timer" and idCheck == id) or (event == "modem_message" and channel == channels.receive and message == channels.confirm)
  509. until message == channels.confirm
  510. connected = true
  511. print("Connection Confirmed!")
  512. sleep(1.5)
  513. end
  514. local function biometrics(sendChannel)
  515. local commands = { Confirm = "Confirm" }
  516. local toSend = { ["x"] = x, ["y"] = (y/3 + math.ceil(lastHeight/2)), ["z"] = z, --The y calc is weird...
  517. ["xPos"] = xPos, ["yPos"] = yPos, ["zPos"] = zPos,
  518. ["percent"] = percent, ["mined" ]= mined,
  519. ["fuel"] = checkFuel(), ["moved"] = moved,
  520. ["remainingBlocks"] = (volume-mined), ["ID"] = os.getComputerID(),
  521. ["isInPath"] = isInPath, --Whether it is going back to start
  522. ["volume"] = volume, ["area"] = area}
  523. modem.transmit(channels.send, channels.receive, textutils.serialize(toSend))
  524. id = os.startTimer(0.1)
  525. local event, message
  526. repeat
  527. local locEvent, idCheck, confirm, _, locMessage, distance = os.pullEvent()
  528. event, message = locEvent, locMessage
  529. until (event == "timer" and idCheck == id) or (event == "modem_message" and confirm == channels.receive)
  530. if event == "modem_message" then connected = true else connected = false end
  531. --Stuff to do for different commands
  532. end
  533. --Showing changes to settings
  534. screen(1,1)
  535. print("Your selected settings:")
  536. if #changedT == 0 then
  537. print("Completely Default")
  538. else
  539. for i=1, #changedT do
  540. local title, value = changedT.getPair(i)
  541. print(capitalize(title)..": ",value)
  542. end
  543. end
  544. print("\nStarting in 3"); sleep(1); print("2"); sleep(1); print("1"); sleep(1.5) --Dramatic pause at end
  545.  
  546.  
  547.  
  548. ----------------------------------------------------------------
  549. --Define ALL THE FUNCTIONS
  550. function display() --This is just the last screen that displays at the end
  551. screen(1,1)
  552. print("Total Blocks Mined: "..mined)
  553. print("Current Fuel Level: "..turtle.getFuelLevel())
  554. print("Cobble: "..totals.cobble)
  555. print("Usable Fuel: "..totals.fuel)
  556. print("Other: "..totals.other)
  557. if rednetEnabled then
  558. print("")
  559. print("Sent Stop Message")
  560. finalTable = {{["Mined: "] = mined}, {["Cobble: "] = totals.cobble}, {["Fuel: "] = totals.fuel},
  561. {["Other: "] = totals.other}, {["Fuel: "] = checkFuel()} }
  562. modem.transmit(channels.send,channels.receive,"stop")
  563. modem.transmit(channels.send,channels.receive,textutils.serialize(finalTable))
  564. modem.close(channels.receive)
  565. end
  566. if doBackup then fs.delete(saveFile) end
  567. end
  568. function updateDisplay() --Runs in Mine(), display information to the screen in a certain place
  569. screen(1,1)
  570. print("Blocks Mined")
  571. print(mined)
  572. print("Percent Complete")
  573. print(percent.."%")
  574. print("Fuel")
  575. print(checkFuel())
  576. if rednetEnabled then
  577. screenLine(1,7)
  578. print("Connected: "..tostring(connected))
  579. end
  580. end
  581. function logMiningRun(textExtension, extras) --Logging mining runs
  582. if logging then
  583. local number
  584. if not fs.isDir(logFolder) then
  585. fs.delete(logFolder)
  586. fs.makeDir(logFolder)
  587. number = 1
  588. else
  589. local i = 0
  590. repeat
  591. i = i + 1
  592. until not fs.exists(logFolder.."/Quarry_Log_"..tostring(i)..(textExtension or ""))
  593. number = i
  594. end
  595. handle = fs.open(logFolder.."/Quarry_Log_"..tostring(number)..(textExtension or ""),"w")
  596. local function write(...)
  597. for a, b in ipairs({...}) do
  598. handle.write(tostring(b))
  599. end
  600. handle.write("\n")
  601. end
  602. write("Welcome to the Quarry Logs!")
  603. write("Entry Number: ",number)
  604. write("Dimensions (X Z Y): ",x," ",z," ", dispY)
  605. write("Blocks Mined: ", mined)
  606. write(" Cobble: ", totals.cobble)
  607. write(" Usable Fuel: ", totals.fuel)
  608. write(" Other: ",totals.other)
  609. write("Total Fuel Used: ", originalFuel- checkFuel())
  610. write("Expected Fuel Use: ", neededFuel)
  611. handle.close()
  612. end
  613. end
  614. function isFull(slots)
  615. slots = slots or 16
  616. local numUsed = 0
  617. sleep(0)
  618. for i=1, slots do
  619. if turtle.getItemCount(i) > 0 then numUsed = numUsed + 1 end
  620. end
  621. if numUsed >= slots then
  622. return true
  623. end
  624. return false
  625. end
  626. function dig(doAdd, func)
  627. doAdd = doAdd or true
  628. func = func or turtle.dig
  629. if func() then
  630. if doAdd then
  631. mined = mined + 1
  632. end
  633. return true
  634. end
  635. return false
  636. end
  637. function digUp(doAdd)
  638. return dig(doAdd,turtle.digUp)
  639. end
  640. function digDown(doAdd)
  641. return dig(doAdd,turtle.digDown)
  642. end
  643. function relativeXCalc()
  644. if rowCheck == "right" then relxPos = xPos else relxPos = (x-xPos)+1 end
  645. end
  646. function forward(doAdd)
  647. if doAdd == nil then doAdd = true end
  648. if turtle.forward() then
  649. if doAdd then
  650. moved = moved + 1
  651. end
  652. if facing == 0 then
  653. xPos = xPos + 1
  654. elseif facing == 1 then
  655. zPos = zPos + 1
  656. elseif facing == 2 then
  657. xPos = xPos - 1
  658. elseif facing == 3 then
  659. zPos = zPos - 1
  660. else
  661. error("Function forward, facing should be 0 - 3, got "..tostring(facing),2)
  662. end
  663. relativeXCalc()
  664. return true
  665. end
  666. return false
  667. end
  668. function up(sneak)
  669. sneak = sneak or 1
  670. if inverted and sneak == 1 then
  671. down(-1)
  672. else
  673. while not turtle.up() do
  674. if not digUp() then
  675. attackUp()
  676. sleep(0.5)
  677. end
  678. end
  679. yPos = yPos - sneak --Oh! I feel so clever
  680. end --This works because inverted :)
  681. end
  682. function down(sneak)
  683. sneak = sneak or 1
  684. local count = 0
  685. if inverted and sneak == 1 then
  686. up(-1)
  687. else
  688. while not turtle.down() do
  689. count = count + 1
  690. if not digDown() then
  691. attackDown()
  692. sleep(0.2)
  693. end
  694. if count > 20 then bedrock() end
  695. end
  696. yPos = yPos + sneak
  697. end
  698. end
  699. function right(num)
  700. num = num or 1
  701. for i=1, num do facingF(1); saveProgress(); turtle.turnRight() end
  702. end
  703. function left(num)
  704. num = num or 1
  705. for i=1, num do facingF(-1); saveProgress(); turtle.turnLeft() end
  706. end
  707. function attack(doAdd, func)
  708. doAdd = doAdd or true
  709. func = func or turtle.attack
  710. if func() then
  711. if doAdd then
  712. attacked = attacked + 1
  713. end
  714. return true
  715. end
  716. return false
  717. end
  718. function attackUp(doAdd)
  719. if inverted then
  720. return attack(doAdd, turtle.attackDown)
  721. else
  722. return attack(doAdd, turtle.attackUp)
  723. end
  724. end
  725. function attackDown(doAdd)
  726. if inverted then
  727. return attack(doAdd, turtle.attackUp)
  728. else
  729. return attack(doAdd, turtle.attackDown)
  730. end
  731. end
  732.  
  733.  
  734. function mine(doDigDown, doDigUp, outOfPath,doCheckInv) -- Basic Move Forward
  735. if doCheckInv == nil then doCheckInv = true end
  736. if doDigDown == nil then doDigDown = true end
  737. if doDigUp == nil then doDigUp = true end
  738. if outOfPath == nil then outOfPath = false end
  739. if inverted then
  740. doDigUp, doDigDown = doDigDown, doDigUp --Just switch the two if inverted
  741. end
  742. if doRefuel and checkFuel() <= fuelTable[fuelSafety]/2 then
  743. for i=1, 16 do
  744. if turtle.getItemCount(i) > 0 then
  745. turtle.select(i)
  746. if checkFuel() < 200 + fuelTable[fuelSafety] then
  747. turtle.refuel()
  748. end
  749. end
  750. end
  751. end
  752. local count = 0
  753. while not forward(not outOfPath) do
  754. sleep(0) --Calls coroutine.yield to prevent errors
  755. count = count + 1
  756. if not dig() then
  757. attack()
  758. end
  759. if count > 10 then
  760. attack()
  761. sleep(0.2)
  762. end
  763. if count > 50 then
  764. if turtle.getFuelLevel() == 0 then --Don't worry about inf fuel because I modified this function
  765. saveProgress({doCheckFuel = true})
  766. error("No more fuel",0)
  767. elseif yPos > (startY-7) then --If it is near bedrock
  768. bedrock()
  769. else --Otherwise just sleep for a bit to avoid sheeps
  770. sleep(1)
  771. end
  772. end
  773. end
  774. local tab = {} --This registers a change in the saveProgress file
  775. if facing == 0 then --I do this because when it restores, it always
  776. tab.xPos = xPos + 1-- Thinks it is one position back, for some reason
  777. elseif facing == 1 then-- This overwrites that.
  778. tab.zPos = zPos + 1
  779. elseif facing == 2 then
  780. tab.xPos = xPos - 1
  781. elseif facing == 3 then
  782. tab.zPos = zPos - 1
  783. end
  784. saveProgress(tab)
  785. if doDigUp then
  786. while turtle.detectUp() do
  787. sleep(0) --Calls coroutine.yield
  788. if not digUp() then
  789. attackUp()
  790. count = count + 1
  791. end
  792. if count > 50 and yPos > (startY-7) then --Same deal with bedrock as above
  793. bedrock()
  794. end
  795. end
  796. end
  797. if doDigDown then
  798. digDown()
  799. end
  800. percent = math.ceil(moved/moveVolume*100)
  801. updateDisplay()
  802. isInPath = (not outOfPath) --For rednet
  803. if doCheckInv and careAboutResources then
  804. if moved%invCheckFreq == 0 then
  805. if isFull(16-keepOpen) then dropOff() end
  806. end; end
  807. if rednetEnabled then biometrics() end
  808. end
  809. --Direction: Front = 0, Right = 1, Back = 2, Left = 3
  810. function facingF(num)
  811. facing = facing + num
  812. if facing > 3 then facing = 0 end
  813. if facing < 0 then facing = 3 end
  814. end
  815.  
  816. function turnTo(num, dir)
  817. num = num or facing
  818. dir = dir or "left"
  819. while facing ~= num do
  820. if dir == "left" then
  821. left()
  822. elseif dir == "right" then
  823. right()
  824. else
  825. error("TurnTo: Left or Right expected, got "..tosrting(dir))
  826. end
  827. end
  828. end
  829. function goto(x,z,y, toFace)
  830. --Will first go to desired z pos, then x pos, y pos varies
  831. x = x or 1; y = y or 1; z = z or 1; toFace = toFace or facing
  832. gotoX,gotoY,gotoZ,gotoFacing = xPos,yPos,zPos,facing --For use in session persistence
  833. if yPos > y then --Will go up first if below position
  834. while yPos~=y do up() end
  835. end
  836. if zPos > z then
  837. turnTo(3)
  838. elseif zPos < z then
  839. turnTo(1)
  840. end
  841. while zPos ~= z do mine(false,false,true,false) end
  842. if xPos > x then
  843. turnTo(2)
  844. elseif xPos < x then
  845. turnTo(0)
  846. end
  847. while xPos ~= x do mine(false,false,true,false) end
  848. if yPos < y then --Will go down after if above position
  849. while yPos~=y do down() end
  850. end
  851. turnTo(toFace,"right")
  852. saveProgress()
  853. gotoX,gotoY,gotoZ,gotoFacing = nil
  854. end
  855. function drop(side, final, allowSkip)
  856. side = sides[side] or "front" --The final number means that it will
  857. if final then final = 0 else final = 1 end --drop a whole stack at the end
  858. local allowSkip = allowSkip or (final == 0) --This will allow drop(side,t/f, rednetConnected)
  859. count()
  860. if doRefuel then
  861. for i=1, 16 do
  862. if slot[i][1] == 2 then
  863. turtle.select(i); turtle.refuel()
  864. end
  865. end
  866. turtle.select(1)
  867. end
  868. if side == "right" then turnTo(1) end
  869. if side == "left" then turnTo(3) end
  870. local whereDetect, whereDrop1, whereDropAll
  871. local _1 = slot[1][2] - final --All but one if final, all if not final
  872. if side == "top" then
  873. whereDetect = turtle.detectUp ; whereDrop = turtle.dropUp
  874. elseif side == "bottom" then
  875. whereDetect = turtle.detectDown ; whereDrop = turtle.dropDown
  876. else
  877. whereDetect = turtle.detect; whereDrop = turtle.drop
  878. end
  879. local function waitDrop(val) --This will just drop, but wait if it can't
  880. val = val or 64
  881. local try = 1
  882. while not whereDrop(val) do
  883. print("Chest Full, Try "..try)
  884. try = try + 1
  885. sleep(2)
  886. end
  887. end
  888. repeat
  889. local detected = whereDetect()
  890. if detected then
  891. waitDrop(_1)
  892. for i=2, 16 do
  893. if turtle.getItemCount(i) > 0 then
  894. turtle.select(i)
  895. waitDrop()
  896. end
  897. end
  898. elseif not allowSkip then
  899. print("Waiting for chest placement place a chest to continue")
  900. while not whereDetect() do
  901. sleep(1)
  902. end
  903. end
  904. until detected or allowSkip
  905. if not allowSkip then totals.cobble = totals.cobble - 1 end
  906. turtle.select(1)
  907. turnTo(0)
  908. end
  909. function dropOff() --Not local because called in mine()
  910. local currX,currZ,currY,currFacing = xPos, zPos, yPos, facing
  911. goto(0,1,1,2)
  912. drop(dropSide,false)
  913. mine(false,false,true, false)
  914. goto(1,1,1, 0)
  915. goto(currX,currZ,currY,currFacing)
  916. end
  917. function bedrock()
  918. if checkFuel() == 0 then error("No Fuel",0) end
  919. local origin = {x = xPos, y = yPos, z = zPos}
  920. print("Bedrock Detected")
  921. if turtle.detectUp() then
  922. print("Block Above")
  923. local var
  924. if facing == 0 then var = 2 elseif facing == 2 then var = 0 else error("Was facing left or right on bedrock") end
  925. goto(xPos,zPos,yPos,var)
  926. for i=1, relxPos do mine(true,true); end
  927. end
  928. goto(0,1,1,2)
  929. drop(dropSide, true)
  930. display()
  931. print("\nFound bedrock at these coordinates: ")
  932. print(origin.x," Was position in row\n",origin.z," Was row in layer\n",origin.y," Blocks down from start")
  933. error("",0)
  934. end
  935. -------------------------------------------------------------------------------------
  936. --Pre-Mining Stuff dealing with session persistence
  937. local doDigDown, doDigUp = (lastHeight ~= 1), false --Used in lastHeight
  938. if not restoreFound then
  939. --Check if it is a mining turtle
  940. if not isMiningTurtle then
  941. local a, b = turtle.dig()
  942. if a then mined = mined + 1; isMiningTurtle = true
  943. elseif b == "Nothing to dig with" then
  944. print("This is not a mining turtle. To make a mining turtle, craft me together with a diamond pickaxe")
  945. error("",0)
  946. end
  947. end
  948. else digUp(); digDown() end --Get it into the quarry
  949. 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.
  950. gpsSecondPos = {gps.locate(gpsTimeout)} --Note: Does not run this if it has already been restarted.
  951. end
  952. if restoreFound then
  953. if gotoX then
  954. goto(gotoX,gotoZ,gotoY,gotoFacing)
  955. end
  956. local func
  957. if rowCheck == "left" then func = right else func = left end
  958. if endRow == 1 then
  959. mine()
  960. func()
  961. elseif endRow == 2 then
  962. func()
  963. end
  964. end
  965. if y ~= 0 and not restoreFound then down() end
  966. --Mining Loops
  967. turtle.select(1)
  968. while layersDone <= y do -------------Height---------
  969. moved = moved + 1 --To account for the first position in row as "moved"
  970. if not restoreFound then rowCheck = "right" end
  971. relativeXCalc()
  972. while zPos <= z do -------------Width----------
  973. while relxPos < x do ------------Length---------
  974. mine()
  975. end ---------------Length End-------
  976. if zPos ~= z then
  977. local func
  978. if rowCheck == "right" and zPos ~= z then --Swithcing to next row
  979. func = right; rowCheck = "left"; else func = left; rowCheck = "right" end --Which way to turn
  980. func()
  981. endRow = 1
  982. mine()
  983. endRow = 2
  984. func()
  985. endRow = 0
  986. else break
  987. end
  988. end ---------------Width End--------
  989. goto(1,1,yPos,0)
  990. if yPos+1 ~= y then
  991. for i=1, 3 do down() end
  992. end
  993. layersDone = layersDone + 3
  994. restoreFound = false --This is done so that rowCheck works properly upon restore
  995. end ---------------Height End-------
  996. if lastHeight ~= 0 then ---------LAST ROW--------- (copied from above)
  997. moved = moved + 1 --To account for the first position in row as "moved"
  998. if y ~= 0 then --If the basic y == 2 or 1
  999. for i=1, 2 do down() end
  1000. end
  1001. if not restoreFound then rowCheck = "right" end
  1002. relativeXCalc()
  1003. while zPos <= z do -------------Width----------
  1004. while relxPos < x do ------------Length---------
  1005. mine(doDigDown,doDigUp)
  1006. end ---------------Length End-------
  1007. if zPos ~= z then
  1008. local func
  1009. if rowCheck == "right" and zPos ~= z then --Swithcing to next row
  1010. func = right; rowCheck = "left"; else func = left; rowCheck = "right" end --Which way to turn
  1011. func()
  1012. endRow = 1
  1013. mine(doDigDown,doDigUp)
  1014. endRow = 2
  1015. func()
  1016. endRow = 0
  1017. else break
  1018. end
  1019. end ---------------Width End--------
  1020. goto(1,1,yPos,0)
  1021. end
  1022. if doDigDown then
  1023. if inverted then
  1024. digUp()
  1025. else
  1026. digDown()
  1027. end
  1028. end
  1029. goto(0,1,1,2)
  1030.  
  1031. --Output to a chest or sit there
  1032. drop(dropSide, true)
  1033. --Display was moved above to be used in bedrock function
  1034. display()
  1035. --Log current mining run
  1036. logMiningRun(logExtension)
  1037.  
  1038. --Cleanup
  1039. turtle.getFuelLevel = getFuel
Add Comment
Please, Sign In to add comment