· 9 years ago · Nov 05, 2016, 09:24 AM
1{
2 {
3 path = "/getid/",
4 content = "turtle.dig()\
5turtle.forward()\
6peripheral.call(\"front\", \"getID\")\
7turtle.back()\
8turtle.place()",
9 },
10 {
11 path = "/portalFloor2/",
12 content = "turtle.select(1)\
13\
14for i = 1, 44 do\
15 turtle.digUp()\
16 turtle.up()\
17end\
18\
19turtle.dig()\
20turtle.forward()\
21\
22for i = 1, 66 do\
23 turtle.dig()\
24 turtle.forward()\
25end\
26\
27for i = 1, 66 do\
28 turtle.back()\
29end\
30\
31turtle.turnLeft()\
32turtle.turnLeft()\
33\
34for i = 1, 66 do\
35 while turtle.getItemCount() == 0 do\
36 turtle.select(turtle.getSelectedSlot() + 1)\
37 end\
38 turtle.place()\
39 turtle.back()\
40end\
41\
42turtle.place()\
43\
44turtle.back()\
45turtle.place()\
46\
47for i = 1, 45 do\
48 turtle.digDown()\
49 turtle.down()\
50end",
51 },
52 {
53 path = "/quarry/",
54 content = "--Civilwargeeky's Quarry Program--\
55 VERSION = \"3.6.4.5\"\
56--[[\
57Recent Changes:\
58 Parameter Files! Create a file of parameters, and use -file to load it!\
59 Works will with -forcePrompt\
60 Quarry no longer goes to start at end of row!\
61 Turtle can go left!\
62 QuadCopters! Check Lyqyd's thread\
63New Parameters:\
64 -overfuel/fuelMultiplier [number]: This number is is what neededFuel is multiplied by when fuel is low.\
65 -version: This will display the current version number and end the program\
66 -file [fileName]: This will load a custom configuration file (basically a list of parameters). \"##\" starts comment lines. In the future \"#\" will start programs to run (but only through shell)\
67 -preciseTotals [t/f]: If true, turtle will write exactly what it mined to the logs. It may also transmit it over rednet.\
68 -forcePrompt [param]: This will add to a list of parameters to force prompt for. So if you say \"-forcePrompt doRefuel\" it will prompt you \"Length\",\"Width\",\"Height\",\"Invert\",\"Do Refuel\" etc.\
69]]\
70--Defining things\
71civilTable = nil; _G.civilTable = {}; setmetatable(civilTable, {__index = getfenv()}); setfenv(1,civilTable)\
72originalDay = os.day() --Used in logging\
73numResumed = 0 --Number of times turtle has been resumed\
74-------Defaults for Arguments----------\
75--Arguments assignable by text\
76x,y,z = 3,3,3 --These are just in case tonumber fails\
77inverted = false --False goes from top down, true goes from bottom up [Default false]\
78rednetEnabled = false --Default rednet on or off [Default false]\
79--Arguments assignable by tArgs\
80dropSide = \"front\" --Side it will eject to when full or done [Default \"front\"]\
81careAboutResources = true --Will not stop mining once inventory full if false [Default true]\
82doCheckFuel = true --Perform fuel check [Default true]\
83doRefuel = false --Whenever it comes to start location will attempt to refuel from inventory [Default false]\
84keepOpen = 1 --How many inventory slots it will attempt to keep open at all times [Default 1]\
85fuelSafety = \"moderate\" --How much fuel it will ask for: safe, moderate, and loose [Default moderate]\
86excessFuelAmount = math.huge --How much fuel the turtle will get maximum. Limited by turtle.getFuelLimit in recent CC [Default math.huge]\
87fuelMultiplier = 1 --How much extra fuel turtle will ask for when it does need fuel [Default 1]\
88saveFile = \"Civil_Quarry_Restore\" --Where it saves restore data [Default \"Civil_Quarry_Restore\"]\
89autoResume = true --If true, turtle will auto-restart when loaded. [Default true]\
90startupRename = \"oldStartup.quarry\" --What the startup is temporarily renamed to [Default \"oldStartup.quarry\"]\
91startupName = \"startup\" --What the turtle auto-resumes with [Default \"startup\"]\
92doBackup = true --If it will keep backups for session persistence [Default true]\
93uniqueExtras = 8 --How many different items (besides cobble) the turtle expects. [Default 8]\
94maxTries = 200 --How many times turtle will try to dig a block before it \"counts\" bedrock [Default 200]\
95gpsEnabled = false -- If option is enabled, will attempt to find position via GPS api [Default false]\
96gpsTimeout = 3 --The number of seconds the program will wait to get GPS coords. Not in arguments [Default 3]\
97legacyRednet = false --Use this if playing 1.4.7\
98logging = true --Whether or not the turtle will log mining runs. [Default ...still deciding]\
99logFolder = \"Quarry_Logs\" --What folder the turtle will store logs in [Default \"Quarry_Logs\"]\
100logExtension = \"\" --The extension of the file (e.g. \".txt\") [Default \"\"]\
101flatBedrock = false --If true, will go down to bedrock to set startDown [Default false]\
102startDown = 0 --How many blocks to start down from the top of the mine [Default 0]\
103preciseTotals = false --If true, will record exact totals and names for all materials [Default false]\
104goLeftNotRight = false --Quarry to left, not right (parameter is \"left\") [Default false]\
105oreQuarry = false --Enables ore quarry functionality [Default false]\
106oreQuarryBlacklistName = \"oreQuarryBlacklist.txt\" --This is the file that will be parsed for item names [Default \"oreQuarryBlacklist\"]\
107dumpCompareItems = true --If ore quarry, the turtle will dump items compared to (like cobblestone) [Default true]\
108frontChest = false --If oreQuarry and chest checking, you can turn this on to make turtle check in front of itself for chests as well [Default false]\
109lavaBuffer = 500 --If using a lava bucket, this is the buffer it will wait for before checking for lava [Default 500]\
110inventoryMax = 16 --The max number of slots in the turtle inventory [Default 16] (Not assignable by parameter)\
111quadEnabled = false --Whether or not to request a quadRotor when out of fuel [Default false]\
112quadTimeout = 60 * 5 --How long the turtle will wait for a quadRotor [Default 5 minutes]\
113--Standard number slots for fuel (you shouldn't care)\
114fuelTable = { --Will add in this amount of fuel to requirement.\
115safe = 1000,\
116moderate = 200,\
117loose = 0 } --Default 1000, 200, 0\
118--Standard rednet channels\
119channels = {\
120send = os.getComputerID() + 1 ,\
121receive = os.getComputerID() + 101 ,\
122confirm = \"Turtle Quarry Receiver\",\
123message = \"Civil's Quarry\",\
124fingerprint = \"quarry\"\
125}\
126\
127--AVERAGE USER: YOU DON'T CARE BELOW THIS POINT\
128\
129local help_paragraph = [[\
130Welcome!: Welcome to quarry help. Below are help entries for all parameters. Examples and tips are at the bottom.\
131-default: This will force no prompts. If you use this and nothing else, only defaults will be used.\
132-dim: [length] [width] [height] This sets the dimensions for the quarry\
133-invert: [t/f] If true, quarry will be inverted (go up instead of down)\
134-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\
135-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\
136-autoResume / autoRestore: Turtle will automatically resume if stopped. Replaces startup\
137-oreQuarry: [t/f] If true, the turtle will use ore quarry mode. It will not mine the blocks that are placed in the turtle initially. So if you put in stone, it will ignore stone blocks and only mine ores.\
138-oreQuarry: [t/f] If you are using a newer version of CC, you won't have to put in any compare blocks. (CC 1.64+)\
139-blacklist: [file name] If using oreQuarry, this is the blacklist file it will read. Example --\
140 minecraft:stone\
141 minecraft:sand\
142 ThermalExpansion:Sponge\
143 ThermalFoundation:Storage\
144 \
145 Note: If you have bspkrsCore, look \
146 for \"UniqueNames.txt\" in your config\
147-file: [file name] Will load a file of parameters. One parameter per line. # is a comment line (See the forum thread for more detailed directions)\
148-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.\
149-doRefuel: [t/f] If true, the turtle will refuel itself with coal and planks it finds on its mining run\
150-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...\
151-overfuel: [number] When fuel is below required, fuel usage is multiplied by this. Large numbers permit more quarries without refueling\
152-fuelMultiplier: [number] See overfuel\
153-uniqueExtras: [number] The expected number of slots filled with low-stacking items like ore. Higher numbers request more fuel.\
154-maxFuel: [number] How much the turtle will fuel to max (limited by turtle in most cases)\
155-chest: [side] This specifies what side the chest at the end will be on. You can say \"top\", \"bottom\", \"front\", \"left\", or \"right\"\
156-enderChest: [slot] 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.\
157-fuelChest: [slot] See the above, but for a fueling chest. Reccommend use with -maxFuel and -doCheckFuel false\
158-lava: [slot] If using an oreQuarry, will fill itself with lava it finds to maxFuel\
159-lavaBuffer: [number] The amount of fuel below maxFuel the turtle will wait for before using lava again\
160-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\
161-quad: [t/f] This forces the use of GPS. Make sure you have a network set up. This will request to be refueled by a quadrotor from Lyqyd's mod if the turtle is out of fuel\
162-quadTimeout: [number] The amount of time the turtle will wait for a quadRotor\
163-sendChannel: [number] This is what channel your turtle will send rednet messages on\
164-receiveChannel: [number] This is what channel your turtle will receive rednet messages on\
165-legacyRednet: [t/f] Check true if using 1.4.7\
166-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\
167-startupRename: [file name] What to rename any existing startup to.\
168-startupName: [file name] What the turtle will save its startup file to.\
169-extraDropItems: [force] If oreQuarry then this will prompt the user for extra items to drop, but not compare to (like cobblestone)\
170-dumpCompareItems: [t/f] If oreQuarry and this is true, the turtle will dump off compare blocks instead of storing them in a chest\
171-oldOreQuarry: [t/f] If you are using new CC versions, you can use this to use the old oreQuarry.\
172-compareChest: [slot] If using oldOreQuarry, this will allow you to check for dungeon chests and suck from them.\
173-frontChest: [t/f] If using oreQuarry/oldOreQuarry, this will check in front of itself for chests as well.\
174-left: [t/f] If true, turtle will quarry to the left instead of the right\
175-maxTries: [number] This is the number of times the turtle will try to dig before deciding its run into bedrock.\
176-forcePrompt: [parameter] Whatever parameter you specify, it will always prompt you, like it does now for invert and dim.\
177-logging: [t/f] If true, will record information about its mining run in a folder at the end of the mining run\
178-preciseTotals: [t/f] If true (and turtle.inspect exists), it will log a detailed record of every block the turtle mines and send it over rednet\
179-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...)\
180-saveFile: [word] This is what the backup file will be called\
181-logFolder: [word] The folder that quarry logs will be stored in\
182-logExtension: [word] The extension given to each quarry log (e.g. \".txt\" or \".notepad\" or whatever)\
183-keepOpen: [number] This is the number of the slots the turtle will make sure are open. It will check every time it mines\
184-careAboutResources: [t/f] Who cares about the materials! If set to false, it will just keep mining when its inventory is full\
185-startDown: [number] If you set this, the turtle will go down this many blocks from the start before starting its quarry\
186 =\
187 C _ |\
188 |\
189 |\
190 |\
191 |_ _ _ _ >\
192-flatBedrock: [t/f] If true, turtle will find bedrock and \"zero\" itself so it ends on bedrock level\
193-promptAll: This is the opposite of -Default, it prompts for everything\
194-listParams: This will list out all your selected parameters and end quarry. Good for testing\
195-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\"\
196-version: Displays the current quarry version and stops the program\
197-help: Thats what this is :D\
198Examples: Everything below is examples and tips for use\
199Important Note:\
200 None of the above parameters are necessary. They all have default values, and the above are just if you want to change them.\
201Examples [1]:\
202 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\".\
203 You just told it to start a quarry with dimensions 10x6x3, and \"-default\" means it won't prompt you about invert or rednet. Wasn't that easy?\
204Examples [2]:\
205 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.\
206Examples [2] [cont.]:\
207 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\
208 \"quarry -dim 40x20x9 -invert false -startDown 45 -rednet true -enderChest 12 -restore\"\
209 BAM. Now you can just let that turtle do it's thing\
210Tips:\
211 The order of the parameters doesn't matter. \"quarry -invert false -rednet true\" is the same as \"quarry -rednet true -invert false\"\
212 \
213 Capitalization doesn't matter. \"quarry -iNVErt FALSe\" does the same thing as \"quarry -invert false\"\
214Tips [cont.]:\
215 For [t/f] parameters, you can also use \"yes\" and \"no\" so \"quarry -invert yes\"\
216 \
217 For [t/f] parameters, it only cares about the first letter. So you can use \"quarry -invert t\" or \"quarry -invert y\"\
218Tips [cont.]:\
219 If you are playing with fuel turned off, the program will automatically change settings for you so you don't have to :D\
220 \
221 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.\
222Internal Config:\
223 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.\
224 \
225 You can also use this if there are settings that you don't like the default value of.\
226]]\
227--NOTE: BIOS 114 MEANS YOU FORGOT A COLON\
228--NOTE: THIS ALSO BREAKS IF YOU REMOVE \"REDUNDANT\" WHITESPACE\
229--Parsing help for display\
230--[[The way the help table works:\
231All help indexes are numbered. There is a help[i].title that contains the title,\
232and the other lines are in help[i][1] - help[i][#help[i] ]\
233Different lines (e.g. other than first) start with a space.\
234As of now, the words are not wrapped, fix that later]]\
235local help = {}\
236local i = 0\
237local titlePattern = \".-%:\" --Find the beginning of the line, then characters, then a \":\"\
238local textPattern = \"%:.+\" --Find a \":\", then characters until the end of the line\
239for a in help_paragraph:gmatch(\"\\n?.-\\n\") do --Matches in between newlines\
240 local current = string.sub(a,1,-2)..\"\" --Concatenate Trick\
241 if string.sub(current,1,1) ~= \" \" then\
242 i = i + 1\
243 help[i] = {}\
244 help[i].title = string.sub(string.match(current, titlePattern),1,-2)..\"\"\
245 help[i][1] = string.sub(string.match(current,textPattern) or \" \",3,-1)\
246 elseif string.sub(current,1,1) == \" \" then\
247 table.insert(help[i], string.sub(current,2, -1)..\"\")\
248 end\
249end\
250\
251local supportsRednet\
252if peripheral.find then\
253 supportsRednet = peripheral.find(\"modem\") or false\
254else\
255 supportsRednet = (peripheral.getType(\"right\") == \"modem\") or false\
256end\
257\
258--Pre-defining variables that need to be saved\
259 xPos,yPos,zPos,facing,percent,mined,moved,relxPos, rowCheck, connected, isInPath, layersDone, attacked, startY, chestFull, gotoDest, atChest, fuelLevel, numDropOffs, allowedItems, compareSlots, dumpSlots, selectedSlot, extraDropItems, oldOreQuarry, specialSlots, relzPos, eventInsertionPoint\
260 = 0, 1, 1, 0, 0, 0, 0, 1, true , false, true, 1, 0, 0, false, \"\", false, 0, 0, {}, {}, {}, 1, false, false, {explicit = {}}, 0, 1\
261\
262--These are slot options that need to exist as variables for parameters to work.\
263 enderChest, fuelChest, lavaBucket, compareChest\
264= false, false, false, false\
265\
266local chestID, lavaID, lavaMeta = \"minecraft:chest\", \"minecraft:flowing_lava\", 0\
267\
268local statusString\
269\
270--Initializing various inventory management tables\
271for i=1, inventoryMax do\
272 allowedItems[i] = 0 --Number of items allowed in slot when dropping items\
273 dumpSlots[i] = false --Does this slot contain junk items?\
274end --compareSlots is a table of the compare slots, not all slots with a condition\
275totals = {cobble = 0, fuel = 0, other = 0} -- Total for display (cannot go inside function), this goes up here because many functions use it\
276\
277local function newSpecialSlot(index, value, explicit) --If isn't explicit, it will move whatever is already in the slot around to make room.\
278 value = tonumber(value) or 0 --We only want numerical indexes\
279 local flag = false --Used in slot moving, moved slot is returned for ease of use\
280 local function check(num) return num >= 1 and num <= inventoryMax end\
281 if not check(value) then error(\"from newSpecialSlot: number \"..value..\" out of range\",2) end\
282 local function getFirstFree(start)\
283 for i=1, math.max(inventoryMax-value,value-1) do\
284 for a=-1,1,2 do\
285 local num = value + (a*i)\
286 if check(num) and not specialSlots[num] then return num end\
287 end\
288 end\
289 return false\
290 end\
291 if specialSlots[value] and specialSlots[value] ~= index then --If we aren't trying to override the same slot :P\
292 if not explicit then\
293 value = getFirstFree(value) or error(\"from newSpecialSlots: all slots full, could not add\")\
294 elseif explicit and not specialSlots.explicit[value] then --Moving around other slots\
295 flag = getFirstFree(value)\
296 if not flag then error(\"from newSpecialSlots: could not add explicit in slot: \"..index..\" \"..value..\" Taken by \"..specialSlots[value],2) end\
297 specialSlots[flag] = specialSlots[value]\
298 specialSlots[specialSlots[value]] = flag --These will get set to the new thing later\
299 else\
300 error('You cannot put a \"'..index..'\" in the same slot as a \"'..specialSlots.explicit[value]..'\" (Slot '..value..\")\",0) --Show the user an understandable error :)\
301 end\
302 end\
303 specialSlots[index] = value\
304 specialSlots[value] = index\
305 if explicit then\
306 specialSlots.explicit[value] = index\
307 end\
308 return value, flag\
309end\
310\
311function resetDumpSlots()\
312 for i=1, inventoryMax do\
313 if oldOreQuarry then\
314 if turtle.getItemCount(i) > 0 and i~= specialSlots.enderChest then\
315 dumpSlots[i] = true\
316 else\
317 dumpSlots[i] = false\
318 end\
319 else\
320 dumpSlots[i] = false\
321 end\
322 end\
323 if not oldOreQuarry and specialSlots.enderChest == 1 then\
324 dumpSlots[2] = true\
325 elseif not oldOreQuarry then\
326 dumpSlots[1] = true\
327 end\
328end\
329\
330local function copyTable(tab) if type(tab) ~= \"table\" then error(\"copyTable received \"..type(tab)..\", expected table\",2) end local toRet = {}; for a, b in pairs(tab) do toRet[a] = b end; return toRet end --This goes up here because it is a basic utility\
331\
332--NOTE: rowCheck is a bit. true = \"right\", false = \"left\"\
333\
334local foundBedrock = false\
335\
336local checkFuel, checkFuelLimit\
337if turtle then --Function inits\
338 checkFuel = turtle.getFuelLevel\
339 if turtle.getFuelLevel() == \"unlimited\" then --Fuel is disabled --Unlimited screws up my calculations\
340 checkFuel = function() return math.huge end --Infinite Fuel\
341 end --There is no \"else\" because it will already return the regular getFuel\
342 if turtle.getFuelLimit then\
343 checkFuelLimit = function() return math.min(turtle.getFuelLimit(), excessFuelAmount) end --Return the limiting one\
344 if turtle.getFuelLimit() == \"unlimited\" then\
345 checkFuelLimit = function() return math.huge end\
346 end\
347 else\
348 checkFuelLimit = function() return excessFuelAmount end --If the function doesn't exist\
349 end\
350\
351\
352 turtle.select(1) --To ensure this is correct\
353end\
354\
355\
356function select(slot)\
357 if slot ~= selectedSlot and slot > 0 and slot <= inventoryMax then\
358 selectedSlot = slot\
359 return turtle.select(slot), selectedSlot\
360 end\
361end\
362\
363\
364 -----------------------------------------------------------------\
365--Input Phase\
366local function screen(xPos,yPos)\
367xPos, yPos = xPos or 1, yPos or 1\
368term.setCursorPos(xPos,yPos); term.clear(); end\
369local function screenLine(xPos,yPos)\
370term.setCursorPos(xPos,yPos); term.clearLine(); end\
371\
372screen(1,1)\
373print(\"----- Welcome to Quarry! -----\")\
374print(\"\")\
375\
376local sides = {top = \"top\", right = \"right\", left = \"left\", bottom = \"bottom\", front = \"front\"} --Used to whitelist sides\
377local tArgs --Will be set in initializeArgs\
378local originalArgs = {...}\
379local changedT, tArgsWithUpper, forcePrompts = {}, {}, {}\
380changedT.new = function(key, value, name) table.insert(changedT,{key, value, name}); if name then changedT[name] = #changedT end end --Numeric list of lists\
381changedT.remove = function(num) changedT[num or #changedT].hidden = true end --Note actually remove, just hide :)\
382local function capitalize(text) return (string.upper(string.sub(text,1,1))..string.sub(text,2,-1)) end\
383local function initializeArgs()\
384 tArgs = copyTable(originalArgs) --\"Reset\" tArgs\
385 for i=1, #tArgs do --My signature key-value pair system, now with upper\
386 tArgsWithUpper[i] = tArgs[i]\
387 tArgsWithUpper[tArgsWithUpper[i]] = i\
388 tArgs[i] = tArgs[i]:lower()\
389 tArgs[tArgs[i]] = i\
390 if tArgs[i] == \"-forceprompt\" and i ~= #tArgs then --If the prompt exists then add it to the list of prompts\
391 forcePrompts[tArgs[i+1]:lower()] = true\
392 end\
393 end\
394end\
395initializeArgs()\
396\
397local restoreFound, restoreFoundSwitch = false --Initializing so they are in scope\
398function parseParam(name, displayText, formatString, forcePrompt, trigger, variableOverride, variableExists) --Beware confusion, all ye who enter here\
399 --[[ Guide to Variables\
400 originalValue: what the variable was before the function\
401 givenValue: This is the value after the parameter. So -invert fAlSe, givenValue is \"fAlSe\"\
402 ]]\
403 if variableExists ~= false then variableExists = true end --Almost all params should have the variable exist. Some don't exist unless invoked\
404 if trigger == nil then trigger = true end --Defaults to being able to run\
405 if not trigger then return end --This is what the trigger is for. Will not run if trigger not there\
406 if restoreFoundSwitch or tArgs[\"-default\"] then forcePrompt = false end --Don't want to prompt if these. Default is no variable because resuming\
407 if not restoreFoundSwitch and (tArgs[\"-promptall\"] or forcePrompts[name:lower()]) then forcePrompt = true end --Won't prompt if resuming, can prompt all or checks list of prompts\
408 local toGetText = name:lower() --Because all params are now lowered\
409 local formatType = formatString:match(\"^%a+\"):lower() or error(\"Format String Unknown: \"..formatString) --Type of format string\
410 local args = formatString:match(\" (.+)\") or \"\"..\"\" --Everything in formatString after the type\
411 local variable = variableOverride or name --Goes first to the override for name\
412 local func = loadstring(\"return \"..variable) --Note to future self: If you want to remove loadstring, this breaks on tables. You will have to remove tables or figure something else out\
413 setfenv(func,getfenv(1))\
414 local originalValue = assert(func)() --This is the default value, for checking to add to changed table\
415 if originalValue == nil and variableExists then error(\"From addParam, \\\"\"..variable..\"\\\" returned nil\",2) end --I may have gotten a wrong variable name\
416 local givenValue, toRet, values --Initializing for use\
417 if tArgs[\"-\"..toGetText] then\
418 givenValue = tArgsWithUpper[tArgs[\"-\"..toGetText]+1] --This is the value after the desired parameter\
419 elseif forcePrompt then\
420 write(displayText..\"? \")\
421 givenValue = io.read()\
422 end\
423 if formatType == \"force\" then --This is the one exception. Should return true if givenValue is nothing\
424 toRet = (tArgs[\"-\"..toGetText] and true) or false --Will return true if param exists, otherwise false\
425 end\
426 if not (givenValue or toRet) or (type(givenValue) == \"string\" and #givenValue == 0) then return end --Don't do anything if you aren't given anything. Leave it as default, except for \"force\". Also don't want empty strings\
427 if formatType == \"boolean\" then --All the format strings will be basically be put through a switch statement\
428 toRet = givenValue:sub(1,1):lower() ~= \"n\" and givenValue:sub(1,1):lower() ~= \"f\" --Accepts anything but false or no\
429 elseif formatType == \"string\" then\
430 toRet = givenValue:match(\"^[%w%./]+\") --Basically anything not a space or control character etc\
431 elseif formatType == \"number\" or formatType == \"float\" then\
432 toRet = tonumber(givenValue) --Note this is a local, not the above so we don't change anything\
433 if not toRet then return end --We need a number... Otherwise compare errors\
434 if formatType == \"number\" then toRet = math.floor(toRet) end --Get proper integers\
435 local startNum, endNum = formatString:match(\"(%d+)%-(%d+)\") --Gets range of numbers\
436 startNum, endNum = tonumber(startNum), tonumber(endNum)\
437 if not ((toRet >= startNum) and (toRet <= endNum)) then return end --Can't use these\
438 elseif formatType == \"side\" then\
439 local exclusionTab = {} --Ignore the wizardry here. Just getting arguments without format string\
440 for a in args:gmatch(\"%S+\") do exclusionTab[a] = true end --This makes a list of the sides to not include\
441 if not exclusionTab[givenValue] then toRet = sides[givenValue] end --If side is not excluded\
442 elseif formatType == \"list\" then\
443 toRet = {}\
444 for a in args:gmatch(\"[^,]\") do\
445 table.insert(toRet,a)\
446 end\
447 elseif formatType == \"slot\" then\
448 if givenValue:sub(1,1):lower() == \"n\" or givenValue:sub(1,1):lower() == \"f\" then --Copied from boolean\
449 toRet = false\
450 else\
451 local userNumber, correction = givenValue:match(\"^%d+$\") --This makes sure the value is a number | Locally initialize correction\
452 toRet, correction = newSpecialSlot(variable, tonumber(userNumber or args), userNumber) --If givenValue was \"true\", it won't be explicit and will use default number\
453 if correction then changedT[changedT[specialSlots[correction]]][2] = tostring(correction) end --This changes the value field of the changedT index taken from the named pointer (which is the value in specialSlots under correction)\
454 end\
455 elseif formatType == \"force\" then --Do nothing, everything is already done\
456 else error(\"Improper formatType\",2)\
457 end\
458 if toRet == nil then return end --Don't want to set variables to nil... That's bad\
459 tempParam = toRet --This is what loadstring will see :D\
460 local func = loadstring(variable..\" = tempParam\")\
461 setfenv(func, getfenv(1)) --Note to future self: If you want to remove loadstring, this breaks on tables. You will have to remove tables or figure something else out\
462 func()\
463 tempParam = nil --Cleanup of global\
464 if toRet ~= originalValue and displayText ~= \"\" then\
465 changedT.new(displayText, tostring(toRet), variable)\
466 end\
467 return toRet\
468end\
469\
470local paramLookup = {}\
471local function addParam(...)\
472 local args = {...}\
473 if not paramLookup[args[1]] then\
474 local toRet = copyTable(args)\
475 for i=2, table.maxn(toRet) do --Have to do this because table.remove breaks on nil\
476 toRet[i-1] = toRet[i]\
477 end\
478 table.remove(toRet)\
479 paramLookup[args[1]] = toRet\
480 end\
481 return parseParam(unpack(args, 1, table.maxn(args)))\
482end\
483\
484local function paramAlias(original, alias)\
485 local a = paramLookup[original]\
486 if a then\
487 if a[5] == nil then a[5] = original end --This is variableOverride because the originals won't put a variable override\
488 return parseParam(alias, unpack(a, 1, table.maxn(a)))\
489 else\
490 error(\"In paramAlias: '\"..original..\"' did not exist\",2)\
491 end\
492end\
493\
494--Check if it is a turtle\
495if not(turtle or tArgs[\"help\"] or tArgs[\"-help\"] or tArgs[\"-?\"] or tArgs[\"?\"]) then --If all of these are false then\
496 print(\"This is not a turtle, you might be looking for the \\\"Companion Rednet Program\\\" \\nCheck My forum thread for that\")\
497 print(\"Press 'q' to quit, or any other key to start help \")\
498 if ({os.pullEvent(\"char\")})[2] ~= \"q\" then tArgs.help = true else error(\"\",0) end\
499end\
500\
501if tArgs[\"help\"] or tArgs[\"-help\"] or tArgs[\"-?\"] or tArgs[\"?\"] then\
502 print(\"You have selected help, press any key to continue\"); print(\"Use arrow keys to navigate, q to quit\"); os.pullEvent(\"key\")\
503 local pos = 1\
504 local key = 0\
505 while pos <= #help and key ~= keys.q do\
506 if pos < 1 then pos = 1 end\
507 screen(1,1)\
508 print(help[pos].title)\
509 for a=1, #help[pos] do print(help[pos][a]) end\
510 repeat\
511 _, key = os.pullEvent(\"key\")\
512 until key == 200 or key == 208 or key == keys.q\
513 if key == 200 then pos = pos - 1 end\
514 if key == 208 then pos = pos + 1 end\
515 end\
516 error(\"\",0)\
517end\
518\
519if tArgs[\"-version\"] or tArgs[\"version\"] then\
520 print(\"QUARRY VERSION: \",VERSION)\
521 error(\"\",0) --Exit not so gracefully\
522end\
523\
524--Loading custom parameter lists\
525local function split(str, sep)\
526 assert(#sep == 1, \"Split seperator too long. Got '\"..sep..\"'\")\
527 if not str:match(sep) then return {str} end --So everything else isn't pointless\
528 local toRet = {}\
529 toRet[1] = str:match(\"^([^\"..sep..\"]-)\"..sep)\
530 for i in str:gmatch(sep..\"([^\"..sep..\"]*)\") do --Matches not seperator chars\
531 toRet[#toRet+1] = i\
532 end\
533 return toRet\
534end\
535\
536if addParam(\"file\",\"Custom Parameters\",\"string\", false, nil, \"parameterFile\", false) and parameterFile then --This will not load when resuming because there is no \"file\" parameter when resuming.\
537 if not fs.exists(parameterFile) then\
538 print(\"WARNING: '\"..parameterFile..\"' DOES NOT EXIST. FILE NOT LOADED\")\
539 sleep(3)\
540 changedT.remove()\
541 else\
542 local file = fs.open(parameterFile, \"r\")\
543 local text = file.readAll()\
544 file.close()\
545 text = text..\"\\n\" --So that all replacements work properly\
546 text = text:gsub(\"#[^\\n]-\\n\",\"\") --Replace program codes/comment lines+\
547 local commands = {} --Contains all the parameters\
548 local append = table.insert\
549 for _, a in pairs(split(text,\"\\n\")) do\
550 local words = split(a,\" \")\
551 if not a:match(\"-\") then --This means only one command per line\
552 append(originalArgs,\"-\"..words[1])\
553 for i=2, #words do\
554 append(originalArgs, words[i])\
555 end\
556 else --Otherwise the dashes are already ordered where we want!\
557 for i=1, #words do\
558 append(originalArgs, words[i])\
559 end\
560 end\
561 end\
562 initializeArgs() --Manipulate the args again, because we modified them\
563 print(\"Finished loading file: \",tArgs[tArgs[\"-file\"]+1])\
564 sleep(0.5) --Give em a sec\
565 end\
566end\
567\
568\
569\
570--Saving\
571addParam(\"doBackup\", \"Backup Save File\", \"boolean\")\
572addParam(\"saveFile\", \"Save File Name\", \"string\")\
573\
574restoreFound = fs.exists(saveFile)\
575restoreFoundSwitch = (tArgs[\"-restore\"] or tArgs[\"-resume\"] or tArgs[\"-atchest\"]) and restoreFound and doBackup\
576if restoreFoundSwitch then\
577 local file = fs.open(saveFile,\"r\")\
578 local test = file.readAll() ~= \"\"\
579 file.close()\
580 if test then\
581 local temp = shell and copyTable(shell) --For whatever reason, the shell table doesn't survive resuming. shell and ... so that copyTable doesn't error\
582 os.run(getfenv(1),saveFile) --This is where the actual magic happens\
583 shell = temp\
584 numResumed = numResumed + 1\
585 if checkFuel() ~= math.huge then --If turtle uses fuel\
586 if fuelLevel - checkFuel() == 1 then\
587 if facing == 0 then xPos = xPos + 1\
588 elseif facing == 2 then xPos = xPos - 1\
589 elseif facing == 1 then zPos = zPos + 1\
590 elseif facing == 3 then zPos = zPos - 1 end\
591 elseif fuelLevel - checkFuel() ~= 0 then\
592 print(\"Very Strange Fuel in Restore Section...\")\
593 print(\"Current: \",checkFuel())\
594 print(\"Saved: \",fuelLevel)\
595 print(\"Difference: \",fuelLevel - checkFuel())\
596 os.pullEvent(\"char\")\
597 end\
598 end\
599 if gpsEnabled then --If it had saved gps coordinates\
600 print(\"Found GPS Start Coordinates\")\
601 local currLoc = {gps.locate(gpsTimeout)} or {}\
602 local backupPos = {xPos, yPos, zPos} --This is for comparing to later\
603 if #currLoc > 0 and #gpsStartPos > 0 and #gpsSecondPos > 0 then --Cover all the different positions I'm using\
604 print(\"GPS Position Successfully Read\")\
605 if currLoc[1] == gpsStartPos[1] and currLoc[3] == gpsStartPos[3] then --X coord, y coord, z coord in that order\
606 xPos, yPos, zPos = 0,1,1\
607 if facing ~= 0 then turnTo(0) end\
608 print(\"Is at start\")\
609 else\
610 if inverted then --yPos setting\
611 ------------------------------------------------FIX THIS\
612 end\
613 local a, b = copyTable(gpsStartPos), copyTable(gpsSecondPos) --For convenience\
614 local flag = true --So we can account for left quarry\
615 if b[3] - a[3] == -1 then--If went north (-Z)\
616 a[1] = a[1] - 1 --Shift x one to west to create a \"zero\"\
617 xPos, zPos = -currLoc[3] + a[3], currLoc[1] + -a[1]\
618 elseif b[1] - a[1] == 1 then--If went east (+X)\
619 a[3] = a[3] - 1 --Shift z up one to north to create a \"zero\"\
620 xPos, zPos = currLoc[1] + -a[1], currLoc[3] + -a[3]\
621 elseif b[3] - a[3] == 1 then--If went south (+Z)\
622 a[1] = a[1] + 1 --Shift x one to east to create a \"zero\"\
623 xPos, zPos = currLoc[3] + a[3], -currLoc[1] + a[3]\
624 elseif b[1] - a[1] == -1 then--If went west (-X)\
625 a[3] = a[3] + 1 --Shift z down one to south to create a \"zero\"\
626 xPos, zPos = -currLoc[1] + a[1], -currLoc[3] + a[3]\
627 else\
628 flag = false\
629 print(\"Improper Coordinates\")\
630 print(\"GPS Locate Failed, Using Standard Methods\") ----Maybe clean this up a bit to use flags instead.\
631 end\
632 if flag and goLeftNotRight then --This accounts for left quarry (barred to left only because there might be errors in a regular, causing neg/0\
633 zPos = math.abs(zPos-1) + 1\
634 end\
635 end\
636 print(\"X Pos: \",xPos)\
637 print(\"Y Pos: \",yPos)\
638 print(\"Z Pos: \",zPos)\
639 print(\"Facing: \",facing)\
640 for i=1, 3, 2 do --We want 1 and 3, but 2 could be coming back to start.\
641 if backupPos[i] ~= currLoc[i] then\
642 events = {} --We want to remove event queue if not in proper place, so won't turn at end of row or things.\
643 end\
644 end\
645 else\
646 print(\"GPS Locate Failed, Using Standard Methods\")\
647 end\
648 print(\"Restore File read successfully. Starting in 3\"); sleep(3)\
649 end\
650 else\
651 fs.delete(saveFile)\
652 print(\"Restore file was empty, sorry, aborting\")\
653 error(\"\",0)\
654 end\
655else --If turtle is just starting\
656 events = {} --This is the event queue :D\
657 originalFuel = checkFuel() --For use in logging. To see how much fuel is REALLY used\
658end\
659\
660--Dimensions\
661if tArgs[\"-dim\"] then\
662 local a,b,c = x,y,z\
663 local num = tArgs[\"-dim\"]\
664 x = tonumber(tArgs[num + 1]) or x; z = tonumber(tArgs[num + 2]) or z; y = tonumber(tArgs[num + 3]) or y\
665 if a ~= x then changedT.new(\"Length\", x) end\
666 if c ~= z then changedT.new(\"Width\", z) end\
667 if b ~= y then changedT.new(\"Height\", y) end\
668elseif not (tArgs[\"-default\"] or restoreFoundSwitch) then\
669 print(\"What dimensions?\")\
670 print(\"\")\
671 --This will protect from negatives, letters, and decimals\
672 term.write(\"Length? \")\
673 x = math.floor(math.abs(tonumber(io.read()) or x))\
674 term.write(\"Width? \")\
675 z = math.floor(math.abs(tonumber(io.read()) or z))\
676 term.write(\"Height? \")\
677 y = math.floor(math.abs(tonumber(io.read()) or y))\
678 changedT.new(\"Length\",x); changedT.new(\"Width\",z); changedT.new(\"Height\",y)\
679end\
680--Params: parameter/variable name, display name, type, force prompt, boolean condition, variable name override\
681--Invert\
682addParam(\"flatBedrock\",\"Go to bedrock\", \"boolean\") --Not done before GPS because GPS only runs on restart\
683addParam(\"invert\", \"Inverted\",\"boolean\", true, not flatBedrock, \"inverted\") --Not flat bedrock, because invert will be set to false\
684addParam(\"startDown\",\"Start Down\",\"number 1-256\", nil, not flatBedrock)\
685addParam(\"left\",\"Left Quarry\",\"boolean\", nil, nil, \"goLeftNotRight\")\
686--Inventory\
687addParam(\"chest\", \"Chest Drop Side\", \"side front\", nil, nil, \"dropSide\")\
688addParam(\"enderChest\",\"Ender Chest Slot\",\"slot 16\") --Note: All slots can be 16 and they will auto-assign, but I feel it is less confusing if they are always the same\
689addParam(\"fuelChest\",\"Fuel Chest Slot\",\"slot 15\")\
690--Rednet\
691addParam(\"rednet\", \"Rednet Enabled\",\"boolean\",true, supportsRednet, \"rednetEnabled\")\
692addParam(\"sendChannel\", \"Rednet Send Channel\", \"number 1-65535\", false, supportsRednet, \"channels.send\")\
693addParam(\"receiveChannel\",\"Rednet Receive Channel\", \"number 1-65535\", false, supportsRednet, \"channels.receive\")\
694addParam(\"fingerprint\",\"Sending Fingerprint\", \"string\", false, supportsRednet, \"channels.fingerprint\")\
695addParam(\"legacyRednet\",\"Legacy Rednet\",\"boolean\", false, supportsRednet)\
696--Quad Rotor --Must be before GPS\
697if addParam(\"quad\", \"Quad Rotor Enabled\",\"boolean\",nil, rednetEnabled, \"quadEnabled\") then --This returns true if param found :3\
698 gpsEnabled = true\
699end\
700addParam(\"quadTimeout\",\"Quad Rotor Timeout\",\"number 1-1000000\", nil, quadEnabled) --The amount of time to wait for a quadRotor\
701--GPS\
702addParam(\"gps\", \"GPS Location Services\", \"force\", nil, (not restoreFoundSwitch) and supportsRednet and not quadEnabled, \"gpsEnabled\" ) --Has these triggers so that does not record position if restarted.\
703if gpsEnabled and not restoreFoundSwitch then\
704 gpsStartPos = {gps.locate(gpsTimeout)} --Stores position in array\
705 gpsEnabled = #gpsStartPos > 0 --Checks if location received properly. If not, position is not saved\
706 if quadEnabled and not gpsEnabled then\
707 error(\"You have no GPS network. You may not use Quad Rotors\",0)\
708 end\
709end\
710--Fuel\
711addParam(\"uniqueExtras\",\"Unique Items\", \"number 0-15\")\
712addParam(\"doRefuel\", \"Refuel from Inventory\",\"boolean\", nil, checkFuel() ~= math.huge) --math.huge due to my changes\
713addParam(\"doCheckFuel\", \"Check Fuel\", \"boolean\", doCheckFuel and fuelChest, checkFuel() ~= math.huge) --Will prompt if doCheckFuel and fuelChest are on. Probably don't want\
714excessFuelAmount = excessFuelAmount or math.huge --Math.huge apparently doesn't save properly (Without saving, this is the config, on save it is actually set to nil if math.huge)\
715addParam(\"maxFuel\", \"Max Fuel\", \"number 1-999999999\", maxFuel == checkFuelLimit() and fuelChest, checkFuel() ~= math.huge, \"excessFuelAmount\") --Will prompt if fuel chest and the limit isn't changed\
716addParam(\"fuelMultiplier\", \"Fuel Multiplier\", \"float 1-9001\", nil, checkFuel() ~= math.huge)\
717paramAlias(\"fuelMultiplier\",\"fuelRequestMultiplier\")\
718paramAlias(\"fuelMultiplier\",\"overFuel\")\
719--Logging\
720addParam(\"logging\", \"Logging\", \"boolean\")\
721addParam(\"logFolder\", \"Log Folder\", \"string\")\
722addParam(\"logExtension\",\"Log Extension\", \"string\")\
723--Misc\
724addParam(\"startY\", \"Start Y\",\"number 1-256\")\
725addParam(\"maxTries\",\"Tries Before Bedrock\", \"number 1-9001\")\
726--Inventory\
727addParam(\"keepOpen\", \"Slots to Keep Open\", \"number 1-15\")\
728addParam(\"careAboutResources\", \"Care About Resources\",\"boolean\")\
729addParam(\"preciseTotals\",\"Precise Totals\",\"boolean\", rednetEnabled and turtle.inspect, turtle.getItemDetail ~= nil)\
730if preciseTotals and not restoreFoundSwitch then\
731 exactTotals = {} --Don't want to initialize if we aren't using this\
732end\
733--Auto Startup\
734addParam(\"autoResume\", \"Auto Resume\", \"boolean\", nil, doBackup)\
735paramAlias(\"autoResume\",\"autoRestart\")\
736addParam(\"startupRename\", \"Startup Rename\",\"string\", nil, autoResume)\
737addParam(\"startupName\", \"Startup File\", \"string\", nil, autoResume)\
738--Ore Quarry\
739addParam(\"oreQuarry\", \"Ore Quarry\", \"boolean\" )\
740if oreQuarry and not turtle.inspect then\
741 oldOreQuarry = true\
742 oreQuarry = false\
743end\
744addParam(\"lavaBucket\",\"Lava Bucket Slot\", \"slot 14\", nil, oreQuarry)\
745paramAlias(\"lavaBucket\",\"lava\")\
746paramAlias(\"lavaBucket\",\"lavaRefuel\")\
747addParam(\"lavaBuffer\",\"Lava Buffer\",\"number 1-19999\", nil, lavaBucket)\
748--Old Ore\
749addParam(\"oldOreQuarry\", \"Old Ore Quarry\", \"boolean\")\
750addParam(\"dumpCompareItems\", \"Dump Compare Items\", \"boolean\", nil, oldOreQuarry) --Do not dump compare items if not oreQuarry\
751addParam(\"extraDropItems\", \"\", \"force\", nil, oldOreQuarry) --Prompt for extra dropItems\
752paramAlias(\"extraDropItems\",\"extraDumpItems\") --changed to Dump\
753addParam(\"compareChest\",\"Compare Chest Slot\",\"slot 13\", nil, oldOreQuarry)\
754addParam(\"frontChest\",\"Front Chest Check\",\"boolean\", nil, compareChest or turtle.insepect) --Does not need oreQuarry, but is similar (does need inspect if not compareChest)\
755--New Ore\
756addParam(\"blacklist\",\"Ore Blacklist\", \"string\", nil, oreQuarry, \"oreQuarryBlacklistName\")\
757paramAlias(\"blacklist\",\"blacklistFile\")\
758--Mod Related\
759\
760--Extra\
761if tArgs[\"-testparams\"] then\
762 screen()\
763 print(\"KEY: VALUE (VARIABLE)\")\
764 for key, val in ipairs(changedT) do\
765 if not val.hidden then\
766 print(val[1],\": \",val[2],\" (\",val[3] or \"\",\")\")\
767 end\
768 end\
769 error(\"Done\",0)\
770end\
771 \
772\
773--for flatBedrock\
774if flatBedrock then\
775 inverted = false\
776end\
777\
778--Auto Startup functions\
779local function doAutoResumeStuff()\
780 if fs.exists(startupName) then\
781 if fs.exists(startupRename) then fs.delete(startupRename) end\
782 fs.move(startupName, startupRename)\
783 end\
784 local file = fs.open(startupName,\"w\") --Startup File\
785 file.writeLine( --The below is on the left because spacing\
786[[\
787--This is an auto-generated startup\
788--Made by civilwargeeky's Variable Size Quarry\
789print(\"Now Resuming Quarry\")\
790print(\"Press any key to quit. You have 5 seconds.\")\
791function deleteStuff()\
792 fs.delete(\"]]..startupName..[[\")\
793 if fs.exists(\"]]..startupRename..[[\") then\
794 fs.move(\"]]..startupRename..\"\\\",\\\"\"..startupName..[[\")\
795 end\
796end\
797local event\
798if fs.exists(\"]]..saveFile..[[\") then\
799 for i=5,1,-1 do\
800 print(i)\
801 os.startTimer(1)\
802 event = os.pullEvent()\
803 if event == \"key\" then break end\
804 end\
805 if event == \"timer\" then\
806 os.run({},\"]]..shell.getRunningProgram()..[[\",\"-resume\")\
807 else\
808\
809 deleteStuff()\
810 end\
811else\
812 print(\"Never mind, no save file found\")\
813 deleteStuff()\
814end\
815 ]])\
816 file.close()\
817end\
818if autoResume and not restoreFoundSwitch then --Don't do for restore because would overwrite renamed thing. Can't edit mid-run because no shell in restarted\
819 doAutoResumeStuff()\
820end\
821--oreQuarry blacklist\
822local blacklist = { \"minecraft:air\", \"minecraft:bedrock\", \"minecraft:cobblestone\", \"minecraft:dirt\", \"minecraft:ice\", \"minecraft:ladder\", \"minecraft:netherrack\", \"minecraft:sand\", \"minecraft:sandstone\",\
823 \"minecraft:snow\", \"minecraft:snow_layer\", \"minecraft:stone\", \"minecraft:gravel\", \"minecraft:grass\", \"minecraft:torch\" }\
824for a,b in pairs(copyTable(blacklist)) do\
825 blacklist[b], blacklist[a] = true, nil --Switch\
826end\
827if fs.exists(oreQuarryBlacklistName) then --Loading user-defined blacklist\
828 local file = fs.open(oreQuarryBlacklistName, \"r\")\
829 blacklist = {}\
830 for a in file:readAll():gmatch(\"[^,\\n]+\") do\
831 blacklist[a:match(\"[%w_.]+:[%w_.]+\")] = true --Grab only the actual characters, not whitespaces\
832 end\
833 file:close()\
834end\
835\
836--Manual Position\
837if tArgs[\"-manualpos\"] then --Gives current coordinates in xPos,zPos,yPos, facing\
838 local a = tArgs[\"-manualpos\"]\
839 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\
840 changedT.new(\"xPos\",xPos); changedT.new(\"zPos\",zPos); changedT.new(\"yPos\",yPos); changedT.new(\"facing\",facing)\
841 restoreFoundSwitch = true --So it doesn't do beginning of quarry behavior\
842 for i=0,4 do tArgs[a+i] = \"\" end --Get rid of this argument from future restores\
843end\
844if 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.\
845 local neededLayer = math.floor((yPos+1)/3)*3-1 --Make it a proper layer, +- because mining rows are 2, 5, etc.\
846 if neededLayer > 2 and neededLayer%3 ~= 2 then --If turtle was not on a proper mining layer\
847 print(\"Last known pos was not in proper layer, restarting quarry\")\
848 sleep(4)\
849 neededLayer = 2\
850 end\
851 xPos, zPos, yPos, facing, rowCheck, layersDone = 0,1,1, 0, true, math.ceil(neededLayer/3)\
852 doAutoResumeStuff() --This was probably deleted when they hit a key to launch with -atChest\
853 events = {{\"goto\",1,1,neededLayer, 0}}\
854end\
855\
856\
857local function saveProgress(extras) --Session persistence\
858exclusions = { modem = true, shell = true, _ENV = true}\
859if doBackup then\
860local toWrite = \"\"\
861for a,b in pairs(getfenv(1)) do\
862 if not exclusions[a] then\
863 --print(a ,\" \", b, \" \", type(b)) --Debug\
864 if type(b) == \"string\" then b = \"\\\"\"..b..\"\\\"\" end\
865 if type(b) == \"table\" then b = textutils.serialize(b) end\
866 if type(b) ~= \"function\" then\
867 toWrite = toWrite..a..\" = \"..tostring(b)..\"\\n\"\
868 end\
869 end\
870end\
871toWrite = toWrite..\"doCheckFuel = false\\n\" --It has already used fuel, so calculation unnecessary\
872local file\
873repeat\
874 file = fs.open(saveFile,\"w\")\
875until file\
876file.write(toWrite)\
877if type(extras) == \"table\" then\
878 for a, b in pairs(extras) do\
879 file.write(a..\" = \"..tostring(b)..\"\\n\")\
880 end\
881end\
882if checkFuel() ~= math.huge then --Used for location comparing\
883 file.write(\"fuelLevel = \"..tostring(checkFuel())..\"\\n\")\
884end\
885file.close()\
886end\
887end\
888\
889local area = x*z\
890local volume = x*y*z\
891local lastHeight = y%3\
892layers = math.ceil(y/3)\
893local yMult = layers --This is basically a smart y/3 for movement\
894local moveVolume = (area * yMult) --Kept for display percent\
895--Calculating Needed Fuel--\
896do --Because many local variables unneeded elsewhere\
897 local changeYFuel = 2*(y + startDown)\
898 local dropOffSupplies = 2*(x + z + y + startDown) --Assumes turtle as far away as possible, and coming back\
899 local frequency = math.ceil(((moveVolume/(64*(15-uniqueExtras) + uniqueExtras)) ) ) --This is complicated: volume / inventory space of turtle, defined as 64*full stacks + 1 * unique stacks.\
900 --max of 15 full stacks because once one item is picked up, slot is \"full\". Ceil to count for initial back and forth\
901 if enderChest then frequency = 0 end --Never goes back to start\
902 neededFuel = moveVolume + changeYFuel + (frequency * dropOffSupplies) + ((x + z) * layers) --x + z *layers because turtle has to come back from far corner every layer\
903 neededFuel = neededFuel + fuelTable[fuelSafety] --For safety\
904end\
905\
906if neededFuel > checkFuelLimit() and doCheckFuel then--Checks for if refueling goes over turtle fuel limit\
907 if not (doRefuel or fuelChest) then\
908 screen()\
909 print(\"Turtle cannot hold enough fuel\\n\")\
910 print(\"Options: \\n1. Select a smaller size \\n2. Enable Mid-Run Refueling (RECOMMENDED) \\n3. Turn fuel checking off (only if fuel chest) \\n4. Do nothing\")\
911 local _, key = os.pullEvent(\"char\")\
912 if key == \"1\" then\
913 screen(); print(\"Okay\"); error(\"\",0)\
914 elseif key == \"3\" then\
915 doCheckFuel = false\
916 elseif key == \"4\" then\
917 --pass\
918 else --Not for number two because this is default\
919 doRefuel = true\
920 end\
921 end\
922 neededFuel = checkFuelLimit()-checkFuel()-1\
923end\
924\
925\
926--Getting Fuel\
927local hasRefueled --This is for oldOreQuarry prompting\
928if doCheckFuel and checkFuel() < neededFuel then\
929 neededFuel = math.min(math.floor(neededFuel * fuelMultiplier), checkFuelLimit()-checkFuel()-1) --Does the same as above, but not verbose because optional\
930 hasRefueled = true\
931 print(\"Not enough fuel\")\
932 print(\"Current: \",checkFuel(),\" Needed: \",neededFuel)\
933 print(\"Starting SmartFuel...\")\
934 sleep(2) --So they can read everything.\
935 term.clear()\
936 local oneFuel, neededFuelItems = 0,0 --Initializing Variables\
937 local currSlot = 0\
938 local function output(text, x, y) --For displaying fuel statistics\
939 local currX, currY = term.getCursorPos()\
940 term.setCursorPos(x,y)\
941 term.clearLine()\
942 term.write(text)\
943 term.setCursorPos(currX,currY)\
944 end\
945 local function roundTo(num, target) --For stacks of fuel and turtle slots when undergoing addition/subtraction\
946 if num >= target then return target elseif num < 0 then return 0 else return num end\
947 end\
948 local function updateScreen()\
949 output(\"Welcome to SmartFuel! Now Refueling...\", 1,1)\
950 output(\"Fuel Request Multiplier: \"..tostring(fuelMultiplier)..\"x\",1,2)\
951 output(\"Currently taking fuel from slot \"..currSlot,1,3)\
952 output(\"Current single fuel: \"..tostring(oneFuel or 0),1,4)\
953 output(\"Current estimate of needed fuel: \",1,4)\
954 output(\"Single Items: \"..math.ceil(neededFuelItems),4,6)\
955 output(\"Stacks: \"..math.ceil(neededFuelItems / 64),4,7)\
956 output(\"Needed Fuel: \"..tostring(neededFuel),1,12)\
957 output(\"Current Fuel: \"..tostring(checkFuel()),1,13)\
958 end\
959 while checkFuel() < neededFuel do\
960 currSlot = currSlot + 1\
961 select(currSlot)\
962 if currSlot ~= 1 and not turtle.refuel(0) then --If it's not the first slot, and not fuel, go back to start\
963 currSlot = 1; select(currSlot)\
964 end\
965 updateScreen()\
966 while turtle.getItemCount(currSlot) == 0 do\
967 sleep(1.5)\
968 end\
969 repeat --TODO: Probably unnecessary loop, remove later\
970 local previous = checkFuel()\
971 turtle.refuel(1)\
972 oneFuel = checkFuel() - previous\
973 updateScreen()\
974 until (oneFuel or 0) > 0 --Not an if to prevent errors if fuel taken out prematurely.\
975 neededFuelItems = math.ceil((neededFuel - checkFuel()) / oneFuel)\
976 turtle.refuel(roundTo(neededFuelItems, 64)) --Change because can only think about 64 at once.\
977 if turtle.getItemCount(roundTo(currSlot + 1, inventoryMax)) == 0 then --Resets if no more fuel\
978 currSlot = 0\
979 end\
980 neededFuelItems = math.ceil((neededFuel - checkFuel()) / oneFuel) --This line is not repeated uselessly, it's for the display function\
981 end\
982 select(1)\
983end\
984--Ender Chest Obtaining\
985function promptSpecialSlot(specialSlot, name, limit)\
986 local function isInRange(toCheck, lower, upper) return toCheck <= upper and toCheck >= lower end\
987 while not isInRange(turtle.getItemCount(specialSlots[specialSlot]), 1, limit or 1) do\
988 screen(1,1)\
989 print(\"You have decided to use a \",name,\"!\")\
990 print(\"Please place one \",name,\" in slot \",specialSlots[specialSlot])\
991 sleep(1)\
992 end\
993 print(name,\" in slot \",specialSlots[specialSlot], \" checks out\")\
994end\
995function checkSpecialSlot(specialSlot, name, allowed)\
996 if restoreFoundSwitch and turtle.getItemCount(specialSlots[specialSlot]) == 0 then --If the turtle was stopped while dropping off items.\
997 select(specialSlots[specialSlot])\
998 turtle.dig()\
999 select(1)\
1000 end\
1001 promptSpecialSlot(specialSlot, name, allowed)\
1002 allowedItems[specialSlots[specialSlot]] = 1\
1003 sleep(1)\
1004end\
1005if enderChest then\
1006 checkSpecialSlot(\"enderChest\",\"Ender Chest\")\
1007end\
1008if fuelChest then\
1009 checkSpecialSlot(\"fuelChest\",\"Fuel Chest\")\
1010end\
1011if lavaBucket then\
1012 checkSpecialSlot(\"lavaBucket\",\"Empty Bucket\")\
1013 select(specialSlots.lavaBucket)\
1014 if turtle.refuel(1) then --Just in case they actually put in a lava bucket >:(\
1015 print(\"No! You're supposed to put in an empty bucket\") --This doubles as emptying the lava bucket if mid-run\
1016 sleep(2)\
1017 end\
1018 select(1)\
1019end\
1020if compareChest then\
1021 checkSpecialSlot(\"compareChest\",\"Chest\", 64)\
1022end\
1023\
1024--Setting which slots are marked as compare slots\
1025if oldOreQuarry then\
1026 if not restoreFoundSwitch then --We don't want to reset compare blocks every restart\
1027 local counter = 0\
1028 for i=1, inventoryMax do if turtle.getItemCount(i) > 0 and not specialSlots[i] then counter = counter+1 end end --If the slot has items, but isn't enderChest slot if it is enabled\
1029\
1030 screen(1,1)\
1031 print(\"You have selected an Ore Quarry!\")\
1032 if counter == 0 or hasRefueled then --If there are no compare slots, or the turtle has refueled, and probably has fuel in inventory\
1033 print(\"Please place your compare blocks in the first slots\\n\")\
1034\
1035 print(\"Press Enter when done\")\
1036 repeat until ({os.pullEvent(\"key\")})[2] == 28 --Should wait for enter key to be pressed\
1037 else\
1038 print(\"Registering slots as compare slots\")\
1039 sleep(1)\
1040 end\
1041 for i=1, inventoryMax do\
1042 if turtle.getItemCount(i) > 0 then\
1043 if not specialSlots[i] then\
1044 table.insert(compareSlots, i) --Compare slots are ones compared to while mining. Conditions are because we Don't want to compare to enderChest\
1045 allowedItems[i] = 1 --Blacklist is for dropping off items. The number is maximum items allowed in slot when dropping off\
1046 dumpSlots[i] = true --We also want to ignore all excess of these items, like dirt\
1047 end\
1048 end\
1049 end\
1050 if extraDropItems then\
1051 screen(1,1)\
1052 print(\"Put in extra drop items now\\n\")\
1053 print(\"Press Enter when done\")\
1054 repeat until ({os.pullEvent(\"key\")})[2] == 28 --Should wait for enter key to be pressed\
1055 for i=1,inventoryMax do\
1056 if not dumpSlots[i] and turtle.getItemCount(i) > 0 then --I don't want to modify from above, so I check it hasn't been assigned.\
1057 dumpSlots[i] = true\
1058 allowedItems[i] = 1\
1059 end\
1060 end\
1061 end\
1062 --This is could go very wrong if this isn't here\
1063 if #compareSlots >= inventoryMax-keepOpen then screen(1,1); error(\"You have more quarry compare items than keep open slots, the turtle will continuously come back to start. Please fix.\",0) end\
1064 end\
1065 local counter = 0\
1066 for a, b in pairs(compareSlots) do if turtle.getItemCount(b) > 0 then counter = counter + 1 end end\
1067 if counter == 0 then\
1068 screen(1,1)\
1069 print(\"You have an ore quarry without any compare slots. Continue? y/n\")\
1070 if ({os.pullEvent(\"char\")})[2] ~= \"y\" then error(\"\",0) end\
1071 end\
1072elseif not oreQuarry then --This was screwing up dumpCompareItems\
1073 dumpCompareItems = false --If not an ore quarry, this should definitely be false\
1074 if specialSlots.enderChest == 1 then\
1075 dumpSlots[2] = true\
1076 else\
1077 dumpSlots[1] = true\
1078 end\
1079end\
1080\
1081--Rednet Handshake\
1082function newMessageID()\
1083 return math.random(1,2000000000)\
1084end\
1085function sendMessage(send, receive, message)\
1086 if legacyRednet then\
1087 if type(message) == \"table\" then message = textutils.serialize(message) end\
1088 return modem.transmit(send, receive, message)\
1089 end\
1090 return modem.transmit(send , receive, {fingerprint = channels.fingerprint, id = newMessageID(), message = message})\
1091end\
1092if rednetEnabled then\
1093 screen(1,1)\
1094 print(\"Rednet is Enabled\")\
1095 print(\"The Channel to open is \"..channels.send)\
1096 if peripheral.find then\
1097 modem = peripheral.find(\"modem\")\
1098 else\
1099 modem = peripheral.wrap(\"right\")\
1100 end\
1101 modem.open(channels.receive)\
1102 local i = 0\
1103 repeat\
1104 local id = os.startTimer(3)\
1105 i=i+1\
1106 print(\"Sending Initial Message \"..i)\
1107 sendMessage(channels.send, channels.receive, channels.message)\
1108 local message = {} --Have to initialize as table to prevent index nil\
1109 repeat\
1110 local event, idCheck, channel,_,locMessage, distance = os.pullEvent()\
1111 if locMessage then message = locMessage end\
1112 if legacyRednet then --For that one guy that uses 1.4.7\
1113 message = {message = message}\
1114 end\
1115 until (event == \"timer\" and idCheck == id) or (event == \"modem_message\" and channel == channels.receive and type(message) == \"table\")\
1116 until message.message == channels.confirm\
1117 connected = true\
1118 print(\"Connection Confirmed!\")\
1119 sleep(1.5)\
1120end\
1121function biometrics(isAtBedrock, requestQuad)\
1122 if not rednetEnabled then return end --This function won't work if rednet not enabled :P\
1123 local toSend = { label = os.getComputerLabel() or \"No Label\", id = os.getComputerID(),\
1124 percent = percent, zPos = relzPos, xPos = relxPos, yPos = yPos,\
1125 layersDone = layersDone, x = x, z = z, layers = layers,\
1126 openSlots = getNumOpenSlots(), mined = mined, moved = moved,\
1127 chestFull = chestFull, isAtChest = (xPos == 0 and yPos == 1 and zPos == 1),\
1128 isGoingToNextLayer = (gotoDest == \"layerStart\"), foundBedrock = foundBedrock,\
1129 fuel = checkFuel(), volume = volume, status = statusString,\
1130 }\
1131 if requestQuad and isInPath then --If we are requesting a quadRotor to send help\
1132 if not gps.locate(gpsTimeout) then\
1133 print(\"\\nOH NOES! Trying to reach quadrotor, but can't get GPS position!\")\
1134 sleep(1)\
1135 else\
1136 toSend.firstPos = gpsStartPos\
1137 toSend.secondPos = gpsSecondPos\
1138 toSend.emergencyLocation = {gps.locate(gpsTimeout)}\
1139 end\
1140 end\
1141 sendMessage(channels.send, channels.receive, toSend)\
1142 id = os.startTimer(0.1)\
1143 local event, received\
1144 repeat\
1145 local locEvent, idCheck, confirm, _, locMessage, distance = os.pullEvent()\
1146 event, received = locEvent, locMessage or {message = \"\"}\
1147 if legacyRednet and type(received) == \"string\" then\
1148 received = {message = received}\
1149 end\
1150 until (event == \"timer\" and idCheck == id) or (event == \"modem_message\" and confirm == channels.receive and type(received) == \"table\")\
1151 if event == \"modem_message\" then connected = true else connected = false end\
1152 local message = received.message:lower()\
1153 if message == \"stop\" or message == \"quit\" or message == \"kill\" then\
1154 count(true)\
1155 display()\
1156 error(\"Rednet said to stop...\",0)\
1157 end\
1158 if message == \"return\" then\
1159 endingProcedure()\
1160 error('Rednet said go back to start...',0)\
1161 end\
1162 if message == \"drop\" then\
1163 dropOff()\
1164 end\
1165 if message == \"pause\" then\
1166 print(\"\\nTurtle is paused. Send 'resume' or press any character to resume\")\
1167 statusString = \"Paused\"\
1168 toSend.status = statusString\
1169 os.startTimer(3)\
1170 repeat --The turtle sends out periodic messages, which will clear the receiver's queue and send a message (if it exists)\
1171 --This may be a bit overkill, sending the whole message again, but whatever.\
1172 local event, idCheck, confirm, _, message, distance = os.pullEvent()\
1173 if event == \"timer\" then os.startTimer(3); sendMessage(channels.send, channels.receive, toSend) end --Only send messages on the timer. This prevents ridiculous spam\
1174 until (event == \"modem_message\" and confirm == channels.receive and (message.message == \"resume\" or message.message == \"unpause\" or message.message == \"pause\")) or (event == \"char\")\
1175 statusString = nil\
1176 end\
1177 if message == \"refuel\" then\
1178 print(\"\\nEngaging in emergency refueling\")\
1179 emergencyRefuel(true)\
1180 end\
1181\
1182end\
1183--Showing changes to settings\
1184screen(1,1)\
1185print(\"Your selected settings:\")\
1186if #changedT == 0 then\
1187 print(\"Completely Default\")\
1188 else\
1189 for i=1, #changedT do\
1190 if not changedT[i].hidden then\
1191 print(changedT[i][1],\": \",changedT[i][2]) --Name and Value\
1192 end\
1193 end\
1194end\
1195print(\"\\nStarting in 3\"); sleep(1); print(\"2\"); sleep(1); print(\"1\"); sleep(1.5) --Dramatic pause at end\
1196\
1197\
1198\
1199----------------------------------------------------------------\
1200--Define ALL THE FUNCTIONS\
1201--Event System Functions\
1202function eventSetInsertionPoint(num)\
1203 eventInsertionPoint = num or 1\
1204end\
1205function eventAddAt(pos, ...)\
1206 return table.insert(events,pos, {...}) or true\
1207end\
1208function eventAdd(...) --Just a wrapper\
1209 return eventAddAt(eventInsertionPoint, ...)\
1210end\
1211function eventGet(pos)\
1212 return events[tonumber(pos) or #events]\
1213end\
1214function eventPop(pos)\
1215 return table.remove(events,tonumber(pos) or #events) or false --This will return value popped, tonumber returns nil if fail, so default to end\
1216end\
1217function eventRun(value, ...)\
1218 local argsList = {...}\
1219 if type(value) == \"string\" then\
1220 if value:sub(-1) ~= \")\" then --So supports both \"up()\" and \"up\"\
1221 value = value .. \"(\"\
1222 for a, b in pairs(argsList) do --Appending arguments\
1223 local toAppend\
1224 if type(b) == \"table\" then toAppend = textutils.serialize(b)\
1225 elseif type(b) == \"string\" then toAppend = \"\\\"\"..tostring(b)..\"\\\"\" --They weren't getting strings around them\
1226 else toAppend = tostring(b) end\
1227 value = value .. (toAppend or \"true\") .. \", \"\
1228 end\
1229 if value:sub(-1) ~= \"(\" then --If no args, do not want to cut off\
1230 value = value:sub(1,-3)..\"\"\
1231 end\
1232 value = value .. \")\"\
1233 end\
1234 --print(value) --Debug\
1235 local func = loadstring(value)\
1236 setfenv(func, getfenv(1))\
1237 return func()\
1238 end\
1239end\
1240function eventClear(pos)\
1241 if pos then events[pos] = nil else events = {} end\
1242end\
1243function runAllEvents()\
1244 while #events > 0 do\
1245 local toRun = eventGet()\
1246 --print(toRun[1]) --Debug\
1247 eventRun(unpack(toRun))\
1248 eventPop()\
1249 end\
1250end\
1251\
1252--Display Related Functions\
1253function display() --This is just the last screen that displays at the end\
1254 screen(1,1)\
1255 print(\"Total Blocks Mined: \"..mined)\
1256 print(\"Current Fuel Level: \"..checkFuel())\
1257 print(\"Cobble: \"..totals.cobble)\
1258 print(\"Usable Fuel: \"..totals.fuel)\
1259 print(\"Other: \"..totals.other)\
1260 if rednetEnabled then\
1261 print(\"\")\
1262 print(\"Sent Stop Message\")\
1263 if legacyRednet then --This was the traditional stopping signal\
1264 print(\"Sent Legacy Stop\")\
1265 sendMessage(channels.send, channels.receive, \"stop\")\
1266 end\
1267 local finalTable = {mined = mined, cobble = totals.cobble, fuelblocks = totals.fuel,\
1268 other = totals.other, fuel = checkFuel(), isDone = true }\
1269 if preciseTotals then\
1270 finalTable.preciseTotals = exactTotals --This table doubles as a flag.\
1271 end\
1272 sendMessage(channels.send,channels.receive, finalTable)\
1273 modem.close(channels.receive)\
1274 end\
1275 if doBackup then\
1276 fs.delete(saveFile)\
1277 if autoResume then --Getting rid of the original startup files and replacing\
1278 fs.delete(startupName)\
1279 if fs.exists(startupRename) then\
1280 fs.move(startupRename, startupName)\
1281 end\
1282 end\
1283 end\
1284end\
1285function updateDisplay() --Runs in Mine(), display information to the screen in a certain place\
1286screen(1,1)\
1287print(\"Blocks Mined\")\
1288print(mined)\
1289print(\"Percent Complete\")\
1290print(percent..\"%\")\
1291print(\"Fuel\")\
1292print(checkFuel())\
1293 -- screen(1,1)\
1294 -- print(\"Xpos: \")\
1295 -- print(xPos)\
1296 -- print(\"RelXPos: \")\
1297 -- print(relxPos)\
1298 -- print(\"Z Pos: \")\
1299 -- print(zPos)\
1300 -- print(\"Y pos: \")\
1301 -- print(yPos)\
1302if rednetEnabled then\
1303screenLine(1,7)\
1304print(\"Connected: \"..tostring(connected))\
1305end\
1306end\
1307--Utility functions\
1308local function pad(str, length, side)\
1309 toRet = \"\"\
1310 if side == \"right\" then\
1311 toRet = str\
1312 end\
1313 for i=1, length-#str do\
1314 toRet = toRet..\" \"\
1315 end\
1316 if side == \"left\" then\
1317 toRet = toRet..str\
1318 end\
1319 return toRet\
1320end\
1321function logMiningRun(textExtension, extras) --Logging mining runs\
1322 if not logging then return end\
1323 local number, name = 0\
1324 if not fs.isDir(logFolder) then\
1325 fs.delete(logFolder)\
1326 fs.makeDir(logFolder)\
1327 end\
1328 repeat\
1329 number = number + 1 --Number will be at least 2\
1330 name = logFolder..\"/Quarry_Log_\"..tostring(number)..(textExtension or \"\")\
1331 until not fs.exists(name)\
1332 local handle = fs.open(name,\"w\")\
1333 local function write(...)\
1334 for a, b in ipairs({...}) do\
1335 handle.write(tostring(b))\
1336 end\
1337 handle.write(\"\\n\")\
1338 end\
1339 local function boolToText(bool) if bool then return \"Yes\" else return \"No\" end end\
1340 write(\"Welcome to the Quarry Logs!\")\
1341 write(\"Entry Number: \",number)\
1342 write(\"Quarry Version: \",VERSION)\
1343 write(\"Dimensions (X Z Y): \",x,\" \",z,\" \", y)\
1344 write(\"Blocks Mined: \", mined)\
1345 write(\" Cobble: \", totals.cobble)\
1346 write(\" Usable Fuel: \", totals.fuel)\
1347 write(\" Other: \",totals.other)\
1348 write(\"Total Fuel Used: \", (originalFuel or (neededFuel + checkFuel()))- checkFuel()) --Protect against errors with some precision\
1349 write(\"Expected Fuel Use: \", neededFuel)\
1350 write(\"Days to complete mining run: \",os.day()-originalDay)\
1351 write(\"Day Started: \", originalDay)\
1352 write(\"Number of times resumed: \", numResumed)\
1353 write(\"Was an ore quarry? \",boolToText(oreQuarry or oldOreQuarry))\
1354 write(\"Was inverted? \",boolToText(invert))\
1355 write(\"Was using rednet? \",boolToText(rednetEnabled))\
1356 write(\"Chest was on the \",dropSide,\" side\")\
1357 if startDown > 0 then write(\"Started \",startDown,\" blocks down\") end\
1358 if exactTotals then\
1359 write(\"\\n==DETAILED TOTALS==\")\
1360 for a,b in pairs(exactTotals) do\
1361 write(pad(a, 15, \"right\"),\":\",pad(tostring(b),({term.getSize()})[1]-15-1, \"left\"))\
1362 end\
1363 end\
1364 handle.close()\
1365end\
1366--Inventory related functions\
1367function isFull(slots) --Checks if there are more than \"slots\" used inventory slots.\
1368 slots = slots or inventoryMax\
1369 local numUsed = 0\
1370 sleep(0)\
1371 for i=1, inventoryMax do\
1372 if turtle.getItemCount(i) > 0 then numUsed = numUsed + 1 end\
1373 end\
1374 if numUsed > slots then\
1375 return true\
1376 end\
1377 return false\
1378end\
1379function countUsedSlots() --Returns number of slots with items in them, as well as a table of item counts\
1380 local toRet, toRetTab = 0, {}\
1381 for i=1, inventoryMax do\
1382 local a = turtle.getItemCount(i)\
1383 if a > 0 then toRet = toRet + 1 end\
1384 table.insert(toRetTab, a)\
1385 end\
1386 return toRet, toRetTab\
1387end\
1388function getSlotsTable() --Just get the table from above\
1389 local _, toRet = countUsedSlots()\
1390 return toRet\
1391end\
1392function getChangedSlots(tab1, tab2) --Returns a table of changed slots. Format is {slotNumber, numberChanged}\
1393 local toRet = {}\
1394 for i=1, math.min(#tab1, #tab2) do\
1395 diff = math.abs(tab2[i]-tab1[i])\
1396 if diff > 0 then\
1397 table.insert(toRet, {i, diff})\
1398 end\
1399 end\
1400 return toRet\
1401end\
1402function getFirstChanged(tab1, tab2) --Just a wrapper. Probably not needed\
1403 local a = getChangedSlots(tab1,tab2)\
1404 return (a[1] or {\"none\"})[1]\
1405end\
1406\
1407function getRep(which, list) --Gets a representative slot of a type. Expectation is a sequential table of types\
1408 for a,b in pairs(list) do\
1409 if b == which then return a end\
1410 end\
1411 return false\
1412end\
1413function assignTypes(types, count) --The parameters allow a preexisting table to be used, like a table from the original compareSlots...\
1414 types, count = types or {1}, count or 1 --Table of types and current highest type\
1415 for i=1, inventoryMax do\
1416 if turtle.getItemCount(i) > 0 and not specialSlots[i] then --Not special slots so we don't count ender chests\
1417 select(i)\
1418 for k=1, count do\
1419 if turtle.compareTo(getRep(k, types)) then types[i] = k end\
1420 end\
1421 if not types[i] then\
1422 count = count + 1\
1423 types[i] = count\
1424 end\
1425 if oreQuarry then\
1426 if blacklist[turtle.getItemDetail().name] then\
1427 dumpSlots[i] = true\
1428 else\
1429 dumpSlots[i] = false\
1430 end\
1431 end\
1432 end\
1433 end\
1434 select(1)\
1435 return types, count\
1436end\
1437function getTableOfType(which, list) --Returns a table of all the slots of which type\
1438 local toRet = {}\
1439 for a, b in pairs(list) do\
1440 if b == which then\
1441 table.insert(toRet, a)\
1442 end\
1443 end\
1444 return toRet\
1445end\
1446\
1447--This is so the turtle will properly get types, otherwise getRep of a type might not be a dumpSlot, even though it should be.\
1448if not restoreFoundSwitch then --We only want this to happen once\
1449 if oldOreQuarry then --If its not ore quarry, this screws up type assigning\
1450 initialTypes, initialCount = assignTypes()\
1451 else\
1452 initialTypes, initialCount = {1}, 1\
1453 end\
1454end\
1455\
1456function count(add) --Done any time inventory dropped and at end, true=add, false=nothing, nil=subtract\
1457 local mod = -1\
1458 if add then mod = 1 end\
1459 if add == false then mod = 0 end\
1460 slot = {} --1: Filler 2: Fuel 3:Other --[1] is type, [2] is number\
1461 for i=1, inventoryMax do\
1462 slot[i] = {}\
1463 slot[i][2] = turtle.getItemCount(i)\
1464 end\
1465\
1466 local function iterate(toSet , rawTypes, set)\
1467 for _, a in pairs(getTableOfType(toSet, rawTypes)) do --Get all slots matching type\
1468 slot[a][1] = set --Set official type to \"set\"\
1469 end\
1470 end\
1471\
1472 --This assigns \"dumb\" types to all slots based on comparing, then based on knowledge of dump type slots, changes all slots matching a dump type to one. Otherwise, if the slot contains fuel, it is 2, else 3\
1473 local rawTypes, numTypes = assignTypes(copyTable(initialTypes), initialCount) --This gets increasingly numbered types, copyTable because assignTypes will modify it\
1474\
1475 for i=1, numTypes do\
1476 if (select(getRep(i, rawTypes)) or true) and turtle.refuel(0) then --Selects the rep slot, checks if it is fuel\
1477 iterate(i, rawTypes, 2) --This type is fuel\
1478 elseif dumpSlots[getRep(i,(oreQuarry and rawTypes) or initialTypes)] then --If the rep of this slot is a dump item. This is initial types so that the rep is in dump slots. rawTypes if oreQuarry to get newly assigned dumps\
1479 iterate(i, rawTypes, 1) --This type is cobble/filler\
1480 else\
1481 iterate(i, rawTypes, 3) --This type is other\
1482 end\
1483 end\
1484\
1485 for i=1,inventoryMax do\
1486 if not specialSlots[i] then --Do nothing for specialSlots!\
1487 if exactTotals and slot[i][2] > 0 then\
1488 local data = turtle.getItemDetail(i)\
1489 exactTotals[data.name] = (exactTotals[data.name] or 0) + (data.count * mod)\
1490 end\
1491 if slot[i][1] == 1 then totals.cobble = totals.cobble + (slot[i][2] * mod)\
1492 elseif slot[i][1] == 2 then totals.fuel = totals.fuel + (slot[i][2] * mod)\
1493 elseif slot[i][1] == 3 then totals.other = totals.other + (slot[i][2] * mod) end\
1494 end\
1495 end\
1496\
1497 select(1)\
1498end\
1499\
1500--Refuel Functions\
1501function emergencyRefuel(forceBasic)\
1502 local continueEvac = true --This turns false if more fuel is acquired\
1503 if fuelChest then --This is pretty much the only place that this will be used\
1504 if not fuelChestPhase then --Since I want to do things with return of enderRefuel, I will just make a special system. All of this is for backup safety.\
1505 fuelChestPhase = 0 --Global variable will be saved\
1506 fuelChestProperFacing = facing\
1507 end\
1508 if fuelChestPhase == 0 then\
1509 turnTo(coterminal(fuelChestProperFacing+2))\
1510 dig(false)\
1511 fuelChestPhase = 1\
1512 saveProgress()\
1513 end\
1514 if fuelChestPhase == 1 then\
1515 select(specialSlots.fuelChest)\
1516 turtle.place()\
1517 fuelChestPhase = 2\
1518 saveProgress()\
1519 end\
1520 if fuelChestPhase == 2 then\
1521 if not enderRefuel() then --Returns false if slots are full\
1522 select(specialSlots.fuelChest)\
1523 turtle.drop() --Somehow stuff got in here...\
1524 end\
1525 fuelChestPhase = 3\
1526 saveProgress()\
1527 end\
1528 if fuelChestPhase == 3 then\
1529 select(specialSlots.fuelChest)\
1530 dig(false)\
1531 select(1)\
1532 fuelChestPhase = 4\
1533 saveProgress()\
1534 end\
1535 if fuelChestPhase == 4 then\
1536 turnTo(fuelChestProperFacing)\
1537 fuelChestProperFacing = nil --Getting rid of saved values\
1538 fuelChestPhase = nil\
1539 continueEvac = false\
1540 end\
1541 elseif quadEnabled then --Ask for a quadRotor\
1542 screen()\
1543 print(\"Attempting an emergency Quad Rotor refuel\")\
1544 print(\"The turtle will soon send a message, then wait \",quadTimeout,\" seconds before moving on\")\
1545 print(\"Press any key to break timer\")\
1546 biometrics(nil, true)\
1547 local timer, counter, counterID, event, id = os.startTimer(quadTimeout), 0, os.startTimer(1)\
1548 local startInventory = getSlotsTable()\
1549 repeat\
1550 if id == counterID then counter = counter + 1; counterID = os.startTimer(1) end\
1551 screenLine(1,6)\
1552 print(\"Seconds elapsed: \",counter)\
1553 event, id = os.pullEvent() --Waits for a key or fuel or the timer\
1554 until (event == \"timer\" and id == timer) or event == \"key\" or event == \"turtle_inventory\" --Key event just makes turtle go back to start\
1555 if event == \"turtle_inventory\" then --If fuel was actually delivered\
1556 local slot = getFirstChanged(startInventory, getSlotsTable())\
1557 select(slot)\
1558 local initialFuel = checkFuel()\
1559 midRunRefuel(slot)\
1560 if checkFuel() > initialFuel then\
1561 print(\"Fuel delivered! Evac aborted\")\
1562 continueEvac = false\
1563 else\
1564 print(\"What did you send the turtle? Not fuel >:(\")\
1565 print(\"Continuing evac\")\
1566 end\
1567 sleep(1)\
1568 end\
1569 elseif doRefuel or forceBasic then --Attempt an emergency refueling\
1570 screen()\
1571 print(\"Attempting an emergency refuel\")\
1572 print(\"Fuel Level: \",checkFuel())\
1573 print(\"Distance Back: \",(xPos+zPos+yPos+1))\
1574 print(\"Categorizing Items\")\
1575 count(false) --Do not add count, but categorize\
1576 local fuelSwitch, initialFuel = false, checkFuel() --Fuel switch so we don't go over limit (in emergency...)\
1577 print(\"Going through available fuel slots\")\
1578 for i=1, inventoryMax do\
1579 if fuelSwitch then break end\
1580 if turtle.getItemCount(i) > 0 and slot[i][1] == 2 then --If there are items and type 2 (fuel)\
1581 select(i)\
1582 fuelSwitch = midRunRefuel(i) --See above \"function drop\" for usage\
1583 end\
1584 end\
1585 select(1) --Cleanup\
1586 print(\"Done fueling\")\
1587 if checkFuel() > initialFuel then\
1588 continueEvac = false\
1589 print(\"Evac Aborted\")\
1590 else\
1591 print(\"Evac is a go, returning to base\")\
1592 sleep(1.5) --Pause for reading\
1593 end\
1594 end\
1595 return continueEvac\
1596end\
1597\
1598function lavaRefuel(suckDir)\
1599 if checkFuel() + lavaBuffer >= checkFuelLimit() then return false end -- we don't want to constantly over-fuel the turtle.\
1600 local suckFunc\
1601 if suckDir == \"up\" then suckFunc = turtle.placeUp\
1602 elseif suckDir == \"down\" then suckFunc = turtle.placeDown\
1603 else suckFunc = turtle.place end\
1604 \
1605 select(specialSlots.lavaBucket)\
1606 if suckFunc() then\
1607 midRunRefuel(specialSlots.lavaBucket, 0) --0 forces it to refuel, even though allowed items[slot] is 1\
1608 end\
1609 select(1)\
1610 return true\
1611end\
1612\
1613--Mining functions\
1614function dig(doAdd, mineFunc, inspectFunc, suckDir) --Note, turtle will not bother comparing if not given an inspectFunc\
1615 if doAdd == nil then doAdd = true end\
1616 mineFunc = mineFunc or turtle.dig\
1617 local function retTab(tab) if type(tab) == \"table\" then return tab end end --Please ignore the stupid one-line trickery. I felt special writing that. (Unless it breaks, then its cool)\
1618 --Mine if not in blacklist. inspectFunc returns success and (table or string) so retTab filters out the string and the extra table prevents errors.\
1619 local mineFlag = false\
1620 if oreQuarry and inspectFunc then\
1621 local worked, data = inspectFunc()\
1622 if data then\
1623 mineFlag = not blacklist[data.name]\
1624 if data.name == chestID then\
1625 emptyChest(suckDir)\
1626 end\
1627 if lavaBucket and data.name == lavaID and data.metadata == lavaMeta then\
1628 lavaRefuel(suckDir)\
1629 end\
1630 end\
1631 end\
1632 if not oreQuarry or not inspectFunc or mineFlag then --Mines if not oreQuarry, or if the inspect passed\
1633 if mineFunc() then\
1634 if doAdd then\
1635 mined = mined + 1\
1636 end\
1637 return true\
1638 else\
1639 return false\
1640 end\
1641 end\
1642 return true --This only runs if oreQuarry but item not in blacklist. true means succeeded in duty, not necessarily dug block\
1643end\
1644\
1645function digUp(doAdd, ignoreInspect)--Regular functions :) I switch definitions for optimization (I think)\
1646 return dig(doAdd, turtle.digUp, (not ignoreInspect and turtle.inspectUp) or nil, \"up\")\
1647end\
1648function digDown(doAdd, ignoreInspect)\
1649 return dig(doAdd, turtle.digDown, (not ignoreInspect and turtle.inspectDown) or nil, \"down\")\
1650end\
1651if inverted then --If inverted, switch the options\
1652 digUp, digDown = digDown, digUp\
1653end\
1654\
1655function smartDig(doDigUp, doDigDown) --This function is used only in mine when oldOreQuarry\
1656 if inverted then doDigUp, doDigDown = doDigDown, doDigUp end --Switching for invert\
1657 local blockAbove, blockBelow = doDigUp and turtle.detectUp(), doDigDown and turtle.detectDown() --These control whether or not the turtle digs\
1658 local index = 1\
1659 for i=1, #compareSlots do\
1660 if not (blockAbove or blockBelow) then break end --We don't want to go selecting if there is nothing to dig\
1661 index = i --To access out of scope\
1662 select(compareSlots[i])\
1663 if blockAbove and turtle.compareUp() then blockAbove = false end\
1664 if blockBelow and turtle.compareDown() then blockBelow = false end\
1665 end\
1666 if compareChest then\
1667 local flag = false\
1668 select(specialSlots.compareChest)\
1669 if turtle.compareUp() then emptyChest(\"up\") end --Impressively, this actually works with session persistence. I'm gooood (apparently :P )\
1670 if turtle.compareDown() then emptyChest(\"down\") end --Looking over the code, I see no reason why that works... Oh well.\
1671 end\
1672 table.insert(compareSlots, 1, table.remove(compareSlots, index)) --This is so the last selected slot is the first slot checked, saving a select call\
1673 if blockAbove then dig(true, turtle.digUp) end\
1674 if blockBelow then dig(true, turtle.digDown) end\
1675end\
1676\
1677function relxCalc()\
1678 if layersDone % 2 == 1 then\
1679 relzPos = zPos\
1680 else\
1681 relzPos = (z-zPos) + 1\
1682 end\
1683 if relzPos % 2 == 1 then\
1684 relxPos = xPos\
1685 else\
1686 relxPos = (x-xPos)+1\
1687 end\
1688 if layersDone % 2 == 0 and z % 2 == 1 then\
1689 relxPos = (x-relxPos)+1\
1690 end\
1691end\
1692function horizontalMove(movement, posAdd, doAdd)\
1693 if doAdd == nil then doAdd = true end\
1694 if movement() then\
1695 if doAdd then\
1696 moved = moved + 1\
1697 end\
1698 if facing == 0 then\
1699 xPos = xPos + 1\
1700 elseif facing == 1 then\
1701 zPos = zPos + 1\
1702 elseif facing == 2 then\
1703 xPos = xPos - 1\
1704 elseif facing == 3 then\
1705 zPos = zPos - 1\
1706 else\
1707 error(\"Function forward, facing should be 0 - 3, got \"..tostring(facing),2)\
1708 end\
1709 relxCalc()\
1710 return true\
1711 end\
1712 return false\
1713end\
1714function forward(doAdd)\
1715 return horizontalMove(turtle.forward, 1, doAdd)\
1716end\
1717function back(doAdd)\
1718 return horizontalMove(turtle.back, -1, doAdd)\
1719end\
1720function verticalMove(moveFunc, yDiff, digFunc, attackFunc)\
1721 local count = 0\
1722 while not moveFunc() do\
1723 if not digFunc(true, true) then --True True is doAdd, and ignoreInspect\
1724 attackFunc()\
1725 sleep(0.5)\
1726 count = count + 1\
1727 if count > maxTries and yPos > (startY-7) then bedrock() end\
1728 end\
1729 end\
1730 yPos = yDiff + yPos\
1731 saveProgress()\
1732 biometrics()\
1733 return true\
1734end\
1735function up() --Uses other function if inverted\
1736 verticalMove(inverted and turtle.down or turtle.up, -1, digUp, attackUp) --Other functions deal with invert already\
1737end\
1738function down()\
1739 verticalMove(inverted and turtle.up or turtle.down, 1, digDown, attackDown)\
1740end\
1741\
1742\
1743function right(num)\
1744 num = num or 1\
1745 for i=1, num do\
1746 facing = coterminal(facing+1)\
1747 saveProgress()\
1748 if not goLeftNotRight then turtle.turnRight() --Normally\
1749 else turtle.turnLeft() end --Left Quarry\
1750 end\
1751end\
1752function left(num)\
1753 num = num or 1\
1754 for i=1, num do\
1755 facing = coterminal(facing-1)\
1756 saveProgress()\
1757 if not goLeftNotRight then turtle.turnLeft() --Normally\
1758 else turtle.turnRight() end --Left Quarry\
1759end\
1760end\
1761\
1762function attack(doAdd, func)\
1763 doAdd = doAdd or true\
1764 func = func or turtle.attack\
1765 if func() then\
1766 if doAdd then\
1767 attacked = attacked + 1\
1768 end\
1769 return true\
1770 end\
1771 return false\
1772end\
1773function attackUp(doAdd)\
1774 if inverted then\
1775 return attack(doAdd, turtle.attackDown)\
1776 else\
1777 return attack(doAdd, turtle.attackUp)\
1778 end\
1779end\
1780function attackDown(doAdd)\
1781 if inverted then\
1782 return attack(doAdd, turtle.attackUp)\
1783 else\
1784 return attack(doAdd, turtle.attackDown)\
1785 end\
1786end\
1787\
1788function detect(func)\
1789 func = func or turtle.detect\
1790 return func()\
1791end\
1792function detectUp(ignoreInvert)\
1793 if inverted and not ignoreInvert then return detect(turtle.detectDown)\
1794 else return detect(turtle.detectUp) end\
1795end\
1796function detectDown(ignoreInvert)\
1797 if inverted and not ignoreInvert then return detect(turtle.detectUp)\
1798 else return detect(turtle.detectDown) end\
1799end\
1800\
1801\
1802\
1803function mine(doDigDown, doDigUp, outOfPath,doCheckInv) -- Basic Move Forward\
1804 if doCheckInv == nil then doCheckInv = true end\
1805 if doDigDown == nil then doDigDown = true end\
1806 if doDigUp == nil then doDigUp = true end\
1807 if outOfPath == nil then outOfPath = false end\
1808 isInPath = (not outOfPath) --For rednet\
1809 if not outOfPath and (checkFuel() <= xPos + zPos + yPos + 5) then --If the turtle can just barely get back to the start, we need to get it there. We don't want this to activate coming back though...\
1810 local continueEvac = false --It will be set true unless at start\
1811 if xPos ~= 0 then\
1812 continueEvac = emergencyRefuel() --This is a huge list of things to do in an emergency\
1813 end\
1814 if continueEvac then\
1815 eventClear() --Clear any annoying events for evac\
1816 local currPos = yPos\
1817 endingProcedure() --End the program\
1818 print(\"Turtle ran low on fuel so was brought back to start for you :)\\n\\nTo resume where you left off, use '-startDown \"..tostring(currPos-1)..\"' when you start\")\
1819 error(\"\",0)\
1820 end\
1821 end\
1822 if frontChest and not outOfPath then\
1823 if turtle.inspect then\
1824 local check, data = turtle.inspect()\
1825 if check and data.name == chestID then\
1826 emptyChest(\"front\")\
1827 end\
1828 else\
1829 local flag = false\
1830 select(specialSlots.compareChest)\
1831 if turtle.compare() then flag = true end\
1832 select(1)\
1833 if flag then\
1834 emptyChest(\"front\")\
1835 end\
1836 end\
1837 end\
1838 \
1839 local count = 0\
1840 if not outOfPath then dig() end --This speeds up the quarry by a decent amount if there are more mineable blocks than air\
1841 while not forward(not outOfPath) do\
1842 sleep(0) --Calls coroutine.yield to prevent errors\
1843 count = count + 1\
1844 if not dig() then\
1845 attack()\
1846 end\
1847 if count > 10 then\
1848 attack()\
1849 sleep(0.2)\
1850 end\
1851 if count > maxTries then\
1852 if checkFuel() == 0 then --Don't worry about inf fuel because I modified this function\
1853 saveProgress({doCheckFuel = true, doRefuel = true}) --This is emergency because this should never really happen.\
1854 os.reboot()\
1855 elseif yPos > (startY-7) and turtle.detect() then --If it is near bedrock\
1856 bedrock()\
1857 else --Otherwise just sleep for a bit to avoid sheeps\
1858 sleep(1)\
1859 end\
1860 end\
1861 end\
1862 checkSanity() --Not kidding... This is necessary\
1863 saveProgress(tab)\
1864\
1865 if not oldOreQuarry then\
1866 if doDigUp then--The digging up and down part\
1867 sleep(0) --Calls coroutine.yield\
1868 if not digUp(true) and detectUp() then --This is relative: will dig down first on invert\
1869 if not attackUp() then\
1870 if yPos > (startY-7) then bedrock() end --Checking for bedrock, but respecting user wishes\
1871 end\
1872 end\
1873 end\
1874 if doDigDown then\
1875 digDown(true) --This needs to be absolute as well\
1876 end\
1877 else --If oldQuarry\
1878 smartDig(doDigUp,doDigDown)\
1879 end\
1880 percent = math.ceil(moved/moveVolume*100)\
1881 updateDisplay()\
1882 if doCheckInv and careAboutResources then\
1883 if isFull(inventoryMax-keepOpen) then\
1884 if not ((oreQuarry or oldOreQuarry) and dumpCompareItems) then\
1885 dropOff()\
1886 else\
1887 local currInv = getSlotsTable()\
1888 drop(nil, false, true) --This also takes care of counting.\
1889 if #getChangedSlots(currInv, getSlotsTable()) <= 2 then --This is so if the inventory is full of useful stuff, it still has to drop it\
1890 dropOff()\
1891 end\
1892 end\
1893 end\
1894 end\
1895 biometrics()\
1896end\
1897--Insanity Checking\
1898function checkSanity()\
1899 if not isInPath then --I don't really care if its not in the path.\
1900 return true\
1901 end\
1902 if not (facing == 0 or facing == 2) and #events == 0 then --If mining and not facing proper direction and not in a turn\
1903 turnTo(0)\
1904 rowCheck = true\
1905 end\
1906 if xPos < 0 or xPos > x or zPos < 0 or zPos > z or yPos < 0 then\
1907 saveProgress()\
1908 print(\"I have gone outside boundaries, attempting to fix (maybe)\")\
1909 if xPos > x then goto(x, zPos, yPos, 2) end --I could do this with some fancy math, but this is much easier\
1910 if xPos < 0 then goto(1, zPos, yPos, 0) end\
1911 if zPos > z then goto(xPos, z, yPos, 3) end\
1912 if zPos < 0 then goto(xPos, 1, yPos, 1) end\
1913 relxCalc() --Get relxPos properly\
1914 eventClear()\
1915\
1916 --[[\
1917 print(\"Oops. Detected that quarry was outside of predefined boundaries.\")\
1918 print(\"Please go to my forum thread and report this with a short description of what happened\")\
1919 print(\"If you could also run \\\"pastebin put Civil_Quarry_Restore\\\" and give me that code it would be great\")\
1920 error(\"\",0)]]\
1921 end\
1922end\
1923\
1924local function fromBoolean(input) --Like a calculator\
1925if input then return 1 end\
1926return 0\
1927end\
1928local function multBoolean(first,second) --Boolean multiplication\
1929return (fromBoolean(first) * fromBoolean(second)) == 1\
1930end\
1931function coterminal(num, limit) --I knew this would come in handy :D\
1932limit = limit or 4 --This is for facing\
1933return math.abs((limit*fromBoolean(num < 0))-(math.abs(num)%limit))\
1934end\
1935if tArgs[\"-manualpos\"] then\
1936 facing = coterminal(facing) --Done to improve support for \"-manualPos\"\
1937 if facing == 0 then rowCheck = true elseif facing == 2 then rowCheck = false end --Ditto\
1938 relxCalc() --Ditto\
1939end\
1940\
1941--Direction: Front = 0, Right = 1, Back = 2, Left = 3\
1942function turnTo(num)\
1943 num = num or facing\
1944 num = coterminal(num) --Prevent errors\
1945 local turnRight = true\
1946 if facing-num == 1 or facing-num == -3 then turnRight = false end --0 - 1 = -3, 1 - 0 = 1, 2 - 1 = 1\
1947 while facing ~= num do --The above is used to smartly turn\
1948 if turnRight then\
1949 right()\
1950 else\
1951 left()\
1952 end\
1953 end\
1954end\
1955function goto(x,z,y, toFace, destination)\
1956 --Will first go to desired z pos, then x pos, y pos varies\
1957 x = x or 1; y = y or 1; z = z or 1; toFace = toFace or facing\
1958 gotoDest = destination or \"\" --This is used by biometrics.\
1959 statusString = \"Going to \".. (destination or \"somewhere\")\
1960 --Possible destinations: layerStart, quarryStart\
1961 if yPos > y then --Will go up first if below position\
1962 while yPos~=y do up() end\
1963 end\
1964 if zPos > z then\
1965 turnTo(3)\
1966 elseif zPos < z then\
1967 turnTo(1)\
1968 end\
1969 while zPos ~= z do mine(false,false,true,false) end\
1970 if xPos > x then\
1971 turnTo(2)\
1972 elseif xPos < x then\
1973 turnTo(0)\
1974 end\
1975 while xPos ~= x do mine(false,false,true,false) end\
1976 if yPos < y then --Will go down after if above position\
1977 while yPos~=y do down() end\
1978 end\
1979 turnTo(toFace)\
1980 saveProgress()\
1981 gotoDest = \"\"\
1982 statusString = nil\
1983end\
1984function getNumOpenSlots()\
1985 local toRet = 0\
1986 for i=1, inventoryMax do\
1987 if turtle.getItemCount(i) == 0 then\
1988 toRet = toRet + 1\
1989 end\
1990 end\
1991 return toRet\
1992end\
1993function emptyChest(suckDirection)\
1994 eventAdd(\"emptyChest\",suckDirection)\
1995 eventSetInsertionPoint(2) --Because dropOff adds events we want to run first\
1996 local suckFunc\
1997 if suckDirection == \"up\" then\
1998 suckFunc = turtle.suckUp\
1999 elseif suckDirection == \"down\" then\
2000 suckFunc = turtle.suckDown\
2001 else\
2002 suckFunc = turtle.suck\
2003 end\
2004 repeat\
2005 if inventoryMax - countUsedSlots() <= 0 then --If there are no slots open, need to empty\
2006 dropOff()\
2007 end\
2008 until not suckFunc()\
2009 eventClear()\
2010 eventSetInsertionPoint()\
2011end\
2012\
2013--Ideas: Bring in inventory change-checking functions, count blocks that have been put in, so it will wait until all blocks have been put in.\
2014local function waitDrop(slot, allowed, whereDrop) --This will just drop, but wait if it can't\
2015 allowed = allowed or 0\
2016 while turtle.getItemCount(slot) > allowed do --No more half items stuck in slot!\
2017 local tries = 1\
2018 while not whereDrop(turtle.getItemCount(slot)-allowed) do --Drop off only the amount needed\
2019 screen(1,1)\
2020 print(\"Chest Full, Try \"..tries)\
2021 chestFull = true\
2022 biometrics()--To send that the chest is full\
2023 tries = tries + 1\
2024 sleep(2)\
2025 end\
2026 chestFull = false\
2027 end\
2028end\
2029\
2030function midRunRefuel(i, allowed)\
2031 allowed = allowed or allowedItems[i]\
2032 local numToRefuel = turtle.getItemCount(i)-allowed\
2033 if checkFuel() >= checkFuelLimit() then return true end --If it doesn't need fuel, then signal to not take more\
2034 local firstCheck = checkFuel()\
2035 if numToRefuel > 0 then turtle.refuel(1) --This is so we can see how many fuel we need.\
2036 else return false end --Bandaid solution: If won't refuel, don't try.\
2037 local singleFuel\
2038 if checkFuel() - firstCheck > 0 then singleFuel = checkFuel() - firstCheck else singleFuel = math.huge end --If fuel is 0, we want it to be huge so the below will result in 0 being taken\
2039 --Refuel The lesser of max allowable or remaining fuel space / either inf or a single fuel (which can be 0)\
2040 turtle.refuel(math.min(numToRefuel-1, math.ceil((checkFuelLimit()-checkFuel()) / singleFuel))) --The refueling part of the the doRefuel option\
2041 if checkFuel() >= checkFuelLimit() then return true end --Do not need any more fuel\
2042 return false --Turtle can still be fueled\
2043end\
2044\
2045function enderRefuel() --Assumes a) An enderchest is in front of it b) It needs fuel\
2046 local slot\
2047 for a,b in ipairs(getSlotsTable()) do\
2048 if b == 0 then slot = a; break end\
2049 end\
2050 if not slot then return false end --No room for fueling\
2051 select(slot)\
2052 repeat\
2053 print(\"Required Fuel: \",checkFuelLimit())\
2054 print(\"Current Fuel: \",checkFuel())\
2055 local tries = 0\
2056 while not turtle.suck() do\
2057 sleep(1)\
2058 statusString = \"No Fuel in Ender Chest\"\
2059 biometrics() --Let user know that fuel chest is empty\
2060 print(statusString,\". Try: \",tries)\
2061 tries = tries + 1\
2062 end\
2063 statusString = nil\
2064 until midRunRefuel(slot, 0) --Returns true when should not refuel any more\
2065 if not turtle.drop() then turtle.dropDown() end --If cannot put fuel back, just drop it, full fuel chest = user has too much fuel already\
2066 return true -- :D\
2067end\
2068\
2069\
2070function drop(side, final, compareDump)\
2071 side = sides[side] or \"front\"\
2072 local dropFunc, detectFunc, dropFacing = turtle.drop, turtle.detect, facing+2\
2073 if side == \"top\" then dropFunc, detectFunc = turtle.dropUp, turtle.detectUp end\
2074 if side == \"bottom\" then dropFunc, detectFunc = turtle.dropDown, turtle.detectDown end\
2075 if side == \"right\" then turnTo(1); dropFacing = 0 end\
2076 if side == \"left\" then turnTo(3); dropFacing = 0 end\
2077 local properFacing = facing --Capture the proper direction to be facing\
2078\
2079 count(true) --Count number of items before drop. True means add. This is before chest detect, because could be final\
2080\
2081 while not compareDump and not detectFunc() do\
2082 if final then return end --If final, we don't need a chest to be placed, but there can be\
2083 chestFull = true\
2084 biometrics() --Let the user know there is a problem with chest\
2085 screen(1,1) --Clear screen\
2086 print(\"Waiting for chest placement on \",side,\" side (when facing quarry)\")\
2087 sleep(2)\
2088 end\
2089 chestFull = false\
2090\
2091 local fuelSwitch = false --If doRefuel, this can switch so it won't overfuel\
2092 for i=1,inventoryMax do\
2093 --if final then allowedItems[i] = 0 end --0 items allowed in all slots if final ----It is already set to 1, so just remove comment if want change\
2094 if turtle.getItemCount(i) > 0 then --Saves time, stops bugs\
2095 if slot[i][1] == 1 and dumpCompareItems then turnTo(dropFacing) --Turn around to drop junk, not store it. dumpComapareItems is global config\
2096 else turnTo(properFacing) --Turn back to proper position... or do nothing if already there\
2097 end\
2098 select(i)\
2099 if slot[i][1] == 2 then --Intelligently refuels to fuel limit\
2100 if doRefuel and not fuelSwitch then --Not in the conditional because we don't want to waitDrop excess fuel. Not a break so we can drop junk\
2101 fuelSwitch = midRunRefuel(i)\
2102 else\
2103 waitDrop(i, allowedItems[i], dropFunc)\
2104 end\
2105 if fuelSwitch then\
2106 waitDrop(i, allowedItems[i], dropFunc)\
2107 end\
2108 elseif not compareDump or (compareDump and slot[i][1] == 1) then --This stops all wanted items from being dropped off in a compareDump\
2109 waitDrop(i, allowedItems[i], dropFunc)\
2110 end\
2111 end\
2112 end\
2113\
2114 if compareDump then\
2115 for i=2, inventoryMax do\
2116 if not specialSlots[i] then --We don't want to move buckets and things into earlier slots\
2117 select(i)\
2118 for j=1, i-1 do\
2119 if turtle.getItemCount(i) == 0 then break end\
2120 turtle.transferTo(j)\
2121 end\
2122 end\
2123 end\
2124 select(1)\
2125 end\
2126 if oldOreQuarry or compareDump then count(nil) end--Subtract the items still there if oreQuarry\
2127 resetDumpSlots() --So that slots gone aren't counted as dump slots next\
2128\
2129 select(1) --For fanciness sake\
2130\
2131end\
2132\
2133function dropOff() --Not local because called in mine()\
2134 local currX,currZ,currY,currFacing = xPos, zPos, yPos, facing\
2135 if careAboutResources then\
2136 if not enderChest then --Regularly\
2137 eventAdd(\"goto\", 1,1,currY,2, \"drop off\") --Need this step for \"-startDown\"\
2138 eventAdd('goto(0,1,1,2,\"drop off\")')\
2139 eventAdd(\"drop\", dropSide,false)\
2140 eventAdd(\"turnTo(0)\")\
2141 eventAdd(\"mine\",false,false,true,false)\
2142 eventAdd(\"goto(1,1,1, 0)\")\
2143 eventAdd(\"goto\", 1, 1, currY, 0)\
2144 eventAdd(\"goto\", currX,currZ,currY,currFacing)\
2145 else --If using an enderChest\
2146 if turtle.getItemCount(specialSlots.enderChest) ~= 1 then eventAdd(\"promptSpecialSlot('enderChest','Ender Chest')\") end\
2147 eventAdd(\"turnTo\",currFacing-2)\
2148 eventAdd(\"dig\",false)\
2149 eventAdd(\"select\",specialSlots.enderChest)\
2150 eventAdd(\"turtle.place\")\
2151 eventAdd(\"drop\",\"front\",false)\
2152 eventAdd(\"turnTo\",currFacing-2)\
2153 eventAdd(\"select\", specialSlots.enderChest)\
2154 eventAdd(\"dig\",false)\
2155 eventAdd(\"turnTo\",currFacing)\
2156 eventAdd(\"select(1)\")\
2157 end\
2158 runAllEvents()\
2159 numDropOffs = numDropOffs + 1 --Analytics tracking\
2160 end\
2161 return true\
2162end\
2163function endingProcedure() --Used both at the end and in \"biometrics\"\
2164 eventAdd(\"goto\",1,1,yPos,2,\"quarryStart\") --Allows for startDown variable\
2165 eventAdd(\"goto\",0,1,1,2, \"quarryStart\") --Go back to base\
2166 runAllEvents()\
2167 --Output to a chest or sit there\
2168 if enderChest then\
2169 if dropSide == \"right\" then eventAdd(\"turnTo(1)\") end --Turn to proper drop side\
2170 if dropSide == \"left\" then eventAdd(\"turnTo(3)\") end\
2171 eventAdd(\"dig(false)\") --This gets rid of a block in front of the turtle.\
2172 eventAdd(\"select\",specialSlots.enderChest)\
2173 eventAdd(\"turtle.place\")\
2174 eventAdd(\"select(1)\")\
2175 end\
2176 eventAdd(\"drop\",dropSide, true)\
2177 eventAdd(\"turnTo(0)\")\
2178\
2179 --Display was moved above to be used in bedrock function\
2180 eventAdd(\"display\")\
2181 --Log current mining run\
2182 eventAdd(\"logMiningRun\",logExtension)\
2183 toQuit = true --I'll use this flag to clean up (legacy)\
2184 runAllEvents()\
2185end\
2186function bedrock()\
2187 foundBedrock = true --Let everyone know\
2188 if rednetEnabled then biometrics() end\
2189 if checkFuel() == 0 then error(\"No Fuel\",0) end\
2190 local origin = {x = xPos, y = yPos, z = zPos}\
2191 print(\"Bedrock Detected\")\
2192 if turtle.detectUp() and not turtle.digUp() then\
2193 print(\"Block Above\")\
2194 turnTo(facing+2)\
2195 repeat\
2196 if not forward(false) then --Tries to go back out the way it came\
2197 if not attck() then --Just making sure not mob-blocked\
2198 if not dig() then --Now we know its bedrock\
2199 turnTo(facing+1) --Try going a different direction\
2200 end\
2201 end\
2202 end\
2203 until not turtle.detectUp() or turtle.digUp() --These should be absolute and we don't care about about counting resources here.\
2204 end\
2205 up() --Go up two to avoid any bedrock.\
2206 up()\
2207 eventClear() --Get rid of any excess events that may be run. Don't want that.\
2208 endingProcedure()\
2209 print(\"\\nFound bedrock at these coordinates: \")\
2210 print(origin.x,\" Was position in row\\n\",origin.z,\" Was row in layer\\n\",origin.y,\" Blocks down from start\")\
2211 error(\"\",0)\
2212end\
2213\
2214function endOfRowTurn(startZ, wasFacing, mineFunctionTable)\
2215local halfFacing = ((layersDone % 2 == 1) and 1) or 3\
2216local toFace = coterminal(wasFacing + 2) --Opposite side\
2217if zPos == startZ then\
2218 if facing ~= halfFacing then turnTo(halfFacing) end\
2219 mine(unpack(mineFunctionTable or {}))\
2220end\
2221if facing ~= toFace then\
2222 turnTo(toFace)\
2223end\
2224end\
2225\
2226\
2227-------------------------------------------------------------------------------------\
2228--Pre-Mining Stuff dealing with session persistence\
2229runAllEvents()\
2230if toQuit then error(\"\",0) end --This means that it was stopped coming for its last drop\
2231\
2232local doDigDown, doDigUp = (lastHeight ~= 1), (lastHeight == 0) --Used in lastHeight\
2233if not restoreFoundSwitch then --Regularly\
2234 --Check if it is a mining turtle\
2235 if not isMiningTurtle then\
2236 local a, b = turtle.dig()\
2237 if a then\
2238 mined = mined + 1\
2239 isMiningTurtle = true\
2240 elseif b == \"Nothing to dig with\" or b == \"No tool to dig with\" then\
2241 print(\"This is not a mining turtle. To make a mining turtle, craft me together with a diamond pickaxe\")\
2242 error(\"\",0)\
2243 end\
2244 end\
2245 \
2246 if checkFuel() == 0 then --Some people forget to start their turtles with fuel\
2247 screen(1,1)\
2248 print(\"I have no fuel and doCheckFuel is off!\")\
2249 print(\"Starting emergency fueling procedures!\\n\")\
2250 emergencyRefuel()\
2251 if checkFuel() == 0 then\
2252 print(\"I have no fuel and can't get more!\")\
2253 print(\"Try using -doRefuel or -fuelChest\")\
2254 print(\"I have no choice but to quit.\")\
2255 error(\"\",0)\
2256 end\
2257 end\
2258 \
2259 mine(false,false,true) --Get into quarry by going forward one\
2260 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.\
2261 gpsSecondPos = {gps.locate(gpsTimeout)} --Note: Does not run this if it has already been restarted.\
2262 end\
2263 for i = 1, startDown do\
2264 eventAdd(\"down\") --Add a bunch of down events to get to where it needs to be.\
2265 end\
2266 runAllEvents()\
2267 if flatBedrock then\
2268 while (detectDown() and digDown(false, true)) or not detectDown() do --None of these functions are non-invert protected because inverse always false here\
2269 down()\
2270 startDown = startDown + 1\
2271 end\
2272 startDown = startDown - y + 1\
2273 for i=1, y-2 do\
2274 up() --It has hit bedrock, now go back up for proper 3 wide mining\
2275 end\
2276 elseif not(y == 1 or y == 2) then\
2277 down() --Go down to align properly. If y is one or two, it doesn't need to do this.\
2278 end\
2279else --restore found\
2280 if not(layersDone == layers and not doDigDown) then digDown() end\
2281 if not(layersDone == layers and not doDigUp) then digUp() end --Get blocks missed before stopped\
2282end\
2283--Mining Loops--------------------------------------------------------------------------\
2284select(1)\
2285while layersDone <= layers do -------------Height---------\
2286local lastLayer = layersDone == layers --If this is the last layer\
2287local secondToLastLayer = (layersDone + 1) == layers --This is a check for going down at the end of a layer.\
2288moved = moved + 1 --To account for the first position in row as \"moved\"\
2289if not(layersDone == layers and not doDigDown) then digDown() end --This is because it doesn't mine first block in layer\
2290if not restoreFoundSwitch and layersDone % 2 == 1 then rowCheck = true end\
2291relxCalc()\
2292while relzPos <= z do -------------Width----------\
2293while relxPos < x do ------------Length---------\
2294mine(not lastLayer or (doDigDown and lastLayer), not lastLayer or (doDigUp and lastLayer)) --This will be the idiom that I use for the mine function\
2295end ---------------Length End-------\
2296if relzPos ~= z then --If not on last row of section\
2297 local func\
2298 if rowCheck == true then --Switching to next row\
2299 func = \"right\"; rowCheck = false; else func = false; rowCheck = true end --Which way to turn\
2300 eventAdd(\"endOfRowTurn\", zPos, facing , {not lastLayer or (doDigDown and lastLayer), not lastLayer or (doDigUp and lastLayer)}) --The table is passed to the mine function\
2301 runAllEvents()\
2302else break\
2303end\
2304end ---------------Width End--------\
2305if layersDone % 2 == 0 then --Will only go back to start on non-even layers\
2306 eventAdd(\"goto\",1,1,yPos,0, \"layerStart\") --Goto start of layer\
2307else\
2308 eventAdd(\"turnTo\",coterminal(facing-2))\
2309end\
2310if not lastLayer then --If there is another layer\
2311 for i=1, 2+fromBoolean(not(lastHeight~=0 and secondToLastLayer)) do eventAdd(\"down()\") end --The fromBoolean stuff means that if lastheight is 1 and last and layer, will only go down two\
2312end\
2313eventAdd(\"relxCalc\")\
2314layersDone = layersDone + 1\
2315restoreFoundSwitch = false --This is done so that rowCheck works properly upon restore\
2316runAllEvents()\
2317end ---------------Height End-------\
2318\
2319endingProcedure() --This takes care of getting to start, dropping in chest, and displaying ending screen",
2320 },
2321 {
2322 path = "/altError/",
2323 content = "local tArgs = {...}\
2324\
2325local monX, monY = term.getSize()\
2326\
2327local function fTest(sErr)\
2328 term.setBackgroundColor(colors.blue)\
2329 term.clear()\
2330 term.setBackgroundColor(colors.white)\
2331 term.setTextColor(colors.blue)\
2332 term.setCursorPos((monX / 2) - (string.len(\"arcOS\") / 2), monY / 2 - 1)\
2333 term.write(\"arcOS\")\
2334 term.setBackgroundColor(colors.blue)\
2335 term.setTextColor(colors.white)\
2336 term.setCursorPos((monX / 2) - (string.len(sErr) / 2), monY / 2 + 1)\
2337 term.write(sErr)\
2338 term.setCursorPos((monX / 2) - (string.len(\"Press any key to continue...\") / 2), monY / 2 + 2)\
2339 term.write(\"Press any key to continue...\")\
2340 sleep(0.2)\
2341 os.pullEvent(\"key\")\
2342 term.setBackgroundColor(colors.black)\
2343 term.clear()\
2344 term.setCursorPos(1, 1)\
2345end\
2346\
2347os.run({error = fTest, shell = shell, multishell = multishell}, tArgs[1])",
2348 },
2349 {
2350 path = "/tst/",
2351 content = "bite()\
2352error(\"ok\")",
2353 },
2354 {
2355 path = "/dig/",
2356 content = "--[[\
2357Version\
2358 0.07 1/2/2015 1:41 PM\
2359Changelog\
2360 0.01 - Starting Of Rewriting\
2361 0.02 - More Writing\
2362 0.03 - Adding Fuel Code\
2363 0.04 - Small but many program error fixed\
2364 0.05 - Fully Test\
2365 0.06 - Fixing Minor Bug when add 3 to deep because firstdig had no 3 add to deepcount\
2366 0.07 - Fixing High Error\
2367--]]\
2368\
2369-- Local Variables\
2370-- Starting\
2371local wide = 0\
2372local wideCount = 0\
2373local long = 0\
2374local longCount = 0\
2375local deep = 0\
2376local deepCount = 0\
2377local totalBlocks = 0\
2378local coalNeeded = 0\
2379local corrent = n\
2380-- Inventory This Will Check At Start Code\
2381local chest = 0\
2382local fuelCount = 0\
2383local fuelCount1 = 0\
2384local noFuelNeed = 0 -- if Config has fuel no need on\
2385local error = 0 -- Error Code\
2386local reCheck = 0 -- Recheck Code\
2387-- Others\
2388local totalBlocks = 0\
2389local totalBlockDone = 0 -- How many Block Mined\
2390local LSorWS = 0 -- Go Left or Go Right This is for Wide Code\
2391local ALorAR = 0 -- align left Or align Right\
2392local processRaw = 0\
2393local process = 0\
2394local enderChest = 0 -- TODO\
2395local blockUp = 0 -- Fixing to Chest Probleem and moving probleem\
2396local processRaw = 0\
2397local process = 0\
2398\
2399-- Checking\
2400local function check()\
2401 if noFuelNeed == 0 then\
2402 if fuelCount == 0 then\
2403 print(\"Turtle has no fuel\")\
2404 print(\"Put fuel in Second and Thrid slot\")\
2405 error = 1\
2406 else\
2407 print(\"Turtle has Fuel\")\
2408 end\
2409 if fuelCount1 == 0 then\
2410 print(\"Turtle has no extra fuel but if is short job it okey\")\
2411 end\
2412 end\
2413 if chest == 0 then\
2414 print(\"No chest in Turtle\")\
2415 print(\"Put chest in 1 slot\")\
2416 error = 1\
2417 else\
2418 print(\"Turtle has chest\")\
2419 end\
2420 if error == 1 then\
2421 print(\"Items are missing please try again\")\
2422 print(\"Turtle will recheck in 8 sec\")\
2423 end\
2424end\
2425\
2426-- Recheck if user forget something turtle will check after 6 sec\
2427local function reCheck()\
2428 chest = turtle.getItemCount(1)\
2429 fuelCount = turtle.getItemCount(2)\
2430 fuelCount1 = turtle.getItemCount(3)\
2431 error = 0\
2432end\
2433\
2434local function chestDump()\
2435 if turtle.getItemCount(16)> 0 then -- If slot 16 in turtle has item slot 4 to 16 will go to chest\
2436 repeat -- The Fix to Gravel Chest Bug. It check if gravel above then it dig till it gone\
2437 turtle.digUp()\
2438 sleep(0.6)\
2439 if turtle.detectUp() then\
2440 turtle.digUp()\
2441 blockUp = 1\
2442 else\
2443 blockUp = 0\
2444 end\
2445 until blockUp == 0\
2446 turtle.select(1)\
2447 turtle.placeUp()\
2448 chest = chest - 1\
2449 for slot = 4, 16 do\
2450 turtle.select(slot)\
2451 sleep(0.6) -- Small fix for slow pc because i had people problem with this\
2452 turtle.dropUp()\
2453 end\
2454 turtle.select(4)\
2455 if Chest == 0 then\
2456 print(\"Out Of Chest\")\
2457 os.shutdown()\
2458 end\
2459 end\
2460end\
2461\
2462-- Refuel\
2463local function refuel()\
2464 if noFuelNeed == 0 then\
2465 repeat\
2466 if turtle.getFuelLevel() < 160 then\
2467 if fuelCount > 0 then\
2468 turtle.select(2)\
2469 turtle.refuel(1)\
2470 fuelCount = fuelCount - 1\
2471 elseif fuelCount1 > 0 then\
2472 turtle.select(3)\
2473 turtle.refuel(1)\
2474 fuelCount1 = fuelCount1 - 1\
2475 else\
2476 print(\"out of fuel\")\
2477 os.shutdown()\
2478 end\
2479 end\
2480 until turtle.getFuelLevel() >= 160\
2481 end\
2482end\
2483\
2484local function mineLong()\
2485 if turtle.detect() then\
2486 turtle.dig()\
2487 end\
2488 if turtle.forward() then\
2489 longCount = longCount + 1\
2490 else\
2491 repeat\
2492 turtle.dig()\
2493 sleep(0.6)\
2494 if turtle.forward() then\
2495 blockUp = 0\
2496 else\
2497 blockUp = 1\
2498 end\
2499 until blockUp == 0\
2500 longCount = longCount + 1\
2501 print(totalBlocks - totalBlockDone)\
2502 end\
2503 if turtle.detectUp() then\
2504 turtle.digUp()\
2505 end\
2506 if turtle.detectDown() then\
2507 turtle.digDown()\
2508 end\
2509 totalBlockDone = totalBlockDone + 3\
2510end\
2511\
2512local function wideMineLeft() -- TODO\
2513 turtle.turnLeft()\
2514 if turtle.detect() then\
2515 turtle.dig()\
2516 sleep(0.6) -- Minor bug fix if there is gravel\
2517 end\
2518 if turtle.forward() then\
2519 --notting\
2520 else\
2521 repeat\
2522 turtle.dig()\
2523 sleep(0.6)\
2524 if turtle.forward() then\
2525 blockUp = 0\
2526 else\
2527 blockUp = 1\
2528 end\
2529 until blockUp == 0\
2530 end\
2531 if turtle.detectUp() then\
2532 turtle.digUp()\
2533 end\
2534 if turtle.detectDown() then\
2535 turtle.digDown()\
2536 end\
2537 turtle.turnLeft()\
2538 LSorWS = 0\
2539 longCount = 0\
2540 wideCount = wideCount + 1\
2541 totalBlockDone = totalBlockDone + 3\
2542 end\
2543\
2544local function wideMineRight() -- TODO\
2545 turtle.turnRight()\
2546 if turtle.detect() then\
2547 turtle.dig()\
2548 sleep(0.6)\
2549 end\
2550 if turtle.forward() then\
2551 --Notting\
2552 else\
2553 repeat\
2554 turtle.dig()\
2555 sleep(0.6)\
2556 if turtle.forward() then\
2557 blockUp = 0\
2558 else\
2559 blockUp = 1\
2560 end\
2561 until blockUp == 0\
2562 end\
2563 if turtle.detectUp() then\
2564 turtle.digUp()\
2565 end\
2566 if turtle.detectDown() then\
2567 turtle.digDown()\
2568 end\
2569 turtle.turnRight()\
2570 LSorWS = 1\
2571 longCount = 0\
2572 wideCount = wideCount + 1\
2573 totalBlockDone = totalBlockDone + 3\
2574end\
2575\
2576local function deepMine()\
2577 turtle.digDown()\
2578 turtle.down()\
2579 turtle.digDown()\
2580 turtle.down()\
2581 turtle.digDown()\
2582 turtle.down()\
2583 turtle.digDown()\
2584 turtle.turnRight()\
2585 turtle.turnRight()\
2586 wideCount = 0\
2587 longCount = 0\
2588 deepCount = deepCount + 3\
2589 totalBlockDone = totalBlockDone + 3\
2590end\
2591\
2592local function main()\
2593 repeat --Repeat for each level\
2594 mineLong()\
2595 refuel()\
2596 chestDump()\
2597 if longCount == long then\
2598 if wideCount ~= wide then\
2599 process = totalBlockDone / totalBlocks * 100\
2600 processRaw = totalBlocks - totalBlockDone\
2601 print(\"How Much Is Done: \" .. math.floor(process+0.5) .. \" %\")\
2602 print(\"TotalBlocks Still Need To Dig Is \" .. processRaw)\
2603 if LSorWS == 0 then\
2604 wideMineRight()\
2605 else\
2606 wideMineLeft()\
2607 end\
2608 elseif wideCount >= wide then\
2609 deepMine()\
2610 end\
2611 end\
2612 until deepCount >= deep\
2613 print(\"turtle is Done\")\
2614end\
2615\
2616local function firstDig()\
2617 turtle.digDown()\
2618 turtle.down()\
2619 turtle.digDown()\
2620 turtle.down()\
2621 turtle.digDown()\
2622 wideCount = 0\
2623 longCount = 0\
2624 totalBlockDone = totalBlockDone + 3\
2625end\
2626\
2627local function start()\
2628 print(\"Welcome To Excavation Turtle Program\")\
2629 print(\"Slot 1: Chest, Slot 2: Fuel, Slot 3: Fuel\")\
2630 print(\"Note: If now put item in then it say error just wait it fix it self\")\
2631 print(\"How long(Lenght) you want\")\
2632 input = io.read()\
2633 long = tonumber(input)\
2634 long = long - 1\
2635 print(\"How wide(Width) you want\")\
2636 input2 = io.read()\
2637 wide = tonumber(input2)\
2638 wide = wide - 1\
2639 print(\"How Deep(Depth) You Want\")\
2640 input3 = io.read()\
2641 deep = tonumber(input3)\
2642 print(\"Is This Corrent Lenght \" .. \"Lenght = \" .. (long + 1) .. \" Width = \" .. (wide + 1) .. \" Depth = \" .. (deep))\
2643 print(\"Type y Or Y if it is correct and if not then n or N\")\
2644 corrent = io.read()\
2645 if corrent == n or N then\
2646 os.reboot()\
2647 end\
2648 print(\"Okey Program Will Do Calculations\")\
2649 totalBlocks = (wide + 1) * (long + 1) * deep -- 1 is add because above it removed for wide and long code\
2650 print(\"Total amount for block to mine is \" .. totalBlocks)\
2651 coalNeeded = totalBlocks / 3 / 80\
2652 print(\"Total amount for Coal needed is \" .. math.floor(coalNeeded+0.5))\
2653 if turtle.getFuelLevel() == \"unlimited\" then\
2654 print(\"Your turtle config does need fuel\")\
2655 noFuelNeed = 1\
2656 elseif turtle.getFuelLevel() < 160 then\
2657 turtle.select(2)\
2658 turtle.refuel(2)\
2659 end\
2660 reCheck()\
2661 check()\
2662 if error == 1 then\
2663 repeat\
2664 sleep(6)\
2665 reCheck()\
2666 check()\
2667 until error == 0\
2668 end\
2669 print(\"Turtle will now start!\")\
2670 firstDig()\
2671 main()\
2672end\
2673\
2674start()",
2675 },
2676 {
2677 path = "/cobblestone/",
2678 content = "while true do\
2679while not turtle.detect() do\
2680turtle.digUp()\
2681turtle.forward()\
2682end\
2683\
2684turtle.digUp()\
2685\
2686turtle.turnLeft()\
2687turtle.turnLeft()\
2688\
2689while not turtle.detect() do\
2690turtle.forward()\
2691end\
2692\
2693turtle.turnLeft()\
2694turtle.forward()\
2695turtle.turnLeft()\
2696\
2697end",
2698 },
2699 {
2700 path = "/destroyDirt/",
2701 content = "while not turtle.detect() do\
2702turtle.digDown()\
2703turtle.forward()\
2704end\
2705\
2706turtle.digDown()\
2707\
2708turtle.turnRight()\
2709turtle.forward()\
2710turtle.turnRight()\
2711\
2712turtle.digDown()\
2713\
2714while not turtle.detect() do\
2715turtle.digDown()\
2716turtle.forward()\
2717end\
2718\
2719turtle.digDown()\
2720turtle.up()",
2721 },
2722 {
2723 path = "/nsh/nsh/",
2724 content = "local args = { ... }\
2725\
2726local connections = {}\
2727\
2728local nshAPI = {\
2729\009connList = connections\
2730}\
2731\
2732if not framebuffer then if not ((fs.exists(\"framebuffer\") and os.loadAPI(\"framebuffer\")) or (fs.exists(\"LyqydOS/framebuffer\") and os.loadAPI(\"LyqydOS/framebuffer\"))) then print(\"Couldn't find framebuffer API, using fallback\") end end\
2733\
2734local function rawSend(id, msg)\
2735\009if term.current then\
2736\009\009return rednet.send(id, msg, \"tror\")\
2737\009else\
2738\009\009return rednet.send(id, msg)\
2739\009end\
2740end\
2741\
2742local function rawRecv(id, timeout)\
2743\009if type(timeout) == \"number\" then timeout = os.startTimer(timeout) end\
2744\009while true do\
2745\009\009event = {os.pullEvent()}\
2746\009\009if event[1] == \"rednet_message\" and (id == nil and true or event[2] == id) and (not term.current and true or event[4] == \"tror\") then\
2747\009\009\009return event[3]\
2748\009\009elseif event[1] == \"timer\" and event[2] == timeout then\
2749\009\009\009return nil\
2750\009\009end\
2751\009end\
2752end\
2753\
2754\
2755nshAPI.getRemoteID = function()\
2756\009--check for connected clients with matching threads.\
2757\009for cNum, cInfo in pairs(nshAPI.connList) do\
2758\009\009if cInfo.thread == coroutine.running() then\
2759\009\009\009if cNum == \"localShell\" then\
2760\009\009\009\009--if we are a client running on the server, return the remote server ID.\
2761\009\009\009\009if nshAPI.serverNum then\
2762\009\009\009\009\009return nshAPI.serverNum\
2763\009\009\009\009else\
2764\009\009\009\009\009return nil\
2765\009\009\009\009end\
2766\009\009\009end\
2767\009\009\009return cNum\
2768\009\009end\
2769\009end\
2770\009--client running without local server, return remote server ID.\
2771\009if nshAPI.serverNum then return nshAPI.serverNum end\
2772\009return nil\
2773end\
2774\
2775nshAPI.send = function(msg)\
2776\009local id = nshAPI.getRemoteID()\
2777\009if id then\
2778\009\009return rawSend(id, msg)\
2779\009end\
2780\009return nil\
2781end\
2782\
2783nshAPI.receive = function(timeout)\
2784\009return rawRecv(nshAPI.getRemoteID(), timeout)\
2785end\
2786\
2787nshAPI.getClientCapabilities = function()\
2788\009if nshAPI.clientCapabilities then return nshAPI.clientCapabilities end\
2789\009nshAPI.send(\"SP:;clientCapabilities\")\
2790\009return nshAPI.receive(1)\
2791end\
2792\
2793nshAPI.getRemoteConnections = function()\
2794\009local remotes = {}\
2795\009for cNum, cInfo in pairs(nshAPI.connList) do\
2796\009\009table.insert(remotes, cNum)\
2797\009\009if cInfo.outbound then\
2798\009\009\009table.insert(remotes, cInfo.outbound)\
2799\009\009end\
2800\009end\
2801\009return remotes\
2802end\
2803\
2804nshAPI.packFile = function(path)\
2805\009local data = {}\
2806\009local count = 0\
2807\009local handle = io.open(path, \"rb\")\
2808\009if handle then\
2809\009\009local byte = handle:read()\
2810\009\009repeat\
2811\009\009\009data[#data + 1] = byte\
2812\009\009\009count = count + 1\
2813\009\009\009if count % 1000 == 0 then\
2814\009\009\009\009os.queueEvent(\"yield\")\
2815\009\009\009\009os.pullEvent(\"yield\")\
2816\009\009\009end\
2817\009\009\009byte = handle:read()\
2818\009\009until not byte\
2819\009\009handle:close()\
2820\009else\
2821\009\009return false\
2822\009end\
2823\009local outputTable = {}\
2824\009for i = 1, #data, 3 do\
2825\009\009local num1, num2, num3 = data[i], data[i + 1] or 0, data[i + 2] or 0\
2826\009\009table.insert(outputTable, string.char(bit32.band(bit32.arshift(num1, 2), 63)))\
2827\009\009table.insert(outputTable, string.char(bit32.bor(bit32.band(bit32.lshift(num1, 4), 48), bit32.band(bit32.arshift(num2, 4), 15))))\
2828\009\009table.insert(outputTable, string.char(bit32.bor(bit32.band(bit32.lshift(num2, 2), 60), bit32.band(bit32.arshift(num3, 6), 3))))\
2829\009\009table.insert(outputTable, string.char(bit32.band(num3, 63)))\
2830\009end\
2831\009--mark non-data (invalid) bytes\
2832\009if #data % 3 == 1 then\
2833\009\009outputTable[#outputTable] = \"=\"\
2834\009\009outputTable[#outputTable - 1] = \"=\"\
2835\009elseif #data % 3 == 2 then\
2836\009\009outputTable[#outputTable] = \"=\"\
2837\009end\
2838\009return table.concat(outputTable, \"\")\
2839end\
2840\
2841nshAPI.unpackAndSaveFile = function(path, data)\
2842\009local outputTable = {}\
2843\009for i=1, #data, 4 do\
2844\009\009local char1, char2, char3, char4 = string.byte(string.sub(data, i, i)), string.byte(string.sub(data, i + 1, i + 1)), string.byte(string.sub(data, i + 2, i + 2)), string.byte(string.sub(data, i + 3, i + 3))\
2845\009\009table.insert(outputTable, bit32.band(bit32.bor(bit32.lshift(char1, 2), bit32.arshift(char2, 4)), 255))\
2846\009\009table.insert(outputTable, bit32.band(bit32.bor(bit32.lshift(char2, 4), bit32.arshift(char3, 2)), 255))\
2847\009\009table.insert(outputTable, bit32.band(bit32.bor(bit32.lshift(char3, 6), char4), 255))\
2848\009end\
2849\009--clean invalid bytes if marked\
2850\009if string.sub(data, #data, #data) == \"=\" then\
2851\009\009table.remove(outputTable)\
2852\009\009if string.sub(data, #data - 1, #data - 1) == \"=\" then\
2853\009\009\009table.remove(outputTable)\
2854\009\009end\
2855\009end\
2856\009local handle = io.open(path, \"wb\")\
2857\009if handle then\
2858\009\009for i = 1, #outputTable do\
2859\009\009\009handle:write(outputTable[i])\
2860\009\009\009if i % 10 == 0 then\
2861\009\009\009\009os.startTimer(0.1)\
2862\009\009\009\009os.pullEvent(\"timer\")\
2863\009\009\009end\
2864\009\009end\
2865\009\009handle:close()\
2866\009end\
2867end\
2868\
2869local packetConversion = {\
2870\009query = \"SQ\",\
2871\009response = \"SR\",\
2872\009data = \"SP\",\
2873\009close = \"SC\",\
2874\009fileQuery = \"FQ\",\
2875\009fileSend = \"FS\",\
2876\009fileResponse = \"FR\",\
2877\009fileHeader = \"FH\",\
2878\009fileData = \"FD\",\
2879\009fileEnd = \"FE\",\
2880\009textWrite = \"TW\",\
2881\009textCursorPos = \"TC\",\
2882\009textGetCursorPos = \"TG\",\
2883\009textGetSize = \"TD\",\
2884\009textInfo = \"TI\",\
2885\009textClear = \"TE\",\
2886\009textClearLine = \"TL\",\
2887\009textScroll = \"TS\",\
2888\009textBlink = \"TB\",\
2889\009textColor = \"TF\",\
2890\009textBackground = \"TK\",\
2891\009textIsColor = \"TA\",\
2892\009textTable = \"TT\",\
2893\009event = \"EV\",\
2894\009SQ = \"query\",\
2895\009SR = \"response\",\
2896\009SP = \"data\",\
2897\009SC = \"close\",\
2898\009FQ = \"fileQuery\",\
2899\009FS = \"fileSend\",\
2900\009FR = \"fileResponse\",\
2901\009FH = \"fileHeader\",\
2902\009FD = \"fileData\",\
2903\009FE = \"fileEnd\",\
2904\009TW = \"textWrite\",\
2905\009TC = \"textCursorPos\",\
2906\009TG = \"textGetCursorPos\",\
2907\009TD = \"textGetSize\",\
2908\009TI = \"textInfo\",\
2909\009TE = \"textClear\",\
2910\009TL = \"textClearLine\",\
2911\009TS = \"textScroll\",\
2912\009TB = \"textBlink\",\
2913\009TF = \"textColor\",\
2914\009TK = \"textBackground\",\
2915\009TA = \"textIsColor\",\
2916\009TT = \"textTable\",\
2917\009EV = \"event\",\
2918}\
2919\
2920local function openModem()\
2921\009local modemFound = false\
2922\009for _, side in ipairs(rs.getSides()) do\
2923\009\009if peripheral.getType(side) == \"modem\" then\
2924\009\009\009if not rednet.isOpen(side) then rednet.open(side) end\
2925\009\009\009modemFound = true\
2926\009\009\009break\
2927\009\009end\
2928\009end\
2929\009return modemFound\
2930end\
2931\
2932local function send(id, pType, message)\
2933\009if pType and message then\
2934\009\009return rawSend(id, packetConversion[pType]..\":;\"..message)\
2935\009end\
2936end\
2937\
2938local function awaitResponse(id, time)\
2939\009id = tonumber(id)\
2940\009local listenTimeOut = nil\
2941\009local messRecv = false\
2942\009if time then listenTimeOut = os.startTimer(time) end\
2943\009while not messRecv do\
2944\009\009local event, p1, p2 = os.pullEvent()\
2945\009\009if event == \"timer\" and p1 == listenTimeOut then\
2946\009\009\009return false\
2947\009\009elseif event == \"rednet_message\" then\
2948\009\009\009sender, message = p1, p2\
2949\009\009\009if id == sender and message then\
2950\009\009\009\009if packetConversion[string.sub(message, 1, 2)] then packetType = packetConversion[string.sub(message, 1, 2)] end\
2951\009\009\009\009message = string.match(message, \";(.*)\")\
2952\009\009\009\009messRecv = true\
2953\009\009\009end\
2954\009\009end\
2955\009end\
2956\009return packetType, message\
2957end\
2958\
2959local function processText(conn, pType, value)\
2960\009if not pType then return false end\
2961\009if pType == \"textWrite\" and value then\
2962\009\009term.write(value)\
2963\009elseif pType == \"textClear\" then\
2964\009\009term.clear()\
2965\009elseif pType == \"textClearLine\" then\
2966\009\009term.clearLine()\
2967\009elseif pType == \"textGetCursorPos\" then\
2968\009\009local x, y = term.getCursorPos()\
2969\009\009send(conn, \"textInfo\", math.floor(x)..\",\"..math.floor(y))\
2970\009elseif pType == \"textCursorPos\" then\
2971\009\009local x, y = string.match(value, \"(%-?%d+),(%-?%d+)\")\
2972\009\009term.setCursorPos(tonumber(x), tonumber(y))\
2973\009elseif pType == \"textBlink\" then\
2974\009\009if value == \"true\" then\
2975\009\009\009term.setCursorBlink(true)\
2976\009\009else\
2977\009\009\009term.setCursorBlink(false)\
2978\009\009end\
2979\009elseif pType == \"textGetSize\" then\
2980\009\009x, y = term.getSize()\
2981\009\009send(conn, \"textInfo\", x..\",\"..y)\
2982\009elseif pType == \"textScroll\" and value then\
2983\009\009term.scroll(tonumber(value))\
2984\009elseif pType == \"textIsColor\" then\
2985\009\009send(conn, \"textInfo\", tostring(term.isColor()))\
2986\009elseif pType == \"textColor\" and value then\
2987\009\009value = tonumber(value)\
2988\009\009if (value == 1 or value == 32768) or term.isColor() then\
2989\009\009\009term.setTextColor(value)\
2990\009\009end\
2991\009elseif pType == \"textBackground\" and value then\
2992\009\009value = tonumber(value)\
2993\009\009if (value == 1 or value == 32768) or term.isColor() then\
2994\009\009\009term.setBackgroundColor(value)\
2995\009\009end\
2996\009elseif pType == \"textTable\" then\
2997\009\009local linesTable = textutils.unserialize(value)\
2998\009\009for i=1, linesTable.sizeY do\
2999\009\009\009term.setCursorPos(1,i)\
3000\009\009\009local lineEnd = false\
3001\009\009\009local offset = 1\
3002\009\009\009while not lineEnd do\
3003\009\009\009\009local textColorString = string.match(string.sub(linesTable.textColor[i], offset), string.sub(linesTable.textColor[i], offset, offset)..\"*\")\
3004\009\009\009\009local backColorString = string.match(string.sub(linesTable.backColor[i], offset), string.sub(linesTable.backColor[i], offset, offset)..\"*\")\
3005\009\009\009\009term.setTextColor(2 ^ tonumber(string.sub(textColorString, 1, 1), 16))\
3006\009\009\009\009term.setBackgroundColor(2 ^ tonumber(string.sub(backColorString, 1, 1), 16))\
3007\009\009\009\009term.write(string.sub(linesTable.text[i], offset, offset + math.min(#textColorString, #backColorString) - 1))\
3008\009\009\009\009offset = offset + math.min(#textColorString, #backColorString)\
3009\009\009\009\009if offset > linesTable.sizeX then lineEnd = true end\
3010\009\009\009end\
3011\009\009end\
3012\009\009term.setCursorPos(linesTable.cursorX, linesTable.cursorY)\
3013\009\009term.setCursorBlink(linesTable.cursorBlink)\
3014\009end\
3015\009return\
3016end\
3017\
3018local function textRedirect(id)\
3019\009local textTable = {}\
3020\009textTable.id = id\
3021\009textTable.write = function(text)\
3022\009\009return send(textTable.id, \"textWrite\", text)\
3023\009end\
3024\009textTable.clear = function()\
3025\009\009return send(textTable.id, \"textClear\", \"nil\")\
3026\009end\
3027\009textTable.clearLine = function()\
3028\009\009return send(textTable.id, \"textClearLine\", \"nil\")\
3029\009end\
3030\009textTable.getCursorPos = function()\
3031\009\009send(textTable.id, \"textGetCursorPos\", \"nil\")\
3032\009\009local pType, message = awaitResponse(textTable.id, 2)\
3033\009\009if pType and pType == \"textInfo\" then\
3034\009\009\009local x, y = string.match(message, \"(%-?%d+),(%-?%d+)\")\
3035\009\009\009return tonumber(x), tonumber(y)\
3036\009\009end\
3037\009end\
3038\009textTable.setCursorPos = function(x, y)\
3039\009\009return send(textTable.id, \"textCursorPos\", math.floor(x)..\",\"..math.floor(y))\
3040\009end\
3041\009textTable.setCursorBlink = function(b)\
3042\009\009if b then\
3043\009\009\009return send(textTable.id, \"textBlink\", \"true\")\
3044\009\009else\
3045\009\009\009return send(textTable.id, \"textBlink\", \"false\")\
3046\009\009end\
3047\009end\
3048\009textTable.getSize = function()\
3049\009\009send(textTable.id, \"textGetSize\", \"nil\")\
3050\009\009local pType, message = awaitResponse(textTable.id, 2)\
3051\009\009if pType and pType == \"textInfo\" then\
3052\009\009\009local x, y = string.match(message, \"(%d+),(%d+)\")\
3053\009\009\009return tonumber(x), tonumber(y)\
3054\009\009end\
3055\009end\
3056\009textTable.scroll = function(lines)\
3057\009\009return send(textTable.id, \"textScroll\", lines)\
3058\009end\
3059\009textTable.isColor = function()\
3060\009\009send(textTable.id, \"textIsColor\", \"nil\")\
3061\009\009local pType, message = awaitResponse(textTable.id, 2)\
3062\009\009if pType and pType == \"textInfo\" then\
3063\009\009\009if message == \"true\" then\
3064\009\009\009\009return true\
3065\009\009\009end\
3066\009\009end\
3067\009\009return false\
3068\009end\
3069\009textTable.isColour = textTable.isColor\
3070\009textTable.setTextColor = function(color)\
3071\009\009return send(textTable.id, \"textColor\", tostring(color))\
3072\009end\
3073\009textTable.setTextColour = textTable.setTextColor\
3074\009textTable.setBackgroundColor = function(color)\
3075\009\009return send(textTable.id, \"textBackground\", tostring(color))\
3076\009end\
3077\009textTable.setBackgroundColour = textTable.setBackgroundColor\
3078\009return textTable\
3079end\
3080\
3081local function getServerID(server)\
3082\009if tonumber(server) then\
3083\009\009return tonumber(server)\
3084\009elseif term.current then\
3085\009\009return rednet.lookup(\"tror\", args[1])\
3086\009end\
3087end\
3088\
3089local function resumeThread(conn, event)\
3090\009local cInfo = connections[conn]\
3091\009if not connections[conn].filter or event[1] == connections[conn].filter then\
3092\009\009connections[conn].filter = nil\
3093\009\009local _oldTerm = term.redirect(connections[conn].target)\
3094\009\009local passback = {coroutine.resume(connections[conn].thread, table.unpack(event))}\
3095\009\009if passback[1] and passback[2] then\
3096\009\009\009connections[conn].filter = passback[2]\
3097\009\009end\
3098\009\009if coroutine.status(connections[conn].thread) == \"dead\" then\
3099\009\009\009send(conn, \"close\", \"disconnect\")\
3100\009\009\009connections[conn] = nil\
3101\009\009end\
3102\009\009if _oldTerm then\
3103\009\009\009term.redirect(_oldTerm)\
3104\009\009else\
3105\009\009\009term.restore()\
3106\009\009end\
3107\009\009if connections[conn] and conn ~= \"localShell\" and framebuffer then\
3108\009\009\009send(conn, \"textTable\", textutils.serialize(connections[conn].target.buffer))\
3109\009\009end\
3110\009end\
3111end\
3112\
3113local eventFilter = {\
3114\009key = true,\
3115\009char = true,\
3116\009mouse_click = true,\
3117\009mouse_drag = true,\
3118\009mouse_scroll = true,\
3119}\
3120\
3121local function newSession(conn, x, y, color)\
3122\009local session = {}\
3123\009local path = \"/rom/programs/shell\"\
3124\009if #args >= 2 and shell.resolveProgram(args[2]) then path = shell.resolveProgram(args[2]) end\
3125\009session.thread = coroutine.create(function() shell.run(path) end)\
3126\009if framebuffer then\
3127\009\009session.target = framebuffer.new(x, y, color)\
3128\009else\
3129\009\009session.target = textRedirect(conn)\
3130\009end\
3131\009session.status = \"open\"\
3132\009_oldTerm = term.redirect(session.target)\
3133\009coroutine.resume(session.thread)\
3134\009if _oldTerm then\
3135\009\009term.redirect(_oldTerm)\
3136\009else\
3137\009\009term.restore()\
3138\009end\
3139\009if framebuffer then\
3140\009\009send(conn, \"textTable\", textutils.serialize(session.target.buffer))\
3141\009end\
3142\009return session\
3143end\
3144\
3145if #args >= 1 and args[1] == \"host\" then\
3146\009_G.nsh = nshAPI\
3147\009if not openModem() then return end\
3148\009if term.current then\
3149\009\009if args[4] then\
3150\009\009\009rednet.host(\"tror\", args[4])\
3151\009\009elseif os.getComputerLabel() then\
3152\009\009\009rednet.host(\"tror\", os.getComputerLabel())\
3153\009\009else\
3154\009\009\009print(\"No label or hostname provided!\")\
3155\009\009\009return\
3156\009\009end\
3157\009end\
3158\009local connInfo = {}\
3159\009connInfo.target = term.current and term.current() or term.native\
3160\009local path = \"/rom/programs/shell\"\
3161\009if #args >= 3 and shell.resolveProgram(args[3]) then path = shell.resolveProgram(args[3]) end\
3162\009connInfo.thread = coroutine.create(function() shell.run(path) end)\
3163\009connections.localShell = connInfo\
3164\009term.clear()\
3165\009term.setCursorPos(1,1)\
3166\009coroutine.resume(connections.localShell.thread)\
3167\
3168\009while true do\
3169\009\009event = {os.pullEventRaw()}\
3170\009\009if event[1] == \"rednet_message\" then\
3171\009\009\009if type(event[3]) == \"string\" and packetConversion[string.sub(event[3], 1, 2)] then\
3172\009\009\009\009--this is a packet meant for us.\
3173\009\009\009\009conn = event[2]\
3174\009\009\009\009packetType = packetConversion[string.sub(event[3], 1, 2)]\
3175\009\009\009\009message = string.match(event[3], \";(.*)\")\
3176\009\009\009\009if connections[conn] and connections[conn].status == \"open\" then\
3177\009\009\009\009\009if packetType == \"event\" or string.sub(packetType, 1, 4) == \"text\" then\
3178\009\009\009\009\009\009local eventTable = {}\
3179\009\009\009\009\009\009if packetType == \"event\" then\
3180\009\009\009\009\009\009\009eventTable = textutils.unserialize(message)\
3181\009\009\009\009\009\009else\
3182\009\009\009\009\009\009\009--we can pass the packet in raw, since this is not an event packet.\
3183\009\009\009\009\009\009\009eventTable = event\
3184\009\009\009\009\009\009end\
3185\009\009\009\009\009\009resumeThread(conn, eventTable)\
3186\009\009\009\009\009elseif packetType == \"query\" then\
3187\009\009\009\009\009\009local connType, color, x, y = string.match(message, \"(%a+):(%a+);(%d+),(%d+)\")\
3188\009\009\009\009\009\009if connType == \"connect\" or (connType == \"resume\" and (not framebuffer)) then\
3189\009\009\009\009\009\009\009--reset connection\
3190\009\009\009\009\009\009\009send(conn, \"response\", \"OK\")\
3191\009\009\009\009\009\009\009connections[conn] = newSession(conn, tonumber(x), tonumber(y), color == \"true\")\
3192\009\009\009\009\009\009elseif connType == \"resume\" then\
3193\009\009\009\009\009\009\009--restore connection\
3194\009\009\009\009\009\009\009send(conn, \"response\", \"OK\")\
3195\009\009\009\009\009\009\009send(conn, \"textTable\", textutils.serialize(connections[conn].target.buffer))\
3196\009\009\009\009\009\009end\
3197\009\009\009\009\009elseif packetType == \"close\" then\
3198\009\009\009\009\009\009connections[conn] = nil\
3199\009\009\009\009\009\009send(conn, \"close\", \"disconnect\")\
3200\009\009\009\009\009\009--close connection\
3201\009\009\009\009\009else\
3202\009\009\009\009\009\009--we got a packet, have an open connection, but despite it being in the conversion table, don't handle it ourselves. Send it onward.\
3203\009\009\009\009\009\009resumeThread(conn, event)\
3204\009\009\009\009\009end\
3205\009\009\009\009elseif packetType ~= \"query\" then\
3206\009\009\009\009\009--usually, we would send a disconnect here, but this prevents one from hosting nsh and connecting to other computers. Pass these to all shells as well.\
3207\009\009\009\009\009for cNum, cInfo in pairs(connections) do\
3208\009\009\009\009\009\009resumeThread(cNum, event)\
3209\009\009\009\009\009end\
3210\009\009\009\009else\
3211\009\009\009\009\009--open new connection\
3212\009\009\009\009\009send(conn, \"response\", \"OK\")\
3213\009\009\009\009\009local color, x, y = string.match(message, \"connect:(%a+);(%d+),(%d+)\")\
3214\009\009\009\009\009local connInfo = newSession(conn, tonumber(x), tonumber(y), color == \"true\")\
3215\009\009\009\009\009connections[conn] = connInfo\
3216\009\009\009\009end\
3217\009\009\009else\
3218\009\009\009\009--rednet message, but not in the correct format, so pass to all shells.\
3219\009\009\009\009for cNum, cInfo in pairs(connections) do\
3220\009\009\009\009\009resumeThread(cNum, event)\
3221\009\009\009\009end\
3222\009\009\009end\
3223\009\009elseif eventFilter[event[1]] then\
3224\009\009\009--user interaction.\
3225\009\009\009coroutine.resume(connections.localShell.thread, table.unpack(event))\
3226\009\009\009if coroutine.status(connections.localShell.thread) == \"dead\" then\
3227\009\009\009\009for cNum, cInfo in pairs(connections) do\
3228\009\009\009\009\009if cNum ~= \"localShell\" then\
3229\009\009\009\009\009\009send(cNum, \"close\", \"disconnect\")\
3230\009\009\009\009\009end\
3231\009\009\009\009end\
3232\009\009\009\009return\
3233\009\009\009end\
3234\009\009else\
3235\009\009\009--dispatch all other events to all shells\
3236\009\009\009for cNum, cInfo in pairs(connections) do\
3237\009\009\009\009resumeThread(cNum, event)\
3238\009\009\009end\
3239\009\009end\
3240\009end\
3241\
3242elseif #args <= 2 and nsh and nsh.getRemoteID() then\
3243\009print(nsh.getRemoteID())\
3244\009--forwarding mode\
3245\009local conns = nsh.getRemoteConnections()\
3246\009for i = 1, #conns do\
3247\009\009if conns[i] == serverNum then\
3248\009\009\009print(\"Cyclic connection refused.\")\
3249\009\009\009return\
3250\009\009end\
3251\009end\
3252\009local fileTransferState = nil\
3253\009local fileData = nil\
3254\009local serverNum = getServerID(args[1])\
3255\009if not serverNum then\
3256\009\009print(\"Server Not Found\")\
3257\009\009return\
3258\009end\
3259\009send(serverNum, \"query\", \"connect\")\
3260\009local pType, message = awaitResponse(serverNum, 2)\
3261\009if pType ~= \"response\" then\
3262\009\009print(\"Connection Failed\")\
3263\009\009return\
3264\009else\
3265\009\009nsh.connList[nsh.getRemoteID()].outbound = serverNum\
3266\009\009term.clear()\
3267\009\009term.setCursorPos(1,1)\
3268\009end\
3269\009local clientID = nsh.getRemoteID()\
3270\009local serverID = tonumber(args[1])\
3271\009while true do\
3272\009\009event = {os.pullEvent()}\
3273\009\009if event[1] == \"rednet_message\" then\
3274\009\009\009if event[2] == clientID or event[2] == serverID then\
3275\009\009\009\009if event[2] == serverID and string.sub(event[3], 1, 2) == \"SC\" then break end\
3276\009\009\009\009rednet.send((event[2] == clientID and serverID or clientID), event[3])\
3277\009\009\009end\
3278\009\009elseif eventFilter[event[1]] then\
3279\009\009\009rednet.send(serverID, \"EV:;\"..textutils.serialize(event))\
3280\009\009end\
3281\009end\
3282\009nsh.connList[nsh.getRemoteID()].outbound = nil\
3283\009term.clear()\
3284\009term.setCursorPos(1, 1)\
3285\009print(\"Connection closed by server\")\
3286\
3287elseif #args >= 1 then --either no server running or we are the local shell on the server.\
3288\009if not openModem() then return end\
3289\009local serverNum = getServerID(args[1])\
3290\009if not serverNum then\
3291\009\009print(\"Server Not Found\")\
3292\009\009return\
3293\009end\
3294\009if nsh then\
3295\009\009local conns = nsh.getRemoteConnections()\
3296\009\009for i = 1, #conns do\
3297\009\009\009if conns[i] == serverNum then\
3298\009\009\009\009print(\"Connection refused.\")\
3299\009\009\009\009return\
3300\009\009\009end\
3301\009\009end\
3302\009end\
3303\009local fileTransferState = nil\
3304\009local fileData = nil\
3305\009local fileBinaryData = nil\
3306\009local unpackCo = {}\
3307\009local color = term.isColor()\
3308\009local x, y = term.getSize()\
3309\009if args[2] == \"resume\" then\
3310\009\009send(serverNum, \"query\", \"resume:\"..tostring(color)..\";\"..tostring(x)..\",\"..tostring(y))\
3311\009else\
3312\009\009send(serverNum, \"query\", \"connect:\"..tostring(color)..\";\"..tostring(x)..\",\"..tostring(y))\
3313\009end\
3314\009local timeout = os.startTimer(2)\
3315\009while true do\
3316\009\009local event = {os.pullEvent()}\
3317\009\009if event[1] == \"timer\" and event[2] == timeout then\
3318\009\009\009print(\"Connection failed.\")\
3319\009\009\009return\
3320\009\009elseif event[1] == \"rednet_message\" and event[2] == serverNum and string.sub(event[3], 1, 2) == \"SR\" then\
3321\009\009\009if nsh then nshAPI = nsh end\
3322\009\009\009if nshAPI.connList and nshAPI.connList.localShell then nshAPI.connList.localShell.outbound = serverNum end\
3323\009\009\009nshAPI.serverNum = serverNum\
3324\009\009\009nshAPI.clientCapabilities = \"-fileTransfer-extensions-\"\
3325\009\009\009term.clear()\
3326\009\009\009term.setCursorPos(1,1)\
3327\009\009\009break\
3328\009\009end\
3329\009end\
3330\
3331\009while true do\
3332\009\009event = {os.pullEventRaw()}\
3333\009\009if #unpackCo > 0 then\
3334\009\009\009for i = #unpackCo, 1, -1 do\
3335\009\009\009\009if coroutine.status(unpackCo[i]) ~= \"dead\" then\
3336\009\009\009\009\009coroutine.resume(unpackCo[i], table.unpack(event))\
3337\009\009\009\009else\
3338\009\009\009\009\009table.remove(unpackCo, i)\
3339\009\009\009\009end\
3340\009\009\009end\
3341\009\009end\
3342\009\009if event[1] == \"rednet_message\" and event[2] == serverNum then\
3343\009\009\009if packetConversion[string.sub(event[3], 1, 2)] then\
3344\009\009\009\009packetType = packetConversion[string.sub(event[3], 1, 2)]\
3345\009\009\009\009message = string.match(event[3], \";(.*)\")\
3346\009\009\009\009if string.sub(packetType, 1, 4) == \"text\" then\
3347\009\009\009\009\009processText(serverNum, packetType, message)\
3348\009\009\009\009elseif packetType == \"data\" then\
3349\009\009\009\009\009if message == \"clientCapabilities\" then\
3350\009\009\009\009\009\009rednet.send(serverNum, nshAPI.clientCapabilities)\
3351\009\009\009\009\009end\
3352\009\009\009\009elseif packetType == \"fileQuery\" then\
3353\009\009\009\009\009--send a file to the server\
3354\009\009\009\009\009local mode, file = string.match(message, \"^(%a)=(.*)\")\
3355\009\009\009\009\009if fs.exists(file) then\
3356\009\009\009\009\009\009send(serverNum, \"fileHeader\", file)\
3357\009\009\009\009\009\009if mode == \"b\" then\
3358\009\009\009\009\009\009\009local fileString = nshAPI.packFile(file)\
3359\009\009\009\009\009\009\009send(serverNum, \"fileData\", \"b=\"..fileString)\
3360\009\009\009\009\009\009else\
3361\009\009\009\009\009\009\009local handle = io.open(file, \"r\")\
3362\009\009\009\009\009\009\009if handle then\
3363\009\009\009\009\009\009\009\009send(serverNum, \"fileData\", \"t=\"..handle:read(\"*a\"))\
3364\009\009\009\009\009\009\009\009handle:close()\
3365\009\009\009\009\009\009\009end\
3366\009\009\009\009\009\009end\
3367\009\009\009\009\009else\
3368\009\009\009\009\009\009send(serverNum, \"fileHeader\", \"fileNotFound\")\
3369\009\009\009\009\009end\
3370\009\009\009\009\009send(serverNum, \"fileEnd\", \"end\")\
3371\009\009\009\009elseif packetType == \"fileSend\" then\
3372\009\009\009\009\009--receive a file from the server, but don't overwrite existing files.\
3373\009\009\009\009\009local mode, file = string.match(message, \"^(%a)=(.*)\")\
3374\009\009\009\009\009if not fs.exists(file) then\
3375\009\009\009\009\009\009fileTransferState = \"receive_wait:\"..file\
3376\009\009\009\009\009\009send(serverNum, \"fileResponse\", \"ok\")\
3377\009\009\009\009\009\009if mode == \"b\" then\
3378\009\009\009\009\009\009\009fileBinaryData = \"\"\
3379\009\009\009\009\009\009\009fileData = nil\
3380\009\009\009\009\009\009else\
3381\009\009\009\009\009\009\009fileData = \"\"\
3382\009\009\009\009\009\009\009fileBinaryData = nil\
3383\009\009\009\009\009\009end\
3384\009\009\009\009\009else\
3385\009\009\009\009\009\009send(serverNum, \"fileResponse\", \"reject\")\
3386\009\009\009\009\009end\
3387\009\009\009\009elseif packetType == \"fileHeader\" then\
3388\009\009\009\009\009if message == \"fileNotFound\" then\
3389\009\009\009\009\009\009fileTransferState = nil\
3390\009\009\009\009\009end\
3391\009\009\009\009elseif packetType == \"fileData\" then\
3392\009\009\009\009\009if fileTransferState and string.match(fileTransferState, \"(.-):\") == \"receive_wait\" then\
3393\009\009\009\009\009\009if string.match(message, \"^(%a)=\") == \"b\" then\
3394\009\009\009\009\009\009\009fileBinaryData = fileBinaryData..string.match(message, \"^b=(.*)\")\
3395\009\009\009\009\009\009else\
3396\009\009\009\009\009\009\009fileData = fileData..string.match(message, \"^t=(.*)\")\
3397\009\009\009\009\009\009end\
3398\009\009\009\009\009end\
3399\009\009\009\009elseif packetType == \"fileEnd\" then\
3400\009\009\009\009\009if fileTransferState and string.match(fileTransferState, \"(.-):\") == \"receive_wait\" then\
3401\009\009\009\009\009\009if fileBinaryData then\
3402\009\009\009\009\009\009\009local co = coroutine.create(nshAPI.unpackAndSaveFile)\
3403\009\009\009\009\009\009\009coroutine.resume(co, string.match(fileTransferState, \":(.*)\"), fileBinaryData)\
3404\009\009\009\009\009\009\009if coroutine.status(co) ~= \"dead\" then\
3405\009\009\009\009\009\009\009\009table.insert(unpackCo, co)\
3406\009\009\009\009\009\009\009end\
3407\009\009\009\009\009\009elseif fileData then\
3408\009\009\009\009\009\009\009local handle = io.open(string.match(fileTransferState, \":(.*)\"), \"w\")\
3409\009\009\009\009\009\009\009if handle then\
3410\009\009\009\009\009\009\009\009handle:write(fileData)\
3411\009\009\009\009\009\009\009\009handle:close()\
3412\009\009\009\009\009\009\009end\
3413\009\009\009\009\009\009end\
3414\009\009\009\009\009\009fileTransferState = nil\
3415\009\009\009\009\009end\
3416\009\009\009\009elseif packetType == \"close\" then\
3417\009\009\009\009\009if term.isColor() then\
3418\009\009\009\009\009\009term.setBackgroundColor(colors.black)\
3419\009\009\009\009\009\009term.setTextColor(colors.white)\
3420\009\009\009\009\009end\
3421\009\009\009\009\009term.clear()\
3422\009\009\009\009\009term.setCursorPos(1, 1)\
3423\009\009\009\009\009print(\"Connection closed by server.\")\
3424\009\009\009\009\009nshAPI.serverNum = nil\
3425\009\009\009\009\009if nshAPI.connList and nshAPI.connList.localShell then nshAPI.connList.localShell.outbound = nil end\
3426\009\009\009\009\009return\
3427\009\009\009\009end\
3428\009\009\009end\
3429\009\009elseif event[1] == \"mouse_click\" or event[1] == \"mouse_drag\" or event[1] == \"mouse_scroll\" or event[1] == \"key\" or event[1] == \"char\" then\
3430\009\009\009--pack up event\
3431\009\009\009send(serverNum, \"event\", textutils.serialize(event))\
3432\009\009elseif event[1] == \"terminate\" then\
3433\009\009\009nshAPI.serverNum = nil\
3434\009\009\009if nshAPI.localShell then nshAPI.localShell.outbound = nil end\
3435\009\009\009term.clear()\
3436\009\009\009term.setCursorPos(1, 1)\
3437\009\009\009print(\"Connection closed locally.\")\
3438\009\009\009return\
3439\009\009end\
3440\009end\
3441else\
3442\009print(\"Usage: nsh <serverID> [resume]\")\
3443\009print(\" nsh host [remote [local [name]]]\")\
3444end",
3445 },
3446 {
3447 path = "/nsh/framebuffer/",
3448 content = "function new(_sizeX, _sizeY, _color)\
3449\009local redirect = {buffer = {text = {}, textColor = {}, backColor = {}, cursorX = 1, cursorY = 1, cursorBlink = false, curTextColor = \"0\", curBackColor = \"f\", sizeX = _sizeX or 51, sizeY = _sizeY or 19, color = _color}}\
3450\009redirect.write = function(text)\
3451\009\009text = tostring(text)\
3452\009\009local pos = redirect.buffer.cursorX\
3453\009\009if redirect.buffer.cursorY > redirect.buffer.sizeY or redirect.buffer.cursorY < 1 then\
3454\009\009\009redirect.buffer.cursorX = pos + #text\
3455\009\009\009return\
3456\009\009end\
3457\009\009local writeText\
3458\009\009if pos + #text <= 1 then\
3459\009\009\009--skip entirely.\
3460\009\009\009redirect.buffer.cursorX = pos + #text\
3461\009\009\009return\
3462\009\009elseif pos < 1 then\
3463\009\009\009--adjust text to fit on screen starting at one.\
3464\009\009\009writeText = string.sub(text, math.abs(redirect.buffer.cursorX) + 2)\
3465\009\009\009redirect.buffer.cursorX = 1\
3466\009\009elseif pos > redirect.buffer.sizeX then\
3467\009\009\009--if we're off the edge to the right, skip entirely.\
3468\009\009\009redirect.buffer.cursorX = pos + #text\
3469\009\009\009return\
3470\009\009else\
3471\009\009\009writeText = text\
3472\009\009end\
3473\009\009local lineText = redirect.buffer.text[redirect.buffer.cursorY]\
3474\009\009local lineColor = redirect.buffer.textColor[redirect.buffer.cursorY]\
3475\009\009local lineBack = redirect.buffer.backColor[redirect.buffer.cursorY]\
3476\009\009local preStop = redirect.buffer.cursorX - 1\
3477\009\009local preStart = math.min(1, preStop)\
3478\009\009local postStart = redirect.buffer.cursorX + string.len(writeText)\
3479\009\009local postStop = redirect.buffer.sizeX\
3480\009\009redirect.buffer.text[redirect.buffer.cursorY] = string.sub(lineText, preStart, preStop)..writeText..string.sub(lineText, postStart, postStop)\
3481\009\009redirect.buffer.textColor[redirect.buffer.cursorY] = string.sub(lineColor, preStart, preStop)..string.rep(redirect.buffer.curTextColor, #writeText)..string.sub(lineColor, postStart, postStop)\
3482\009\009redirect.buffer.backColor[redirect.buffer.cursorY] = string.sub(lineBack, preStart, preStop)..string.rep(redirect.buffer.curBackColor, #writeText)..string.sub(lineBack, postStart, postStop)\
3483\009\009redirect.buffer.cursorX = pos + string.len(text)\
3484\009end\
3485\009redirect.clear = function()\
3486\009\009for i=1, redirect.buffer.sizeY do\
3487\009\009\009redirect.buffer.text[i] = string.rep(\" \", redirect.buffer.sizeX)\
3488\009\009\009redirect.buffer.textColor[i] = string.rep(redirect.buffer.curTextColor, redirect.buffer.sizeX)\
3489\009\009\009redirect.buffer.backColor[i] = string.rep(redirect.buffer.curBackColor, redirect.buffer.sizeX)\
3490\009\009end\
3491\009end\
3492\009redirect.clearLine = function()\
3493\009\009redirect.buffer.text[redirect.buffer.cursorY] = string.rep(\" \", redirect.buffer.sizeX)\
3494\009\009redirect.buffer.textColor[redirect.buffer.cursorY] = string.rep(redirect.buffer.curTextColor, redirect.buffer.sizeX)\
3495\009\009redirect.buffer.backColor[redirect.buffer.cursorY] = string.rep(redirect.buffer.curBackColor, redirect.buffer.sizeX)\
3496\009end\
3497\009redirect.getCursorPos = function()\
3498\009\009return redirect.buffer.cursorX, redirect.buffer.cursorY\
3499\009end\
3500\009redirect.setCursorPos = function(x, y)\
3501\009\009redirect.buffer.cursorX = math.floor(tonumber(x)) or redirect.buffer.cursorX\
3502\009\009redirect.buffer.cursorY = math.floor(tonumber(y)) or redirect.buffer.cursorY\
3503\009end\
3504\009redirect.setCursorBlink = function(b)\
3505\009\009redirect.buffer.cursorBlink = b\
3506\009end\
3507\009redirect.getSize = function()\
3508\009\009return redirect.buffer.sizeX, redirect.buffer.sizeY\
3509\009end\
3510\009redirect.scroll = function(n)\
3511\009\009n = tonumber(n) or 1\
3512\009\009if n > 0 then\
3513\009\009\009for i = 1, redirect.buffer.sizeY - n do\
3514\009\009\009\009if redirect.buffer.text[i + n] then\
3515\009\009\009\009\009redirect.buffer.text[i] = redirect.buffer.text[i + n]\
3516\009\009\009\009\009redirect.buffer.textColor[i] = redirect.buffer.textColor[i + n]\
3517\009\009\009\009\009redirect.buffer.backColor[i] = redirect.buffer.backColor[i + n]\
3518\009\009\009\009end\
3519\009\009\009end\
3520\009\009\009for i = redirect.buffer.sizeY, redirect.buffer.sizeY - n + 1, -1 do\
3521\009\009\009\009redirect.buffer.text[i] = string.rep(\" \", redirect.buffer.sizeX)\
3522\009\009\009\009redirect.buffer.textColor[i] = string.rep(redirect.buffer.curTextColor, redirect.buffer.sizeX)\
3523\009\009\009\009redirect.buffer.backColor[i] = string.rep(redirect.buffer.curBackColor, redirect.buffer.sizeX)\
3524\009\009\009end\
3525\009\009elseif n < 0 then\
3526\009\009\009for i = redirect.buffer.sizeY, math.abs(n) + 1, -1 do\
3527\009\009\009\009if redirect.buffer.text[i + n] then\
3528\009\009\009\009\009redirect.buffer.text[i] = redirect.buffer.text[i + n]\
3529\009\009\009\009\009redirect.buffer.textColor[i] = redirect.buffer.textColor[i + n]\
3530\009\009\009\009\009redirect.buffer.backColor[i] = redirect.buffer.backColor[i + n]\
3531\009\009\009\009end\
3532\009\009\009end\
3533\009\009\009for i = 1, math.abs(n) do\
3534\009\009\009\009redirect.buffer.text[i] = string.rep(\" \", redirect.buffer.sizeX)\
3535\009\009\009\009redirect.buffer.textColor[i] = string.rep(redirect.buffer.curTextColor, redirect.buffer.sizeX)\
3536\009\009\009\009redirect.buffer.backColor[i] = string.rep(redirect.buffer.curBackColor, redirect.buffer.sizeX)\
3537\009\009\009end\
3538\009\009end\
3539\009end\
3540\009redirect.setTextColor = function(clr)\
3541\009\009if clr and clr <= 32768 and clr >= 1 then\
3542\009\009\009if redirect.buffer.color then\
3543\009\009\009\009redirect.buffer.curTextColor = string.format(\"%x\", math.floor(math.log(clr) / math.log(2)))\
3544\009\009\009elseif clr == 1 or clr == 32768 then\
3545\009\009\009\009redirect.buffer.curTextColor = string.format(\"%x\", math.floor(math.log(clr) / math.log(2)))\
3546\009\009\009else\
3547\009\009\009\009return nil, \"Colour not supported\"\
3548\009\009\009end\
3549\009\009end\
3550\009end\
3551\009redirect.setTextColour = redirect.setTextColor\
3552\009redirect.setBackgroundColor = function(clr)\
3553\009\009if clr and clr <= 32768 and clr >= 1 then\
3554\009\009\009if redirect.buffer.color then\
3555\009\009\009\009redirect.buffer.curBackColor = string.format(\"%x\", math.floor(math.log(clr) / math.log(2)))\
3556\009\009\009elseif clr == 32768 or clr == 1 then\
3557\009\009\009\009redirect.buffer.curBackColor = string.format(\"%x\", math.floor(math.log(clr) / math.log(2)))\
3558\009\009\009else\
3559\009\009\009\009return nil, \"Colour not supported\"\
3560\009\009\009end\
3561\009\009end\
3562\009end\
3563\009redirect.setBackgroundColour = redirect.setBackgroundColor\
3564\009redirect.isColor = function()\
3565\009\009return redirect.buffer.color == true\
3566\009end\
3567\009redirect.isColour = redirect.isColor\
3568\009redirect.render = function(inputBuffer)\
3569\009\009for i = 1, redirect.buffer.sizeY do\
3570\009\009\009redirect.buffer.text[i] = inputBuffer.text[i]\
3571\009\009\009redirect.buffer.textColor[i] = inputBuffer.textColor[i]\
3572\009\009\009redirect.buffer.backColor[i] = inputBuffer.backColor[i]\
3573\009\009end\
3574\009end\
3575\009redirect.clear()\
3576\009return redirect\
3577end\
3578\
3579function draw(buffer, current)\
3580\009for i=1, buffer.sizeY do\
3581\009\009term.setCursorPos(1,i)\
3582\009\009if (current and (buffer.text[i] ~= current.text[i] or buffer.textColor[i] ~= current.textColor[i] or buffer.backColor[i] ~= current.backColor[i])) or not current then\
3583\009\009\009local lineEnd = false\
3584\009\009\009local offset = 1\
3585\009\009\009while not lineEnd do\
3586\009\009\009\009local textColorString = string.match(string.sub(buffer.textColor[i], offset), string.sub(buffer.textColor[i], offset, offset)..\"*\")\
3587\009\009\009\009local backColorString = string.match(string.sub(buffer.backColor[i], offset), string.sub(buffer.backColor[i], offset, offset)..\"*\")\
3588\009\009\009\009term.setTextColor(2 ^ tonumber(string.sub(textColorString, 1, 1), 16))\
3589\009\009\009\009term.setBackgroundColor(2 ^ tonumber(string.sub(backColorString, 1, 1), 16))\
3590\009\009\009\009term.write(string.sub(buffer.text[i], offset, offset + math.min(#textColorString, #backColorString) - 1))\
3591\009\009\009\009offset = offset + math.min(#textColorString, #backColorString)\
3592\009\009\009\009if offset > buffer.sizeX then lineEnd = true end\
3593\009\009\009end\
3594\009\009\009if current then\
3595\009\009\009\009current.text[i] = buffer.text[i]\
3596\009\009\009\009current.textColor[i] = buffer.textColor[i]\
3597\009\009\009\009current.backColor[i] = buffer.backColor[i]\
3598\009\009\009end\
3599\009\009end\
3600\009end\
3601\009term.setCursorPos(buffer.cursorX, buffer.cursorY)\
3602\009term.setTextColor(2 ^ tonumber(buffer.curTextColor, 16))\
3603\009term.setBackgroundColor(2 ^ tonumber(buffer.curBackColor, 16))\
3604\009term.setCursorBlink(buffer.cursorBlink)\
3605\009return current\
3606end",
3607 },
3608 {
3609 path = "/nsh/get/",
3610 content = "if not nsh then print(\"No nsh session!\") return end\
3611\
3612local args = {...}\
3613\
3614if #args < 2 then\
3615\009print(\"Usage: get <remote> <local>\")\
3616\009print(\"<remote>: any file on the server\")\
3617\009print(\"<local>: any non-existant file on the client\")\
3618\009return\
3619end\
3620\
3621if fs.exists(args[1]) then\
3622\009nsh.send(\"FS:;t=\"..args[2])\
3623\009local message = nsh.receive()\
3624\009if message == \"FR:;ok\" then\
3625\009\009nsh.send(\"FH:;\"..args[1])\
3626\009\009local handle = io.open(args[1], \"r\")\
3627\009\009if handle then\
3628\009\009\009nsh.send(\"FD:;t=\"..handle:read(\"*a\"))\
3629\009\009\009handle:close()\
3630\009\009end\
3631\009\009nsh.send(\"FE:;end\")\
3632\009else\
3633\009\009print(\"Client rejected file!\")\
3634\009end\
3635end",
3636 },
3637 {
3638 path = "/nsh/put/",
3639 content = "if not nsh then print(\"No nsh session!\") return end\
3640\
3641local args = {...}\
3642\
3643if #args < 2 then\
3644\009print(\"Usage: put <local> <remote>\")\
3645\009print(\"<local>: any file on the client\")\
3646\009print(\"<remote>: any file on the server\")\
3647\009return\
3648end\
3649\
3650local fileData = \"\"\
3651\
3652nsh.send(\"FQ:;t=\"..args[1])\
3653local message = nsh.receive()\
3654if message ~= \"fileNotFound\" then\
3655\009while true do\
3656\009\009message = nsh.receive()\
3657\009\009pType = string.sub(message, 1, 2)\
3658\009\009if pType == \"FD\" then\
3659\009\009\009fileData = fileData..string.match(message, \"^FD:;t=(.*)\")\
3660\009\009elseif pType == \"FE\" then\
3661\009\009\009break\
3662\009\009end\
3663\009end\
3664\009if #fileData > 0 then\
3665\009\009local handle = io.open(args[2], \"w\")\
3666\009\009if handle then\
3667\009\009\009handle:write(fileData)\
3668\009\009\009handle:close()\
3669\009\009end\
3670\009else\
3671\009\009print(\"Empty file not written!\")\
3672\009end\
3673end",
3674 },
3675 {
3676 path = "/threeDig/",
3677 content = "args = {...}\
3678args[1] = args[1] or 0\
3679\
3680for i = 1, args[1] do\
3681turtle.digUp()\
3682turtle.digDown()\
3683turtle.dig()\
3684turtle.forward()\
3685end",
3686 },
3687 {
3688 path = "/carrot/",
3689 content = "while true do\
3690 success, data = turtle.inspectDown()\
3691 \
3692 while data.state.age < 7 do\
3693 success, data = turtle.inspectDown()\
3694 sleep(0.2)\
3695 end\
3696 \
3697 turtle.digDown()\
3698 turtle.placeDown()\
3699end",
3700 },
3701 {
3702 path = "/turtleless/",
3703 content = "term.setBackgroundColor(colors.black)\
3704term.clear()\
3705term.setCursorPos(1, 1)\
3706\
3707term.write(\"ArcOS Turtle Server\")\
3708rednet.open(\"right\")\
3709\
3710local info = {loc = {x = 0, y = 0, z = 0}, inventory = {}, fuel = {}, blocks = {}, selectedSlot = 0}\
3711\
3712\
3713function sendInfoFunc()\
3714 while true do\
3715 info = {loc = {x = 0, y = 0, z = 0}, inventory = {}, fuel = {}, blocks = {}, selectedSlot = 0}\
3716\
3717 xPos, yPos, zPos = gps.locate(0.5)\
3718\
3719 if xPos then\
3720 info.loc.x = xPos\
3721 info.loc.y = yPos\
3722 info.loc.z = zPos\
3723 else\
3724 info.loc.x = \"?\"\
3725 info.loc.y = \"?\"\
3726 info.loc.z = \"?\"\
3727 end\
3728\
3729 for i = 1, 16 do\
3730 data = turtle.getItemDetail(i)\
3731\
3732 if data then\
3733 info.inventory[tostring(i)] = {}\
3734 info.inventory[tostring(i)][\"name\"] = data.name\
3735 info.inventory[tostring(i)][\"count\"] = data.count\
3736 end\
3737 end\
3738\
3739 info.fuel[\"count\"] = turtle.getFuelLevel()\
3740 info.fuel[\"max\"] = turtle.getFuelLimit()\
3741 info.fuel[\"percent\"] = (100 * info.fuel[\"count\"]) / info.fuel[\"max\"]\
3742\
3743 info.fuel[\"percent\"] = math.floor(info.fuel[\"percent\"])\
3744\
3745 if turtle.detect() then\
3746 success, data = turtle.inspect()\
3747 info.blocks[\"front\"] = data.name\
3748 else\
3749 info.blocks[\"front\"] = \"minecraft:air\"\
3750 end\
3751\
3752 if turtle.detectUp() then\
3753 success, data = turtle.inspectUp()\
3754 info.blocks[\"up\"] = data.name\
3755 else\
3756 info.blocks[\"up\"] = \"minecraft:air\"\
3757 end\
3758\
3759 if turtle.detectDown() then\
3760 success, data = turtle.inspectDown()\
3761 info.blocks[\"down\"] = data.name\
3762 else\
3763 info.blocks[\"down\"] = \"minecraft:air\"\
3764 end\
3765\
3766 info.selectedSlot = turtle.getSelectedSlot()\
3767\
3768 sendInfo = textutils.serialise(info)\
3769 rednet.send(2735, sendInfo)\
3770 sleep(0.1)\
3771 end\
3772end\
3773\
3774function redCommand()\
3775 while true do\
3776 event, id, msg = os.pullEvent(\"rednet_message\")\
3777\
3778 if id == 2735 then\
3779 if msg == \"forward\" then\
3780 turtle.forward()\
3781 elseif msg == \"backward\" then\
3782 turtle.back()\
3783 elseif msg == \"up\" then\
3784 turtle.up()\
3785 elseif msg == \"down\" then\
3786 turtle.down()\
3787 elseif msg == \"left\" then\
3788 turtle.turnLeft()\
3789 elseif msg == \"right\" then\
3790 turtle.turnRight()\
3791 elseif msg == \"dig\" then\
3792 turtle.dig()\
3793 elseif msg == \"digDown\" then\
3794 turtle.digDown()\
3795 elseif msg == \"digUp\" then\
3796 turtle.digUp()\
3797 elseif msg == \"place\" then\
3798 turtle.place()\
3799 elseif msg == \"placeUp\" then\
3800 turtle.placeUp()\
3801 elseif msg == \"placeDown\" then\
3802 turtle.placeDown()\
3803 elseif msg == \"attack\" then\
3804 turtle.attack()\
3805 elseif msg == \"attackUp\" then\
3806 turtle.attackUp()\
3807 elseif msg == \"attackDown\" then\
3808 turtle.attackDown()\
3809 elseif msg == \"dropDown\" then\
3810 turtle.dropDown()\
3811 elseif string.find(msg, \"select\") then\
3812 minStr, maxStr = string.find(msg, \"select\")\
3813 nSlt = tonumber(string.sub(msg, maxStr + 1, #msg))\
3814 turtle.select(nSlt)\
3815 elseif string.find(msg, \"open:\") then\
3816 minStr, maxStr = string.find(msg, \"open:\")\
3817 sPrg = string.sub(msg, maxStr + 1, #msg)\
3818 shell.openTab(sPrg)\
3819 elseif msg == \"redstone\" then\
3820 for i = 1, #rs.getSides() do\
3821 rs.setOutput(rs.getSides()[i], true)\
3822 end\
3823 end\
3824 end\
3825 end\
3826end\
3827\
3828parallel.waitForAny(sendInfoFunc, redCommand)",
3829 },
3830 {
3831 path = "/wall/",
3832 content = "local tArgs = {...}\
3833local height = tonumber(tArgs[1]) \
3834local length = tonumber(tArgs[2])\
3835local up = true\
3836local slot = 1\
3837\
3838turtle.select(slot)\
3839\
3840for j = 1, length, 1 do\
3841 for i = 1,height,1 do\
3842 \
3843 if turtle.getItemCount(slot) == 0 then\
3844 slot = slot + 1\
3845 turtle.select(slot)\
3846 turtle.place()\
3847 else\
3848 turtle.place()\
3849 end\
3850 \
3851 if i < height then\
3852 if up == true then\
3853 turtle.up()\
3854 else\
3855 turtle.down()\
3856 end\
3857 \
3858 else\
3859 \
3860 if j < length then\
3861 turtle.turnRight()\
3862 turtle.forward()\
3863 turtle.turnLeft()\
3864 if up == false then\
3865 up = true\
3866 else\
3867 up = false\
3868 end\
3869 else \
3870 if up == true then\
3871 for i = 1, height - 1, 1 do\
3872 turtle.down()\
3873 end\
3874 end\
3875 end\
3876 \
3877 end\
3878\
3879 end\
3880end",
3881 },
3882 {
3883 path = "/sponge/",
3884 content = "rednet.open(\"right\")\
3885\
3886os.pullEvent(\"rednet_message\")\
3887\
3888turtle.turnLeft()\
3889turtle.turnLeft()\
3890\
3891while true do\
3892while not turtle.detect() do\
3893turtle.placeUp()\
3894turtle.forward()\
3895turtle.forward()\
3896end\
3897turtle.down()\
3898turtle.turnLeft()\
3899turtle.turnLeft()\
3900while not turtle.detect() do\
3901turtle.placeUp()\
3902turtle.forward()\
3903turtle.forward()\
3904end\
3905turtle.down()\
3906turtle.turnLeft()\
3907turtle.turnLeft()\
3908end",
3909 },
3910 {
3911 path = "/wLaunch/",
3912 content = "turtle.forward()\
3913turtle.turnLeft()\
3914turtle.forward()\
3915turtle.forward()\
3916turtle.select(9)\
3917shell.run(\"corner\")\
3918turtle.turnRight()\
3919turtle.forward()\
3920turtle.forward()\
3921turtle.forward()\
3922turtle.forward()\
3923turtle.select(10)\
3924shell.run(\"corner\")\
3925turtle.turnRight()\
3926turtle.forward()\
3927turtle.forward()\
3928turtle.forward()\
3929turtle.forward()\
3930turtle.select(11)\
3931shell.run(\"corner\")\
3932turtle.turnRight()\
3933turtle.forward()\
3934turtle.forward()\
3935turtle.forward()\
3936turtle.forward()\
3937turtle.select(12)\
3938shell.run(\"corner\")\
3939turtle.turnRight()\
3940turtle.forward()\
3941turtle.forward()\
3942turtle.turnLeft()\
3943turtle.forward()\
3944turtle.turnLeft()\
3945turtle.turnLeft()\
3946turtle.select(1)\
3947shell.run(\"water\")",
3948 },
3949 {
3950 path = "/backupUI/",
3951 content = "local monX, monY = term.getSize()\
3952\
3953local function drawUI(sStepNumber, sText)\
3954 term.clear()\
3955 term.setBackgroundColor(colors.black)\
3956 \
3957 paintutils.drawLine(1, 1, monX, 1, colors.white)\
3958 \
3959 term.setTextColor(colors.black)\
3960 term.setCursorPos(1, 1)\
3961 term.write(\"arc13's Backup Utility\")\
3962 \
3963 term.setBackgroundColor(colors.black)\
3964 \
3965 term.setTextColor(colors.white)\
3966 term.setCursorPos(1, 3)\
3967 term.write(\"Step \"..sStepNumber)\
3968 \
3969 term.setCursorPos(1, 4)\
3970 \
3971 for i = 1, monX do\
3972 write(string.char(131))\
3973 end\
3974 \
3975 term.setCursorPos(1, 5)\
3976 print(sText)\
3977end\
3978\
3979drawUI(\"1\", \"Welcome to the arc13's Backup Utility.\\n\\nThis wizard will guide you through this utility.\\n\\nIt is recommended that you eject all disks that may be connected to this computer.\\n\\nPress any key to continue.\")\
3980os.pullEvent(\"key\")\
3981\
3982drawUI(\"2\", \"The wizard will now run the backup utility.\\n\\nPress any key to continue.\\n\\n\")\
3983os.pullEvent(\"key\")\
3984\
3985shell.run(\"pastebin run 20CdUw4b\")\
3986\
3987drawUI(\"3\", \"The backup is done.\\n\\nYou should have a file called \\\"files.bkp\\\" in the \\\"/\\\" directory, please do a \\\"pastebin put files.bkp\\\" after this program finish.\\n\\nPress any key to continue.\")\
3988os.pullEvent(\"key\")\
3989\
3990drawUI(\"4\", \"The backup utility wizard is now finished.\\n\\nThanks for using me!\\n\\nPress any key to finish.\")\
3991os.pullEvent(\"key\")\
3992\
3993term.clear()\
3994term.setCursorPos(1, 1)\
3995print(\"Don't forget to upload to pastebin the \\\"files.bkp\\\" file by using \\\"pastebin put files.bkp\\\".\\n\")",
3996 },
3997 {
3998 path = "/ud/",
3999 content = "local args = {...}\
4000\
4001if not args[1] then\
4002 exit()\
4003end\
4004\
4005h = http.get(\"http://82.235.168.183/cc/\"..args[1]..\".lua\")\
4006p = h.readAll()\
4007\
4008fs.delete(args[1])\
4009f = fs.open(args[1], \"w\")\
4010f.write(p)\
4011\
4012h.close()\
4013f.close()\
4014\
4015si = fs.getSize(args[1])\
4016print(si..\" bytes downloaded\")",
4017 },
4018 {
4019 path = "/destroyPrismarine/",
4020 content = "for i = 1, 14 do\
4021for i = 1, 49 do\
4022turtle.digDown()\
4023turtle.forward()\
4024end\
4025turtle.turnLeft()\
4026turtle.forward()\
4027turtle.turnLeft()\
4028for i = 1, 49 do\
4029turtle.digDown()\
4030turtle.forward()\
4031end\
4032turtle.turnRight()\
4033turtle.forward()\
4034turtle.turnRight()\
4035end",
4036 },
4037 {
4038 path = "/slab/",
4039 content = "for i = 1, 31 do\
4040turtle.digDown()\
4041turtle.forward()\
4042end\
4043turtle.digDown()\
4044turtle.turnRight()\
4045turtle.forward()\
4046turtle.turnRight()\
4047turtle.digDown()\
4048for i = 1, 30 do\
4049turtle.digDown()\
4050turtle.forward()\
4051end",
4052 },
4053 {
4054 path = "/cotran/",
4055 content = "function tran(iCount)\
4056 turtle.transferTo(iCount, 16)\
4057end\
4058\
4059a = coroutine.create(tran)\
4060b = coroutine.create(tran)\
4061c = coroutine.create(tran)\
4062d = coroutine.create(tran)\
4063\
4064coroutine.resume(a, 1)\
4065coroutine.resume(b, 2)\
4066coroutine.resume(c, 5)\
4067coroutine.resume(d, 6)",
4068 },
4069 {
4070 path = "/market/",
4071 content = "--Market by: TurtleScripts.com\
4072--This is a modified version of the PasteBin script to work directly with TurtleScript project files.\
4073local tArgs = { ... }\
4074\
4075local function printUsage()\
4076 term.clear()\
4077 term.setCursorPos(1,1)\
4078 print( \"TurtleMarket v1.0 BETA [#gjdgyl]\" )\
4079\009print( \"-------------------------------------------------\" )\
4080\009print( \"by: TurtleScripts.com (update file_key: #gjdgz7)\" )\
4081\009print( \" \" )\
4082\009print( \"Usages:\" )\
4083\009print( \" ==UPLOAD==\" )\
4084\009print( \" market put (file_key) (filename) (write_pin)\" )\
4085\009print( \" [pin req'd]\" )\
4086\009print( \" ==DOWNLOAD==\" )\
4087\009print( \" market get (file_key) (filename) (read_pin) [y]\" )\
4088\009print( \" [pin req'd for private/drafts]\" )\
4089\009print( \" \" )\
4090end\
4091\
4092local function putFile(sCode, sFile, sPin, sOverride)\
4093 local sPath = shell.resolve( sFile )\
4094\009if not fs.exists( sPath ) or fs.isDir( sPath ) then\
4095 print( \"No such file\" )\
4096 return\
4097\009end\
4098\009local sName = fs.getName( sPath )\
4099\009local file = fs.open( sPath, \"r\" )\
4100\009local sText = file.readAll()\
4101\009file.close()\
4102\009write( \"Connecting to TurtleScripts.com... \" )\
4103\009local response = http.post(\"http://api.turtlescripts.com/putFileRaw/\"..textutils.urlEncode( sCode ),\"pin=\"..sPin..\"&\"..\"data=\"..textutils.urlEncode(sText))\
4104\009if response then\
4105\009\009print( \"Success.\" )\
4106\009\009local sResponse = response.readAll()\
4107\009\009response.close()\
4108\009\009print( \" \" )\
4109\009\009print( \"Local: \"..sFile )\
4110\009\009print( \"Remote: #\"..sCode )\
4111\009\009print( \"[==========================================] 100%\" )\
4112\009\009print(string.len(sText)..\" bytes\")\
4113\009\009print( \" \" )\
4114\009\009print( \"Upload Complete.\" )\
4115\009else\
4116\009\009print( \"Failed.\" )\
4117\009\009print( \" \" )\
4118\009\009print( \"ERROR: The file key is bad or project pin is wrong.\" )\
4119\009end\
4120end\
4121local function getFile(sCode, sFile, sPin, sOverride)\
4122 local sPath = shell.resolve( sFile )\
4123 if sCode == \"\" then\
4124\009\009print( \"You must specify a File Key from TurtleScripts.com!\" )\
4125\009\009return\
4126\009end\
4127\009if sFile == \"\" then\
4128\009\009print( \"You must specify a Filename to write to!\" )\
4129\009\009return\
4130\009end\
4131\009if fs.exists( sPath ) then\
4132\009\009print( \"File already exists\" )\
4133 if sOverride == \"\" and (sPin ~= \"y\" or sOverride ~= \"\") then\
4134\009\009 return\
4135 end\
4136\009end\
4137\009write( \"Connecting to TurtleScripts.com... \" )\
4138\009local response = http.post(\"http://api.turtlescripts.com/getFileRaw/\"..textutils.urlEncode( sCode ),\"pin=\"..sPin)\
4139\009if response then\
4140\009\009print( \"Success.\" )\
4141\009\009local sResponse = response.readAll()\
4142\009\009response.close()\
4143\009\009local file = fs.open( sPath, \"w\" )\
4144\009\009file.write( sResponse )\
4145\009\009file.close()\
4146\009\009print( \" \" )\
4147\009\009print( \"Remote: #\"..sCode )\
4148\009\009print( \"Local: \"..sFile )\
4149\009\009print( \"[==========================================] 100%\" )\
4150\009\009print(string.len(sResponse)..\" bytes\")\
4151\009\009print( \" \" )\
4152\009\009print( \"Downloaded Complete.\" )\
4153\009else\
4154\009\009print( \"Failed.\" )\
4155\009\009print( \" \" )\
4156\009\009print( \"ERROR: The file key is bad or project is private (in which case, did you specify your project pin??).\" )\
4157\009end\
4158end\
4159\
4160 local gui_mode = false\
4161 if #tArgs < 3 then\
4162\009\009printUsage()\
4163\009\009return\
4164\009end\
4165 local sCommand = tArgs[1]\
4166 local sCode = tArgs[2] or \"\"\
4167\009local sFile = tArgs[3] or \"\"\
4168 local sPin = tArgs[4] or \"\"\
4169 if sCommand == \"put\" then\
4170 \009putFile(sCode, sFile, sPin)\
4171 elseif sCommand == \"get\" then\
4172 local sOverride = tArgs[5] or \"\"\009\
4173 getFile(sCode, sFile, sPin, sOverride)\
4174 else\
4175 \009printUsage()\
4176 \009return\
4177 end",
4178 },
4179 {
4180 path = "/portalIgnite/",
4181 content = "turtle.select(16)\
4182\
4183turtle.turnRight()\
4184turtle.forward()\
4185turtle.turnLeft()\
4186turtle.up()\
4187\
4188turtle.place()\
4189\
4190for i = 1, 22 do\
4191 turtle.up()\
4192end\
4193\
4194turtle.place()\
4195\
4196for i = 1, 22 do\
4197 turtle.up()\
4198end\
4199\
4200turtle.place()\
4201\
4202for i = 1, 45 do\
4203 turtle.down()\
4204end\
4205\
4206turtle.turnLeft()\
4207turtle.forward()\
4208turtle.turnRight()\
4209\
4210turtle.select(1)",
4211 },
4212 {
4213 path = "/startup/",
4214 content = "shell.openTab(\"turtleless\")\
4215--shell.openTab(\"carrot\")\
4216os.loadAPI(\"/nsh/framebuffer\")",
4217 },
4218 {
4219 path = "/destroyPortal/",
4220 content = "turtle.select(1)\
4221\
4222while true do\
4223 turtle.place()\
4224 turtle.place()\
4225 turtle.forward()\
4226 turtle.forward()\
4227end",
4228 },
4229 {
4230 path = "/cube/",
4231 content = "function digIt()\
4232\009turtle.dig()\
4233\009local g = 0\
4234\009for g=0,dy do\
4235\009\009sleep(1.4)\
4236\009\009if turtle.detect() then\
4237\009\009\009turtle.dig()\
4238\009\009else\
4239\009\009\009break\
4240\009\009end\
4241\009end\
4242end\
4243\
4244\
4245term.clear()\
4246term.setCursorPos(8,6)\
4247print(\"Loading Cubic Miner...\")\
4248sleep(3)\
4249term.clear()\
4250term.setCursorPos(8,6)\
4251textutils.slowPrint(\".: Written by Evan :.\")\
4252term.setCursorPos(5,7)\
4253textutils.slowPrint(\".: Modified by BlackRa1n :.\")\
4254sleep(4)\
4255term.clear()\
4256term.setCursorPos(1,1)\
4257print(\"BlackRa1n Inc. CubicMiner V1\")\
4258print(\"---------------------------------\")\
4259sleep(2)\
4260print(\"\")\
4261textutils.slowPrint(\"Please enter full numbers only!\")\
4262sleep(2)\
4263textutils.slowPrint(\"Zero counts as a full number!\")\
4264sleep(2)\
4265textutils.slowPrint(\"You can also use negative numbers!\")\
4266sleep(2)\
4267term.clear()\
4268term.setCursorPos(1,1)\
4269print(\"BlackRa1n Inc. CubicMiner V1\")\
4270print(\"---------------------------------\")\
4271sleep(2)\
4272print(\"Desired Blocks Dug Forwards: \")\
4273input = read()\
4274dz = tonumber(input)\
4275if dz==0 then\
4276 dz0 = true\
4277 turned = false\
4278else\
4279 dz0 = false\
4280 turned = false\
4281end\
4282if dz<0 then\
4283 downZ = true\
4284else\
4285 downZ = false\
4286end\
4287if dz<0 then\
4288 dz = dz*-1\
4289end\
4290sleep(2)\
4291textutils.slowPrint(\"Registered!\")\
4292sleep(2)\
4293term.clear()\
4294term.setCursorPos(1,1)\
4295print(\"BlackRa1n Inc. CubicMiner V1\")\
4296print(\"---------------------------------\")\
4297sleep(2)\
4298print(\"\")\
4299print(\"Desired Blocks Dug Right: \")\
4300input = read()\
4301dx = tonumber(input)\
4302if dx<0 then\
4303 downX = false\
4304elseif dx>0 then\
4305 downX = true\
4306end\
4307if dx<0 then\
4308 dx = dx*-1\
4309end\
4310if dz0 == true then\
4311 dx = dx\
4312else\
4313 dx = dx + 1\
4314end\
4315sleep(2)\
4316textutils.slowPrint(\"Registered!\")\
4317sleep(2)\
4318term.clear()\
4319term.setCursorPos(1,1)\
4320print(\"BlackRa1n Inc. CubicMiner V1\")\
4321print(\"---------------------------------\")\
4322sleep(2)\
4323print(\"\")\
4324print(\"Desired Blocks Dug Down/Up: \")\
4325input = read()\
4326dy = tonumber(input)\
4327if dy<0 then\
4328 downY = true\
4329 dy = dy\
4330else\
4331 downY = false\
4332 dy = dy\
4333end\
4334if dy<0 then\
4335 dy = dy*-1\
4336end\
4337dy = dy + 1\
4338print(\"Starting...\")\
4339\
4340function digVert(dir)\
4341\009if dir==true then\
4342\009\009turtle.digUp()\
4343\009\009local g = 0\
4344\009\009for g=0,dy do \
4345\009\009sleep(1)\
4346\009\009if turtle.detectUp() then\
4347\009\009\009turtle.digUp()\
4348\009\009else\
4349\009\009\009break\
4350\009\009end\
4351\009\009end\
4352\009else\
4353\009\009turtle.digDown()\
4354\009\009local g = 0\
4355\009\009for g=0,dy do \
4356\009\009sleep(1)\
4357\009\009if turtle.detectDown() then\
4358\009\009\009turtle.digDown()\
4359\009\009else\
4360\009\009\009break\
4361\009\009end\
4362\009\009end\
4363\009end\
4364end\
4365\
4366if downZ == true then\
4367\009turtle.turnRight()\
4368\009turtle.turnRight()\
4369\009if downX == true then\
4370\009\009downX = false\
4371\009else\
4372\009\009downX = true\
4373\009end\
4374end\
4375\
4376for y=1,dy do\
4377\009for x=1,dx do\
4378\009\009if dz0 == true then\
4379\009\009\009\
4380\009\009\009if downX == false then\
4381\009\009\009\009if turned == false then\
4382\009\009\009\009\009turtle.turnLeft()\
4383\009\009\009\009\009turned = true\
4384\009\009\009\009end\
4385\009\009\009\009digIt()\
4386\009\009\009\009turtle.forward()\
4387\009\009\009else\
4388\009\009\009\009if turned == false then\
4389\009\009\009\009\009turtle.turnRight()\
4390\009\009\009\009\009turned = true\
4391\009\009\009\009end\
4392\009\009\009\009digIt()\
4393\009\009\009\009turtle.forward()\
4394\009\009\009end\
4395\009\009else\
4396\009\009\009\
4397\009\009\009\
4398\009\009if (x % 2) == 0 then\
4399\009\009\009\009odd = false\
4400\009\009\009else\
4401\009\009\009\009odd = true\
4402\009\009\009end\
4403\009\009if (y % 2) == 0 then\
4404\009\009\009if odd == true then\
4405\009\009\009\009odd = false\
4406\009\009\009else\
4407\009\009\009\009odd = true\
4408\009\009\009end\009\009\009\
4409\009\009end\
4410\009\009\009for z=1,dz do\
4411\009\009\009\009digIt()\
4412\009\009\009\009turtle.forward()\
4413\009\009\009end\
4414\009\009\009if odd == false then\
4415\009\009\009\009if downX == true then\
4416\009\009\009\009\009\009turtle.turnLeft()\
4417\009\009\009\009\009else \
4418\009\009\009\009\009\009turtle.turnRight()\
4419\009\009\009\009end\
4420\009\009\009\009if x == dx then\
4421\009\009\009\009else\
4422\009\009\009\009\009digIt()\
4423\009\009\009\009\009turtle.forward()\
4424\009\009\009\009end\
4425\009\009\009\009if downX == true then\
4426\009\009\009\009\009turtle.turnLeft()\
4427\009\009\009\009else\
4428\009\009\009\009\009turtle.turnRight()\
4429\009\009\009\009end\
4430\009\009\009\009\
4431\009\009\009elseif odd == true then\
4432\009\009\009\009if downX == true then\
4433\009\009\009\009\009\009turtle.turnRight()\
4434\009\009\009\009\009else turtle.turnLeft()\
4435\009\009\009\009end\
4436\009\009\009\009if x == dx then\
4437\009\009\009\009else\
4438\009\009\009\009\009digIt()\
4439\009\009\009\009turtle.forward()\
4440\009\009\009\009end\
4441\009\009\009\009if downX == true then\
4442\009\009\009\009\009\009turtle.turnRight()\
4443\009\009\009\009\009else turtle.turnLeft()\
4444\009\009\009\009end\
4445\009\009\009end\
4446\009\009end\
4447\009end\009\
4448\009if y==dy then\
4449\009else\
4450\009\009if downY == true then\
4451\009\009\009digVert(false)\
4452\009\009\009turtle.down()\
4453\009\009else\
4454\009\009\009digVert(true)\
4455\009\009\009turtle.up()\
4456\009\009end\
4457\009end\
4458end",
4459 },
4460 {
4461 path = "/placeSand/",
4462 content = "turtle.select(1)\
4463\
4464while true do\
4465while turtle.getItemCount() == 0 do\
4466turtle.select(turtle.getSelectedSlot() + 1)\
4467end\
4468\
4469while not turtle.detectDown() do\
4470turtle.placeDown()\
4471if turtle.getItemCount() == 0 then\
4472turtle.select(turtle.getSelectedSlot() + 1)\
4473end\
4474end\
4475turtle.forward()\
4476end",
4477 },
4478 {
4479 path = "/q/",
4480 content = "shell.run(\"quarry -dim 4 4 7 -invert true -rednet false\")",
4481 },
4482 {
4483 path = "/barre/",
4484 content = "for i = 1, 30 do\
4485turtle.dig()\
4486turtle.place()\
4487turtle.down()\
4488end\
4489\
4490for i = 1, 30 do\
4491turtle.up()\
4492end",
4493 },
4494 {
4495 path = "/minage/",
4496 content = "local tArgs = { ... }\
4497\
4498if #tArgs ~= 2 then\
4499 print(\"Usage : minage1 <length> <lines>\")\
4500 return\
4501end\
4502\
4503local length = tonumber( tArgs[1] )\
4504local lines = tonumber( tArgs[2])\
4505local torche = 0\
4506local avance = 0\
4507local nblines = 0\
4508local flagturn = 0\
4509\
4510local function turnLOR()\
4511 write(\"Function turnLOR \"..flagturn)\
4512 if flagturn == 0 then\
4513 turtle.turnRight()\
4514 else\
4515 turtle.turnLeft()\
4516 end\
4517\
4518end\
4519\
4520local function setFlagturn()\
4521 write(\"Function setFlagturn debut \"..flagturn)\
4522 if flagturn == 0 then\
4523 flagturn = 1\
4524 else\
4525 flagturn = 0\
4526 end\
4527 write(\"Function setFlagturn fin \"..flagturn)\
4528end\
4529\
4530local function poseTorche()\
4531\
4532 if torche == 8 then\
4533 turtle.select(16)\
4534 turtle.placeDown()\
4535 torche = 0\
4536 turtle.select(1)\
4537 end\
4538\
4539end\
4540\
4541local function turtleAvance()\
4542\
4543 while not turtle.forward() do\
4544 turtle.dig()\
4545 end\
4546\
4547end\
4548\
4549--main\
4550\
4551while nblines < lines do\
4552 avance = 0\
4553 while avance < length do\
4554\
4555 if turtle.getFuelLevel() > 0 then\
4556 turtle.dig()\
4557 --turtle.digUp()\
4558 turtle.digDown()\
4559 torche = torche + 1\
4560 avance = avance + 1\
4561 poseTorche()\
4562 turtleAvance()\
4563 else\
4564 print(\"Remettre fuel dans slot 15\")\
4565 print(\"Puis appuyez sur Entrée\")\
4566 z = read()\
4567 turtle.select(15)\
4568 turtle.refuel()\
4569 turtle.select(1)\
4570 end \
4571\
4572 end\
4573\
4574 nblines = nblines + 1\
4575\
4576 if nblines < lines then\
4577 turnLOR()\
4578 turtle.dig()\
4579 --turtle.digUp()\
4580 turtle.digDown()\
4581 turtleAvance()\
4582 turtle.dig()\
4583 --turtle.digUp()\
4584 turtle.digDown()\
4585 turtleAvance()\
4586 turtle.dig()\
4587 --turtle.digUp()\
4588 turtle.digDown()\
4589 turtleAvance()\
4590 turnLOR()\
4591 turtle.dig()\
4592 --turtle.digUp()\
4593 turtle.digDown()\
4594 turtleAvance()\
4595 setFlagturn()\
4596 end\
4597\
4598end",
4599 },
4600 {
4601 path = "/portalMaker/",
4602 content = "turtle.back()\
4603turtle.back()\
4604\
4605shell.run(\"portalPillar\")\
4606\
4607turtle.select(3)\
4608turtle.transferTo(1)\
4609turtle.select(4)\
4610turtle.transferTo(2)\
4611turtle.select(1)\
4612\
4613turtle.turnRight()\
4614\
4615for i = 1, 22 do\
4616 turtle.forward()\
4617end\
4618\
4619turtle.turnLeft()\
4620\
4621shell.run(\"portalPillar\")\
4622\
4623turtle.select(5)\
4624turtle.transferTo(1)\
4625turtle.select(6)\
4626turtle.transferTo(2)\
4627turtle.select(1)\
4628\
4629turtle.turnRight()\
4630\
4631for i = 1, 22 do\
4632 turtle.forward()\
4633end\
4634\
4635turtle.turnLeft()\
4636\
4637shell.run(\"portalPillar\")\
4638\
4639turtle.select(7)\
4640turtle.transferTo(1)\
4641turtle.select(8)\
4642turtle.transferTo(2)\
4643turtle.select(1)\
4644\
4645turtle.turnRight()\
4646\
4647for i = 1, 22 do\
4648 turtle.forward()\
4649end\
4650\
4651turtle.turnLeft()\
4652\
4653shell.run(\"portalPillar\")\
4654\
4655turtle.turnRight()\
4656turtle.forward()\
4657turtle.turnLeft()\
4658turtle.forward()\
4659turtle.turnLeft()\
4660\
4661turtle.select(2)\
4662turtle.transferTo(1)\
4663turtle.select(4)\
4664turtle.transferTo(2)\
4665\
4666shell.run(\"portalFloor\")\
4667\
4668turtle.turnRight()\
4669turtle.forward()\
4670turtle.turnLeft()\
4671\
4672for i = 1, 68 do\
4673 turtle.forward()\
4674end\
4675\
4676turtle.turnLeft()\
4677turtle.forward()\
4678turtle.turnLeft()\
4679\
4680turtle.select(2)\
4681turtle.transferTo(1)\
4682turtle.select(6)\
4683turtle.transferTo(2)\
4684turtle.select(1)\
4685\
4686shell.run(\"portalFloor2\")\
4687\
4688turtle.up()\
4689\
4690turtle.turnRight()\
4691turtle.forward()\
4692turtle.turnLeft()\
4693\
4694for i = 1, 68 do\
4695 turtle.forward()\
4696end\
4697\
4698turtle.turnLeft()\
4699turtle.forward()\
4700turtle.turnLeft()\
4701\
4702turtle.select(2)\
4703turtle.transferTo(1)\
4704turtle.select(8)\
4705turtle.transferTo(2)\
4706turtle.select(1)\
4707\
4708shell.run(\"portalFloor3\")\
4709\
4710os.shutdown()\
4711\
4712turtle.select(16)\
4713\
4714turtle.turnRight()\
4715turtle.forward()\
4716turtle.turnLeft()\
4717turtle.forward()\
4718turtle.turnLeft()\
4719\
4720shell.run(\"portalIgnite\")\
4721\
4722turtle.turnRight()\
4723\
4724for i = 1, 22 do\
4725 turtle.forward()\
4726end\
4727\
4728turtle.turnLeft()\
4729\
4730shell.run(\"portalIgnite\")\
4731\
4732turtle.turnRight()\
4733\
4734for i = 1, 22 do\
4735 turtle.forward()\
4736end\
4737\
4738turtle.turnLeft()\
4739\
4740shell.run(\"portalIgnite\")\
4741\
4742turtle.turnLeft()\
4743\
4744for i = 1, 45 do\
4745 turtle.forward()\
4746end",
4747 },
4748 {
4749 path = "/prismarine/",
4750 content = "for i = 1, 51 do\
4751turtle.forward()\
4752turtle.placeDown()\
4753end\
4754\
4755turtle.turnRight()\
4756turtle.forward()\
4757turtle.turnRight()\
4758turtle.select(2)\
4759\
4760for i = 1, 52 do\
4761turtle.forward()\
4762turtle.placeDown()\
4763end\
4764\
4765turtle.turnLeft()\
4766turtle.forward()\
4767turtle.turnLeft()\
4768turtle.select(3)\
4769\
4770for i = 1, 51 do\
4771turtle.forward()\
4772turtle.placeDown()\
4773end\
4774\
4775turtle.select(1)",
4776 },
4777 {
4778 path = "/pillar/",
4779 content = "s, d = turtle.inspectDown()\
4780\
4781j = 0\
4782\
4783while d.name == \"minecraft:sand\" do\
4784turtle.digDown()\
4785turtle.down()\
4786j = j + 1\
4787end\
4788\
4789for i = 1, j do\
4790turtle.up()\
4791end",
4792 },
4793 {
4794 path = "/portalFloor/",
4795 content = "turtle.select(1)\
4796\
4797for i = 1, 22 do\
4798 turtle.up()\
4799end\
4800\
4801turtle.dig()\
4802turtle.forward()\
4803\
4804for i = 1, 66 do\
4805 turtle.dig()\
4806 turtle.forward()\
4807end\
4808\
4809for i = 1, 66 do\
4810 turtle.back()\
4811end\
4812\
4813turtle.turnLeft()\
4814turtle.turnLeft()\
4815\
4816for i = 1, 66 do\
4817 while turtle.getItemCount() == 0 do\
4818 turtle.select(turtle.getSelectedSlot() + 1)\
4819 end\
4820 turtle.place()\
4821 turtle.back()\
4822end\
4823\
4824turtle.place()\
4825\
4826turtle.back()\
4827turtle.place()\
4828\
4829for i = 1, 22 do\
4830 turtle.down()\
4831end",
4832 },
4833 {
4834 path = "/sand/",
4835 content = "while true do\
4836while turtle.detect() do\
4837turtle.dig()\
4838end\
4839turtle.forward()\
4840end",
4841 },
4842 {
4843 path = "/portalPillar/",
4844 content = "turtle.select(1)\
4845\
4846for i = 1, 66 do\
4847 while turtle.getItemCount() == 0 do\
4848 turtle.select(turtle.getSelectedSlot() + 1)\
4849 end\
4850 turtle.place()\
4851 turtle.up()\
4852end\
4853\
4854for i = 1, 66 do\
4855 turtle.down()\
4856end",
4857 },
4858 {
4859 path = "/crypt/",
4860 content = "cipher = \"10011100\" -- must be eight digit binary number\
4861\
4862--Returns the XOR of two binary numbers\
4863function xor(a,b)\
4864 local r = 0\
4865 local f = math.floor\
4866 for i = 0, 31 do\
4867 local x = a / 2 + b / 2\
4868 if x ~= f(x) then\
4869 r = r + 2^i\
4870 end\
4871 a = f(a / 2)\
4872 b = f(b / 2)\
4873 end\
4874 return r\
4875end\
4876\
4877--Changes a decimal to a binary number\
4878function toBits(num)\
4879 local t={}\
4880 while num>0 do\
4881 rest=math.fmod(num,2)\
4882 t[#t+1]=rest\
4883 num=(num-rest)/2\
4884 end\
4885\009--[[ t gives the binary number in reverse. To fix this\
4886\009\009the bits table will give the correct value\
4887\009\009by reversing the values in t.\
4888\009\009The result will be left paddied with zeros to eight digits\
4889\009]]\
4890\009local bits = {}\
4891\009local lpad = 8 - #t\
4892\009if lpad > 0 then\
4893\009\009for c = 1,lpad do table.insert(bits,0) end\
4894\009end\
4895\009-- Reverse the values in t\
4896\009for i = #t,1,-1 do table.insert(bits,t[i]) end\
4897\
4898 return table.concat(bits)\
4899end\
4900\
4901--Changes eight digit binary to decimal\
4902function toDec(bits)\
4903\009local bmap = {128,64,32,16,8,4,2,1} --binary map\
4904\
4905\009local bitt = {}\
4906\009for c in bits:gmatch(\".\") do table.insert(bitt,c) end\
4907\
4908\009local result = 0\
4909\
4910\009for i = 1,#bitt do\
4911\009\009if bitt[i] == \"1\" then result = result + bmap[i] end\
4912\009end\
4913\
4914\009return result\
4915end\
4916\
4917--Encryption and Decryption Algorithm for XOR Block cipher\
4918function E(str)\
4919\009--split cipher string into a table\
4920\009local ciphert = {}\
4921\009for c in cipher:gmatch(\".\") do table.insert(ciphert,c) end\
4922\
4923\009--split string into a table containing only binary numbers of each character\
4924\009local block = {}\
4925\009for ch in str:gmatch(\".\") do\
4926\009\009local c = toBits(string.byte(ch))\
4927\009\009table.insert(block,c)\
4928\009end\
4929\
4930\009--for each binary number perform xor transformation\
4931\009for i = 1,#block do\
4932\009\009local bitt = {}\
4933\009\009local bit = block[i]\
4934\009\009for c in bit:gmatch(\".\") do table.insert(bitt,c) end\
4935\
4936\009\009local result = {}\
4937\009\009for i = 1,8,1 do\
4938\009\009\009table.insert(result,xor(ciphert[i],bitt[i]))\
4939\009\009end\
4940\
4941\009\009block[i] = string.char(toDec(table.concat(result)))\
4942\009end\
4943\
4944\009return table.concat(block)\
4945end",
4946 },
4947 {
4948 path = "/water/",
4949 content = "turtle.forward()\
4950turtle.forward()\
4951turtle.down()\
4952\
4953j = 0\
4954\
4955while not turtle.detectDown() do\
4956turtle.select(1)\
4957turtle.place()\
4958turtle.down()\
4959turtle.select(2)\
4960turtle.place()\
4961turtle.down()\
4962j = j + 2\
4963end\
4964\
4965for i = 1, j do\
4966turtle.dig()\
4967turtle.up()\
4968end\
4969\
4970turtle.dig()\
4971turtle.up()\
4972turtle.dig()\
4973turtle.back()\
4974turtle.back()\
4975\
4976turtle.select(1)",
4977 },
4978 {
4979 path = "/portalFloor3/",
4980 content = "turtle.select(1)\
4981\
4982for i = 1, 66 do\
4983 turtle.digUp()\
4984 turtle.up()\
4985end\
4986\
4987turtle.dig()\
4988turtle.forward()\
4989\
4990for i = 1, 66 do\
4991 turtle.dig()\
4992 turtle.forward()\
4993end\
4994\
4995for i = 1, 66 do\
4996 turtle.back()\
4997end\
4998\
4999turtle.turnLeft()\
5000turtle.turnLeft()\
5001\
5002for i = 1, 66 do\
5003 while turtle.getItemCount() == 0 do\
5004 turtle.select(turtle.getSelectedSlot() + 1)\
5005 end\
5006 turtle.place()\
5007 turtle.back()\
5008end\
5009\
5010turtle.place()\
5011turtle.back()\
5012\
5013for i = 1, 66 do\
5014 turtle.digDown()\
5015 turtle.down()\
5016end",
5017 },
5018 {
5019 path = "/replaceDown/",
5020 content = "args = {...}\
5021length = args[1] or 64\
5022\
5023for i = 1, length do\
5024if turtle.detect() then\
5025break\
5026end\
5027turtle.placeDown()\
5028turtle.forward()\
5029end",
5030 },
5031 {
5032 path = "/corner/",
5033 content = "while not turtle.detectDown() do\
5034turtle.placeDown()\
5035end",
5036 },
5037 {
5038 path = "/dirt/",
5039 content = "while true do\
5040turtle.placeDown()\
5041turtle.forward()\
5042if turtle.detect() then\
5043turtle.select(2)\
5044turtle.placeDown()\
5045turtle.turnRight()\
5046turtle.forward()\
5047turtle.turnRight()\
5048turtle.placeDown()\
5049while not turtle.detect() do\
5050turtle.placeDown()\
5051turtle.forward()\
5052end\
5053turtle.placeDown()\
5054break\
5055end\
5056end",
5057 },
5058 {
5059 path = "/break/",
5060 content = "for i = 1, 20 do\
5061 for i = 1, 23 do\
5062 turtle.dig()\
5063 turtle.up()\
5064 end\
5065 \
5066 for i = 1, 23 do\
5067 turtle.down()\
5068 end\
5069 \
5070 turtle.turnRight()\
5071 turtle.forward()\
5072 turtle.turnLeft()\
5073end",
5074 },
5075 {
5076 path = "/Quarry_Logs/Quarry_Log_8/",
5077 content = "Welcome to the Quarry Logs!\
5078Entry Number: 8\
5079Quarry Version: 3.6.4.5\
5080Dimensions (X Z Y): 4 4 7\
5081Blocks Mined: 112\
5082 Cobble: 112\
5083 Usable Fuel: 0\
5084 Other: 0\
5085Total Fuel Used: 62\
5086Expected Fuel Use: 316\
5087Days to complete mining run: 0\
5088Day Started: 115\
5089Number of times resumed: 0\
5090Was an ore quarry? No\
5091Was inverted? No\
5092Was using rednet? No\
5093Chest was on the front side",
5094 },
5095 {
5096 path = "/Quarry_Logs/Quarry_Log_7/",
5097 content = "Welcome to the Quarry Logs!\
5098Entry Number: 7\
5099Quarry Version: 3.6.4.5\
5100Dimensions (X Z Y): 4 4 7\
5101Blocks Mined: 96\
5102 Cobble: 90\
5103 Usable Fuel: 0\
5104 Other: 6\
5105Total Fuel Used: 62\
5106Expected Fuel Use: 316\
5107Days to complete mining run: 0\
5108Day Started: 115\
5109Number of times resumed: 0\
5110Was an ore quarry? No\
5111Was inverted? No\
5112Was using rednet? No\
5113Chest was on the front side",
5114 },
5115 {
5116 path = "/Quarry_Logs/Quarry_Log_12/",
5117 content = "Welcome to the Quarry Logs!\
5118Entry Number: 12\
5119Quarry Version: 3.6.4.5\
5120Dimensions (X Z Y): 4 4 7\
5121Blocks Mined: 97\
5122 Cobble: 97\
5123 Usable Fuel: 0\
5124 Other: 0\
5125Total Fuel Used: 62\
5126Expected Fuel Use: 316\
5127Days to complete mining run: 0\
5128Day Started: 116\
5129Number of times resumed: 0\
5130Was an ore quarry? No\
5131Was inverted? No\
5132Was using rednet? No\
5133Chest was on the front side",
5134 },
5135 {
5136 path = "/Quarry_Logs/Quarry_Log_1/",
5137 content = "Welcome to the Quarry Logs!\
5138Entry Number: 1\
5139Quarry Version: 3.6.4.5\
5140Dimensions (X Z Y): 4 4 7\
5141Blocks Mined: 112\
5142 Cobble: 16\
5143 Usable Fuel: 0\
5144 Other: 96\
5145Total Fuel Used: 62\
5146Expected Fuel Use: 316\
5147Days to complete mining run: 0\
5148Day Started: 114\
5149Number of times resumed: 0\
5150Was an ore quarry? No\
5151Was inverted? No\
5152Was using rednet? No\
5153Chest was on the front side",
5154 },
5155 {
5156 path = "/Quarry_Logs/Quarry_Log_9/",
5157 content = "Welcome to the Quarry Logs!\
5158Entry Number: 9\
5159Quarry Version: 3.6.4.5\
5160Dimensions (X Z Y): 4 4 7\
5161Blocks Mined: 111\
5162 Cobble: 111\
5163 Usable Fuel: 0\
5164 Other: 0\
5165Total Fuel Used: 62\
5166Expected Fuel Use: 316\
5167Days to complete mining run: 0\
5168Day Started: 115\
5169Number of times resumed: 0\
5170Was an ore quarry? No\
5171Was inverted? No\
5172Was using rednet? No\
5173Chest was on the front side",
5174 },
5175 {
5176 path = "/Quarry_Logs/Quarry_Log_10/",
5177 content = "Welcome to the Quarry Logs!\
5178Entry Number: 10\
5179Quarry Version: 3.6.4.5\
5180Dimensions (X Z Y): 4 4 7\
5181Blocks Mined: 112\
5182 Cobble: 112\
5183 Usable Fuel: 0\
5184 Other: 0\
5185Total Fuel Used: 62\
5186Expected Fuel Use: 316\
5187Days to complete mining run: 0\
5188Day Started: 115\
5189Number of times resumed: 0\
5190Was an ore quarry? No\
5191Was inverted? No\
5192Was using rednet? No\
5193Chest was on the front side",
5194 },
5195 {
5196 path = "/Quarry_Logs/Quarry_Log_3/",
5197 content = "Welcome to the Quarry Logs!\
5198Entry Number: 3\
5199Quarry Version: 3.6.4.5\
5200Dimensions (X Z Y): 4 4 7\
5201Blocks Mined: 112\
5202 Cobble: 16\
5203 Usable Fuel: 0\
5204 Other: 96\
5205Total Fuel Used: 62\
5206Expected Fuel Use: 316\
5207Days to complete mining run: 0\
5208Day Started: 114\
5209Number of times resumed: 0\
5210Was an ore quarry? No\
5211Was inverted? No\
5212Was using rednet? No\
5213Chest was on the front side",
5214 },
5215 {
5216 path = "/Quarry_Logs/Quarry_Log_6/",
5217 content = "Welcome to the Quarry Logs!\
5218Entry Number: 6\
5219Quarry Version: 3.6.4.5\
5220Dimensions (X Z Y): 4 4 7\
5221Blocks Mined: 112\
5222 Cobble: 15\
5223 Usable Fuel: 0\
5224 Other: 97\
5225Total Fuel Used: 62\
5226Expected Fuel Use: 316\
5227Days to complete mining run: 0\
5228Day Started: 115\
5229Number of times resumed: 0\
5230Was an ore quarry? No\
5231Was inverted? No\
5232Was using rednet? No\
5233Chest was on the front side",
5234 },
5235 {
5236 path = "/Quarry_Logs/Quarry_Log_5/",
5237 content = "Welcome to the Quarry Logs!\
5238Entry Number: 5\
5239Quarry Version: 3.6.4.5\
5240Dimensions (X Z Y): 4 4 7\
5241Blocks Mined: 110\
5242 Cobble: 14\
5243 Usable Fuel: 0\
5244 Other: 96\
5245Total Fuel Used: 62\
5246Expected Fuel Use: 316\
5247Days to complete mining run: 0\
5248Day Started: 115\
5249Number of times resumed: 0\
5250Was an ore quarry? No\
5251Was inverted? No\
5252Was using rednet? No\
5253Chest was on the front side",
5254 },
5255 {
5256 path = "/Quarry_Logs/Quarry_Log_2/",
5257 content = "Welcome to the Quarry Logs!\
5258Entry Number: 2\
5259Quarry Version: 3.6.4.5\
5260Dimensions (X Z Y): 4 4 7\
5261Blocks Mined: 112\
5262 Cobble: 15\
5263 Usable Fuel: 0\
5264 Other: 97\
5265Total Fuel Used: 62\
5266Expected Fuel Use: 316\
5267Days to complete mining run: 0\
5268Day Started: 114\
5269Number of times resumed: 0\
5270Was an ore quarry? No\
5271Was inverted? No\
5272Was using rednet? No\
5273Chest was on the front side",
5274 },
5275 {
5276 path = "/Quarry_Logs/Quarry_Log_11/",
5277 content = "Welcome to the Quarry Logs!\
5278Entry Number: 11\
5279Quarry Version: 3.6.4.5\
5280Dimensions (X Z Y): 4 4 7\
5281Blocks Mined: 112\
5282 Cobble: 112\
5283 Usable Fuel: 0\
5284 Other: 0\
5285Total Fuel Used: 62\
5286Expected Fuel Use: 316\
5287Days to complete mining run: 0\
5288Day Started: 115\
5289Number of times resumed: 0\
5290Was an ore quarry? No\
5291Was inverted? No\
5292Was using rednet? No\
5293Chest was on the front side",
5294 },
5295 {
5296 path = "/Quarry_Logs/Quarry_Log_4/",
5297 content = "Welcome to the Quarry Logs!\
5298Entry Number: 4\
5299Quarry Version: 3.6.4.5\
5300Dimensions (X Z Y): 4 4 7\
5301Blocks Mined: 112\
5302 Cobble: 13\
5303 Usable Fuel: 0\
5304 Other: 99\
5305Total Fuel Used: 62\
5306Expected Fuel Use: 316\
5307Days to complete mining run: 0\
5308Day Started: 115\
5309Number of times resumed: 0\
5310Was an ore quarry? No\
5311Was inverted? No\
5312Was using rednet? No\
5313Chest was on the front side",
5314 },
5315}