SHOW:
|
|
- or go back to the newest paste.
1 | - | version = 20241122.1730 |
1 | + | version = 20231005.1900 |
2 | ||
3 | local tkVersion = version -- otherwise over-written by clsTurtle when loaded | |
4 | --[[ | |
5 | **********Toolkit v2********** | |
6 | https://pastebin.com/UFvjc1bw | |
7 | Last edited: see version YYYYMMDD.HHMM | |
8 | if NOT online: | |
9 | Make sure you create a folder 'lib' and place menu.lua and clsTurtle.lua into it | |
10 | else | |
11 | lib folder will be created and files obtained automatically! | |
12 | end | |
13 | ]] | |
14 | ||
15 | args = {...} -- eg "farm", "tree" | |
16 | ||
17 | local menu, T | |
18 | --[[ | |
19 | Computercraft started with mc version 1.7.10 and went to 1.8.9 | |
20 | - | ccTweaked started around mc 1.12.2 and currently at 1.21.1 |
20 | + | ccTweaked started around mc 1.12.2 and currently at 1.18 |
21 | - | mc 1.18 onwards has new blocks and bedrock at -64, so needs to be taken into account. |
21 | + | mc 1.18 has new blocks and bedrock at -64, so needs to be taken into account. |
22 | _HOST = The ComputerCraft and Minecraft version of the current computer environment. | |
23 | For example, ComputerCraft 1.93.0 (Minecraft 1.15.2). | |
24 | ]] | |
25 | local dbug = false -- debug is reserved word | |
26 | local bedrock = 0 | |
27 | local netherBedrock = 0 | |
28 | local ceiling = 255 | |
29 | local deletesWater = false | |
30 | local brick = "minecraft:nether_brick" -- pre 1.16+ name | |
31 | local ccMajorVersion = _HOST:sub(15, _HOST:find("Minecraft") - 2) --eg ComputerCraft 1.93.0 (Minecraft 1.15.2) | |
32 | local ccMinorVersion = 0 | |
33 | - | local barrelItems = nil -- list of items and the barrels where they are usually found |
33 | + | |
34 | - | local chestItems = nil -- list of items and the chests where they are usually found |
34 | + | |
35 | Chunk borders F3+G or: | |
36 | math.floor(x / 16) * 16 add 16 for each border. same for z | |
37 | ]] | |
38 | function string:split(sSeparator, nMax, bRegexp, noEmpty) | |
39 | --[[return a table split with sSeparator. noEmpty removes empty elements | |
40 | use: tblSplit = SplitTest:split('~',[nil], [nil], false) or tblSplit = string.split(SplitTest, '~')]] | |
41 | assert(sSeparator ~= '','separator must not be empty string') | |
42 | assert(nMax == nil or nMax >= 1, 'nMax must be >= 1 and not nil') | |
43 | if noEmpty == nil then noEmpty = true end | |
44 | ||
45 | local aRecord = {} | |
46 | local newRecord = {} | |
47 | -- self refers to the 'string' being split | |
48 | if self:len() > 0 then | |
49 | local bPlain = not bRegexp | |
50 | nMax = nMax or -1 | |
51 | ||
52 | local nField, nStart = 1, 1 | |
53 | local nFirst,nLast = self:find(sSeparator, nStart, bPlain) | |
54 | while nFirst and nMax ~= 0 do | |
55 | aRecord[nField] = self:sub(nStart, nFirst-1) | |
56 | nField = nField+1 | |
57 | nStart = nLast+1 | |
58 | nFirst,nLast = self:find(sSeparator, nStart, bPlain) | |
59 | nMax = nMax-1 | |
60 | end | |
61 | aRecord[nField] = self:sub(nStart) | |
62 | ||
63 | if noEmpty then --split on newline preserves empty values | |
64 | for i = 1, #aRecord do | |
65 | if aRecord[i] ~= "" then | |
66 | table.insert(newRecord, aRecord[i]) | |
67 | end | |
68 | end | |
69 | else | |
70 | newRecord = aRecord | |
71 | end | |
72 | end | |
73 | ||
74 | return newRecord | |
75 | end | |
76 | ||
77 | if tonumber(ccMajorVersion) == nil then -- 1.93.0 NAN | |
78 | --ccMajorVersion = ccMajorVersion:sub(1, ccMajorVersion:find(".", 3, true) - 1) | |
79 | local parts = ccMajorVersion:split(".") | |
80 | ccMajorVersion = parts[1] | |
81 | if parts[2] ~= nil then | |
82 | ccMajorVersion = ccMajorVersion.."."..parts[2] | |
83 | end | |
84 | ccMajorVersion = tonumber(ccMajorVersion) | |
85 | if parts[3] ~= nil then | |
86 | ccMinorVersion = tonumber(parts[3]) | |
87 | end | |
88 | end | |
89 | ||
90 | local mcMajorVersion = _HOST:sub(_HOST:find("Minecraft") + 10, _HOST:find("\)") - 1) -- eg 1.18 or 1.20 -> 1.18, 1.20 | |
91 | local mcMinorVersion = 0 | |
92 | if tonumber(mcMajorVersion) == nil then -- 1.18.3 NAN | |
93 | --mcMajorVersion = tonumber(_HOST:sub(_HOST:find("Minecraft") + 10, _HOST:find("\)") - 3)) -- eg 1.19.4 -> 1.19 | |
94 | local parts = mcMajorVersion:split(".") | |
95 | mcMajorVersion = parts[1] | |
96 | if parts[2] ~= nil then | |
97 | mcMajorVersion = mcMajorVersion.."."..parts[2] | |
98 | end | |
99 | mcMajorVersion = tonumber(mcMajorVersion) | |
100 | if parts[3] ~= nil then | |
101 | mcMinorVersion = tonumber(parts[3]) | |
102 | end | |
103 | end | |
104 | ||
105 | if mcMajorVersion < 1.7 and mcMajorVersion >= 1.18 then -- 1.12 to 1.?? | |
106 | bedrock = -64 | |
107 | ceiling = 319 | |
108 | end | |
109 | if mcMajorVersion < 1.7 and mcMajorVersion >= 1.16 then -- 1.12 to 1.?? | |
110 | brick = "minecraft:nether_bricks" | |
111 | end | |
112 | if mcMajorVersion < 1.7 and mcMajorVersion <= 1.12 then --- turtle in source deletes it. 1.7.10 to 1.12 | |
113 | deletesWater = true | |
114 | end | |
115 | ||
116 | local utils = {} | |
117 | ||
118 | function utils.tableConcat(tbl, sep) | |
119 | - | local network = {} |
119 | + | |
120 | for i,value in pairs(tbl) do | |
121 | - | function network.addToStorageList(storageType, itemKey, storageName, writeToFile) |
121 | + | |
122 | - | -- itemKey is a table, so is passed byRef. No need to return a value |
122 | + | |
123 | - | -- eg itemKey: [ "minecraft:dark_oak_sapling" ] = {"minecraft:barrel_94", "minecraft:barrel_96"} |
123 | + | |
124 | - | -- storageName = "minecraft:barrel_99" |
124 | + | |
125 | - | local itemTable = {} |
125 | + | |
126 | - | if storageType == "chest" then |
126 | + | |
127 | - | itemTable = chestItems[itemKey] -- eg [ "minecraft:dark_oak_sapling" ] = {"minecraft:barrel_94", "minecraft:barrel_96"} |
127 | + | |
128 | end | |
129 | - | itemTable = barrelItems[itemKey] |
129 | + | |
130 | function utils.calculateDimensions(R) | |
131 | - | if itemTable == nil then -- key does not match. This item not previously stored |
131 | + | |
132 | - | if storageType == "chest" then |
132 | + | |
133 | - | chestItems[itemKey] = {storageName} -- eg U.chestItems[minecraft:diorite] = {chest_105} |
133 | + | |
134 | print("Calculated Length = "..R.length) | |
135 | - | barrelItems[itemKey] = {storageName} |
135 | + | |
136 | R.width = utils.calculateDistance(R.width) -- now facing right | |
137 | print("Calculated width = "..R.width) | |
138 | - | for _, storage in ipairs(itemTable) do -- is "minecraft:barrel_99" already in the list? |
138 | + | |
139 | - | if storage == storageName then |
139 | + | |
140 | - | return -- exit function |
140 | + | |
141 | if R.height == 0 then -- use auto settings based on water detection | |
142 | R.height = 64 | |
143 | - | -- not found so add to table. return not required as funcion is ended |
143 | + | |
144 | - | table.insert(itemTable, storageName) -- add to table eg table[ "minecraft:dark_oak_sapling" ] = {"minecraft:barrel_94", "minecraft:barrel_96",, "minecraft:barrel_99"} |
144 | + | |
145 | end | |
146 | - | if writeToFile then |
146 | + | |
147 | - | network.updateList(storageType) |
147 | + | |
148 | --[[ | |
149 | measure length | |
150 | movement stops when either solid block in front or solid below | |
151 | - | function network.attachModem() |
151 | + | |
152 | - | -- modem cannot be "attached". Has to be player right-click! |
152 | + | |
153 | - | -- place on top or next to a modem and ask player to right-click |
153 | + | |
154 | local nonSolidBelow = utils.clearVegetation("down") | |
155 | - | menu.colourPrint("Please right-click on the modem(s) I am next to or above/below".. |
155 | + | |
156 | - | "\nThe centre square should be lit red.\n".. |
156 | + | |
157 | - | "If embedded use narrow gap at side\n", colors.red) |
157 | + | |
158 | - | local event, side = os.pullEvent("peripheral") |
158 | + | |
159 | - | for timer = 5, 0, -1 do |
159 | + | |
160 | - | -- text, fg, bg, width, isInput, cr |
160 | + | |
161 | - | menu.colourWrite("Thanks. continuing in ".. timer.." seconds", colors.lime, colors.black, 0, false, true) |
161 | + | |
162 | if turtle.forward() then -- able to move forward | |
163 | moves = moves + 1 | |
164 | else | |
165 | break | |
166 | - | function network.checkInventory(inventory, itemName, itemsPerSlot, matchPart) |
166 | + | |
167 | if not utils.clearVegetation("down") then -- solid below | |
168 | - | Find an item already in an inventory |
168 | + | |
169 | - | inventory = The wrapped inventory or it's name |
169 | + | |
170 | - | itemName = The name of the item to find. |
170 | + | |
171 | - | return no of items already present, and storage space for additional |
171 | + | |
172 | end | |
173 | - | itemsPerSlot = itemsPerSlot or 64 |
173 | + | |
174 | - | matchPart = matchPart or "" |
174 | + | |
175 | - | local contents = nil |
175 | + | |
176 | - | local numSlots = 0 |
176 | + | |
177 | - | if type(inventory) == "string" then |
177 | + | |
178 | - | contents = peripheral.call(inventory, "list") |
178 | + | local quantity = tonumber(quantity) |
179 | - | numSlots = peripheral.call(inventory, "size") |
179 | + | local fuelNeeded = quantity - tonumber(turtle.getFuelLevel()) -- eg 600 |
180 | - | --assert(contents ~= nil, "Nil contents from inventory "..tostring(inventory)) |
180 | + | |
181 | - | T:saveToLog("network.checkInventory('"..inventory.."', itemName = "..itemName..", itemsPerSlot = "..itemsPerSlot..", matchPart = "..tostring(matchPart)) |
181 | + | |
182 | if T:checkInventoryForItem({"coal"}, {math.ceil(fuelNeeded / 60)}, false) == nil then | |
183 | - | contents = inventory.list() |
183 | + | |
184 | - | numSlots = inventory.size() |
184 | + | |
185 | end | |
186 | - | local inStock = 0 |
186 | + | |
187 | - | local partMatch = false |
187 | + | |
188 | - | local canStore = 0 |
188 | + | |
189 | - | if contents ~= nil then |
189 | + | |
190 | - | T:saveToLog("#slots in use = "..#contents) |
190 | + | |
191 | - | canStore = (numSlots - #contents) * itemsPerSlot -- capacity of empty slots |
191 | + | |
192 | - | for slot, item in pairs(contents) do |
192 | + | -- blockType, blockModifier, data |
193 | - | if item.name == itemName then |
193 | + | local blockType, blockModifier = T:getBlockType(direction) |
194 | - | inStock = inStock + item.count |
194 | + | |
195 | - | canStore = canStore + itemsPerSlot - item.count |
195 | + | |
196 | T:dig(direction) | |
197 | - | if matchPart ~= "" then -- eg check for "cobblestone" or "slab" |
197 | + | |
198 | - | if item.name:find(matchPart) ~= nil then |
198 | + | |
199 | - | partMatch = true |
199 | + | |
200 | and blockType:find("ice") == nil then | |
201 | -- NOT water, ice or lava | |
202 | isAirWaterLava = false -- solid block | |
203 | end | |
204 | end | |
205 | - | T:saveToLog("network.checkInventory return inStock = "..inStock..", canStore = "..canStore..", partMatch = "..tostring(partMatch)) |
205 | + | |
206 | - | return inStock, canStore, partMatch -- eg 1, 3647, false if contains only 1 matching item in otherwise empty chest |
206 | + | |
207 | end | |
208 | ||
209 | - | function network.emptyInventory(R, barrels, chests, sticksAsFuel) |
209 | + | |
210 | - | --[[network.emptyInventory(R, {"sapling", "propagule", "dirt", "crafting"}, {"all"}, true)]] |
210 | + | |
211 | - | if not T:isEmpty() then |
211 | + | |
212 | - | if sticksAsFuel then |
212 | + | |
213 | - | utils.useSticksAsFuel() |
213 | + | |
214 | if type(R) == "table" then | |
215 | - | for _, item in ipairs(barrels) do |
215 | + | |
216 | - | network.sendItemToNetworkStorage(R, "barrel", item, 0) |
216 | + | |
217 | reduce = true | |
218 | - | for _, item in ipairs(chests) do |
218 | + | |
219 | - | network.sendItemToNetworkStorage(R, "chest", item, 0) |
219 | + | |
220 | else | |
221 | length = R | |
222 | end | |
223 | local numBlocks = 0 | |
224 | - | function network.loadStorageLists() |
224 | + | |
225 | if reduce then | |
226 | T:forward(1) | |
227 | - | function lib.createList(storageType) |
227 | + | |
228 | - | local storage, turtleName, storageNames = network.wrapModem(R, storageType) -- list of barrel/chest peripherals, name of turtle, names of barrels / chests |
228 | + | |
229 | - | local total = 0 |
229 | + | |
230 | - | local locations = {} |
230 | + | |
231 | - | for _, store in pairs(storageNames) do -- eg "minecraft:chest_1" |
231 | + | |
232 | - | T:clear() |
232 | + | |
233 | - | T:saveToLog("Checking "..store.. " contents") -- eg "checking minecraft:chest_1 contents" |
233 | + | |
234 | - | local contents = peripheral.call(store, "list") -- list of items / slots for this chest |
234 | + | |
235 | - | for slot, item in pairs(contents) do -- for each item check if this storage is listed |
235 | + | |
236 | - | if locations[item.name] == nil then -- this item not yet found |
236 | + | |
237 | - | locations[item.name] = {store} -- add to table eg locations["minecraft:cobblestone"] = {"minecraft:chest_1"} |
237 | + | |
238 | - | else -- already has at least 1 location |
238 | + | |
239 | - | network.addToStorageList(storageType, locations[item.name], store, false) |
239 | + | |
240 | end | |
241 | local place = utils.clearVegetation("down") | |
242 | - | total = total + 1 |
242 | + | |
243 | if T:fillVoid("down", {}, false) then -- false if out of blocks | |
244 | - | T:saveToLog("found ".. total.." "..storageType) |
244 | + | |
245 | - | local output = textutils.serialize(locations) -- serialise to json ready to write to file |
245 | + | |
246 | - | local fileName = storageType.."Items.lua" -- barrelList.lua or chestList.lua |
246 | + | |
247 | - | local outputHandle = fs.open(fileName, "w") -- open file |
247 | + | |
248 | - | outputHandle.writeLine("return") -- start file with return |
248 | + | |
249 | - | outputHandle.write(output) -- add serialised table |
249 | + | T:place("minecraft:torch", -1, "forward", false) |
250 | - | outputHandle.close() -- close file |
250 | + | |
251 | end | |
252 | - | return locations |
252 | + | |
253 | else | |
254 | break | |
255 | - | function lib.listNeedUpdating(storageType, list) |
255 | + | |
256 | - | -- see if named chest/barrel in list is found in fresh peripheral.find |
256 | + | |
257 | - | -- turtle may have moved to a different network |
257 | + | |
258 | - | -- list = eg [ "minecraft:stick" ] = {"minecraft:barrel_91","minecraft:barrel_114"} |
258 | + | |
259 | - | local rawStorage = {peripheral.find(storageType)} |
259 | + | |
260 | - | if not utils.isTableEmpty(rawStorage) then -- chests / barrels are attached see if they match |
260 | + | |
261 | - | for item, storeList in pairs(list) do -- existing storage names can be found here |
261 | + | |
262 | - | local found = false |
262 | + | |
263 | - | for key, value in ipairs(rawStorage) do -- look in the fresh list of storage names to see if there are missing entries |
263 | + | |
264 | - | local name = peripheral.getName(value) |
264 | + | |
265 | - | for _, storageName in ipairs(storeList) do -- check each storage name found |
265 | + | |
266 | - | if storageName == name then -- recorded name matches, check next one |
266 | + | |
267 | - | found = true |
267 | + | |
268 | - | break |
268 | + | |
269 | D.height = # | |
270 | D.ceiling = false | |
271 | - | if found then break end |
271 | + | |
272 | D.vDirection = "U" or "D" | |
273 | - | if not found then |
273 | + | |
274 | - | -- no match in existing list for this storage: list needs updating |
274 | + | |
275 | - | return true-- list does not match |
275 | + | |
276 | ]] | |
277 | local turn = "R1" | |
278 | local oTurn = "L1" | |
279 | - | return false -- list is ok |
279 | + | |
280 | turn = "L1" | |
281 | oTurn = "R1" | |
282 | - | local _, turtleName, storageNames = network.wrapModem(R, "chest") -- _, name of turtle, list of names of storage |
282 | + | |
283 | - | if turtleName == "Modem not found" then return turtleName end |
283 | + | |
284 | - | local redo = false |
284 | + | |
285 | - | if barrelItems == nil then -- not yet loaded |
285 | + | |
286 | - | T:saveToLog("barrelItems == nil") |
286 | + | |
287 | - | if fs.exists("barrelItems.lua") then |
287 | + | |
288 | - | T:saveToLog("require('barrelItems')") |
288 | + | |
289 | - | barrelItems = require("barrelItems") -- global variable |
289 | + | |
290 | - | redo = lib.listNeedUpdating("barrel", barrelItems) |
290 | + | |
291 | return "C2" | |
292 | - | T:saveToLog("lib.createList('barrel'") |
292 | + | |
293 | - | barrelItems = lib.createList("barrel") |
293 | + | |
294 | if D.ceiling then | |
295 | return "C0" | |
296 | - | if chestItems == nil then -- not yet loaded |
296 | + | |
297 | - | T:saveToLog("chestItems == nil") |
297 | + | |
298 | - | if fs.exists("chestItems.lua") then |
298 | + | |
299 | - | T:saveToLog("require('chestItems')") |
299 | + | |
300 | - | chestItems = require("chestItems") -- global variable |
300 | + | |
301 | - | redo = lib.listNeedUpdating("chest", barrelItems) |
301 | + | |
302 | end | |
303 | - | T:saveToLog("lib.createList('chest'") |
303 | + | |
304 | - | chestItems = lib.createList("chest") |
304 | + | |
305 | - | end |
305 | + | |
306 | end | |
307 | - | if redo then |
307 | + | |
308 | - | barrelItems = lib.createList("barrel") |
308 | + | |
309 | - | chestItems = lib.createList("chest") |
309 | + | |
310 | return "" -- start and finish both false | |
311 | end | |
312 | ||
313 | - | function network.findEmptySlot(list, size) |
313 | + | |
314 | - | --[[ adapted from https://github.com/cc-tweaked/CC-Tweaked/discussions/1552 |
314 | + | |
315 | - | Find the first empty slot in a chest. |
315 | + | |
316 | - | list = list of items in the chest/barrel/dropper |
316 | + | |
317 | - | size = The size of the inventory |
317 | + | |
318 | - | return integer? slot The slot number of the first empty slot, or nil if none are empty. |
318 | + | |
319 | T:go(place, false, 0, true)-- place floor / ceiling | |
320 | - | for slot = 1, size do |
320 | + | |
321 | - | if not list[slot] then |
321 | + | |
322 | - | return slot |
322 | + | |
323 | elseif width == D.width then -- checking opposite wall | |
324 | if outward then -- travelling away from start | |
325 | T:go(turn..placeF..oTurn, false, 0, true) -- face wall and check if block | |
326 | - | return nil |
326 | + | |
327 | T:go(oTurn..placeF..turn, false, 0, true) -- face wall and check if block | |
328 | end | |
329 | - | function network.findItemCountInInventory(list, itemName, exactMatch) |
329 | + | |
330 | -- move forward | |
331 | - | Find an item in an inventory |
331 | + | |
332 | - | list = The list of items in the inventory |
332 | + | |
333 | - | itemName = The name of the item to find. |
333 | + | |
334 | - | return integer? The slot number of the item, or nil if not found. |
334 | + | |
335 | if width < D.width then | |
336 | - | exactMatch = exactMatch or false |
336 | + | |
337 | - | if type(list) == "string" then |
337 | + | |
338 | - | list = peripheral.call(list, "list") |
338 | + | |
339 | else | |
340 | - | local retValue = nil |
340 | + | |
341 | - | local count = 0 |
341 | + | |
342 | - | for slot, item in pairs(list) do |
342 | + | |
343 | else | |
344 | - | if exactMatch then |
344 | + | |
345 | - | if item.name == itemName then found = true end |
345 | + | |
346 | else | |
347 | - | if item.name:find(itemName) ~= nil then found = true end |
347 | + | |
348 | end | |
349 | end | |
350 | - | if retValue == nil then |
350 | + | |
351 | - | retValue = {} |
351 | + | |
352 | ||
353 | - | table.insert(retValue,{slot, item.count}) -- eg {1, 64} |
353 | + | |
354 | - | count = count + item.count |
354 | + | |
355 | if height == 1 then | |
356 | lib.layer(D, true, false) -- first layer, so start = true, finish = false | |
357 | - | return count, retValue -- either nil or eg {{1, 64},{4, 22}} |
357 | + | |
358 | lib.layer(D, false, true) -- final layer, so start = false, finish = true | |
359 | else | |
360 | - | function network.findItemInInventory(inventory, itemName, exactMatch) |
360 | + | |
361 | - | --[[ adapted from https://github.com/cc-tweaked/CC-Tweaked/discussions/1552 |
361 | + | |
362 | - | Find an item in an inventory |
362 | + | |
363 | - | inventory = name of inventory or wrapped peripheral |
363 | + | |
364 | - | itemName = The name of the item to find. |
364 | + | |
365 | - | return integer?, integer? The slot number and count of the item, or nil if not found. |
365 | + | |
366 | if D.goHome then-- ends at starting point | |
367 | - | exactMatch = exactMatch or false |
367 | + | |
368 | - | if type(inventory) == "string" then |
368 | + | |
369 | - | T:saveToLog("network.findItemInInventory("..inventory..", "..itemName..", exactMatch = "..tostring(exactMatch)..")", true) |
369 | + | |
370 | - | contents = peripheral.call(inventory, "list") |
370 | + | |
371 | - | else -- should be supplied with .list() already |
371 | + | |
372 | - | T:saveToLog("network.findItemInInventory(<inventory>, "..itemName..", exactMatch = "..tostring(exactMatch)..")", true) |
372 | + | |
373 | - | contents = inventory |
373 | + | |
374 | ||
375 | - | --T:saveToLog("contents = "..table.concat(contents, ", ")) |
375 | + | |
376 | - | --utils.writeTraceTable("contents = ", contents) |
376 | + | |
377 | - | if contents ~= nil then |
377 | + | |
378 | - | for slot, item in pairs(contents) do |
378 | + | |
379 | - | --T:saveToLog("item.name = "..item.name..", item.count = "..item.count) |
379 | + | |
380 | - | if exactMatch then |
380 | + | |
381 | - | if item.name == itemName then |
381 | + | |
382 | - | T:saveToLog("Item found in "..slot..", quantity = "..item.count) |
382 | + | |
383 | - | return slot, item.count |
383 | + | |
384 | -- assume on flat surface, but allow for blocks above | |
385 | T:go("x0C2F1 x0C2F1 x0C2F1 x0C2R1 F1 x0C2F1 x0C2F1 x0C2R1 F1 x0C2F1 x0C2F1 x0C2R1 F1 x0C2F1 x0C2", false, 0, false) | |
386 | - | if (item.name):find(itemName) ~= nil then |
386 | + | |
387 | - | T:saveToLog("Matching Item found in "..slot..", quantity = "..item.count) |
387 | + | |
388 | - | return slot, item.count |
388 | + | |
389 | for i = 1, 2 do | |
390 | T:placeWater("down") | |
391 | T:go("F1R1F1R1", false, 0, false) | |
392 | end | |
393 | - | T:saveToLog("Item not found") |
393 | + | |
394 | - | return 0,0 |
394 | + | |
395 | sleep(0.5) | |
396 | T:placeWater("down") | |
397 | - | function network.getItemFromNetwork(storageType, itemRequired, countRequired, toTurtleSlot, ignoreStock) |
397 | + | |
398 | T:go("R2F1R1F1R1") | |
399 | -- end above lower left of pond (starting point) | |
400 | - | function lib.getItem(storageTable, turtleName, itemRequired, countRequired, toTurtleSlot, sent) |
400 | + | |
401 | - | local exit = false |
401 | + | |
402 | - | for k, storageName in pairs(storageTable) do -- eg {"minecraft:barrel_17", "minecraft:barrel_18"...} |
402 | + | |
403 | - | local available, data = network.findItemCountInInventory(storageName, itemRequired, false) -- either nil or eg {{1, 64},{4, 22}} |
403 | + | |
404 | - | T:saveToLog("network.findItemCountInInventory("..storageName..", "..itemRequired..", false") |
404 | + | |
405 | - | if data ~= nil then |
405 | + | |
406 | - | for i = 1, #data do |
406 | + | |
407 | - | local request = countRequired |
407 | + | |
408 | - | if countRequired > 64 then |
408 | + | |
409 | - | request = 64 |
409 | + | |
410 | end | |
411 | - | local received = network.sendItemsToTurtle(turtleName, storageName, data[i][1], request, toTurtleSlot) -- request items, returns number sent |
411 | + | |
412 | - | if received == nil then received = 0 end |
412 | + | |
413 | - | sent = sent + received |
413 | + | |
414 | - | T:saveToLog("received = "..received..", request = "..request.." from "..storageName..", sent = "..sent) |
414 | + | |
415 | - | if sent >= countRequired then |
415 | + | |
416 | - | exit = true |
416 | + | |
417 | - | break |
417 | + | |
418 | - | end -- job done, no need to check remaining slots |
418 | + | |
419 | - | countRequired = countRequired - sent -- this line not reached if sent >= count |
419 | + | |
420 | T:go("D1R1C1 R1C1 U1C1 L1C1 U1C1 R1C1 L2D1 C2C0", false, 0, true) | |
421 | -- finished on same mid 3 high column with wall behind and right completed | |
422 | - | --if sent >= countRequired then break end -- no need to check other storage |
422 | + | |
423 | - | --if countRequired <= 0 then break end |
423 | + | |
424 | - | if exit then |
424 | + | |
425 | - | return sent, countRequired |
425 | + | |
426 | T:go("L1F"..offset.."L2C1 R1D1C1 U1C1 U1C1 D1") | |
427 | -- end next row along the width, facing the back, mid point | |
428 | -- wall ahead completed | |
429 | - | return sent, countRequired |
429 | + | |
430 | ||
431 | function lib.frontTurn() | |
432 | - | -- eg slot, count = network.getItemFromNetwork("barrel", "minecraft:crafting_table", 1) |
432 | + | |
433 | - | -- storageType either "chest" or "barrel" |
433 | + | |
434 | - | if countRequired == nil then return 0,0 end |
434 | + | |
435 | - | --if toTurtleSlot not specified then nil = use any slot |
435 | + | |
436 | - | ignoreStock = ignoreStock or false -- return only no of items obtained from storage |
436 | + | |
437 | - | T:saveToLog("network.getItemFromNetwork(storageType = "..storageType..", itemRequired = ".. itemRequired.. |
437 | + | |
438 | - | ", countRequired = ".. countRequired..", toTurtleSlot = "..tostring(toTurtleSlot)..", ignoreStock = "..tostring(ignoreStock)) |
438 | + | |
439 | - | -- Must be next to a modem: MUST remove crafting table if modem on that side. Other tools ok |
439 | + | |
440 | - | local sent = 0 |
440 | + | |
441 | - | local turtleSlot, turtleCount = T:getItemSlot(itemRequired) -- check local stock |
441 | + | |
442 | - | if not ignoreStock then -- take account of existing items and reduce count accordingly |
442 | + | |
443 | - | countRequired = countRequired - turtleCount |
443 | + | |
444 | lib.startCorner() | |
445 | - | local savedItems = nil |
445 | + | |
446 | - | if storageType == "barrel" then |
446 | + | |
447 | - | savedItems = barrelItems |
447 | + | |
448 | - | elseif storageType == "chest" then |
448 | + | |
449 | - | savedItems = chestItems |
449 | + | |
450 | end | |
451 | - | local storage, turtleName, storageNames = network.wrapModem(R, storageType) -- list of chest/barrel peripherals, name of turtle, list of storage names |
451 | + | |
452 | - | --if turtleName == "Modem not found" then return 0, nil, nil, turtleName end |
452 | + | |
453 | - | if countRequired > 0 then -- not enough in stock, or ignore current stock |
453 | + | |
454 | - | -- check if item in storageLists |
454 | + | |
455 | - | local testStores = nil |
455 | + | |
456 | - | if savedItems[itemRequired] ~= nil then -- only works with full item names |
456 | + | |
457 | - | T:saveToLog("savedItems key in list: "..textutils.serialise(savedItems[itemRequired], {compact = true})) |
457 | + | |
458 | - | testStores = savedItems[itemRequired] |
458 | + | |
459 | return 1 | |
460 | - | for key, value in pairs(savedItems) do |
460 | + | |
461 | - | if key:find(itemRequired)~= nil then |
461 | + | |
462 | - | T:saveToLog("savedItems found in list: "..textutils.serialise(value, {compact = true})) |
462 | + | |
463 | - | testStores = value |
463 | + | |
464 | local waterPresent = false | |
465 | for i = 1, distance do | |
466 | if T:isWater("down") then | |
467 | waterPresent = true | |
468 | - | if testStores == nil then -- no match in storage lists |
468 | + | |
469 | - | T:saveToLog("Unable to find recorded storage, using all "..storageType.."s") |
469 | + | |
470 | - | sent, countRequired = lib.getItem(storageNames, turtleName, itemRequired, countRequired, toTurtleSlot, sent) |
470 | + | |
471 | - | else -- match found, list of storage availble -- eg {"minecraft:barrel_17", "minecraft:barrel_18"...} |
471 | + | |
472 | - | T:saveToLog("Using recorded list alias 'testStores'") |
472 | + | |
473 | - | sent, countRequired = lib.getItem(testStores, turtleName, itemRequired, countRequired, toTurtleSlot, sent) |
473 | + | |
474 | T:go("C1", false, 0, true) | |
475 | end | |
476 | - | -- slotData.lastSlot, total, slotData -- integer, integer, table |
476 | + | |
477 | - | local data = {} |
477 | + | |
478 | - | turtleSlot, turtleCount, data = T:getItemSlot(itemRequired) |
478 | + | |
479 | - | T:saveToLog("turtleSlot = "..turtleSlot..", turtleCount = "..turtleCount..", sent = "..sent) --..", data = "..textutils.serialise(data)) |
479 | + | |
480 | - | if ignoreStock then |
480 | + | |
481 | - | return turtleSlot, sent -- 0 -> count |
481 | + | |
482 | for i = 1, distance do | |
483 | - | return turtleSlot, turtleCount -- 0 -> count |
483 | + | |
484 | if i < distance then | |
485 | T:forward(1) | |
486 | end | |
487 | - | function network.getSlotContains(inventoryName, inSlot) |
487 | + | |
488 | - | local list = peripheral.call(inventoryName, "list") |
488 | + | |
489 | - | for slot, item in pairs(list) do |
489 | + | |
490 | - | if inSlot == slot then |
490 | + | |
491 | - | return item.name |
491 | + | |
492 | if R.data == "" then | |
493 | if turtle.detectDown() then -- on solid surface | |
494 | - | return "" |
494 | + | |
495 | end | |
496 | end | |
497 | - | function network.moveItem(inventoryName, itemName, toSlot) |
497 | + | |
498 | - | --[[ adapted from https://github.com/cc-tweaked/CC-Tweaked/discussions/1552 |
498 | + | |
499 | - | Move a specific item to specific slot eg 1, moving other items out of the way if needed. |
499 | + | |
500 | - | inventoryName = The name of the chest/barrel/dropper to search. |
500 | + | |
501 | - | itemName = The name of the item to find. |
501 | + | |
502 | - | toSlot optional. default is slot 1 |
502 | + | |
503 | - | return boolean success Whether or not the item was successfully moved to toSlot (or already existed there) |
503 | + | |
504 | R = utils.calculateDimensions(R) | |
505 | - | toSlot = toSlot or 1 |
505 | + | |
506 | - | local list = peripheral.call(inventoryName, "list") |
506 | + | |
507 | - | local size = peripheral.call(inventoryName, "size") |
507 | + | |
508 | - | local slot = network.findItemInInventory(list, itemName) |
508 | + | |
509 | T:go("R2D2", false, 0, true) -- at start, level 2, facing towards the front, move backards | |
510 | - | -- If the item didn't exist, or is already in the first slot, we're done. |
510 | + | |
511 | - | if not slot then |
511 | + | |
512 | - | T:saveToLog("network.moveItem(): Item not found") |
512 | + | |
513 | if lib.placeDam(R.length) then | |
514 | waterPresent = true | |
515 | - | if slot == toSlot then |
515 | + | |
516 | row = row + 1 | |
517 | -- left side wall has been built, 2 rows of walls laid. row = 2 | |
518 | while row < R.width - 1 do -- eg width=2, row=2, this will not run. width=5, row=2 | |
519 | - | -- If an item is blocking the first slot (we already know it's not the one we want), we need to move it. |
519 | + | |
520 | - | if list[toSlot] then |
520 | + | |
521 | - | T:saveToLog("network.moveItem() Slot "..toSlot.." occupied, moving..") |
521 | + | |
522 | - | local emptySlot = network.findEmptySlot(list, size) |
522 | + | |
523 | waterPresent = true | |
524 | - | -- If there are no empty slots, we can't move the item. |
524 | + | |
525 | - | if not emptySlot then |
525 | + | |
526 | - | T:saveToLog("network.moveItem(): No empty slots") |
526 | + | |
527 | -- lay right wall | |
528 | lib.frontTurn() | |
529 | lib.removeDam(R.length) | |
530 | - | -- Move the item to the first empty slot. |
530 | + | |
531 | row = row + lib.placeRetainingWall(R.length) | |
532 | - | if not network.moveItemStack(inventoryName, toSlot, emptySlot) then |
532 | + | |
533 | - | T:saveToLog("network.moveItem(): Failed to move item to slot " .. emptySlot) |
533 | + | |
534 | T:go("L1F1R1") | |
535 | lib.removeDam(R.length) -- faces to front on finish | |
536 | depth = depth + 3 | |
537 | - | T:saveToLog("network.moveItem(): Moved item to slot " .. emptySlot) |
537 | + | |
538 | if depth == R.height or not waterPresent then -- still replacing water | |
539 | T:up(depth - 1) -- when h == R.height will go up | |
540 | - | -- Move the item to slot 1. |
540 | + | |
541 | - | if not network.moveItemStack(inventoryName, slot, toSlot) then |
541 | + | |
542 | - | T:saveToLog("network.moveItem(): Failed to move item to slot "..toSlot) |
542 | + | |
543 | end | |
544 | return {} | |
545 | end | |
546 | - | T:saveToLog("network.moveItem(): Moved item to slot "..toSlot) |
546 | + | |
547 | - | return true |
547 | + | |
548 | while not turtle.detectDown() do -- over water. will be infinite loop if out of sand | |
549 | if not T:place("sand", -1, "down", false) then | |
550 | - | function network.moveItemsFromTurtle(turtleName, toInventoryName, fromTurtleSlot, quantity, toSlot) |
550 | + | |
551 | sleep(2) | |
552 | - | Move quantity of an item from one inventory to another. Turtles MUST use attachedInventory.pullItems() |
552 | + | |
553 | - | eg network.moveItemsFromTurtle(turtleName, chestName, turtleSlot, turtleCount, nil) |
553 | + | |
554 | - | turtleName: The name of the turtle (via getLocalName()) |
554 | + | |
555 | - | toInventoryName: The name of the inventory to move items into. |
555 | + | |
556 | - | fromTurtleSlot: The slot to move from. must be pre-determined for the item required |
556 | + | |
557 | - | quantity: The amount to transfer (nil for full stack) |
557 | + | |
558 | - | toSlot: The slot to move to. (nil will use any available slot(s)) |
558 | + | |
559 | allows 2 turtles to co-operate | |
560 | - | return peripheral.call(toInventoryName, "pullItems", turtleName, fromTurtleSlot, quantity, toSlot) |
560 | + | |
561 | R.side = "R" or "L" | |
562 | ]] | |
563 | - | function network.moveItemStack(inventoryName, fromSlot, toSlot) |
563 | + | |
564 | - | --[[ adapted from https://github.com/cc-tweaked/CC-Tweaked/discussions/1552 |
564 | + | |
565 | - | Move an item from one slot to another in a given inventory. |
565 | + | |
566 | - | inventoryName The name of the inventory to move items in. |
566 | + | |
567 | - | fromSlot The slot to move from. |
567 | + | |
568 | - | toSlot The slot to move to. |
568 | + | |
569 | local finished = false | |
570 | - | return peripheral.call(inventoryName, "pushItems", inventoryName, fromSlot, nil, toSlot) |
570 | + | |
571 | rs.setAnalogueOutput("front", 0) -- switch off output | |
572 | local blockType = T:getBlockType("forward") | |
573 | - | function network.sendItemToNetworkStorage(R, storageType, itemToSend, amountToSend) |
573 | + | |
574 | - | -- used to remove items from turtle inventory |
574 | + | |
575 | - | -- Must be next to a modem: MUST remove crafting table if modem on that side. Other tools ok |
575 | + | |
576 | sleep(0.1) | |
577 | timer = timer + 0.1 | |
578 | - | function lib.sendItem(savedItems, peripheralNames, turtleName, turtleSlot, item, slotCount, itemsPerSlot) |
578 | + | |
579 | - | local storageToUse = "" |
579 | + | |
580 | - | local storageList = lib.getStorageFromList(savedItems, item, slotCount, itemsPerSlot) -- try from savedList |
580 | + | |
581 | - | if storageList == nil then -- no match found, but use first one found with network.wrapModem |
581 | + | |
582 | - | T:saveToLog("No storage with matching items found, using first empty chest") |
582 | + | |
583 | - | storageToUse = lib.findEmptyStorage(peripheralNames, item, itemsPerSlot, slotCount) |
583 | + | |
584 | endTimer = 0 | |
585 | - | T:saveToLog("Storage with matching items found, checking capacity") |
585 | + | |
586 | - | storageToUse = lib.checkCapacity(storageList, item, slotCount, itemsPerSlot) |
586 | + | |
587 | - | if storageToUse == "" then -- no capacity in known storage list, so start a new one |
587 | + | |
588 | - | storageToUse = lib.findEmptyStorage(peripheralNames, item, itemsPerSlot, slotCount) |
588 | + | |
589 | if confirmed then | |
590 | menu.colourWrite("Turtle confirmed: input = "..rsIn.." output = "..rsOut, colors.orange, nil, nil, false, true) | |
591 | - | --network.moveItemsFromTurtle(turtleName, toInventoryName, fromTurtleSlot, quantity, toSlot) |
591 | + | |
592 | - | T:saveToLog("network.moveItemsFromTurtle(turtleName = "..turtleName..", storageToUse = "..tostring(storageToUse)..", slot = "..tostring(turtleSlot)..", slotCount = "..tostring(slotCount)..")") |
592 | + | |
593 | - | network.moveItemsFromTurtle(turtleName, storageToUse, turtleSlot, slotCount) |
593 | + | |
594 | else | |
595 | menu.colourWrite("Waiting: input = "..rsIn.." output = "..rsOut, colors.orange, nil, nil, false, true) | |
596 | - | function lib.findEmptyStorage(peripheralNames, itemName, itemsPerSlot, itemCount) |
596 | + | |
597 | - | T:saveToLog("lib.findEmptyStorage("..textutils.serialise(peripheralNames,{compact = true})..", itemName = "..itemName.. ", itemsPerSlot = "..itemsPerSlot) |
597 | + | |
598 | - | for store = 1, #peripheralNames do |
598 | + | |
599 | - | inStock, canStore, partMatch = network.checkInventory(peripheralNames[store], itemName, itemsPerSlot, "") |
599 | + | |
600 | - | if canStore > itemCount then |
600 | + | |
601 | - | return peripheralNames[store] |
601 | + | |
602 | end | |
603 | if endTimer >= 10 then -- allows time for other computer to get ready | |
604 | - | return nil |
604 | + | |
605 | end | |
606 | rs.setAnalogueOutput("front", 1) -- output 1 as a signal initially | |
607 | - | function lib.getStorageFromList(savedItems, item, sendAmount, itemsPerSlot) |
607 | + | |
608 | - | if savedItems[item] == nil then -- no record of this item stored |
608 | + | |
609 | - | T:saveToLog("lib.getStorageFromList() "..item.." not found") |
609 | + | |
610 | - | local parts = T:getNames(item) -- eg minecraft:jungle_planks = "minecraft", "jungle", "planks" |
610 | + | |
611 | - | for part = #parts, 1, -1 do -- iterate "planks", "jungle", "minecraft" |
611 | + | |
612 | - | local searchTerm = parts[part] |
612 | + | |
613 | - | if searchTerm ~= "minecraft" and searchTerm ~= "mysticalagriculture" then |
613 | + | |
614 | - | for itemName, storageList in pairs(savedItems) do -- iterate items used as keys eg minecraft:jungle_log matches jungle |
614 | + | |
615 | - | if itemName:find(searchTerm) ~= nil then -- partial match eg "sapling" found in "minecraft:oak_sapling" |
615 | + | |
616 | - | T:saveToLog("lib.getStorageFromList() matched "..searchTerm.." with "..itemName) |
616 | + | |
617 | - | return storageList -- eg {"minecraft:chest_22", "minecraft:chest_23"} |
617 | + | |
618 | confirmed = true | |
619 | rsOut = 15 | |
620 | elseif rsIn == 15 or confirmed then | |
621 | menu.colourWrite("endTimer active = "..endTimer, colors.orange, nil, nil, false, true) | |
622 | endTimer = endTimer + 1 -- start endTimer | |
623 | - | T:saveToLog("lib.getStorageFromList() ["..item.."] found") |
623 | + | |
624 | - | return savedItems[item] -- list of chests with this item available |
624 | + | |
625 | T:go(R.side.."3") | |
626 | - | return nil |
626 | + | |
627 | return rsIn -- 15 | |
628 | end | |
629 | - | function lib.checkCapacity(storageList, item, sendAmount, itemsPerSlot) |
629 | + | |
630 | - | -- find a chest/barrel with sufficient capacity from list of storage |
630 | + | |
631 | - | for store = 1, #storageList do |
631 | + | |
632 | - | local inStock, canStore, partMatch = network.checkInventory(storageList[store], item, itemsPerSlot, "") |
632 | + | |
633 | - | if canStore > sendAmount then |
633 | + | |
634 | - | return storageList[store] |
634 | + | |
635 | maxDescent = maxDescent or 1 -- prevents continuous down due to lack of water | |
636 | if goIn == nil then -- turtle should submerge | |
637 | goIn = true | |
638 | end | |
639 | local descent = 0 -- counter for going down | |
640 | - | amountToSend = amountToSend or 0 -- 0 = remove all of this item |
640 | + | |
641 | - | local totalSent = 0 -- track quantity sent |
641 | + | |
642 | - | local minSend = 0 -- minimum amount to send |
642 | + | |
643 | - | if amountToSend > 0 then minSend = amountToSend end -- update minimum to send |
643 | + | |
644 | - | local _, turtleName, peripheralNames = network.wrapModem(R, storageType) -- _, name of turtle, list of names of storage |
644 | + | |
645 | if T:getBlockType("forward"):find("water") ~= nil or T:getBlockType("forward"):find("bubble") ~= nil then | |
646 | - | T:saveToLog("network.sendItemToNetworkStorage(R, storageType = '"..storageType.."', itemToSend = '"..itemToSend.."', amountToSend = "..amountToSend..")") |
646 | + | |
647 | - | T:saveToLog("network.wrapModem(R, storageType = "..storageType..", turtleName = "..turtleName..")") |
647 | + | |
648 | - | local savedItems = nil |
648 | + | |
649 | - | if storageType == "barrel" then |
649 | + | |
650 | - | savedItems = barrelItems |
650 | + | |
651 | - | elseif storageType == "chest" then |
651 | + | |
652 | - | savedItems = chestItems |
652 | + | |
653 | end | |
654 | -- should now be above water, but may be further down so onWater still false | |
655 | - | if itemToSend == "all" then -- empty Turtle, so item names not relevant |
655 | + | |
656 | - | T:saveToLog("itemToSend = all") |
656 | + | |
657 | descent = descent + 1 | |
658 | - | local item, turtleSlot, slotCount, itemsPerSlot = "", 0, 0, 64 |
658 | + | |
659 | - | for slot = 1, 16 do |
659 | + | |
660 | - | item, slotCount = T:getSlotContains(slot) |
660 | + | |
661 | - | if slotCount > 0 then |
661 | + | |
662 | - | turtleSlot = slot |
662 | + | |
663 | - | T:saveToLog("for slot = 1, 16 do: item = "..item..", slotCount = "..slotCount) |
663 | + | |
664 | - | itemsPerSlot = utils.getSlotCapacity(slot) -- most items capacity is 64 per slot |
664 | + | |
665 | - | T:saveToLog("sending'"..item.."' from slot "..slot..", quantity = "..slotCount) |
665 | + | |
666 | end | |
667 | -- now above water | |
668 | if goIn then | |
669 | - | if turtleSlot > 0 then |
669 | + | |
670 | - | lib.sendItem(savedItems, peripheralNames, turtleName, turtleSlot, item, slotCount, itemsPerSlot) |
670 | + | |
671 | end | |
672 | - | until turtleSlot == 0 |
672 | + | |
673 | - | return 0 -- exit function |
673 | + | |
674 | ||
675 | - | local storageToUse = "" |
675 | + | |
676 | - | repeat -- until item no longer present in inventory or requested amount has been sent |
676 | + | |
677 | - | local sourceSlot, total, data = T:getItemSlot(itemToSend) -- which slot and how much of itemToSend is in turtle? |
677 | + | |
678 | - | local slotCount = data.leastCount |
678 | + | |
679 | - | T:saveToLog("T:getItemSlot('"..itemToSend.."' sourceSlot = "..sourceSlot..", total = "..total..")") |
679 | + | |
680 | - | if sourceSlot == 0 then |
680 | + | |
681 | - | T:saveToLog(itemToSend.." not found in turtle inventory") |
681 | + | |
682 | - | return 0 -- exit function |
682 | + | |
683 | ||
684 | - | local itemsPerSlot = utils.getSlotCapacity(sourceSlot) -- most items capacity is 64 per slot |
684 | + | |
685 | - | itemToSend = data.leastName -- full name of item with lowest itemCount |
685 | + | local lastSlot, leastModifier, total, slotData = T:getItemSlot("minecraft:bucket", -1) |
686 | - | T:saveToLog("network.sendItemToNetworkStorage(R, '"..itemToSend.."', sourceSlot = "..sourceSlot..", slotCount = "..slotCount) --..", data = "..textutils.serialise(data)..")") |
686 | + | |
687 | - | if sourceSlot > 0 then -- item is present in turtle inventory |
687 | + | |
688 | - | local newStore = false |
688 | + | |
689 | - | local sent = 0 |
689 | + | |
690 | - | local storageList = lib.getStorageFromList(savedItems, itemToSend, slotCount, itemsPerSlot) |
690 | + | |
691 | - | if storageList == nil then |
691 | + | |
692 | - | T:saveToLog("not found in any storage, finding empty") |
692 | + | |
693 | - | storageToUse = lib.findEmptyStorage(peripheralNames, itemToSend, itemsPerSlot, total) |
693 | + | |
694 | - | T:saveToLog("new storage: "..storageToUse.." is available") |
694 | + | |
695 | - | network.addToStorageList(storageType, itemToSend, storageToUse, true) |
695 | + | |
696 | - | sent = network.moveItemsFromTurtle(turtleName, storageToUse, sourceSlot, slotCount) |
696 | + | |
697 | ||
698 | - | storageToUse = lib.checkCapacity(storageList, itemToSend, slotCount, itemsPerSlot) |
698 | + | |
699 | - | if storageToUse == "" then -- no capacity in known storage list, so start a new one |
699 | + | |
700 | - | storageToUse = lib.findEmptyStorage(peripheralNames, itemToSend, itemsPerSlot, total) |
700 | + | |
701 | - | newStore = true |
701 | + | |
702 | end | |
703 | - | T:saveToLog("sent = network.moveItemsFromTurtle(turtleName = "..turtleName..", storageToUse = "..storageToUse..", sourceSlot = "..sourceSlot..", slotCount = ".. slotCount) |
703 | + | |
704 | - | sent = network.moveItemsFromTurtle(turtleName, storageToUse, sourceSlot, slotCount) |
704 | + | |
705 | end | |
706 | - | totalSent = totalSent + sent |
706 | + | |
707 | - | if minSend > 0 and totalSent >= minSend then |
707 | + | |
708 | - | return totalSent |
708 | + | |
709 | ||
710 | - | if amountToSend > 0 then -- sending specified amount |
710 | + | |
711 | - | amountToSend = amountToSend - sent |
711 | + | |
712 | T:getWater("down") -- take water from source | |
713 | - | if newStore then |
713 | + | |
714 | - | network.addToStorageList(storageType, itemToSend, storageName, true) |
714 | + | |
715 | else | |
716 | if not turtle.detectDown() then | |
717 | T:go("C2", false, 0, false) | |
718 | - | until sourceSlot == 0 |
718 | + | |
719 | T:getWater("forward") -- take water from source | |
720 | sleep(0.2) | |
721 | - | return totalSent |
721 | + | |
722 | end | |
723 | end | |
724 | - | function network.sendItemsToCrafter(crafterName, fromInventoryName, fromInventorySlot, quantity, toCrafterSlot) |
724 | + | |
725 | function utils.getWaterBucketCount() | |
726 | - | fromInventoryName: The name of the inventory to move items from. |
726 | + | -- lastSlot, leastModifier, total, slotData = T:getItemSlot(item, useDamage) |
727 | - | fromInventorySlot: The slot to move from. must be pre-determined for the item required |
727 | + | local lastSlot, leastModifier, total, slotData = T:getItemSlot("minecraft:water_bucket", -1) |
728 | - | quantity: The amount to transfer (nil for full stack) |
728 | + | |
729 | - | toCrafterSlot: The slot to move to. (nil will use any available slot(s)) |
729 | + | |
730 | ||
731 | - | return peripheral.call(fromInventoryName, "pushItems", crafterName, fromInventorySlot, quantity, toCrafterSlot) |
731 | + | |
732 | --[[ Usage: | |
733 | local inWater, onWater = utils.getWaterStatus() -- returns turtle position near water | |
734 | - | function network.sendItemsToTurtle(turtleName, fromInventoryName, fromInventorySlot, quantity, toTurtleSlot) |
734 | + | |
735 | - | --network.sendItemsToTurtle(turtleName, storageName, storageSlot, count, toTurtleSlot) |
735 | + | |
736 | ]] | |
737 | - | Move quantity of an item from one inventory to another. Turtles MUST use attachedInventory.pushItems() |
737 | + | |
738 | - | eg network.sendItemsToTurtle(turtleName, chestName, chestSlot, chestCount, 16) -- move to slot 16 so must be empty |
738 | + | |
739 | - | fromInventoryName: The name of the inventory to move items from. |
739 | + | |
740 | - | fromInventorySlot: The slot to move from. must be pre-determined for the item required |
740 | + | |
741 | - | quantity: The amount to transfer (nil for full stack) |
741 | + | |
742 | - | toTurtleSlot: The slot to move to. (nil will use any available slot(s)) |
742 | + | |
743 | T:turnRight(1) | |
744 | - | return peripheral.call(fromInventoryName, "pushItems", turtleName, fromInventorySlot, quantity, toTurtleSlot) |
744 | + | |
745 | if T:getBlockType("down"):find("water") ~= nil or T:getBlockType("down"):find("bubble") ~= nil then | |
746 | onWater = true | |
747 | - | function network.transferItem(fromInventoryName, toInventoryName, itemName, quantity, toSlot) |
747 | + | |
748 | return inWater, onWater | |
749 | - | Move a specific number of an item from one inventory to another |
749 | + | |
750 | - | fromInventoryName: The name of the chest/barrel/dropper to search. |
750 | + | |
751 | - | toInventoryName: The name of the receiving inventory (chest/barrel/dropper/smelter) |
751 | + | |
752 | - | itemName: The name of the item to find. |
752 | + | |
753 | - | toSlot: optional. nil picks any slot |
753 | + | |
754 | - | return: boolean success Whether or not the item was successfully moved to toSlot (or already existed there) |
754 | + | |
755 | if not turtle.back() then | |
756 | - | --T:saveToLog("network.transferItem(from: "..fromInventoryName..", to: "..toInventoryName..", itemName = "..itemName..", quantity = "..tostring(quantity)..", toSlot = "..tostring(toSlot)) |
756 | + | |
757 | - | local list = peripheral.call(fromInventoryName, "list") |
757 | + | |
758 | - | local size = peripheral.call(fromInventoryName, "size") |
758 | + | |
759 | - | --T:saveToLog("network.transferItem() size = "..size..", list = \n"..textutils.serialize(list)) |
759 | + | |
760 | - | local count, data = network.findItemCountInInventory(list, itemName) -- either nil or eg {{1, 64},{4, 22}} |
760 | + | |
761 | - | --T:saveToLog("network.transferItem() data = "..textutils.serialize(data, {compact = true})) |
761 | + | |
762 | - | local remaining = quantity -- eg 22 items needed |
762 | + | |
763 | ||
764 | - | if data == nil then -- Item not found |
764 | + | |
765 | - | return quantity -- return amount requested = nothing sent |
765 | + | |
766 | menuPromptColour = menuPromptColour or colors.white | |
767 | ||
768 | - | local fromSlot = 0 |
768 | + | |
769 | - | local count = 64 |
769 | + | |
770 | - | local available = 0 |
770 | + | |
771 | - | for _, v in pairs(data) do -- eg {1, 64},{2, 64} |
771 | + | |
772 | - | if v[2] < count and v[2] >= quantity then |
772 | + | |
773 | - | fromSlot = v[1] |
773 | + | |
774 | - | count = v[2] |
774 | + | |
775 | end | |
776 | - | available = available + v[2] |
776 | + | |
777 | function utils.move(R, blocks, reverse) | |
778 | if reverse == nil then | |
779 | - | if fromSlot > 0 then -- now have slot with min required quantity |
779 | + | |
780 | - | T:saveToLog("network.transferItem() from: "..fromInventoryName..", to: "..toInventoryName..", fromSlot: "..fromSlot..", toSlot: "..tostring(toSlot)..", quantity: "..tostring(quantity)) |
780 | + | |
781 | - | network.transferItems(fromInventoryName, toInventoryName, fromSlot, toSlot, quantity) |
781 | + | |
782 | - | return 0 |
782 | + | if R.subChoice == 2 then -- reverse direction |
783 | - | else -- available must be at least 1 |
783 | + | |
784 | - | for i = 1, #data do -- itreate all slots containg at least 1 item |
784 | + | |
785 | - | fromSlot = data[i][1] -- eg slot 1 |
785 | + | |
786 | - | local send = data[i][2] -- eg 10 items |
786 | + | |
787 | - | if remaining - send < 0 then -- eg 22 - 10 = 12 |
787 | + | |
788 | - | send = remaining |
788 | + | |
789 | - | remaining = 0 |
789 | + | |
790 | T:up(blocks) | |
791 | - | remaining = remaining - send-- eg remaining = 22 - 10 = 12 |
791 | + | |
792 | T:down(blocks) | |
793 | - | network.transferItems(fromInventoryName, toInventoryName, fromSlot, toSlot, send) |
793 | + | |
794 | - | if remaining <= 0 then -- all required items transferred |
794 | + | |
795 | - | return 0 |
795 | + | |
796 | end | |
797 | ||
798 | function utils.setStorageOptions() | |
799 | local storage = "" | |
800 | - | return remaining -- return remaining items to be found from a different inventory |
800 | + | |
801 | if T:getItemSlot("barrel") > 0 then | |
802 | storage = "barrel" | |
803 | - | function network.transferItems(fromInventoryName, toInventoryName, fromSlot, toSlot, quantity) |
803 | + | |
804 | end | |
805 | - | Move quantity of an item from one inventory to another |
805 | + | |
806 | - | fromInventoryName: The name of the inventory to move items from. |
806 | + | |
807 | - | toInventoryName: The name of the inventory to move items into. |
807 | + | |
808 | - | fromSlot: The slot to move from. must be pre-determined for the item required |
808 | + | |
809 | - | toSlot: The slot to move to. (nil will use any available slot(s)) |
809 | + | |
810 | - | quantity: The amount to transfer (nil for full stack) |
810 | + | |
811 | return storage, storageBackup | |
812 | - | T:saveToLog("network.transferItems(from: "..fromInventoryName..", to: "..toInventoryName..", fromSlot: "..fromSlot..", toSlot: "..tostring(toSlot)..", quantity: "..tostring(quantity)..")") |
812 | + | |
813 | - | return peripheral.call(fromInventoryName, "pushItems", toInventoryName, fromSlot, quantity, toSlot) |
813 | + | |
814 | local pp = utils.getPrettyPrint() | |
815 | ||
816 | - | function network.transferItemToTurtle(availableStorage, availableStorageKeys, turtleName, crafterData) |
816 | + | |
817 | - | -- network.transferItemToTurtle(<availableStorage>, data = {{1, 64},{4, 22}}, "crafter_01", <crafterData>) |
817 | + | |
818 | - | -- availableStorage.minecraft:chest_114 = {count = 86, data = {{1, 64},{4, 22}}, |
818 | + | |
819 | - | -- availableStorage.minecraft:chest_115 = {count = 1024, data = {{1, 64},{2, 64},{3, 64}, ... } |
819 | + | |
820 | - | -- crafterData = {{2,64}, {4,64}, {6,64}, {8,64}} 64 items in each of 4 slots in the crafter |
820 | + | |
821 | - | -- glitch? in crafter inventory, cannot add sequentially to existing items. |
821 | + | |
822 | - | -- send to turtle slot first, then transfer |
822 | + | |
823 | - | T:saveToLog("network.transferItemToTurtle(availableStorage = "..textutils.serialise(availableStorage, {compact = true}).. |
823 | + | |
824 | - | "\navailableStorageKeys = "..textutils.serialise(availableStorageKeys, {compact = true}).. |
824 | + | |
825 | - | "\n"..turtleName..", crafterData = "..textutils.serialise(crafterData, {compact = true})) |
825 | + | |
826 | T:go("C1", false, 0, false, R.useBlockType) | |
827 | - | local total = 0 |
827 | + | |
828 | - | local numSlots = 0 |
828 | + | |
829 | - | local sent = 0 |
829 | + | |
830 | - | for _, v in ipairs(crafterData) do -- how many items required in total? |
830 | + | |
831 | - | total = total + v[2] -- how many slots does it go in |
831 | + | |
832 | - | numSlots = numSlots + 1 |
832 | + | |
833 | if l == R.length and R.data == "house" then | |
834 | - | for _, availableStorageKey in ipairs(availableStorageKeys) do -- eg {minecraft:chest_114, minecraft:chest_115} |
834 | + | |
835 | - | local storageName = availableStorageKey -- eg minecraft:chest_114 |
835 | + | |
836 | - | local object = availableStorage[storageName] -- availableStorage.minecraft:chest_114 = {count = 90, data = {{14,64},{15,26}} |
836 | + | |
837 | - | local storageData = object.data -- eg data = {{14,64},{15,26}} |
837 | + | |
838 | - | local storageCount = object.count -- eg count = 90 |
838 | + | |
839 | - | for _, crafterSlotData in ipairs(crafterData) do -- eg {{2,22}, {4,22}, {6,22}, {8,22}} -> iteration 1 = {2, 22} iterate crafter slots to be filled |
839 | + | |
840 | - | local toCrafterSlot = crafterSlotData[1] -- eg slot 2 in turtle |
840 | + | |
841 | - | local amountToSend = crafterSlotData[2] -- eg place 22 items in slot 2 |
841 | + | |
842 | - | T:saveToLog("storageData = "..textutils.serialise(storageData, {compact = true})) |
842 | + | |
843 | - | T:saveToLog("crafterSlotData = "..textutils.serialise(crafterSlotData, {compact = true})) |
843 | + | |
844 | - | for i = 1, #storageData do -- {{14,64},{15,26}} |
844 | + | |
845 | - | local slotData = storageData[i] -- {14,64} |
845 | + | |
846 | - | local availableToSend = slotData[2] -- 64 |
846 | + | |
847 | - | local fromStorageSlot = slotData[1] -- 14 |
847 | + | |
848 | - | local confirmedSent = 0 |
848 | + | |
849 | end | |
850 | - | T:saveToLog("i = "..i..", slotData = "..textutils.serialise(slotData, {compact = true})) |
850 | + | |
851 | - | if availableToSend >= amountToSend then |
851 | + | |
852 | - | T:saveToLog("availableToSend ("..availableToSend..") >= amountToSend: ("..amountToSend.."), current value of sent = "..sent) |
852 | + | |
853 | - | T:saveToLog("?confirmedSent = peripheral.call("..storageName..", 'pushItems', "..turtleName.. |
853 | + | |
854 | - | ", from slot "..fromStorageSlot..", amountToSend = ".. |
854 | + | |
855 | - | amountToSend..", to turtle slot "..toCrafterSlot) |
855 | + | |
856 | - | confirmedSent = peripheral.call(storageName, "pushItems", turtleName, fromStorageSlot, amountToSend, toCrafterSlot) |
856 | + | |
857 | - | sent = sent + confirmedSent |
857 | + | |
858 | - | T:saveToLog("verified confirmedSent = "..confirmedSent..", sent = "..sent) |
858 | + | |
859 | - | slotData[2] = slotData[2] - confirmedSent |
859 | + | |
860 | - | crafterSlotData[2] = 0 |
860 | + | |
861 | - | T:saveToLog("slotData[2] = "..slotData[2]..", crafterSlotData[2] = "..crafterSlotData[2]) |
861 | + | |
862 | T:turnRight(2) -- rotate 180 | |
863 | - | T:saveToLog("availableToSend ("..availableToSend..") < amountToSend: ("..amountToSend.."), current value of sent = "..sent) |
863 | + | |
864 | - | T:saveToLog("?confirmedSent = peripheral.call("..storageName..", 'pushItems', "..turtleName.. |
864 | + | |
865 | - | ", from slot "..fromStorageSlot..", availableToSend = ".. |
865 | + | |
866 | - | availableToSend..", to turtle slot "..toCrafterSlot) |
866 | + | |
867 | - | -- taking items from multiple storage slots requires loading into turtle first |
867 | + | |
868 | - | confirmedSent = peripheral.call(storageName, "pushItems", turtleName, fromStorageSlot, availableToSend, toCrafterSlot) |
868 | + | |
869 | - | sent = sent + confirmedSent |
869 | + | |
870 | - | T:saveToLog("verified confirmedSent = "..confirmedSent..", sent = "..sent) |
870 | + | |
871 | - | amountToSend = amountToSend - confirmedSent |
871 | + | |
872 | - | slotData[2] = slotData[2] - confirmedSent |
872 | + | |
873 | - | crafterSlotData[2] = amountToSend |
873 | + | |
874 | - | T:saveToLog("slotData[2] = "..slotData[2]..", crafterSlotData[2] = "..crafterSlotData[2]) |
874 | + | |
875 | T:go("U3F1R2") | |
876 | end | |
877 | - | if crafterSlotData[2] == 0 then |
877 | + | |
878 | - | T:saveToLog("crafterSlotData[2]("..crafterSlotData[2]..") == 0: breaking\n") |
878 | + | |
879 | - | break -- already sent correct amount |
879 | + | |
880 | elseif remaining == 2 then | |
881 | lib.doubleLayer(R) | |
882 | end | |
883 | - | if sent >= total then |
883 | + | |
884 | - | T:saveToLog("sent("..sent..") >= total ("..total.."): breaking\n") |
884 | + | |
885 | while turtle.down() do end | |
886 | end | |
887 | ||
888 | return {} | |
889 | - | return sent |
889 | + | |
890 | ||
891 | local function buildStructure(R) | |
892 | - | function network.pullItems(fromName, fromSlot, quantity, toName, toSlot) |
892 | + | |
893 | - | quantity = quantity or 1 |
893 | + | |
894 | - | toSlot = toSlot or nil |
894 | + | |
895 | - | if type(fromName) == "table" then -- already a wrapped peripheral |
895 | + | |
896 | - | fromName = peripheral.getName(fromName) |
896 | + | |
897 | T:down(1) | |
898 | - | if type(toName) == "string" then |
898 | + | |
899 | - | toName = peripheral.wrap(toName) |
899 | + | |
900 | local buildHeight = R.height | |
901 | - | toName.pullItems(fromName, fromSlot, quantity, toSlot) |
901 | + | |
902 | local width = R.width | |
903 | local length = R.length | |
904 | - | function network.updateList(storageType) |
904 | + | |
905 | - | local output = "" |
905 | + | |
906 | - | if storageType == "barrel" then |
906 | + | |
907 | - | output = textutils.serialize(barrelItems) -- serialise to json ready to write to file |
907 | + | |
908 | - | elseif storageType == "chest" then |
908 | + | |
909 | - | output = textutils.serialize(chestItems) -- serialise to json ready to write to file |
909 | + | |
910 | end | |
911 | - | local fileName = storageType.."Items.lua" -- barrelList.lua or chestList.lua |
911 | + | |
912 | - | local outputHandle = fs.open(fileName, "w") -- open file |
912 | + | |
913 | - | outputHandle.writeLine("return") -- start file with return |
913 | + | |
914 | - | outputHandle.write(output) -- add serialised table |
914 | + | |
915 | - | outputHandle.close() -- close file |
915 | + | |
916 | buildWall(R) | |
917 | ||
918 | - | function network.wrapModem(R, storageType) |
918 | + | |
919 | - | --[[To move turtle inventory items use the target peripheral: |
919 | + | |
920 | - | local modem = peripheral.wrap("front") -- wrap modem next to turtle (beware crafting table!) |
920 | + | |
921 | - | local turtleName = modem.getNameLocal() -- get name of the turtle |
921 | + | |
922 | - | local barrel = peripheral.find("barrel") -- find barrel name you want to receive goods |
922 | + | |
923 | - | barrel.pushItems(turtleName, 1, 1) -- push items FROM turtle to barrel pushItems(toName, fromSlot , limit , toSlot) |
923 | + | |
924 | - | barrel.pullItems(turtleName, fromSlot , limit , toSlot) |
924 | + | |
925 | lib.goDown(R) | |
926 | - | local modem = peripheral.find("modem") -- find modem |
926 | + | |
927 | - | if modem == nil then |
927 | + | |
928 | - | return nil, "Modem not found" |
928 | + | |
929 | height = height - R.height -- 1, 2 or 3 | |
930 | - | local turtleName = modem.getNameLocal() -- get name of the turtle |
930 | + | |
931 | - | local rawStorage = nil -- peripheral find can return duplicate values |
931 | + | |
932 | - | if storageType:find("barrel") ~= nil then |
932 | + | |
933 | - | rawStorage = {peripheral.find("minecraft:barrel")} |
933 | + | |
934 | - | elseif storageType:find("chest") ~= nil then |
934 | + | |
935 | - | rawStorage = {peripheral.find("minecraft:chest")} |
935 | + | |
936 | R.length = length | |
937 | - | local storage = {} |
937 | + | |
938 | - | local names = {} |
938 | + | |
939 | - | for k, value in ipairs(rawStorage) do |
939 | + | |
940 | - | local name = peripheral.getName(value) |
940 | + | |
941 | - | if not utils.tableContains(names, name, true) then -- use exact match as checking peripherals |
941 | + | |
942 | - | table.insert(storage, value) |
942 | + | |
943 | - | table.insert(names, name) |
943 | + | |
944 | return {} | |
945 | end | |
946 | - | return storage, turtleName, names |
946 | + | |
947 | local function buildGableRoof(R) | |
948 | --[[ | |
949 | - | function utils.assessFarm(R) |
949 | + | |
950 | - | -- sets R.networkFarm and R.mysticalAgriculture |
950 | + | |
951 | - | menu.colourPrint("Assessing farm properties...", colors.yellow) |
951 | + | |
952 | - | --local storage = true |
952 | + | |
953 | - | for turns = 1, 4 do |
953 | + | |
954 | | down | |
955 | - | local itemAhead = T:getBlockType("forward") |
955 | + | |
956 | - | if itemAhead:find("modem") ~= nil then |
956 | + | |
957 | - | if not R.networkFarm then -- prevents repeated text display |
957 | + | |
958 | - | R.networkFarm = true |
958 | + | |
959 | - | menu.colourPrint("Network storage in use.", colors.magenta) |
959 | + | |
960 | for i = 1, R.length + 2 do | |
961 | if R.useBlockType:find("stairs") ~= nil then | |
962 | - | if itemAhead:find("mysticalagriculture") ~= nil then |
962 | + | T:place("stairs", 0, "up") |
963 | - | R.mysticalAgriculture = true |
963 | + | |
964 | - | menu.colourPrint("Mystical Agriculture deployed.", colors.lime) |
964 | + | |
965 | end | |
966 | if i < R.length + 2 then | |
967 | - | sleep(1.5) |
967 | + | |
968 | T:go("L1F1R1") | |
969 | else | |
970 | T:go("R1F1L1") | |
971 | end | |
972 | - | function utils.assessTreeFarm(R) |
972 | + | |
973 | end | |
974 | end | |
975 | - | function lib.getSaplingType(R, blockType) |
975 | + | |
976 | - | if blockType == "minecraft:mangrove_log" then |
976 | + | |
977 | - | R.logType = "mangrove" |
977 | + | |
978 | - | R.useBlockType ="mangrove_propagule" |
978 | + | |
979 | for w = 1, width do | |
980 | - | local parts = T:getNames(blockType) |
980 | + | |
981 | - | if parts[2] == "dark" then |
981 | + | |
982 | - | R.logType = "dark_oak" |
982 | + | |
983 | - | parts[2] = "dark_oak" |
983 | + | |
984 | else | |
985 | - | R.logType = parts[2] -- eg "oak" |
985 | + | |
986 | end | |
987 | end | |
988 | - | R.useBlockType = parts[2].."_sapling" -- eg "oak_sapling" |
988 | + | |
989 | if h < R.height then | |
990 | if outward then | |
991 | - | turtle.turnLeft() |
991 | + | |
992 | else | |
993 | - | return R |
993 | + | |
994 | end | |
995 | end | |
996 | width = width - 2 | |
997 | - | if blockType:find("modem") ~= nil then |
997 | + | |
998 | - | R.networkFarm = true |
998 | + | |
999 | return outward | |
1000 | - | if blockType:find("polished") == nil then |
1000 | + | |
1001 | - | R.message = "Not on modem or polished. Check position" |
1001 | + | |
1002 | local outward = true | |
1003 | -- go to centre of end wall if odd no, or half width if even | |
1004 | R.height = math.floor(R.width / 2) | |
1005 | - | if R.networkFarm then |
1005 | + | |
1006 | ||
1007 | utils.goBack(1) | |
1008 | - | T:saveToLog("T:forward(1): blockType = "..blockType) |
1008 | + | |
1009 | - | if blockType:find("log") ~= nil then |
1009 | + | |
1010 | - | R = lib.getSaplingType(R, blockType) |
1010 | + | |
1011 | - | elseif blockType:find("barrel") ~= nil then |
1011 | + | |
1012 | - | T:go("R2F2") |
1012 | + | |
1013 | T:down(1) | |
1014 | - | if blockType:find("log") ~= nil then |
1014 | + | |
1015 | - | R = lib.getSaplingType(R, blockType) |
1015 | + | |
1016 | end | |
1017 | - | else -- if in correct position water is 2 blocks below |
1017 | + | |
1018 | T:go("F"..R.height + 2 .."R2U"..R.height) | |
1019 | else | |
1020 | - | if blockType:find("water") == nil then |
1020 | + | |
1021 | - | R.message = "No modem below. Check position" |
1021 | + | |
1022 | for h = 1, R.height + 1 do -- place tiles on right side of roof | |
1023 | lib.placeRoof(R, outward) | |
1024 | - | turtle.up() |
1024 | + | |
1025 | - | utils.goBack(1) |
1025 | + | |
1026 | - | T:go("R1F1") |
1026 | + | |
1027 | outward = not outward | |
1028 | - | if blockType:find("log") ~= nil then |
1028 | + | |
1029 | - | R = lib.getSaplingType(R, blockType) |
1029 | + | |
1030 | -- gable ends | |
1031 | - | R.message = "Unable to determine location. Check position" |
1031 | + | |
1032 | - | return R |
1032 | + | |
1033 | else | |
1034 | T:go("F1L1U1") | |
1035 | end | |
1036 | - | R.message = "Unable to determine location. Check position" |
1036 | + | |
1037 | - | return R |
1037 | + | |
1038 | if outward then | |
1039 | T:go("R1F"..R.height - 1 .."R1") | |
1040 | else | |
1041 | T:go("L1F"..R.height - 1 .."L1") | |
1042 | - | return R -- sets R.networkFarm and R.useBlockType to sapling type |
1042 | + | |
1043 | outward = not outward | |
1044 | outward = lib.placeGable(R, outward) | |
1045 | if isOdd then | |
1046 | if outward then | |
1047 | T:go("L1F1R1U2F1") | |
1048 | else | |
1049 | T:go("R1F1L1U2F1") | |
1050 | end | |
1051 | for i = 1, R.length do | |
1052 | T:go("C2F1", false, 0, false) | |
1053 | end | |
1054 | for i = 1, R.length + 2 do | |
1055 | utils.goBack(1) | |
1056 | T:place("slab", 0, "forward") | |
1057 | end | |
1058 | end | |
1059 | while turtle.down() do end | |
1060 | ||
1061 | return {} | |
1062 | end | |
1063 | ||
1064 | local function buildPitchedRoof(R) | |
1065 | --[[ | |
1066 | stairs placement: | |
1067 | _| up | |
1068 | ||
1069 | T L forward | |
1070 | _ | |
1071 | | down | |
1072 | ||
1073 | ]] | |
1074 | local lib = {} | |
1075 | ||
1076 | function lib.placeRoofSection(length) | |
1077 | -- starts facing centre of building | |
1078 | for i = 1, length do | |
1079 | if i < length then | |
1080 | if R.useBlockType:find("stairs") ~= nil then | |
1081 | T:place("stairs", 0, "up") | |
1082 | else | |
1083 | T:go("C0", false, 0, false, R.useBlockType) | |
1084 | end | |
1085 | T:go("L1F1R1") | |
1086 | end | |
1087 | end | |
1088 | -- ends facing centre of building | |
1089 | end | |
1090 | ||
1091 | function lib.placeRoof(R, width, length) | |
1092 | - | function utils.checkFarmPosition(R) |
1092 | + | |
1093 | - | local discovered = "" |
1093 | + | |
1094 | - | local success, storage, detected = false, "", 0 |
1094 | + | |
1095 | T:go("R1") | |
1096 | - | T:saveToLog("Checking position "..blockType.. " down") |
1096 | + | |
1097 | - | if blockType:find("water") ~= nil then -- over water, ? facing E (crops) |
1097 | + | |
1098 | - | -- network: E = __modem_, N = _modem__, W = modem___, S = ___modem |
1098 | + | |
1099 | - | -- storage: E = _chestchest_, N = chestchest__, W = chest__chest, S = __chestchest |
1099 | + | |
1100 | - | -- storage: E = _barrelbarrel_, N = barrelbarrel__, W = barrel__barrel, S = __barrelbarrel |
1100 | + | |
1101 | - | T:saveToLog("? over water = true") |
1101 | + | |
1102 | -- add slabs at top | |
1103 | - | success, storage = utils.isStorage("forward") -- true/false, chest, barrel, modem / "" |
1103 | + | |
1104 | - | local itemAhead = T:getBlockType("forward") |
1104 | + | |
1105 | T:forward(length - 3) | |
1106 | - | discovered = discovered .. storage |
1106 | + | |
1107 | - | if storage == "modem" then |
1107 | + | T:place("slab", 0, "forward") |
1108 | - | R.networkFarm = true |
1108 | + | |
1109 | end | |
1110 | T:place("slab", 0, "forward") | |
1111 | - | discovered = discovered .. "_" |
1111 | + | |
1112 | T:place("slab", 0, "forward") | |
1113 | - | if itemAhead:find("mysticalagriculture") ~= nil then |
1113 | + | |
1114 | - | R.mysticalAgriculture = true |
1114 | + | |
1115 | utils.goBack(1) | |
1116 | end | |
1117 | --[[ | |
1118 | - | T:saveToLog("Storage blocks found:"..discovered) |
1118 | + | |
1119 | - | if R.networkFarm then |
1119 | + | |
1120 | - | if discovered == "modemmodem__" then |
1120 | + | |
1121 | - | T:turnLeft(1) |
1121 | + | |
1122 | - | elseif discovered == "modem__modem" then |
1122 | + | |
1123 | - | T:turnLeft(2) |
1123 | + | |
1124 | - | elseif discovered == "__modemmodem" then |
1124 | + | |
1125 | - | T:turnRight(1) |
1125 | + | |
1126 | if width is odd, ignore top layer as is only 1 block wide | |
1127 | - | R.ready = true |
1127 | + | |
1128 | local isWidthOdd, isLengthOdd, width, length = false, false, 0, 0 | |
1129 | - | if discovered == "barrelbarrel__" or |
1129 | + | |
1130 | - | discovered == "barrelchest__" or |
1130 | + | |
1131 | - | discovered == "chestchest__" then |
1131 | + | |
1132 | - | T:turnLeft(1) |
1132 | + | |
1133 | - | elseif discovered == "barrel__barrel" or discovered == "chest__chest" then |
1133 | + | |
1134 | - | T:turnLeft(2) |
1134 | + | |
1135 | - | elseif discovered == "__barrelbarrel" or discovered == "__chestchest" then |
1135 | + | |
1136 | - | T:turnRight(1) |
1136 | + | |
1137 | width = width + 2 | |
1138 | - | R.ready = true |
1138 | + | |
1139 | utils.goBack(1) | |
1140 | - | end -- else not over water |
1140 | + | |
1141 | utils.goBack(1) | |
1142 | - | T:saveToLog("utils.checkFarmPosition(R) return R = "..textutils.serialise(R, {compact = true})) |
1142 | + | |
1143 | - | return R -- now facing crops, R.ready = true/false, R.networkFarm = true/false |
1143 | + | |
1144 | while turtle.down() do end | |
1145 | ||
1146 | return {} | |
1147 | - | local fuelNeeded = quantity - turtle.getFuelLevel() -- eg 600 |
1147 | + | |
1148 | ||
1149 | local function clearAndReplantTrees() -- 25 | |
1150 | --[[ clear all trees in a rectangle area defined by walls, fences or non-dirt blocks | |
1151 | replant with same type of sapling. If original tree 2 blocks wide, replant 4 if possible. ]] | |
1152 | ||
1153 | local lib = {} | |
1154 | ||
1155 | function lib.getSaplingFromLogType(log) | |
1156 | --[[ get type of sapling to plant from log type ]] | |
1157 | if log:find("oak") ~= nil then | |
1158 | return "minecraft:oak_sapling" | |
1159 | elseif log:find("spruce") ~= nil then | |
1160 | - | -- blockType, data |
1160 | + | |
1161 | - | local blockType = T:getBlockType(direction) |
1161 | + | |
1162 | return "minecraft:birch_sapling" | |
1163 | elseif log:find("jungle") ~= nil then | |
1164 | return "minecraft:jungle_sapling" | |
1165 | elseif log:find("acacia") ~= nil then | |
1166 | return "minecraft:acacia_sapling" | |
1167 | elseif log:find("dark_oak") ~= nil then | |
1168 | return "minecraft:dark_oak_sapling" | |
1169 | end | |
1170 | return "sapling" | |
1171 | end | |
1172 | ||
1173 | function lib.plantSapling(sapling, double) | |
1174 | --[[ plant sapling(s) ]] | |
1175 | if sapling == "" or sapling == nil then sapling = "sapling" end | |
1176 | T:up(1) | |
1177 | - | function utils.convertEssence(R) |
1177 | + | |
1178 | - | -- R.subChoice = 1 to 5 |
1178 | + | |
1179 | - | -- R.size = quantity |
1179 | + | |
1180 | - | -- 1 = inferium to prudentium |
1180 | + | |
1181 | - | -- 2 = prudentium to tertium |
1181 | + | |
1182 | - | -- 3 = Tertium to Imperium |
1182 | + | |
1183 | - | -- 4 = Imperium to Supremium |
1183 | + | T:place(sapling, -1, "down") |
1184 | - | -- 5 = Supremium to Insanium |
1184 | + | |
1185 | end | |
1186 | T:forward(1) -- above pre-planted sapling | |
1187 | - | function lib.getCrystal() |
1187 | + | |
1188 | - | local turtleSlot, turtleCount = 0, 0 |
1188 | + | if not T:place(sapling, -1, "down") then |
1189 | - | if utils.isStorage("up") then |
1189 | + | T:place("sapling", -1, "down") |
1190 | - | turtle.select(2) |
1190 | + | |
1191 | - | turtle.suckUp() |
1191 | + | |
1192 | else | |
1193 | - | turtleSlot = T:getItemSlot("crystal") |
1193 | + | if not T:place(sapling, -1, "down") then |
1194 | - | if turtleSlot == 0 then |
1194 | + | T:place("sapling", -1, "down") |
1195 | - | turtleSlot, turtleCount = network.getItemFromNetwork("chest", "infusion_crystal", 1) |
1195 | + | |
1196 | end | |
1197 | - | if turtleSlot > 0 then |
1197 | + | |
1198 | - | turtle.select(turtleSlot) |
1198 | + | |
1199 | - | turtle.transferTo(2) |
1199 | + | |
1200 | function lib.suck() | |
1201 | --[[ Collect saplings, sticks and apples ]] | |
1202 | turtle.select(1) | |
1203 | turtle.suck() | |
1204 | turtle.suckUp() | |
1205 | turtle.suckDown() | |
1206 | - | function lib.loadCrafter(crafterName) |
1206 | + | |
1207 | - | -- up to 64 essences stored in turtle slots 2, 4, 6, 8 |
1207 | + | |
1208 | - | local slots = {2, 4, 6, 8} |
1208 | + | |
1209 | - | for _, slot in ipairs(slots) do -- drop each slot contents into crafter ? slot 1 |
1209 | + | |
1210 | if direction == "r" then | |
1211 | - | turtle.drop() |
1211 | + | |
1212 | - | peripheral.call(crafterName, "pushItems", crafterName, 1, nil, slot) -- move to correct place |
1212 | + | |
1213 | else | |
1214 | T:turnLeft(1) | |
1215 | direction = "r" | |
1216 | - | function lib.loadTurtle(availableStorage, availableStorageKeys, turtleName, essence, loaded) |
1216 | + | |
1217 | - | -- collect essence as above and place in minecraft:crafter slots 2, 4, 6, 8 |
1217 | + | |
1218 | - | local crafterData = {{2, loaded}, {4, loaded}, {6, loaded}, {8, loaded}} -- eg 64 items in each of 4 slots in the crafter |
1218 | + | |
1219 | - | network.transferItemToTurtle(availableStorage, availableStorageKeys, turtleName, crafterData) |
1219 | + | |
1220 | function lib.emptyInventory(blockTypeD) | |
1221 | --[[ Empty all except 32 of each sapling and 1 chest ]] | |
1222 | - | function lib.runCrafter(crafterName, count) |
1222 | + | |
1223 | - | -- can only craft once, then crystal + output is returned to turtle |
1223 | + | |
1224 | - | -- repeat process count times |
1224 | + | |
1225 | - | -- drop crystal into crafter, move to slot 5 |
1225 | + | |
1226 | -- empty logs, apples, sticks and all but 1 stack of each sapling type | |
1227 | - | local slot = T:getItemSlot("crystal") |
1227 | + | |
1228 | - | if slot > 0 then |
1228 | + | |
1229 | else | |
1230 | - | turtle.drop() |
1230 | + | |
1231 | - | network.moveItem(crafterName, "crystal", 5) |
1231 | + | |
1232 | - | for i = 1, 3 do |
1232 | + | |
1233 | - | rs.setAnalogOutput("front",15) |
1233 | + | |
1234 | - | sleep(0.1) |
1234 | + | |
1235 | - | rs.setAnalogOutput("front", 0) |
1235 | + | |
1236 | if blockTypeD == nil then | |
1237 | blockTypeD = T:getBlockType("down") | |
1238 | end | |
1239 | - | while turtle.suck() do end |
1239 | + | |
1240 | T:down(1) | |
1241 | lib.suck() | |
1242 | - | function lib.storeCrystal() |
1242 | + | |
1243 | - | if utils.isStorage("up") then |
1243 | + | |
1244 | - | T:dropItem("crystal", "up") |
1244 | + | |
1245 | end | |
1246 | - | network.sendItemToNetworkStorage(R, "chest", "crystal", 0) -- empty turtle to storage chests |
1246 | + | |
1247 | function lib.moveForward() | |
1248 | --[[ Move forward 1 block only, go down to ground while air or leaves below ]] | |
1249 | local blockTypeF = T:getBlockType("forward") | |
1250 | - | function lib.storeOutput() |
1250 | + | |
1251 | - | if utils.isStorage("up") then |
1251 | + | |
1252 | - | T:dropItem("crystal", "up") |
1252 | + | |
1253 | T:dig("up") -- remove leaves / low branches above to allow space for player | |
1254 | - | network.sendItemToNetworkStorage(R, "chest", "all", 0) -- empty turtle to storage chests |
1254 | + | |
1255 | blockTypeD = lib.moveDown() | |
1256 | if not lib.emptyInventory(blockTypeD) then -- check if above a corner chest / barrel | |
1257 | - | function lib.getStorageData(essence) |
1257 | + | |
1258 | - | local _, turtleName, storageNames = network.wrapModem(R, "chests") -- _, turtleName, list of chest names |
1258 | + | |
1259 | - | if turtleName == "Modem not found" then return 0, nil, nil, turtleName end |
1259 | + | |
1260 | - | local availableStorage = {} |
1260 | + | |
1261 | - | local availableStorageKeys = {} |
1261 | + | |
1262 | - | local total = 0 |
1262 | + | |
1263 | - | for _, storageName in pairs(storageNames) do |
1263 | + | |
1264 | - | local storageCount, storageData = network.findItemCountInInventory(storageName, essence) -- eg 86, {{1, 64},{4, 22}} |
1264 | + | |
1265 | - | if storageCount > 0 then -- eg 86: storage has some items |
1265 | + | |
1266 | - | T:saveToLog("storageCount = "..storageCount) |
1266 | + | |
1267 | - | availableStorage[storageName] = {} |
1267 | + | |
1268 | - | availableStorage[storageName].count = storageCount |
1268 | + | |
1269 | - | availableStorage[storageName].data = storageData |
1269 | + | |
1270 | - | table.insert(availableStorageKeys, storageName) |
1270 | + | |
1271 | - | total = total + storageCount |
1271 | + | |
1272 | while blockTypeF:find("dirt") ~= nil or | |
1273 | blockTypeF:find("grass_block") ~= nil or | |
1274 | T:isVegetation(blockTypeF) do -- go up while dirt, grass-block or any vegetation in front | |
1275 | - | return total, availableStorage, availableStorageKeys, turtleName |
1275 | + | |
1276 | blockTypeF = T:getBlockType("forward") | |
1277 | - | availableStorage.minecraft:chest_114 = {count = 86, data = {{1, 64},{4, 22}}, |
1277 | + | |
1278 | - | availableStorage.minecraft:chest_115 = {count = 1024, data = {{1, 64},{2, 64},{3, 64}, ... } |
1278 | + | |
1279 | return T:getBlockType("forward") | |
1280 | elseif blockTypeF:find("leaves") ~= nil then | |
1281 | T:dig("forward") | |
1282 | - | local essences = {"mysticalagriculture:inferium_essence", |
1282 | + | |
1283 | - | "mysticalagriculture:prudentium_essence", |
1283 | + | |
1284 | - | "mysticalagriculture:tertium_essence", |
1284 | + | |
1285 | - | "mysticalagriculture:imperium_essence", |
1285 | + | |
1286 | - | "mysticalagriculture:supremium_essence", |
1286 | + | |
1287 | - | "mysticalagriculture:insanium_essence"} |
1287 | + | |
1288 | function lib.harvestTree(blockTypeF) | |
1289 | - | local message = network.loadStorageLists() |
1289 | + | |
1290 | - | if message ~= nil then return {message} end |
1290 | + | |
1291 | - | local essence = essences[R.subChoice] |
1291 | + | |
1292 | - | local missing = "" |
1292 | + | |
1293 | - | local crafter = peripheral.find("minecraft:crafter") |
1293 | + | |
1294 | - | local crafterName = "" |
1294 | + | |
1295 | - | local completed = 0 |
1295 | + | |
1296 | - | if R.size > 0 then |
1296 | + | |
1297 | - | R.size = math.floor(R.size / 4) * 4 |
1297 | + | |
1298 | - | if R.size == 0 then R.size = 4 end |
1298 | + | |
1299 | local success = true | |
1300 | - | if crafter == nil then |
1300 | + | |
1301 | - | return {"No crafter found"} |
1301 | + | |
1302 | if not success then -- did not move forwards, block in the way: either log, dirt/grass, border block or vegetation | |
1303 | - | crafterName = peripheral.getName(crafter) |
1303 | + | |
1304 | - | T:saveToLog("utils.convertEssence started using "..essence..", quantity = "..R.size ) |
1304 | + | |
1305 | - | while turtle.suck() do end -- empty crafter |
1305 | + | |
1306 | - | lib.storeOutput() -- empty turtle to storage chests, (except crystal if storage above) |
1306 | + | |
1307 | - | if not lib.getCrystal() then |
1307 | + | |
1308 | - | return {"Failed: missing infusion crystal"} |
1308 | + | |
1309 | blockTypeF = lib.moveUp(blockTypeF) -- move up until leaves/log/air | |
1310 | - | lib.storeCrystal() |
1310 | + | |
1311 | - | local totalInStorage, availableStorage, availableStorageKeys, turtleName = lib.getStorageData(essence) |
1311 | + | |
1312 | - | if totalInStorage < 4 then |
1312 | + | |
1313 | - | return {"Only "..totalInStorage.." ".. essence:sub(20).." available"} |
1313 | + | |
1314 | end | |
1315 | - | -- can only transfer full amount direct to crafter |
1315 | + | |
1316 | - | -- if a chest has 32 items in 1 slot and 32 in another Slot |
1316 | + | |
1317 | - | -- these have to be sent into the turtle first, dropped into crafter slot 1 and moved to correct position |
1317 | + | |
1318 | - | totalInStorage = math.floor(totalInStorage / 4) * 4 |
1318 | + | |
1319 | - | if R.size == 0 then -- process all |
1319 | + | |
1320 | - | T:saveToLog("initial call lib.loadTurtle("..turtleName..", "..totalInStorage.." essence") |
1320 | + | |
1321 | - | local processed = 0 |
1321 | + | |
1322 | - | local loaded = 0 |
1322 | + | |
1323 | function lib.isBorder(blockType) | |
1324 | - | while totalInStorage > 0 do -- use ALL stored essence |
1324 | + | |
1325 | - | if totalInStorage - 256 > 0 then |
1325 | + | |
1326 | - | loaded = 64 |
1326 | + | |
1327 | end | |
1328 | - | loaded = totalInStorage / 4 |
1328 | + | |
1329 | return false, "" | |
1330 | - | lib.loadTurtle(availableStorage, availableStorageKeys, turtleName, essence, loaded) |
1330 | + | |
1331 | - | lib.loadCrafter(crafterName) |
1331 | + | |
1332 | - | lib.getCrystal() |
1332 | + | |
1333 | - | processed = processed + loaded |
1333 | + | |
1334 | - | totalInStorage = totalInStorage - loaded * 4 |
1334 | + | |
1335 | - | lib.runCrafter(crafterName, loaded) |
1335 | + | |
1336 | - | lib.storeOutput() |
1336 | + | |
1337 | end | |
1338 | - | elseif R.size <= 64 then |
1338 | + | |
1339 | - | local loaded = math.min(R.size, totalInStorage) -- process requested or available if less |
1339 | + | |
1340 | - | if loaded > 0 then |
1340 | + | |
1341 | - | lib.loadTurtle(availableStorage, availableStorageKeys, turtleName, essence, loaded) |
1341 | + | |
1342 | - | lib.loadCrafter(crafterName) |
1342 | + | |
1343 | - | lib.getCrystal() |
1343 | + | |
1344 | - | lib.runCrafter(crafterName, loaded) |
1344 | + | |
1345 | - | lib.storeOutput() |
1345 | + | |
1346 | end | |
1347 | - | else -- amount > 64 |
1347 | + | |
1348 | - | local processed = 0 |
1348 | + | |
1349 | - | local loaded = 0 |
1349 | + | |
1350 | - | while totalInStorage > 0 and processed < R.size do -- stop if run out of essence, or reached target |
1350 | + | |
1351 | - | if totalInStorage - 256 > 0 and R.size - processed >= 64 then |
1351 | + | |
1352 | - | loaded = 64 |
1352 | + | |
1353 | - | elseif totalInStorage - 256 > 0 and R.size - processed > 0 then |
1353 | + | |
1354 | - | loaded = R.size - processed |
1354 | + | |
1355 | else | |
1356 | - | lib.loadTurtle(availableStorage, availableStorageKeys, turtleName, essence, loaded) |
1356 | + | |
1357 | - | lib.loadCrafter(crafterName) |
1357 | + | |
1358 | - | lib.getCrystal() |
1358 | + | |
1359 | - | processed = processed + loaded |
1359 | + | |
1360 | - | totalInStorage = totalInStorage - loaded * 4 |
1360 | + | |
1361 | - | lib.runCrafter(crafterName, loaded) |
1361 | + | |
1362 | - | lib.storeOutput() |
1362 | + | |
1363 | --[[ assume started after reset. if log above harvest tree else return to ground. Find starting corner]] | |
1364 | local blockType = T:getBlockType("up") -- dig any logs above, return to ground | |
1365 | - | lib.storeOutput() |
1365 | + | |
1366 | if blockType:find("log") ~= nil then -- originally felling a tree so complete it | |
1367 | - | return {"success"} |
1367 | + | |
1368 | local double = T:harvestTree(false, false, "up") -- assume single tree, will auto-discover | |
1369 | lib.plantSapling(log, double) | |
1370 | else -- no log above so go downm | |
1371 | - | function utils.craftItem(R) |
1371 | + | |
1372 | - | local message = network.loadStorageLists() -- initialises or creates lists of where an item can be found: GLOBAL LISTS! |
1372 | + | |
1373 | - | if message ~= nil then return {message} end |
1373 | + | |
1374 | - | T:saveToLog("call network.emptyInventory(R, {'sapling', 'propagule', 'dirt', 'crafting'}, {'all'}, true)") |
1374 | + | |
1375 | - | network.emptyInventory(R, {"sapling", "propagule", "dirt", "crafting"}, {"all"}, true) -- 2 lists, one for barrels, one for chests |
1375 | + | |
1376 | - | T:saveToLog("\ncall network.getItemFromNetwork('barrel', 'minecraft:dirt', 169)") |
1376 | + | |
1377 | - | --network.getItemFromNetwork(storageType, itemRequired, countRequired, toTurtleSlot, ignoreStock) |
1377 | + | |
1378 | - | local turtleSlot, turtleCount = network.getItemFromNetwork("barrel", "minecraft:dirt", 169, nil, false) |
1378 | + | |
1379 | - | T:saveToLog("Get from barrel completed: turtleSlot = "..turtleSlot..", turtleCount = "..turtleCount..", ignoreStock = "..tostring(ignoreStock)) |
1379 | + | |
1380 | - | if turtleCount < 169 then |
1380 | + | |
1381 | - | T:saveToLog("\ncall network.getItemFromNetwork('chest', 'minecraft:dirt', ".. 169 - turtleCount..", ignoreStock = "..tostring(ignoreStock)..")") |
1381 | + | |
1382 | - | turtleSlot, turtleCount = network.getItemFromNetwork("chest", "minecraft:dirt", 169 - turtleCount, nil, true) |
1382 | + | |
1383 | - | if turtleCount < 169 then -- ask player for saplings |
1383 | + | |
1384 | - | T:checkInventoryForItem({"dirt"}, {169 - turtleCount}) |
1384 | + | |
1385 | end | |
1386 | local secondBorderFound = false | |
1387 | while not secondBorderFound do | |
1388 | lib.safeMove() -- moves forward until reaches border forward or below | |
1389 | lib.turn(direction) -- turn r or l. direction is not changed | |
1390 | success, blockTypeF = lib.isBorder() -- no blockType passed as parameter so will return current block in new forward direction | |
1391 | if success then | |
1392 | secondBorderFound = true -- game over | |
1393 | elseif blockTypeF:find("log") ~= nil then -- tree in front | |
1394 | lib.harvestTree(blockTypeF) | |
1395 | elseif blockTypeF == "" or blockTypeF:find("leaves") ~= nil then -- air or leaves in front | |
1396 | T:forward(1) -- move forward 1 block | |
1397 | lib.moveDown() -- go down if required | |
1398 | elseif blockTypeF:find("dirt") ~= nil or | |
1399 | blockTypeF:find("grass_block") ~= nil or | |
1400 | T:isVegetation(blockTypeF) then -- dirt, grass_block or vegetation in front | |
1401 | blockTypeF = lib.moveUp(blockTypeF) -- move up until air or border ahead. | |
1402 | if lib.isBorder(blockTypeF) then -- border ahead | |
1403 | secondBorderFound = true | |
1404 | else -- air ahead | |
1405 | T:forward(1) -- move forward 1 block | |
1406 | end | |
1407 | end | |
1408 | direction = lib.turn(direction) -- turn r or l. direction is changed to opposite | |
1409 | end | |
1410 | lib.moveDown() -- return to ground level | |
1411 | lib.emptyInventory() | |
1412 | return {} | |
1413 | end | |
1414 | ||
1415 | local function clearArea(R) -- 71, called from 22 | |
1416 | local evenWidth = false | |
1417 | local evenHeight = false | |
1418 | local loopWidth | |
1419 | -- go(path, useTorch, torchInterval, leaveExisting) | |
1420 | if R.width % 2 == 0 then | |
1421 | evenWidth = true | |
1422 | loopWidth = R.width / 2 | |
1423 | else | |
1424 | loopWidth = math.ceil(R.width / 2) | |
1425 | end | |
1426 | if R.length % 2 == 0 then | |
1427 | evenHeight = true | |
1428 | end | |
1429 | turtle.select(1) | |
1430 | - | T:place("minecraft:torch", "forward", false) |
1430 | + | |
1431 | -- if R.width is even no, then complete the up/down run | |
1432 | -- if R.width odd no then finish at top of up run and reverse | |
1433 | -- should be on flat ground, check voids below, harvest trees | |
1434 | for x = 1, loopWidth do | |
1435 | -- Clear first column (up) | |
1436 | for y = 1, R.length do | |
1437 | if R.useBlockType == "dirt" then | |
1438 | if not turtle.detectDown() then | |
1439 | T:place("minecraft:dirt", -1, "down", true) | |
1440 | else --if not water, dirt, grass , stone then replace with dirt | |
1441 | blockType, blockModifier = T:getBlockType("down") | |
1442 | if blockType ~= "" then | |
1443 | if blockType ~= "minecraft:dirt" and blockType ~= "minecraft:grass_block" then | |
1444 | turtle.digDown() | |
1445 | T:place("minecraft:dirt", -1, "down", true) | |
1446 | - | function utils.createStorage() |
1446 | + | |
1447 | - | -- start in centre, above 1st level |
1447 | + | |
1448 | - | T:place("modem", "down") |
1448 | + | |
1449 | end | |
1450 | if y < R.length then | |
1451 | - | T:place("chest", "down") -- places with handle at back of turtle |
1451 | + | |
1452 | end | |
1453 | - | T:place("chest", "down") -- 2nd of pair |
1453 | + | |
1454 | - | for i = 1, 3 do |
1454 | + | |
1455 | if x < loopWidth or (x == loopWidth and evenWidth) then -- go down if on R.width 2,4,6,8 etc | |
1456 | - | T:place("chest", "down") |
1456 | + | |
1457 | - | T:go("R1F1L1") |
1457 | + | |
1458 | - | T:place("chest", "down") |
1458 | + | |
1459 | if not turtle.detectDown() then | |
1460 | T:place("minecraft:dirt", -1, "down", true) | |
1461 | - | T:go("F1L1F1") -- end at starting position |
1461 | + | |
1462 | - | network.attachModem() |
1462 | + | blockType, blockModifier = T:getBlockType("down") |
1463 | if blockType ~= "" then | |
1464 | if blockType ~= "minecraft:dirt" and blockType ~= "minecraft:grass_block" then | |
1465 | turtle.digDown() | |
1466 | T:place("minecraft:dirt", -1, "down", true) | |
1467 | end | |
1468 | end | |
1469 | end | |
1470 | end | |
1471 | if y < R.length then | |
1472 | T:go("F1+1", false, 0, false) | |
1473 | end | |
1474 | end | |
1475 | if x < loopWidth then | |
1476 | T:go("L1F1+1L1", false,0,false) | |
1477 | else | |
1478 | T:turnRight(1) | |
1479 | T:forward(R.width - 1) | |
1480 | T:turnRight(1) | |
1481 | end | |
1482 | else -- equals R.width but is 1,3,5,7 etc | |
1483 | T:turnLeft(2) --turn round 180 | |
1484 | T:forward(R.length - 1) | |
1485 | T:turnRight(1) | |
1486 | T:forward(R.width - 1) | |
1487 | T:turnRight(1) | |
1488 | end | |
1489 | end | |
1490 | return {} | |
1491 | end | |
1492 | ||
1493 | local function clearRectangle(R) -- 72 | |
1494 | --local function clearRectangle(width, length, up, down) | |
1495 | -- height = 0: one level, 1 = +up, 2 = +down, 3 = +up/down | |
1496 | local lib = {} | |
1497 | function lib.UpDown(length) | |
1498 | for l = 1, length do | |
1499 | T:go("x0x2F1x0x2") | |
1500 | end | |
1501 | end | |
1502 | ||
1503 | function lib.Up(length) | |
1504 | for l = 1, length do | |
1505 | T:go("x0F1x0") | |
1506 | end | |
1507 | end | |
1508 | ||
1509 | function lib.Down(length) | |
1510 | for l = 1, length do | |
1511 | T:go("x2F1x2") | |
1512 | end | |
1513 | end | |
1514 | ||
1515 | function lib.Forward(length) | |
1516 | T:forward(length) | |
1517 | end | |
1518 | ||
1519 | -- could be 1 wide x xx R.length (trench) R.up and return | |
1520 | -- could be 2+ x 2+ | |
1521 | -- even no of runs return after last run | |
1522 | -- odd no of runs forward, back, forward, reverse and return | |
1523 | turtle.select(1) | |
1524 | if R.width == 1 then -- single block trench ahead only | |
1525 | if R.up and R.down then -- single block wide trench dig R.up and R.down = 3 blocks deep | |
1526 | lib.UpDown(R.length - 1) | |
1527 | elseif R.up then -- single block wide trench dig R.up = 2 blocks deep | |
1528 | lib.Up(R.length - 1) | |
1529 | elseif R.down then -- single block wide trench dig R.down = 2 blocks deep | |
1530 | lib.Down(R.length - 1) | |
1531 | else -- single block wide = 1 block deep | |
1532 | lib.Forward(R.length - 1) | |
1533 | end | |
1534 | T:turnRight(2) -- turn at the top of the run | |
1535 | T:forward(R.length - 1) -- return to start | |
1536 | T:turnRight(2) -- turn round to original position | |
1537 | else -- R.width 2 or more blocks | |
1538 | local iterations = 0 -- R.width = 2, 4, 6, 8 etc | |
1539 | if R.width % 2 == 1 then -- R.width = 3, 5, 7, 9 eg R.width 7 | |
1540 | iterations = (R.width - 1) / 2 -- iterations 1, 2, 3, 4 for widths 3, 5, 7, 9 | |
1541 | else | |
1542 | iterations = R.width / 2 -- iterations 1, 2, 3, 4 for widths 2, 4, 6, 8 | |
1543 | end | |
1544 | for i = 1, iterations do -- eg 3 blocks wide, iterations = 1 | |
1545 | if R.up and R.down then -- dig R.up and R.down | |
1546 | lib.UpDown(R.length - 1) | |
1547 | T:go("x0x2R1F1x0x2R1x0x2") -- turn round | |
1548 | lib.UpDown(R.length - 1) | |
1549 | elseif R.up then -- dig R.up | |
1550 | lib.Up(R.length - 1) | |
1551 | T:go("x0R1F1x0R1x0") | |
1552 | lib.Up(R.length - 1) | |
1553 | elseif R.down then -- dig R.down | |
1554 | lib.Down(R.length - 1) | |
1555 | T:go("x2R1F1x2R1x2") | |
1556 | lib.Down(R.length - 1) | |
1557 | else -- no digging R.up or R.down | |
1558 | lib.Forward(R.length - 1) | |
1559 | T:go("R1F1R1") | |
1560 | lib.Forward(R.length - 1) | |
1561 | end | |
1562 | -- if 1 less than end, reposition for next run | |
1563 | if i < iterations then | |
1564 | T:go("L1F1L1", false, 0, false) | |
1565 | end | |
1566 | end | |
1567 | if R.width % 2 == 1 then -- additional run and return to base needed | |
1568 | T:go("L1F1L1", false, 0, false) | |
1569 | if R.up and R.down then | |
1570 | lib.UpDown(R.length - 1) | |
1571 | elseif R.up then | |
1572 | lib.Up(R.length - 1) | |
1573 | elseif R.down then | |
1574 | lib.Down(R.length - 1) | |
1575 | else | |
1576 | lib.Forward(R.length - 1) | |
1577 | end | |
1578 | T:turnRight(2) | |
1579 | T:forward(R.length - 1) | |
1580 | end | |
1581 | T:go("R1F"..R.width - 1 .."R1", false, 0, false) | |
1582 | end | |
1583 | return {} | |
1584 | end | |
1585 | ||
1586 | local function clearPerimeter(R) -- 74 | |
1587 | local lib = {} | |
1588 | function lib.UpDown(length) | |
1589 | for l = 1, length do | |
1590 | T:go("x0x2F1x0x2") | |
1591 | end | |
1592 | end | |
1593 | ||
1594 | function lib.Up(length) | |
1595 | for l = 1, length do | |
1596 | T:go("x0F1x0") | |
1597 | end | |
1598 | end | |
1599 | ||
1600 | function lib.Down(length) | |
1601 | for l = 1, length do | |
1602 | T:go("x2F1x2") | |
1603 | end | |
1604 | end | |
1605 | ||
1606 | function lib.Forward(length) | |
1607 | T:forward(length) | |
1608 | end | |
1609 | ||
1610 | if R.up and R.down then | |
1611 | for i = 1, 2 do | |
1612 | lib.UpDown(R.length - 1) | |
1613 | T:turnRight(1) | |
1614 | lib.UpDown(R.width - 1) | |
1615 | T:turnRight(1) | |
1616 | end | |
1617 | elseif R.up then | |
1618 | for i = 1, 2 do | |
1619 | lib.Up(R.length - 1) | |
1620 | T:turnRight(1) | |
1621 | lib.Up(R.width - 1) | |
1622 | T:turnRight(1) | |
1623 | end | |
1624 | elseif R.down then | |
1625 | for i = 1, 2 do | |
1626 | lib.Down(R.length - 1) | |
1627 | T:turnRight(1) | |
1628 | lib.Down(R.width - 1) | |
1629 | T:turnRight(1) | |
1630 | end | |
1631 | else | |
1632 | for i = 1, 2 do | |
1633 | lib.Forward(R.length - 1) | |
1634 | T:turnRight(1) | |
1635 | lib.Forward(R.width - 1) | |
1636 | T:turnRight(1) | |
1637 | end | |
1638 | end | |
1639 | return {} | |
1640 | end | |
1641 | ||
1642 | local function clearBuilding(R) -- 75, 43 | |
1643 | --[[ | |
1644 | Clear the outer shell of a building, leaving inside untouched. Optional floor/ceiling removal | |
1645 | clearBuilding(R) | |
1646 | R.subChoice = 1-'up' or 2-'down' | |
1647 | R.data.ceiling = true / false | |
1648 | R.data.floor = true / false | |
1649 | ]] | |
1650 | local height = 1 | |
1651 | local remaining = R.height -- eg 5 | |
1652 | local start = true | |
1653 | local finish = false | |
1654 | local lib = {} | |
1655 | ||
1656 | function lib.floorOrCeiling(R) | |
1657 | T:go("F1R1 F1L1") | |
1658 | R.length = R.length - 2 | |
1659 | R.width = R.width - 2 | |
1660 | clearRectangle(R) | |
1661 | R.length = R.length + 2 | |
1662 | R.width = R.width + 2 | |
1663 | T:go("L1F1R1") | |
1664 | utils.goBack(1) | |
1665 | end | |
1666 | ||
1667 | function lib.singleLayer(R) | |
1668 | R.up = false | |
1669 | R.down = false | |
1670 | if start then | |
1671 | if R.data.ceiling or R.data.floor then -- floor / ceiling to go. only one layer, so clearRectangle | |
1672 | lib.floorOrCeiling(R) | |
1673 | end | |
1674 | start = false | |
1675 | end | |
1676 | if finish then | |
1677 | if R.data.ceiling or R.data.floor then -- floor / ceiling to go. only one layer, so clearRectangle | |
1678 | lib.floorOrCeiling(R) | |
1679 | end | |
1680 | finish = false | |
1681 | end | |
1682 | clearPerimeter(R) -- no floor / ceiling | |
1683 | end | |
1684 | ||
1685 | function lib.doubleLayer(R) | |
1686 | R.up = false | |
1687 | R.down = false | |
1688 | if start then | |
1689 | if R.data.floor and R.subChoice == 1 then -- going up and floor needs removing | |
1690 | lib.floorOrCeiling(R) -- remove floor/ceiling | |
1691 | elseif R.data.ceiling and R.subChoice == 2 then -- going down and ceiling needs removing | |
1692 | lib.floorOrCeiling(R) -- remove floor/ceiling | |
1693 | end | |
1694 | start = false | |
1695 | end | |
1696 | if finish then | |
1697 | if R.data.ceiling and R.subChoice == 1 then -- going down and ceiling needs removing | |
1698 | lib.floorOrCeiling(R) -- remove floor/ceiling | |
1699 | elseif R.data.floor and R.subChoice == 2 then -- going down and floor needs removing | |
1700 | lib.floorOrCeiling(R) -- remove floor/ceiling | |
1701 | end | |
1702 | finish = false | |
1703 | end | |
1704 | if R.subChoice == 1 then | |
1705 | R.up = true | |
1706 | else | |
1707 | R.down = true | |
1708 | end | |
1709 | clearPerimeter(R) | |
1710 | end | |
1711 | ||
1712 | function lib.tripleLayer(R) | |
1713 | -- turtle in centre layer | |
1714 | R.up = false | |
1715 | R.down = false | |
1716 | if start then | |
1717 | if R.data.floor and R.subChoice == 1 then -- going up and floor needs removing | |
1718 | height = height + utils.move(R, 1, true) -- move down 1 block | |
1719 | lib.floorOrCeiling(R) -- remove floor/ceiling | |
1720 | height = height + utils.move(R, 1) -- move up 1 block | |
1721 | elseif R.data.ceiling and R.subChoice == 2 then -- going down and ceiling needs removing | |
1722 | height = height + utils.move(R, 1, true) -- move up 1 block | |
1723 | lib.floorOrCeiling(R) -- remove floor/ceiling | |
1724 | height = height + utils.move(R, 1) -- move down 1 block | |
1725 | end | |
1726 | start = false | |
1727 | end | |
1728 | if finish then | |
1729 | if R.data.ceiling and R.subChoice == 1 then -- going up and ceiling needs removing | |
1730 | height = height + utils.move(R, 1, true) -- move down 1 block | |
1731 | lib.floorOrCeiling(R) -- remove floor/ceiling | |
1732 | height = height + utils.move(R, 1) -- move up 1 block | |
1733 | elseif R.data.floor and R.subChoice == 2 then -- going down and floor needs removing | |
1734 | height = height + utils.move(R, 1, true) -- move up 1 block | |
1735 | lib.floorOrCeiling(R) -- remove floor/ceiling | |
1736 | height = height + utils.move(R, 1) -- move up 1 block | |
1737 | end | |
1738 | finish = false | |
1739 | end | |
1740 | R.up = true | |
1741 | R.down = true | |
1742 | clearPerimeter(R) | |
1743 | end | |
1744 | --[[ | |
1745 | R.data = "up" or "down" as direction of travel | |
1746 | R.up = true to remove ceiling | |
1747 | R.down = true to remove floor | |
1748 | ]] | |
1749 | - | if not T:place("sand", "down", false) then |
1749 | + | |
1750 | if R.height < 3 then --1-3 layers only | |
1751 | if R.height == 1 then --one layer only | |
1752 | lib.singleLayer(R) | |
1753 | elseif R.height == 2 then --2 layers only current + dig up/down | |
1754 | lib.doubleLayer(R) | |
1755 | end | |
1756 | else -- 3 or more levels | |
1757 | height = height + utils.move(R, 1) -- move up/down 1 block for first layer | |
1758 | while remaining >= 3 do -- min 3 levels | |
1759 | lib.tripleLayer(R) | |
1760 | remaining = remaining - 3 | |
1761 | if remaining == 0 then -- all finished | |
1762 | break | |
1763 | elseif remaining == 1 then | |
1764 | height = height + utils.move(R, 2) -- move up/down 2 blocks | |
1765 | lib.singleLayer(R) | |
1766 | elseif remaining == 2 then | |
1767 | height = height + utils.move(R, 2) -- move up/down 2 blocks | |
1768 | lib.doubleLayer(R) | |
1769 | else | |
1770 | height = height + utils.move(R, 3) -- move up/down 3 blocks | |
1771 | if remaining == 3 then | |
1772 | finish = true | |
1773 | else | |
1774 | --height = height + 3 | |
1775 | end | |
1776 | end | |
1777 | end | |
1778 | end | |
1779 | ||
1780 | if height > 1 then | |
1781 | utils.move(R, height - 1, true) -- reverse direction | |
1782 | end | |
1783 | ||
1784 | return {} | |
1785 | end | |
1786 | ||
1787 | local function clearMineshaft(R, equippedRight, equippedLeft, inInventory) -- 19 | |
1788 | local lib = {} | |
1789 | ||
1790 | function lib.checkCobweb(directions, inInventory) | |
1791 | assert(type(directions) == "table", "directions must be a table eg {'up','down'}") | |
1792 | for _, direction in ipairs(directions) do | |
1793 | local blockType = T:getBlockType(direction) | |
1794 | if inInventory == "minecraft:diamond_sword" then -- using a sword | |
1795 | local side = "left" | |
1796 | ||
1797 | if blockType:find("cobweb") ~= nil then | |
1798 | --clsTurtle.equip(self, side, useItem, useDamage) | |
1799 | if equippedRight == "minecraft:diamond_pickaxe" then | |
1800 | side = "right" | |
1801 | end | |
1802 | T:equip(side, "minecraft:diamond_sword") | |
1803 | T:dig(direction) | |
1804 | T:equip(side, "minecraft:diamond_pickaxe") | |
1805 | elseif blockType ~= "" then | |
1806 | T:dig(direction) | |
1807 | end | |
1808 | else | |
1809 | T:dig(direction) | |
1810 | end | |
1811 | end | |
1812 | end | |
1813 | ||
1814 | -- check position by rotating until facing away from wall | |
1815 | length = 0 | |
1816 | torch = 0 | |
1817 | turns = 0 | |
1818 | while not turtle.detect() do | |
1819 | T:turnRight(1) | |
1820 | turns = turns + 1 | |
1821 | if turns > 4 then | |
1822 | return {"I am not facing a wall. Unable to continue"} | |
1823 | end | |
1824 | end | |
1825 | T:turnRight(2) | |
1826 | -- move forward until obstructed, digging up/down. place torches | |
1827 | while not turtle.detect() do | |
1828 | lib.checkCobweb({"up","down"}, inInventory) -- dig cobweb or any other block up/down | |
1829 | length = length + 1 | |
1830 | torch = torch + 1 | |
1831 | if torch == R.torchInterval then | |
1832 | torch = 0 | |
1833 | T:place("minecraft:torch", -1, "down", false) ---(self, blockType, damageNo, direction, leaveExisting, signText) | |
1834 | end | |
1835 | lib.checkCobweb({"forward"}, inInventory) -- dig cobweb or any other block in front | |
1836 | T:forward(1) | |
1837 | end | |
1838 | -- turn right, forward, right, return to start with up/down dig | |
1839 | T:go("R1") | |
1840 | lib.checkCobweb({"up","down"}, inInventory) -- dig cobweb or any other block up/down | |
1841 | T:go("F1R1") | |
1842 | for i = 1, length, 1 do | |
1843 | lib.checkCobweb({"up", "down", "forward"}, inInventory) -- dig cobweb or any other block up/down/forward | |
1844 | T:forward(1) | |
1845 | end | |
1846 | -- move to other wall and repeat. | |
1847 | T:go("R1") | |
1848 | lib.checkCobweb({"up","down"}, inInventory) -- dig cobweb or any other block up/down | |
1849 | T:go("F1") | |
1850 | lib.checkCobweb({"up","down"}, inInventory) -- dig cobweb or any other block up/down | |
1851 | T:go("F1R1") | |
1852 | lib.checkCobweb({"up","down"}, inInventory) -- dig cobweb or any other block up/down | |
1853 | for i = 1, length, 1 do | |
1854 | lib.checkCobweb({"up", "down", "forward"}, inInventory) -- dig cobweb or any other block up/down/forward | |
1855 | T:forward(1) | |
1856 | end | |
1857 | lib.checkCobweb({"up", "down"}, inInventory) -- dig cobweb or any other block up/down/forward | |
1858 | ||
1859 | return {} | |
1860 | end | |
1861 | ||
1862 | local function clearMonumentLayer(R) -- 85 | |
1863 | R.up = true | |
1864 | R.down = true | |
1865 | R.silent = true | |
1866 | if R.subChoice == 0 then | |
1867 | R.up = false | |
1868 | R.down = false | |
1869 | end | |
1870 | -- send turtle down until it hits bottom | |
1871 | -- then clear rectangle of given size | |
1872 | -- start above water, usually on cobble scaffold above monument | |
1873 | if T:detect("down") then -- in case not over wall | |
1874 | T:forward(1) | |
1875 | end | |
1876 | local height = 1 | |
1877 | -- go down until solid block detected | |
1878 | while utils.clearVegetation("down") do | |
1879 | T:down(1) | |
1880 | height = height + 1 | |
1881 | end | |
1882 | T:down(1) | |
1883 | height = height + 1 | |
1884 | clearRectangle(R) | |
1885 | - | local lastSlot, leastModifier, total, slotData = T:getItemSlot("minecraft:bucket") |
1885 | + | |
1886 | ||
1887 | return {} | |
1888 | end | |
1889 | ||
1890 | local function clearWaterPlants(R) -- 87 | |
1891 | local lib = {} | |
1892 | ||
1893 | function lib.getLength() | |
1894 | local length = 1 | |
1895 | print("Checking water length") | |
1896 | while utils.clearVegetation("forward") do | |
1897 | T:forward(1) | |
1898 | length = length + 1 | |
1899 | end | |
1900 | for i = 1, length do | |
1901 | turtle.back() | |
1902 | end | |
1903 | return length | |
1904 | end | |
1905 | ||
1906 | function lib.clearDown(D) | |
1907 | while utils.clearVegetation("down") do --clears any grass or sea plants, returns true if air or water, bubble column or ice | |
1908 | T:down(1) | |
1909 | D.depth = D.depth + 1 | |
1910 | - | function utils.getSlotCapacity(slot) |
1910 | + | |
1911 | - | return turtle.getItemSpace(slot) + turtle.getItemCount(slot) |
1911 | + | |
1912 | D.blockType = T:getBlockType("down") | |
1913 | if D.blockType:find("slab") ~= nil then | |
1914 | T:go("C2") | |
1915 | end | |
1916 | if D.depth > D.maxDepth then | |
1917 | D.maxDepth = D.depth | |
1918 | end | |
1919 | ||
1920 | return D | |
1921 | end | |
1922 | ||
1923 | function lib.clearLength(D) | |
1924 | local moves = 0 | |
1925 | local blockHeight = 1 | |
1926 | D.floorLength = 0 -- reset | |
1927 | while moves < D.length - 1 do | |
1928 | if utils.clearVegetation("forward") then | |
1929 | T:forward(1) | |
1930 | - | -- lastSlot, leastModifier, total, slotData = T:getItemSlot(item) |
1930 | + | |
1931 | - | local lastSlot, leastModifier, total, slotData = T:getItemSlot("minecraft:water_bucket") |
1931 | + | |
1932 | if not D.monumentArchesClear then | |
1933 | D = lib.checkArches(D) | |
1934 | end | |
1935 | end | |
1936 | local temp = D.depth | |
1937 | D = lib.clearDown(D) -- go down if in water/air | |
1938 | if blockHeight == 4 and D.depth - temp == 3 then -- could be just gone over 3 block high column in ocean monument | |
1939 | if not D.monumentTopClear then | |
1940 | D = lib.checkTop(D) | |
1941 | end | |
1942 | blockHeight = 1 | |
1943 | end | |
1944 | if D.useBlockType == "prismarine" then | |
1945 | if D.blockType:find("prismarine") == nil then | |
1946 | -- on monument floor so restrict forward movement to 8 blocks | |
1947 | D.floorLength = D.floorLength + 1 | |
1948 | if D.floorLength == 8 then | |
1949 | D.blockType = T:getBlockType("forward") | |
1950 | while D.blockType:find("prismarine") == nil do | |
1951 | T:up(1) | |
1952 | D.blockType = T:getBlockType("forward") | |
1953 | end | |
1954 | D.floorLength = 0 | |
1955 | end | |
1956 | end | |
1957 | end | |
1958 | if moves >= D.length - 1 then | |
1959 | D.width = D.width + 1 -- another length completed so increase width | |
1960 | return D | |
1961 | end | |
1962 | else -- block in front | |
1963 | blockHeight = 1 | |
1964 | local waterAbove = utils.clearVegetation("up") | |
1965 | local waterAhead = utils.clearVegetation("forward") -- true if air/water in front | |
1966 | while not waterAhead do -- solid block in front | |
1967 | if waterAbove then -- move up | |
1968 | T:up(1) | |
1969 | D.depth = D.depth - 1 | |
1970 | blockHeight = blockHeight + 1 | |
1971 | if D.depth < 1 then | |
1972 | D.width = D.width + 1 -- another length completed so increase width | |
1973 | return D | |
1974 | end | |
1975 | else -- block above so go back | |
1976 | while not waterAbove do | |
1977 | utils.goBack() -- returns true if no object behind, but moves anyway | |
1978 | waterAbove = utils.clearVegetation("up") | |
1979 | moves = moves - 1 | |
1980 | if moves == 0 then | |
1981 | - | function utils.isStorage(direction) |
1981 | + | |
1982 | - | local blockType = T:getBlockType(direction) |
1982 | + | |
1983 | - | if blockType:find("barrel") ~= nil then |
1983 | + | |
1984 | - | return true, "barrel" |
1984 | + | |
1985 | - | elseif blockType:find("chest") ~= nil then |
1985 | + | |
1986 | - | return true, "chest" |
1986 | + | |
1987 | - | elseif blockType:find("modem") ~= nil then |
1987 | + | |
1988 | - | return true, "modem" |
1988 | + | |
1989 | end | |
1990 | -- go up 1 to prevent loop | |
1991 | - | return false, blockType |
1991 | + | |
1992 | D.depth = D.depth - 1 | |
1993 | end | |
1994 | - | function utils.isTableEmpty(aTable) |
1994 | + | |
1995 | - | if next(aTable) == nil then |
1995 | + | |
1996 | end | |
1997 | end | |
1998 | - | return false |
1998 | + | |
1999 | D.width = D.width + 1 -- another length completed so increase width | |
2000 | D.maxDepth = D.maxDepth + 1 -- +1 to allow for starting pos in top layer | |
2001 | ||
2002 | - | if blocks == 0 then return 0 end |
2002 | + | |
2003 | end | |
2004 | ||
2005 | function lib.checkArches(D) | |
2006 | -- gone under a block so could be monument arch (6) | |
2007 | - | --if R.subChoice == 2 then -- reverse direction |
2007 | + | |
2008 | - | if R.direction == "down" or R.subChoice == 2 then -- reverse direction |
2008 | + | |
2009 | T:go("B1U2F1R1") | |
2010 | if T:getBlockType("forward"):find("prismarine") ~= nil then -- correct guess | |
2011 | direction = "R" | |
2012 | else -- wrong direction. turn round and check other side | |
2013 | T:go("R2") | |
2014 | if T:getBlockType("forward"):find("prismarine") ~= nil then | |
2015 | - | --if R.subChoice == 1 then |
2015 | + | |
2016 | - | if R.direction == "up" or R.subChoice == 1 then |
2016 | + | |
2017 | end | |
2018 | local path = "U1F1 U1F3 D1F1 D1R2 U2F5 D2" | |
2019 | --for i = 1, 6 do | |
2020 | T:go(path) -- clears arch top 1 and returns | |
2021 | T:go(direction.."1F6"..direction.."1") | |
2022 | T:go(path) -- clears arch top 2 and returns | |
2023 | T:go(direction.."1F6"..direction.."1") | |
2024 | T:go(path) -- clears arch top 3 and returns | |
2025 | - | function utils.printR(R) |
2025 | + | |
2026 | T:go(path) -- clears arch top 4 and returns | |
2027 | - | choice = 0, |
2027 | + | |
2028 | - | subChoice = 0, |
2028 | + | |
2029 | - | size = 0, |
2029 | + | |
2030 | - | width = 0, |
2030 | + | |
2031 | - | length = 0, |
2031 | + | |
2032 | - | height = 0, |
2032 | + | |
2033 | - | depth = 0, |
2033 | + | |
2034 | - | up = false, |
2034 | + | |
2035 | - | down = false, |
2035 | + | |
2036 | - | silent = false, |
2036 | + | |
2037 | - | data = {}, |
2037 | + | |
2038 | - | torchInterval = 0, |
2038 | + | |
2039 | - | useBlockType = "", |
2039 | + | |
2040 | - | auto = false, |
2040 | + | |
2041 | - | side = "", |
2041 | + | |
2042 | - | direction = "", |
2042 | + | |
2043 | - | ready = false, |
2043 | + | |
2044 | - | networkFarm = false, |
2044 | + | |
2045 | - | mysticalAgriculture = false, |
2045 | + | |
2046 | - | logType = "", |
2046 | + | |
2047 | - | treeSize = "", |
2047 | + | |
2048 | - | message = "" |
2048 | + | |
2049 | end | |
2050 | end | |
2051 | - | print("choice= ".. tostring(R.choice)..", subChoice= ".. tostring(R.subChoice)) |
2051 | + | |
2052 | - | print("size= ".. tostring(R.size)..", width= ".. tostring(R.width)) |
2052 | + | |
2053 | - | print("length= ".. tostring(R.length)..", height= ".. tostring(R.height)..", depth= ".. tostring(R.depth)) |
2053 | + | |
2054 | - | print("silent= "..tostring(R.silent)..", up= ".. tostring(R.up)..", down= "..tostring(R.down)) |
2054 | + | |
2055 | - | print("torchInterval= ".. tostring(R.torchInterval)) |
2055 | + | |
2056 | - | print("useBlockType= "..tostring(R.useBlockType)) |
2056 | + | |
2057 | - | print("auto= ".. tostring(R.auto)..", side= "..tostring(R.side)..", direction= "..tostring(R.direction)) |
2057 | + | |
2058 | - | print("ready= ".. tostring(R.ready)..", networkFarm= "..tostring(R.networkFarm)..", mysticalAgriculture= "..tostring(R.mysticalAgriculture)) |
2058 | + | |
2059 | - | print("logType= ".. tostring(R.logType)..", treeSize= "..tostring(R.treeSize)..", message= "..tostring(R.message)) |
2059 | + | |
2060 | - | if type(R.data) == "table" then |
2060 | + | |
2061 | - | io.write("data= ") |
2061 | + | |
2062 | - | for k,v in pairs(R.data) do |
2062 | + | |
2063 | - | print(k ..": "..tostring(v)) |
2063 | + | |
2064 | repeat | |
2065 | if utils.clearVegetation("forward") then | |
2066 | - | print("data= ".. tostring(R.data)) |
2066 | + | |
2067 | D = lib.clearDown(D) -- go down if in water/air, D.blockType is updated with floor type | |
2068 | - | io.write("Enter to continue") |
2068 | + | |
2069 | local waterAbove = utils.clearVegetation("up") | |
2070 | local waterAhead = utils.clearVegetation("forward") -- true if air/water in front | |
2071 | while not waterAhead do -- solid block in front | |
2072 | if waterAbove then -- move up | |
2073 | T:up(1) | |
2074 | else -- block above so go back | |
2075 | while not waterAbove do | |
2076 | utils.goBack() -- returns true if no object behind, but moves anyway | |
2077 | waterAbove = utils.clearVegetation("up") | |
2078 | end | |
2079 | end | |
2080 | waterAbove = utils.clearVegetation("up") | |
2081 | waterAhead = utils.clearVegetation("forward") | |
2082 | end | |
2083 | end | |
2084 | until D.blockType:find(D.useBlockType) == nil | |
2085 | -- now above a non-prismarine block, facing away from monument | |
2086 | T:turnRight(2) -- facing monument | |
2087 | D.blockType = T:getBlockType("forward") | |
2088 | while D.blockType:find(D.useBlockType) ~= nil do | |
2089 | T:up(1) | |
2090 | D.blockType = T:getBlockType("forward") | |
2091 | end | |
2092 | T:go("F1L1") | |
2093 | D.blockType = T:getBlockType("down") | |
2094 | while D.blockType:find(D.useBlockType) ~= nil do | |
2095 | T:forward(1) | |
2096 | D.blockType = T:getBlockType("down") | |
2097 | end | |
2098 | turtle.back() | |
2099 | -- should now be at end of monument base | |
2100 | - | function utils.tableContains(tableName, value, exactMatch) |
2100 | + | |
2101 | - | exactMatch = exactMatch or false |
2101 | + | |
2102 | - | for k, v in ipairs(tableName) do |
2102 | + | |
2103 | - | if exactMatch then |
2103 | + | |
2104 | - | if v == value then |
2104 | + | |
2105 | direction = "L" | |
2106 | end | |
2107 | T:go(direction.. 1) | |
2108 | - | if v:find(value) ~= nil then |
2108 | + | |
2109 | T:forward(1) | |
2110 | --D.depth = D.depth + lib.clearDown(depth) | |
2111 | D = lib.clearDown(D) | |
2112 | else | |
2113 | - | return false |
2113 | + | |
2114 | T:up(1) | |
2115 | D.depth = D.depth - 1 | |
2116 | - | function utils.useSticksAsFuel() |
2116 | + | |
2117 | - | local slot = T:getItemSlot("minecraft:stick") |
2117 | + | |
2118 | - | if slot > 0 then -- use any sticks to refuel |
2118 | + | |
2119 | - | turtle.select(slot) |
2119 | + | |
2120 | - | turtle.refuel() |
2120 | + | |
2121 | ||
2122 | - | slot = T:getItemSlot("minecraft:mangrove_roots") |
2122 | + | |
2123 | - | if slot > 0 then -- use any roots to refuel |
2123 | + | |
2124 | - | turtle.select(slot) |
2124 | + | |
2125 | - | turtle.refuel() |
2125 | + | |
2126 | D.depth = 0 | |
2127 | D.maxDepth = 0 | |
2128 | D.blockType = "" | |
2129 | - | function utils.waitForInput(message) |
2129 | + | |
2130 | - | -- debugging. Pause script and asks user to continue |
2130 | + | |
2131 | - | -- global dbug flag has to be set first |
2131 | + | |
2132 | - | if dbug then |
2132 | + | |
2133 | - | if message ~= nil then |
2133 | + | |
2134 | - | print(message) |
2134 | + | |
2135 | - | T:saveToLog(message, false) |
2135 | + | |
2136 | D.onWater = false | |
2137 | - | menu.colourPrint("Enter to continue...", colors.lightBlue) |
2137 | + | |
2138 | - | --io.write("Press Enter to continue...") |
2138 | + | |
2139 | - | return read() |
2139 | + | |
2140 | if R.data == "clearWaterPlants" then -- NOT monument corner discovery | |
2141 | D.inWater, D.onWater = utils.startWaterFunction(D.onWater, D.inWater, 2, true) -- move into water | |
2142 | if R.length == 0 then | |
2143 | - | function utils.writeTraceTable(description, tbl) |
2143 | + | |
2144 | - | local text = "" |
2144 | + | |
2145 | - | for key, value in pairs(tbl) do |
2145 | + | |
2146 | - | if type(value) == "table" then |
2146 | + | |
2147 | - | for k,v in pairs(value) do |
2147 | + | |
2148 | - | text = text.."k = "..k..", v = "..v.."; " |
2148 | + | |
2149 | end | |
2150 | end | |
2151 | - | text = "key = "..key..", value = "..value |
2151 | + | |
2152 | D = lib.clearDown(D) -- go down to floor, set depth, maxDepth, blockType | |
2153 | if R.data == "clearWaterPlants" then -- NOT monument corner discovery | |
2154 | - | T:saveToLog(description.."\n".. text) |
2154 | + | |
2155 | print("Single row clearing") | |
2156 | D = lib.clearLength(D) --D.width also increased | |
2157 | else | |
2158 | while D.width < R.width do -- D.width starts at 0 | |
2159 | -- now on floor, move along sea/river bed following contour | |
2160 | D = lib.clearLength(D) --D.width also increased | |
2161 | -- now turn and repeat | |
2162 | if D.width < R.width then | |
2163 | D = lib.turn(D) | |
2164 | if D.depth <= 0 then | |
2165 | break | |
2166 | end | |
2167 | end | |
2168 | end | |
2169 | end | |
2170 | -- finished so return to surface | |
2171 | T:up(1) -- up 1 to check for water below | |
2172 | while T:getBlockType("down"):find("water") ~= nil do | |
2173 | T:up(1) | |
2174 | end | |
2175 | T:down(2) -- return to surface | |
2176 | --[[while utils.clearVegetation("forward") do | |
2177 | T:forward(1) | |
2178 | end]] | |
2179 | elseif R.data == "oceanMonumentColumns" then -- monument corner discovery | |
2180 | -- this function used to find edge of monument base | |
2181 | if D.blockType:find(D.useBlockType) ~= nil then | |
2182 | lib.findBlockTypeEnd(D) | |
2183 | return {""} | |
2184 | else | |
2185 | T:up(D.depth) | |
2186 | return {"Prismarine not found on ocean floor"} | |
2187 | end | |
2188 | end | |
2189 | if R.silent then | |
2190 | return {D.maxDepth, R.length} | |
2191 | else | |
2192 | return {""} | |
2193 | end | |
2194 | end | |
2195 | ||
2196 | local function clearMountainSide(R) -- 78 | |
2197 | --[[ | |
2198 | First row outward l s f mid (length, start, finish, midPoint) | |
2199 | ||
2200 | >|*|*| true lib.clearRow() moves: 7-5=2, midPoint starts at 2 | |
2201 | +|*|*| | |
2202 | +|*|*| | |
2203 | ^|*|*| < false 7 5 6 2 lib.clearRow() moves: 9-2=7, midPoint starts at -4 -1 = -5 | |
2204 | |*|*|*| + | |
2205 | |*|*|*|*|*| + | |
2206 | > |*|*|*|*|*| ^ true 9 2 6 -4 lib.getStartingLength(). Ends 1 block after block finish | |
2207 | ^|*|*|*|*|*|*|*|*| starts here, moves up 1 | |
2208 | 1 2 3 4 5 6 7 8 block index | |
2209 | ||
2210 | Second row outward l s f mid | |
2211 | < false | |
2212 | + | |
2213 | |*|*| + | |
2214 | >|*|*|*|*|^ true | |
2215 | +|*|*|*|*| | |
2216 | +|*|*|*|*| | |
2217 | ^|*|*|*|*| < false 6 5 6 2 | |
2218 | |*|*|*|*|*|*| + | |
2219 | |*|*|*|*|*|*|*|*| + | |
2220 | |*|*|*|>|*|*|*|*| ^ true 7+5 5 -7 lib.getHalf(R); goBack(7) | |
2221 | |*|*|*|*|*|*|*|*|*|*|*| starts at midPoint of previous row eg block 4 | |
2222 | 0 1 2 3 4 5 6 7 8 9 10 | |
2223 | ]] | |
2224 | ||
2225 | -- variables declared before lib for them to be used within lib as is then in scope | |
2226 | local turn = "R" | |
2227 | local oTurn = "L" | |
2228 | if R.subChoice == 1 then -- remove left side | |
2229 | turn = "L" | |
2230 | oTurn = "R" | |
2231 | end | |
2232 | local outward = true -- direction flag | |
2233 | ||
2234 | local lib = {} | |
2235 | ||
2236 | function lib.isAnyAbove(above) | |
2237 | T:saveToLog("lib.isAnyAbove: "..utils.tableConcat(above, ", "), false) | |
2238 | for k,v in ipairs(above) do | |
2239 | if v then | |
2240 | T:saveToLog("lib.isAnyAbove Found: "..k , false) | |
2241 | return true | |
2242 | end | |
2243 | end | |
2244 | return false | |
2245 | end | |
2246 | ||
2247 | function lib.clearLevel(R, above) -- eg 9, 2, 6, -4 from lib.getStartingLength OR 7, 5, 6, 3 from previous | |
2248 | -- clearLevel always follows either lib.getStartingLength or a previous lib.clearLevel | |
2249 | -- midPoint should be adjusted as turtle moves to reflect current row length | |
2250 | if #above == 0 then return above, 1 end | |
2251 | --local index = 0 | |
2252 | local minMoves = math.floor(#above / 2) | |
2253 | local up, forward, down = lib.getDetect() | |
2254 | if outward then -- follow table indexes | |
2255 | for x = 1, minMoves do -- clear first half | |
2256 | above[x] = up -- reset this with new value | |
2257 | T:go("x0x2F1") -- clear and move forward | |
2258 | up, forward, down = lib.getDetect() | |
2259 | --index = index + 1 | |
2260 | end | |
2261 | for x = minMoves + 1, #above do -- check remaing half and clear | |
2262 | T:go("x0x2") -- clear above / below | |
2263 | if above[x] then -- is a block recorded as present?(now below) | |
2264 | above[x] = up -- reset this with new value | |
2265 | T:forward(1) -- move forward | |
2266 | up, forward, down = lib.getDetect() | |
2267 | --index = index + 1 | |
2268 | else | |
2269 | break | |
2270 | end | |
2271 | end | |
2272 | else -- iterate table in reverse | |
2273 | --index = #above | |
2274 | for x = #above, minMoves, -1 do -- clear first half | |
2275 | above[x] = up -- reset this with new value | |
2276 | T:go("x0x2F1") -- clear and move forward | |
2277 | up, forward, down = lib.getDetect() | |
2278 | --index = index - 1 | |
2279 | end | |
2280 | for x = minMoves - 1, 1, -1 do -- check remaing half and clear | |
2281 | T:go("x0x2") -- clear up / down | |
2282 | if above[x] then -- is a block recorded as present?(now below) | |
2283 | above[x] = up -- reset this with new value | |
2284 | T:forward(1) -- move forward | |
2285 | up, forward, down = lib.getDetect() | |
2286 | --index = index - 1 | |
2287 | else | |
2288 | break | |
2289 | end | |
2290 | end | |
2291 | end | |
2292 | T:go("x0x2 F1R2 x0x2 F1") -- face opposite direction, delete blocks above and below | |
2293 | outward = not outward -- switch direction flag | |
2294 | return above -- eg {false, true, true, true, false} | |
2295 | end | |
2296 | ||
2297 | function lib.getDetect() | |
2298 | return turtle.detectUp(), turtle.detect(), turtle.detectDown() | |
2299 | end | |
2300 | ||
2301 | function lib.getStartingLength(R) | |
2302 | --[[ | |
2303 | length of column by excavating blocks above, ahead or below | |
2304 | Rotate 180 at end of run ready to return | |
2305 | - | T:place("stairs", "up") |
2305 | + | |
2306 | ]] | |
2307 | local above = {} -- empty table of boolean values | |
2308 | local length = 0 -- used as counter | |
2309 | T:forward(1) -- start check 1 block ahead | |
2310 | local up, forward, down = lib.getDetect() -- check if anything around current block | |
2311 | if up or forward or down then -- block found nearby: continue | |
2312 | while up or forward or down do -- while blocks ahead / up / down move forward | |
2313 | table.insert(above, up) | |
2314 | T:go("x0x2F1") | |
2315 | up, forward, down = lib.getDetect() -- check if anything around current block | |
2316 | length = length + 1 | |
2317 | if length >= R.length then -- check if going out of range | |
2318 | T:saveToLog("lib.getStartingLength(R) : outward = "..tostring(outward).." MaxLength "..maxLength.." reached", false) | |
2319 | break | |
2320 | end | |
2321 | end | |
2322 | T:go("R2x0x2") -- Rotate 180 and clear blocks above/below | |
2323 | else -- no blocks nearby: exit | |
2324 | T:go("R2F1") -- return to start position rotated 180 | |
2325 | end | |
2326 | outward = not outward | |
2327 | ||
2328 | return above -- above = {false, true, true, true, true, false, false} | |
2329 | end | |
2330 | ||
2331 | function lib.firstRow(R) | |
2332 | local height = 1 -- starts at ground level, but forced up 1 | |
2333 | T:up(1) | |
2334 | local above = lib.getStartingLength(R) -- clear the ground level and 1 above eg 9, 2, 5, 4 | |
2335 | if T:saveToLog("startLength: "..#above, true) then | |
2336 | T:saveToLog(utils.tableConcat(above, ", "), false) | |
2337 | if dbug then read() end | |
2338 | end -- at end of first row as already turned 180, outward set to false in getStartingLength | |
2339 | while lib.isAnyAbove(above) do | |
2340 | T:go("U3") -- go up 3 | |
2341 | height = height + 3 | |
2342 | above = lib.clearLevel(R, above) -- returns start and finish of blocks above, rotates 180 | |
2343 | if T:saveToLog("checking level: "..height, true) then | |
2344 | T:saveToLog(utils.tableConcat(above, ", "), false) | |
2345 | if dbug then read() end | |
2346 | end | |
2347 | end -- first row all levels completed. | |
2348 | T:down(height) -- now on ground + 1, facing last column cleared. | |
2349 | ||
2350 | return above | |
2351 | end | |
2352 | ||
2353 | function lib.deepCopy(tbl) | |
2354 | local copy = {} | |
2355 | for key, value in ipairs(tbl) do | |
2356 | table.insert(copy, value) | |
2357 | end | |
2358 | return copy | |
2359 | end | |
2360 | ||
2361 | function lib.getHalf(R, above) | |
2362 | -- already 1 block above ground | |
2363 | local maxLength = R.length | |
2364 | local temp = {} | |
2365 | local retValue = {} | |
2366 | if #above > 0 then -- not empty table, so must be second half | |
2367 | temp = lib.deepCopy(above) -- copy existing table | |
2368 | above = {} -- initialise above | |
2369 | end | |
2370 | local up, forward, down = lib.getDetect() | |
2371 | ||
2372 | while up or forward or down do -- while blocks ahead / up / down move forward | |
2373 | T:go("x0x2F1") | |
2374 | table.insert(above, up) | |
2375 | up, forward, down = lib.getDetect() -- check if anything around current block | |
2376 | ||
2377 | if #above >= math.floor(maxLength / 2) then -- check if going out of range | |
2378 | T:saveToLog("lib.getHalf(R) : outward = "..tostring(outward).." MaxLength "..maxLength.." reached", false) | |
2379 | T:go("x0x2") | |
2380 | break | |
2381 | end | |
2382 | end | |
2383 | T:turnRight(2) -- ready for next half or return | |
2384 | outward = not outward | |
2385 | if #temp > 0 then -- completing a second half measurement | |
2386 | for i = #above, 1, -1 do | |
2387 | table.insert(retValue, above[i]) -- combine 2 tables into 1 | |
2388 | end | |
2389 | for i = 1, #temp do | |
2390 | table.insert(retValue, temp[i]) | |
2391 | end | |
2392 | else | |
2393 | retValue = above | |
2394 | end | |
2395 | return retValue | |
2396 | end | |
2397 | ||
2398 | function lib.nextRow(R) | |
2399 | - | T:place("slab", "forward") |
2399 | + | |
2400 | T:saveToLog("lib.nextRow(R)", false) | |
2401 | T:up(1) | |
2402 | local pattern = turn.."1F1"..turn.."1" | |
2403 | if not outward then | |
2404 | pattern = oTurn.."1F1"..oTurn.."1" | |
2405 | end | |
2406 | T:go(pattern) | |
2407 | T:saveToLog(" T:go("..pattern..")", false) | |
2408 | outward = not outward -- reverse direction flag | |
2409 | -- now in next vertical row | |
2410 | local above = lib.getHalf(R, {}) | |
2411 | local index = 0 | |
2412 | if T:saveToLog("\t first half Length: "..#above.." Enter", true) then | |
2413 | T:saveToLog(utils.tableConcat(above, ", "), false) | |
2414 | if dbug then read() end | |
2415 | end | |
2416 | lib.returnToMidPoint(#above) -- return to starting point | |
2417 | T:forward(1) | |
2418 | above = lib.getHalf(R, above) -- returns length - 1 eg 5, 4 | |
2419 | if T:saveToLog("\t total length: "..#above.." Enter", true) then | |
2420 | T:saveToLog(utils.tableConcat(above, ", "), false) | |
2421 | if dbug then read() end | |
2422 | end | |
2423 | ||
2424 | - | T:place("stairs", "up") |
2424 | + | |
2425 | T:go("U3") -- go up 3 | |
2426 | height = height + 3 -- increment height | |
2427 | T:saveToLog("\tClear height loop: height = "..height, false) | |
2428 | above = lib.clearLevel(R, above) -- returns start and finish of blocks above | |
2429 | end | |
2430 | T:down(height) -- now on ground + 1 | |
2431 | lib.returnToMidPoint(above) | |
2432 | end | |
2433 | ||
2434 | function lib.returnToMidPoint(above) | |
2435 | --[[ value can be integer or table]] | |
2436 | if type(above) == "table" then | |
2437 | T:saveToLog("lib.returnToMidPoint("..#above..")", false) | |
2438 | if #above > 0 then | |
2439 | local midPoint = math.floor(#above / 2) | |
2440 | if #above % 2 == 1 and not outward then -- length is odd no | |
2441 | midPoint = math.ceil(#above / 2) | |
2442 | T:saveToLog(" midPoint adjusted "..midPoint..")", false) | |
2443 | end | |
2444 | T:saveToLog(" T:forward("..midPoint..")", false) | |
2445 | T:forward(midPoint) | |
2446 | end | |
2447 | else | |
2448 | T:saveToLog("lib.returnToMidPoint("..above..")", false) | |
2449 | if above > 0 then | |
2450 | - | T:place("slab", "forward") |
2450 | + | |
2451 | T:forward(above) | |
2452 | end | |
2453 | - | T:place("slab", "forward") |
2453 | + | |
2454 | -- now back at starting point | |
2455 | - | T:place("slab", "forward") |
2455 | + | |
2456 | ||
2457 | -- Start here | |
2458 | -- if "tk log d.." typed instead of "tk" will start logfile and display comments. read() will be activated for debugging | |
2459 | T:saveToLog("Starting function clearMountainSide", false) | |
2460 | local above = lib.firstRow(R) -- outward depends on height eg 1-2 = false, 3-5 = true, 6-8 = false | |
2461 | lib.returnToMidPoint(above) -- return to mid first row of blocks | |
2462 | for row = 1, R.width -1 do | |
2463 | lib.nextRow(R) | |
2464 | end | |
2465 | ||
2466 | return {} | |
2467 | end | |
2468 | ||
2469 | local function clearSandWall(R) -- 81 | |
2470 | --dig down while on top of sand/red_sand/soul_sand | |
2471 | local lib = {} | |
2472 | ||
2473 | function lib.checkAbove(height) | |
2474 | if turtle.detectUp() then -- moved under a ledge | |
2475 | T:go("B1U1") | |
2476 | height = height - 1 | |
2477 | end | |
2478 | return height | |
2479 | end | |
2480 | ||
2481 | function lib.moveDown(height) | |
2482 | blockType = T:getBlockType("down") | |
2483 | while blockType:find("sand") ~= nil do | |
2484 | T:down(1) | |
2485 | height = height + 1 | |
2486 | blockType = T:getBlockType("down") | |
2487 | end | |
2488 | return height | |
2489 | end | |
2490 | ||
2491 | function lib.moveForward(length) | |
2492 | lib.digForward() | |
2493 | T:forward(1) | |
2494 | length = length + 1 | |
2495 | local blockType = T:getBlockType("forward") | |
2496 | return length, blockType | |
2497 | end | |
2498 | ||
2499 | function lib.digForward() | |
2500 | while T:dig("forward") do | |
2501 | while T:suck("forward") do end | |
2502 | while T:suck("up") do end | |
2503 | end | |
2504 | end | |
2505 | ||
2506 | local moves = 0 | |
2507 | local height = 0 | |
2508 | local length = 0 | |
2509 | local search = 0 | |
2510 | local reverse = false | |
2511 | local blockType = T:getBlockType("down") | |
2512 | if R.length == 0 then | |
2513 | R.length = 64 | |
2514 | end | |
2515 | ||
2516 | print("Checking for sand below") | |
2517 | while blockType:find("sand") == nil do --move forward until sand detected or 3 moves | |
2518 | T:forward(1) | |
2519 | search = search + 1 | |
2520 | blockType = T:getBlockType("down") | |
2521 | if search > 3 then | |
2522 | T:go("B"..search) | |
2523 | return {"Unable to locate sand"} | |
2524 | end | |
2525 | end | |
2526 | - | T:place(sapling, "down") |
2526 | + | |
2527 | height = lib.moveDown(height) -- go down if sand below | |
2528 | -- repeat until height == 0 | |
2529 | repeat -- starts at bottom of sand wall | |
2530 | blockType = T:getBlockType("forward") | |
2531 | - | if not T:place(sapling, "down") then |
2531 | + | |
2532 | - | T:place("sapling", "down") |
2532 | + | |
2533 | if blockType == "" or blockType:find("sand") ~= nil then -- sand or nothing in front | |
2534 | height = lib.moveDown(height) -- go down if sand below | |
2535 | end | |
2536 | - | if not T:place(sapling, "down") then |
2536 | + | |
2537 | - | T:place("sapling", "down") |
2537 | + | |
2538 | blockType = T:getBlockType("down") | |
2539 | if blockType:find("sand") ~= nil then -- sand below | |
2540 | T:dig("down") | |
2541 | end | |
2542 | T:up(1) | |
2543 | height = height - 1 | |
2544 | else -- air/water in front so move forward | |
2545 | if length < 60 then -- in case missing wall and in open ocean | |
2546 | length, blockType = lib.moveForward(length) -- move forward 1 and dig sand | |
2547 | height = lib.checkAbove(height) | |
2548 | else -- already > monument length of 56 | |
2549 | T:up(1) | |
2550 | height = height - 1 | |
2551 | end | |
2552 | end | |
2553 | end | |
2554 | until height == 0 or length == R.length | |
2555 | blockType = T:getBlockType("down") | |
2556 | if blockType:find("sand") ~= nil then -- sand below | |
2557 | T:dig("down") | |
2558 | end | |
2559 | if height > 0 then -- finished as length ran out | |
2560 | T:up(height) | |
2561 | end | |
2562 | -- stay at end of cleared wall unless user chose to return | |
2563 | if R.data == "return" then | |
2564 | T:go("R2F"..length.."R2") | |
2565 | end | |
2566 | ||
2567 | return {} | |
2568 | end | |
2569 | ||
2570 | local function clearSolid(R) -- 76 | |
2571 | --[[ direction = R.subChoice = 1 up or 2 down ]] | |
2572 | local height = 1 | |
2573 | local remaining = R.height | |
2574 | local lib = {} | |
2575 | ||
2576 | function lib.singleLayer(R) | |
2577 | R.up = false | |
2578 | R.down = false | |
2579 | clearRectangle(R) | |
2580 | end | |
2581 | ||
2582 | function lib.doubleLayer(R) | |
2583 | R.up = false | |
2584 | R.down = false | |
2585 | if R.subChoice == 1 then | |
2586 | R.up = true | |
2587 | else | |
2588 | R.down = true | |
2589 | end | |
2590 | clearRectangle(R) | |
2591 | end | |
2592 | ||
2593 | function lib.tripleLayer(R) | |
2594 | -- turtle in centre layer | |
2595 | R.up = true | |
2596 | R.down = true | |
2597 | clearRectangle(R) | |
2598 | end | |
2599 | ||
2600 | R.silent = true | |
2601 | if R.height < 3 then --1-3 layers only | |
2602 | if R.height == 1 then --one layer only | |
2603 | lib.singleLayer(R) | |
2604 | elseif R.height == 2 then --2 layers only current + dig up/down | |
2605 | lib.doubleLayer(R) | |
2606 | end | |
2607 | else -- 3 or more levels | |
2608 | height = height + utils.move(R, 1) -- move up/down 1 block for first layer | |
2609 | while remaining >= 3 do -- min 3 levels | |
2610 | lib.tripleLayer(R) | |
2611 | remaining = remaining - 3 | |
2612 | if remaining == 0 then -- all finished | |
2613 | break | |
2614 | elseif remaining == 1 then | |
2615 | height = height + utils.move(R, 2) -- move up/down 2 blocks | |
2616 | lib.singleLayer(R) | |
2617 | elseif remaining == 2 then | |
2618 | height = height + utils.move(R, 2) -- move up/down 2 blocks | |
2619 | lib.doubleLayer(R) | |
2620 | else | |
2621 | height = height + utils.move(R, 3) -- move up/down 3 blocks | |
2622 | if remaining == 3 then | |
2623 | finish = true | |
2624 | end | |
2625 | end | |
2626 | end | |
2627 | end | |
2628 | ||
2629 | if height > 1 then | |
2630 | utils.move(R, height - 1, true) -- reverse direction | |
2631 | end | |
2632 | ||
2633 | return {} | |
2634 | end | |
2635 | ||
2636 | local function clearSandCube(R) -- 81 | |
2637 | R.data = "" | |
2638 | for w = 1, R.width do | |
2639 | clearSandWall(R) | |
2640 | if w < R.width then | |
2641 | if w % 2 == 1 then | |
2642 | T:go("R1F1R1") | |
2643 | else | |
2644 | T:go("L1F1L1") | |
2645 | end | |
2646 | end | |
2647 | end | |
2648 | ||
2649 | return {} | |
2650 | end | |
2651 | ||
2652 | local function clearWall(R) -- 73 | |
2653 | local lib = {} | |
2654 | ||
2655 | function lib.move(direction, blocks, reverse) | |
2656 | --[[ Move up or down by blocks count ]] | |
2657 | if reverse == nil then | |
2658 | reverse = false | |
2659 | end | |
2660 | if reverse then | |
2661 | if direction == "down" then -- reverse direction | |
2662 | T:up(blocks) | |
2663 | else | |
2664 | T:down(blocks) | |
2665 | end | |
2666 | else | |
2667 | if direction == "up" then | |
2668 | T:up(blocks) | |
2669 | else | |
2670 | T:down(blocks) | |
2671 | end | |
2672 | end | |
2673 | return blocks | |
2674 | end | |
2675 | ||
2676 | function lib.singleLayer(length) | |
2677 | T:go("F"..length - 1) | |
2678 | end | |
2679 | ||
2680 | function lib.doubleLayer(modifier, length) | |
2681 | for i = 1, length do | |
2682 | if i < length then | |
2683 | T:go("x"..modifier.."F1") | |
2684 | else | |
2685 | T:go("x"..modifier) | |
2686 | end | |
2687 | end | |
2688 | end | |
2689 | ||
2690 | function lib.tripleLayer(direction, length) | |
2691 | for i = 1, length do | |
2692 | if i < length then | |
2693 | T:go("x0x2F1") | |
2694 | else | |
2695 | T:go("x0x2") | |
2696 | end | |
2697 | end | |
2698 | end | |
2699 | ||
2700 | ||
2701 | -- R.width preset to 1 | |
2702 | -- R.subChoice = 1 up / 2 down | |
2703 | if R.height < 3 then | |
2704 | R.silent = true | |
2705 | end | |
2706 | -- dig along and up/down for specified R.length | |
2707 | local modifier = "0" | |
2708 | local direction = "U" | |
2709 | local outbound = true | |
2710 | local height = 0 | |
2711 | if R.subChoice == 2 then | |
2712 | modifier = "2" | |
2713 | direction = "D" | |
2714 | end | |
2715 | if R.height == 1 then -- single block so dig and return | |
2716 | lib.singleLayer(R.length) | |
2717 | elseif R.height == 2 then | |
2718 | lib.doubleLayer(modifier, R.length) | |
2719 | else -- 4 blocks or more. start with bulk 3 blocks | |
2720 | local remaining = R.height | |
2721 | T:go(direction.."1") -- up 1 or down 1 | |
2722 | height = 1 | |
2723 | while remaining >= 3 do | |
2724 | lib.tripleLayer(direction, R.length) | |
2725 | remaining = remaining - 3 | |
2726 | ||
2727 | if remaining == 0 then -- no more, return home, already in position | |
2728 | ||
2729 | elseif remaining == 1 or remaining == 2 then | |
2730 | T:go(direction.."2") | |
2731 | height = height + 2 | |
2732 | else | |
2733 | T:go(direction.."3") | |
2734 | height = height + 3 | |
2735 | if remaining >= 3 then -- another iteration | |
2736 | T:go("R2") | |
2737 | outbound = not outbound | |
2738 | end | |
2739 | end | |
2740 | end | |
2741 | -- 0, 1 or 2 layers left | |
2742 | if remaining > 0 then | |
2743 | T:go("R2") | |
2744 | outbound = not outbound | |
2745 | if remaining == 1 then | |
2746 | lib.singleLayer(R.length) | |
2747 | elseif remaining == 2 then | |
2748 | lib.doubleLayer(modifier, R.length) | |
2749 | end | |
2750 | end | |
2751 | end | |
2752 | if outbound then | |
2753 | T:go("R2F"..R.length) | |
2754 | else | |
2755 | T:forward(1) | |
2756 | end | |
2757 | direction = "D" -- reverse direction | |
2758 | if R.subChoice == 2 then | |
2759 | direction = "U" | |
2760 | end | |
2761 | if height > 0 then | |
2762 | T:go(direction..height.."R2") | |
2763 | else | |
2764 | T:go("R2") | |
2765 | end | |
2766 | return {} | |
2767 | end | |
2768 | ||
2769 | local function convertWater(R) -- 88 | |
2770 | --[[ | |
2771 | if dry need enough buckets to place along (width + length - 1) / 2 | |
2772 | use 12 buckets | |
2773 | start on floor + 1 | |
2774 | place slab down and water up along 2 edges. stay on this level | |
2775 | return round same 2 edges removing slabs and and placing them 1 above | |
2776 | placeUp water onto slabs on both edges | |
2777 | repeat recover slabs, place 1 above , placeUp water | |
2778 | ||
2779 | for sloping water, place full area with slabs | |
2780 | place sloping water on top of slabs | |
2781 | remove slabs | |
2782 | - | T:place("minecraft:dirt", "down", true) |
2782 | + | |
2783 | ]] | |
2784 | local lib = {} | |
2785 | ||
2786 | function lib.checkStartPosition() | |
2787 | --[[ | |
2788 | - | T:place("minecraft:dirt", "down", true) |
2788 | + | |
2789 | 1 W|S|F|F|F|F|F -- sloping flowing water | |
2790 | 2 W|F|F|F|F|F|F -- blocks removed after placing flowing water above | |
2791 | 3 W|S|S|S|S|S|S -- original sources | |
2792 | 4 W|?|?|?|?|?|? -- may be sources | |
2793 | ]] | |
2794 | -- need to be on floor or R.height if specified | |
2795 | local depth = 0 | |
2796 | local blockType = T:getBlockType("down") | |
2797 | local isWaterUp, isSourceUp = T:isWater("up") | |
2798 | local isWaterForward, isSourceForward = T:isWater("forward") | |
2799 | local isWaterDown, isSourceDown = T:isWater("down") | |
2800 | print("Block below is "..blockType) | |
2801 | print("Water above is "..tostring(isWaterUp)) | |
2802 | print("Water forward is "..tostring(isWaterForward)) | |
2803 | - | T:place("minecraft:dirt", "down", true) |
2803 | + | |
2804 | if blockType:find("water") == nil then -- on at least level 0 | |
2805 | - | blockType = T:getBlockType("down") |
2805 | + | |
2806 | sleep(2) | |
2807 | T:forward(1) | |
2808 | blockType = T:getBlockType("down") | |
2809 | - | T:place("minecraft:dirt", "down", true) |
2809 | + | |
2810 | print("Water found. Going down to floor") | |
2811 | depth = -1 | |
2812 | else | |
2813 | T:down(1) | |
2814 | blockType = T:getBlockType("down") | |
2815 | if blockType:find("water") ~= nil then | |
2816 | depth = -2 | |
2817 | else | |
2818 | return 0, "Not close to water. Aborting..." | |
2819 | end | |
2820 | end | |
2821 | end | |
2822 | while turtle.down() do | |
2823 | depth = depth + 1 | |
2824 | end | |
2825 | local emptyBuckets = utils.getEmptyBucketCount() | |
2826 | for i = depth, 0, -1 do | |
2827 | if emptyBuckets > 0 then | |
2828 | lib.fillBuckets() | |
2829 | emptyBuckets = utils.getEmptyBucketCount() | |
2830 | end | |
2831 | turtle.up() | |
2832 | end | |
2833 | ||
2834 | return depth, "" | |
2835 | end | |
2836 | ||
2837 | function lib.fillBuckets() | |
2838 | local emptyBuckets = utils.getEmptyBucketCount() | |
2839 | local direction = "forward"-- start with forward | |
2840 | local isWater, isSource, isIce = T:isWater(direction) | |
2841 | if emptyBuckets > 0 then | |
2842 | - | --T:go("x0x2F1x0x2") |
2842 | + | |
2843 | - | turtle.digDown() -- dig below |
2843 | + | |
2844 | - | while turtle.digUp() do end -- dig up including gravity blocks |
2844 | + | |
2845 | - | while not turtle.forward() do -- if no block in front, moves forward |
2845 | + | |
2846 | - | turtle.dig() -- block in front, so dig it |
2846 | + | |
2847 | isWater, isSource, isIce = T:isWater(direction) | |
2848 | - | turtle.digDown() -- now moved forward so dig down again |
2848 | + | |
2849 | - | while turtle.digUp() do end -- dig up again including gravity blocks |
2849 | + | |
2850 | end | |
2851 | end | |
2852 | end | |
2853 | if direction == "" then | |
2854 | print("Unable to locate water source") | |
2855 | - | --T:go("x0F1x0") |
2855 | + | |
2856 | - | while turtle.digUp() do end |
2856 | + | |
2857 | - | while not turtle.forward() do -- if no block in front, moves forward |
2857 | + | |
2858 | - | turtle.dig() -- block in front, so dig it |
2858 | + | |
2859 | sleep(0.3) | |
2860 | - | while turtle.digUp() do end |
2860 | + | |
2861 | print("Unable to fill bucket ".. i .." / "..emptyBuckets) | |
2862 | end | |
2863 | end | |
2864 | end | |
2865 | end | |
2866 | - | --T:go("x2F1x2") |
2866 | + | |
2867 | - | turtle.digDown() |
2867 | + | |
2868 | - | while not turtle.forward() do -- if no block in front, moves forward |
2868 | + | |
2869 | - | turtle.dig() -- block in front, so dig it |
2869 | + | |
2870 | for i = 1, length do | |
2871 | - | turtle.digDown() |
2871 | + | T:place("slab", -1, "down", false) |
2872 | if i < length then | |
2873 | T:forward(1) | |
2874 | end | |
2875 | end | |
2876 | end | |
2877 | ||
2878 | function lib.placeSources(length, place) | |
2879 | local moves = 1 | |
2880 | local waterBuckets = utils.getWaterBucketCount() | |
2881 | -- place sources alternate positions + start and finish | |
2882 | while moves < length do | |
2883 | if place then | |
2884 | if T:placeWater("up") then | |
2885 | print("Placed source up") | |
2886 | waterBuckets = waterBuckets - 1 | |
2887 | end | |
2888 | end | |
2889 | - | elseif R.down then -- single block wide trench dig R.down = 2 blocks deep |
2889 | + | |
2890 | if moves < length then | |
2891 | - | else -- single block wide = 1 block deep |
2891 | + | |
2892 | moves = moves + 1 | |
2893 | end | |
2894 | - | T:turnRight(2) -- turn at the top of the run |
2894 | + | |
2895 | - | T:forward(R.length - 1) -- return to start |
2895 | + | |
2896 | - | T:turnRight(2) -- turn round to original position |
2896 | + | |
2897 | - | else -- R.width 2 or more blocks |
2897 | + | |
2898 | - | local iterations = 0 -- R.width = 2, 4, 6, 8 etc |
2898 | + | T:place("slab", -1, "down", false) |
2899 | - | if R.width % 2 == 1 then -- R.width = 3, 5, 7, 9 eg R.width 7 |
2899 | + | |
2900 | - | iterations = (R.width - 1) / 2 -- iterations 1, 2, 3, 4 for widths 3, 5, 7, 9 |
2900 | + | |
2901 | if T:placeWater("up") then -- end of length | |
2902 | print("Placed final source up") | |
2903 | end | |
2904 | - | for i = 1, iterations do -- eg 3 blocks wide, iterations = 1 |
2904 | + | |
2905 | end | |
2906 | ||
2907 | function lib.moveSlabs(length) | |
2908 | for i = 1, length do | |
2909 | T:dig("down") | |
2910 | T:up(1) | |
2911 | T:place("slab", -1, "down", true) | |
2912 | if i < length then | |
2913 | T:forward(1) | |
2914 | T:down(1) | |
2915 | end | |
2916 | end | |
2917 | end | |
2918 | ||
2919 | function lib.recoverSlabs(length) | |
2920 | for i = 1, length do | |
2921 | T:dig("down") | |
2922 | if i < length then | |
2923 | T:forward(1) | |
2924 | end | |
2925 | end | |
2926 | end | |
2927 | ||
2928 | local depth, message = lib.checkStartPosition() | |
2929 | if message ~= "" then | |
2930 | return {message} | |
2931 | end | |
2932 | local maxDepth = R.height | |
2933 | local buckets = utils.getWaterBucketCount() | |
2934 | R = utils.calculateDimensions(R) -- if R.width or R.length == 0 | |
2935 | T:down(depth) | |
2936 | lib.placeSlabs(R.length) | |
2937 | T:go("R1") | |
2938 | lib.placeSlabs(R.width) | |
2939 | T:go("R2") | |
2940 | ||
2941 | while depth > 0 do | |
2942 | local place = true | |
2943 | lib.fillBuckets() | |
2944 | place = lib.placeSources(R.width, place) | |
2945 | T:go("L1") | |
2946 | place = lib.placeSources(R.length, place) | |
2947 | lib.fillBuckets() | |
2948 | T:go("R2") | |
2949 | lib.moveSlabs(R.length) -- dig slab from below, move up and replace below | |
2950 | T:go("R1F1D1") | |
2951 | lib.moveSlabs(R.width - 1) | |
2952 | T:go("R2") -- now moved up 1 layer | |
2953 | depth = depth - 1 | |
2954 | if depth == 0 then | |
2955 | place = lib.placeSources(R.width, true) | |
2956 | T:go("L1") | |
2957 | place = lib.placeSources(R.length, place) | |
2958 | T:go("R2") | |
2959 | lib.recoverSlabs(R.length) | |
2960 | T:go("R1") | |
2961 | lib.recoverSlabs(R.width) | |
2962 | end | |
2963 | end | |
2964 | ||
2965 | return {} | |
2966 | end | |
2967 | ||
2968 | local function createBoatLift(R) -- 59 state:0=new, size:1=extend, side:0=left, 1=right | |
2969 | -- build stepped lift with fencing gates and soul sand | |
2970 | local lib = {} | |
2971 | ||
2972 | function lib.getWater(backToWater, downToWater) | |
2973 | if backToWater > 0 then | |
2974 | utils.goBack(backToWater) | |
2975 | end | |
2976 | if downToWater > 0 then | |
2977 | T:down(downToWater) | |
2978 | end | |
2979 | T:getWater("down") -- take water from source | |
2980 | sleep(0.2) | |
2981 | T:getWater("down") -- take water from source | |
2982 | if downToWater > 0 then | |
2983 | T:up(downToWater) | |
2984 | end | |
2985 | if backToWater > 0 then | |
2986 | T:forward(backToWater) | |
2987 | end | |
2988 | end | |
2989 | ||
2990 | --T:place(blockType, damageNo, direction, leaveExisting, signText) | |
2991 | ||
2992 | local backToWater = 0 | |
2993 | local downToWater = 0 | |
2994 | ||
2995 | T:go("R1F1L1") -- over canal facing forward | |
2996 | for h = 1, R.height do | |
2997 | lib.getWater(backToWater, downToWater) -- check water supplies, return to starting position | |
2998 | T:go("L1C1 R1D1 L1C1 R1", false, 0, false) -- place towpath, forward, down, place towpath, face forward | |
2999 | T:place("soul", -1, "down", false) -- place soulsand down | |
3000 | T:place("soul", -1, "forward", false) -- place soulsand forward | |
3001 | T:go("R1F1C1L1", false, 0, false) -- place right towpath face forward | |
3002 | T:place("soul", -1, "down", false) -- place soulsand down | |
3003 | T:place("soul", -1, "forward", false) -- place soulsand forward | |
3004 | - | menu item: Clear hollow structure |
3004 | + | |
3005 | T:placeWater("down") -- place water down | |
3006 | - | if outside active area will have already moved in |
3006 | + | |
3007 | - | R.direction = "up" or "down" as direction of travel |
3007 | + | T:place("gate", -1, "forward", false) -- place fence gate |
3008 | - | R.up = true / false to dig up as well |
3008 | + | |
3009 | - | R.down = true / false to dig down as well |
3009 | + | |
3010 | - | R.data.ceiling = true / false to remove ceiling |
3010 | + | |
3011 | - | R.data.floor = true / false to remove floor |
3011 | + | T:place("gate", -1, "forward", false) -- place fence gate |
3012 | - | examples use a 5 x 5 x 7 cube |
3012 | + | |
3013 | T:go("R1F1 L1x1 R1C1") | |
3014 | - | --utils.printR(R) -- debug values in R |
3014 | + | |
3015 | - | local height = 1 -- current level of turtle |
3015 | + | |
3016 | - | local cleared = false |
3016 | + | |
3017 | backToWater = 1 | |
3018 | - | R.up = false |
3018 | + | |
3019 | - | R.down = false |
3019 | + | |
3020 | - | -- check if floor/ceiling is to be cleared |
3020 | + | |
3021 | - | if R.direction == "up" then -- from bottom to top |
3021 | + | |
3022 | - | if R.data.floor then |
3022 | + | |
3023 | - | clearRectangle(R) |
3023 | + | |
3024 | - | cleared = true |
3024 | + | |
3025 | T:go("D1 L1C1 U1C1") -- build left towpath, facing towpath, above water level | |
3026 | - | else -- from top to bottom |
3026 | + | |
3027 | - | if R.data.ceiling then |
3027 | + | |
3028 | - | clearRectangle(R) |
3028 | + | |
3029 | - | cleared = true |
3029 | + | |
3030 | utils.goBack(1) | |
3031 | T:go("L1F1") | |
3032 | T:placeWater("down") | |
3033 | - | if R.height == 1 and not cleared then -- only 1 layer, perimeter only eg R.height = 7 |
3033 | + | |
3034 | return {} | |
3035 | - | elseif R.height == 2 and not cleared then -- only 2 layers, perimeter only |
3035 | + | |
3036 | - | if R.direction == "up" then -- from bottom to top |
3036 | + | |
3037 | local function createBorehole(R) | |
3038 | --[[go down to bedrock and return. Chart all blocks dug/ passed through]] | |
3039 | local diary = {} | |
3040 | local lib = {} | |
3041 | local depth = R.height -- eg 63 start position | |
3042 | - | elseif R.height >= 3 then -- 3 or more levels, floor/ceiling already assessed eg R.height = 7 |
3042 | + | |
3043 | --R.height = current level | |
3044 | ||
3045 | - | height = height + utils.move(R, 1) -- move up/down 1 block for first layer eg height: 1 + 1 = 2 |
3045 | + | |
3046 | - | -- height h + 3 R.height loop |
3046 | + | |
3047 | - | -- 2 5 5 end |
3047 | + | |
3048 | - | -- 2 5 7 + |
3048 | + | |
3049 | - | -- 5 8 7 end |
3049 | + | |
3050 | - | repeat |
3050 | + | |
3051 | - | clearPerimeter(R) -- runs at least once, removes 3 layers: 1,2,3 |
3051 | + | |
3052 | - | local move = 3 |
3052 | + | |
3053 | - | --if height + 3 < R.height then -- range with min 3(0), 4(1), 5(2), 6(3), 7(4), 8(5), 9(6) etc |
3053 | + | |
3054 | - | --height = height + utils.move(R, move) -- move up/down 3 blocks eg height 5, 8, 11, 14 |
3054 | + | |
3055 | - | --else |
3055 | + | |
3056 | - | --move = R.height - height - 1 |
3056 | + | |
3057 | - | --height = height + utils.move(R, move) -- move up/down 1-2 blocks eg height = 2 + 3 = 5 |
3057 | + | |
3058 | end | |
3059 | end | |
3060 | - | if height + 3 >= R.height then -- range with min 3(0), 4(1), 5(2), 6(3), 7(4), 8(5), 9(6) etc |
3060 | + | |
3061 | - | move = R.height - height |
3061 | + | |
3062 | end | |
3063 | - | height = height + utils.move(R, move) -- move up/down 1-2 blocks eg height = 2 + 3 = 5 |
3063 | + | |
3064 | - | until height > R.height - 3 -- min 3 levels eg height = 2, R.height - 3 --> 7 - 3 = 4, 4 - 3 = 1 |
3064 | + | |
3065 | return diary | |
3066 | - | R.down = false |
3066 | + | |
3067 | - | if height == R.height then -- already on top/bottom layer eg height = 5, R.height = 5 |
3067 | + | |
3068 | - | if R.direction == "up" then -- reverse digging direction. Up = move to top and dig down |
3068 | + | |
3069 | - | R.down = true |
3069 | + | |
3070 | - | else -- reverse digging direction. Up = move to floor and dig up |
3070 | + | |
3071 | - | R.up = true |
3071 | + | |
3072 | return item | |
3073 | - | clearPerimeter(R) |
3073 | + | |
3074 | ||
3075 | - | if R.direction == "up" then -- reverse digging direction. Up = move to top and dig down |
3075 | + | |
3076 | - | R.down = true |
3076 | + | |
3077 | - | else -- reverse digging direction. Up = move to floor and dig up |
3077 | + | |
3078 | - | R.up = true |
3078 | + | |
3079 | for l = 1, levelsPerCol do -- add 32 empty strings | |
3080 | table.insert(lines, "") | |
3081 | - | clearPerimeter(R) |
3081 | + | |
3082 | local lineNo = 1 | |
3083 | for k, v in ipairs(diary) do | |
3084 | local level = R.height - k -- eg 63 range 63 to -59 | |
3085 | - | R.up = false |
3085 | + | |
3086 | - | R.down = false |
3086 | + | |
3087 | - | if R.direction == "up" then |
3087 | + | |
3088 | - | if R.data.ceiling then -- from bottom to top |
3088 | + | |
3089 | - | clearRectangle(R) |
3089 | + | |
3090 | lev = "-0"..math.abs(level).." " -- "-09 " to "-01 " | |
3091 | - | elseif R.direction == "down" then |
3091 | + | |
3092 | - | if R.data.floor then -- from top to bottom |
3092 | + | |
3093 | - | clearRectangle(R) |
3093 | + | |
3094 | lev = " "..level.." " -- " 10 " to " 99 " | |
3095 | else | |
3096 | lev = " "..level.." " -- " 100 " to " 319 " | |
3097 | end | |
3098 | local output = lev..item -- eg "-10 grass_block" | |
3099 | if #output > 20 then -- eg "-10 some_long_block_name" | |
3100 | output = output:sub(1, 20) -- eg "-10 some_long_block_" | |
3101 | else | |
3102 | output = menu.padRight(output, 20, " ") -- eg "-10 grass_block " | |
3103 | end | |
3104 | lines[lineNo] = lines[lineNo]..output -- add new entry to this line | |
3105 | lineNo = lineNo + 1 -- increase line no | |
3106 | if lineNo > levelsPerCol then -- past last line number | |
3107 | lineNo = 1 -- reset to 1 | |
3108 | end | |
3109 | end | |
3110 | ||
3111 | local fileName = "borehole"..os.getComputerID()..".txt" | |
3112 | local handle = fs.open(fileName, "w") --create file eg "borehole0.txt" | |
3113 | handle.writeLine("Level Block Level Block Level Block Level Block") | |
3114 | for k,v in ipairs(lines) do | |
3115 | handle.writeLine(v) | |
3116 | end | |
3117 | ||
3118 | handle.close() | |
3119 | ||
3120 | return fileName | |
3121 | end | |
3122 | ||
3123 | local blockType = T:getBlockType("down") | |
3124 | while T:down(1) do | |
3125 | depth = depth - 1 | |
3126 | moves = moves + 1 | |
3127 | if depth == R.depth then | |
3128 | break | |
3129 | end | |
3130 | diary = lib.addBlock(depth, blockType, diary) | |
3131 | blockType = T:getBlockType("down") | |
3132 | end | |
3133 | local fileName = lib.writeReport(R, diary) | |
3134 | T:up(moves) | |
3135 | ||
3136 | return {"File '"..fileName.."' written"} | |
3137 | end | |
3138 | ||
3139 | local function createBubbleLift(R) -- 15 | |
3140 | local lib = {} | |
3141 | ||
3142 | function lib.addLayer() | |
3143 | T:go("F2 L1C1 R1C1 R1C1 L1", false, 0, true) | |
3144 | turtle.back() | |
3145 | T:dig("up") -- clear block above so completed lift can be found | |
3146 | T:placeWater("forward") | |
3147 | turtle.back() | |
3148 | T:go("C1x0") | |
3149 | end | |
3150 | - | T:place("minecraft:torch", "down", false) ---(self, blockType, damageNo, direction, leaveExisting, signText) |
3150 | + | |
3151 | function lib.addSign() | |
3152 | turtle.back() | |
3153 | T:placeWater("forward") | |
3154 | T:go("L1B1") | |
3155 | T:place("sign", -1, "forward") | |
3156 | end | |
3157 | ||
3158 | function lib.buildLift(toHeight) | |
3159 | local built = lib.goToWater() -- returns lift blocks already placed, total height of drop from starting point | |
3160 | local toBuild = toHeight - built -- no of blocks remaining to increase lift size | |
3161 | local water = 0 | |
3162 | while toBuild > 0 do -- at least 1 block height remaining | |
3163 | water = lib.fillBuckets(toBuild, false) -- no of water buckets onboard (could be more than required) | |
3164 | if water > toBuild then -- more water than required | |
3165 | water = toBuild -- reduce to correct amount | |
3166 | end | |
3167 | T:up(built) -- climb to top of existing lift | |
3168 | while water > 0 and toBuild > 0 do | |
3169 | lib.addLayer() | |
3170 | water = water - 1 | |
3171 | T:up(1) | |
3172 | toBuild = toBuild - 1 | |
3173 | end | |
3174 | -- may still be some height to complete, but needs refill | |
3175 | if toBuild > 0 then | |
3176 | built = lib.goToWater() --return to source | |
3177 | toBuild = toHeight - built | |
3178 | --lib.fillBuckets(toBuild) | |
3179 | end | |
3180 | end | |
3181 | end | |
3182 | ||
3183 | function lib.cleanUp(fromHeight) | |
3184 | local plug = false | |
3185 | T:turnRight(2) | |
3186 | for i = 1, fromHeight do | |
3187 | plug = false | |
3188 | if turtle.detect() then | |
3189 | plug = true | |
3190 | end | |
3191 | turtle.down() | |
3192 | if plug then | |
3193 | T:place("stone", -1, "up") | |
3194 | end | |
3195 | end | |
3196 | T:go("D1 C1R1x1 R1C1 R1F1 R1x1 L2x1 L1C1 x1") -- delete water sources | |
3197 | T:go("D1 C1R1x1 R1") | |
3198 | local blockType = T:getBlockType("forward") | |
3199 | if blockType:find("dirt") == nil and blockType:find("soul") == nil then -- not dirt or soul sand in front | |
3200 | T:go("C1") | |
3201 | end | |
3202 | T:go("R1F1 R1x1 L2x1 L1C1 x1") | |
3203 | end | |
3204 | ||
3205 | function lib.fillBuckets(toBuild, withSort) | |
3206 | local emptySlots, water = lib.stackBuckets(withSort)-- gets no of empty slots + no of water buckets | |
3207 | if water < toBuild then -- no of water buckets onboard less than required quantity | |
3208 | for i = 1, toBuild do -- fill required no of buckets up to max space in inventory | |
3209 | if emptySlots == 0 then -- inventory full | |
3210 | break | |
3211 | else | |
3212 | if T:getWater("down") then | |
3213 | water = water + 1 | |
3214 | sleep(0.5) | |
3215 | end | |
3216 | end | |
3217 | emptySlots = lib.getEmptySlots() | |
3218 | end | |
3219 | end | |
3220 | ||
3221 | return water | |
3222 | end | |
3223 | ||
3224 | function lib.getEmptySlots() | |
3225 | local empty = 0 | |
3226 | for i = 1, 16 do | |
3227 | if turtle.getItemCount(i) == 0 then | |
3228 | empty = empty + 1 | |
3229 | end | |
3230 | end | |
3231 | return empty | |
3232 | end | |
3233 | ||
3234 | function lib.goToWater() | |
3235 | local built = 0 -- measures completed lift height | |
3236 | while turtle.down() do -- takes turtle to bottom of water source | |
3237 | if turtle.detect() then | |
3238 | built = built + 1 | |
3239 | end | |
3240 | end | |
3241 | T:up(1) -- above watersource ready to fill buckets | |
3242 | -- height = height - 1 | |
3243 | -- built = built - 1 not required as next block is water source: not detected | |
3244 | return built -- , height | |
3245 | end | |
3246 | ||
3247 | function lib.stackBuckets(withSort) | |
3248 | if withSort == nil then withSort = false end | |
3249 | local data = {} | |
3250 | local bucketSlot = 0 | |
3251 | local emptySlots = 0 | |
3252 | local water = 0 | |
3253 | if withSort then | |
3254 | T:sortInventory() | |
3255 | end | |
3256 | for i = 1, 16 do | |
3257 | -- find first empty bucket | |
3258 | if turtle.getItemCount(i) > 0 then | |
3259 | data = turtle.getItemDetail(i) | |
3260 | if data.name == "minecraft:bucket" then | |
3261 | if bucketSlot == 0 then | |
3262 | bucketSlot = i | |
3263 | else | |
3264 | turtle.select(i) | |
3265 | turtle.transferTo(bucketSlot) | |
3266 | end | |
3267 | elseif data.name == "minecraft:water_bucket" then | |
3268 | water = water + 1 | |
3269 | end | |
3270 | else | |
3271 | emptySlots = emptySlots + 1 | |
3272 | end | |
3273 | end | |
3274 | return emptySlots, water | |
3275 | end | |
3276 | ||
3277 | ||
3278 | T:go("C1R1") -- place block next to ladder support block, turn right to check ladder | |
3279 | local blockType = T:getBlockType("forward") -- Is there a ladder to the right? | |
3280 | if blockType:find("ladder") == nil then | |
3281 | T:go("C1L2") -- Place block as ladder not present | |
3282 | else -- ladder present | |
3283 | T:go("L2") -- ready to check other side | |
3284 | end | |
3285 | blockType = T:getBlockType("forward") | |
3286 | if blockType:find("ladder") == nil then | |
3287 | T:go("C1R1") | |
3288 | else | |
3289 | T:go("R1") | |
3290 | end | |
3291 | blockType = T:getBlockType("down") | |
3292 | local dirt = "minecraft:dirt" | |
3293 | if T:getItemSlot("minecraft:soul_sand") > 0 then | |
3294 | dirt = "minecraft:soul_sand" | |
3295 | end | |
3296 | if blockType:find("bedrock") ~= nil then | |
3297 | utils.goBack(1) | |
3298 | T:place(dirt, -1, "forward", false) -- placed at end of potential water source, next to ladder | |
3299 | else | |
3300 | T:place(dirt, -1, "down", false) -- placed in ground, next to ladder | |
3301 | utils.goBack(1) | |
3302 | T:placeWater("forward") -- place extra water source | |
3303 | end | |
3304 | T:go("R1C1 R2C1 L1F1C2 R1C1 L2C1 R1F1C2 R1C1 L1C1 L1C1 L1F1", false, 0, true) | |
3305 | -- ready for water sources to be placed | |
3306 | T:placeWater("forward") -- place front water source | |
3307 | T:turnRight(2) -- facing backward | |
3308 | T:placeWater("forward") -- place back water source | |
3309 | T:go("R2U1") -- facing forward, U1, above centre of water source | |
3310 | lib.fillBuckets(R.height, true) -- fill as many buckets as required or until inventory full, sort inventory as well | |
3311 | local nextToLadder = false | |
3312 | --T:go("F2R1") | |
3313 | T:go("x0F1 x0F1C1 R1") -- move forward 2 taking out blocks above, plug behind soul sand | |
3314 | if T:getBlockType("forward"):find("ladder") == nil then -- no ladder here | |
3315 | T:turnLeft(2) | |
3316 | if T:getBlockType("forward"):find("ladder") ~= nil then -- ladder here | |
3317 | nextToLadder = true | |
3318 | end | |
3319 | T:turnRight(1) | |
3320 | else | |
3321 | nextToLadder = true | |
3322 | T:turnLeft(1) | |
3323 | end | |
3324 | -- now above soul sand, facing forward | |
3325 | if nextToLadder then -- if nextToLadder, no need for signs | |
3326 | utils.goBack(2) -- return to source centre | |
3327 | else | |
3328 | T:go("F2 L1C1R1C1R1C1L1", false, 0, true) -- prepare layer 1 | |
3329 | lib.addSign() | |
3330 | T:go("U1F1R1F1 L1C1R1C1R1C1L1", false, 0, true) -- prepare layer 2 | |
3331 | lib.addSign() | |
3332 | T:go("L1F1 R1F1R1", false, 0, true) -- above source, level 2 | |
3333 | end | |
3334 | -- ready to build lift | |
3335 | lib.buildLift(R.height - 1) | |
3336 | lib.cleanUp(R.height - 1) | |
3337 | ||
3338 | return {"Bubble lift created", "Check correct operation", "Check exit before using" } | |
3339 | end | |
3340 | ||
3341 | local function createBubbleTrap(R) -- 34 | |
3342 | --[[ | |
3343 | Replace floor of existing volume of water with soulsand | |
3344 | Used in river biome for squid farm. Area should be enclosed | |
3345 | with solid walls surface to floor. | |
3346 | Usually 7 blocks wide | |
3347 | ]] | |
3348 | local lib = {} | |
3349 | ||
3350 | function lib.clearDown(depth) | |
3351 | while utils.clearVegetation("down") do | |
3352 | T:down(1) | |
3353 | depth = depth + 1 | |
3354 | end | |
3355 | T:place("soul_sand", -1, "down", false) | |
3356 | return depth | |
3357 | end | |
3358 | ||
3359 | function lib.clearLength(length, depth) | |
3360 | local moves = 0 | |
3361 | while moves < length - 1 do | |
3362 | if utils.clearVegetation("forward") then | |
3363 | T:forward(1) | |
3364 | moves = moves + 1 | |
3365 | depth = lib.clearDown(depth) -- go down if in water/air | |
3366 | if moves >= length - 1 then | |
3367 | return depth | |
3368 | end | |
3369 | else -- block in front | |
3370 | local waterAhead = utils.clearVegetation("forward") -- true if air/water in front | |
3371 | while not waterAhead do -- solid block in front | |
3372 | T:up(1) | |
3373 | depth = depth - 1 | |
3374 | if depth < 1 then | |
3375 | return 0 | |
3376 | end | |
3377 | waterAhead = utils.clearVegetation("forward") | |
3378 | end | |
3379 | end | |
3380 | end | |
3381 | ||
3382 | return depth | |
3383 | end | |
3384 | ||
3385 | function lib.turn(facingForward, depth) | |
3386 | local direction = "R" | |
3387 | if not facingForward then | |
3388 | direction = "L" | |
3389 | end | |
3390 | T:go(direction.. 1) | |
3391 | if utils.clearVegetation("forward") then | |
3392 | T:forward(1) | |
3393 | depth = depth + lib.clearDown(depth) | |
3394 | else | |
3395 | while not utils.clearVegetation("forward") do | |
3396 | T:up(1) | |
3397 | depth = depth - 1 | |
3398 | end | |
3399 | end | |
3400 | T:go(direction.. 1) | |
3401 | ||
3402 | return depth | |
3403 | end | |
3404 | ||
3405 | local depth = 0 | |
3406 | local length = 0 | |
3407 | local width = 0 | |
3408 | local outbound = true | |
3409 | local facingForward = true | |
3410 | local inWater, onWater = utils.getWaterStatus() | |
3411 | inWater, onWater = utils.startWaterFunction(onWater, inWater, 2 ,true) -- move into water, max descent 2 | |
3412 | if R.length == 0 then | |
3413 | R.length = lib.getLength() | |
3414 | end | |
3415 | if R.width == 0 then | |
3416 | T:turnRight(1) | |
3417 | R.width = lib.getLength() | |
3418 | T:turnLeft(1) | |
3419 | end | |
3420 | -- go down to floor | |
3421 | depth = lib.clearDown(depth) | |
3422 | while width < R.width do | |
3423 | -- now on floor, move along sea/river bed following contour | |
3424 | depth = lib.clearLength(R.length, depth) | |
3425 | width = width + 1 | |
3426 | -- now turn and repeat | |
3427 | if width < R.width then | |
3428 | depth = lib.turn(facingForward, depth) | |
3429 | facingForward = not facingForward | |
3430 | end | |
3431 | end | |
3432 | -- finished so return to surface | |
3433 | T:up(1) -- up 1 to check for water below | |
3434 | while T:isWater("down") do | |
3435 | T:up(1) | |
3436 | end | |
3437 | ||
3438 | return {} | |
3439 | end | |
3440 | ||
3441 | local function createCorridor(R) -- 52 | |
3442 | --[[create a corridoor 2 blocks high, with floor and ceiling guaranteed | |
3443 | T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)]] | |
3444 | local lib = {} | |
3445 | ||
3446 | function lib.continue(R, currentSteps, totalSteps) | |
3447 | if not R.silent then | |
3448 | if currentSteps >= 64 and R.length == 0 then | |
3449 | -- request permission to continue if infinite | |
3450 | T:clear() | |
3451 | print("Completed "..totalSteps..". Ready for 64 more") | |
3452 | print("Do you want to continue? (y/n)") | |
3453 | response = read() | |
3454 | if response:lower() ~= "y" then | |
3455 | return true, 0 | |
3456 | else | |
3457 | return false, currentSteps | |
3458 | end | |
3459 | end | |
3460 | end | |
3461 | return true, currentSteps | |
3462 | end | |
3463 | ||
3464 | function lib.seal() | |
3465 | local blockType = T:getBlockType("forward") | |
3466 | if blockType:find("water") ~= nil then | |
3467 | T:place("stone", 0, "forward", false) | |
3468 | return "water" -- water found | |
3469 | elseif blockType:find("lava") ~= nil then | |
3470 | T:place("stone", 0, "forward", false) | |
3471 | return "lava" -- lava found | |
3472 | end | |
3473 | return "" -- no water or lava | |
3474 | end | |
3475 | ||
3476 | function lib.checkSeal(R) | |
3477 | local fluidType = "" | |
3478 | if R.data == "seal" then -- check for lava/water at the sides | |
3479 | T:turnRight(1) | |
3480 | fluidType = lib.seal() -- could be "", "water", "lava" | |
3481 | T:turnLeft(2) | |
3482 | local blockType = lib.seal() | |
3483 | if fluidType == "" then -- no water / lava so far | |
3484 | fluidType = blockType -- could be "", "water", "lava" | |
3485 | end | |
3486 | T:turnRight(1) | |
3487 | end | |
3488 | return fluidType -- could be "", "water", "lava" | |
3489 | end | |
3490 | ||
3491 | function lib.placeTorch(R, torchSpaces, totalSteps) | |
3492 | if R.torchInterval > 0 then -- torches onboard | |
3493 | if torchSpaces == R.torchInterval then -- time to place another torch | |
3494 | if totalSteps < R.length then -- not at end of run | |
3495 | if T:getItemSlot("minecraft:torch") > 0 then | |
3496 | T:place("minecraft:torch", -1, "down") | |
3497 | end | |
3498 | torchSpaces = 1 | |
3499 | end | |
3500 | end | |
3501 | end | |
3502 | return torchSpaces -- original value or 1 | |
3503 | end | |
3504 | ||
3505 | local currentSteps = 0 -- counter for infinite length. pause every 64 blocks | |
3506 | local totalSteps = 0 -- counter for all steps so far | |
3507 | local torchSpaces = R.torchInterval -- if torches present, counter to place with 8 blocks between | |
3508 | local fluidType = "" | |
3509 | local damLength = 0 | |
3510 | local damStarted = false | |
3511 | local doContinue = true | |
3512 | if T:getItemSlot("minecraft:torch") == 0 then | |
3513 | R.torchInterval = 0 -- set to default 9 in getTask() | |
3514 | end | |
3515 | for steps = 1, R.length do | |
3516 | -- starts on floor of tunnel | |
3517 | doContinue, currentSteps = lib.continue(R, currentSteps, totalSteps) -- continue tunnelling? | |
3518 | if not doContinue then | |
3519 | break | |
3520 | end | |
3521 | T:go("C2U1C0", false, 0, true) -- place floor, up 1, place ceiling | |
3522 | fluidType = lib.checkSeal(R) -- if R.data == "seal", check for water/lava at ceiling level | |
3523 | if fluidType == "" then -- either R.data ~= "seal" or no fluid found | |
3524 | torchSpaces = lib.placeTorch(R, torchSpaces, totalSteps) -- original value or 1 if torch placed | |
3525 | T:go("F1D1") | |
3526 | elseif fluidType == "water" then | |
3527 | T:go("F1R2 C1D1 C1L2", false, 0, true) | |
3528 | damStarted = true | |
3529 | damLength = damLength + 1 | |
3530 | else --lava | |
3531 | T:go("F1D1") | |
3532 | end | |
3533 | blockType = lib.checkSeal(R) | |
3534 | if blockType ~= "" then | |
3535 | fluidType = blockType | |
3536 | end | |
3537 | currentSteps = currentSteps + 1 | |
3538 | totalSteps = totalSteps + 1 | |
3539 | torchSpaces = torchSpaces + 1 | |
3540 | if damStarted and fluidType == "" then -- was in water, but no more | |
3541 | T:go("R2 F"..damLength + 1 .."U1L2F"..damLength + 1 .."D1") | |
3542 | damStarted = false | |
3543 | end | |
3544 | end | |
3545 | if fluidType ~= "" then -- water or lava found while tunnelling | |
3546 | T:go("U1C0", false, 0, true) | |
3547 | lib.checkSeal(R) | |
3548 | T:go("C1", false, 0, true) | |
3549 | T:down(1) | |
3550 | end | |
3551 | return {} | |
3552 | end | |
3553 | ||
3554 | local function createDragonTrap() -- 49 | |
3555 | local lib = {} | |
3556 | ||
3557 | function lib.attack() | |
3558 | local totalHitsF = 0 | |
3559 | local totalHitsU = 0 | |
3560 | local totalHitsD = 0 | |
3561 | while true do | |
3562 | local hitF = false | |
3563 | local hitU = false | |
3564 | local hitD = false | |
3565 | if turtle.attackUp() then | |
3566 | hitU = true | |
3567 | totalHitsU = totalHitsU + 1 | |
3568 | end | |
3569 | if turtle.attackDown() then | |
3570 | hitD = true | |
3571 | totalHitsD = totalHitsD + 1 | |
3572 | end | |
3573 | if turtle.attack() then | |
3574 | hitF = true | |
3575 | totalHitsF = totalHitsF + 1 | |
3576 | end | |
3577 | if hitF or hitU or hitD then | |
3578 | print("hits forward: "..totalHitsF..", up: "..totalHitsU..", down: "..totalHitsD) | |
3579 | end | |
3580 | end | |
3581 | end | |
3582 | -- build up 145 blocks with ladders | |
3583 | T:clear() | |
3584 | menu.colourPrint("Press Enter to start 1 minute delay\n", colors.red) | |
3585 | menu.colourPrint("Run to island centre across the bridge\n", colors.orange) | |
3586 | menu.colourPrint("You have already made the bridge?...", colors.lime) | |
3587 | read() | |
3588 | for t = 60, 1, -1 do | |
3589 | sleep(1) | |
3590 | T:clear() | |
3591 | io.write("Starting in "..t.. " seconds ") | |
3592 | end | |
3593 | for i = 1, 145 do | |
3594 | T:go("U1C2") | |
3595 | turtle.back() | |
3596 | T:place("minecraft:ladder", -1, "down") | |
3597 | turtle.forward() | |
3598 | end | |
3599 | T:go("R2F1C1 L1C1 L2C1 R1") | |
3600 | for i = 1, 100 do | |
3601 | T:go("F1C2U1C0D1") | |
3602 | end | |
3603 | T:forward(1) | |
3604 | T:place("minecraft:obsidian", -1, "down") | |
3605 | T:go("R2F1x2R2") | |
3606 | T:placeWater("forward") | |
3607 | T:go("R2F6R2") | |
3608 | lib.attack() | |
3609 | ||
3610 | return {} | |
3611 | end | |
3612 | ||
3613 | local function createEnderTower(stage) -- 66 | |
3614 | --[[ lower base = stage 1, upper base = 2, tower = 3 ]] | |
3615 | local lib = {} | |
3616 | --[[ go(path, useTorch, torchInterval, leaveExisting, preferredBlock) ]] | |
3617 | function lib.getEmptySlots() | |
3618 | local empty = 0 | |
3619 | for i = 1, 16 do | |
3620 | if turtle.getItemCount(i) == 0 then | |
3621 | empty = empty + 1 | |
3622 | end | |
3623 | end | |
3624 | return empty | |
3625 | end | |
3626 | ||
3627 | function lib.getStone(direction, stacks) | |
3628 | --[[ get block user wants to use ]] | |
3629 | local suck = turtle.suck | |
3630 | if direction == "down" then | |
3631 | suck = turtle.suckDown | |
3632 | end | |
3633 | if T:getBlockType(direction) == "minecraft:chest" then | |
3634 | T:sortInventory() | |
3635 | local slot = T:getFirstEmptySlot() --find spare slot | |
3636 | if slot > 0 then --empty slot found | |
3637 | turtle.select(1) | |
3638 | if stacks == 0 then | |
3639 | while suck() do end | |
3640 | else | |
3641 | for i = 1, stacks do -- get # stacks of stone from chest | |
3642 | suck() | |
3643 | end | |
3644 | end | |
3645 | if T:getSlotContains(slot) == "" then | |
3646 | return T:getMostItem() -- empty chest | |
3647 | else | |
3648 | return T:getSlotContains(slot) -- use this as default building block | |
3649 | end | |
3650 | else | |
3651 | return T:getMostItem() -- full inventory | |
3652 | end | |
3653 | else | |
3654 | - | utils.waitForInput() |
3654 | + | |
3655 | end | |
3656 | end | |
3657 | ||
3658 | function lib.stackBuckets() | |
3659 | local data = {} | |
3660 | local bucketSlot = 0 | |
3661 | local emptySlots = 0 | |
3662 | - | utils.waitForInput() |
3662 | + | |
3663 | T:sortInventory() | |
3664 | for i = 1, 16 do | |
3665 | -- find first empty bucket | |
3666 | if turtle.getItemCount(i) > 0 then | |
3667 | data = turtle.getItemDetail(i) | |
3668 | if data.name == "minecraft:bucket" then | |
3669 | if bucketSlot == 0 then | |
3670 | bucketSlot = i | |
3671 | else | |
3672 | turtle.select(i) | |
3673 | turtle.transferTo(bucketSlot) | |
3674 | end | |
3675 | elseif data.name == "minecraft:water_bucket" then | |
3676 | water = water + 1 | |
3677 | end | |
3678 | else | |
3679 | emptySlots = emptySlots + 1 | |
3680 | end | |
3681 | end | |
3682 | return emptySlots, water | |
3683 | end | |
3684 | ||
3685 | function lib.countWaterBuckets() | |
3686 | local data = {} | |
3687 | local buckets = 0 | |
3688 | for i = 1, 16 do | |
3689 | data = turtle.getItemDetail(i) | |
3690 | if data.name == "minecraft:water_bucket" then | |
3691 | buckets = buckets + 1 | |
3692 | end | |
3693 | end | |
3694 | return buckets | |
3695 | end | |
3696 | ||
3697 | function lib.baseRun(preferredBlock, count, turn) | |
3698 | for i = 1, count do | |
3699 | T:go("C2F1", false, 0, false, preferredBlock) | |
3700 | end | |
3701 | T:go("C2"..turn, false, 0, false, preferredBlock) | |
3702 | end | |
3703 | ||
3704 | function lib.outsideRun(preferredBlock) | |
3705 | T:place("fence", -1, "down", false) | |
3706 | T:forward(1) | |
3707 | T:place(preferredBlock, -1, "down", false) | |
3708 | T:forward(1) | |
3709 | T:place(preferredBlock, -1, "down", false) | |
3710 | T:forward(2) | |
3711 | T:place(preferredBlock, -1, "down", false) | |
3712 | end | |
3713 | ||
3714 | function lib.signRun(preferredBlock ,message) | |
3715 | T:place(preferredBlock, -1, "down", false) | |
3716 | T:forward(4) | |
3717 | T:place(preferredBlock, -1, "down", false) | |
3718 | turtle.back() | |
3719 | turtle.back() | |
3720 | T:down(1) | |
3721 | T:place("sign", -1, "forward", false, message) | |
3722 | T:go("U1F2") | |
3723 | end | |
3724 | ||
3725 | function lib.goToWater(height) | |
3726 | local built = 0 -- measures completed lift height | |
3727 | while turtle.down() do -- takes turtle to bottom of water source | |
3728 | height = height + 1 | |
3729 | if turtle.detect() then | |
3730 | built = built + 1 | |
3731 | - | utils.waitForInput() |
3731 | + | |
3732 | end | |
3733 | T:up(1) -- above watersource assuming it is 1-1.5 blocks deep | |
3734 | height = height - 1 | |
3735 | -- built = built - 1 not required as next block is water source: not detected | |
3736 | return built, height | |
3737 | end | |
3738 | - | utils.waitForInput() |
3738 | + | |
3739 | function lib.fillBuckets(toBuild) | |
3740 | local emptySlots, water = lib.stackBuckets() -- gets no of empty slots + no of water buckets | |
3741 | if water < toBuild then -- no of water buckets onboard less than required quantity | |
3742 | for i = 1, toBuild do -- fill required no of buckets up to max space in inventory | |
3743 | emptySlots = lib.getEmptySlots() | |
3744 | if emptySlots == 0 then -- inventory full | |
3745 | break | |
3746 | else | |
3747 | if T:getWater("down") then | |
3748 | water = water + 1 | |
3749 | sleep(0.5) | |
3750 | end | |
3751 | end | |
3752 | end | |
3753 | end | |
3754 | ||
3755 | return water | |
3756 | end | |
3757 | ||
3758 | function lib.buildLift(preferredBlock) | |
3759 | local built = 0 -- measures completed lift height | |
3760 | local height = 0 -- measures total height from starting position | |
3761 | built, height = lib.goToWater(height) -- returns lift blocks already placed, total height of drop from starting point | |
3762 | local toBuild = height - built -- no of blocks to increase lift size | |
3763 | while toBuild > 0 do -- at least 1 block height remaining | |
3764 | local water = lib.fillBuckets(toBuild) -- no of water buckets onboard (could be more than required) | |
3765 | if water > toBuild then | |
3766 | water = toBuild | |
3767 | end | |
3768 | while turtle.detect() do -- climb to top of existing lift | |
3769 | turtle.up() | |
3770 | height = height - 1 | |
3771 | end | |
3772 | T:forward(1) | |
3773 | for i = 1, water do -- build lift by no of water buckets | |
3774 | if T:placeWater("forward") then | |
3775 | T:up(1) | |
3776 | height = height - 1 | |
3777 | toBuild = toBuild - 1 | |
3778 | T:place(preferredBlock, -1, "down", false) | |
3779 | end | |
3780 | end | |
3781 | turtle.back() | |
3782 | -- may still be some height to complete, but needs refill | |
3783 | if toBuild > 0 then | |
3784 | lib.goToWater(0) --return to source | |
3785 | lib.fillBuckets(toBuild) | |
3786 | end | |
3787 | end | |
3788 | if height > 0 then -- if any remaining distance | |
3789 | T:up(height) | |
3790 | end | |
3791 | ||
3792 | end | |
3793 | ||
3794 | function lib.buildSection(preferredBlock, solid) | |
3795 | -- builds a section without any blocks in the centre | |
3796 | -- second layer of each section end walls have fence posts | |
3797 | T:go("F1C2 F2C2 F1R1", false, 0, false, preferredBlock) -- first side solid row | |
3798 | if solid then -- first layer of each section | |
3799 | T:go("F1C2 F1R1", false, 0, false, preferredBlock) -- top side solid row | |
3800 | else | |
3801 | T:go("F1") -- top side solid row | |
3802 | if not T:place("fence", -1, "down", false) then-- first side | |
3803 | T:place(preferredBlock, -1, "down", false) | |
3804 | end | |
3805 | T:go("F1R1") -- top side solid row | |
3806 | end | |
3807 | T:go("F1C2 F2C2 F1R1", false, 0, false, preferredBlock) -- far side solid row | |
3808 | T:go("F1C2 F1R1U1", false, 0, false, preferredBlock) -- bottom side solid row | |
3809 | end | |
3810 | --[[ | |
3811 | clsTurtle methods: | |
3812 | clsTurtle.place(self, blockType, damageNo, direction, leaveExisting) | |
3813 | clsTurtle.go(self, path, useTorch, torchInterval, leaveExisting, preferredBlock) | |
3814 | ]] | |
3815 | -- remove 1 stack stone from chest | |
3816 | local preferredBlock = lib.getStone("down", 1) -- use this as default building block | |
3817 | if stage == 1 then | |
3818 | -- build base floor | |
3819 | --T:go("R2F2R1F3R1", false, 0, false, preferredBlock) | |
3820 | T:go("R2F1C2R1F1C2F1C2F1C2R1", false, 0, false, preferredBlock) | |
3821 | for i = 1, 2 do | |
3822 | lib.baseRun(preferredBlock, 8, "R1F1R1") | |
3823 | lib.baseRun(preferredBlock, 8, "L1F1L1") | |
3824 | lib.baseRun(preferredBlock, 8, "R1F4R1") | |
3825 | end | |
3826 | -- move back to centre, build water source, with soul sand at base of first source | |
3827 | --T:go("R1F3L1C2F1C2F2D1", false, 0, false, preferredBlock) --just behind chest, 1 below ground level | |
3828 | T:go("R1F3L1F2C2F1D1", false, 0, false, preferredBlock) --1 block behind chest, 1 below ground level | |
3829 | T:place("minecraft:soul_sand", -1, "down", false) -- over block 1 of water source | |
3830 | T:go("F1C2F1C2", false, 0, false, preferredBlock) -- over block 2 of water source | |
3831 | T:go("F1C2U1C2", false, 0, false, preferredBlock) -- over block 4 of water source | |
3832 | T:go("F1C2F1C2R2F5R2", false, 0, false, preferredBlock) -- over block 1 of water source | |
3833 | T:placeWater("down") | |
3834 | T:forward(2) -- over block 3 of water source | |
3835 | T:placeWater("down") | |
3836 | turtle.back() -- over block 2 of water source | |
3837 | T:getWater("down") | |
3838 | T:go("F2D1R2C2") -- over block 4 of water source | |
3839 | T:go("U1", false, 0, false, preferredBlock) | |
3840 | T:placeWater("down") | |
3841 | T:forward(4) | |
3842 | lib.stackBuckets() -- put all buckets in same slot | |
3843 | T:dropItem("minecraft:dirt", "up", 0) -- drop dirt up: clsTurtle.dropItem(self, item, direction, keepAmount) | |
3844 | preferredBlock = lib.getStone("down", 6) | |
3845 | T:go("R1F2R1U1") -- move to start position | |
3846 | for i = 1, 2 do | |
3847 | -- build first level of tower: 2 x outside run, 2 x sign run | |
3848 | lib.outsideRun(preferredBlock) | |
3849 | if i == 1 then -- place door | |
3850 | T:go("L1F1L1F1L1D1") | |
3851 | T:place("door", -1, "forward", false) | |
3852 | T:go("U1L1F1R1F1L1") | |
3853 | end | |
3854 | T:go("R1F1R1") | |
3855 | lib.signRun(preferredBlock, "Pint size\nzombies\nProhibited") | |
3856 | T:go("L1F1L1C2", false, 0, false, preferredBlock) | |
3857 | T:forward(4) -- miss out centre block | |
3858 | T:place(preferredBlock, -1, "down", false) | |
3859 | T:go("R1F1R1") | |
3860 | lib.signRun(preferredBlock, "Pint size\nzombies\nProhibited") | |
3861 | T:go("L1F1L1") | |
3862 | lib.outsideRun(preferredBlock) | |
3863 | if i == 1 then -- layer 1 | |
3864 | T:go("R1F1R1F1R1D1") -- place door | |
3865 | T:place("door", -1, "forward", false) | |
3866 | T:go("U1 R1F1 L1F5 L1U1 F2D1 F2R2 U1") -- go over door | |
3867 | else -- layer 2 | |
3868 | T:go("L1F5L1F6R2U1") -- over corner of lower platform | |
3869 | end | |
3870 | end | |
3871 | for i = 1, 2 do -- build both sides of platform, leave centre missing | |
3872 | lib.baseRun(preferredBlock, 8, "R1F1R1") | |
3873 | lib.baseRun(preferredBlock, 8, "L1F1L1") | |
3874 | lib.baseRun(preferredBlock, 8, "R1F4R1") | |
3875 | end | |
3876 | T:go("R1F3L1C2F1C2F1C2F4C2F1C2F1C2", false, 0, false, preferredBlock) --fill in centre row | |
3877 | --T:go("R2F6R1F1R1U1") -- go to start of tower base | |
3878 | T:go("R2F7R2D3") -- go to start on top of chest | |
3879 | T:sortInventory() | |
3880 | elseif stage == 2 then | |
3881 | -- start on top of chest, should have sufficient stone in inventory | |
3882 | T:go("U3L1F1R1F1U1") -- go to start of tower base | |
3883 | for i = 1, 7 do -- build 14 block high tower | |
3884 | lib.buildSection(preferredBlock, false) | |
3885 | lib.buildSection(preferredBlock, true) | |
3886 | end | |
3887 | T:go("R2F4R1F4R1", false, 0, false, preferredBlock) -- build upper platform (154 blocks remaining) | |
3888 | - | --[[ direction = R.direction "up" or "down" ]] |
3888 | + | |
3889 | lib.baseRun(preferredBlock, 12, "R1F1R1") | |
3890 | lib.baseRun(preferredBlock, 12, "L1F1L1") | |
3891 | lib.baseRun(preferredBlock, 12, "R1F1R1") | |
3892 | lib.baseRun(preferredBlock, 12, "L1F1L1") | |
3893 | lib.baseRun(preferredBlock, 12, "R1F6R1") | |
3894 | end | |
3895 | T:go("R1F5 L1C2 F1C2 F1C2 F1C2 F1C2 F4C2 F1C2 F1C2 F1C2 F1C2 ", false, 0, false, preferredBlock) --fill in centre row | |
3896 | T:go("R2F5") -- return to drop area | |
3897 | lib.buildLift(preferredBlock) -- build bubble lift | |
3898 | T:go("F3R1F1R1U1") -- go to start of tower base | |
3899 | T:go("C2F4 C2R1F1R1", false, 0, false, preferredBlock) -- left side layer 21 | |
3900 | T:go("F2C2 F2C2 L1F1L1", false, 0, false, preferredBlock) -- centre layer 21 | |
3901 | T:go("C2F4 C2R2U1", false, 0, false, preferredBlock) -- right side layer 21 | |
3902 | - | if R.direction == "up" then |
3902 | + | |
3903 | T:place("fence", -1, "down", false) -- fence centre of bottom side layer 22 | |
3904 | T:go("F2C2 F2L1F1L1", false, 0, false, preferredBlock) -- centre layer 22 | |
3905 | T:go("C2F4 C2R2F2L1F1R2D2", false, 0, false, preferredBlock) --ready to place ladder | |
3906 | T:place("ladder", -1, "forward", false) | |
3907 | T:up(1) | |
3908 | T:place("ladder", -1, "forward", false) | |
3909 | --T:go("U2R1F4R1F1R1") -- ready to make upper part of tower base | |
3910 | T:go("U2R1F4R1F1R1") -- ready to make upper part of tower base | |
3911 | for i = 1, 2 do -- build both sides of platform, leave centre missing | |
3912 | lib.baseRun(preferredBlock, 8, "R1F1R1") | |
3913 | lib.baseRun(preferredBlock, 8, "L1F1L1") | |
3914 | lib.baseRun(preferredBlock, 8, "R1F4R1") | |
3915 | end | |
3916 | T:go("R1F3 L1C2 F1C2 F1C2 F1", false, 0, false, preferredBlock) --fill in centre row | |
3917 | T:place("minecraft:soul_sand", -1, "down", false) | |
3918 | T:go("F1C2 F2C2 F1C2 F1C2", false, 0, false, preferredBlock) | |
3919 | T:go("R2F6R1F1R1U1") -- go to start of tower base | |
3920 | -- build 2 levels, finish signs and ladders | |
3921 | T:go("C2F2 R1D2 U1", false, 0, false, preferredBlock) | |
3922 | T:place("ladder", -1, "down", false) | |
3923 | T:turnRight(1) | |
3924 | T:place("sign", -1, "forward", false, "UP\n^\n|\n|") | |
3925 | T:go("U1R2F2C2 R1F2C2 R1", false, 0, false, preferredBlock) --top right corner | |
3926 | T:go("F4C2B2D1", false, 0, false, preferredBlock) | |
3927 | T:place("sign", -1, "forward", false, "UP\n^\n|\n|") | |
3928 | T:go("U1F2R1F1C2F1R1U1", false, 0, false, preferredBlock) --ready for second level | |
3929 | T:go("C2F2 R2D1", false, 0, false, preferredBlock) | |
3930 | T:place("sign", -1, "forward", false, "UP\n^\n|\n|") | |
3931 | T:go("U1R2F2C2R1", false, 0, false, preferredBlock) --top left corner | |
3932 | T:go("F1R1C2F4C2", false, 0, false, preferredBlock) --mid bottom row | |
3933 | T:go("L1F1L1C2", false, 0, false, preferredBlock) -- bottom right corner | |
3934 | T:go("F2R2D1", false, 0, false, preferredBlock) | |
3935 | T:place("sign", -1, "forward", false, "UP\n^\n|\n|") | |
3936 | T:go("U1R2F2C2", false, 0, false, preferredBlock) -- top right corner | |
3937 | -- return to chest | |
3938 | T:go("L1F1L1 F5D23R2", false, 0, false, preferredBlock) -- return to chest | |
3939 | T:sortInventory() | |
3940 | elseif stage == 3 then | |
3941 | --[[ move to top of structure | |
3942 | | 4 | | |
3943 | |3 5| | |
3944 | | X | | |
3945 | |2 6| | |
3946 | | 1 | | |
3947 | ]] | |
3948 | local towerHeight = 128 -- even no only suggest 128 | |
3949 | while turtle.detect() do | |
3950 | turtle.up() | |
3951 | end | |
3952 | T:go("F1U1", false, 0, false, preferredBlock) -- return to finish tower | |
3953 | for i = 1, towerHeight do -- 1 | |
3954 | T:go("C2U1", false, 0, false, preferredBlock) | |
3955 | end | |
3956 | T:go("F1L1F1R1D2") | |
3957 | while turtle.down() do -- 2 | |
3958 | T:fillVoid("up", {preferredBlock}) | |
3959 | end | |
3960 | T:go("F1R2C1R2F1D1", false, 0, false, preferredBlock) | |
3961 | for i = 1, towerHeight / 2 do -- 3 | |
3962 | T:go("U2C2", false, 0, false, preferredBlock) | |
3963 | end | |
3964 | T:go("U1F1R1F1R1D1", false, 0, false, preferredBlock) -- back of tower facing front | |
3965 | local deviate = false | |
3966 | while turtle.down() do -- 4 | |
3967 | T:place("fence", -1, "up", false) | |
3968 | if turtle.down() then | |
3969 | T:fillVoid("up", {preferredBlock}) | |
3970 | else | |
3971 | T:go("F1R2C1R1F1R1D1", false, 0, false, preferredBlock) | |
3972 | deviate = true | |
3973 | break | |
3974 | end | |
3975 | end | |
3976 | if not deviate then | |
3977 | T:go("F1L1F1R1D1", false, 0, false, preferredBlock) | |
3978 | end | |
3979 | for i = 1, towerHeight / 2 do -- 5 | |
3980 | T:go("U2C2", false, 0, false, preferredBlock) | |
3981 | end | |
3982 | T:go("F2R2", false, 0, false, preferredBlock) -- facing back of tower | |
3983 | while turtle.down() do -- 6 | |
3984 | T:fillVoid("up", {preferredBlock}) --layer 129 | |
3985 | end | |
3986 | T:go("F1L2C1U"..towerHeight) | |
3987 | T:go("F4R1F3R1U1", false, 0, false, preferredBlock) | |
3988 | -- add small platform at the top | |
3989 | lib.baseRun(preferredBlock, 8, "R1F1R1") | |
3990 | lib.baseRun(preferredBlock, 8, "L1F3L1") | |
3991 | lib.baseRun(preferredBlock, 8, "L1F1L1") | |
3992 | lib.baseRun(preferredBlock, 8, "R1F1R1") | |
3993 | T:go("C2 F1C2 F1C2 F4C2 F1C2 F1C2 R2F3", false, 0, false, preferredBlock) --fill in centre row | |
3994 | lib.buildLift(preferredBlock) -- build bubble lift | |
3995 | end | |
3996 | return {} | |
3997 | end | |
3998 | ||
3999 | local function createFarm(R, extend) -- 31 | |
4000 | -- if extend ~= nil then this has been called from createFarmExtension() | |
4001 | -- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock) | |
4002 | local lib = {} | |
4003 | function lib.addWaterSource(R, pattern, storage) | |
4004 | -- pattern = {"d","c","c","d"} t = place crafting instead of dirt | |
4005 | -- place(self, blockType, damageNo, direction, leaveExisting, signText) | |
4006 | T:go("D1x2C2", false, 0, false, R.useBlockType) | |
4007 | for i = 1, 4 do | |
4008 | T:dig("forward") | |
4009 | if pattern[i] == "d" then | |
4010 | T:place("dirt", -1, "forward", false) | |
4011 | elseif pattern[i] == "t" then | |
4012 | --if not T:place("minecraft:crafting_table", -1, "forward", false) then | |
4013 | if T:place(storage, -1, "forward", false) then | |
4014 | if T:dropItem("crafting", "forward", 0) then | |
4015 | print("Crafting table -> buried storage") | |
4016 | end | |
4017 | else | |
4018 | T:place("dirt", -1, "forward", false) -- dirt if no storage available | |
4019 | end | |
4020 | else | |
4021 | T:place(R.useBlockType, -1, "forward", false) | |
4022 | end | |
4023 | T:turnRight(1) | |
4024 | end | |
4025 | T:up(1) | |
4026 | T:placeWater("down") | |
4027 | end | |
4028 | ||
4029 | function lib.placeDirt(count, atCurrent) | |
4030 | if atCurrent then | |
4031 | local blockType = T:getBlockType("down") | |
4032 | if blockType:find("dirt") == nil and blockType:find("grass_block") == nil then | |
4033 | T:place("dirt", -1, "down", false) | |
4034 | end | |
4035 | end | |
4036 | for i = 1, count do | |
4037 | T:forward(1) | |
4038 | T:dig("up") | |
4039 | local blockType = T:getBlockType("down") | |
4040 | if blockType:find("dirt") == nil and blockType:find("grass_block") == nil then | |
4041 | T:place("dirt", -1, "down", false) | |
4042 | end | |
4043 | end | |
4044 | end | |
4045 | ||
4046 | function lib.placeStorage(storage, storageBackup) | |
4047 | T:dig("down") | |
4048 | if not T:place(storage, -1, "down", false) then-- place barrel/chest below | |
4049 | T:place(storageBackup, -1, "down", false) -- place chest below | |
4050 | end | |
4051 | end | |
4052 | ||
4053 | ||
4054 | -- extend "", "right" or "forward". only adds a single new farm. | |
4055 | -- right adds farm and checks for existing front extensions, dealt with separately | |
4056 | -- clsTurtle.place(blockType, damageNo, direction, leaveExisting) | |
4057 | if extend == nil then | |
4058 | extend = "" | |
4059 | end | |
4060 | local blockType = "" | |
4061 | -- extend = "right": placed on cobble corner of existing farm facing right side | |
4062 | -- extend = "front": placed on cobble corner of existing farm facing front | |
4063 | -- else placed on ground at corner of potential new farm facing front | |
4064 | ||
4065 | local storage, storageBackup = utils.setStorageOptions() | |
4066 | -- step 1 dig ditch round perimeter wall | |
4067 | if extend == "right" then | |
4068 | -- move to front corner ground ready for ditch | |
4069 | T:go("F1L1F12D1R1", false, 0, false, R.useBlockType) | |
4070 | -- cut ditch round new farm extension | |
4071 | for i = 1, 12 do | |
4072 | T:go("x0F1") | |
4073 | end | |
4074 | T:go("R1x0") | |
4075 | for i = 1, 13 do | |
4076 | T:go("x0F1") | |
4077 | end | |
4078 | T:go("R1x0") | |
4079 | -- now at lower right corner. if extension below, do not cut ditch | |
4080 | blockType = T:getBlockType("forward") | |
4081 | if blockType:find("stone") ~= nil then -- already a farm extension on left side | |
4082 | -- return to start for adding chests and walls | |
4083 | T:go("U1R1F1L1F12", false, 0, false, R.useBlockType) | |
4084 | else -- finish ditch | |
4085 | for i = 1, 12 do | |
4086 | T:go("x0F1") | |
4087 | end | |
4088 | T:go("R1U1F1") -- on corner of new extension | |
4089 | end | |
4090 | elseif extend == "forward" then | |
4091 | T:go("L1F2R1D1", false, 0, false, R.useBlockType) | |
4092 | -- cut ditch round new farm extension | |
4093 | for i = 1, 12 do | |
4094 | T:go("x0F1", false, 0, false, R.useBlockType) | |
4095 | end | |
4096 | T:go("R1x0", false, 0, false, R.useBlockType) | |
4097 | for i = 1, 13 do | |
4098 | T:go("x0F1", false, 0, false, R.useBlockType) | |
4099 | end | |
4100 | T:go("R1x0", false, 0, false, R.useBlockType) | |
4101 | for i = 1, 11 do | |
4102 | T:go("x0F1", false, 0, false, R.useBlockType) | |
4103 | end | |
4104 | T:go("U1x0F1R1F12R1", false, 0, false, R.useBlockType) -- on corner of new extension | |
4105 | else -- new farm. cut a groove round the entire farm base | |
4106 | -- move to left side of intended wall | |
4107 | T:go("L1F1x0R1", false, 0, false, R.useBlockType) | |
4108 | for j = 1, 4 do | |
4109 | for i = 1, 12 do | |
4110 | T:go("x0F1", false, 0, false, R.useBlockType) | |
4111 | end | |
4112 | T:go("R1x0F1", false, 0, false, R.useBlockType) | |
4113 | end | |
4114 | T:go("R1F1L1U1", false, 0, false, R.useBlockType) | |
4115 | end | |
4116 | -- stage 2 place sapling and double barrel/chest | |
4117 | T:dig("down") --remove cobble if present | |
4118 | T:place("dirt", -1, "down", false) | |
4119 | T:go("F1R2") | |
4120 | T:place("sapling", -1, "forward", false) -- plant sapling | |
4121 | T:go("L1") | |
4122 | lib.placeStorage(storage, storageBackup) | |
4123 | T:go("L1F1R1") | |
4124 | lib.placeStorage(storage, storageBackup) | |
4125 | T:turnLeft(1) | |
4126 | if extend == "right" then -- cobble wall exists so go forward to its end | |
4127 | T:forward(9) | |
4128 | else -- new farm or extend forward | |
4129 | for i = 1, 9 do -- complete left wall to end of farm | |
4130 | T:go("F1x0x2C2", false, 0, false, R.useBlockType) | |
4131 | end | |
4132 | end | |
4133 | T:go("R1F1 R1x0 x2C2 F1D1", false, 0, false, R.useBlockType)-- turn round ready for first dirt col | |
4134 | lib.addWaterSource(R, {"d","c","c","d"}, storage) -- water at top of farm | |
4135 | lib.placeDirt(9, false) -- place dirt back to start | |
4136 | lib.addWaterSource(R, {"c","c","t","d"}, storage) -- water source next to chests, includes crafting table | |
4137 | T:go("U1F1R2") | |
4138 | if T:getBlockType("down"):find(storage) == nil and T:getBlockType("down"):find(storageBackup) == nil then | |
4139 | lib.placeStorage(storage, storageBackup) | |
4140 | end | |
4141 | T:go("R1F1L1") | |
4142 | if T:getBlockType("down"):find(storage) == nil and T:getBlockType("down"):find(storageBackup) == nil then | |
4143 | lib.placeStorage(storage, storageBackup) | |
4144 | end | |
4145 | T:go("F1D1") | |
4146 | lib.placeDirt(9, true) | |
4147 | local turn = "R" | |
4148 | for i = 1, 7 do | |
4149 | T:go("F1U1x0C2"..turn.."1F1"..turn.."1x0x2C2F1D1", false, 0, false, R.useBlockType) | |
4150 | lib.placeDirt(9, true) | |
4151 | if turn == "R" then | |
4152 | turn = "L" | |
4153 | else | |
4154 | turn = "R" | |
4155 | end | |
4156 | end | |
4157 | T:go("F1U1x0C2"..turn.."1F1"..turn.."1x0x2C2F1D1", false, 0, false, R.useBlockType) | |
4158 | lib.addWaterSource(R, {"d","c","c","d"}, storage) | |
4159 | lib.placeDirt(9, false) | |
4160 | lib.addWaterSource(R, {"c","c","d","d"}, storage) | |
4161 | T:go("F1U1R1C2x0F1x0x2C2R1", false, 0, false, R.useBlockType) | |
4162 | for i = 1, 11 do | |
4163 | T:go("F1x0x2C2", false, 0, false, R.useBlockType) | |
4164 | end | |
4165 | -- add barrel/chest to any existing farm extension to the right | |
4166 | T:go("L1F1L1") | |
4167 | if T:getBlockType("down"):find("stone") == nil then -- farm extension already exists to right | |
4168 | lib.placeStorage(storage, storageBackup) | |
4169 | end | |
4170 | T:go("L1F11") | |
4171 | ||
4172 | return {"Modular farm completed"} | |
4173 | end | |
4174 | ||
4175 | local function createFarmExtension(R) -- 32 | |
4176 | -- assume inventory contains 4 chests, 64 cobble, 128 dirt, 4 water, 1 sapling | |
4177 | -- check position by rotating to face tree/sapling | |
4178 | local doContinue = true | |
4179 | local treePresent = false | |
4180 | local extend = "right" -- default | |
4181 | if R.subChoice == 1 then | |
4182 | extend = "forward" | |
4183 | end | |
4184 | local storage, storageBackup = utils.setStorageOptions() | |
4185 | local blockType = T:getBlockType("down") | |
4186 | if blockType:find(storage) == nil and blockType:find(storageBackup) == nil then | |
4187 | return | |
4188 | - | T:place("slab", "down", false) |
4188 | + | |
4189 | "Barrel or chest not present below\n", | |
4190 | "Unable to calculate position", | |
4191 | "Move me next to/front of the tree/sapling", | |
4192 | "lower left corner of the existing farm." | |
4193 | } | |
4194 | else | |
4195 | for i = 1, 4 do | |
4196 | blockType = T:getBlockType("forward") | |
4197 | if blockType:find("log") ~= nil or blockType:find("sapling") ~= nil then | |
4198 | treePresent = true | |
4199 | break | |
4200 | end | |
4201 | T:turnRight() | |
4202 | end | |
4203 | if not treePresent then | |
4204 | return | |
4205 | { | |
4206 | "Unable to locate tree or sapling", | |
4207 | "Plant a sapling on the lower left", | |
4208 | "corner of the farm, or move me there" | |
4209 | } | |
4210 | end | |
4211 | end | |
4212 | if doContinue then -- facing tree. check if on front or l side of farm | |
4213 | if extend == "forward" then | |
4214 | T:go("R1F11") -- to other side of farm. may be stone or barrel/chest below | |
4215 | - | T:place("slab", "down", false) |
4215 | + | |
4216 | if blockType:find(storage) ~= nil or blockType:find(storageBackup) ~= nil then | |
4217 | doContinue = false | |
4218 | end | |
4219 | else | |
4220 | T:go("R2F9") -- to right of farm, may be sapling/tree in front | |
4221 | blockType = T:getBlockType("forward") | |
4222 | if blockType:find("log") ~= nil or blockType:find("sapling") ~= nil then | |
4223 | doContinue = false | |
4224 | end | |
4225 | end | |
4226 | if doContinue then -- extend farm. | |
4227 | createFarm(R, extend) | |
4228 | - | T:place("slab", "down", true) |
4228 | + | |
4229 | return | |
4230 | { | |
4231 | "This farm has already been extended", | |
4232 | "Move me next to/front of the tree / sapling", | |
4233 | "of the last extension in this direction." | |
4234 | } | |
4235 | end | |
4236 | end | |
4237 | return {"Modular crop farm extended"} | |
4238 | end | |
4239 | ||
4240 | local function createFloorCeiling(R) -- 79 size integer 1 to 4 | |
4241 | --[[ | |
4242 | R.up = true for ceiling | |
4243 | R.down = true for floor | |
4244 | R.height = 0 for normal | |
4245 | R.height combined with R.up/R.down used for remote access | |
4246 | ]] | |
4247 | ||
4248 | local useBlock = T:getSlotContains(1) | |
4249 | local waterPresent = false | |
4250 | ||
4251 | if R.useBlockType ~= "" then | |
4252 | useBlock = R.useBlockType | |
4253 | end | |
4254 | print("Using ".. useBlock) | |
4255 | local direction = "down" | |
4256 | if R.up then | |
4257 | direction = "up" | |
4258 | end | |
4259 | if R.height > 0 then -- remote placing. go up/down R.height first | |
4260 | R.silent = true | |
4261 | local depth = 0 | |
4262 | if R.down then -- floor could be under water | |
4263 | while turtle.down() do | |
4264 | depth = depth + 1 | |
4265 | end | |
4266 | elseif R.up then | |
4267 | while turtle.up() do | |
4268 | depth = depth + 1 | |
4269 | if depth > R.height + 3 then | |
4270 | break | |
4271 | end | |
4272 | end | |
4273 | end | |
4274 | if not(R.height - depth <= 2 or depth - R.height <= 2) then | |
4275 | T:up(depth) | |
4276 | return {"Measured depth/height of "..depth.." > setting: "..R.height} | |
4277 | end | |
4278 | -- not returned so depth acceptable | |
4279 | end | |
4280 | -- check if block above/below | |
4281 | local blockBelow = turtle.detectDown() | |
4282 | local blockAbove = turtle.detectUp() | |
4283 | if R.subChoice == 2 then -- New floor over existing | |
4284 | -- if no block below, assume in correct position and continue | |
4285 | -- else move up 1 and continue | |
4286 | if blockBelow then T:up(1) end | |
4287 | elseif R.subChoice == 4 then -- New ceiling under existing | |
4288 | -- if no block above, assume in correct position and continue | |
4289 | -- else move down 1 and continue | |
4290 | if blockAbove then T:down(1) end | |
4291 | end | |
4292 | ||
4293 | local evenWidth = false | |
4294 | local evenHeight = false | |
4295 | local loopWidth | |
4296 | -- go(path, useTorch, torchInterval, leaveExisting) | |
4297 | if R.width % 2 == 0 then | |
4298 | evenWidth = true | |
4299 | loopWidth = R.width / 2 | |
4300 | else | |
4301 | loopWidth = math.ceil(R.width / 2) | |
4302 | end | |
4303 | if R.length % 2 == 0 then | |
4304 | evenHeight = true | |
4305 | end | |
4306 | -- if R.width is even no, then complete the up/down run | |
4307 | - | --T:place(blockType, direction, leaveExisting, signText) |
4307 | + | |
4308 | for x = 1, loopWidth do | |
4309 | -- Clear first column (up) | |
4310 | local tAvailable = T:getStock(useBlock, -1) | |
4311 | if tAvailable.total < R.length and not R.silent then | |
4312 | return {"Insufficient resources to complete current row"} | |
4313 | end | |
4314 | for y = 1, R.length do | |
4315 | local blockType = T:getBlockType("forward") | |
4316 | - | T:place("soul", "down", false) -- place soulsand down |
4316 | + | |
4317 | - | T:place("soul", "forward", false) -- place soulsand forward |
4317 | + | |
4318 | waterPresent = true | |
4319 | - | T:place("soul", "down", false) -- place soulsand down |
4319 | + | |
4320 | - | T:place("soul", "forward", false) -- place soulsand forward |
4320 | + | |
4321 | T:place(useBlock, -1, direction, false) -- leaveExisting = false | |
4322 | if y < R.length then | |
4323 | T:go("F1", false, 0, false) | |
4324 | - | T:place("gate", "forward", false) -- place fence gate |
4324 | + | |
4325 | end | |
4326 | -- clear second column (down) | |
4327 | if x < loopWidth or (x == loopWidth and evenWidth) then -- go down if on R.width 2,4,6,8 etc | |
4328 | - | T:place("gate", "forward", false) -- place fence gate |
4328 | + | T:go("R1F1R1", false,0,false) |
4329 | tAvailable = T:getStock(useBlock, -1) | |
4330 | if tAvailable.total < R.length and not R.silent then | |
4331 | return {"Insufficient resources to complete current row"} | |
4332 | end | |
4333 | for y = 1, R.length do | |
4334 | T:place(useBlock, -1, direction, false) -- leaveExisting = false | |
4335 | if y < R.length then | |
4336 | T:go("F1", false, 0, false) | |
4337 | end | |
4338 | end | |
4339 | if x < loopWidth then | |
4340 | T:go("L1F1L1", false,0,false) | |
4341 | else | |
4342 | T:turnRight(1) | |
4343 | T:forward(R.width - 1) | |
4344 | T:turnRight(1) | |
4345 | end | |
4346 | else -- equals R.width but is 1,3,5,7 etc | |
4347 | T:turnLeft(2) --turn round 180 | |
4348 | T:forward(R.length - 1) | |
4349 | T:turnRight(1) | |
4350 | T:forward(R.width - 1) | |
4351 | T:turnRight(1) | |
4352 | end | |
4353 | end | |
4354 | if waterPresent then | |
4355 | return {"water or lava found"} | |
4356 | end | |
4357 | return {""} | |
4358 | end | |
4359 | ||
4360 | local function createIceCanal(R) -- 55 | |
4361 | --[[ | |
4362 | R.subChoice = | |
4363 | 1: move right into canal, build left towpath | |
4364 | 2: build left towpath | |
4365 | 3: build right towpath | |
4366 | 4: move left into canal, build right towpath | |
4367 | 5/8: clear path 3 blocks high, place slabs/torches | |
4368 | 6/7: build alternating ice road / create 3 block high air gap (2 over water) | |
4369 | ]] | |
4370 | local oTurn = "R" | |
4371 | if R.side == "R" then | |
4372 | oTurn = "L" | |
4373 | end | |
4374 | local lib = {} | |
4375 | ||
4376 | function lib.convertTowpath(R) | |
4377 | -- only used to convert existing water canal, so assume towpath already present | |
4378 | -- starting position 1 block above existing towpath | |
4379 | for i = 1, R.length do | |
4380 | if turtle.detectDown() then -- eg existing torch | |
4381 | T:dig("down") | |
4382 | end | |
4383 | local placeSlab = true | |
4384 | if R.torchInterval > 0 then -- place torches | |
4385 | if i == 1 or i % R.torchInterval == 0 then -- ready to place torch | |
4386 | --go(path, useTorch, torchInterval, leaveExisting, preferredBlock) | |
4387 | T:go("C2x0", false, 0, false, R.useBlockType)-- place solid block below | |
4388 | T:go("F1R2x0") | |
4389 | T:place("torch", 0, "forward") -- place torch, move forward | |
4390 | T:turnRight(2) -- turn round | |
4391 | placeSlab = false | |
4392 | end | |
4393 | end | |
4394 | if placeSlab then | |
4395 | T:dig("up") | |
4396 | if not T:place("slab", 0, "down") then -- break if out of slabs | |
4397 | break | |
4398 | end | |
4399 | if i < R.length then | |
4400 | T:forward(1) -- move forward | |
4401 | end | |
4402 | end | |
4403 | end | |
4404 | end | |
4405 | ||
4406 | function lib.iceCanalTowpath(R) | |
4407 | -- move forward placing slabs along the way. If existing water canal, ceiling will be raised by 1 block | |
4408 | local torchInterval = 0 | |
4409 | local placeIce = true | |
4410 | for i = 1, R.length do | |
4411 | local addTorch = false | |
4412 | if R.torchInterval > 0 then | |
4413 | if i == 1 then addTorch = true end | |
4414 | if torchInterval >= R.torchInterval then | |
4415 | addTorch = true | |
4416 | torchInterval = 0 | |
4417 | end | |
4418 | end | |
4419 | lib.iceCanalEdge(R, addTorch, i, placeIce) | |
4420 | torchInterval = torchInterval + 1 | |
4421 | placeIce = not placeIce | |
4422 | end | |
4423 | T:go(oTurn.."1") | |
4424 | end | |
4425 | ||
4426 | function lib.iceCanalEdge(R, addTorch, numBlocks, placeIce) | |
4427 | -- starting position facing canal side | |
4428 | local blockType = T:getBlockType("forward") -- ? air / slab / other | |
4429 | local isWater, isSource, isIce = T:isWater("down") -- water / ice below | |
4430 | if blockType:find("slab") == nil then -- add slab | |
4431 | if addTorch then -- check if torch needed | |
4432 | -- T:place(blockType, damageNo, direction, leaveExisting, signText) | |
4433 | if not T:place("stone", -1, "forward", false) then | |
4434 | T:checkInventoryForItem({"stone"}, {math.ceil(R.length / R.torchInterval)}, true) | |
4435 | end | |
4436 | T:go("U1x1 U1x1 D1") -- water level to 2 above water level | |
4437 | if T:getItemSlot("minecraft:torch", -1) > 0 then | |
4438 | T:place("torch", -1, "forward", false) | |
4439 | end | |
4440 | T:down(1) -- back to above water level | |
4441 | if not isIce then -- break block below if NOT ice | |
4442 | T:dig("down") | |
4443 | end | |
4444 | else | |
4445 | if not T:place("slab", -1, "forward", false) then | |
4446 | T:checkInventoryForItem({"slab"}, {R.length - numBlocks}, true) | |
4447 | end | |
4448 | if not isSource then -- NOT on water, so dig above | |
4449 | T:go("U1x1 U1x1 D2") | |
4450 | end | |
4451 | if not isIce and not isSource then | |
4452 | T:dig("down") | |
4453 | end | |
4454 | end | |
4455 | else -- slab already on side | |
4456 | if addTorch then -- check if torch needed | |
4457 | T:dig("forward") | |
4458 | if not T:place("stone", -1, "forward", false) then | |
4459 | T:checkInventoryForItem({"stone"}, {math.ceil(R.length / R.torchInterval)}, true) | |
4460 | end | |
4461 | T:go("U1x1 U1x1 D1") -- water level to 2 above water level | |
4462 | if T:getItemSlot("minecraft:torch", -1) > 0 then | |
4463 | T:place("torch", -1, "forward", false) | |
4464 | end | |
4465 | T:down(1) -- back to above water level | |
4466 | if not isIce then -- break block below if NOT ice | |
4467 | T:dig("down") | |
4468 | end | |
4469 | end | |
4470 | end | |
4471 | if R.data == "ice" and placeIce and not isIce then -- R.data = "ice", placeIce = true, not already ice present | |
4472 | - | T:place("sign", "forward") |
4472 | + | T:place("ice", -1, "down", true) |
4473 | end | |
4474 | if numBlocks < R.length then | |
4475 | T:go(oTurn.."1F1"..R.side.."1") | |
4476 | end | |
4477 | end | |
4478 | ||
4479 | function lib.convertIcepath(length) | |
4480 | -- use only for placing ice to convert a water canal | |
4481 | -- place ice on alternate blocks until length reached or run out of ice | |
4482 | local placeIce = true | |
4483 | for i = 1, length do | |
4484 | if T:getBlockType("down"):find("ice") == nil then -- no ice below | |
4485 | T:dig("down") -- remove any existing block | |
4486 | if placeIce then | |
4487 | if not T:place("ice", -1, "down", true) then -- out of ice | |
4488 | break | |
4489 | end | |
4490 | if i == length - 1 then | |
4491 | break | |
4492 | end | |
4493 | end | |
4494 | else -- ice already below | |
4495 | placeIce = true | |
4496 | end | |
4497 | T:go("U1x0 D1F1") | |
4498 | placeIce = not placeIce -- reverse action | |
4499 | end | |
4500 | end | |
4501 | ||
4502 | function lib.convertToAir(length) | |
4503 | -- use only for converting a water canal. start at ground level | |
4504 | -- dig up/down/forward to clear space | |
4505 | for i = 1, length + 1 do | |
4506 | T:go("U1x0D1") | |
4507 | if i < length + 1 then | |
4508 | T:go("x2F1") | |
4509 | else | |
4510 | - | T:place("stone", "up") |
4510 | + | |
4511 | end | |
4512 | end | |
4513 | end | |
4514 | ||
4515 | function lib.initialise(R) | |
4516 | if R.subChoice == 1 or R.subChoice == 4 then | |
4517 | local blockType = T:getBlockType("down") -- ? at ground/water level or on top of existing slab | |
4518 | if blockType:find("slab") ~= nil then -- slab already present | |
4519 | T:go(oTurn.."1F1D1"..R.side.."2") -- move right/left forward, down onto ice canal top, face canal wall | |
4520 | elseif blockType:find("torch") ~= nil then | |
4521 | T:go(oTurn.."1F1D2"..R.side.."2") -- move right/left forward, down onto ice canal top, face canal wall | |
4522 | else -- assume on ground / water level | |
4523 | T:go(oTurn.."1F1"..R.side.."2") -- move right/left forward onto ice canal top, face canal wall | |
4524 | end | |
4525 | else | |
4526 | if T:isWater("forward") then -- player put turtle inside canal water | |
4527 | T:up(1) | |
4528 | end | |
4529 | T:go(R.side.."1") -- face canal wall | |
4530 | end | |
4531 | end | |
4532 | ||
4533 | if R.length == 0 then R.length = 1024 end | |
4534 | ||
4535 | if R.subChoice <= 4 then -- towpath 1,2,3,4 | |
4536 | lib.initialise(R) -- reposition | |
4537 | lib.iceCanalTowpath(R) -- build towpath | |
4538 | elseif R.subChoice == 5 or R.subChoice == 8 then -- assume placed on towpath | |
4539 | if T:getBlockType("down"):find("slab") ~= nil then -- slab already present | |
4540 | T:go("F1") | |
4541 | else | |
4542 | T:up(1) | |
4543 | end | |
4544 | lib.convertTowpath(R) | |
4545 | elseif R.subChoice == 6 or R.subChoice == 7 then | |
4546 | if R.data == "ice" then -- assume placed on existing ice or initial ice position | |
4547 | lib.convertIcepath(R.length)-- place ice | |
4548 | else -- assume placed on empty path | |
4549 | lib.convertToAir(R.length) -- clear 3 high area | |
4550 | end | |
4551 | end | |
4552 | ||
4553 | return {} | |
4554 | end | |
4555 | ||
4556 | local function createLadder(R) -- 12 | |
4557 | -- createLadder(R.data ="bedrock", R.height = 70, R.depth = -48) | |
4558 | -- go(path, useTorch, torchInterval, leaveExisting) | |
4559 | -- place(blockType, damageNo, direction, leaveExisting) | |
4560 | local lib = {} | |
4561 | ||
4562 | function lib.placeLadder(direction, ledge, i, height) | |
4563 | -- 1 check both sides and behind | |
4564 | local fluid = false | |
4565 | local block = T:isWaterOrLava("forward", ledge) | |
4566 | if block:find("water") ~= nil or block:find("lava") ~= nil then | |
4567 | --[[ surround 2 block shaft with blocks ]] | |
4568 | T:go("R1C1 R1C1 R1C1 R1F1 L1C1 R1C1 R1C1 R1C1F1 R2C1 x1") | |
4569 | else | |
4570 | --[[ no water/lava so prepare ladder site]] | |
4571 | T:go("F1 L1C1 R1C1 R1C1 L1B1", false, 0, true) | |
4572 | end | |
4573 | if not T:place("ladder", -1, "forward", false) then | |
4574 | T:checkInventoryForItem({"ladder"}, {height - i}, false) | |
4575 | end | |
4576 | -- 3 check if ledge, torch | |
4577 | if ledge == 0 and i > 1 then -- place block above unless new ladder | |
4578 | T:place("common", -1, direction, false) -- any common block | |
4579 | elseif ledge == 1 then | |
4580 | T:place("minecraft:torch", -1, direction, false) | |
4581 | elseif ledge == 2 then | |
4582 | ledge = -1 | |
4583 | end | |
4584 | ||
4585 | return ledge | |
4586 | end | |
4587 | ||
4588 | local retValue = {} | |
4589 | local ledge = 0 | |
4590 | local height = math.abs(R.depth - R.height) --height of ladder | |
4591 | local blockType = T:getBlockType("forward") | |
4592 | if R.up then -- create ladder from current level to height specified | |
4593 | for i = 1, height do -- go up, place ladder as you go | |
4594 | ledge = lib.placeLadder("down", ledge, i, height) -- ladder placed forward, stone ledge for torch placed down | |
4595 | if i < height then | |
4596 | T:up(1) | |
4597 | ledge = ledge + 1 | |
4598 | end | |
4599 | end | |
4600 | else -- R.down = true: ladder towards bedrock | |
4601 | local success = true | |
4602 | local numBlocks, errorMsg = 0, "" | |
4603 | T:down(1) | |
4604 | for i = 1, height do -- go down, place ladder as you go | |
4605 | ledge = lib.placeLadder("up", ledge, i, heigt) -- ladder placed forward, stone torch placed up | |
4606 | --success, blocksMoved, errorMsg, blockType = clsTurtle.down(self, steps, getBlockType) | |
4607 | if i < height then | |
4608 | success, numBlocks, errorMsg, blockType = T:down(1, true) -- true = return blockType | |
4609 | ledge = ledge + 1 | |
4610 | end | |
4611 | -- if looking for stronghold then check for stone_bricks | |
4612 | if blockType:find("stone_bricks") ~= nil then | |
4613 | table.insert(retValue, "Stronghold discovered") | |
4614 | break -- stop descent at stronghold | |
4615 | - | T:place(dirt, "forward", false) -- placed at end of potential water source, next to ladder |
4615 | + | |
4616 | end | |
4617 | - | T:place(dirt, "down", false) -- placed in ground, next to ladder |
4617 | + | |
4618 | if R.data == "chamber" then -- user has chosen to build a chamber | |
4619 | table.insert(retValue, "Shelter constucted at level".. R.depth) | |
4620 | if blockType:find("bedrock") ~= nil then | |
4621 | T:findBedrockTop(0) -- test to check if on safe level immediately above tallest bedrock | |
4622 | end | |
4623 | -- In shaft, facing start direction, on lowest safe level | |
4624 | -- create a square space round shaft base, end facing original shaft, 1 space back | |
4625 | T:go("L1n1 R1n3 R1n2 R1n3 R1n1", false, 0, true) | |
4626 | T:go("U1Q1 R1Q3 R1Q2 R1Q3 R1Q1 R1D1", false, 0, true) | |
4627 | end | |
4628 | end | |
4629 | ||
4630 | return retValue | |
4631 | end | |
4632 | ||
4633 | local function createLadderToWater(R) -- 86 | |
4634 | -- go down to water/lava with alternaate solid/open layers | |
4635 | -- create a working area at the base | |
4636 | -- Return to surface facing towards player placing ladders | |
4637 | local inAir = true | |
4638 | local numBlocks, errorMsg = 0, "" | |
4639 | local height = 2 | |
4640 | local blockType = T:getBlockType("down") | |
4641 | if blockType ~= "" then -- not over air | |
4642 | T:forward(1) | |
4643 | end | |
4644 | T:go("R2D1") -- face player, go down 2 | |
4645 | while inAir do --success = false when hits water/lava | |
4646 | blockType = T:isWaterOrLava("down") | |
4647 | if blockType:find("water") ~= nil or blockType:find("lava") ~= nil then | |
4648 | inAir = false | |
4649 | end | |
4650 | T:go("C1R1 C1R2 C1R1", false, 0, false) -- surround front and sides with cobble | |
4651 | if inAir then | |
4652 | T:down(1) | |
4653 | height = height + 1 | |
4654 | end | |
4655 | T:place("ladder", 0, "up") | |
4656 | end | |
4657 | -- In shaft, facing opposite start direction, on water/lava, ladders above | |
4658 | T:go("C2", false, 0, false) | |
4659 | utils.goBack(1) | |
4660 | T:place("ladder", 0, "forward") | |
4661 | T:up(3) | |
4662 | height = height - 3 | |
4663 | for i = 1, height do | |
4664 | if i < height then | |
4665 | T:go("C2U1", false, 0, false) | |
4666 | else | |
4667 | T:go("C2", false, 0, false) | |
4668 | end | |
4669 | end | |
4670 | ||
4671 | return {} | |
4672 | - | T:place("soul_sand", "down", false) |
4672 | + | |
4673 | ||
4674 | local function createMine() -- 11 | |
4675 | -- go(path, useTorch, torchInterval, leaveExisting, preferredBlock) | |
4676 | T:clear() | |
4677 | T:go("m32U1R2M16", true, 8, true) -- mine ground level, go up, reverse and mine ceiling to mid-point | |
4678 | T:go("U2D2") -- create space for chest | |
4679 | T:place("minecraft:chest", -1, "up", false) | |
4680 | T:emptyTrash("up") | |
4681 | T:go("D1R1m16U1R2M16", true, 8, true) -- mine floor/ceiling of right side branch | |
4682 | T:emptyTrash("up") | |
4683 | T:go("D1m16U1R2M16", true, 8, true) -- mine floor/ceiling of left side branch | |
4684 | T:emptyTrash("up") | |
4685 | T:go("L1M15F1R1D1", true, 8, true) -- mine ceiling of entry corridor, turn right | |
4686 | T:go("F1x0 F1x0 n14 R1n32 R1n32 R1n32 R1n14 F1x0 F1U1", true, 8, true)-- mine floor of 36 x 36 square corridor | |
4687 | T:go("R1F16R2") --return to centre | |
4688 | T:emptyTrash("up") | |
4689 | T:go("F16R1") --return to entry shaft | |
4690 | T:go("F2Q14R1Q32R1Q32R1Q32R1Q14F2R1", true, 8, true) --mine ceiling of 36x36 square corridor. return to entry shaft + 1 | |
4691 | T:go("F16R2") --return to centre | |
4692 | T:emptyTrash("up") | |
4693 | -- get rid of any remaining torches | |
4694 | while T:getItemSlot("minecraft:torch", -1) > 0 do | |
4695 | turtle.select(T:getItemSlot("minecraft:torch", -1)) | |
4696 | turtle.dropUp() | |
4697 | end | |
4698 | T:go("F16R1F1R1") --return to shaft + 1 | |
4699 | for i = 1, 8 do | |
4700 | T:go("N32L1F1L1", true, 8, true) | |
4701 | T:go("N16L1F"..(i * 2).."R2", true, 8, true) | |
4702 | T:emptyTrash("up") | |
4703 | if i < 8 then | |
4704 | T:go("F"..(i * 2).."L1N16R1F1R1", true, 8, true) | |
4705 | else | |
4706 | T:go("F"..(i * 2).."L1N16L1", true, 8, true) | |
4707 | end | |
4708 | end | |
4709 | T:go("F17L1") -- close gap in wall, return to ladder + 1 | |
4710 | for i = 1, 8 do | |
4711 | T:go("N32R1F1R1", true, 8, true) | |
4712 | T:go("N16R1F"..(i * 2).."R2", true, 8, true) | |
4713 | T:emptyTrash("up") | |
4714 | if i < 8 then | |
4715 | T:go("F"..(i * 2).."R1N16L1F1L1", true, 8, true) | |
4716 | else | |
4717 | T:go("F"..(i * 2).."R1N16R1", true, 8, true) | |
4718 | end | |
4719 | end | |
4720 | T:go("F16R1") | |
4721 | T:clear() | |
4722 | return{"Mining operation complete"} | |
4723 | end | |
4724 | ||
4725 | local function createMobFarmCube(R) -- 61, 62 | |
4726 | --[[ | |
4727 | Part 1 / 3 Mob Spawner Farm | |
4728 | blaze = true: blaze spawner in nether | |
4729 | R.subChoice is set to: | |
4730 | 1 = on top of spawner | |
4731 | 2 = line of sight | |
4732 | 3 = room below | |
4733 | blaze = false: overworld mob spawner | |
4734 | R.subChoice is set to: | |
4735 | 1 = on top of spawner | |
4736 | 2 = bottom left corner | |
4737 | 3 = top left corner | |
4738 | 4 = bottom right, corner | |
4739 | 5 = top right corner | |
4740 | R.width / R.length set by player (external size) | |
4741 | ]] | |
4742 | local blaze = true | |
4743 | if R.data == "spawner" or R.data == "chest" then | |
4744 | blaze = false | |
4745 | end | |
4746 | local continue = false | |
4747 | if R.data == "restart" then | |
4748 | continue = true | |
4749 | end | |
4750 | R.direction = "clock" -- starting on right side | |
4751 | if not blaze then | |
4752 | print("R.width: "..tostring(R.width)) | |
4753 | R.width = R.width - 2 -- internal width | |
4754 | R.length = R.length - 2 -- internal length | |
4755 | ||
4756 | if R.subChoice == 2 or R.subChoice == 3 then | |
4757 | R.direction = "anticlock" | |
4758 | end | |
4759 | end | |
4760 | -- R.data allows for 2-part operation "blaze" = main cube, "restart" = killzone | |
4761 | T:clear() | |
4762 | local lib = {} | |
4763 | ||
4764 | function lib.floorSection(length) | |
4765 | for i = 1, length do -- starts on top left corner | |
4766 | T:go("C2") | |
4767 | if i < length then | |
4768 | T:forward(1) | |
4769 | else | |
4770 | T:go("R1F1") | |
4771 | end | |
4772 | end | |
4773 | end | |
4774 | ||
4775 | function lib.wallSection(blaze) | |
4776 | blaze = blaze or false | |
4777 | for i = 1, 4 do | |
4778 | for j = 1, 11 do | |
4779 | if blaze then | |
4780 | T:place("slab", 0, "up", false) | |
4781 | T:go("C2", false, 0, false) | |
4782 | else | |
4783 | T:go("C0C2", false, 0, false) | |
4784 | - | T:place("stone", "forward", false) |
4784 | + | |
4785 | if j < 11 then | |
4786 | T:forward(1) | |
4787 | - | T:place("stone", "forward", false) |
4787 | + | |
4788 | else | |
4789 | T:turnRight(1) | |
4790 | end | |
4791 | end | |
4792 | end | |
4793 | end | |
4794 | ||
4795 | function lib.ceiling(blaze) | |
4796 | -- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock) | |
4797 | -- all outer walls complete, now for remaining 9x9 ceiling | |
4798 | blaze = blaze or false | |
4799 | for i = 1, 9 do | |
4800 | for j = 1, 9 do | |
4801 | if blaze then | |
4802 | T:place("slab", 0, "up", false) | |
4803 | T:dig("down") | |
4804 | else | |
4805 | T:go("C0x2", false, 0, true) | |
4806 | end | |
4807 | if j < 9 then | |
4808 | T:forward(1) | |
4809 | else -- end of length | |
4810 | local place = false | |
4811 | if i%2 == 1 then -- odd numbers 1,3,5,7,9 | |
4812 | if i < 9 then | |
4813 | - | T:place("minecraft:torch", "down") |
4813 | + | |
4814 | T:go("R1F1 R1") | |
4815 | end | |
4816 | else | |
4817 | place = true | |
4818 | T:go("L1F1 L1") | |
4819 | end | |
4820 | if place then | |
4821 | if blaze then | |
4822 | T:place("slab", 0, "up", false) | |
4823 | T:dig("down") | |
4824 | else | |
4825 | T:go("C0x2", false, 0, true) | |
4826 | end | |
4827 | end | |
4828 | end | |
4829 | end | |
4830 | end | |
4831 | end | |
4832 | ||
4833 | function lib.clearWall(length) | |
4834 | for i = 1, 4 do | |
4835 | for j = 1, length do | |
4836 | if j < length then | |
4837 | T:go("x0x2F1") | |
4838 | else | |
4839 | T:go("x0x2R1") | |
4840 | end | |
4841 | end | |
4842 | end | |
4843 | end | |
4844 | ||
4845 | function lib.isSpawner() | |
4846 | local blockType = T:getBlockType("down") | |
4847 | if blockType:find("spawner") ~= nil then | |
4848 | return true, "top" | |
4849 | end | |
4850 | blockType = T:getBlockType("up") | |
4851 | if blockType:find("spawner") ~= nil then | |
4852 | return true, "bottom" | |
4853 | end | |
4854 | blockType = T:getBlockType("forward") | |
4855 | if blockType:find("spawner") ~= nil then | |
4856 | return true, "forward" | |
4857 | end | |
4858 | return false, "" | |
4859 | end | |
4860 | ||
4861 | function lib.placeFloor(width, length, blockType) | |
4862 | -- T:place(blockType, damageNo, direction, leaveExisting, signText) | |
4863 | for i = 1, width do | |
4864 | for j = 1, length do | |
4865 | T:place(blockType, -1, "down", false) | |
4866 | if j < length then | |
4867 | T:forward(1) | |
4868 | else | |
4869 | if i%2 == 1 then -- odd numbers 1,3,5,7,9 | |
4870 | if i < width then | |
4871 | T:go("R1F1R1", false, 0, true) | |
4872 | end | |
4873 | else | |
4874 | T:go("L1F1L1", false, 0, true) | |
4875 | end | |
4876 | end | |
4877 | end | |
4878 | end | |
4879 | end | |
4880 | ||
4881 | function lib.searchStrip(distance) | |
4882 | --go forward until hit either a wall or a chest | |
4883 | local blocks = 1 | |
4884 | print("Searching strip, distance = "..distance) | |
4885 | while blocks < distance do --max travel is external width/length | |
4886 | if turtle.forward() then | |
4887 | blocks = blocks + 1 | |
4888 | else | |
4889 | print("Checking for chest") | |
4890 | if lib.isChest("forward") then | |
4891 | if turtle.forward() then | |
4892 | blocks = blocks + 1 | |
4893 | end | |
4894 | else | |
4895 | break | |
4896 | end | |
4897 | end | |
4898 | end | |
4899 | end | |
4900 | ||
4901 | function lib.findChests(R) | |
4902 | for i = 1, 4 do | |
4903 | print("Searching wall "..i) | |
4904 | if i == 1 or i == 3 then | |
4905 | lib.searchStrip(R.width) -- find and empty chests along width | |
4906 | else | |
4907 | lib.searchStrip(R.length) -- find and empty chests along length | |
4908 | end | |
4909 | if R.direction == "clock" then | |
4910 | T:turnRight(1) | |
4911 | else | |
4912 | T:turnLeft(1) | |
4913 | - | T:place("minecraft:ladder", "down") |
4913 | + | |
4914 | end | |
4915 | ||
4916 | -- checked all walls | |
4917 | T:go("F".. math.floor(R.width / 2)) -- now at mid-dungeon, next to wall | |
4918 | if T:getItemSlot("chest") > 0 then | |
4919 | if R.direction == "clock" then | |
4920 | T:turnLeft(1) | |
4921 | - | T:place("minecraft:obsidian", "down") |
4921 | + | |
4922 | T:turnRight(1) | |
4923 | end | |
4924 | -- now at mid-dungeon, facing wall | |
4925 | -- deposit chest outside the dungeon | |
4926 | while turtle.back() do end -- backing spawner | |
4927 | T:go("x0 F1x0 F1x0 F1x0 F1x0 F1x0 F1x0 x1x2") | |
4928 | -- place(self, blockType, damageNo, direction, leaveExisting, signText) | |
4929 | T:place("chest", -1, "forward", false) | |
4930 | -- empty out all except stone and slab | |
4931 | T:emptyInventorySelection("forward", {"cobble", "tuff", "slab", "granite", "andesite", "diorite" }, {0,0,0,0,0,0}) | |
4932 | T:turnLeft(2) | |
4933 | T:checkInventoryForItem({"stone"}, {512}, false, "Full cube uses ~700 blocks\nEstimate your requirements") | |
4934 | while turtle.forward() do end -- facing spawner | |
4935 | else | |
4936 | if R.direction == "clock" then | |
4937 | T:turnRight(1) | |
4938 | else | |
4939 | T:turnLeft(1) | |
4940 | end | |
4941 | end -- now at mid-dungeon, facing spawner | |
4942 | end | |
4943 | ||
4944 | function lib.enterDungeon(R) | |
4945 | --[[ find and empty any chests, return to dungeon wall ]] | |
4946 | print("Entering dungeon") | |
4947 | local blockType = T:getBlockType("forward") | |
4948 | if blockType == "" then -- nothing in front.Error | |
4949 | return false, "No block in front: Check position." | |
4950 | else -- attempt entry into dungeon wall | |
4951 | if R.subChoice == 2 then -- bottom left | |
4952 | T:go("R1F1 L1U2 F2R1") | |
4953 | elseif R.subChoice == 3 then -- top left | |
4954 | T:go("R1F1 L1D1 F2R1") | |
4955 | elseif R.subChoice == 4 then -- bottom right | |
4956 | T:go("L1F1 R1U2 F2L1") | |
4957 | elseif R.subChoice == 5 then -- top right | |
4958 | T:go("L1F1 R1D1 F2L1") | |
4959 | end | |
4960 | while turtle.down() do end -- either on floor or chest | |
4961 | if lib.isChest("down") then | |
4962 | turtle.down() | |
4963 | end | |
4964 | print("Searching for chests") | |
4965 | lib.findChests(R) -- go round inside walls emptying chests. Finish mid-wall | |
4966 | end | |
4967 | return true, ""-- success, message | |
4968 | end | |
4969 | ||
4970 | function lib.isChest(direction) | |
4971 | direction = direction or "forward" | |
4972 | local blockType = T:getBlockType(direction) | |
4973 | if blockType:find("chest") ~= nil then -- chest found. early stages so empty and break it | |
4974 | print("Chest found") | |
4975 | while T:suck(direction) do end | |
4976 | T:dig(direction, false) -- false prevents checking for chests | |
4977 | return true | |
4978 | elseif blockType:find("torch") ~= nil then | |
4979 | print("Torch found") | |
4980 | T:dig(direction, false) -- false prevents checking for chests | |
4981 | return true | |
4982 | end | |
4983 | return false | |
4984 | end | |
4985 | ||
4986 | function lib.findSpawner(blaze) | |
4987 | local moves = 0 | |
4988 | local quit = false | |
4989 | -- assume turtle placed on centre of inside spawner wall in front of spawner | |
4990 | -- or as close as possible in Nether | |
4991 | print("Checking if next to spawner") | |
4992 | local found, position = lib.isSpawner() -- true/false, top/bottom/nil | |
4993 | if not found then -- move forward towards spawner | |
4994 | print("Not close to spawner") | |
4995 | while turtle.forward() and not quit do | |
4996 | moves = moves + 1 | |
4997 | if moves > 16 then | |
4998 | quit = true | |
4999 | end | |
5000 | end | |
5001 | found, position = lib.isSpawner() -- true/false, top/bottom/nil | |
5002 | if not found then | |
5003 | if blaze then -- could be behind a wall | |
5004 | print("Assuming blaze spawner behind a wall") | |
5005 | T:forward(1) | |
5006 | moves = moves + 1 | |
5007 | while turtle.forward() and not quit do | |
5008 | moves = moves + 1 | |
5009 | if moves > 16 then | |
5010 | quit = true | |
5011 | end | |
5012 | end | |
5013 | found, position = lib.isSpawner() -- true/false, top/bottom/nil | |
5014 | if not found then | |
5015 | T:go("R2F"..moves + 2 .."R2") | |
5016 | end | |
5017 | end | |
5018 | end | |
5019 | end | |
5020 | ||
5021 | return found, position | |
5022 | - | T:place("fence", "down", false) |
5022 | + | |
5023 | ||
5024 | - | T:place(preferredBlock, "down", false) |
5024 | + | |
5025 | if not continue then -- new mob cube either dungeon or blaze | |
5026 | - | T:place(preferredBlock, "down", false) |
5026 | + | |
5027 | -- determine spawner position level 4, move to top of spawner (level 6) | |
5028 | - | T:place(preferredBlock, "down", false) |
5028 | + | |
5029 | local found, position = lib.isSpawner() -- already on spawner? | |
5030 | if blaze then | |
5031 | if not found then -- away from spawner | |
5032 | - | T:place(preferredBlock, "down", false) |
5032 | + | |
5033 | T:go("U5") | |
5034 | - | T:place(preferredBlock, "down", false) |
5034 | + | |
5035 | found, position = lib.findSpawner(blaze) | |
5036 | end | |
5037 | else -- go to bottom of dungeon and empty chests | |
5038 | - | T:place("sign", "forward", false, message) |
5038 | + | |
5039 | local success, message = lib.enterDungeon(R) | |
5040 | if not success then | |
5041 | return {message} | |
5042 | end | |
5043 | found, position = lib.findSpawner(blaze) -- is spawner in front / above / below? | |
5044 | end | |
5045 | end | |
5046 | ||
5047 | if found then -- true: move to correct starting position | |
5048 | --[[ | |
5049 | 1 |c|c|c|c|c|c|c|c|c|c|c| | |
5050 | 2 |w| | | | | | | | | |w| | |
5051 | 3 |w| | | | | | | | | |w| | |
5052 | 4 |w| | | | | | | | | |w| | |
5053 | 5 |w| | | | | | | | | |w| | |
5054 | 6 |w| | | | |s| | | | |w| | |
5055 | 7 |w| | | | | | | | | |w| | |
5056 | 8 |w| | | | | | | | | |w| | |
5057 | 9 |w| | | | | | | | | |w| | |
5058 | 10 |w| | | | | | | | | |w| exit level for overworld | |
5059 | 11 |f|f|f|f|f|f|f|f|f|f|f| | |
5060 | 12 |f|f|f|f|f|f|f|f|f|f|f| sub floor for overworld | |
5061 | 1 2 3 4 5 6 7 8 9 1 1 | |
5062 | 0 1 | |
5063 | ]] | |
5064 | -- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock) | |
5065 | if position == "bottom" then | |
5066 | T:go("B1U2F1") | |
5067 | elseif position == "forward" then | |
5068 | T:go("U1F1") | |
5069 | end | |
5070 | ||
5071 | T:up(1) | |
5072 | T:place("slab", -1, "down", true) -- place slab on top T:place(blockType, damageNo, direction, leaveExisting) | |
5073 | -- go up 2 blocks, forward 5, right, forward 5, right | |
5074 | T:go("U2F5 R1F5 R1") -- Level 2: now placed 1 below ceiling inside wall, top right corner of new dungeon | |
5075 | lib.wallSection(blaze) -- fix layers 1, 2, 3 including ceiling margin turtle at Level 2 | |
5076 | T:go("F1R2 C1L1 F1R2 C1R1", false, 0, false) -- exit wall, repair behind, still Level 2 | |
5077 | lib.ceiling(blaze) -- fix ceiling, end opposite corner to start | |
5078 | T:go("R2D3") -- clear the inner walls inside original dungeon | |
5079 | lib.clearWall(9) -- clear the 9 x 9 area around the spawner | |
5080 | T:go("F1R1F1L1") | |
5081 | lib.clearWall(7) -- clear the 7 x 7 area around the spawner | |
5082 | T:go("F1R1F1L1") | |
5083 | lib.clearWall(5) -- clear the 5 x 5 area around the spawner. Also needed for cave spiders | |
5084 | T:go("R2F1R1F1R1") | |
5085 | T:go("F7R1 F8L1F1R2", false, 0, false) -- return from ceiling, enter wall below previous section: Level 5 | |
5086 | lib.wallSection() -- deal with areas from spawner level up (4,5,6). walls only | |
5087 | T:go("F1R2 C1L1 F1R2 C1R1 D3", false, 0, false) -- exit wall, repair behind, embed 1 below original floor: Level 8 | |
5088 | clearRectangle({width = 9, length = 9, up = true, down = true}) -- clear levels 7,8,9 | |
5089 | T:go("L1F1 L1F1L2", false, 0, false) -- go inside wall sectio, ready for next wall section | |
5090 | lib.wallSection() -- deal with walls on levels 7,8,9 | |
5091 | T:go("F1R2 C1L1 F1R2 C1R1 D3", false, 0, false) -- exit wall, repair behind, embed 4 below original floor: Level 11 | |
5092 | --print("Check: about to clear 3 floors 3 below spawner") read() | |
5093 | clearRectangle({width = 9, length = 9, up = true, down = true}) -- clear levels 10,11,12 | |
5094 | ||
5095 | - | T:place(preferredBlock, "down", false) |
5095 | + | |
5096 | T:go("L1F1 L1F1L2", false, 0, false) -- ready for next wall section | |
5097 | lib.wallSection() -- wall on layers 10,11,12 | |
5098 | T:go("F1R2 C1L1 F1R2 C1R1 D3", false, 0, false) -- exit wall, repair behind, embed 1 below original floor: Level 8 | |
5099 | clearRectangle({width = 9, length = 9, up = true, down = true}) -- clear levels 13, 14, 15 | |
5100 | end | |
5101 | ||
5102 | T:go("L1F1L1F1L2", false, 0, false) -- ready for next wall section | |
5103 | --print("Check: level 11, 5 north, 5 east") | |
5104 | --read() | |
5105 | lib.wallSection() -- wall on layers 10,11,12 or 12,13,14 if blaze | |
5106 | T:go("F1R1 F1R2 C1R1 U1", false, 0, false) -- exit wall, repair behind: Level 10, facing entry point top right corner | |
5107 | T:down(1) | |
5108 | if blaze then | |
5109 | lib.placeFloor(9, 9, brick) -- place brick floor on level 14 | |
5110 | T:go("L1F4 R1F2 U4") -- ends facing out to lower chamber ?below staircase | |
5111 | -- now needs to build killzone | |
5112 | else | |
5113 | lib.placeFloor(9, 9, "stone") -- ends facing wall on entrance side | |
5114 | T:go("U1R2") | |
5115 | lib.placeFloor(9, 9, "stone") -- ends facing wall on opposite side | |
5116 | -- return to mid-point front | |
5117 | T:go("R2F8 R1F4 L1F2") -- exit at bottom of dungeon | |
5118 | T:go("x1U1 x1U1 x1U1 x1D3 R2") -- rise to chest, then return ready for next stage | |
5119 | - | if not T:place("fence", "down", false) then-- first side |
5119 | + | |
5120 | - | T:place(preferredBlock, "down", false) |
5120 | + | |
5121 | else | |
5122 | return | |
5123 | { | |
5124 | "Spawner not found. Place me on top,", | |
5125 | "immediately below, or facing it.", | |
5126 | "\nEnter to quit" | |
5127 | } | |
5128 | end | |
5129 | end | |
5130 | if continue then | |
5131 | T:clear() | |
5132 | local text = | |
5133 | [[~yellow~Items required to continue: | |
5134 | ||
5135 | ~lightGray~slabs 81 | |
5136 | ~orange~nether bricks 88 | |
5137 | ~yellow~lava buckets 4 | |
5138 | ~brown~chest / barrel 1 | |
5139 | ~gray~hopper 1 | |
5140 | ||
5141 | ~red~WARNING ~yellow~Inventory ejects items if you | |
5142 | continue! ~orange~(Choose at next menu.) | |
5143 | ||
5144 | ~white~Next -> Enter]] | |
5145 | menu.colourText(nil, text, true) | |
5146 | - | T:place("minecraft:soul_sand", "down", false) -- over block 1 of water source |
5146 | + | |
5147 | pp.itemColours = {colors.red, colors.lime} | |
5148 | local choice = menu.new("Choose your option", {"Continue with build", "Re-start later"}, pp, "Type number + Enter") -- 1 = continue, 2= quit | |
5149 | if choice == 1 then | |
5150 | choice = menu.new("Choose your option", {"Turtle is above me", "Turtle is below or next to me"}, pp, "Type number + Enter") -- 1 = up, 2= down | |
5151 | if choice == 1 then | |
5152 | T:emptyInventory("down") | |
5153 | else | |
5154 | T:emptyInventory("up") | |
5155 | end | |
5156 | else | |
5157 | return {"Blaze spawner partial build halted"} | |
5158 | end | |
5159 | ||
5160 | --clsTurtle.getItemSlot(self, item, useDamage): return slotData.lastSlot, slotData.leastModifier, total, slotData | |
5161 | T:checkInventoryForItem({brick}, {88}) | |
5162 | T:checkInventoryForItem({"slab"}, {81}) | |
5163 | T:checkInventoryForItem({"lava"}, {4}) | |
5164 | T:checkInventoryForItem({"sign"}, {1}) | |
5165 | T:checkInventoryForItem({"hopper"}, {1}) | |
5166 | T:checkInventoryForItem({"chest", "barrel"}, {1, 1}) | |
5167 | print("Stand clear. Starting in 2 secs") | |
5168 | - | T:place("door", "forward", false) |
5168 | + | |
5169 | -- place upper floor and slabs under it | |
5170 | T:go("R2D4F2 L1F4 R1U4") | |
5171 | lib.placeFloor(9, 9, brick) -- place brick floor on level 10 | |
5172 | T:down(2) | |
5173 | T:place(brick, 0, "up") | |
5174 | T:go("D1R2") | |
5175 | - | T:place(preferredBlock, "down", false) |
5175 | + | |
5176 | ||
5177 | -- place lava | |
5178 | T:go("L1F4 L1F4 U4") -- through hole in ceiling | |
5179 | T:go("F4 L1F4 R2") | |
5180 | for i = 1, 4 do | |
5181 | T:place("lava", 0 , "down") | |
5182 | - | T:place("door", "forward", false) |
5182 | + | |
5183 | end | |
5184 | T:go("F4 R1F4 D2 F1 R2") | |
5185 | -- place sign and repair above | |
5186 | T:dig("forward") | |
5187 | T:place("sign", 0, true, "") | |
5188 | T:down(1) | |
5189 | T:place(brick, 0 , "up") | |
5190 | T:forward(1) | |
5191 | -- place blocks under exit hole | |
5192 | for i = 1, 4 do | |
5193 | T:place(brick, 0 , "forward") | |
5194 | T:turnRight(1) | |
5195 | end | |
5196 | -- place chest and hopper | |
5197 | ||
5198 | T:go("D2x2") | |
5199 | if not T:place("chest", 0, "down") then | |
5200 | T:place("barrel", 0, "down") | |
5201 | end | |
5202 | T:up(1) | |
5203 | T:place("hopper", 0, "down") | |
5204 | utils.goBack(1) | |
5205 | T:place("slab", 0, "forward") | |
5206 | T:go("R2F5U3")-- return to starting point and create entrance | |
5207 | end | |
5208 | return {} | |
5209 | end | |
5210 | ||
5211 | local function floodMobFarm(R) -- 63 | |
5212 | --[[Part 2 / 3 Mob Spawner Farm turtle on floor, pointing towards water source wall, single hole]] | |
5213 | local lib ={} | |
5214 | ||
5215 | function lib.setPosition(addWater) | |
5216 | local width = 0 | |
5217 | while turtle.forward() do end -- move forward until hit wall | |
5218 | T:go("U1L1") | |
5219 | while turtle.forward() do end -- move forward until hit left wall | |
5220 | - | T:place("fence", "down", false) -- fence centre of bottom side layer 22 |
5220 | + | |
5221 | T:placeWater("down") -- place water down | |
5222 | end | |
5223 | - | T:place("ladder", "forward", false) |
5223 | + | |
5224 | while turtle.forward() do | |
5225 | - | T:place("ladder", "forward", false) |
5225 | + | |
5226 | end -- go forward 7 | |
5227 | if addWater then -- back 1 | |
5228 | T:placeWater("down") -- place water | |
5229 | end | |
5230 | T:go("L2F".. math.floor(width / 2) .."L1") -- turn round, go forward 3 (centre of wall), turn left | |
5231 | end | |
5232 | ||
5233 | function lib.digFloor() | |
5234 | - | T:place("minecraft:soul_sand", "down", false) |
5234 | + | |
5235 | ||
5236 | T:turnLeft(1) -- left turn, go back into right side, facing left | |
5237 | utils.goBack(1) | |
5238 | T:go("x2 F1x2 F1x2 R1F1") -- go right to left dig 3 blocks, forward on left side | |
5239 | - | T:place("ladder", "down", false) |
5239 | + | |
5240 | T:turnRight(1) -- right turn, go back into left side, facing right | |
5241 | - | T:place("sign", "forward", false, "UP\n^\n|\n|") |
5241 | + | |
5242 | T:go("x2 F1x2 F1x2 F1x2 F1x2 L1F1") -- go left to right dig 5 blocks, forward on right side | |
5243 | ||
5244 | - | T:place("sign", "forward", false, "UP\n^\n|\n|") |
5244 | + | |
5245 | utils.goBack(1) | |
5246 | T:go("x2 F1x2 F1x2 F1x2 F1x2 F1x2 F1x2 R1F1") -- go right to left dig 7 blocks, forward on left side | |
5247 | - | T:place("sign", "forward", false, "UP\n^\n|\n|") |
5247 | + | |
5248 | T:turnRight(1) -- right turn, go back into left side, facing right | |
5249 | utils.goBack(1) | |
5250 | T:go("x2 F1x2 F1x2 F1x2 F1x2 F1x2 F1x2 F1x2 F1x2 L1") -- go left to right dig 5 blocks, face forward on right side | |
5251 | end | |
5252 | - | T:place("sign", "forward", false, "UP\n^\n|\n|") |
5252 | + | |
5253 | lib.setPosition(false) -- move to back of cube and verify position | |
5254 | if R.subChoice == 1 then | |
5255 | T:forward(3) -- forward 4 (centre of chamber) | |
5256 | else | |
5257 | T:forward(2) -- forward 3 | |
5258 | end | |
5259 | T:down(1) | |
5260 | lib.digFloor() | |
5261 | if R.subChoice == 1 then | |
5262 | T:go("D1F1 L1F8") | |
5263 | utils.goBack(4) | |
5264 | T:go("L1U1") | |
5265 | lib.setPosition(true) -- place water sources | |
5266 | T:go("F8D2") | |
5267 | -- go down 2, check floor, up 1, place fence | |
5268 | T:go("D2C2U1", false, 0, true) | |
5269 | T:place("fence", -1, "down", false) | |
5270 | T:go("F1D1C2U1", false, 0, true) | |
5271 | T:place("fence", -1, "down", false) | |
5272 | T:go("F1U1R2", false, 0, true) | |
5273 | T:go("F1R1U1") | |
5274 | T:place("sign", -1, "down", false) | |
5275 | T:go("U1C0D1") | |
5276 | T:place("slab", -1, "up", false) | |
5277 | T:go("R2F1R2") | |
5278 | T:place("sign", -1, "forward", false) | |
5279 | T:go("R1F1R2C1R1F1D1L1") --sitting on soul sand/dirt facing spawner | |
5280 | if not T:place("minecraft:soul_sand", -1, "down", false) then | |
5281 | T:place("minecraft:dirt", -1, "down", false) | |
5282 | end | |
5283 | else | |
5284 | - | T:place("fence", "up", false) |
5284 | + | |
5285 | T:go("R1F1 R1F8") | |
5286 | utils.goBack(4) | |
5287 | T:go("R1U1") | |
5288 | lib.setPosition(true) -- place water sources | |
5289 | T:go("F8D2 F1C2C0 F1") -- exit leaving single hole in wall, facing away from spawner | |
5290 | end | |
5291 | ||
5292 | return {} | |
5293 | end | |
5294 | ||
5295 | local function createMobBubbleLift(R) -- 64 | |
5296 | -- Part 3 / 3 Mob Spawner Farm | |
5297 | -- R.subChoice = 1 or 2 (left/right) | |
5298 | local lib = {} | |
5299 | ||
5300 | function lib.initialise() | |
5301 | local blockType = T:getBlockType("down") | |
5302 | if blockType ~= "minecraft:soul_sand" then | |
5303 | T:dig("down") | |
5304 | if not T:place("minecraft:soul_sand", -1, "down", false) then | |
5305 | return {"Unable to find or place soulsand."} | |
5306 | end | |
5307 | end | |
5308 | -- check facing sign, rotate if not | |
5309 | blockType = T:getBlockType("forward") | |
5310 | local turns = 0 | |
5311 | while blockType:find("sign") == nil do | |
5312 | T:turnRight(1) | |
5313 | turns = turns + 1 | |
5314 | if turns == 4 then | |
5315 | return {"Unable to find sign."} | |
5316 | - | local function createFarmNetworkStorage(R, withStorage, removeLegacy) |
5316 | + | |
5317 | - | removeLegacy = removeLegacy or false |
5317 | + | |
5318 | - | -- new or converted farm will have: |
5318 | + | |
5319 | - | -- 2 modems, 1 barrel per plot |
5319 | + | |
5320 | - | -- primary plot and storage needs 1 modem, 1 barrel, 8 chests |
5320 | + | |
5321 | ||
5322 | function lib.createWaterSource(oTurn) | |
5323 | - | function lib.createBasement(R, up, down, width, length) |
5323 | + | |
5324 | - | -- start facing lower left |
5324 | + | |
5325 | - | R.up = up |
5325 | + | |
5326 | - | R.down = down |
5326 | + | |
5327 | - | R.width = width |
5327 | + | |
5328 | - | R.length = length |
5328 | + | |
5329 | - | clearRectangle(R) -- dig 10 x 10 x 2 area, return to starting position |
5329 | + | |
5330 | - | -- add network cable, modems and chests |
5330 | + | |
5331 | T:go("R2F1") -- face column move to middle | |
5332 | T:placeWater("forward") | |
5333 | - | function lib.placeNetwork(count, pattern) |
5333 | + | |
5334 | T:placeWater("forward") | |
5335 | - | T:place("computercraft:cable", "up", true) |
5335 | + | |
5336 | - | if i < count then |
5336 | + | |
5337 | - | T:go(pattern) |
5337 | + | |
5338 | function lib.goToWater(moves) | |
5339 | T:down(moves) | |
5340 | T:getWater("down") | |
5341 | sleep(0.1) | |
5342 | - | -- called when starting at lower left side of plot, facing crops |
5342 | + | |
5343 | - | if removeLegacy then |
5343 | + | |
5344 | ||
5345 | - | while turtle.suckDown() do end |
5345 | + | |
5346 | - | --T:dig("down", false) -- do not bypass chests |
5346 | + | |
5347 | - | turtle.digDown() |
5347 | + | |
5348 | - | T:place("dirt", "down") |
5348 | + | |
5349 | - | T:go("R2F1") |
5349 | + | |
5350 | - | while turtle.suck() do end |
5350 | + | T:place("chest", 0, "down") |
5351 | - | T:go("F1L1 F1U1 R2") -- remove barrel/wall or double chest. face tree |
5351 | + | |
5352 | - | T:place("stone", "down") |
5352 | + | |
5353 | T:place("chest", 0, "down") | |
5354 | - | T:place("modem", "down") |
5354 | + | |
5355 | - | -- could be tree/sapling in front |
5355 | + | |
5356 | T:go("D1x1") | |
5357 | - | if T:getBlockType("down") == "minecraft:dirt" then |
5357 | + | T:place("hopper", 0, "forward") |
5358 | - | T:place("barrel", "down") |
5358 | + | |
5359 | - | T:go("U1x0") |
5359 | + | |
5360 | - | T:place("dirt", "up") |
5360 | + | |
5361 | - | T:go("B1U2") |
5361 | + | |
5362 | - | if T:getBlockType("forward"):find("log") ~= nil then |
5362 | + | |
5363 | - | T:place("sapling", "forward") |
5363 | + | |
5364 | while turtle.detect() do | |
5365 | - | T:go("D3F1 R1F1") |
5365 | + | |
5366 | moves = moves + 1 | |
5367 | - | T:place("barrel", "down") |
5367 | + | |
5368 | ||
5369 | return moves | |
5370 | - | while turtle.suckDown() do end |
5370 | + | |
5371 | - | T:place("modem", "down") |
5371 | + | |
5372 | - | network.attachModem() |
5372 | + | |
5373 | - | T:go("F1x2 R2C2 F1L1 F1D1") |
5373 | + | |
5374 | D.width = 4 | |
5375 | - | T:go("L1D3") -- move below crop field, face N |
5375 | + | |
5376 | - | lib.createBasement(R, true, true, 10, 10) -- ends facing N below water source |
5376 | + | |
5377 | - | T:go("U1 F9R1 F1R2 C1R2 F8R1 F1R2 C1R2 F8R1 F1R2 C1R2 F8") -- facing W below water source |
5377 | + | |
5378 | - | T:go("F1 R2C1 R1 F1L1 x0x2") -- move to corner, face along front edge |
5378 | + | |
5379 | - | for c = 1, 4 do |
5379 | + | |
5380 | - | if c == 1 then |
5380 | + | |
5381 | - | lib.placeNetwork(12, "F1x0x2") |
5381 | + | |
5382 | ||
5383 | - | lib.placeNetwork(11, "F1x0x2") |
5383 | + | |
5384 | end | |
5385 | - | if c < 4 then |
5385 | + | |
5386 | - | T:go("L1F1 x0x2 L1C1R1") |
5386 | + | |
5387 | for i = 1, 9 do -- fill in a solid block bar from bubble column for 8 spaces | |
5388 | T:go("F1C0C2 R1C1 R1C1 R1C1 R1C1") | |
5389 | - | -- now in bottom left facing S |
5389 | + | |
5390 | - | T:go("L2F1R1") -- under modem/netwok cable facing in |
5390 | + | |
5391 | - | for i = 1, 3 do |
5391 | + | |
5392 | - | T:go("L1C1 R1C1 R1C1 L1D1") |
5392 | + | |
5393 | - | T:place("computercraft:cable", "up", true) |
5393 | + | |
5394 | end | |
5395 | - | T:go("C1L1 C1L1 C1L1 C1L1 D1L1")-- ready for clearing rectangle up/down |
5395 | + | |
5396 | - | T:place("computercraft:cable", "up", true) |
5396 | + | |
5397 | local oTurn = "L" | |
5398 | - | T:place("computercraft:cable", "up", true) |
5398 | + | |
5399 | - | lib.createBasement(R, true, true, 11, 11) |
5399 | + | |
5400 | oTurn = "R" | |
5401 | - | lib.placeNetwork(11, "F1") |
5401 | + | |
5402 | - | T:go("R2F4 R1") |
5402 | + | |
5403 | - | lib.placeNetwork(11, "F1") |
5403 | + | |
5404 | - | T:go("L1F5 L1F9 R1D1 C1") -- ready to make ladder column |
5404 | + | |
5405 | return data -- eg {"Unable to find sign."} | |
5406 | - | if i < 5 then |
5406 | + | |
5407 | - | T:go("U1C1") |
5407 | + | |
5408 | for i = 1, 3 do -- fill in back and one side, go up | |
5409 | T:go(turn.."1C1"..turn.."1C1"..turn.."1x1"..turn.."1U1", false, 0, true) | |
5410 | end | |
5411 | - | T:place("ladder", "down") |
5411 | + | |
5412 | local colHeight = 19 | |
5413 | - | if withStorage then |
5413 | + | |
5414 | - | T:go("R1F4 R1F3 D1x2") |
5414 | + | |
5415 | - | T:place("computercraft:cable", "down", true) --ready to build chest storage area |
5415 | + | |
5416 | -- facing spawner 20 blocks up. move either left/right 8 blocks, repairing ceiling and sides | |
5417 | - | utils.createStorage() |
5417 | + | |
5418 | - | T:go("U1R1 F5R1 F5U1 C2U1 R2") -- end on plot starting position, facing crops |
5418 | + | |
5419 | lib.mobTransporter() | |
5420 | - | T:go("U1F2 L1F1 U1C2 U1L1") -- end on plot starting position, facing crops |
5420 | + | |
5421 | -- now create bubble column | |
5422 | T:down(colHeight + 2) | |
5423 | - | return "Farm converted to network storage" |
5423 | + | |
5424 | repeat | |
5425 | lib.goToWater(moves) -- get water | |
5426 | moves = lib.up() | |
5427 | T:go("F1") | |
5428 | - | -- extend "right" or "forward". only adds a single new farm. |
5428 | + | |
5429 | T:go("U1C2") | |
5430 | T:placeWater("forward") | |
5431 | utils.goBack(1) | |
5432 | T:go("C1") | |
5433 | moves = moves + 1 | |
5434 | until moves >= colHeight + 1 | |
5435 | lib.goToWater(moves) -- get water for last time | |
5436 | lib.up() -- finishes above lower part of the transport bar | |
5437 | T:go("F2R2C1D1") -- seal off bubble column | |
5438 | utils.goBack(1) | |
5439 | T:placeWater("forward") -- place source on top of bubble column | |
5440 | utils.goBack(7) -- over down shaft | |
5441 | T:down(1) -- start shaft, facing bubble column | |
5442 | for i = 1, 17 do | |
5443 | - | T:place("dirt", "forward", false) |
5443 | + | |
5444 | T:go("R1C1 R1C1 R1C1 R1C1 D1", false, 0, true) | |
5445 | - | --if not T:place("minecraft:crafting_table", "forward", false) then |
5445 | + | |
5446 | - | if T:place(storage, "forward", false) then |
5446 | + | |
5447 | T:go("x0") | |
5448 | T:go(oTurn.."1C1".. turn.."1D1C2"..oTurn.."1C1"..turn.."1F1".. oTurn.."1F1"..oTurn.."1") -- facing end wall ready to place slabs | |
5449 | for i = 1, 6 do | |
5450 | T:place("slab", 0, "down") | |
5451 | - | T:place("dirt", "forward", false) -- dirt if no storage available |
5451 | + | |
5452 | T:go(oTurn.."1") | |
5453 | end | |
5454 | - | T:place(R.useBlockType, "forward", false) |
5454 | + | |
5455 | T:go("C1") | |
5456 | end | |
5457 | ||
5458 | T:go("D2F2"..turn.."1F5") | |
5459 | - | T:placeWater("down") -- ends facing same direction as started, over water source |
5459 | + | |
5460 | T:go(turn.."1F1"..oTurn.."1") -- facing down mob channel floor | |
5461 | for i = 1, 5 do | |
5462 | T:go("C1") | |
5463 | utils.goBack(1) | |
5464 | end | |
5465 | T:go("C1"..turn.."1F1"..turn.."1F1") | |
5466 | - | T:place("dirt", "down", false) |
5466 | + | |
5467 | T:go("C2x0") | |
5468 | if i < 7 then | |
5469 | T:forward(1) | |
5470 | end | |
5471 | end | |
5472 | T:go("U3R2") | |
5473 | for i = 1, 7 do | |
5474 | - | T:place("dirt", "down", false) |
5474 | + | |
5475 | end | |
5476 | T:go("D3") | |
5477 | ||
5478 | lib.placeCollector(turn, oTurn) -- if hopper / chests present | |
5479 | ||
5480 | return {} | |
5481 | - | if not T:place(storage, "down", false) then-- place barrel/chest below |
5481 | + | |
5482 | - | T:place(storageBackup, "down", false) -- place chest below |
5482 | + | |
5483 | local function createPlatform(R) -- 56 | |
5484 | -- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock) | |
5485 | local forward = true | |
5486 | for w = 1, R.width do | |
5487 | - | -- current position if extend == nil is on ground/farm level facing N |
5487 | + | |
5488 | - | -- if extend = "right", "front" above water source facing crops |
5488 | + | |
5489 | - | local numPlots = 0 |
5489 | + | |
5490 | T:dig("up") | |
5491 | end | |
5492 | if l < R.length then | |
5493 | T:forward(1) | |
5494 | end | |
5495 | - | T:forward(11) |
5495 | + | |
5496 | - | numPlots = numPlots + 1 |
5496 | + | |
5497 | - | until not utils.isStorage("down") -- on top of chest, barrel or modem |
5497 | + | |
5498 | - | T:go("R1F1R2") -- move to front right corner of last plot on right side |
5498 | + | |
5499 | - | --T:go("R1U1 F1L1 F10L1") -- move to front right corner |
5499 | + | |
5500 | else | |
5501 | T:go("R1F1 R1") | |
5502 | end | |
5503 | else | |
5504 | - | T:forward(11) |
5504 | + | |
5505 | - | numPlots = numPlots + 1 |
5505 | + | |
5506 | - | until not utils.isStorage("down") -- on top of chest, barrel or modem |
5506 | + | |
5507 | - | T:go("L1F1 R1x2") -- could dig tree or sapling + block below |
5507 | + | |
5508 | - | --T:go("L2U1 F1R1 F10") |
5508 | + | |
5509 | - | elseif extend == "convertWithStorage" then |
5509 | + | |
5510 | - | -- convert normal (storage) primary plot farm to networked storage |
5510 | + | |
5511 | - | --T:turnLeft(1) -- over water source, facing N |
5511 | + | |
5512 | - | local response = createFarmNetworkStorage(R, true, true) |
5512 | + | |
5513 | - | return {response} |
5513 | + | |
5514 | - | elseif extend == "convert" or extend == "convertWithStorage" then |
5514 | + | |
5515 | - | -- convert normal (storage) extended farm to networked storage |
5515 | + | |
5516 | - | --T:turnLeft(1) -- over water source, facing N |
5516 | + | |
5517 | - | createFarmNetworkStorage(R, false, true) |
5517 | + | |
5518 | - | return {"Farm converted to network storage"} |
5518 | + | |
5519 | - | else -- new farm. |
5519 | + | |
5520 | - | T:up(1) -- assume on the ground, go up 1 |
5520 | + | |
5521 | R.data = "bury" to embed bottom into ground | |
5522 | R.subChoice 1 = facing portal, 2 = aligned | |
5523 | - | -- design change: sapling placed 2 blocks above corner for ease of walking round |
5523 | + | |
5524 | - | if R.networkFarm then -- barrel on corner of plot, modems on each side N/E |
5524 | + | |
5525 | - | T:place("barrel", "down", false) |
5525 | + | |
5526 | function lib.buildBase() | |
5527 | - | T:place(R.useBlockType, "down", false) |
5527 | + | |
5528 | T:go("C2", false, 0, false, R.useBlockType) | |
5529 | - | -- stage 2 place sapling |
5529 | + | |
5530 | for i = 1, R.length - 2 do -- R.length = 4: place when i=1,2 | |
5531 | - | T:place("dirt", "down") |
5531 | + | T:place("minecraft:obsidian", 0, "down", false) |
5532 | - | T:up(1) |
5532 | + | |
5533 | - | T:place("sapling", "down") -- plant sapling |
5533 | + | |
5534 | - | T:go("F1D4") |
5534 | + | |
5535 | - | if R.networkFarm then |
5535 | + | |
5536 | - | T:place("modem", "down", false) |
5536 | + | |
5537 | - | network.attachModem() |
5537 | + | |
5538 | T:place("minecraft:obsidian", 0, "down", false) | |
5539 | - | T:place(R.useBlockType, "down", false) |
5539 | + | |
5540 | T:forward(1) | |
5541 | - | -- stage 2 place double barrel/chest |
5541 | + | |
5542 | T:place("minecraft:obsidian", 0, "down", false) | |
5543 | end | |
5544 | - | T:go("R1F1L1") |
5544 | + | |
5545 | if R.data ~= "bury" then | |
5546 | T:up(1) | |
5547 | end | |
5548 | if R.subChoice == 1 then | |
5549 | T:go("F1R1") | |
5550 | end | |
5551 | local out = true | |
5552 | - | T:go("F1 x0x2C 2", false, 0, false, R.useBlockType) |
5552 | + | |
5553 | lib.buildBase() | |
5554 | for i = 1, R.height - 2 do | |
5555 | T:go("R2U1") | |
5556 | out = not out | |
5557 | - | lib.placeDirt(9, false) -- place dirt back to start |
5557 | + | |
5558 | - | if R.networkFarm then -- water source next to modem |
5558 | + | |
5559 | - | lib.addWaterSource(R, {"c","c","d","d"}, storage) |
5559 | + | |
5560 | - | -- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock |
5560 | + | |
5561 | - | T:go("U1F1L1") |
5561 | + | |
5562 | - | T:place("modem", "down", false) |
5562 | + | |
5563 | - | T:go("F1C2 L1F1 D1", false, 0, false, R.useBlockType) |
5563 | + | |
5564 | end | |
5565 | - | lib.addWaterSource(R, {"c","c","t","d"}, storage) -- put barrel / chest in floor |
5565 | + | |
5566 | - | T:go("U1F1R2") |
5566 | + | |
5567 | - | if T:getBlockType("down"):find(storage) == nil and T:getBlockType("down"):find(storageBackup) == nil then |
5567 | + | |
5568 | - | lib.placeStorage(storage, storageBackup) |
5568 | + | |
5569 | T:go("L1F"..R.width.."D"..R.height - 1 .."R2") | |
5570 | - | T:go("R1F1L1") |
5570 | + | |
5571 | - | if T:getBlockType("down"):find(storage) == nil and T:getBlockType("down"):find(storageBackup) == nil then |
5571 | + | |
5572 | - | lib.placeStorage(storage, storageBackup) |
5572 | + | |
5573 | end | |
5574 | - | T:go("F1D1") |
5574 | + | |
5575 | ||
5576 | return {} | |
5577 | end | |
5578 | ||
5579 | - | T:go("F1U1x0C2"..turn.."1F1"..turn.."1x0 x2C2 F1D1", false, 0, false, R.useBlockType) |
5579 | + | |
5580 | --[[ Used in End World to use a trapdoor to push player through portal ]] | |
5581 | local lib ={} | |
5582 | ||
5583 | function lib.findPortal() | |
5584 | local found = false | |
5585 | local onSide = false | |
5586 | for i = 1, 64 do | |
5587 | if not turtle.up() then -- hit block above | |
5588 | - | lib.addWaterSource(R, {"d","c","c","d"}, storage) -- bottom right |
5588 | + | |
5589 | break | |
5590 | - | lib.addWaterSource(R, {"c","c","d","d"}, storage) -- top right, facing away from plot |
5590 | + | |
5591 | - | T:go("F1U1 R1C2 x0F1 x0x2 C2R1", false, 0, false, R.useBlockType) |
5591 | + | |
5592 | - | for i = 1, 11 do -- build right wall from top of plot to bottom |
5592 | + | |
5593 | -- are we under the centre block, or one of the sides? | |
5594 | if turtle.detect() then -- under a side | |
5595 | - | T:go("R1F10") -- ends on top of front storage/ modem facing tree |
5595 | + | |
5596 | - | if R.networkFarm then -- network storage |
5596 | + | |
5597 | - | network.attachModem() |
5597 | + | |
5598 | - | T:go("R1F1D1R1") -- over water source, facing E (crops) |
5598 | + | |
5599 | - | if extend == "" then -- primary plot |
5599 | + | |
5600 | - | createFarmNetworkStorage(R, true) |
5600 | + | |
5601 | break | |
5602 | - | createFarmNetworkStorage(R, false) |
5602 | + | |
5603 | end | |
5604 | end | |
5605 | if onSide then-- move to centre | |
5606 | T:go("D1F1") | |
5607 | - | utils.goBack(numPlots * 11) |
5607 | + | |
5608 | end | |
5609 | local height = 3 -- allows for 2 bedrock + starting space | |
5610 | - | T:go("R1U1F".. numPlots * 11 .."D1L1") |
5610 | + | |
5611 | height = height + 1 | |
5612 | end | |
5613 | return found, height | |
5614 | end | |
5615 | ||
5616 | function lib.addFloor(length) | |
5617 | for i = 1, length do | |
5618 | if i < length then | |
5619 | - | --T:setUseLog(true, "farmCreateLog.txt", true) |
5619 | + | |
5620 | - | --dbug = true -- set dbug flag |
5620 | + | |
5621 | - | --utils.waitForInput("Logging and debugging enabled") --utils.waitForInput(message) |
5621 | + | |
5622 | end | |
5623 | end | |
5624 | end | |
5625 | ||
5626 | function lib.buildLadder(height) | |
5627 | for i = 1, height do | |
5628 | - | R = utils.checkFarmPosition(R) |
5628 | + | |
5629 | T:go("F1C1 R1C1 L2C1 R1", false, 0, true) | |
5630 | - | if not R.ready then |
5630 | + | |
5631 | - | return {"Unable to determine starting position"} |
5631 | + | |
5632 | T:go("C2") | |
5633 | end | |
5634 | - | createFarm(R, extend) |
5634 | + | T:place("minecraft:ladder", 0, "forward", true) |
5635 | T:up(1) | |
5636 | end | |
5637 | end | |
5638 | ||
5639 | local found, height = lib.findPortal() | |
5640 | if found then -- position under centre of beacon | |
5641 | -- build ladder up and create platform | |
5642 | T:go("L1F1L1F2L2") | |
5643 | T:checkInventoryForItem({"minecraft:ladder"},{height}) | |
5644 | - | R.data == "random" for random floor placement |
5644 | + | |
5645 | T:checkInventoryForItem({"trapdoor"},{1}) | |
5646 | lib.buildLadder(height) -- ends facing ladder, 1 block above | |
5647 | ||
5648 | T:go("R1") | |
5649 | - | function lib.goToRemote(R) |
5649 | + | |
5650 | T:go("C2F1 C2F1 C2F1 C2") | |
5651 | T:go("R1F1R1") | |
5652 | T:go("C2F1 C2F1 C2F1 C2") | |
5653 | utils.goBack(2) | |
5654 | T:go("R1F1") -- facing portal entrance | |
5655 | T:place("trapdoor", -1, "up", false) | |
5656 | else | |
5657 | return {"Portal not found. Move me under","the centre if possible.", "wait for purple beacon."} | |
5658 | end | |
5659 | return {} | |
5660 | end | |
5661 | ||
5662 | local function createRailway(R) -- 93 | |
5663 | -- go(path, useTorch, torchInterval, leaveExisting, preferredBlock) | |
5664 | --[[Build steps up or down ready for railtrack]] | |
5665 | if R.down then | |
5666 | - | return "Measured depth/height of "..depth.." > setting: "..R.height |
5666 | + | |
5667 | local blockType = "" | |
5668 | while blockType == "" do | |
5669 | T:go("F1D1", false, 0, true) | |
5670 | blockType = T:getBlockType("down") | |
5671 | if blockType == "" then | |
5672 | - | function lib.checkPosition(R) |
5672 | + | |
5673 | - | -- check if block above/below |
5673 | + | |
5674 | - | local blockBelow = turtle.detectDown() |
5674 | + | |
5675 | - | local blockAbove = turtle.detectUp() |
5675 | + | |
5676 | - | if R.subChoice == 2 then -- New floor over existing |
5676 | + | |
5677 | - | -- if no block below, assume in correct position and continue |
5677 | + | T:go("U1x0 D1x1 F1x0x1 D1x1 C2", false, 0, false) |
5678 | - | -- else move up 1 and continue |
5678 | + | |
5679 | - | if blockBelow then T:up(1) end |
5679 | + | |
5680 | - | elseif R.subChoice == 4 then -- New ceiling under existing |
5680 | + | |
5681 | - | -- if no block above, assume in correct position and continue |
5681 | + | |
5682 | - | -- else move down 1 and continue |
5682 | + | T:go("C1U2 x0D1F1", false, 0, false) --put stone in front, up 2 excavate 1, down 1, forward 1 |
5683 | - | if blockAbove then T:down(1) end |
5683 | + | |
5684 | end | |
5685 | return {} | |
5686 | end | |
5687 | - | function lib.placeRow(R, direction, waterPresent) |
5687 | + | |
5688 | local function createRectanglePath(R) -- 710, 83 direct commands | |
5689 | -- allow user to control length / width of each path | |
5690 | -- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock) | |
5691 | --local pp = utils.getPrettyPrint() | |
5692 | local lib = {} | |
5693 | ||
5694 | function lib.forward(R) | |
5695 | - | R = lib.getRandomBlock(R) -- changes block randomly ONLY if R.data == "random" |
5695 | + | |
5696 | - | R = lib.changeCheckered(R) -- changes to next block type ONLY if R.data == "checked" |
5696 | + | |
5697 | - | -- ONLY if R.data == "striped" has already been changed for whole row |
5697 | + | |
5698 | - | T:place(R.inventory.useBlock, direction, false) -- leaveExisting = false |
5698 | + | |
5699 | else | |
5700 | for i = 1, R.length do | |
5701 | T:go("F1U1C0D1C2", false, 0, true) | |
5702 | end | |
5703 | - | return waterPresent, R |
5703 | + | |
5704 | end | |
5705 | ||
5706 | - | function lib.getRandomBlock(R) |
5706 | + | |
5707 | - | if R.data == "random" then |
5707 | + | |
5708 | - | local index = math.random(1, #R.inventory.names) -- random index between 1 and no of block types |
5708 | + | |
5709 | - | local success = false |
5709 | + | |
5710 | - | for i = index, R.inventory.blockTypeCount do -- iterate from index upwards |
5710 | + | |
5711 | - | if R.inventory.quantities[i] > 0 then -- at least 1 block left |
5711 | + | |
5712 | - | R.inventory.useBlock = R.inventory.names[i] |
5712 | + | |
5713 | - | R.inventory.quantities[i] = R.inventory.quantities[i] - 1 |
5713 | + | |
5714 | - | R.inventory.blockCount = R.inventory.blockCount - 1 |
5714 | + | |
5715 | - | success = true |
5715 | + | |
5716 | function lib.right(R) | |
5717 | T:turnRight(R.length) | |
5718 | end | |
5719 | ||
5720 | - | if not success then -- no blocks left in the range of index -> no of block types |
5720 | + | |
5721 | - | for i = index, 1, -1 do -- go backwards from index to 1 |
5721 | + | |
5722 | - | if R.inventory.quantities[i] > 0 then -- at least 1 block left |
5722 | + | |
5723 | - | R.inventory.useBlock = R.inventory.names[i] |
5723 | + | |
5724 | - | R.inventory.quantities[i] = R.inventory.quantities[i] - 1 |
5724 | + | |
5725 | - | R.inventory.blockCount = R.inventory.blockCount - 1 |
5725 | + | |
5726 | - | success = true |
5726 | + | |
5727 | ||
5728 | function lib.down() | |
5729 | T:go("D1C2", false, 0, true) | |
5730 | end | |
5731 | - | end |
5731 | + | |
5732 | if R.data == "menu" then | |
5733 | - | return R |
5733 | + | |
5734 | local width = 0 | |
5735 | local length = 0 | |
5736 | - | function lib.changeStripe(R) |
5736 | + | |
5737 | - | if R.data == "striped" then |
5737 | + | |
5738 | - | R.size = R.size + 1 |
5738 | + | |
5739 | - | if R.size > R.inventory.blockTypeCount then |
5739 | + | |
5740 | - | R.size = 1 |
5740 | + | |
5741 | "Back # blocks", | |
5742 | - | R.inventory.useBlock = R.inventory.names[R.size] |
5742 | + | |
5743 | "Turn Left", | |
5744 | - | return R |
5744 | + | |
5745 | "Down 1 block", | |
5746 | "Quit" | |
5747 | - | function lib.changeCheckered(R) |
5747 | + | |
5748 | - | --swap between 2 block types |
5748 | + | |
5749 | - | if R.data == "checked" then |
5749 | + | |
5750 | - | if R.inventory.useBlock == R.inventory.names[1] then |
5750 | + | |
5751 | - | R.inventory.useBlock = R.inventory.names[2] |
5751 | + | |
5752 | if choice == 1 then | |
5753 | - | R.inventory.useBlock = R.inventory.names[1] |
5753 | + | |
5754 | lib.forward(R) | |
5755 | elseif choice == 2 then | |
5756 | - | return R |
5756 | + | |
5757 | R.length = menu.getInteger("Move forward how many blocks?", 1, 250, nil, colors.lime) | |
5758 | lib.forward(R) | |
5759 | elseif choice == 3 then | |
5760 | R.length = 1 | |
5761 | - | if R.data == "random" then |
5761 | + | |
5762 | - | math.randomseed(R.inventory.blockCount) |
5762 | + | |
5763 | - | print("Using random blocks") |
5763 | + | |
5764 | - | elseif R.data == "striped" then |
5764 | + | |
5765 | - | print("Using striped pattern") |
5765 | + | |
5766 | - | elseif R.data == "checked" then |
5766 | + | |
5767 | - | print("Using checkered pattern") |
5767 | + | |
5768 | elseif choice == 6 then | |
5769 | R.length = 1 | |
5770 | lib.left(R) | |
5771 | elseif choice == 7 then | |
5772 | lib.up(R) | |
5773 | elseif choice == 8 then | |
5774 | lib.down() | |
5775 | - | local message = lib.goToRemote(R) |
5775 | + | |
5776 | - | if message ~= "" then -- error encountered |
5776 | + | |
5777 | - | return {message} |
5777 | + | |
5778 | local instructions = | |
5779 | [[~lightGray~Commands: | |
5780 | ||
5781 | - | lib.checkPosition(R) |
5781 | + | |
5782 | - | -- based on clearRectangle code |
5782 | + | |
5783 | - | if R.width == 1 then -- single block ahead only |
5783 | + | |
5784 | - | waterPresent, R = lib.placeRow(R, direction, waterPresent) |
5784 | + | |
5785 | - | T:turnRight(2) -- turn at the top of the run |
5785 | + | |
5786 | - | T:forward(R.length - 1) -- return to start |
5786 | + | |
5787 | - | T:turnRight(2) -- turn round to original position |
5787 | + | |
5788 | ~red~q = quit | |
5789 | - | local iterations = 0 -- R.width = 2, 4, 6, 8 etc |
5789 | + | |
5790 | - | if R.width % 2 == 1 then -- R.width = 3, 5, 7, 9 eg R.width 7 |
5790 | + | |
5791 | - | iterations = (R.width - 1) / 2 -- iterations 1, 2, 3, 4 for widths 3, 5, 7, 9 |
5791 | + | |
5792 | while cmd ~= "q" do | |
5793 | local line = menu.clear() | |
5794 | line = menu.colourText(line, instructions) | |
5795 | - | R = lib.changeStripe(R) |
5795 | + | |
5796 | - | R = lib.changeCheckered(R) |
5796 | + | |
5797 | - | for i = 1, iterations do -- eg 3 blocks wide, iterations = 1 |
5797 | + | |
5798 | - | waterPresent, R = lib.placeRow(R, direction, waterPresent) |
5798 | + | |
5799 | cmd = input:sub(1,1) | |
5800 | - | R = lib.changeStripe(R) |
5800 | + | |
5801 | - | --R = lib.changeCheckered(R) |
5801 | + | |
5802 | - | waterPresent, R = lib.placeRow(R, direction, waterPresent) |
5802 | + | |
5803 | end | |
5804 | if cmd == "q" then | |
5805 | return{"User has quit application"} | |
5806 | - | R = lib.changeStripe(R) |
5806 | + | |
5807 | if cmd == "f" then | |
5808 | lib.forward(R) | |
5809 | elseif cmd == "b" then | |
5810 | lib.back(R) | |
5811 | - | R = lib.changeStripe(R) |
5811 | + | |
5812 | - | waterPresent, R = lib.placeRow(R, direction, waterPresent) |
5812 | + | |
5813 | elseif cmd == "r" then | |
5814 | lib.right(R) | |
5815 | elseif cmd == "u" then | |
5816 | lib.up(R) | |
5817 | elseif cmd == "d" then | |
5818 | lib.down() | |
5819 | end | |
5820 | end | |
5821 | end | |
5822 | return {} | |
5823 | end | |
5824 | ||
5825 | local function createRetainingWall(R) -- 34, 82 | |
5826 | -- facing direction wall will take | |
5827 | -- will need to rotate 180 to build | |
5828 | -- if R.height > 0 then build to specified depth | |
5829 | local lib = {} | |
5830 | ||
5831 | function lib.checkFloor() | |
5832 | local newDepth = 0 | |
5833 | place = utils.clearVegetation("down") -- in case col in front is deeper | |
5834 | while place do -- loop will be entered at least once | |
5835 | T:down(1) | |
5836 | newDepth = newDepth + 1 | |
5837 | place = utils.clearVegetation("down") | |
5838 | end | |
5839 | if newDepth > 0 then | |
5840 | for j = 1, newDepth do -- go up until column base is met | |
5841 | T:go("U1C2") | |
5842 | end | |
5843 | end | |
5844 | end | |
5845 | ||
5846 | function lib.patchMissingBlock() | |
5847 | if turtle.back() then | |
5848 | T:go("C1") | |
5849 | else | |
5850 | T:go("B1C1") | |
5851 | end | |
5852 | end | |
5853 | ||
5854 | function lib.placeSingle(height) | |
5855 | - | T:place("torch", "forward") -- place torch, move forward |
5855 | + | |
5856 | if height > 0 then | |
5857 | T:go("D"..height) | |
5858 | y = height | |
5859 | else | |
5860 | local place = utils.clearVegetation("down") | |
5861 | while place do -- loop will be entered at least once | |
5862 | - | if not T:place("slab", "down") then -- break if out of slabs |
5862 | + | |
5863 | if place then | |
5864 | T:down(1) | |
5865 | y = y + 1 | |
5866 | end | |
5867 | end | |
5868 | end | |
5869 | -- return to surface, placing below | |
5870 | for i = 1, y do | |
5871 | T:go("U1C2", false, 0, true) | |
5872 | end | |
5873 | end | |
5874 | ||
5875 | function lib.placeDouble(height) | |
5876 | --T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock) | |
5877 | local y = 0 | |
5878 | if not turtle.back() then | |
5879 | T:go("B1") | |
5880 | end | |
5881 | if height > 0 then | |
5882 | for i = 1, height do | |
5883 | T:go("C1D1", false, 0, true) | |
5884 | end | |
5885 | T:go("C1", false, 0, true) | |
5886 | y = height | |
5887 | else | |
5888 | local place = utils.clearVegetation("down") | |
5889 | -- build back column | |
5890 | while place do -- loop will be entered at least once | |
5891 | place = utils.clearVegetation("down") | |
5892 | if place then | |
5893 | T:go("C1D1", false, 0, true) | |
5894 | y = y + 1 | |
5895 | end | |
5896 | end | |
5897 | -- reached bottom. floor in front could drop down | |
5898 | - | -- T:place(blockType, direction, leaveExisting, signText) |
5898 | + | |
5899 | - | if not T:place("stone", "forward", false) then |
5899 | + | |
5900 | turtle.back() -- back at starting point | |
5901 | T:go("C1", false, 0, true) | |
5902 | end | |
5903 | - | if T:getItemSlot("minecraft:torch") > 0 then |
5903 | + | |
5904 | - | T:place("torch", "forward", false) |
5904 | + | |
5905 | T:go("U1C2", false, 0, true) | |
5906 | end | |
5907 | end | |
5908 | ||
5909 | function lib.placeTriple(height) | |
5910 | --T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock) | |
5911 | - | if not T:place("slab", "forward", false) then |
5911 | + | |
5912 | if turtle.back() then | |
5913 | T:go("C1") | |
5914 | else | |
5915 | T:go("B1C1") | |
5916 | end | |
5917 | if height > 0 then | |
5918 | for i = 1, height do | |
5919 | T:go("C1D1", false, 0, true) | |
5920 | end | |
5921 | for i = 1, height do | |
5922 | T:go("C1D1", false, 0, true) | |
5923 | end | |
5924 | - | if not T:place("stone", "forward", false) then |
5924 | + | |
5925 | y = height | |
5926 | else | |
5927 | local place = utils.clearVegetation("down") | |
5928 | - | if T:getItemSlot("minecraft:torch") > 0 then |
5928 | + | |
5929 | - | T:place("torch", "forward", false) |
5929 | + | |
5930 | place = utils.clearVegetation("down") | |
5931 | if place then | |
5932 | T:go("C1D1", false, 0, true) | |
5933 | y = y + 1 | |
5934 | end | |
5935 | end | |
5936 | -- reached bottom. floor in front could drop down | |
5937 | T:go("F1") -- move under first column | |
5938 | - | T:place("ice", "down", true) |
5938 | + | |
5939 | T:go("B1C1R2F1", false, 0, true) | |
5940 | lib.checkFloor() | |
5941 | T:go("B1C1") | |
5942 | -- return to surface , placing below and to front | |
5943 | end | |
5944 | for i = 1, y do | |
5945 | T:go("C1U1C2", false, 0, true) | |
5946 | end | |
5947 | T:go("F1R2C1", false, 0, true) | |
5948 | -- facing back again inside edge of col 3 | |
5949 | return y -- depth of this run | |
5950 | end | |
5951 | ||
5952 | local topInPlace = false -- topInPlace = true already a path across the water eg monument rectangle | |
5953 | - | if not T:place("ice", "down", true) then -- out of ice |
5953 | + | |
5954 | topInPlace = true | |
5955 | end | |
5956 | local place = false | |
5957 | local inWater = false | |
5958 | local onWater = false | |
5959 | if not topInPlace then | |
5960 | if R.length > 1 then | |
5961 | inWater, onWater = utils.getWaterStatus() -- returns whether above water, or immersed | |
5962 | end | |
5963 | end | |
5964 | ||
5965 | local maxDepth = 5 --initial estimated value | |
5966 | -- start at surface, move back 1 block | |
5967 | -- each iteration completes 3 columns | |
5968 | local numBlocks = T:getSolidBlockCount() | |
5969 | print("Solid blocks in inventory: "..numBlocks) | |
5970 | ||
5971 | if R.length == 1 then -- single column down to water bed | |
5972 | lib.placeSingle(R.height) | |
5973 | elseif R.length == 2 then--down then up: 2 cols | |
5974 | inWater, onWater = utils.startWaterFunction(onWater, inWater, 2, true) -- move into water | |
5975 | T:go("R2") -- move to face player | |
5976 | lib.placeDouble(R.height) | |
5977 | if not inWater then | |
5978 | T:go("U1C2", false, 0, true) | |
5979 | end | |
5980 | else -- R.length 3 or more | |
5981 | if topInPlace then | |
5982 | T:down(1) -- break through top | |
5983 | else | |
5984 | inWater, onWater = utils.startWaterFunction(onWater, inWater, 2, true) -- move into water | |
5985 | end | |
5986 | T:go("R2") -- move to face player | |
5987 | -- now at water surface | |
5988 | local remain = R.length | |
5989 | while remain >= 3 do | |
5990 | numBlocks = T:getSolidBlockCount() | |
5991 | print("Inventory blocks: "..numBlocks.." depth: "..maxDepth) | |
5992 | if numBlocks < maxDepth * 3 then | |
5993 | --ask player for more | |
5994 | T:checkInventoryForItem({"stone"}, {maxDepth * remain}, false) | |
5995 | end | |
5996 | local y = lib.placeTriple(R.height) -- moves back, places col in front, centre and behind. R.height = 0 for auto depth | |
5997 | if y > maxDepth then | |
5998 | maxDepth = y | |
5999 | end | |
6000 | remain = remain - 3 | |
6001 | if remain > 1 then | |
6002 | lib.patchMissingBlock() | |
6003 | end | |
6004 | end | |
6005 | if remain == 1 then -- 1 more column | |
6006 | lib.patchMissingBlock() | |
6007 | lib.placeSingle(R.height) | |
6008 | elseif remain == 2 then -- 2 cols | |
6009 | lib.placeDouble(R.height) | |
6010 | end | |
6011 | T:go("U1C2") -- above surface | |
6012 | end | |
6013 | return {} | |
6014 | end | |
6015 | ||
6016 | local function createSafeDrop(R) -- 14 | |
6017 | -- dig down height blocks, checking for blocks on all sides | |
6018 | local drop = 0 | |
6019 | local isBedrock = false | |
6020 | T:down(2) | |
6021 | drop = 2 | |
6022 | for i = 1, R.height - 1 do | |
6023 | for j = 1, 4 do | |
6024 | -- go(path, useTorch, torchInterval, leaveExisting, preferredBlock) | |
6025 | T:go("C1R1", false, 0, true) | |
6026 | end | |
6027 | if T:down(1) then | |
6028 | drop = drop + 1 | |
6029 | else | |
6030 | isBedrock = true | |
6031 | break | |
6032 | end | |
6033 | if T:isWaterOrLava("up") ~= "" then | |
6034 | T:go("C0x0", false, 0, false) -- delete water/ lava block | |
6035 | end | |
6036 | end | |
6037 | if not isBedrock then -- not sitting on bedrock, so break foot level exit block | |
6038 | T:go("U1R2x1") | |
6039 | - | if not T:place("ladder", "forward", false) then |
6039 | + | |
6040 | T:placeWater("down") | |
6041 | if isBedrock then | |
6042 | T:go("U1x1 U1x1") | |
6043 | else | |
6044 | - | T:place("common", direction, false) -- any common block |
6044 | + | |
6045 | end | |
6046 | - | T:place("minecraft:torch", direction, false) |
6046 | + | |
6047 | ||
6048 | return {"Safe drop completed "..drop .. " blocks"} | |
6049 | end | |
6050 | ||
6051 | local function createSlopingWater(R) -- 34, 89 | |
6052 | --[[ | |
6053 | creates a sloping water area above existing lake/river/ocean | |
6054 | R.width is usually 7 with an existing wall on 8th row | |
6055 | R.length is user choice, limited to bucket/slab quantities | |
6056 | Places slabs into existing surface, places row of sources | |
6057 | Removes slabs | |
6058 | ]] | |
6059 | local lib = {} | |
6060 | ||
6061 | function lib.fillBuckets() | |
6062 | local emptyBuckets = utils.getEmptyBucketCount() | |
6063 | for i = 1, emptyBuckets do | |
6064 | if utils.fillBucket("down") then | |
6065 | print("Bucket filled down") | |
6066 | sleep(0.3) | |
6067 | else | |
6068 | print("Unable to fill bucket ".. i .." / "..emptyBuckets) | |
6069 | end | |
6070 | end | |
6071 | return utils.getWaterBucketCount() | |
6072 | end | |
6073 | ||
6074 | local outbound = true | |
6075 | local inWater, onWater = utils.getWaterStatus() | |
6076 | inWater, onWater = utils.startWaterFunction(onWater, inWater, 2 ,false) -- move above water, max descent 2 | |
6077 | local waterBuckets = lib.fillBuckets() | |
6078 | for w = 1, R.width do | |
6079 | for l = 1, R.length do | |
6080 | T:place("slab", -1, "down", false) | |
6081 | if l < R.length then | |
6082 | T:forward(1) | |
6083 | end | |
6084 | end | |
6085 | if w < R.width then | |
6086 | if outbound then | |
6087 | T:go("R1F1R1") | |
6088 | else | |
6089 | T:go("L1F1L1") | |
6090 | end | |
6091 | outbound = not outbound | |
6092 | end | |
6093 | end | |
6094 | if outbound then | |
6095 | T:go("L1F"..R.width - 1 .."L1") | |
6096 | else | |
6097 | T:go("R1F"..R.width - 1 .."R1") | |
6098 | end | |
6099 | T:placeWater("up") -- place in corner | |
6100 | local move = true | |
6101 | while move do | |
6102 | move = turtle.forward() | |
6103 | move = turtle.forward() -- false if at end of run | |
6104 | T:placeWater("up") -- alternate positions + end of run | |
6105 | end | |
6106 | T:go("R2D1") | |
6107 | T:sortInventory() -- get all buckets into 1 slot | |
6108 | for w = 1, R.width do | |
6109 | for l = 1, R.length do | |
6110 | if l < R.length then | |
6111 | T:forward(1) | |
6112 | end | |
6113 | end | |
6114 | if w < R.width then | |
6115 | if outbound then | |
6116 | T:go("R1F1R1") | |
6117 | else | |
6118 | T:go("L1F1L1") | |
6119 | end | |
6120 | outbound = not outbound | |
6121 | - | T:place("ladder", "up") |
6121 | + | |
6122 | end | |
6123 | if outbound then | |
6124 | T:go("L1F"..R.width - 1 .."L1") | |
6125 | else | |
6126 | - | T:place("ladder", "forward") |
6126 | + | |
6127 | end | |
6128 | T:go("U2") | |
6129 | ||
6130 | return {} | |
6131 | end | |
6132 | ||
6133 | local function createSquidFarmBase(R) -- 34 | |
6134 | -- dig down to y=45. assume starting at water level (64) | |
6135 | local depth = 0 | |
6136 | local message = | |
6137 | [[Place the turtle under the grid | |
6138 | left corner above current pit | |
6139 | opening. | |
6140 | It will descend to the base and | |
6141 | continue to level y=45. | |
6142 | ||
6143 | Enter to continue... | |
6144 | ]] | |
6145 | - | T:place("minecraft:chest", "up", false) |
6145 | + | |
6146 | while turtle.down()do | |
6147 | depth = depth + 1 | |
6148 | end | |
6149 | T:down(1) | |
6150 | R.height = 21 - depth | |
6151 | R.width = 15 | |
6152 | R.length = 15 | |
6153 | R.silent = true | |
6154 | R.data = "down" | |
6155 | clearSolid(R) | |
6156 | T:up(depth + 4) | |
6157 | return {} | |
6158 | end | |
6159 | ||
6160 | - | while T:getItemSlot("minecraft:torch") > 0 do |
6160 | + | |
6161 | - | turtle.select(T:getItemSlot("minecraft:torch")) |
6161 | + | |
6162 | --move above water | |
6163 | local maxMove = 2 | |
6164 | while turtle.detectDown() and maxMove > 0 do | |
6165 | T:forward(1) | |
6166 | maxMove = maxMove - 1 | |
6167 | end | |
6168 | if R.length > 0 then | |
6169 | for i = 1, R.length - 1 do | |
6170 | success = utils.dropSand() | |
6171 | T:forward(1, false) | |
6172 | end | |
6173 | success = utils.dropSand() | |
6174 | else | |
6175 | while not turtle.detectDown() do -- over water | |
6176 | while not turtle.detectDown() do -- nested to allow forward movement | |
6177 | success = utils.dropSand() -- drops sand and checks supplies | |
6178 | end | |
6179 | if success then | |
6180 | T:forward(1, false) | |
6181 | else -- out of sand | |
6182 | break | |
6183 | end | |
6184 | end | |
6185 | end | |
6186 | return {} | |
6187 | end | |
6188 | ||
6189 | local function createSinkingPlatform(R) -- 58 | |
6190 | local lib = {} | |
6191 | ||
6192 | function lib.stage1a(R) -- build side wall left side | |
6193 | for l = 1, R.length do -- | |*| | | |
6194 | T:go("L1C1 R1C2", false, 0, false) -- |*|>| | to |*|>| | place left wall | |
6195 | if l == 1 then -- first iteration | |
6196 | T:go("U1C2 D1 F1C2", false, 0, false)-- |*|>| | to |*|*|>| up/down block to delete source at corner | |
6197 | elseif l < R.length then -- mid run | |
6198 | T:go("F1C2", false, 0, false) -- |*|>| | to |*|*|>| move forward | |
6199 | else -- end of run | |
6200 | T:go("C1U1 C2D1", false, 0, false) -- |*|>| | to |*|>|*| place end wall | |
6201 | end | |
6202 | end | |
6203 | end | |
6204 | ||
6205 | function lib.stage1b(R) -- same as stage1a on right side | |
6206 | for l = 1, R.length do | |
6207 | T:go("R1C1 L1C2", false, 0, false) | |
6208 | if l == 1 then | |
6209 | T:go("U1C2 D1 F1C2", false, 0, false) | |
6210 | elseif l < R.length then | |
6211 | T:go("F1C2", false, 0, false) | |
6212 | else | |
6213 | T:go("C1U1 C2D1", false, 0, false) | |
6214 | end | |
6215 | end | |
6216 | end | |
6217 | ||
6218 | function lib.stage2(forward) | |
6219 | if forward then | |
6220 | T:go("C1R1 F1L1 C1R2", false, 0, false) | |
6221 | else | |
6222 | T:go("C1L1 F1R1 C1L2", false, 0, false) | |
6223 | end | |
6224 | end | |
6225 | ||
6226 | local forward = true | |
6227 | local goingRight = true | |
6228 | local blockType = T:getBlockType("down") | |
6229 | if blockType:find("water") ~= nil or blockType:find("lava") ~= nil then | |
6230 | T:up(1) | |
6231 | end | |
6232 | for h = 1, R.height do -- repeatedly create a platform, move down and repeat | |
6233 | T:down(1) -- move down into existing platform | |
6234 | if goingRight then -- first side | |
6235 | if forward then -- complete left side | |
6236 | T:go("R2C1 L2", false, 0, false) -- | |>| | to |*|<| | to |*|>| | | |
6237 | lib.stage1a(R) -- build left wall | |
6238 | T:go("R1F1 L1C1 R2C2", false, 0, false) -- turn ready for next side | |
6239 | else | |
6240 | T:go("L2C1 R2", false, 0, false) -- block 1, 1 | |
6241 | lib.stage1b(R) -- turn ready for next side | |
6242 | T:go("L1F1 R1C1 L2C2", false, 0, false) | |
6243 | end | |
6244 | else -- on right side so different approach | |
6245 | if forward then | |
6246 | - | T:place("slab", "up", false) |
6246 | + | |
6247 | lib.stage1b(R) | |
6248 | T:go("C1L1 F1R1 C1L2 C2", false, 0, false) -- turn ready for next side | |
6249 | else -- complete left side | |
6250 | T:go("R2C1 L2", false, 0, false) -- block 1, 1 | |
6251 | lib.stage1a(R) -- turn ready for next side | |
6252 | T:go("C1R1 F1L1 C1R2 C2", false, 0, false) | |
6253 | end | |
6254 | end | |
6255 | forward = not forward -- continue strips across until at far edge | |
6256 | for w = 1, R.width - 2 do | |
6257 | for l = 1, R.length do | |
6258 | if l < R.length then | |
6259 | T:go("C2F1", false, 0, false) | |
6260 | else | |
6261 | T:go("C2", false, 0, false) | |
6262 | end | |
6263 | end | |
6264 | if goingRight then | |
6265 | lib.stage2(forward) | |
6266 | else | |
6267 | lib.stage2(not forward) | |
6268 | - | T:place("slab", "up", false) |
6268 | + | |
6269 | forward = not forward | |
6270 | end -- far side | |
6271 | if goingRight then | |
6272 | if forward then | |
6273 | lib.stage1b(R) | |
6274 | else | |
6275 | lib.stage1a(R) | |
6276 | end | |
6277 | else | |
6278 | if forward then | |
6279 | lib.stage1a(R) | |
6280 | else | |
6281 | lib.stage1b(R) | |
6282 | end | |
6283 | end | |
6284 | goingRight = not goingRight | |
6285 | T:turnRight(2) | |
6286 | forward = not forward | |
6287 | end | |
6288 | - | T:place("slab", "up", false) |
6288 | + | |
6289 | end | |
6290 | ||
6291 | local function createStaircase(R) -- 13 | |
6292 | -- R# L# F# B# U# D# +0 -0 = Right, Left, Forward, Back, Up, Down, up while detect and return, down while not detect | |
6293 | -- dig: x0,x1,x2 (up/fwd/down) | |
6294 | -- suck: s0,s1,s2 | |
6295 | -- place chest: H0,H1,H2 | |
6296 | -- place sapling: S0,S1,S2 | |
6297 | -- place Torch: T0,T1,T2 | |
6298 | -- place Hopper: P0,P1,P2 | |
6299 | -- mine floor: m# = mine # blocks above and below, checking for valuable items below, and filling space with cobble or dirt | |
6300 | -- mine ceiling: M# = mine # blocks, checking for valuable items above, and filling space with cobble or dirt | |
6301 | -- mine ceiling: N# same as M but not mining block below unless valuable | |
6302 | -- place: C,H,r,S,T,P,^ = Cobble / cHest / DIrT / Sapling / Torch / hoPper /stair in direction 0/1/2 (up/fwd/down) eg C2 = place cobble down | |
6303 | ||
6304 | -- 3| |B| | | |
6305 | -- - - - | |
6306 | -- 2|A| |C| | |
6307 | -- - - - | |
6308 | -- 1|^|D| | | |
6309 | -- - - - | |
6310 | -- 1 2 3 | |
6311 | local lib = {} | |
6312 | ||
6313 | function lib.checkFluids() | |
6314 | local isFluid = false | |
6315 | -- check if water or lava present | |
6316 | for i = 1, 4 do | |
6317 | blockType = T:isWaterOrLava("forward") | |
6318 | if blockType:find("lava") ~= nil or blockType:find("water") ~= nil then | |
6319 | isFluid = true | |
6320 | end | |
6321 | end | |
6322 | return isFluid | |
6323 | end | |
6324 | ||
6325 | function lib.createStaircaseSection(onGround, levels, level) | |
6326 | -- start 1,1,1, n | |
6327 | -- stage A | |
6328 | - | -- T:place(blockType, direction, leaveExisting, signText) |
6328 | + | |
6329 | local blockType = "" | |
6330 | local data = T:getStock("stairs") | |
6331 | - | T:place(blockType, "down", false) |
6331 | + | |
6332 | T:craft('stairs', 4) | |
6333 | end | |
6334 | if onGround and isFluid then | |
6335 | -- add right side and block entrance | |
6336 | T:go("R1C1R1C1R2") | |
6337 | end | |
6338 | if isFluid then | |
6339 | T:go("L1C1 R1F1C2 L1C1 R1x1 R1C1 L1C2B1 C1x1 ^1C2", false, 0, true) --start:1,1,1,n stairs A on level 1, going back to 1,1,1,n | |
6340 | else | |
6341 | T:go("F1x1 R1C1 L1C2B1 ^1C2", false, 0, true) | |
6342 | end | |
6343 | if not onGround then | |
6344 | -- stage A1 | |
6345 | T:go("L2C1L2", false, 0, true) -- start 1,1,1,n fix corner on level 1 end: 1,1,1,n | |
6346 | end | |
6347 | -- stage B | |
6348 | T:go("U1L1", false, 0, true) -- end 1,1,1,w layer 2 | |
6349 | level = level + 1 | |
6350 | isFluid = lib.checkFluids() | |
6351 | if isFluid then | |
6352 | T:go("C1", false, 0, true) -- end 1,1,1,w layer 2 | |
6353 | end | |
6354 | if not onGround then | |
6355 | if isFluid then | |
6356 | T:go("L1C1R1", false, 0, true) -- end 1,1,1,w layer 2 | |
6357 | end | |
6358 | end | |
6359 | -- stage C1 | |
6360 | if isFluid then | |
6361 | T:go("R1C1F1C1x1 L1C1 R2C1 L1B1", false, 0, true) | |
6362 | else | |
6363 | T:go("R1F1 R1C1 L1B1", false, 0, true) | |
6364 | end | |
6365 | --level = level + 1 | |
6366 | --if level == levels then | |
6367 | --return false, level | |
6368 | --end | |
6369 | -- stage C2 | |
6370 | T:go("U1") | |
6371 | level = level + 1 | |
6372 | --if level == levels then | |
6373 | --return true, level | |
6374 | --end | |
6375 | isFluid = lib.checkFluids() | |
6376 | if isFluid then | |
6377 | T:go("L1C1L1 C1L2 C1F1L1 C1R2 C1L1 B1C2 D1", false, 0, true) -- end 1,1,2,n | |
6378 | else | |
6379 | T:go("F1R1 C1L1 B1D1", false, 0, true) -- end 1,1,2,n | |
6380 | end | |
6381 | level = level - 1 -- went down in branch above | |
6382 | --if level == levels then | |
6383 | --return false, level | |
6384 | --end | |
6385 | -- stage D | |
6386 | isFluid = lib.checkFluids() | |
6387 | if isFluid then | |
6388 | T:go("C1F1C1F1C1x1L1 C1R1 C1R1", false, 0, true) -- 3,1,2,e | |
6389 | else | |
6390 | T:go("F2 C1R1", false, 0, true) -- 3,1,2,e | |
6391 | end | |
6392 | ||
6393 | return false, level | |
6394 | end | |
6395 | - | T:place("chest", "forward", false) |
6395 | + | |
6396 | --local height = currentLevel -- eg 64 at top or 5 at bedrock | |
6397 | local data = T:getStock("stairs") | |
6398 | --{rt.total, rt.mostSlot, rt.leastSlot, rt.mostCount, rt.leastCount} | |
6399 | local numStairs = data.total | |
6400 | local levels = math.abs(R.depth - R.height) --height of stairs | |
6401 | local numStairsNeeded = levels | |
6402 | numStairsNeeded = numStairsNeeded - numStairs | |
6403 | if numStairsNeeded > 40 then | |
6404 | print('crafting '..numStairsNeeded..' : '..numStairs.. ' in stock') | |
6405 | if T:craft('stairs', 40) then -- max 40 so repeat | |
6406 | data = T:getStock("stairs") | |
6407 | if data.total == 0 then | |
6408 | data = T:getStock("stairs") | |
6409 | end | |
6410 | numStairs = data.total | |
6411 | numStairsNeeded = numStairsNeeded - numStairs | |
6412 | else | |
6413 | return {"Unable to craft stairs"} | |
6414 | end | |
6415 | end | |
6416 | if numStairsNeeded > 0 then | |
6417 | T:craft('stairs', numStairsNeeded) | |
6418 | end | |
6419 | local level = 0 | |
6420 | if R.down then -- go down towards bedrock | |
6421 | local atBedrock = false | |
6422 | for i = 1, levels do | |
6423 | level = level - 1 | |
6424 | if not T:down() then | |
6425 | atBedrock = true | |
6426 | break | |
6427 | end | |
6428 | end | |
6429 | if atBedrock then -- hit bedrock so get to level 5 / -59 | |
6430 | level = T:findBedrockTop(level) | |
6431 | T:go("R1F1R1", false, 0, true) | |
6432 | end | |
6433 | end | |
6434 | local onGround = true | |
6435 | level = 0 | |
6436 | while level < levels do | |
6437 | onGround, level = lib.createStaircaseSection(onGround, levels, level) | |
6438 | end | |
6439 | if not turtle.detectDown() then | |
6440 | T:go("C2") | |
6441 | end | |
6442 | ||
6443 | return{"Staircase completed"} | |
6444 | end | |
6445 | ||
6446 | local function createStripMine(R) | |
6447 | --[[ | |
6448 | R.length should be a multiple of 16 | |
6449 | mine a corridoor repairing floor and ceiling | |
6450 | check sides, remove valuable items | |
6451 | plug if lava present | |
6452 | Every 16 blocks dig a side passage 1 block deep 2 blocks long | |
6453 | ]] | |
6454 | local lib = {} | |
6455 | ||
6456 | function lib.seal(R) | |
6457 | if T:isValuable("forward") then -- valuable block in front. If debris then refuse already dumped | |
6458 | T:dig("forward") | |
6459 | end | |
6460 | local blockType = T:getBlockType("forward") | |
6461 | if blockType:find("lava") ~= nil then | |
6462 | --T:place("stone", 0, "forward", false) -- place does not allow for specific blocktype | |
6463 | T:go("C1", false, 0, false, R.useBlockType) | |
6464 | return true | |
6465 | end | |
6466 | ||
6467 | return false | |
6468 | end | |
6469 | ||
6470 | function lib.checkSeal(R) | |
6471 | local retValue = false | |
6472 | T:turnRight(1) | |
6473 | if lib.seal(R) then | |
6474 | retValue = true | |
6475 | end | |
6476 | T:turnLeft(2) | |
6477 | if lib.seal(R) then | |
6478 | retValue = true | |
6479 | end | |
6480 | T:turnRight(1) | |
6481 | return retValue | |
6482 | end | |
6483 | ||
6484 | function lib.alcove(R) | |
6485 | -- right side, starting at ceiling | |
6486 | T:go("R1F1 C0", false, 0, false, R.useBlockType)-- stone ceiling, facing alcove wall (upper) | |
6487 | lib.seal(R) -- seal alcove wall (upper) | |
6488 | T:go("D1C2", false, 0, false, "cobble") -- cobble floor, facing alcove wall (lower) | |
6489 | lib.seal(R) -- seal alcove wall (lower) | |
6490 | T:go("L2 F1") -- down 1, turn round, return to corridoor. | |
6491 | -- left side | |
6492 | T:go("F1 C2", false, 0, false, "cobble") -- cobble floor, facing alcove wall (lower) | |
6493 | lib.seal(R) -- seal alcove wall (lower) | |
6494 | T:go("U1 C0", false, 0, false, R.useBlockType) -- stone ceiling, still facing alcove wall | |
6495 | lib.seal(R) -- seal alcove wall (upper) | |
6496 | T:go("L2F1L1") -- return to corridoor at ceiling position | |
6497 | lib.placeTorch(R) | |
6498 | end | |
6499 | ||
6500 | function lib.placeTorch(R) | |
6501 | if R.torchInterval > 0 then -- torches onboard | |
6502 | if T:getItemSlot("minecraft:torch") > 0 then | |
6503 | T:place("minecraft:torch", -1, "down") | |
6504 | end | |
6505 | end | |
6506 | end | |
6507 | ||
6508 | local seal = false | |
6509 | if T:getItemSlot("minecraft:torch") == 0 then | |
6510 | R.torchInterval = 0 -- set to default 16 above | |
6511 | end | |
6512 | for steps = 1, R.length do | |
6513 | -- go(path, useTorch, torchInterval, leaveExisting, preferredBlock) | |
6514 | T:go("C2U1C0", false, 0, true, R.useBlockType) -- check and repair floor / ceiling | |
6515 | if steps % 16 == 0 or steps % 16 == 1 then | |
6516 | lib.alcove(R) -- enter and exit at ceiling position | |
6517 | else | |
6518 | seal = lib.checkSeal(R) | |
6519 | end | |
6520 | T:go("F1D1", false, 0, true) | |
6521 | seal = lib.checkSeal(R) | |
6522 | end | |
6523 | if seal then -- water or lava found while tunnelling | |
6524 | T:go("U1C0", false, 0, true, R.useBlockType) | |
6525 | lib.checkSeal(R) | |
6526 | T:go("C1", false, 0, true, R.useBlockType) | |
6527 | T:down(1) | |
6528 | end | |
6529 | return {} | |
6530 | end | |
6531 | ||
6532 | local function createTreefarm(R) -- 22 | |
6533 | local lib = {} | |
6534 | --go(path, useTorch, torchInterval, leaveExisting, preferredBlock) | |
6535 | function lib.buildWallSection(length, placePolished, useBlockType) | |
6536 | for i = 1, length do | |
6537 | if placePolished and i == length - 4 then | |
6538 | - | T:place("slab", "down", true) -- place slab on top T:place(blockType, direction, leaveExisting) |
6538 | + | T:place("polished", 0, "down") |
6539 | T:forward(1) | |
6540 | else | |
6541 | if i < length then | |
6542 | T:go("C2F1", false, 0, false, useBlockType) | |
6543 | end | |
6544 | end | |
6545 | end | |
6546 | end | |
6547 | ||
6548 | function lib.placeFloor(length, useBlockType) | |
6549 | for i = 1, length do | |
6550 | T:go("x0C2", false, 0, false, useBlockType) | |
6551 | if i < length then | |
6552 | T:forward(1) | |
6553 | end | |
6554 | end | |
6555 | end | |
6556 | ||
6557 | function lib.placeWater(length) | |
6558 | T:placeWater("down") | |
6559 | T:go("F"..length.."R1") | |
6560 | end | |
6561 | ||
6562 | function lib.placeCorners(length, numBlocks, useBlockType) | |
6563 | for i = 1, numBlocks do | |
6564 | T:go("C2F1", false, 0, false, useBlockType) | |
6565 | end | |
6566 | -- now at 5th space | |
6567 | T:forward(length - (numBlocks * 2)) | |
6568 | for i = 1, numBlocks do | |
6569 | T:go("C2", false, 0, false, useBlockType) | |
6570 | if i < numBlocks then | |
6571 | T:forward(1) | |
6572 | end | |
6573 | end | |
6574 | end | |
6575 | ||
6576 | function lib.turn(outward) | |
6577 | if outward then | |
6578 | T:go("R1F1R1") | |
6579 | else | |
6580 | T:go("L1F1L1") | |
6581 | end | |
6582 | return not outward | |
6583 | end | |
6584 | ||
6585 | local blockType | |
6586 | local blockModifier | |
6587 | -- R.data = "existing" if on existing tree farm | |
6588 | -- R.up = true if clear area | |
6589 | if R.up then | |
6590 | clearArea(R) | |
6591 | end | |
6592 | ||
6593 | if R.data == "existing" then | |
6594 | T:go("R1F1 D1", false, 0, false) -- move 14 blocks, right, forward, down 1 | |
6595 | lib.buildWallSection(R.width - 1, false, R.useBlockType) | |
6596 | T:turnLeft(1) | |
6597 | lib.buildWallSection(R.length, false, R.useBlockType) | |
6598 | T:turnLeft(1) | |
6599 | lib.buildWallSection(R.width - 1, false, R.useBlockType) | |
6600 | T:go("C2U1R2") | |
6601 | lib.buildWallSection(R.width - 1, true, R.useBlockType) | |
6602 | T:turnRight(1) | |
6603 | lib.buildWallSection(R.length, true, R.useBlockType) | |
6604 | T:turnRight(1) | |
6605 | lib.buildWallSection(R.width, true, R.useBlockType) | |
6606 | T:go("R1") -- on lower left corner facing forward | |
6607 | else | |
6608 | T:down(1) | |
6609 | local placePolished = false | |
6610 | for i = 1, 2 do | |
6611 | lib.buildWallSection(R.length, placePolished, R.useBlockType) | |
6612 | T:turnRight(1) | |
6613 | lib.buildWallSection(R.width, placePolished, R.useBlockType) | |
6614 | T:turnRight(1) | |
6615 | lib.buildWallSection(R.length, placePolished, R.useBlockType) | |
6616 | T:turnRight(1) | |
6617 | lib.buildWallSection(R.width, placePolished, R.useBlockType) | |
6618 | T:turnRight(1) | |
6619 | placePolished = true | |
6620 | if i == 1 then | |
6621 | T:up(1) | |
6622 | end | |
6623 | end -- on lower left corner facing forward | |
6624 | end | |
6625 | T:go("F1R1 F1L1 D2") -- over 13 x 13 internal area | |
6626 | local outward = true | |
6627 | for i = 1, R.width - 2 do | |
6628 | lib.placeFloor(R.length - 2, R.useBlockType) | |
6629 | if i < R.width - 2 then | |
6630 | outward = lib.turn(outward) | |
6631 | end | |
6632 | end | |
6633 | T:go("U1R2") -- over 13 x 13 internal area opposite corner | |
6634 | -- now add corners | |
6635 | lib.placeCorners(R.length - 2, 4, R.useBlockType) | |
6636 | outward = lib.turn(outward) | |
6637 | lib.placeCorners(R.length - 2, 3, R.useBlockType) | |
6638 | outward = lib.turn(outward) | |
6639 | - | T:place(brick, "up") |
6639 | + | lib.placeCorners(R.length - 2, 2, R.useBlockType) |
6640 | outward = lib.turn(outward) | |
6641 | lib.placeCorners(R.length - 2, 1, R.useBlockType) | |
6642 | if outward then | |
6643 | T:go("R1F"..R.width - 9 .."R1") | |
6644 | else | |
6645 | T:go("L1F"..R.width - 9 .."L1") | |
6646 | end | |
6647 | - | T:place("lava", "down") |
6647 | + | |
6648 | lib.placeCorners(R.length - 2, 1, R.useBlockType) | |
6649 | outward = lib.turn(outward) | |
6650 | lib.placeCorners(R.length - 2, 2, R.useBlockType) | |
6651 | outward = lib.turn(outward) | |
6652 | lib.placeCorners(R.length - 2, 3, R.useBlockType) | |
6653 | - | T:place("sign", true, "") |
6653 | + | outward = lib.turn(outward) |
6654 | lib.placeCorners(R.length - 2, 4, R.useBlockType) -- should be back in starting corner facing front | |
6655 | - | T:place(brick, "up") |
6655 | + | |
6656 | T:go("U1R1") | |
6657 | lib.placeWater(R.length - 3) -- place water down then move forward, turn right | |
6658 | lib.placeWater(R.width - 3) | |
6659 | - | T:place(brick, "forward") |
6659 | + | lib.placeWater(R.length - 3) |
6660 | lib.placeWater(R.width - 3) | |
6661 | T:go("F".. math.floor((R.length - 2) / 2).."R1F".. math.floor((R.width - 2) / 2)) -- should be in centre | |
6662 | T:go("D4C2 R1C1 R1C1 R1C1 R1F1 R2") -- facing back of hole ready to place water | |
6663 | T:placeWater("forward") | |
6664 | T:go("R2F7U4") | |
6665 | - | if not T:place("chest", "down") then |
6665 | + | |
6666 | - | T:place("barrel", "down") |
6666 | + | |
6667 | end | |
6668 | ||
6669 | - | T:place("hopper", "down") |
6669 | + | |
6670 | local lib = {} | |
6671 | - | T:place("slab", "forward") |
6671 | + | |
6672 | function lib.placeBarrel(R) | |
6673 | if R.data == "barrel" then | |
6674 | utils.goBack(1) | |
6675 | T:go("L1F1") | |
6676 | T:place("barrel", 0, "down", false) | |
6677 | utils.goBack(1) | |
6678 | T:go("R1") | |
6679 | T:forward(1) | |
6680 | end | |
6681 | end | |
6682 | ||
6683 | function lib.placeTorch(R) | |
6684 | T:up(1) | |
6685 | local up = 1 | |
6686 | local blockType = T:getBlockType("forward") | |
6687 | while blockType:find(R.useBlockType) ~= nil and blockType ~= "" do -- prevent continuous upward travel | |
6688 | T:up(1) | |
6689 | up = up + 1 | |
6690 | blockType = T:getBlockType("forward") | |
6691 | end | |
6692 | T:place("torch", 0, "forward", true) | |
6693 | T:down(up) | |
6694 | end | |
6695 | ||
6696 | function lib.buildWall(R, length) | |
6697 | -- T:place(blockType, damageNo, direction, leaveExisting, signText) | |
6698 | local blockType = "" | |
6699 | local blocks = 0 | |
6700 | lib.placeBarrel(R) | |
6701 | while blocks < length do | |
6702 | if turtle.back() then | |
6703 | T:place(R.useBlockType, 0, "forward", true) | |
6704 | if R.torchInterval > 0 then | |
6705 | if blocks == 0 or blocks % R.torchInterval == 0 then | |
6706 | lib.placeTorch(R) | |
6707 | end | |
6708 | end | |
6709 | blocks = blocks + 1 -- still facing start position | |
6710 | while turtle.down() do | |
6711 | T:place(R.useBlockType, 0, "up", true) | |
6712 | end | |
6713 | else -- obstruction | |
6714 | T:turnRight(2) -- facing away from start | |
6715 | blockType = T:getBlockType("forward") | |
6716 | if blockType:find("torch") ~= nil then | |
6717 | T:go("F1R2") | |
6718 | T:place(R.useBlockType, 0, "forward") | |
6719 | blocks = blocks + 1 -- facing start | |
6720 | elseif blockType:find("log") ~= nil then | |
6721 | T:harvestTree() | |
6722 | T:turnRight(2) | |
6723 | T:place(R.useBlockType, 0, "forward") | |
6724 | blocks = blocks + 1 -- facing start | |
6725 | elseif T:isVegetation(blockType) then | |
6726 | T:go("F1R2") | |
6727 | T:place(R.useBlockType, 0, "forward") | |
6728 | blocks = blocks + 1 -- facing start | |
6729 | else -- cant go forward, go up instead | |
6730 | while turtle.detect() and blockType:find("torch") == nil and blockType:find("log") == nil and not T:isVegetation(blockType) do -- block ahead, but not torch or tree | |
6731 | while turtle.detectUp() do -- will only run if block above | |
6732 | utils.goBack(1) | |
6733 | blocks = blocks - 1 | |
6734 | end | |
6735 | - | T:place("fence", "down", false) |
6735 | + | |
6736 | T:place(R.useBlockType, 0, "down", true) | |
6737 | - | T:place("fence", "down", false) |
6737 | + | |
6738 | end | |
6739 | T:turnRight(2) -- facing start | |
6740 | - | T:place("sign", "down", false) |
6740 | + | |
6741 | end | |
6742 | - | T:place("slab", "up", false) |
6742 | + | |
6743 | end | |
6744 | - | T:place("sign", "forward", false) |
6744 | + | |
6745 | T:turnRight(2) --facing start position | |
6746 | - | if not T:place("minecraft:soul_sand", "down", false) then |
6746 | + | |
6747 | - | T:place("minecraft:dirt", "down", false) |
6747 | + | |
6748 | else | |
6749 | lib.buildWall(R, R.length - 1) | |
6750 | T:go("R1") -- facing start so left turn = turnRight | |
6751 | lib.buildWall(R, R.width - 1) | |
6752 | T:go("R1") | |
6753 | lib.buildWall(R, R.length - 1) | |
6754 | T:go("R1") | |
6755 | lib.buildWall(R, R.width - 2) | |
6756 | T:go("U1") | |
6757 | T:place(R.useBlockType, 0, "down", true) | |
6758 | end | |
6759 | ||
6760 | return {"Wall or fence completed"} | |
6761 | end | |
6762 | ||
6763 | local function createWaterCanal(R) -- 53 | |
6764 | --[[ | |
6765 | designed for 4 turtles, but can be done with 2 as well | |
6766 | R.data = 1 (2 turtles) or 2 (4 turtles) | |
6767 | R.height = 0 (in water/ on canal floor) or 1 (at ground level) | |
6768 | R.side = "R" or "L" | |
6769 | R.subChoice = | |
6770 | - | if not T:place("minecraft:soul_sand", "down", false) then |
6770 | + | |
6771 | 2 = left side above canal water (new canal only) | |
6772 | 3 = right side above canal water (new canal only) | |
6773 | 4 = right side, ground level (on towpath) | |
6774 | 5 = left side in canal water (if present) | |
6775 | 6 = right side in canal water (if present) | |
6776 | ||
6777 | if R.height = 0 then already at correct height on canal floor | |
6778 | check block below, block to left and block above, move forward tunnelling | |
6779 | if entering water then move up, onto canal wall and continue pathway | |
6780 | if tunnelling then flood canal | |
6781 | else R.height = 1 then above water and on path across | |
6782 | move forward, checking for water below | |
6783 | if water finishes, move into canal, drop down and continue tunnelling | |
6784 | ]] | |
6785 | local lib = {} | |
6786 | ||
6787 | function lib.newCanalSide(oTurn) | |
6788 | T:go("C1 U1x1 U1x1 D2"..oTurn.."1", false, 0, false) | |
6789 | end | |
6790 | ||
6791 | function lib.newCanalBase(R) | |
6792 | local oTurn = "R" -- assume R.side = "L" | |
6793 | if R.side == "R" then | |
6794 | oTurn = "L" | |
6795 | end | |
6796 | if not turtle.detectDown() then -- air / water below: fill floor | |
6797 | T:go(oTurn.."1D1") -- *|>| | | to *|V| | | turn towards canal centre, go down ready to repair neighbouring canal base | |
6798 | if T:getBlockType("forward"):find("turtle") ~= nil then -- turtle in similar position | |
6799 | if R.side == "L" then -- only left side repairs, so wait 1 second | |
6800 | sleep(1) | |
6801 | T:go("C1") -- repair neighbouring canal base | |
6802 | end | |
6803 | else | |
6804 | T:go("C1") -- repair neighbouring canal base | |
6805 | end | |
6806 | T:go(R.side.."1") -- *|V| | | to *|>| | | turn to face start | |
6807 | T:up(1) -- *|>| | | return to canal floor | |
6808 | end | |
6809 | T:go("C2", false, 0, false) | |
6810 | end | |
6811 | ||
6812 | function lib.newCanal(R) | |
6813 | -- no source in front as this function called -- *|<| | | facing end wall ready for new canal canal base level | |
6814 | local oTurn = "R" -- assume R.side = "L" | |
6815 | if R.side == "R" then | |
6816 | - | T:place("chest", "down") |
6816 | + | |
6817 | end | |
6818 | lib.newCanalSide(oTurn) -- *|<| | | wall fixed. to -- *|^| | | | |
6819 | - | T:place("chest", "down") |
6819 | + | |
6820 | lib.newCanalBase(R) -- *|>| | | base fixed | |
6821 | T:go("F1"..R.side.."1") -- *|>| | | to *| |>| | to *| |^| | | |
6822 | lib.newCanalSide(oTurn) -- *| |^| | to *| |>| | | |
6823 | - | T:place("hopper", "forward") |
6823 | + | |
6824 | T:go("F1"..R.side.."1") -- *| |>| | to *| | |>| to *| | |^| | |
6825 | lib.newCanalSide(oTurn) -- *| | |^| to *| | |>| | |
6826 | lib.newCanalBase(R) -- *| | |>| base fixed | |
6827 | T:go(R.side.."2") -- *| | |>| to *| | |<|facing existing / back wall | |
6828 | T:forward(1) -- *| |<| | | |
6829 | T:placeWater("forward") -- *|W|<| | placed against start wall | |
6830 | T:go("L2") -- *|W|>| | | |
6831 | T:placeWater("forward") -- *|W|>|W| placed direction of travel | |
6832 | T:go("R2") -- *|W|<|W| rotate | |
6833 | if deletesWater then | |
6834 | T:up(1) | |
6835 | else | |
6836 | sleep(0.2) | |
6837 | end | |
6838 | utils.getWater() -- *|W|<|W| | |
6839 | T:go(oTurn.."2F1") -- *|W|<|W| to *|W|W|>| ready to go | |
6840 | end | |
6841 | ||
6842 | function lib.towpathOnly(R) | |
6843 | --[[single turtle on towpath only using 4 turtles. Starts at ground level]] | |
6844 | for i = 1, R.length do | |
6845 | if turtle.detectDown() then -- eg dirt, stone | |
6846 | T:dig("down") -- remove block below | |
6847 | end | |
6848 | local placeOnly = true | |
6849 | if R.torchInterval > 0 then -- place torches | |
6850 | if i == 1 or i % R.torchInterval == 0 then -- ready to place torch | |
6851 | T:go("C2U1") -- place solid block below, up 1 | |
6852 | T:place("torch", 0, "down") -- place torch, move forward | |
6853 | T:go("F1D1") -- move forward, down | |
6854 | placeOnly = false | |
6855 | end | |
6856 | end | |
6857 | if placeOnly then | |
6858 | T:dig("up") -- clear blocks above | |
6859 | if not T:place("stone", 0, "down") then -- place stone below | |
6860 | break | |
6861 | end | |
6862 | if i < R.length then | |
6863 | T:forward(1) -- move forward | |
6864 | end | |
6865 | end | |
6866 | end | |
6867 | end | |
6868 | ||
6869 | function lib.initialiseCanal(R) | |
6870 | --[[ move turtle to correct position. return moves]] | |
6871 | local moves = 1 | |
6872 | local oTurn = "R" | |
6873 | if R.side == "R" then | |
6874 | oTurn = "L" | |
6875 | end | |
6876 | local newCanal, isWater, isSource = false, false, false | |
6877 | if R.data == 1 then -- use 2 turtles only | |
6878 | if R.subChoice == 1 or R.subChoice == 4 then -- left / right side on towpath- move into canal space | |
6879 | if deletesWater then | |
6880 | T:go(oTurn.."1F1") -- turn to face canal centre, go forward over water | |
6881 | isWater, isSource = T:isWater("down") | |
6882 | if isSource then -- canal already exists | |
6883 | T:go(oTurn.."1") -- stay above water, face existing canal | |
6884 | else -- NOT above source | |
6885 | T:go("D1"..oTurn.."1") -- go to canal floor, face existing | |
6886 | newCanal = true -- flag create 6 water source blocks | |
6887 | end | |
6888 | else -- NOT deletesWater | |
6889 | T:go(oTurn.."1F1D1"..oTurn.."1") -- move into canal, face back along any existing canal | |
6890 | isWater, isSource = T:isWater("forward") | |
6891 | if isSource then | |
6892 | T:go(R.side.."2") -- face forward for new canal | |
6893 | else | |
6894 | newCanal = true | |
6895 | end | |
6896 | end | |
6897 | elseif R.subChoice == 2 or R.subChoice == 3 then-- left / right side above canal finishing pos if deletesWater | |
6898 | if deletesWater then | |
6899 | isWater, isSource = T:isWater("down") | |
6900 | if isSource then | |
6901 | T:go(R.side.."2") -- face towards existing canal | |
6902 | else | |
6903 | T:go("D1"..R.side.."2") -- go down and face existing canal -- no water ahead | |
6904 | newCanal = true -- already in newCanal starting position | |
6905 | end | |
6906 | else -- NOT deletesWater | |
6907 | T:go("D1"..R.side.."2") -- facing existing on canal floor | |
6908 | isWater, isSource = T:isWater("forward") | |
6909 | if isSource then -- water ahead | |
6910 | T:go(R.side.."2") -- face forward for new canal | |
6911 | else | |
6912 | newCanal = true | |
6913 | end | |
6914 | end | |
6915 | elseif R.subChoice == 5 or R.subChoice == 6 then -- left / right side in canal base. Assume NOT deletesWater | |
6916 | - | T:place("slab", "down") |
6916 | + | |
6917 | isWater, isSource = T:isWater("forward") | |
6918 | if isSource then | |
6919 | T:go(oTurn.."2") | |
6920 | else | |
6921 | newCanal = true | |
6922 | end | |
6923 | end | |
6924 | else -- use 4 turtles | |
6925 | if R.subChoice == 1 or R.subChoice == 4 then -- left / right side on towpath stays in place for 4 part canal | |
6926 | ||
6927 | elseif R.subChoice == 2 or R.subChoice == 3 then-- left / right side above canal finishing pos if deletesWater | |
6928 | ||
6929 | elseif R.subChoice == 5 or R.subChoice == 6 then -- left / right side in canal base. Assume NOT deletesWater | |
6930 | ||
6931 | end | |
6932 | end | |
6933 | if newCanal then -- no water ahead, facing start wall of new canal *|<| | | | |
6934 | lib.newCanal(R) -- start new canal, finish facing new canal 6 block water sources | |
6935 | moves = 2 | |
6936 | end | |
6937 | ||
6938 | return moves -- facing forward ready for new canal *|>| | | | |
6939 | end | |
6940 | ||
6941 | function lib.side(R, maxLength) | |
6942 | -- Already in position facing new canal, 2 water buckets | |
6943 | local torch = R.length - maxLength -- start torch count at 1-2 depending on lib.initialise() | |
6944 | local sourceCount = 0 -- allow for 1 iteration of placing source blocks when changing from solid to water | |
6945 | local numBlocks = 0 -- distance travelled | |
6946 | local _, isSource = nil, false -- initialise variables | |
6947 | local oTurn = "R" -- assume R.side == "L" -> oTurn = "R" | |
6948 | if R.side == "R" then -- R.side = "R" | |
6949 | oTurn = "L" -- oTurn = "L" | |
6950 | end | |
6951 | ||
6952 | while numBlocks < maxLength do -- loop from here. Facing forwards to extend canal | |
6953 | torch = torch + 1 -- increase torch spacing interval | |
6954 | numBlocks = numBlocks + 1 -- inrease block count | |
6955 | if deletesWater then -- up to and including mc 1.12.2 | |
6956 | T:forward(1) -- move forward to extend canal | |>| | |
6957 | _, isSource = T:isWater("down") -- check if source water below | |
6958 | if isSource then | |
6959 | sourceCount = sourceCount + 1 -- count source blocks | |
6960 | else | |
6961 | T:down(1) -- down to canal floor | |
6962 | sourceCount = 0 -- reset | |
6963 | T:go("C2", false, 0, false) -- place block below | |
6964 | T:up(1) -- up to water level | |
6965 | end -- still facing away from canal | |
6966 | T:go(R.side.."1F1C2", false, 0, false) -- go above towpath, place stone down, facing out | |
6967 | if turtle.detectUp() then -- ? block above | |
6968 | T:go(R.side.."2U1F1D1"..R.side.."2") -- rotate to face canal, up 1 forward over canal, back down to water level, face towpath | |
6969 | else | |
6970 | utils.goBack(1) -- face towpath | |
6971 | end | |
6972 | -- facing towpath | |
6973 | if R.torchInterval > 0 then -- Are torches required? | |
6974 | if torch == R.torchInterval or numBlocks == 0 then -- check if ready to place | |
6975 | torch = 0 -- reset interval counter | |
6976 | T:go("U1F1") | |
6977 | T:place("torch", -1, "down") -- place torch | |
6978 | utils.goBack(1) | |
6979 | T:down(1) | |
6980 | end | |
6981 | end -- facing towpath, above water | |
6982 | -- facing towpath | |
6983 | if isSource and scoreCount > 0 then | |
6984 | T:go(oTurn.."1x0") -- face new canal direction | |
6985 | else -- not source below, or first time found, ensures continous canal | |
6986 | T:go(R.side.."1x0") -- face back to existing canal | |
6987 | T:placeWater("down") -- place water | |
6988 | T:forward(1) -- forward 1 | |
6989 | T:placeWater("down") -- place water | |
6990 | utils.getWater() -- collects water from below | |
6991 | utils.goBack(1) -- back 1 | |
6992 | T:go(oTurn.."1x0") -- face new canal | |
6993 | end | |
6994 | else | |
6995 | T:forward(1) -- move forward to extend canal | |
6996 | _, isSource = T:isWater("forward") -- check if source water ahead | |
6997 | - | T:place("minecraft:obsidian", "down", false) |
6997 | + | |
6998 | sourceCount = sourceCount + 1 | |
6999 | else | |
7000 | sourceCount = 0 | |
7001 | if not turtle.detectDown() then -- air / water below, but no source in front, so fill it | |
7002 | T:go(oTurn.."1D1") -- ready to repair neighbouring canal base | |
7003 | if T:getBlockType("forward"):find("turtle") ~= nil then -- turtle in similar position | |
7004 | - | T:place("minecraft:obsidian", "down", false) |
7004 | + | |
7005 | sleep(1) | |
7006 | T:go("C1") -- repair neighbouring canal base | |
7007 | end | |
7008 | - | T:place("minecraft:obsidian", "down", false) |
7008 | + | |
7009 | else | |
7010 | T:go("C1"..R.side.."1") -- repair neighbouring canal base if air | |
7011 | end | |
7012 | T:up(1) | |
7013 | end | |
7014 | T:go("C2", false, 0, false) -- place block below if not already source | |
7015 | end | |
7016 | T:go(R.side.."1C1", false, 0, false) -- face canal wall, replace with stone | |
7017 | ||
7018 | local placeTorch = false | |
7019 | if R.torchInterval > 0 then -- Are torches required? | |
7020 | if torch == R.torchInterval or numBlocks == 0 then -- check if ready to place | |
7021 | torch = 0 -- reset interval counter | |
7022 | placeTorch = true | |
7023 | end | |
7024 | end | |
7025 | if (isSource and placeTorch) or not isSource then | |
7026 | T:go("U1x1 U1x1") -- up 2 and excavate blocks above tow path | |
7027 | if placeTorch then -- torch required | |
7028 | T:forward(1) -- move over towpath | |
7029 | T:place("torch", -1, "down") -- place torch | |
7030 | utils.goBack(1) -- move back | |
7031 | end | |
7032 | T:down(2) -- return to canal base | |
7033 | end | |
7034 | if isSource and sourceCount > 1 then -- source ahead found at least once | |
7035 | T:go(oTurn.."1") -- face newcanal as no water refill required | |
7036 | else -- not source in front, or first time found, ensures continous canal | |
7037 | T:go(oTurn.."1C1") -- *| | | |>| face along new canal and block entrance | |
7038 | utils.goBack(1) -- *| | |>| | back 1 | |
7039 | T:placeWater("forward") -- *| | |>|W| place water | |
7040 | T:go(oTurn.."2") -- *| | |<|W| face existing canal | |
7041 | _, isSource = T:isWater("forward") -- *| |?|<|W| check if source water ahead | |
7042 | if not isSource then | |
7043 | if not T:placeWater("forward") then -- place water again *| |W|<|W| | |
7044 | while not T:getWater("forward") do -- wait for other turtle | |
7045 | print("Out of water buckets") | |
7046 | sleep(1) | |
7047 | end | |
7048 | sleep(0.2) | |
7049 | T:getWater("forward") | |
7050 | end | |
7051 | end | |
7052 | utils.getWater() -- collects water *| |W|<|W| | |
7053 | T:go(R.side.."2F1") -- face along new canal *| |W|>|W| to *| |W|W|>| | |
7054 | end | |
7055 | end | |
7056 | end | |
7057 | end | |
7058 | ||
7059 | function lib.waterOnly(R, maxLength) | |
7060 | -- Already in position facing new canal, 2 water buckets | |
7061 | local torch = R.length - maxLength -- start torch count at 1-2 depending on lib.initialise() | |
7062 | local sourceCount = 0 -- allow for 1 iteration of placing source blocks when changing from solid to water | |
7063 | local numBlocks = 0 -- distance travelled | |
7064 | local _, isSource = nil, false -- initialise variables | |
7065 | local oTurn = "R" -- assume R.side == "L" -> oTurn = "R" | |
7066 | if R.side == "R" then -- R.side = "R" | |
7067 | oTurn = "L" -- oTurn = "L" | |
7068 | end | |
7069 | ||
7070 | while numBlocks < maxLength do -- loop from here. Facing forwards to extend canal | |
7071 | torch = torch + 1 -- increase torch spacing interval | |
7072 | numBlocks = numBlocks + 1 -- inrease block count | |
7073 | if deletesWater then -- up to and including mc 1.12.2 | |
7074 | T:forward(1) -- move forward to extend canal | |>| | |
7075 | _, isSource = T:isWater("down") -- check if source water below | |
7076 | if isSource then | |
7077 | sourceCount = sourceCount + 1 -- count source blocks | |
7078 | else | |
7079 | T:down(1) -- down to canal floor | |
7080 | sourceCount = 0 -- reset | |
7081 | T:go("C2", false, 0, false) -- place block below | |
7082 | T:up(1) -- up to water level | |
7083 | end -- still facing away from canal | |
7084 | if turtle.detectUp() then -- ? block above | |
7085 | T:go("U1x0") -- break block above | |
7086 | end | |
7087 | if not isSource or scoreCount == 0 then -- not source below, or first time found, ensures continous canal | |
7088 | T:go(R.side.."2x0") -- face back to existing canal | |
7089 | T:placeWater("down") -- place water | |
7090 | T:forward(1) -- forward 1 | |
7091 | T:placeWater("down") -- place water | |
7092 | utils.getWater() -- collects water from below | |
7093 | utils.goBack(1) -- back 1 | |
7094 | T:go(R.side.."2") -- face new canal | |
7095 | end | |
7096 | else | |
7097 | T:forward(1) -- move forward to extend canal | |
7098 | _, isSource = T:isWater("forward") -- check if source water ahead | |
7099 | if isSource then -- ? source ahead | |
7100 | - | T:place("minecraft:ladder", "forward", true) |
7100 | + | |
7101 | else | |
7102 | sourceCount = 0 | |
7103 | if not turtle.detectDown() then -- air / water below, but no source in front, so fill it | |
7104 | T:go(oTurn.."1D1") -- ready to repair neighbouring canal base | |
7105 | if T:getBlockType("forward"):find("turtle") ~= nil then -- turtle in similar position | |
7106 | if R.side == "L" then -- only left side repairs, so wait 1 second | |
7107 | sleep(1) | |
7108 | T:go("C1", false, 0, true) -- repair neighbouring canal base | |
7109 | end | |
7110 | T:go(R.side.."1") -- face forward | |
7111 | else | |
7112 | T:go("C1"..R.side.."1",false, 0, true) -- repair neighbouring canal base if air | |
7113 | end | |
7114 | T:up(1) | |
7115 | end | |
7116 | T:go("C2", false, 0, false) -- place block below if not already source | |
7117 | end | |
7118 | if not isSource then | |
7119 | T:go("U1x0D1") -- up 1 and excavate blocks above canal. return to canal base | |
7120 | end | |
7121 | - | T:place("trapdoor", "up", false) |
7121 | + | |
7122 | if not isSource and sourceCount == 0 then -- not source in front, or first time found, ensures continous canal | |
7123 | T:go("C1", false, 0, true) -- *| | | |>| face along new canal and block entrance | |
7124 | utils.goBack(1) -- *| | |>| | back 1 | |
7125 | T:placeWater("forward") -- *| | |>|W| place water | |
7126 | T:go(oTurn.."2") -- *| | |<|W| face existing canal | |
7127 | _, isSource = T:isWater("forward") -- *| |?|<|W| check if source water ahead | |
7128 | if not isSource then | |
7129 | if not T:placeWater("forward") then -- place water again *| |W|<|W| | |
7130 | while not T:getWater("forward") do -- wait for other turtle | |
7131 | - | Build steps up or down ready for railtrack |
7131 | + | |
7132 | - | R.depth = headroom, default 2 |
7132 | + | |
7133 | end | |
7134 | sleep(0.2) | |
7135 | T:placeWater("forward") | |
7136 | end | |
7137 | end | |
7138 | utils.getWater() -- collects 2 water *| |W|<|W| | |
7139 | T:go(R.side.."2F1") -- face along new canal *| |W|>|W| to *| |W|W|>| | |
7140 | end | |
7141 | end | |
7142 | end | |
7143 | end | |
7144 | ||
7145 | local maxLength = 512 | |
7146 | - | --T:go("U1x0 D1x1 F1x0x1 D1x1 C2", false, 0, false) |
7146 | + | |
7147 | - | T:go("U"..R.depth - 1 .."x0 D"..R.depth - 1 .."x1 F1x0x1 D1x1 C2", false, 0, false) |
7147 | + | |
7148 | end | |
7149 | menu.clear() | |
7150 | menu.colourWrite("Building canal "..R.side.." side", colors.yellow, nil, nil, false, true) | |
7151 | local moves = lib.initialiseCanal(R) -- move to correct position and/or start new canal | |
7152 | - | --T:go("C1U2 x0D1F1", false, 0, false) --put stone in front, up 2 excavate 1, down 1, forward 1 |
7152 | + | |
7153 | - | T:go("C1U"..R.depth.." x0D"..R.depth.."F1", false, 0, false) --put stone in front, up 2 (or headroom) excavate 1, down 1, forward 1 |
7153 | + | |
7154 | else -- 4 turtles | |
7155 | if R.subChoice == 1 or R.subChoice == 4 then -- towpath | |
7156 | lib.towpathOnly(R) | |
7157 | --lib.waterCanalTowpath(R, maxLength - moves) | |
7158 | else -- main canal only | |
7159 | lib.waterOnly(R, maxLength - moves) | |
7160 | end | |
7161 | end | |
7162 | ||
7163 | return {} | |
7164 | end | |
7165 | ||
7166 | local function createMobGrinder(R) | |
7167 | -- go down 5 and create a cavity 9 wide, 5 long, 8 high | |
7168 | -- assume facing out from spawner cube at base of exit (6 blocks above ground | |
7169 | -- R.subChoice = 1 or 2 (sticky or normal pistons) | |
7170 | ||
7171 | local lib = {} | |
7172 | ||
7173 | function lib.getInventory(R) | |
7174 | T:clear() | |
7175 | menu.colourPrint("All blocks to be ejected. Ready? Enter", colors.red) | |
7176 | read() | |
7177 | T:emptyInventory("up") | |
7178 | T:checkInventoryForItem({"stone"}, {20}, true, "Match existing walls?") | |
7179 | if R.subChoice == 1 then -- sticky pistons | |
7180 | T:checkInventoryForItem({"computercraft:computer_normal"}, {1}) | |
7181 | T:checkInventoryForItem({"minecraft:sticky_piston"}, {2}) | |
7182 | else | |
7183 | T:checkInventoryForItem({"computercraft:computer_normal"}, {2}) | |
7184 | T:checkInventoryForItem({"minecraft:piston"}, {4}) | |
7185 | T:checkInventoryForItem({"computercraft:cable"}, {6}) | |
7186 | T:checkInventoryForItem({"computercraft:wired_modem"}, {2}) | |
7187 | end | |
7188 | T:checkInventoryForItem({"polished"}, {23}, true, "Any polished block") | |
7189 | T:checkInventoryForItem({"wall"}, {2}, true, "Any wall block ? match") | |
7190 | T:checkInventoryForItem({"slab"}, {7}, true, "Any stone slab. ? polished / match") | |
7191 | T:checkInventoryForItem({"minecraft:glass"}, {2}) | |
7192 | T:checkInventoryForItem({"minecraft:stone_pressure_plate"}, {1}) | |
7193 | T:checkInventoryForItem({"minecraft:dispenser"}, {1}) | |
7194 | T:checkInventoryForItem({"hopper"}, {1}) | |
7195 | T:checkInventoryForItem({"chest"}, {2}) | |
7196 | T:checkInventoryForItem({"minecraft:redstone"}, {9}) | |
7197 | T:checkInventoryForItem({"lava"}, {1}) | |
7198 | R.useBlockType = T:getPolishedItem("") | |
7199 | if R.useBlockType == "" then | |
7200 | R.useBlockType = T:getMostItem("", true) | |
7201 | end | |
7202 | end | |
7203 | ||
7204 | function lib.placeRedstone() | |
7205 | T:go("D2U2") -- in left corner facing right | |
7206 | T:place("slab", 0, "down") -- place slab layer 1 | |
7207 | T:up(2) | |
7208 | T:place("slab", 0, "down") -- place slab layer 2 | |
7209 | T:up(1) | |
7210 | T:place("redstone", 0, "down") | |
7211 | T:go("F1D4 C2L1C1 L1U1", false, 0, false) -- facing ground level slab | |
7212 | T:place("redstone", 0, "forward") -- redstone on ground level slab | |
7213 | T:up(1) | |
7214 | T:place("slab", 0, "down") -- slab on layer 1 | |
7215 | T:up(2) | |
7216 | T:place("slab", 0, "down") -- slab on layer 3 | |
7217 | T:up(1) | |
7218 | T:place("redstone", 0, "down") -- redstone on layer 3 slab | |
7219 | utils.goBack(1) | |
7220 | T:down(3) -- facing layer 1 slab | |
7221 | T:place("redstone", 0, "forward") -- redstone on layer 1 slab | |
7222 | T:go("D2C2", false, 0, false) -- under end of chest position | |
7223 | T:place("redstone", 0, "forward") -- redstone on level 0 floor | |
7224 | T:go("R1C1R1", false, 0, false) -- face right, repair back wall | |
7225 | T:go("F1C2 L1C1 R1", false, 0, false) -- under chest start | |
7226 | T:go("F1C2 L1C1 R1", false, 0, false) -- under hopper | |
7227 | T:go("F1C2 L1C1 R1", false, 0, false) -- under right side wall block | |
7228 | T:go("U1L2") -- ready for redstone | |
7229 | for i = 1, 4 do | |
7230 | T:place("redstone", 0, "down") -- redstone under chest etc | |
7231 | if i < 4 then | |
7232 | T:forward(1) | |
7233 | end | |
7234 | end | |
7235 | -- finishes facing slab at ground level, redstone below | |
7236 | end | |
7237 | ||
7238 | function lib.placeStorage() | |
7239 | -- starts facing slab at ground level, redstone below | |
7240 | T:go("L1F1L2") -- up and out ready for chest placement | |
7241 | T:place("chest", 0, "forward") -- end chest | |
7242 | T:go("R1F1 L1F1 R1U2") -- at above start chest position facing right | |
7243 | T:place("slab", 0, "down") -- slab above chest | |
7244 | T:turnLeft(1) | |
7245 | utils.goBack(1) | |
7246 | T:down(2) -- in front of start chest position | |
7247 | T:place("chest", 0, "forward") -- start chest | |
7248 | T:go("R1F2L2") -- at pressure plate position facing left | |
7249 | T:place("wall", 0, "forward") -- place wall | |
7250 | T:up(1) | |
7251 | T:place("pressure", 0, "down") -- place pressure plate | |
7252 | T:go("R1F1 L1D1") -- at second wall position | |
7253 | T:place("hopper", 0, "forward") -- place hopper into chest | |
7254 | utils.goBack(1) | |
7255 | T:place("wall", 0, "forward") -- place second wall | |
7256 | -- finishes on level 1 (ground) facing right side wall block | |
7257 | end | |
7258 | ||
7259 | function lib.placePistons(R) | |
7260 | -- starts on level 1 (ground) facing right side wall block | |
7261 | T:go("U1F2 R1") -- go over wall block, facing back wall layer 2 | |
7262 | T:place(R.useBlockType, 0, "forward", false) -- replace back wall with polished block layer 2 | |
7263 | T:up(1) -- layer 3 | |
7264 | T:place(R.useBlockType, 0, "forward", false) -- replace back wall with polished block layer 3 | |
7265 | T:turnRight(1) -- face right side | |
7266 | if R.subChoice == 1 then -- use sticky pistons x 2 | |
7267 | T:place(R.useBlockType, 0, "forward", false)-- polished block above second wall layer 3 | |
7268 | T:go("R2F1") -- ready to place lower piston (works ok as slab already in place behind it) | |
7269 | else | |
7270 | T:go("F2R2") -- move forward 2 and face left | |
7271 | T:place("piston", 0, "forward") -- lower replacer piston placed | |
7272 | T:go("U1F2D1F1") -- go up and over piston forward 1 ready for other piston | |
7273 | end | |
7274 | T:place("piston", 0, "forward") -- lower piston placed | |
7275 | utils.goBack(1) | |
7276 | T:go("U1R1") -- layer 4 | |
7277 | T:place(R.useBlockType, 0, "forward", false) -- polished block back wall layer 4 | |
7278 | T:go("L1F2R2") -- head left ready for dispenser | |
7279 | T:place("dispenser", 0, "forward") -- dispenser placed | |
7280 | T:dropItem("lava", "forward") -- drop lava bucket into dispenser | |
7281 | T:go("U1F2 D1") -- up and over dispenser, facing right side | |
7282 | T:place("slab", 0, "down") -- lower piston slab placed | |
7283 | if R.subChoice == 1 then | |
7284 | T:place(R.useBlockType, 0, "forward", false)-- polished block above second wall layer 4 | |
7285 | T:turnLeft(1) -- facing back wall | |
7286 | else | |
7287 | T:go("F1L1") -- at second computer position, facing back wall | |
7288 | utils.goBack(1) -- ready to place computer | |
7289 | T:place("computercraft:computer_normal", 0, "forward", false) -- place computer | |
7290 | T:go("L1F1R1F1") -- facing back wall in mob drop, level 4 | |
7291 | end | |
7292 | T:place(R.useBlockType, 0, "forward", false) -- polished block back wall layer 4 | |
7293 | T:turnLeft(1) | |
7294 | T:go("U1F3R2") -- level 5 ready for upper piston | |
7295 | T:place("piston", 0, "forward") -- upper piston placed | |
7296 | T:go("U1F3D1R2") -- up and over piston, facing left, level 5 | |
7297 | T:turnRight(1) -- at mob drop, facing wall, level 5 | |
7298 | T:place(R.useBlockType, 0, "forward", false) -- polished block back wall layer 5 | |
7299 | T:turnRight(1) -- facing right side | |
7300 | if R.subChoice == 1 then | |
7301 | T:place(R.useBlockType, 0, "forward", false)-- right side polished block layer 5, facing right side, in mob drop -- layer 5 facing left side, in mob drop | |
7302 | else | |
7303 | T:go("F1C1") -- move forward, place temporary block | |
7304 | utils.goBack(1) | |
7305 | T:place("piston", 0, "forward") -- upper replacer piston placed | |
7306 | end | |
7307 | T:turnRight(2) | |
7308 | T:place("slab", 0, "forward") -- upper piston slab placed | |
7309 | T:turnLeft(1) -- facing away from back wall | |
7310 | end | |
7311 | ||
7312 | function lib.placeComputer(R) | |
7313 | -- starts facing away from back wall, layer 5, in mob drop | |
7314 | T:go("F1R1 F2R1 D1") -- move to left computerposition, facing back wall, layer 4 | |
7315 | T:place("computercraft:computer_normal", 0, "forward", false) -- place computer in gap, layer 4 | |
7316 | end | |
7317 | ||
7318 | function lib.placeColumnSection(direction) | |
7319 | T:place(R.useBlockType, 0, "forward", false) | |
7320 | T:go(direction.."1") | |
7321 | T:place(R.useBlockType, 0, "forward", false) | |
7322 | T:go(direction.."1") | |
7323 | T:place(R.useBlockType, 0, "forward", false) -- facing right | |
7324 | end | |
7325 | ||
7326 | function lib.placeColumns(R) | |
7327 | -- starts facing left computer, layer 4 | |
7328 | T:go("R1F2 L1") -- facing mob drop level 4 | |
7329 | T:place("glass", 0, "down", false) | |
7330 | T:up(1) -- facing mob drop level 5 | |
7331 | T:place("glass", 0, "down", false) -- on top of glass facing back wall at dungeon base level 5 | |
7332 | T:up(1) | |
7333 | T:place(R.useBlockType, 0, "down", false) -- level 6 dungeon exit | |
7334 | T:go("F1L1") | |
7335 | lib.placeColumnSection("L") -- facing right | |
7336 | T:up(1) | |
7337 | lib.placeColumnSection("R") -- facing left | |
7338 | T:up(1) | |
7339 | lib.placeColumnSection("L") -- facing right | |
7340 | T:up(1) | |
7341 | lib.placeColumnSection("R") -- facing left | |
7342 | T:up(1) | |
7343 | T:place(R.useBlockType, 0, "forward", false) | |
7344 | T:turnLeft(2) | |
7345 | T:place(R.useBlockType, 0, "forward", false) -- facing right | |
7346 | T:turnLeft(1) -- at top of column | |
7347 | T:go("x1D1 x1D1 x1U2") -- open exit for mobs | |
7348 | utils.goBack(2) | |
7349 | T:place(R.useBlockType, 0, "forward", false) | |
7350 | T:down(9) | |
7351 | end | |
7352 | ||
7353 | function lib.placeNetwork() | |
7354 | T:go("R1F2L1 F3U3 F1L1F1 L1x1") -- go behind second computer and remove block | |
7355 | T:place("computercraft:wired_modem", 0, "forward", false) -- place modem | |
7356 | utils.goBack(1) | |
7357 | T:place("computercraft:cable", 0, "forward", false) -- place network cable | |
7358 | T:place("computercraft:cable", 0, "forward", false) -- place network cable (no need to move) | |
7359 | T:go("R1F1 x2L1") -- move forward, face back wall | |
7360 | T:place("computercraft:cable", 0, "forward", false) | |
7361 | T:go("R1F1 x2L1") | |
7362 | T:place("computercraft:cable", 0, "forward", false) | |
7363 | T:go("R1F1 x2L1F1 x1x2") -- come behind left computer and expose back | |
7364 | T:place("computercraft:wired_modem", 0, "forward", false) -- place modem | |
7365 | utils.goBack(1) | |
7366 | T:place("computercraft:cable", 0, "forward", false) | |
7367 | T:place("computercraft:cable", 0, "forward", false) | |
7368 | T:go("L1D3 F4R1 F3U4 D4") -- removes temporary block | |
7369 | end | |
7370 | ||
7371 | local tempSubChoice = R.subChoice -- store for later use | |
7372 | R.width = 4 -- settings for createFloorCeiling() | |
7373 | R.length = 9 | |
7374 | R.height = 0 | |
7375 | R.up = true | |
7376 | T:turnRight(2) | |
7377 | local isWater, isSource, isIce, level, isAir = T:isWater("forward") | |
7378 | if not isWater then | |
7379 | T:turnRight(2) | |
7380 | return{"Not in correct position. Must be water behind"} | |
7381 | end | |
7382 | --T:go("U1x1 U1L1 F4R2") -- go up to starting point | |
7383 | T:go("U2L1 F4R2") -- go up to starting point | |
7384 | local data = createFloorCeiling(R)[1] -- place ceiling, returns to starting position. if water or lava present is returned as "water or lava found" | |
7385 | if data == "water or lava found" then | |
7386 | R.height = 10 | |
7387 | R.silent = true | |
7388 | T:up(1) | |
7389 | createSinkingPlatform(R) | |
7390 | T:go("F4L1 U5x1 U1x1 U3R1 F4C0 R1F3C0 R1F8C0 R1F3C0 R1D9") -- re-open exit hole, return to floor level | |
7391 | else -- no water or lava found so empty out area | |
7392 | R.height = 10 | |
7393 | R.subChoice = 2 | |
7394 | clearSolid(R) -- 76 | |
7395 | T:down(R.height - 1) | |
7396 | R.width = 4 -- settings for createFloorCeiling() | |
7397 | R.length = 9 | |
7398 | R.height = 0 | |
7399 | R.down = true | |
7400 | R.up = false | |
7401 | R.subChoice = 1 -- replace existing floor | |
7402 | createFloorCeiling(R) | |
7403 | end | |
7404 | ||
7405 | R.subChoice = tempSubChoice | |
7406 | lib.getInventory(R) | |
7407 | lib.placeRedstone() | |
7408 | lib.placeStorage() | |
7409 | lib.placePistons(R) | |
7410 | lib.placeComputer(R) -- ends facing computer | |
7411 | lib.placeColumns(R) | |
7412 | if R.subChoice == 2 then | |
7413 | lib.placeNetwork() | |
7414 | end | |
7415 | ||
7416 | return {} | |
7417 | end | |
7418 | ||
7419 | local function sandFillArea(R) -- 81 | |
7420 | --clearRectangle with sand drop | |
7421 | -- could be 1 wide x xx length (trench) up and return | |
7422 | -- could be 2+ x 2+ | |
7423 | -- even no of runs return after last run | |
7424 | -- odd no of runs forward, back, forward, reverse and return | |
7425 | local success | |
7426 | local directReturn = true | |
7427 | if R.width % 2 == 1 then | |
7428 | directReturn = false | |
7429 | end | |
7430 | if R.width == 1 then -- trench ahead, so fill then return | |
7431 | for i = 1, R.length - 1 do | |
7432 | success = utils.dropSand() | |
7433 | T:forward(1, false) | |
7434 | end | |
7435 | success = utils.dropSand() | |
7436 | T:go("R2F"..(R.length - 1).."R2", false, 0, false) | |
7437 | else --2 or more columns | |
7438 | if directReturn then -- R.width = 2,4,6,8 etc | |
7439 | for i = 1, R.width, 2 do -- i = 1,3,5,7 etc | |
7440 | -- move along R.length, dropping sand | |
7441 | for j = 1, R.length - 1 do | |
7442 | success = utils.dropSand() | |
7443 | T:forward(1, false) | |
7444 | end | |
7445 | success = utils.dropSand() | |
7446 | T:go("R1F1R1") --turn right and return on next column | |
7447 | for j = 1, R.length - 1 do | |
7448 | success = utils.dropSand() | |
7449 | T:forward(1, false) | |
7450 | end | |
7451 | success = utils.dropSand() | |
7452 | if i < R.width - 2 then -- eg R.width = 8, i compares with 6: 1, 3, 5, 7 | |
7453 | T:go("L1F1L1") | |
7454 | end | |
7455 | end | |
7456 | T:go("R1F"..R.width - 1 .."R1") --return home | |
7457 | else | |
7458 | for i = 1, R.width, 2 do -- i = 1,3,5,7 etc | |
7459 | -- move along R.length, dropping sand | |
7460 | for j = 1, R.length - 1 do | |
7461 | success = utils.dropSand() | |
7462 | T:forward(1, false) | |
7463 | end | |
7464 | success = utils.dropSand() | |
7465 | T:go("R1F1R1") --turn right and return on next column | |
7466 | for j = 1, R.length - 1 do | |
7467 | success = utils.dropSand() | |
7468 | T:forward(1, false) | |
7469 | end | |
7470 | success = utils.dropSand() | |
7471 | T:go("L1F1L1") | |
7472 | end | |
7473 | -- one more run then return | |
7474 | for j = 1, R.length - 1 do | |
7475 | success = utils.dropSand() | |
7476 | T:forward(1, false) | |
7477 | end | |
7478 | success = utils.dropSand() | |
7479 | T:go("R2F"..R.length.."R1F"..R.width - 1 .."R1") | |
7480 | end | |
7481 | end | |
7482 | return {} | |
7483 | end | |
7484 | ||
7485 | local function deactivateDragonTower() -- 45 | |
7486 | -- go up centre of tower to bedrock | |
7487 | local height = 0 | |
7488 | --numBlocksMoved, errorMsg = clsTurtle.doMoves(self, numBlocksRequested, direction) | |
7489 | local numBlocks, message = T:doMoves(1, "up") | |
7490 | while message == nil do | |
7491 | numBlocks, message = T:doMoves(1, "up") | |
7492 | height = height + 1 | |
7493 | end | |
7494 | -- go round bedrock and destroy crystal | |
7495 | T:go("F1R2U2x1U1x1") | |
7496 | -- return to start | |
7497 | T:down(height + 5) | |
7498 | return {} | |
7499 | end | |
7500 | ||
7501 | local function undermineDragonTowers() -- 44 | |
7502 | --[[ | |
7503 | -13, -40....12, -40 NNW (4) NNE (5) | |
7504 | ||
7505 | -34, -25............33, -25 NWW (2) NEE (9) | |
7506 | ||
7507 | -42, -1....................42, 0 W (1) E (8) | |
7508 | ||
7509 | -34, 24............33,24 SWW (3) SEE (10) | |
7510 | ||
7511 | -13,39....12, 39 SSW (7) SSE (6) | |
7512 | ||
7513 | North towers centres 25 blocks apart, 40 blocks north of axis | |
7514 | Mid-North towers 67 blocks apart, 25 blocks north of axis | |
7515 | W-E centres 84 blocks apart, on 0 axis | |
7516 | Mid-south towers 67 blocks apart, 24 blocks south of axis | |
7517 | South towers centres 25 blocks apart, 39 blocks south of axis | |
7518 | ]] | |
7519 | ||
7520 | local lib = {} | |
7521 | function lib.findNextTower(maxDistance, withMarker) | |
7522 | local distance = 0 | |
7523 | local blockTypeF = T:getBlockType("forward") | |
7524 | local blockTypeD = T:getBlockType("down") | |
7525 | for i = 1, maxDistance do | |
7526 | if blockTypeF ~= "minecraft:obsidian" and blockTypeD ~= "minecraft:obsidian" then -- not in a tower | |
7527 | if withMarker and blockTypeD ~= "minecraft:obsidian" then -- used to mark 0 coordinate | |
7528 | T:place("cobble", -1, "down", false) -- place cobblestone or cobbled deepslate to mark zero coordinate | |
7529 | end | |
7530 | else -- obsidian found, could still be in an earlier tower | |
7531 | if i > 10 then | |
7532 | break | |
7533 | end | |
7534 | end | |
7535 | T:go("F1x0") | |
7536 | distance = distance + 1 | |
7537 | blockTypeF = T:getBlockType("forward") | |
7538 | blockTypeD = T:getBlockType("down") | |
7539 | end | |
7540 | if distance == maxDistance then -- obsidian not found ? wrong place/ direction | |
7541 | print("Obsidian not found") | |
7542 | error() | |
7543 | end | |
7544 | -- will now be at side of a tower | |
7545 | lib.findCentre() -- move into tower to find the other side | |
7546 | return distance | |
7547 | end | |
7548 | ||
7549 | function lib.findCentre() | |
7550 | local width = 0 | |
7551 | - | T:place("slab", "down", false) |
7551 | + | |
7552 | local blockTypeF = T:getBlockType("forward") | |
7553 | local blockTypeD = T:getBlockType("down") | |
7554 | while blockTypeF == "minecraft:obsidian" or blockTypeD == "minecraft:obsidian" do | |
7555 | T:go("F1x0") | |
7556 | width = width + 1 | |
7557 | blockTypeF = T:getBlockType("forward") | |
7558 | blockTypeD = T:getBlockType("down") | |
7559 | end | |
7560 | -- will always go outside the tower 1 block. width of 5 block tower = 6 | |
7561 | T:go("R2F"..math.ceil(width / 2)) --return to centre of tower | |
7562 | T:turnLeft(1) -- now find another edge of the tower, dig forward until out of obsidian | |
7563 | for i = 1, math.ceil(width) do -- give additional loops if missed centre | |
7564 | blockTypeF = T:getBlockType("forward") | |
7565 | blockTypeD = T:getBlockType("down") | |
7566 | if blockTypeF == "minecraft:obsidian" or blockTypeD == "minecraft:obsidian" then | |
7567 | T:go("F1x0") | |
7568 | else | |
7569 | break | |
7570 | end | |
7571 | end | |
7572 | -- now outside different edge of the tower | |
7573 | -- reverse and move width/2, dig up + 1 to mark centre, face original direction | |
7574 | T:go("L2F"..math.ceil(width / 2).."R1U2x1") | |
7575 | T:place("minecraft:end_stone", -1, "forward", false) -- place endstone to mark facing direction | |
7576 | T:down(2) | |
7577 | end | |
7578 | ||
7579 | function lib.findPath(maxLength) | |
7580 | local blockTypeD = T:getBlockType("down") | |
7581 | local distance = 0 | |
7582 | while blockTypeD:find("cobble") == nil and distance < maxLength do | |
7583 | T:go("F1x0") -- return to 0 axis, | |
7584 | distance = distance + 1 | |
7585 | blockTypeD = T:getBlockType("down") | |
7586 | end | |
7587 | return distance | |
7588 | end | |
7589 | ||
7590 | -- start at 0,y,0, facing West | |
7591 | T:dig("up") -- in case not already done | |
7592 | local maxLength = 0 | |
7593 | local blockTypeD | |
7594 | local distance = lib.findNextTower(45, true)-- find W tower (1) and mark trail with cobble | |
7595 | T:turnRight(2) | |
7596 | for i = 1, 8 do -- head back East 8 blocks, turn left (facing north) | |
7597 | T:go("F1x0") -- this path may be off-axis, so dig double height | |
7598 | end | |
7599 | T:turnLeft(1) | |
7600 | lib.findNextTower(30) -- find NWW tower (2) | |
7601 | T:turnRight(2) | |
7602 | distance = lib.findPath(30) | |
7603 | distance = distance + lib.findNextTower(30) -- find SWW tower (3) | |
7604 | T:turnRight(2) | |
7605 | distance = lib.findPath(30) | |
7606 | T:turnRight(1) -- should be on cobble path | |
7607 | for i = 1, 21 do -- move East 21 blocks, turn left facing North | |
7608 | T:go("F1x0") | |
7609 | end | |
7610 | T:turnLeft(1) | |
7611 | ||
7612 | distance = lib.findNextTower(45) -- find NNW tower (4) | |
7613 | T:turnRight(1) | |
7614 | distance = lib.findNextTower(30) -- find NNE tower (5) | |
7615 | T:turnRight(1) | |
7616 | distance = lib.findNextTower(85) -- find SSE tower (6) | |
7617 | T:turnRight(1) | |
7618 | ||
7619 | distance = lib.findNextTower(30) -- find SSW tower (7) | |
7620 | T:turnRight(1) | |
7621 | distance = lib.findPath(40) -- head North to 0 axis | |
7622 | T:go("R1F13") -- return to 0,0 facing East | |
7623 | distance = lib.findNextTower(45, true) -- find E tower (8) | |
7624 | ||
7625 | T:turnRight(2) | |
7626 | for i = 1, 9 do | |
7627 | T:go("F1x0") -- this path may be off-axis, so dig double height | |
7628 | end | |
7629 | T:turnRight(1) | |
7630 | ||
7631 | distance = lib.findNextTower(30) -- find NEE tower (9) | |
7632 | T:turnRight(2) | |
7633 | distance = lib.findPath(30) -- return to 0 axis | |
7634 | distance = lib.findNextTower(30) -- find SEE tower (10) | |
7635 | T:turnRight(2) | |
7636 | distance = lib.findPath(30) -- return to 0 axis | |
7637 | T:go("L1F33") -- return to 0, 0 | |
7638 | ||
7639 | return {} | |
7640 | end | |
7641 | ||
7642 | local function demolishPortal(R) -- 43 | |
7643 | --[[ | |
7644 | R.length = length of portal NOT width default 4 | |
7645 | R.height = height of portal default 5 | |
7646 | R.width = thickness of portal default 1 | |
7647 | R.data = "bury" to embed bottom into ground | |
7648 | R.subChoice 1 = facing portal, 2 = aligned | |
7649 | ]] | |
7650 | local data = R.data | |
7651 | if R.subChoice == 1 then -- facing portal | |
7652 | T:go("F"..R.width.."R1") | |
7653 | else | |
7654 | T:forward(1) | |
7655 | end | |
7656 | if R.data == "bury" then | |
7657 | T:down(1) | |
7658 | end | |
7659 | ||
7660 | R.data = "up" | |
7661 | R.silent = true | |
7662 | if R.width == 1 then | |
7663 | clearWall(R) | |
7664 | else | |
7665 | clearBuilding(R, true, true) | |
7666 | end | |
7667 | if data == "bury" then | |
7668 | T:up(1) | |
7669 | end | |
7670 | if R.subChoice == 1 then -- facing portal | |
7671 | T:go("R1F1L1F1L1") | |
7672 | end | |
7673 | ||
7674 | return {} | |
7675 | end | |
7676 | ||
7677 | local function digTrench(R) -- 77 | |
7678 | local blockType | |
7679 | -- go down R.height, move forward | |
7680 | if R.length == 0 then | |
7681 | R.length = 4096 -- will go out of loaded chunks and stop or max 4096 on a server | |
7682 | end | |
7683 | for i = 1, R.length do | |
7684 | local count = 0 | |
7685 | for down = 1, R.height do | |
7686 | blockType = T:isWaterOrLava("down") | |
7687 | -- go down only if no water or lava below | |
7688 | if blockType:find("water") == nil and blockType:find("lava") == nil then | |
7689 | T:down(1) | |
7690 | count = count + 1 | |
7691 | end | |
7692 | end | |
7693 | T:go("C2", false, 0, true) -- if empty below fill void | |
7694 | T:go("U"..count) -- return to surface, continue if block above | |
7695 | while turtle.detect() do -- go up while block in front | |
7696 | blockType = T:getBlockType("forward") | |
7697 | if T:isVegetation(blockType) then | |
7698 | T:dig("forward") | |
7699 | break | |
7700 | elseif blockType:find("log") ~= nil then | |
7701 | T:harvestTree("forward", false) | |
7702 | else | |
7703 | T:up(1) | |
7704 | end | |
7705 | end | |
7706 | T:forward(1) -- move forward | |
7707 | while not turtle.detectDown() do -- go down until block detected | |
7708 | blockType = T:isWaterOrLava("down") | |
7709 | if blockType:find("water") == nil and blockType:find("lava") == nil then | |
7710 | T:down(1) | |
7711 | else | |
7712 | break | |
7713 | end | |
7714 | end | |
7715 | end | |
7716 | ||
7717 | return {} | |
7718 | end | |
7719 | ||
7720 | local function harvestTreeFarm(R) -- 24 | |
7721 | local lib = {} | |
7722 | ||
7723 | function lib.getLogCount() | |
7724 | local count = 0 | |
7725 | for i = 1,16 do | |
7726 | local item, itemCount = T:getSlotContains(i) | |
7727 | if item:find("log") ~= nil then | |
7728 | count = count + itemCount | |
7729 | end | |
7730 | end | |
7731 | ||
7732 | return count | |
7733 | end | |
7734 | ||
7735 | function lib.initialise() | |
7736 | local blockType = T:getBlockType("forward") | |
7737 | local logType = "" | |
7738 | local startHeight = 0 | |
7739 | local range = 0 | |
7740 | if blockType == "" then | |
7741 | while turtle.forward() do | |
7742 | range = range + 1 | |
7743 | if range == 3 then | |
7744 | break | |
7745 | end | |
7746 | end | |
7747 | end | |
7748 | blockType = T:getBlockType("forward") | |
7749 | if blockType:find("dirt") ~= nil then | |
7750 | T:up(1) | |
7751 | startHeight = 1 | |
7752 | else | |
7753 | if blockType:find("log") ~= nil or blockType:find("sapling") ~= nil then | |
7754 | logType = blockType | |
7755 | end | |
7756 | end | |
7757 | ||
7758 | return logType, startHeight | |
7759 | end | |
7760 | ||
7761 | R.silent = true | |
7762 | local treeType, startHeight = lib.initialise() -- possible ID tree type + move to correct position 1 above dirt | |
7763 | ||
7764 | T:forward(1) -- dig first log/sapling/ air if not planted | |
7765 | clearRectangle({width = 7, length = 7, up = true, down = true}) | |
7766 | T:go("L1F2L1F2R2") | |
7767 | local height = 0 | |
7768 | local pastLogCount = -1 | |
7769 | local currentLogCount = lib.getLogCount() | |
7770 | while currentLogCount ~= pastLogCount do | |
7771 | T:up(3) | |
7772 | height = height + 3 | |
7773 | pastLogCount = currentLogCount -- 0 when loop starts | |
7774 | clearRectangle({width = 12, length = 12, up = true, down = true}) | |
7775 | currentLogCount = lib.getLogCount() -- eg 20 logs from first round | |
7776 | end | |
7777 | T:down(height + startHeight) | |
7778 | T:go("R1F2R1F2R2") | |
7779 | ||
7780 | return {} | |
7781 | end | |
7782 | ||
7783 | local function harvestObsidian(R) -- 41 | |
7784 | local lib = {} | |
7785 | ||
7786 | function lib.forward(move) | |
7787 | T:isWaterOrLava("forward") -- automatically use lava ahead to refuel | |
7788 | T:isWaterOrLava("down") -- automatically use lava down to refuel | |
7789 | T:go("C2", false, 0, false) -- place / replace block below | |
7790 | if move then | |
7791 | T:forward(1) | |
7792 | end | |
7793 | end | |
7794 | ||
7795 | function lib.home(outward) | |
7796 | if outward then | |
7797 | T:go("L1F"..R.width - 1 .."L1F"..R.length - 1) | |
7798 | else | |
7799 | T:go("R1F"..R.width - 1 .."R1") | |
7800 | end | |
7801 | end | |
7802 | ||
7803 | function lib.start() | |
7804 | local lavaSlot = T:getItemSlot("lava") | |
7805 | if lavaSlot > 0 then | |
7806 | turtle.select(slot) | |
7807 | turtle.refuel() | |
7808 | end | |
7809 | T:down(1) | |
7810 | end | |
7811 | ||
7812 | local outward = true | |
7813 | ||
7814 | lib.start() -- use lava bucket if placed, move down into block below | |
7815 | for w = 1, R.width do | |
7816 | for l = 1, R.length do | |
7817 | if l < R.length then | |
7818 | lib.forward(true) | |
7819 | else | |
7820 | lib.forward(false) | |
7821 | end | |
7822 | end | |
7823 | if w < R.width then | |
7824 | if outward then | |
7825 | T:go("R1F1R1") | |
7826 | else | |
7827 | T:go("L1F1L1") | |
7828 | end | |
7829 | outward = not outward | |
7830 | end | |
7831 | end | |
7832 | ||
7833 | lib.home(outward) | |
7834 | ||
7835 | return {} | |
7836 | end | |
7837 | ||
7838 | local function harvestShulkers(R) | |
7839 | local lib = {} | |
7840 | ||
7841 | function lib.attackAll() | |
7842 | return turtle.attack(), turtle.attackUp(), turtle.attackDown() | |
7843 | end | |
7844 | ||
7845 | function lib.attack() | |
7846 | local forward, up, down = lib.attackAll() | |
7847 | while forward or up or down do | |
7848 | forward, up, down = lib.attackAll() | |
7849 | sleep(0.2) | |
7850 | end | |
7851 | end | |
7852 | ||
7853 | function lib.approach(direction, limit, dig) | |
7854 | -- move forward until stopped by shulker | |
7855 | limit = limit or 64 | |
7856 | dig = dig or false | |
7857 | local count = 0 | |
7858 | local solidDown = false | |
7859 | move = turtle.forward | |
7860 | if direction == "up" then | |
7861 | move = turtle.up | |
7862 | elseif direction == "down" then | |
7863 | move = turtle.down | |
7864 | end | |
7865 | local forward, up, down = lib.attackAll() | |
7866 | if forward or up or down then -- attacks suceeded | |
7867 | return true, 0, solidDown | |
7868 | else | |
7869 | while move() do | |
7870 | count = count + 1 | |
7871 | if turtle.detectDown() then | |
7872 | solidDown = true | |
7873 | end | |
7874 | if count >= limit then | |
7875 | return false, count, solidDown | |
7876 | end | |
7877 | forward, up, down = lib.attackAll() | |
7878 | if forward or up or down then | |
7879 | return true, count, solidDown | |
7880 | else | |
7881 | if dig then | |
7882 | T:dig("forward") | |
7883 | end | |
7884 | end | |
7885 | end | |
7886 | return false, count, solidDown | |
7887 | end | |
7888 | end | |
7889 | ||
7890 | function lib.home(direction, moves) | |
7891 | local move = turtle.back | |
7892 | if direction == "up" then | |
7893 | move = turtle.down | |
7894 | elseif direction == "down" then | |
7895 | move = turtle.up | |
7896 | end | |
7897 | for i = 1, moves do | |
7898 | move() | |
7899 | end | |
7900 | end | |
7901 | ||
7902 | function lib.checkPosition() | |
7903 | if T:detect("forward") then -- wall in front | |
7904 | T:turnRight(1) | |
7905 | if T:detect("forward") then -- wall to right | |
7906 | T:turnLeft(1) | |
7907 | return true -- position corrected | |
7908 | else | |
7909 | T:turnLeft(2) | |
7910 | if T:detect("forward") then -- wall in front. position correct | |
7911 | return true | |
7912 | end | |
7913 | end | |
7914 | end | |
7915 | return false | |
7916 | end | |
7917 | ||
7918 | function lib.getLength() | |
7919 | local count = 0 | |
7920 | while turtle.detectDown() do | |
7921 | count = count + 1 | |
7922 | T:forward(1) | |
7923 | end | |
7924 | utils.goBack(1) | |
7925 | return count | |
7926 | end | |
7927 | ||
7928 | function lib.clearWall() | |
7929 | local distance = 0 | |
7930 | while distance < 9 do -- smallest external walls are 8 x 8 | |
7931 | local success, count = lib.approach("forward", 8 - distance) | |
7932 | if success then | |
7933 | - | --T:place("stone", "forward", false) -- place does not allow for specific blocktype |
7933 | + | |
7934 | end | |
7935 | distance = distance + count | |
7936 | end | |
7937 | T:turnLeft(1) | |
7938 | if T:detect("forward") then -- larger than 8 blocks | |
7939 | T:turnRight(1) | |
7940 | while distance < 14 do -- larger builds are 14 x 14 | |
7941 | local success, count = lib.approach("forward", 13 - distance) | |
7942 | if success then | |
7943 | lib.attack() | |
7944 | end | |
7945 | distance = distance + count | |
7946 | end | |
7947 | T:go("L1x2") | |
7948 | end | |
7949 | end | |
7950 | ||
7951 | function lib.roof() | |
7952 | -- check position | |
7953 | local doContinue = lib.checkPosition() | |
7954 | ||
7955 | if doContinue then | |
7956 | T:go("U2F3 R1F3 R1") | |
7957 | local length = lib.getLength() | |
7958 | local width = 1 | |
7959 | local outward = lib.turnRound(true) | |
7960 | local success, count, onRoof = false, 0, true | |
7961 | while onRoof do | |
7962 | local distance = 0 | |
7963 | while distance < length - 1 do | |
7964 | success, count, onRoof = lib.approach("forward", length - 1 - distance) | |
7965 | if success then | |
7966 | lib.attack() | |
7967 | end | |
7968 | if count == 0 then | |
7969 | turtle.dig() | |
7970 | end | |
7971 | distance = distance + count | |
7972 | end | |
7973 | width = width + 1 | |
7974 | - | T:place("minecraft:torch", "down") |
7974 | + | |
7975 | end | |
7976 | if outward then | |
7977 | T:go("F".. 3 .."L1F"..width - 3 .."D2L1") | |
7978 | else | |
7979 | T:go("F".. length - 3 .."R1F"..width - 3 .."D2L1") | |
7980 | end | |
7981 | return {} | |
7982 | else | |
7983 | return {"Turtle not in front of a wall"} | |
7984 | end | |
7985 | end | |
7986 | ||
7987 | function lib.turnRound(outward) | |
7988 | if outward then | |
7989 | T:go("R1F1R1") | |
7990 | else | |
7991 | T:go("L1F1L1") | |
7992 | end | |
7993 | return not outward | |
7994 | end | |
7995 | ||
7996 | function lib.upAndOver() | |
7997 | local start, height, forward = 0, 0, 0 | |
7998 | while turtle.detect() do | |
7999 | turtle.up() | |
8000 | start = start + 1 | |
8001 | end | |
8002 | while turtle.forward() do | |
8003 | forward = forward + 1 | |
8004 | end | |
8005 | turtle.turnRight() | |
8006 | - | function lib.buildWallSection(section, useBlockType) |
8006 | + | |
8007 | - | -- build a layer 1 block high below turtle |
8007 | + | |
8008 | - | for i = 1, #section do |
8008 | + | |
8009 | - | local block = section:sub(i, i) |
8009 | + | |
8010 | - | if block == "l" then |
8010 | + | |
8011 | - | T:place("log", "down") |
8011 | + | |
8012 | - | elseif block == "m" then |
8012 | + | |
8013 | - | T:place("modem", "down") |
8013 | + | |
8014 | - | elseif block == "b" then |
8014 | + | |
8015 | - | T:place("barrel", "down") |
8015 | + | |
8016 | - | elseif block == "c" then |
8016 | + | |
8017 | - | T:place("cable", "down") |
8017 | + | |
8018 | end | |
8019 | - | T:place(useBlockType, "down") |
8019 | + | |
8020 | for i = 1, forward do | |
8021 | - | if i < #section then |
8021 | + | |
8022 | end | |
8023 | for i = 1, start do | |
8024 | turtle.down() | |
8025 | end | |
8026 | T:turnRight(2) | |
8027 | end | |
8028 | ||
8029 | - | while turtle.digUp() do end |
8029 | + | |
8030 | - | turtle.digDown() |
8030 | + | |
8031 | - | T:place(useBlockType, "down") |
8031 | + | |
8032 | - | --T:go("x0C2", false, 0, false, useBlockType) |
8032 | + | |
8033 | for i = 1, 4 do | |
8034 | - | while not turtle.forward() do |
8034 | + | |
8035 | - | turtle.dig() |
8035 | + | |
8036 | T:go("F2L1 U1F2 R2") | |
8037 | - | --T:forward(1) |
8037 | + | |
8038 | return {"Turtle not in front of a wall"} | |
8039 | end | |
8040 | end | |
8041 | ||
8042 | local direction = "forward" | |
8043 | local doContinue = false | |
8044 | ||
8045 | if R.subChoice == 1 then -- Shulker is above | |
8046 | direction = "up" | |
8047 | doContinue = true | |
8048 | elseif R.subChoice == 2 then -- Shulker is ahead | |
8049 | doContinue = true | |
8050 | elseif R.subChoice == 3 then -- Shulker is below | |
8051 | direction = "down" | |
8052 | doContinue = true | |
8053 | else | |
8054 | if R.subChoice == 4 then -- Climb tower wall | |
8055 | lib.upAndOver() | |
8056 | elseif R.subChoice == 5 then -- Clear roof above | |
8057 | return lib.roof() | |
8058 | elseif R.subChoice == 6 then -- Clear outside walls | |
8059 | lib.walls() | |
8060 | end | |
8061 | ||
8062 | end | |
8063 | if doContinue then | |
8064 | local success, moves = lib.approach(direction, 64) | |
8065 | if success then | |
8066 | lib.attack() | |
8067 | end | |
8068 | lib.home(direction, moves) | |
8069 | end | |
8070 | - | function lib.findLegacyStart() |
8070 | + | |
8071 | return {} | |
8072 | - | local block = T:getBlockType("down") |
8072 | + | |
8073 | - | if block:find("polished") ~= nil then |
8073 | + | |
8074 | - | return "" -- in correct position, facing centre of front wall |
8074 | + | |
8075 | local lib = {} | |
8076 | - | -- assume on left corner |
8076 | + | |
8077 | - | T:forward (1) |
8077 | + | function lib.checkEquipment() |
8078 | - | local couint = 0 |
8078 | + | --[[ Needs pickaxe and hoe equipped ]] |
8079 | - | while (T:getBlockType("down")):find("polished") == nil do |
8079 | + | |
8080 | --T:checkInventoryForItem(items{}, quantities{}, required, message) | |
8081 | print("Checking equipment. Please wait...") | |
8082 | - | if count > 10 then |
8082 | + | local equippedRight, equippedLeft, inInventory = T:setEquipment() -- any tools equipped except diamond_pickaxe and crafting_table have been removed to inventory |
8083 | - | return "Unable to locate polished block" |
8083 | + | --[[if equippedRight ~= "minecraft:crafting_table" then |
8084 | T:checkInventoryForItem({"minecraft:crafting_table"}, {1}) | |
8085 | local equippedRight, equippedLeft = T:setEquipment() | |
8086 | end]] | |
8087 | T:suck("down") -- if hoe already in storage get it out | |
8088 | if inInventory ~= "minecraft:diamond_hoe" then | |
8089 | - | function lib.floodFarm(R) |
8089 | + | if T:getItemSlot("minecraft:diamond_hoe") > 0 then |
8090 | return true | |
8091 | - | T:sortInventory(false) |
8091 | + | |
8092 | - | for i = 1, R.width - 2 do |
8092 | + | T:checkInventoryForItem({"minecraft:diamond_hoe"}, {1}, true, "Diamond Hoe required for planting!") |
8093 | - | lib.placeFloor(R.length - 2, R.useBlockType) |
8093 | + | |
8094 | - | if i < R.width - 2 then |
8094 | + | |
8095 | - | outward = lib.turn(outward) |
8095 | + | if T:getItemSlot("minecraft:diamond_hoe") > 0 then |
8096 | return true | |
8097 | end | |
8098 | - | T:go("U1R2") -- over 13 x 13 internal area opposite corner |
8098 | + | |
8099 | - | -- now add corners |
8099 | + | |
8100 | - | lib.placeCorners(R.length - 2, 4, R.useBlockType) |
8100 | + | |
8101 | - | outward = lib.turn(outward) |
8101 | + | |
8102 | - | lib.placeCorners(R.length - 2, 3, R.useBlockType) |
8102 | + | |
8103 | - | outward = lib.turn(outward) |
8103 | + | --[[ first function called on start]] |
8104 | - | lib.placeCorners(R.length - 2, 2, R.useBlockType) |
8104 | + | local atHome = false |
8105 | - | outward = lib.turn(outward) |
8105 | + | |
8106 | - | lib.placeCorners(R.length - 2, 1, R.useBlockType) |
8106 | + | print("Checking position "..blockType.. " below") |
8107 | if blockType:find("water") ~= nil then -- over water | |
8108 | - | T:go("R1F"..R.width - 9 .."R1") |
8108 | + | if lib.isStorage("forward") then |
8109 | atHome = true | |
8110 | - | T:go("L1F"..R.width - 9 .."L1") |
8110 | + | |
8111 | if lib.isStorage("forward") then-- confirms in correct position, back to crops | |
8112 | T:turnRight(2) | |
8113 | - | lib.placeCorners(R.length - 2, 1, R.useBlockType) |
8113 | + | else -- facing crafting table |
8114 | - | outward = lib.turn(outward) |
8114 | + | |
8115 | - | lib.placeCorners(R.length - 2, 2, R.useBlockType) |
8115 | + | |
8116 | - | outward = lib.turn(outward) |
8116 | + | else -- not a chest: facing crops or crafting table |
8117 | - | lib.placeCorners(R.length - 2, 3, R.useBlockType) |
8117 | + | |
8118 | - | outward = lib.turn(outward) |
8118 | + | if lib.isStorage("forward") then -- confirms was facing crops |
8119 | - | lib.placeCorners(R.length - 2, 4, R.useBlockType) -- should be back in starting corner facing front |
8119 | + | atHome = true |
8120 | T:turnLeft(1) | |
8121 | - | T:go("U1R1") |
8121 | + | |
8122 | - | lib.placeWater(R.length - 3) -- place water down then move forward, turn right |
8122 | + | |
8123 | - | lib.placeWater(R.width - 3) |
8123 | + | -- should now be facing crops. may be crafting table to left |
8124 | - | lib.placeWater(R.length - 3) |
8124 | + | |
8125 | - | lib.placeWater(R.width - 3) |
8125 | + | return atHome-- now facing crops |
8126 | - | T:go("F".. math.floor((R.length - 2) / 2).."R1F".. math.floor((R.width - 2) / 2)) -- should be in centre |
8126 | + | |
8127 | ||
8128 | - | --T:go("D6x2 F1x2 F1x2 F1x2 F1x2 F1x2 F1x2 F1x2 F1x2 F1x2 R1F7 R1U1") |
8128 | + | function lib.crossFarm() |
8129 | - | T:go("D6F7 R1F7 R1U1") -- end facing back at left corner, 1 block above floor/1 below ceiling |
8129 | + | |
8130 | local blockType = "" | |
8131 | local isReady, cropType, status = lib.isCropReady("down") | |
8132 | - | function lib.clearBasement() |
8132 | + | -- will go forward until chest or cobble detected below |
8133 | - | T:sortInventory(false) |
8133 | + | |
8134 | - | T:dropItem("seeds", "forward") |
8134 | + | |
8135 | - | T:dropItem("flint", "forward") |
8135 | + | |
8136 | - | clearRectangle({width = 15, length = 15, up = true, down = true}) |
8136 | + | |
8137 | - | -- area has been cleared. starts facing back, 1 block above ground, 1 block below ceiling |
8137 | + | blockType = T:getBlockType("down", -1) |
8138 | if blockType == "" or cropType ~= "" then --crops or nothing below | |
8139 | - | for i = 1, 14 do -- place cable into gutter beneath front of farm |
8139 | + | |
8140 | - | T:place("cable", "up") |
8140 | + | elseif blockType:find("barrel") ~= nil or blockType:find("chest") ~= nil or blockType:find("cobble") ~= nil then |
8141 | - | if i < 14 then |
8141 | + | |
8142 | end | |
8143 | numMoves = numMoves + 1 | |
8144 | end | |
8145 | - | -- ends right side facing right, just below ceiling |
8145 | + | return blockType -- either chest or cobble |
8146 | end | |
8147 | ||
8148 | function lib.farmInFront() | |
8149 | --[[ facing crops on first farm. move to next farm in front ]] | |
8150 | T:go("U1L1F11D1R1") -- on next farm, facing crops | |
8151 | - | -- R.data = "new", "left", "right" or "back" to extend tree farm |
8151 | + | local crop = lib.manageTree() -- refuel, gather seeds and other crops |
8152 | local isFarmToRight, _ = lib.harvest(crop) -- harvest field, store crops | |
8153 | - | -- R.networkFarm to create storage area |
8153 | + | return isFarmToRight |
8154 | end | |
8155 | ||
8156 | function lib.farmToRight() | |
8157 | - | -- R.data = "new", "left", "right", "back", "convertStorage", "convert" |
8157 | + | |
8158 | - | if R.data == "new" then -- new treeFarm, Start at current position |
8158 | + | T:go("U1F11 D1") -- on next farm, facing crops |
8159 | - | -- build 4 wall sections in 2 passes |
8159 | + | local crop = lib.manageTree() -- refuel, gather seeds and other crops |
8160 | lib.harvest(crop) -- harvest field, store crops | |
8161 | - | lib.buildWallSection("---------------", R.useBlockType) -- left wall (15 blocks) |
8161 | + | |
8162 | - | T:go("R1F1") |
8162 | + | |
8163 | function lib.getCrops() | |
8164 | - | lib.buildWallSection("--------------", R.useBlockType) -- back/ right wall (14 blocks) |
8164 | + | |
8165 | ||
8166 | if lib.isStorage("forward") then | |
8167 | - | lib.buildWallSection("------c------", R.useBlockType) -- front wall (14 blocks) c = network cable |
8167 | + | lib.getSeeds("forward") |
8168 | end | |
8169 | - | lib.buildWallSection("---------------", R.useBlockType) -- left wall top (15 blocks) |
8169 | + | |
8170 | - | T:go("R1F1") |
8170 | + | if lib.isStorage("forward") then |
8171 | lib.getVeg("forward") | |
8172 | - | lib.buildWallSection("--------------", R.useBlockType) --back/right wall (14 blocks) |
8172 | + | |
8173 | T:turnRight(2) | |
8174 | end | |
8175 | - | --lib.buildWallSection("-----lmb-----", R.useBlockType) --front wall (14 blocks) log/modem/barrel |
8175 | + | |
8176 | - | lib.buildWallSection("-----lmb", R.useBlockType) |
8176 | + | function lib.getSaplings(direction) |
8177 | --[[ get a single sapling from the chest ]] | |
8178 | - | network.attachModem() |
8178 | + | |
8179 | direction = "forward" | |
8180 | - | lib.buildWallSection("-----", R.useBlockType) |
8180 | + | |
8181 | - | T:go("R1F1 D2") -- over 13 x 13 internal area |
8181 | + | while T:suck(direction, 1) do end -- remove saplings/ seeds |
8182 | - | elseif R.data == "left" or R.data == "right" or R.data == "back" then |
8182 | + | |
8183 | - | -- build 3 wall sections in 2 passes |
8183 | + | T:dropItem("sapling", direction, 1) -- drop all but 1 saplings |
8184 | - | if R.data == "left" then -- should be on left corner of existing |
8184 | + | if not T:dropItem("seeds", direction, 0) then-- drop all seeds |
8185 | - | T:go("L1F1 D1") -- move left 1 blocks, down 1: <- |
8185 | + | T:dropItem("seeds", "up", 0) |
8186 | - | lib.buildWallSection("------c-------", R.useBlockType) -- front wall (14 blocks) c = network cable <- |
8186 | + | |
8187 | ||
8188 | - | lib.buildWallSection("--------------", R.useBlockType) -- left wall (14 blocks) ^ |
8188 | + | return T:getItemSlot("sapling", -1) |
8189 | end | |
8190 | - | lib.buildWallSection("-------------", R.useBlockType) -- back wall (13 blocks) -> |
8190 | + | |
8191 | - | T:go("U1R2") -- turn round ready to add next layer <- |
8191 | + | function lib.getSeeds(direction) |
8192 | - | lib.buildWallSection("--------------", R.useBlockType) -- back wall top (14 blocks) <- |
8192 | + | --[[ get 1 stack of wheat seeds or 1 stack of beetroot seeds ]] |
8193 | print("Collecting seeds from storage") | |
8194 | - | lib.buildWallSection("--------------", R.useBlockType) -- left wall top (14 blocks) v |
8194 | + | while T:suck(direction, 1) do end -- remove saplings/ seeds |
8195 | T:dropItem("sapling", direction, 0) -- drop all saplings | |
8196 | - | lib.buildWallSection("-----bm", R.useBlockType) -- front wall (7 blocks) barrel/modem -> |
8196 | + | T:dropItem("minecraft:wheat_seeds", direction, 64) -- drop all but 64 seeds |
8197 | - | network.attachModem() |
8197 | + | T:dropItem("minecraft:beetroot_seeds", direction, 64) |
8198 | local crop = "" | |
8199 | - | lib.buildWallSection("l-----", R.useBlockType) -- front wall (5 blocks) log -> |
8199 | + | if T:getItemSlot("minecraft:wheat_seeds", -1) > 0 then |
8200 | - | T:go("R2F12 R1F1 D2") -- over 13 x 13 internal area lower left side |
8200 | + | crop = "wheat" |
8201 | - | elseif R.data == "right" then -- should be on right corner of existing |
8201 | + | print("Field crop = "..crop) |
8202 | - | T:go("R1F1 D1") -- move right, forward, down 1 |
8202 | + | elseif T:getItemSlot("minecraft:beetroot_seeds", -1) > 0 then |
8203 | - | lib.buildWallSection("------c-------", R.useBlockType) -- front wall (14 blocks) c = network cable |
8203 | + | crop = "beetroot" |
8204 | print("Field crop = "..crop) | |
8205 | - | lib.buildWallSection("--------------", R.useBlockType) -- right wall (14 blocks) |
8205 | + | |
8206 | ||
8207 | - | lib.buildWallSection("-------------", R.useBlockType) -- back wall (13 blocks) |
8207 | + | return crop |
8208 | - | T:go("U1R2") -- turn round ready to add next layer |
8208 | + | |
8209 | - | lib.buildWallSection("--------------", R.useBlockType) -- back wall top (14 blocks) |
8209 | + | |
8210 | function lib.getVeg(direction) | |
8211 | - | lib.buildWallSection("--------------", R.useBlockType) -- left wall top (14 blocks) |
8211 | + | |
8212 | print("Collecting crops from storage") | |
8213 | - | lib.buildWallSection("-----lmb", R.useBlockType) |
8213 | + | |
8214 | while T:suck(direction, 1) do end -- remove carrots / potatoes / wheat / beetroot | |
8215 | - | network.attachModem() |
8215 | + | --clsTurtle.dropItem(self, item, direction, keepAmount) |
8216 | - | T:forward(2) |
8216 | + | T:dropItem("wheat", direction, 0) -- drop all wheat |
8217 | - | lib.buildWallSection("-----", R.useBlockType) |
8217 | + | T:dropItem("beetroot", direction, 0) -- drop all beetroot |
8218 | - | T:go("R1F1 D2") -- over 13 x 13 internal area |
8218 | + | T:dropItem("carrot", direction, 64) -- drop all but 64 carrots |
8219 | - | elseif R.data == "back" then -- should be on left front corner of existing |
8219 | + | T:dropItem("potato", direction, 64) -- drop all but 64 potato |
8220 | - | T:go("R2F1 D4R2 F1") -- move forward 14 blocks, down 1 |
8220 | + | local crop = "" |
8221 | - | for i = 1, 15 do |
8221 | + | if T:getItemSlot("potato", -1) > 0 then |
8222 | - | T:place("cable", "up") |
8222 | + | crop = "potato" |
8223 | print("Field crop = "..crop) | |
8224 | elseif T:getItemSlot("carrot", -1) > 0 then | |
8225 | crop = "carrot" | |
8226 | - | if T:getBlockType("up") == R.useBlockType then -- already a farm on left side |
8226 | + | print("Field crop = "..crop) |
8227 | - | T:go("U2C2 U1C2 F13R1 F1D1", false, 0, false, R.useBlockType) |
8227 | + | |
8228 | - | lib.buildWallSection("--------------", R.useBlockType) -- back wall (14 blocks) |
8228 | + | |
8229 | --T:turnRight(2) -- face crops | |
8230 | return crop | |
8231 | end | |
8232 | - | lib.buildWallSection("--------------", R.useBlockType) -- left wall (14 blocks) |
8232 | + | |
8233 | function lib.goHome() | |
8234 | - | lib.buildWallSection("--------------", R.useBlockType) -- back wall (14 blocks) |
8234 | + | |
8235 | local onTree = false | |
8236 | -- is tree above or in front | |
8237 | -- check if log in front | |
8238 | - | lib.buildWallSection("-------------", R.useBlockType) --right wall (13 blocks) no special blocks |
8238 | + | |
8239 | - | T:go("U1R2") -- turn round ready to add next layer |
8239 | + | lib.harvestTree("forward") -- will only harvest if fuel below half of limit |
8240 | - | for i = 1, 2 do |
8240 | + | |
8241 | - | lib.buildWallSection("--------------", R.useBlockType) --right wall top (14 blocks) no special blocks |
8241 | + | |
8242 | - | T:go("L1F1") |
8242 | + | lib.harvestTree("up") |
8243 | onTree = true | |
8244 | - | lib.buildWallSection("-------------", R.useBlockType) -- left wall top (13 blocks) no special blocks |
8244 | + | elseif T:getItemSlot("log", -1) > 0 then -- tree just harvested |
8245 | - | T:go("F1L1 F7x2") |
8245 | + | |
8246 | - | T:go("D1x2") |
8246 | + | |
8247 | - | T:place("cable", "down") |
8247 | + | |
8248 | lib.harvestTree("up") | |
8249 | - | T:place("modem", "down") |
8249 | + | |
8250 | - | T:go("F1R2x2") |
8250 | + | while turtle.down() do end |
8251 | - | T:place("log", "down") |
8251 | + | |
8252 | - | T:go("F2x2") |
8252 | + | |
8253 | - | T:place("barrel", "down") |
8253 | + | |
8254 | if onTree then -- tree harvested, but direction unknown | |
8255 | - | network.attachModem() |
8255 | + | |
8256 | - | T:go("F6R1 F1D2") |
8256 | + | local turns = 0 |
8257 | local onChest = lib.isStorage("down") | |
8258 | - | else -- convertStorage or convert |
8258 | + | while not onChest do |
8259 | - | -- legacy farm had polished block on positions 4 / (10) from left corner |
8259 | + | |
8260 | - | local message = lib.findLegacyStart() |
8260 | + | if lib.isStorage("down") then |
8261 | - | if message ~= "" then |
8261 | + | onChest = true |
8262 | - | return {message} |
8262 | + | |
8263 | - | end |
8263 | + | turtle.back() |
8264 | - | -- now on top of polished block, 4 from left corner, facing Centre |
8264 | + | |
8265 | - | T:forward(2) |
8265 | + | |
8266 | - | T:place("barrel", "down") |
8266 | + | if not onChest then |
8267 | - | T:go("F1D1") |
8267 | + | |
8268 | - | T:place("cable", "down") |
8268 | + | turns = turns + 1 |
8269 | - | T:up(1) |
8269 | + | |
8270 | - | T:place("modem", "down") |
8270 | + | if turns == 4 then |
8271 | - | network.attachModem() |
8271 | + | |
8272 | - | T:forward(1) |
8272 | + | |
8273 | - | T:place("log", "down") |
8273 | + | end -- should be on chest. If not should be over water |
8274 | - | T:go("R1F1 R1F1 D5R1 F1L1 F7R1")-- left corner, facing back ready to clear basement |
8274 | + | if onChest then -- onChest and onTree, go left,down |
8275 | T:go("R1F1D1R1") | |
8276 | - | if (R.data):find("convert") == nil then |
8276 | + | |
8277 | - | lib.floodFarm(R) |
8277 | + | atHome = lib.checkPosition() |
8278 | if atHome then | |
8279 | - | lib.clearBasement() -- area has been cleared. ends right side facing right, just below ceiling |
8279 | + | return true -- exit function |
8280 | end | |
8281 | - | if R.data == "back" then |
8281 | + | |
8282 | - | T:go("R2F6 R1D1") |
8282 | + | |
8283 | end | |
8284 | - | T:go("R2F6 L1F1 U4D5 R2F1") -- make exit for player. end mid floor/ceiling height, facing back, in centre |
8284 | + | |
8285 | return false | |
8286 | - | if R.data == "new" or R.data == "convertStorage" then -- put storage in this farm |
8286 | + | |
8287 | ||
8288 | - | T:place("cable", "up") |
8288 | + | function lib.gotoTree(logSlot) |
8289 | -- assume facing crops | |
8290 | T:turnRight(1) | |
8291 | - | T:place("cable", "up") |
8291 | + | print("Extracting saplings from storage") |
8292 | lib.getSaplings("forward") -- gets one sapling only (if present) | |
8293 | - | utils.createStorage() -- creates on ground, 1 below current |
8293 | + | print("Moving to tree position") |
8294 | T:go("U1F1R1") | |
8295 | - | T:place("cable", "forward") |
8295 | + | lib.harvestTree("forward") -- fell tree or plant sapling, ends facing tree / dirt / sapling. sticks already used for fuel. excess saplings placed |
8296 | ||
8297 | if logSlot == 0 then -- no logs passed as parameter | |
8298 | - | T:place("cable", "up") |
8298 | + | logSlot = T:getItemSlot("log") |
8299 | end | |
8300 | T:go("R1F1D1") -- return to base, facing buried storage | |
8301 | if logSlot == 0 then -- has logs so needs to craft and refuel | |
8302 | - | for i = 1, 6 do |
8302 | + | T:turnRight(1) -- facing crops |
8303 | - | T:place("cable", "up") |
8303 | + | |
8304 | ||
8305 | return logSlot | |
8306 | end | |
8307 | - | T:place("modem", "up") |
8307 | + | |
8308 | - | T:go("F1R2U2") |
8308 | + | function lib.harvest(crop) |
8309 | - | T:place("barrel", "down") |
8309 | + | |
8310 | - | T:drop("down", "dirt", 64)-- override 'slot' with item string |
8310 | + | |
8311 | - | T:up(1) |
8311 | + | harvest crops if ripe |
8312 | - | T:place("hopper", "down") |
8312 | + | |
8313 | place seeds / harvest in chests | |
8314 | - | network.attachModem() |
8314 | + | |
8315 | - | T:go("U1C2 U2F6 R2") |
8315 | + | |
8316 | - | --network.attachModem() |
8316 | + | |
8317 | local isFarmToRight = false | |
8318 | local isFarmToFront = false | |
8319 | local width = 9 | |
8320 | local length = 10 | |
8321 | local toRight = true | |
8322 | for l = 1, length do | |
8323 | for w = 1, width do | |
8324 | isReady, blockType, _ = lib.isCropReady("down") -- eg true, "minecraft:carrots", "7 / 7" or false, "", "" | |
8325 | turtle.select(1) | |
8326 | if blockType == "" then -- air (above water, storage or dirt) | |
8327 | --turtle.digDown("left") -- use pickaxe | |
8328 | - | T:place("barrel", "down", false) |
8328 | + | turtle.digDown("right") -- use hoe |
8329 | lib.plantCrop(crop, "down") -- plant crop | |
8330 | elseif isReady then -- crop below is ready | |
8331 | turtle.digDown("left") -- use pickaxe | |
8332 | lib.plantCrop(blockType, "down") -- plant crop | |
8333 | end | |
8334 | T:forward(1) | |
8335 | if l == 1 and w == width then -- last block of first row at front of farm | |
8336 | T:forward(1) | |
8337 | if lib.isStorage("down") then | |
8338 | isFarmToRight = true | |
8339 | end | |
8340 | turtle.back() | |
8341 | end | |
8342 | end | |
8343 | -- end of the row: change direction | |
8344 | - | T:place("torch", "forward", true) |
8344 | + | |
8345 | lib.plantCrop(crop, "down") | |
8346 | if toRight then | |
8347 | T:go("L1F1L1") | |
8348 | else | |
8349 | - | -- T:place(blockType, direction, leaveExisting, signText) |
8349 | + | |
8350 | end | |
8351 | end | |
8352 | toRight = not toRight | |
8353 | end | |
8354 | T:go("R1F1") -- goes over chest/cobble on top wall | |
8355 | - | T:place(R.useBlockType, "forward", true) |
8355 | + | if lib.isStorage("down") then |
8356 | isFarmToFront = true | |
8357 | end | |
8358 | T:go("R2F"..length.."D1L1") -- go straight across to seed chest 10 blocks, facing crops | |
8359 | lib.storeCrops() -- rotates from start to deposit seeds and crops, ends facing crops | |
8360 | return isFarmToRight, isFarmToFront | |
8361 | end | |
8362 | ||
8363 | - | T:place(R.useBlockType, "up", true) |
8363 | + | function lib.harvestTree(direction) |
8364 | --[[ | |
8365 | start in front of / during tree harvest | |
8366 | Check if sapling present | |
8367 | Harvest tree if present, replant sapling | |
8368 | Dispose of apples. Use sticks as fuel | |
8369 | Return to base | |
8370 | - | T:place(R.useBlockType, "forward") |
8370 | + | |
8371 | if turtle.getFuelLevel() < turtle.getFuelLimit() / 2 then -- only harvest tree if fuel < half max | |
8372 | direction = direction or "forward" | |
8373 | local inFront = T:getBlockType("forward") | |
8374 | print("Checking tree") | |
8375 | - | T:place(R.useBlockType, "forward") |
8375 | + | if inFront == "" then -- no tree or sapling |
8376 | print("No sapling: planting sapling") | |
8377 | T:place("sapling", -1, "forward", false) | |
8378 | elseif inFront:find("log") ~= nil or direction == "up" then -- tree above or in front | |
8379 | - | T:place(R.useBlockType, "forward") |
8379 | + | -- clsTurtle.harvestTree(self, extend, craftChest, direction) |
8380 | print("Harvesting tree") | |
8381 | T:harvestTree(false, false, direction) --do not investigate side branches in case chunk unloaded | |
8382 | T:go("R2F1R2") -- face dirt | |
8383 | -- place(self, blockType, damageNo, direction, leaveExisting, signText) | |
8384 | T:place("sapling", -1, "forward", false) | |
8385 | end | |
8386 | print("Dropping saplings into storage") | |
8387 | T:dropItem("sapling", "down", 0) -- drop all saplings down into chest | |
8388 | - | T:place(R.useBlockType, "down", true) |
8388 | + | print("Disposing of apples") |
8389 | T:dropItem("apple", "up", 0) -- drop any apples | |
8390 | local slot = T:getItemSlot("minecraft:stick") | |
8391 | if slot > 0 then -- use any sticks to refuel | |
8392 | turtle.select(slot) | |
8393 | turtle.refuel() | |
8394 | end | |
8395 | end | |
8396 | end | |
8397 | ||
8398 | function lib.manageTree() | |
8399 | --[[ starting position facing crops ]] | |
8400 | local crop = "" | |
8401 | local logSlot = T:getItemSlot("stick") | |
8402 | if logSlot > 0 then | |
8403 | turtle.select(logSlot) | |
8404 | turtle.refuel() | |
8405 | end | |
8406 | logSlot = T:getItemSlot("log") | |
8407 | local needsFuel = false | |
8408 | ||
8409 | - | T:place(R.useBlockType, "down", true) |
8409 | + | |
8410 | needsFuel = true | |
8411 | end | |
8412 | if needsFuel then | |
8413 | print("Running Tree Manager") | |
8414 | logSlot = lib.gotoTree(logSlot) -- check for sapling or harvest tree, retuns to start, ends facing buried barrel/chest if has logs, logSlot returned | |
8415 | end | |
8416 | if logSlot > 0 then | |
8417 | if not needsFuel then -- logs already onboard, no tree harvest, so turn towards buried chest | |
8418 | T:turnLeft(1) | |
8419 | end | |
8420 | T:go("F1") -- move to buried storage chest/barrel | |
8421 | lib.refuelWithLogs(logSlot) -- use any logs for fuel | |
8422 | T:go("R2F1") -- facing seed chest/barrel | |
8423 | else | |
8424 | T:turnRight(1) -- facing seed chest/barrel | |
8425 | end | |
8426 | ||
8427 | crop = lib.getSeeds("forward") -- get 1 stack of beetroot / wheat seeds | |
8428 | if crop == "" then | |
8429 | print("No seeds available. Checking root veg") | |
8430 | T:turnRight(1) -- face crop chests | |
8431 | crop = lib.getVeg("forward") -- gets any carrots / potatoes | |
8432 | T:turnRight(2) -- face crops | |
8433 | else | |
8434 | T:turnLeft(1) -- face crops | |
8435 | end | |
8436 | return crop | |
8437 | end | |
8438 | ||
8439 | function lib.isCropReady(direction) | |
8440 | local isReady = false | |
8441 | local status = "" | |
8442 | local cropType = "" | |
8443 | local success = false | |
8444 | local data = {} | |
8445 | ||
8446 | direction = direction or "forward" | |
8447 | ||
8448 | if direction == "down" then | |
8449 | success, data = turtle.inspectDown() | |
8450 | else | |
8451 | success, data = turtle.inspect() | |
8452 | end | |
8453 | if success then | |
8454 | cropType = data.name | |
8455 | --print("cropType: "..cropType) read() | |
8456 | if data.name == "minecraft:carrots" then | |
8457 | status = data.state.age.." / 7" | |
8458 | --print("Carrots status: "..status) read() | |
8459 | if data.state.age == 7 then | |
8460 | isReady = true | |
8461 | end | |
8462 | elseif data.name == "minecraft:potatoes" then | |
8463 | status = data.state.age.." / 7" | |
8464 | if data.state.age == 7 then | |
8465 | isReady = true | |
8466 | end | |
8467 | elseif data.name == "minecraft:wheat" then | |
8468 | status = data.state.age.." / 7" | |
8469 | if data.state.age == 7 then | |
8470 | isReady = true | |
8471 | end | |
8472 | elseif data.name == "minecraft:beetroots" then | |
8473 | status = data.state.age.." / 3" | |
8474 | if data.state.age == 3 then | |
8475 | isReady = true | |
8476 | end | |
8477 | end | |
8478 | end | |
8479 | return isReady, cropType, status -- eg true, "minecraft:carrots", "7 / 7" or false, "", "" | |
8480 | end | |
8481 | ||
8482 | function lib.isStorage(direction) | |
8483 | blockType = T:getBlockType(direction) | |
8484 | if blockType:find("barrel") ~= nil then | |
8485 | return true, "barrel" | |
8486 | elseif blockType:find("chest") ~= nil then | |
8487 | return true, "chest" | |
8488 | end | |
8489 | ||
8490 | return false, "" | |
8491 | end | |
8492 | ||
8493 | function lib.plantCrop(crop, direction) | |
8494 | local planted = false | |
8495 | --turtle.digDown("left") -- harvest existing | |
8496 | --turtle.digDown("right") -- till soil | |
8497 | if crop:find("potato") ~= nil then | |
8498 | T:dropItem("poison", "up", 0) | |
8499 | end | |
8500 | planted = T:place("carrot", -1, direction) | |
8501 | if not planted then | |
8502 | planted = T:place("potato", -1, direction) | |
8503 | end | |
8504 | - | T:place("torch", "down") -- place torch, move forward |
8504 | + | if not planted then |
8505 | planted = T:place("beetroot_seeds", -1, direction) | |
8506 | end | |
8507 | if not planted then | |
8508 | planted = T:place("wheat_seeds", -1, direction) | |
8509 | end | |
8510 | end | |
8511 | - | if not T:place("stone", "down") then -- place stone below |
8511 | + | |
8512 | function lib.refuelWithLogs(logSlot) | |
8513 | -- assume positioned in front of buried chest / barrel, saplings already dropped, apples dumped, sticks used as fuel | |
8514 | print("Logs present: collecting crafting table") | |
8515 | -- earlier versions used crafting table buried in the ground | |
8516 | -- newer versions have a barrel or chest embedded in the ground, containing the crafting table | |
8517 | print("Sorting Inventory") | |
8518 | T:sortInventory() | |
8519 | while T:suck("down") do end -- empty out barrel/chest to find crafting table | |
8520 | if T:getItemSlot("crafting") == 0 then | |
8521 | T:checkInventoryForItem({"crafting"}, {1}, true, "Crafting table required for logs->planks") | |
8522 | end | |
8523 | if T:equip("right", "minecraft:crafting_table") then -- swap equipment on right side | |
8524 | for i = 1, 16 do -- drop anything except logs down into barrel/chest/pit | |
8525 | if T:getSlotContains(i):find("log") == nil then | |
8526 | T:drop("down", i) | |
8527 | else | |
8528 | logSlot = i | |
8529 | end | |
8530 | end | |
8531 | turtle.select(logSlot) | |
8532 | turtle.transferTo(1) | |
8533 | turtle.craft() -- craft logs to planks | |
8534 | logSlot = T:getItemSlot("planks") | |
8535 | while logSlot > 0 do | |
8536 | turtle.select(logSlot) | |
8537 | turtle.refuel() | |
8538 | logSlot = T:getItemSlot("planks") | |
8539 | end | |
8540 | -- refuel using planks | |
8541 | while T:suck("down") do end -- recover items from storagebelow | |
8542 | if not T:equip("right", "minecraft:diamond_hoe") then -- re-equip | |
8543 | T:equip("right", "minecraft:diamond_pickaxe") | |
8544 | end | |
8545 | if T:dropItem("minecraft:crafting_table", "down") then | |
8546 | turtle.refuel() -- use any sticks | |
8547 | end | |
8548 | else | |
8549 | print("Unable to equip crafting table.\n\nCheck turtle inventory and chest or barrel below") | |
8550 | error() | |
8551 | end | |
8552 | end | |
8553 | ||
8554 | function lib.returnToBack() | |
8555 | --[[ move from farm at front back to starting farm ]] | |
8556 | T:go("U1R1F11D1L1") | |
8557 | end | |
8558 | ||
8559 | function lib.returnToLeft() | |
8560 | --[[ move from farm on right back to starting farm ]] | |
8561 | T:go("U1R2F11D1R2") | |
8562 | end | |
8563 | ||
8564 | function lib.storeCrops() | |
8565 | -- place crops and seeds into chests | |
8566 | T:turnRight(1) | |
8567 | if lib.isStorage("forward") then | |
8568 | lib.storeSeeds("forward") | |
8569 | end | |
8570 | T:turnRight(1) | |
8571 | if lib.isStorage("forward") then | |
8572 | lib.storeVeg("forward") | |
8573 | end | |
8574 | T:turnRight(2) -- facing crops again | |
8575 | end | |
8576 | ||
8577 | function lib.storeSeeds(direction) | |
8578 | direction = direction or "forward" | |
8579 | if lib.isStorage(direction) then -- chest exists | |
8580 | if T:getItemSlot("minecraft:wheat_seeds") > 0 then | |
8581 | if not T:dropItem("minecraft:wheat_seeds", direction, 0) then | |
8582 | T:dropItem("minecraft:wheat_seeds", "up", 0) | |
8583 | end -- drop all wheat seeds | |
8584 | elseif T:getItemSlot("minecraft:beetroot_seeds") > 0 then | |
8585 | if not T:dropItem("minecraft:beetroot_seeds", direction, 0) then-- drop all beetroot seeds | |
8586 | T:dropItem("minecraft:beetroot_seeds", "up", 0) | |
8587 | end | |
8588 | end | |
8589 | end | |
8590 | end | |
8591 | ||
8592 | function lib.storeVeg(direction) | |
8593 | direction = direction or "forward" | |
8594 | T:dropItem("apple", "up", 0) -- drop all apples | |
8595 | T:dropItem("poison", "up", 0) -- drop all poison potatoes | |
8596 | if lib.isStorage(direction) then | |
8597 | if not T:dropItem("carrot", direction, 0) then-- drop carrots | |
8598 | --return false | |
8599 | end | |
8600 | T:dropItem("potato", direction, 0) -- drop potato | |
8601 | T:dropItem("minecraft:wheat", direction, 0) -- drop all wheat | |
8602 | T:dropItem("minecraft:beetroot", direction, 0) -- drop all beetroot | |
8603 | end | |
8604 | end | |
8605 | ||
8606 | function lib.watchFarm() | |
8607 | --[[ | |
8608 | check status of crops in front of turtle. | |
8609 | call lib.harvest when ripe | |
8610 | return farm(s) found in front or to the right | |
8611 | ]] | |
8612 | local isReady, crop, status = lib.isCropReady("forward") -- eg true, "minecraft:carrots", "7 / 7" or false, "", "" | |
8613 | -- check state of crop in front. Harvest if ripe | |
8614 | while not isReady do | |
8615 | isReady, crop, status = lib.isCropReady("forward") -- eg true, "minecraft:carrots", "7 / 7" or false, "", "" | |
8616 | if not isReady then | |
8617 | if crop == "" then | |
8618 | print("No crops found in front") | |
8619 | print("Plant seeds, carrots, potatoes") | |
8620 | error() | |
8621 | else | |
8622 | print("Waiting for "..crop.." status: "..status) | |
8623 | end | |
8624 | sleep(60) | |
8625 | end | |
8626 | end | |
8627 | print("Local crops ripe") | |
8628 | ||
8629 | - | T:place("torch", "down") -- place torch |
8629 | + | return lib.manageTree() -- "" or collected seeds / root crops |
8630 | end | |
8631 | ||
8632 | --[[ | |
8633 | called from args on start, or from user choice | |
8634 | farm already built, needs planting and/or harvesting | |
8635 | needs both pickaxe and hoe | |
8636 | may start in any position if chunk unloaded while running | |
8637 | ]] | |
8638 | --local pp = utils.getPrettyPrint() | |
8639 | ||
8640 | local atHome = lib.checkPosition()-- facing crops, placed above water source | |
8641 | if not atHome then | |
8642 | if not lib.goHome() then -- try to find home | |
8643 | return | |
8644 | { | |
8645 | "Unable to determine my position.\n", | |
8646 | "Place me in the lower left corner", | |
8647 | "over water, facing the crops with", | |
8648 | "barrels or chests to my right and behind" | |
8649 | } | |
8650 | end | |
8651 | end | |
8652 | -- check equipment | |
8653 | T:go("L1F1") -- over barrel | |
8654 | local isStorage, storageType = lib.isStorage("down") | |
8655 | if not isStorage then | |
8656 | local message = | |
8657 | [["Farm upgrade required: | |
8658 | Previous designs had a crafting table | |
8659 | next to the water source. | |
8660 | ||
8661 | 1. Place a barrel or chest under the turtle | |
8662 | instead. | |
8663 | ||
8664 | 2. Restart" | |
8665 | ]] | |
8666 | print(message) | |
8667 | error() | |
8668 | end | |
8669 | -- must be storage below to get this far | |
8670 | if lib.checkEquipment() then | |
8671 | T:equip("right", "minecraft:diamond_hoe", 0) -- equip hoe and put crafting chest into inventory | |
8672 | T:dropItem("crafting", "down") | |
8673 | utils.goBack(1) | |
8674 | T:turnRight(1) | |
8675 | else | |
8676 | return {"Unable to equip hoe."} | |
8677 | end | |
8678 | ||
8679 | ||
8680 | -- check if crops already planted | |
8681 | - | T:place("torch", "down") -- place torch |
8681 | + | local isReady, crop, status = lib.isCropReady("forward") |
8682 | local watch = true -- assume watching farm already planted | |
8683 | if crop == "" then -- nothing has been planted | |
8684 | watch = false-- not watching, continue with planting | |
8685 | pp.itemColours = {colors.lightGray, colors.red, colors.orange, colors.brown} | |
8686 | crops = {"minecraft:wheat_seeds", "minecraft:beetroot_seeds", "minecraft:carrots", "minecraft:potatoes"} | |
8687 | choices = {"wheat (seeds)", "beetroot (seeds)", "carrot", "potato"} | |
8688 | choice = menu.menu("Choose preferred crop", choices, pp, "Type number of your choice") | |
8689 | crop = crops[choice] | |
8690 | T:checkInventoryForItem({crop}, {95}, true, "Do not mix! add as many as you want") | |
8691 | end | |
8692 | ||
8693 | while true do -- start infinite loop of watching crops, farming all modules | |
8694 | if watch then -- not already in inventory | |
8695 | crop = lib.watchFarm() --waits if required, returns crop type when ripe | |
8696 | end | |
8697 | print("Beginning "..crop.." management") | |
8698 | local isFarmToRight, isFarmToFront = lib.harvest(crop) | |
8699 | if isFarmToRight then | |
8700 | lib.farmToRight() -- no action if no farmToRight | |
8701 | lib.returnToLeft() -- return home and continue with front | |
8702 | isFarmToRight = false | |
8703 | end | |
8704 | ||
8705 | if isFarmToFront then | |
8706 | isFarmToRight = lib.farmInFront() | |
8707 | if isFarmToRight then | |
8708 | lib.farmToRight() -- no action if no farmToRight | |
8709 | lib.returnToLeft() -- return home | |
8710 | end | |
8711 | lib.returnToBack() | |
8712 | end | |
8713 | if not R.auto then -- not started from startup.lua | |
8714 | T:go("L1F1") | |
8715 | while T:suck("down") do end -- recover items from storagebelow | |
8716 | T:equip("right", "minecraft:crafting_table", 0) -- equip crafting_table | |
8717 | T:dropItem("diamond_hoe", "down") -- drop hoe into storage | |
8718 | T:dropItem("crafting", "down") -- in case spare one picked by mistake | |
8719 | utils.goBack(1) | |
8720 | T:turnRight(1) | |
8721 | return {"Crop management of all modules completed"} | |
8722 | end | |
8723 | end | |
8724 | return {} | |
8725 | end | |
8726 | ||
8727 | local function manageFarmSetup(R) -- 33 | |
8728 | local lib = {} | |
8729 | ||
8730 | function lib.disableAutostart() | |
8731 | if fs.exists("start.txt") then | |
8732 | fs.delete("start.txt") | |
8733 | end | |
8734 | if fs.exists("startup.lua") then | |
8735 | fs.delete("startup.lua") | |
8736 | end | |
8737 | end | |
8738 | ||
8739 | function lib.enableAutostart() | |
8740 | if not fs.exists("startup.lua") then | |
8741 | local h = fs.open("startup.lua", "w") | |
8742 | h.writeLine('function main()') | |
8743 | h.writeLine(' if fs.exists("start.txt") then') | |
8744 | h.writeLine(' local handle = fs.open("start.txt", "r")') | |
8745 | h.writeLine(' local cmd = handle.readLine()') | |
8746 | h.writeLine(' handle.close()') | |
8747 | h.writeLine(' shell.run("tk.lua "..cmd)') | |
8748 | h.writeLine(' end') | |
8749 | h.writeLine('end') | |
8750 | h.writeLine('main()') | |
8751 | h.close() | |
8752 | end | |
8753 | local h = fs.open("start.txt", "w") | |
8754 | if R.data == "farm" then | |
8755 | h.writeLine('farm') | |
8756 | end | |
8757 | h.close() | |
8758 | print("Startup files written") | |
8759 | end | |
8760 | ||
8761 | T:clear() | |
8762 | --local pp = utils.getPrettyPrint() | |
8763 | local choices = {"Plant or harvest this farm complex"} | |
8764 | local isManaged = fs.exists("start.txt") | |
8765 | if isManaged then | |
8766 | table.insert(choices, "Disable automatic farm management") | |
8767 | else | |
8768 | table.insert(choices, "Enable automatic farm management") | |
8769 | end | |
8770 | pp.itemColours = {colors.lime, colors.lightGray} | |
8771 | local userChoice, modifier = menu.menu("Choose your option", choices, pp) -- 1 to 2 | |
8772 | if modifier == "q" then -- quit chosen | |
8773 | return {"Player has quit"} | |
8774 | end | |
8775 | R.subChoice = userChoice | |
8776 | if R.subChoice == 1 then -- harvest now | |
8777 | R.silent = false | |
8778 | R.data = "farm" | |
8779 | R.auto = false | |
8780 | return manageFarm(R) | |
8781 | else -- enable/disable auto farm | |
8782 | local line = menu.clear() | |
8783 | if isManaged then | |
8784 | local message = ( "This turtle has been configured to".. | |
8785 | "start automatically and run the farm".. | |
8786 | "management program.\n") | |
8787 | line = menu.colourText(line, message, true, true) | |
8788 | if menu.getBoolean("Do you want to disable this? (y/n)", line, colors.yellow, colors.black) then | |
8789 | lib.disableAutostart() | |
8790 | end | |
8791 | return {"Autostart disabled. Reboot to activate"} | |
8792 | else -- not managed | |
8793 | local message = ( "~yellow~This turtle can be configured to be\n".. | |
8794 | "a dedicated farm manager.\n\n".. | |
8795 | "~lightGray~It will then start automatically and\n".. | |
8796 | "monitor the farm complex:\n\n".. | |
8797 | "~green~harvesting~yellow~ and ~lime~replanting ~yellow~continuously.\n") | |
8798 | line = menu.colourText(line, message, true, true) | |
8799 | if menu.getBoolean("Do you want to enable this? (y/n)", line + 2, colors.orange, colors.black) then | |
8800 | lib.enableAutostart() | |
8801 | else | |
8802 | return {"Player cancelled operation"} | |
8803 | end | |
8804 | return {"Autostart enabled. Reboot to activate"} | |
8805 | end | |
8806 | end | |
8807 | ||
8808 | return {} | |
8809 | end | |
8810 | ||
8811 | local function measure(R) -- 101 | |
8812 | -- measure height/ depth / length | |
8813 | local lib = {} | |
8814 | ||
8815 | function lib.checkBlocks(R, blocks) | |
8816 | local dimension = "height" | |
8817 | local message = "" | |
8818 | local measure = "" | |
8819 | local doContinue = true | |
8820 | if R.choice == 102 then | |
8821 | dimension = "depth" | |
8822 | elseif R.choice == 103 then | |
8823 | dimension = "length" | |
8824 | end | |
8825 | blocks = blocks + 1 | |
8826 | if blocks > R.size then | |
8827 | message = "Max "..dimension.." of "..R.size.." stopped measurement" | |
8828 | measure = "" | |
8829 | doContinue = false | |
8830 | else | |
8831 | measure = dimension.." measured: "..blocks.." blocks" | |
8832 | end | |
8833 | return doContinue, blocks, measure, message | |
8834 | end | |
8835 | ||
8836 | local blocks = 1 | |
8837 | local method = "" | |
8838 | local measure = "" | |
8839 | local message = "" | |
8840 | local doContinue = true | |
8841 | if R.choice == 101 then -- height | |
8842 | if R.subChoice == 1 then -- obstruction above | |
8843 | method = "Method: Until obstruction above" | |
8844 | while turtle.up() and doContinue do | |
8845 | doContinue, blocks, measure, message = lib.checkBlocks(R, blocks) | |
8846 | end | |
8847 | elseif R.subChoice == 2 then -- end of blocks in front of turtle eg cliff, wall | |
8848 | method = "Method: Until no block detected in front" | |
8849 | while turtle.detect() and doContinue do | |
8850 | if turtle.up() then | |
8851 | doContinue, blocks, measure, message = lib.checkBlocks(R, blocks) | |
8852 | else | |
8853 | message = "Obstruction above stopped measurement" | |
8854 | measure = "" | |
8855 | doContinue = false | |
8856 | end | |
8857 | end | |
8858 | - | T:place("slab", "down") -- place slab layer 1 |
8858 | + | |
8859 | method = "Method:Until search: '"..R.data.."' met" | |
8860 | - | T:place("slab", "down") -- place slab layer 2 |
8860 | + | |
8861 | if turtle.up() then | |
8862 | - | T:place("redstone", "down") |
8862 | + | |
8863 | if doContinue then | |
8864 | - | T:place("redstone", "forward") -- redstone on ground level slab |
8864 | + | |
8865 | if blockType:find(R.data) ~= nil then | |
8866 | - | T:place("slab", "down") -- slab on layer 1 |
8866 | + | |
8867 | message = "Found "..blockType | |
8868 | - | T:place("slab", "down") -- slab on layer 3 |
8868 | + | |
8869 | end | |
8870 | - | T:place("redstone", "down") -- redstone on layer 3 slab |
8870 | + | |
8871 | else | |
8872 | message = "Obstruction above stopped measurement" | |
8873 | - | T:place("redstone", "forward") -- redstone on layer 1 slab |
8873 | + | |
8874 | doContinue = false | |
8875 | - | T:place("redstone", "forward") -- redstone on level 0 floor |
8875 | + | |
8876 | end | |
8877 | elseif R.subChoice == 4 then -- When block above changes eg dragon tower height | |
8878 | local blockType = T:getBlockType("up") | |
8879 | local compare = blockType | |
8880 | method = "Method: Until "..blockType.." changes" | |
8881 | while blockType == compare and doContinue do | |
8882 | - | T:place("redstone", "down") -- redstone under chest etc |
8882 | + | |
8883 | doContinue, blocks, measure, message = lib.checkBlocks(R, blocks) | |
8884 | if doContinue then | |
8885 | blockType = T:getBlockType("up") | |
8886 | end | |
8887 | end | |
8888 | measure = "Height measured: "..blocks.." blocks" | |
8889 | message = "Found "..blockType | |
8890 | end | |
8891 | ||
8892 | for i = 1, blocks do | |
8893 | - | T:place("chest", "forward") -- end chest |
8893 | + | |
8894 | end | |
8895 | - | T:place("slab", "down") -- slab above chest |
8895 | + | |
8896 | T:go("F1R2D1") -- go off the edge and face cliff/pit wall | |
8897 | blocks = blocks + 1 | |
8898 | if R.subChoice == 1 then -- obstruction water / lava below | |
8899 | - | T:place("chest", "forward") -- start chest |
8899 | + | |
8900 | while move do | |
8901 | - | T:place("wall", "forward") -- place wall |
8901 | + | |
8902 | if blockType:find("water") ~= nil or blockType:find("lava") ~= nil then | |
8903 | - | T:place("pressure", "down") -- place pressure plate |
8903 | + | |
8904 | move = false | |
8905 | - | T:place("hopper", "forward") -- place hopper into chest |
8905 | + | |
8906 | move = turtle.down() | |
8907 | - | T:place("wall", "forward") -- place second wall |
8907 | + | |
8908 | blocks = blocks + 1 | |
8909 | else | |
8910 | measure = "Depth measured: "..blocks.." blocks" | |
8911 | end | |
8912 | end | |
8913 | end | |
8914 | - | T:place(R.useBlockType, "forward", false) -- replace back wall with polished block layer 2 |
8914 | + | |
8915 | elseif R.subChoice == 2 then -- end of wall in front` | |
8916 | - | T:place(R.useBlockType, "forward", false) -- replace back wall with polished block layer 3 |
8916 | + | |
8917 | if turtle.down() then | |
8918 | blocks = blocks + 1 | |
8919 | - | T:place(R.useBlockType, "forward", false)-- polished block above second wall layer 3 |
8919 | + | |
8920 | else | |
8921 | message1 = "Obstruction below stopped measurement" | |
8922 | break | |
8923 | - | T:place("piston", "forward") -- lower replacer piston placed |
8923 | + | |
8924 | end | |
8925 | method = "Method: Until no block detected ahead" | |
8926 | - | T:place("piston", "forward") -- lower piston placed |
8926 | + | |
8927 | method = "Method:Until search: '"..R.data.."' met" | |
8928 | while turtle.detect() do | |
8929 | - | T:place(R.useBlockType, "forward", false) -- polished block back wall layer 4 |
8929 | + | |
8930 | blocks = blocks + 1 | |
8931 | - | T:place("dispenser", "forward") -- dispenser placed |
8931 | + | |
8932 | if blockType:find(R.data) ~= nil then | |
8933 | measure = "Depth measured: "..blocks.." blocks" | |
8934 | - | T:place("slab", "down") -- lower piston slab placed |
8934 | + | |
8935 | break | |
8936 | - | T:place(R.useBlockType, "forward", false)-- polished block above second wall layer 4 |
8936 | + | |
8937 | else | |
8938 | message = "Obstruction below stopped measurement" | |
8939 | break | |
8940 | end | |
8941 | - | T:place("computercraft:computer_normal", "forward", false) -- place computer |
8941 | + | |
8942 | end | |
8943 | for i = 1, blocks do | |
8944 | - | T:place(R.useBlockType, "forward", false) -- polished block back wall layer 4 |
8944 | + | |
8945 | end | |
8946 | T:go("F1R2") | |
8947 | - | T:place("piston", "forward") -- upper piston placed |
8947 | + | |
8948 | if R.subChoice == 1 then -- obstruction ahead | |
8949 | method = "Method: Until obstruction ahead" | |
8950 | - | T:place(R.useBlockType, "forward", false) -- polished block back wall layer 5 |
8950 | + | |
8951 | doContinue, blocks, measure, message = lib.checkBlocks(R, blocks) | |
8952 | end | |
8953 | - | T:place(R.useBlockType, "forward", false)-- right side polished block layer 5, facing right side, in mob drop -- layer 5 facing left side, in mob drop |
8953 | + | |
8954 | method = "Method: Until no block detected above" | |
8955 | while turtle.detectUp() and doContinue do | |
8956 | if turtle.forward() then | |
8957 | - | T:place("piston", "forward") -- upper replacer piston placed |
8957 | + | |
8958 | else | |
8959 | message = "Obstruction ahead stopped measurement" | |
8960 | - | T:place("slab", "forward") -- upper piston slab placed |
8960 | + | |
8961 | doContinue = false | |
8962 | end | |
8963 | end | |
8964 | elseif R.subChoice == 3 then -- end of floor below | |
8965 | method = "Method: Until no block detected below" | |
8966 | while turtle.detectDown() and doContinue do | |
8967 | - | T:place("computercraft:computer_normal", "forward", false) -- place computer in gap, layer 4 |
8967 | + | |
8968 | doContinue, blocks, measure, message = lib.checkBlocks(R, blocks) | |
8969 | else | |
8970 | message = "Obstruction ahead stopped measurement" | |
8971 | - | T:place(R.useBlockType, "forward", false) |
8971 | + | |
8972 | doContinue = false | |
8973 | - | T:place(R.useBlockType, "forward", false) |
8973 | + | |
8974 | end | |
8975 | - | T:place(R.useBlockType, "forward", false) -- facing right |
8975 | + | |
8976 | method = "Method:Until search: '"..R.data.."' above met" | |
8977 | while turtle.detectUp() and doContinue do | |
8978 | if turtle.forward() then | |
8979 | doContinue, blocks, measure, message = lib.checkBlocks(R, blocks) | |
8980 | if doContinue then | |
8981 | - | T:place("glass", "down", false) |
8981 | + | |
8982 | if blockType:find(R.data) ~= nil then | |
8983 | - | T:place("glass", "down", false) -- on top of glass facing back wall at dungeon base level 5 |
8983 | + | |
8984 | measure = "Length measured: "..blocks.." blocks" | |
8985 | - | T:place(R.useBlockType, "down", false) -- level 6 dungeon exit |
8985 | + | |
8986 | end | |
8987 | end | |
8988 | else | |
8989 | message = "Obstruction ahead stopped measurement" | |
8990 | measure = "" | |
8991 | doContinue = false | |
8992 | end | |
8993 | end | |
8994 | elseif R.subChoice == 5 then -- search for specific block down min 3 characters | |
8995 | - | T:place(R.useBlockType, "forward", false) |
8995 | + | |
8996 | --while turtle.detectDown() and doContinue do | |
8997 | - | T:place(R.useBlockType, "forward", false) -- facing right |
8997 | + | |
8998 | if turtle.forward() then | |
8999 | doContinue, blocks, measure, message = lib.checkBlocks(R, blocks) | |
9000 | if doContinue then | |
9001 | - | T:place(R.useBlockType, "forward", false) |
9001 | + | |
9002 | if blockType:find(R.data) ~= nil then | |
9003 | message = "Found "..blockType | |
9004 | measure = "Length measured: "..blocks.." blocks" | |
9005 | doContinue = false | |
9006 | end | |
9007 | - | T:place("computercraft:wired_modem", "forward", false) -- place modem |
9007 | + | |
9008 | else | |
9009 | - | T:place("computercraft:cable", "forward", false) -- place network cable |
9009 | + | |
9010 | - | T:place("computercraft:cable", "forward", false) -- place network cable (no need to move) |
9010 | + | |
9011 | doContinue = false | |
9012 | - | T:place("computercraft:cable", "forward", false) |
9012 | + | |
9013 | end | |
9014 | - | T:place("computercraft:cable", "forward", false) |
9014 | + | |
9015 | T:turnRight(2) -- head home | |
9016 | - | T:place("computercraft:wired_modem", "forward", false) -- place modem |
9016 | + | |
9017 | turtle.forward() | |
9018 | - | T:place("computercraft:cable", "forward", false) |
9018 | + | |
9019 | - | T:place("computercraft:cable", "forward", false) |
9019 | + | |
9020 | elseif R.choice == 104 then -- depth of stretch of water | |
9021 | --R.length = 0 to auto calculate | |
9022 | R.width = 1 | |
9023 | R.silent = true | |
9024 | R.useBlockType = "" | |
9025 | R.data = "clearWaterPlants" | |
9026 | local data = clearWaterPlants(R) | |
9027 | R.height = data[1] | |
9028 | local length = data[2] | |
9029 | T:go ("R2F"..length - 1 .."R2U1") | |
9030 | return {"Greatest depth measured: ".. R.height,"Width of water: "..R.length} | |
9031 | end | |
9032 | if message == "" then | |
9033 | return{method, measure} | |
9034 | else | |
9035 | return{method, measure, message} | |
9036 | end | |
9037 | end | |
9038 | ||
9039 | local function mineBedrockArea(R) -- 19 | |
9040 | --[[ | |
9041 | Assume on level 5 or -59 | |
9042 | for 1, width do | |
9043 | for 1, length do | |
9044 | go down until bedrock, digging/replacing all directions | |
9045 | return to 5 / -59 | |
9046 | move forward 1 blocks | |
9047 | end | |
9048 | turn right/ forward 2 turn right | |
9049 | end | |
9050 | ]] | |
9051 | local lib = {} | |
9052 | ||
9053 | function lib.clearColumn(R) | |
9054 | local level = 0 | |
9055 | --T:go("L1x1R2x1L1") | |
9056 | local success = T:down(1) | |
9057 | while success do | |
9058 | level = level + 1 | |
9059 | if R.data == "leaveExposed" then | |
9060 | T:go("R1x1R1x1R1x1R1x1", false, 0, true) | |
9061 | else | |
9062 | T:go("R1C1R1C1R1C1R1C1", false, 0, true) | |
9063 | end | |
9064 | success = T:down(1) | |
9065 | end | |
9066 | if R.data == "leaveExposed" then | |
9067 | T:go("U"..level) | |
9068 | else | |
9069 | T:go("U"..level.."C2") | |
9070 | end | |
9071 | - | local function createTrialCover(R) |
9071 | + | |
9072 | ||
9073 | local goRight = true | |
9074 | for i = 1, R.width do | |
9075 | for j = 1, R.length do | |
9076 | lib.clearColumn(R) | |
9077 | T:forward(1) | |
9078 | end | |
9079 | if goRight then | |
9080 | T:go("R1F1R1") | |
9081 | else | |
9082 | T:go("L1F1L1") | |
9083 | end | |
9084 | goRight = not goRight | |
9085 | end | |
9086 | return {} | |
9087 | end | |
9088 | ||
9089 | local function oceanMonumentColumns(R) | |
9090 | - | function lib.findSpawner() |
9090 | + | |
9091 | local lib = {} | |
9092 | ||
9093 | - | -- assume turtle placed facing trial spawner |
9093 | + | |
9094 | local depth = 0 | |
9095 | while T:isWater("forward") do | |
9096 | T:go("U1C2") | |
9097 | depth = depth + 1 | |
9098 | end | |
9099 | return depth | |
9100 | - | if moves > 32 then |
9100 | + | |
9101 | ||
9102 | function lib.buildTower() | |
9103 | T:go("F1C2 F1C2 F1C2") | |
9104 | T:go("L1F1 L1C2 F1C2 F1C2 F1C2") | |
9105 | - | if not found then -- could be behind a wall |
9105 | + | |
9106 | - | print("Assuming spawner behind a wall") |
9106 | + | |
9107 | ||
9108 | T:go("R2") | |
9109 | - | while turtle.forward() and not quit do |
9109 | + | |
9110 | T:go("U1C2") | |
9111 | - | if moves > 32 then |
9111 | + | |
9112 | - | quit = true |
9112 | + | |
9113 | end | |
9114 | end | |
9115 | - | found, position = lib.isSpawner() -- true/false, top/bottom/nil |
9115 | + | |
9116 | - | if not found then |
9116 | + | |
9117 | - | T:go("R2F"..moves + 2 .."R2") |
9117 | + | |
9118 | local blockType = T:getBlockType("down") | |
9119 | while blockType:find("water") == nil do | |
9120 | T:down(1) -- if on a platform will break through | |
9121 | blockType = T:getBlockType("down") | |
9122 | end | |
9123 | --R.useBlockType = "prismarine", R.data = "oceanMonumentColumns" from getTask | |
9124 | --local tempData = R.data | |
9125 | --R.data = "clearWaterPlants" | |
9126 | local result = clearWaterPlants(R)[1] | |
9127 | if result ~= "" then | |
9128 | return {result} | |
9129 | else | |
9130 | --on corner of monument, facing out to ocean | |
9131 | local depth = lib.buildColumn() | |
9132 | -- now above surface, block below at surface level | |
9133 | for i = 1, 4 do | |
9134 | T:turnRight(1) | |
9135 | R.length = 57 | |
9136 | utils.createPath(R) -- roughly at next corner | |
9137 | if i < 4 then | |
9138 | T:down(depth-2) -- roughly at correct depth | |
9139 | local waterBelow = utils.clearVegetation("down") | |
9140 | while waterBelow do | |
9141 | T:down(1) | |
9142 | waterBelow = utils.clearVegetation("down") | |
9143 | end | |
9144 | blockType = T:getBlockType("down") | |
9145 | while blockType:find("prismarine") ~= nil do | |
9146 | T:forward(1) | |
9147 | blockType = T:getBlockType("down") | |
9148 | end | |
9149 | turtle.back() | |
9150 | depth = lib.buildColumn() | |
9151 | - | local found, position = lib.findSpawner() -- move forwards until meet Spawner, go through wall if present |
9151 | + | |
9152 | - | if not found then --outside dungeon |
9152 | + | |
9153 | - | return {"Trial spawner not found"} |
9153 | + | |
9154 | - | end |
9154 | + | |
9155 | - | if position == "top" then |
9155 | + | |
9156 | - | T:go("B2D1") |
9156 | + | |
9157 | - | elseif position == "forward" then |
9157 | + | |
9158 | - | T:go("B1") |
9158 | + | |
9159 | ||
9160 | - | T:go("B2U1") |
9160 | + | |
9161 | local moves = 2 | |
9162 | - | T:go("R1F2R2") --on lower right corner |
9162 | + | |
9163 | - | -- starts with wall across spawner |
9163 | + | |
9164 | - | buildStructure(R) |
9164 | + | |
9165 | - | T:go("U3F1 R1F1 L1U1 F1") |
9165 | + | |
9166 | if blockType:find("rail") ~= nil then | |
9167 | - | R.width = 3 |
9167 | + | |
9168 | - | R.length = 3 |
9168 | + | |
9169 | T:down(moves) | |
9170 | - | createFloorCeiling(R) |
9170 | + | |
9171 | - | T:go("F1R1 B1D1 B1D2 F1") |
9171 | + | |
9172 | T:place(R.useBlockType, -1, "forward", false) | |
9173 | utils.goBack(1) | |
9174 | T:place("minecraft:redstone_torch", -1, "forward", true) | |
9175 | T:turnLeft(1) | |
9176 | utils.goBack(1) | |
9177 | T:up(moves) | |
9178 | T:go("F1R1F1") | |
9179 | elseif R.data == "up" then -- sloping rail up/down is relative to dirtection facing | |
9180 | moves = 3 | |
9181 | T:turnLeft(1) | |
9182 | utils.goBack(1) | |
9183 | if blockType:find("rail") ~= nil then | |
9184 | moves = 4 | |
9185 | end | |
9186 | T:down(moves) | |
9187 | T:go("F1L1") | |
9188 | T:place("minecraft:redstone_torch", -1, "up", false) | |
9189 | ||
9190 | T:turnRight(1) | |
9191 | utils.goBack(1) | |
9192 | T:up(moves) | |
9193 | T:go("F1R1") | |
9194 | end | |
9195 | return {} | |
9196 | end | |
9197 | ||
9198 | local function plantTreefarm(R) -- 23 | |
9199 | --T:place(blockType, damageNo, direction, leaveExisting, signText) | |
9200 | local lib = {} | |
9201 | ||
9202 | function lib.checkSaplings(saplings, firstChoice, secondChoice) | |
9203 | local saplingSlot, sapling, count = T:getSaplingSlot(firstChoice) | |
9204 | if count < 4 and secondChoice ~= "" then | |
9205 | saplingSlot, sapling, count = T:getSaplingSlot(secondChoice) | |
9206 | end | |
9207 | if count == 0 then | |
9208 | sapling = "" | |
9209 | end | |
9210 | ||
9211 | return sapling, count | |
9212 | end | |
9213 | ||
9214 | function lib.getSaplingInventory() | |
9215 | local saplings = {} | |
9216 | saplings.oak_sapling = 0 | |
9217 | saplings.spruce_sapling = 0 | |
9218 | saplings.birch_sapling = 0 | |
9219 | saplings.jungle_sapling = 0 | |
9220 | saplings.acacia_sapling = 0 | |
9221 | saplings.dark_oak_sapling = 0 | |
9222 | ||
9223 | local firstChoice = "" | |
9224 | local firstCount = 0 | |
9225 | local secondChoice = "" | |
9226 | local secondCount = 0 | |
9227 | for i = 1, 16 do | |
9228 | if turtle.getItemCount(i) > 0 then | |
9229 | local data = turtle.getItemDetail(i) | |
9230 | if data.name:find("sapling") ~= nil then | |
9231 | local name = data.name:sub(11) -- removes "minecraft:" | |
9232 | saplings[name] = saplings[name] + data.count | |
9233 | end | |
9234 | end | |
9235 | end | |
9236 | ||
9237 | for sapling, count in pairs(saplings) do | |
9238 | if count > firstCount then | |
9239 | firstCount = count | |
9240 | firstChoice = sapling | |
9241 | else | |
9242 | if count > secondCount then | |
9243 | secondCount = count | |
9244 | secondChoice = sapling | |
9245 | end | |
9246 | end | |
9247 | end | |
9248 | return saplings, firstChoice, secondChoice -- table, "oak_sapling", "dark_oak_sapling" | |
9249 | end | |
9250 | ||
9251 | function lib.createIsland(sapling, count, exit) | |
9252 | -- place 4 dirt with saplings on all 4 unless jungle | |
9253 | -- sapling count/type already checked | |
9254 | T:forward(2) -- assume starting outside planting area | |
9255 | for i = 1, 4 do | |
9256 | T:go("R1F1") | |
9257 | T:place("dirt", -1, "down", false) | |
9258 | end | |
9259 | T:up(1) | |
9260 | if count >= 4 then | |
9261 | for i = 1, 4 do | |
9262 | T:go("R1F1") | |
9263 | T:place(sapling, -1, "down", false) | |
9264 | end | |
9265 | else | |
9266 | if sapling:find("dark") == nil and sapling ~= "" then | |
9267 | T:place(sapling, -1, "down", false) | |
9268 | end | |
9269 | end | |
9270 | if exit == "forward" then | |
9271 | T:go("F1D1") | |
9272 | elseif exit == "right" then | |
9273 | T:go("R1F2D1") | |
9274 | elseif exit == "left" then | |
9275 | T:go("L1F1D1") | |
9276 | elseif exit == "back" then | |
9277 | T:go("R2F2D1") | |
9278 | end | |
9279 | end | |
9280 | ||
9281 | function lib.createSingle(sapling, exit) | |
9282 | -- place single dirt with sapling on top | |
9283 | -- sapling count/type already checked | |
9284 | T:place("dirt", -1, "down", false) | |
9285 | - | T:place("cobble", "down", false) -- place cobblestone or cobbled deepslate to mark zero coordinate |
9285 | + | |
9286 | if not T:place(sapling, -1, "down", false) then -- try specific sapling | |
9287 | T:place("sapling", -1, "down", false) -- any available sapling | |
9288 | end | |
9289 | if exit == "forward" then | |
9290 | T:go("F1D1") | |
9291 | elseif exit == "right" then | |
9292 | T:go("R1F1D1") | |
9293 | elseif exit == "left" then | |
9294 | T:go("L1F1D1") | |
9295 | elseif exit == "back" then | |
9296 | T:go("R2F1D1") | |
9297 | end | |
9298 | end | |
9299 | ||
9300 | local saplings, firstChoice, secondChoice = lib.getSaplingInventory() | |
9301 | ||
9302 | if firstChoice ~= "" then | |
9303 | print("first sapling choice: "..firstChoice .. " ("..saplings[firstChoice]..")") | |
9304 | end | |
9305 | if secondChoice ~= "" then | |
9306 | print("second sapling choice: "..secondChoice .. " ("..saplings[secondChoice]..")") | |
9307 | end | |
9308 | ||
9309 | -- check type/size of farm | |
9310 | if R.subChoice == 1 then -- 16 single trees | |
9311 | local sapling, count = lib.checkSaplings(saplings, firstChoice, secondChoice) | |
9312 | T:go("U1F4") -- outside first area | |
9313 | for i = 1, 3 do -- column 1/4 | |
9314 | lib.createSingle(sapling, "forward") | |
9315 | T:forward(1) | |
9316 | end | |
9317 | for i = 1, 2 do | |
9318 | lib.createSingle(sapling, "right") -- place 4th dirt/saling and exit to right | |
9319 | T:forward(1) | |
9320 | end | |
9321 | for i = 1, 2 do -- column 2/4 | |
9322 | lib.createSingle(sapling, "forward") | |
9323 | T:forward(1) | |
9324 | end | |
9325 | for i = 1, 2 do | |
9326 | lib.createSingle(sapling, "left") -- place 4th dirt/saling and exit to right | |
9327 | T:forward(1) | |
9328 | end | |
9329 | for i = 1, 2 do -- column 3/4 | |
9330 | lib.createSingle(sapling, "forward") | |
9331 | T:forward(1) | |
9332 | - | T:place("minecraft:end_stone", "forward", false) -- place endstone to mark facing direction |
9332 | + | |
9333 | for i = 1, 2 do | |
9334 | lib.createSingle(sapling, "right") -- place 4th dirt/saling and exit to right | |
9335 | T:forward(1) | |
9336 | end | |
9337 | for i = 1, 3 do -- column 4/4 | |
9338 | lib.createSingle(sapling, "forward") | |
9339 | T:forward(1) | |
9340 | end | |
9341 | T:go("R1F6L1F2R2D1") | |
9342 | elseif R.subChoice == 2 then -- 4 double trees (4 saplings) | |
9343 | -- assume placed 4 blocks from start | |
9344 | local sapling, count = lib.checkSaplings(mostName, secondMostName) | |
9345 | ||
9346 | if count >= 4 then | |
9347 | T:go("U1F3") -- outside first area | |
9348 | lib.createIsland(sapling, count, "forward") | |
9349 | sapling, count = lib.checkSaplings(mostName, secondMostName) | |
9350 | T:go("F2") | |
9351 | lib.createIsland(sapling, count, "right") | |
9352 | sapling, count = lib.checkSaplings(mostName, secondMostName) | |
9353 | T:go("F2") | |
9354 | lib.createIsland(sapling, count, "right") | |
9355 | sapling, count = lib.checkSaplings(mostName, secondMostName) | |
9356 | T:go("F2") | |
9357 | lib.createIsland(sapling, count, "forward") | |
9358 | T:go("R1D1F6L1F3R2") -- outside first area | |
9359 | else | |
9360 | return {"Insufficient saplings to plant"} | |
9361 | end | |
9362 | end | |
9363 | return {} | |
9364 | end | |
9365 | ||
9366 | local function quickMine(R) -- 17 | |
9367 | --[[ | |
9368 | mine valuable blocks from specified area | |
9369 | if R.up set or lava/water found, ceiling is formed | |
9370 | if R.down is set, or lava/water found layer is kept 1 block high | |
9371 | R.subChoice | |
9372 | 1 At mine area start, on the floor | |
9373 | 2 At mine area start, on the ceiling | |
9374 | 3 On floor, start 1 block ahead | |
9375 | 4 On ceiling, start 1 block ahead | |
9376 | 5 On floor diagonally to left" | |
9377 | ]] | |
9378 | local lib = {} | |
9379 | ||
9380 | function lib.refuel(direction) | |
9381 | if T:getWater(direction) then | |
9382 | T:refuel(1000, false) | |
9383 | end | |
9384 | end | |
9385 | ||
9386 | function lib.mine(R) | |
9387 | -- starts on ceiling | |
9388 | local isValuable, blockType | |
9389 | for i = 1, R.length do | |
9390 | local fillUp = R.up | |
9391 | local fillDown = R.down | |
9392 | isValuable, blockType = T:isValuable("down") | |
9393 | if isValuable then | |
9394 | T:dig("down") | |
9395 | elseif blockType:find("water") ~= nil then | |
9396 | fillDown = true | |
9397 | elseif blockType:find("lava") ~= nil then | |
9398 | lib.refuel("down") | |
9399 | fillDown = true | |
9400 | end | |
9401 | isValuable, blockType = T:isValuable("up") | |
9402 | if isValuable then | |
9403 | T:dig("up") | |
9404 | elseif blockType:find("water") ~= nil then | |
9405 | fillUp = true | |
9406 | elseif blockType:find("lava") ~= nil then | |
9407 | lib.refuel("up") | |
9408 | fillUp = true | |
9409 | end | |
9410 | --if not turtle.detectUp() and fillUp then | |
9411 | if fillUp then | |
9412 | T:fillVoid("up") | |
9413 | end | |
9414 | --if not turtle.detectDown() and fillDown then | |
9415 | if fillDown then | |
9416 | T:fillVoid("down") | |
9417 | end | |
9418 | if i < R.length then | |
9419 | T:forward(1) | |
9420 | end | |
9421 | end | |
9422 | end | |
9423 | ||
9424 | local outbound = true | |
9425 | ||
9426 | if R.subChoice == 1 then | |
9427 | T:up(1) | |
9428 | elseif R.subChoice == 3 then | |
9429 | T:go("U1F1") | |
9430 | elseif R.subChoice == 4 then | |
9431 | T:go("F1") | |
9432 | elseif R.subChoice == 5 then | |
9433 | T:go("U1R1 F1L1 F1") | |
9434 | end | |
9435 | ||
9436 | for w = 1, R.width do | |
9437 | lib.mine(R) | |
9438 | if w < R.width then | |
9439 | if outbound then | |
9440 | T:go("R1F1R1") | |
9441 | else | |
9442 | T:go("L1F1L1") | |
9443 | end | |
9444 | outbound = not outbound | |
9445 | end | |
9446 | if T:getFirstEmptySlot() == 0 then | |
9447 | T:dumpRefuse("forward", 1) | |
9448 | end | |
9449 | end | |
9450 | if outbound then | |
9451 | T:go("L1F"..R.width - 1 .."L1F"..R.length - 1) | |
9452 | else | |
9453 | T:go("R1F"..R.width - 1 .."R1") | |
9454 | end | |
9455 | ||
9456 | return {} | |
9457 | end | |
9458 | ||
9459 | local function quickMineCorridor(R) -- 16 | |
9460 | --[[ | |
9461 | R.subChoice | |
9462 | 1: At corridor start, on the floor | |
9463 | 2: At corridor start, on the ceiling | |
9464 | 3: On floor, start 1 block ahead | |
9465 | 4: On ceiling, start 1 block ahead | |
9466 | ]] | |
9467 | if R.subChoice == 2 then | |
9468 | T:down(1) | |
9469 | elseif R.subChoice == 3 then | |
9470 | T:forward(1) | |
9471 | elseif R.subChoice == 4 then | |
9472 | T:go("D1F1") | |
9473 | end | |
9474 | local width = R.width - 1 | |
9475 | local length = R.length - 1 | |
9476 | R.silent = true | |
9477 | R.length = length | |
9478 | createCorridor(R, true) -- put floor and ceiling for R.length, place torch at start | |
9479 | T:turnRight(1) | |
9480 | R.length = width | |
9481 | createCorridor(R, true) | |
9482 | T:turnRight(1) | |
9483 | R.length = length | |
9484 | createCorridor(R, true) | |
9485 | T:turnRight(1) | |
9486 | R.length = width | |
9487 | createCorridor(R, true) | |
9488 | T:turnRight(1) | |
9489 | ||
9490 | return {} | |
9491 | end | |
9492 | ||
9493 | - | -- assumes legacy tree farm with turtle on polished block 4 blocks from corner |
9493 | + | |
9494 | - | local message = "" |
9494 | + | |
9495 | - | R.treeSize = "single" |
9495 | + | |
9496 | -- if width = 1 | |
9497 | - | --local logType = "" |
9497 | + | |
9498 | - | --local startHeight = 0 |
9498 | + | |
9499 | ||
9500 | -- replace block with replaceWith ("" = any) | |
9501 | ||
9502 | -- move up | |
9503 | ||
9504 | --end | |
9505 | ||
9506 | -- move back to beginning | |
9507 | ||
9508 | -- else | |
9509 | - | if blockType:find("dirt") ~= nil then -- dirt found |
9509 | + | |
9510 | - | T:go("R1F1L1") |
9510 | + | |
9511 | ||
9512 | - | if blockType:find("dirt") ~= nil then |
9512 | + | |
9513 | - | R.treeSize = "double" |
9513 | + | |
9514 | -- for h = startAt, height, 1 do | |
9515 | - | T:go("L1F1 R1") |
9515 | + | |
9516 | - | else -- dirt NOT found where expected |
9516 | + | |
9517 | - | message = "Unable to determine position" |
9517 | + | |
9518 | -- move up | |
9519 | ||
9520 | - | blockType = T:getBlockType("forward") -- 1 block above dirt |
9520 | + | |
9521 | - | if blockType:find("log") ~= nil or blockType:find("sapling") ~= nil or blockType:find("propagule") ~= nil then |
9521 | + | |
9522 | - | local parts = T:getNames(blockType) |
9522 | + | |
9523 | - | if parts[2] == "dark" then |
9523 | + | |
9524 | - | R.logType = "dark_oak" |
9524 | + | |
9525 | ||
9526 | - | R.logType = parts[2] -- eg "oak" |
9526 | + | |
9527 | ||
9528 | - | if R.logType == "mangrove" then |
9528 | + | |
9529 | - | R.useBlockType = "mangrove_propagule" |
9529 | + | |
9530 | --end | |
9531 | - | R.useBlockType = parts[2].."_sapling" -- eg "oak_sapling" |
9531 | + | |
9532 | -- end | |
9533 | ||
9534 | - | T:down(1) -- facing dirt |
9534 | + | |
9535 | ||
9536 | - | return R, message |
9536 | + | |
9537 | ||
9538 | local function getTaskItemsList() | |
9539 | - | function lib.waitForGrowth(R) |
9539 | + | |
9540 | - | local pattern = R.treeSize --"single","double" |
9540 | + | |
9541 | - | local elapsed = 0 |
9541 | + | |
9542 | - | local facing = "left" |
9542 | + | |
9543 | - | local ready = {} |
9543 | + | |
9544 | - | ready.left = false |
9544 | + | |
9545 | - | ready.top = false |
9545 | + | |
9546 | - | ready.right = false |
9546 | + | |
9547 | - | ready.bottom = false |
9547 | + | |
9548 | - | if R.logType == "mangrove" then |
9548 | + | |
9549 | - | pattern = "mangrove" |
9549 | + | |
9550 | - | local facings = {"left", "top", "right", "bottom"} |
9550 | + | |
9551 | - | T:up(1) -- go up from dirt to sapling level |
9551 | + | |
9552 | - | while not ready.left or not ready.right or not ready.top or not ready.bottom do |
9552 | + | |
9553 | text[21] = {"1 chest (optional)"} -- Fell Tree | |
9554 | text[22] = {"320 stone", "4 polished stone"} -- Create treefarm | |
9555 | - | if blockType:find("propagule") == nil then -- either grown or deleted by roots |
9555 | + | |
9556 | - | ready[facings[i]] = true |
9556 | + | |
9557 | text[25] = {"width * length * 2 walls or fences", "torches (optional)", "4 barrels (optional)"} -- fence or wall a forest | |
9558 | text[26] = {"1 chest", " any saplings"} -- harvest and replant walled rectangle of natural forest | |
9559 | ||
9560 | - | if ready.left and ready.right and ready.top and ready.bottom then |
9560 | + | |
9561 | text[31] = {"64 stone","128 dirt (optional)", "4 water buckets","4 chests / barrels","1 sapling"} -- Create modular crop farm | |
9562 | text[32] = {"64 stone","128 dirt (optional)", "4 water buckets","5 chests/ barrels","1 sapling"} -- extend modular farm | |
9563 | - | sleep(15) |
9563 | + | |
9564 | - | elapsed = elapsed + 15 |
9564 | + | |
9565 | - | if elapsed / 60 > 15 then -- max 15 mins real time before farm is harvested |
9565 | + | |
9566 | ||
9567 | -- OBSIDIAN | |
9568 | text[41] = {"stone to cover area of obsidian"} -- Harvest obsidian | |
9569 | - | print("Waiting for mangrove growth "..elapsed / 60 .." minutes") |
9569 | + | |
9570 | - | print("Left = "..tostring(ready.left).. |
9570 | + | |
9571 | - | ", top = "..tostring(ready.top).. |
9571 | + | |
9572 | - | ", right = "..tostring(ready.right).. |
9572 | + | |
9573 | - | ", bottom = "..tostring(ready.bottom)) |
9573 | + | |
9574 | text[47] = {"448 stone, 145 ladders, 1 obsidian, 1 water bucket"} -- dragon water trap | |
9575 | text[48] = {"height * 4 stone","height * ladders", "1 trapdoor"} -- build end portal platform | |
9576 | - | --T:go("L1D1") |
9576 | + | |
9577 | - | T:turnLeft(1) -- face front |
9577 | + | |
9578 | text[51] = {"dirt or stone * length","torch (optional)"} -- single path | |
9579 | - | while not ready.left or not ready.right do |
9579 | + | |
9580 | - | T:up(1) -- go up from dirt to sapling level |
9580 | + | |
9581 | - | local blockType = T:getBlockType("forward") |
9581 | + | |
9582 | - | if blockType:find("log") ~= nil then |
9582 | + | |
9583 | - | ready[facing] = true |
9583 | + | |
9584 | text[57] = {"height * 10 stone","height * 4 + 2 soul sand, 2 water buckets"} -- Boat bubble lift | |
9585 | - | if pattern == "single" then |
9585 | + | |
9586 | - | --alternate between 2 trees, starts facing left |
9586 | + | |
9587 | text[61] = {"512 stone","1 slab"} -- 9x9 cube round spawner | |
9588 | - | if facing == "left" then |
9588 | + | |
9589 | - | facing = "right" |
9589 | + | |
9590 | - | elseif facing == "right" then |
9590 | + | |
9591 | - | facing = "left" |
9591 | + | |
9592 | text[64] = {"128 stone","2 water buckets","1 soul sand"} --Build bubble tower kill zone | |
9593 | - | blockType = T:getBlockType("forward") |
9593 | + | |
9594 | - | if blockType:find("log") ~= nil then |
9594 | + | |
9595 | - | ready[facing] = true |
9595 | + | |
9596 | text[66] = {"1856 stone, diorite etc (inc polished)","1 chest","10 empty buckets", | |
9597 | - | T:down(1) -- drop below sapling to dirt level |
9597 | + | "2 water buckets","192 fence","8 signs","3 ladder","2 soul sand"} -- build endermen observation tower |
9598 | - | elseif pattern == "double" then |
9598 | + | |
9599 | - | if ready.left and facing == "left" then-- tree on left now grown. check right |
9599 | + | |
9600 | - | T:go("R2F2") |
9600 | + | |
9601 | - | facing = "right" |
9601 | + | |
9602 | text[73] = {"No items required"} -- Clear wall height, length | |
9603 | - | blockType = T:getBlockType("forward") |
9603 | + | |
9604 | - | if blockType:find("log") ~= nil then |
9604 | + | |
9605 | - | ready[facing] = true |
9605 | + | |
9606 | text[77] = {"No items required"} -- Dig a trench | |
9607 | - | T:down(1) -- drop below sapling to dirt level |
9607 | + | |
9608 | text[79] = {"width * height Any material floor / ceiling"} -- floor or ceiling | |
9609 | text[710] = {"Blocks to add 'floor as you go'"} -- Direct control of movement | |
9610 | - | print("Farm type: "..pattern) |
9610 | + | |
9611 | - | print("Waiting for tree growth "..elapsed / 60 .." minutes") |
9611 | + | |
9612 | - | print("Left grown = "..tostring(ready.left)..", right grown = "..tostring(ready.right)) |
9612 | + | |
9613 | - | if not ready.left or not ready.right then |
9613 | + | |
9614 | - | sleep(15) |
9614 | + | |
9615 | - | elapsed = elapsed + 15 |
9615 | + | |
9616 | - | if pattern == "single" and elapsed / 60 > 10 then -- max 10 mins real time before farm is harvested |
9616 | + | |
9617 | text[86] = {"Full inventories of sand or stone"} -- Ocean monument utilities | |
9618 | - | elseif pattern == "double" and elapsed / 60 > 15 then -- max 15 mins real time before farm is harvested |
9618 | + | |
9619 | text[88] = {"No items required"} -- clear water plants | |
9620 | text[89] = {"water buckets / buckets"} -- convert flowing water to source | |
9621 | text[810] = {"6 buckets","slabs to cover area"} -- create sloping water | |
9622 | ||
9623 | -- BUILDING and MINECART | |
9624 | - | -- growth complete |
9624 | + | |
9625 | - | if pattern == "single" then |
9625 | + | |
9626 | - | if facing == "right" then |
9626 | + | |
9627 | text[94] = {"length * width * height stairs", "length * slabs"} -- Build a pitched roof | |
9628 | text[95] = {"1 block of choice","1 redstone torch"} -- place redstone torch under current block | |
9629 | text[96] = {"1 block of choice","1 redstone torch"} -- place redstone torch on upward slope | |
9630 | text[97] = {"height x block of choice","height/3 x redstone torch"} -- build downward slope | |
9631 | - | --T:go("F1R1 F3R1") -- facing first dirt |
9631 | + | |
9632 | - | T:go("F1R1 F1R1") -- facing first dirt |
9632 | + | |
9633 | - | elseif pattern == "double" then -- assume on right side |
9633 | + | |
9634 | - | if facing == "right" then |
9634 | + | |
9635 | - | T:go("R1F1 R1F4 R1") |
9635 | + | |
9636 | -- display help about selected task | |
9637 | - | T:go("L1F1 R1F2 R1") |
9637 | + | |
9638 | --[[This line of text = 39 characters]] | |
9639 | - | elseif pattern == "mangrove" then |
9639 | + | |
9640 | - | T:go("D2F6 U1F1 R1F6 R1F1 U1") |
9640 | + | |
9641 | info = {} | |
9642 | - | -- ends facing dirt at base of first tree |
9642 | + | |
9643 | - | -- no return needed, function exit so trees are grown |
9643 | + | |
9644 | table.insert(info.main, | |
9645 | [[ ~lightGray~MINING:~white~ | |
9646 | - | function lib.watchFarm(R) |
9646 | + | |
9647 | - | -- rotate to check if dirt on both sides |
9647 | + | |
9648 | - | -- R.subChoice == 1: 16 single trees, 2 = 4 doubles |
9648 | + | |
9649 | - | if R.logType ~= "mangrove" then |
9649 | + | |
9650 | - | R.treeSize = "single" |
9650 | + | |
9651 | - | T:turnRight(2) -- if no dirt then on 4 x doubles |
9651 | + | |
9652 | - | if T:getBlockType("forward") == "" then |
9652 | + | |
9653 | - | R.treeSize = "double" |
9653 | + | |
9654 | the fuel and time) | |
9655 | - | T:saveToLog("lib.watchFarm: R.treeSize set to '"..R.treeSize.."'") |
9655 | + | |
9656 | - | T:turnLeft(2) -- face lower left double dirt |
9656 | + | |
9657 | table.insert(info.main, | |
9658 | - | lib.waitForGrowth(R) |
9658 | + | |
9659 | Fell Tree can be used in Nether as well | |
9660 | - | return R |
9660 | + | |
9661 | Create a simple 16 single tree farm | |
9662 | or 4 double size (Dark oak or any type) | |
9663 | - | function lib.harvestSingle(direction, moves) |
9663 | + | |
9664 | - | -- if direction == "up": starting inside tree on dirt at dirt level |
9664 | + | |
9665 | - | T:saveToLog("lib.harvestSingle('"..direction.."', moves = "..moves) |
9665 | + | |
9666 | ~green~Forest can be harvested and replanted. | |
9667 | - | while turtle.detectUp() do |
9667 | + | |
9668 | ||
9669 | ]]) | |
9670 | table.insert(info.main, | |
9671 | - | else -- direction = "down", but could be mid-tree |
9671 | + | |
9672 | - | local movesUp = 0 |
9672 | + | |
9673 | - | while turtle.detectUp() do |
9673 | + | |
9674 | or rectangular pattern.~lime~ | |
9675 | - | movesUp = movesUp + 1 |
9675 | + | |
9676 | turtle, which must be equipped with a | |
9677 | - | T:down(movesUp) |
9677 | + | |
9678 | - | T:down(moves) |
9678 | + | |
9679 | corner of each module. | |
9680 | Double chests store produce and seeds. | |
9681 | ]]) | |
9682 | table.insert(info.main, | |
9683 | - | function lib.harvestSingleRow() |
9683 | + | |
9684 | - | -- start next to tree/dirt |
9684 | + | |
9685 | lava areas safely.~pink~ | |
9686 | - | local moves = lib.harvestSingle("up", 0) |
9686 | + | |
9687 | - | T:go("F2") |
9687 | + | |
9688 | - | lib.harvestSingle("down", moves) |
9688 | + | |
9689 | - | T:go("F2") |
9689 | + | |
9690 | - | moves = lib.harvestSingle("up", 0) |
9690 | + | |
9691 | - | T:go("F2") |
9691 | + | |
9692 | - | lib.harvestSingle("down", moves) |
9692 | + | |
9693 | Minecart end portal stations built. | |
9694 | ]]) | |
9695 | - | function lib.harvestDouble() |
9695 | + | |
9696 | - | T:forward(1) -- dig dirt, move into left (S) corner |
9696 | + | |
9697 | Can be used in Nether and End.~lightGray~ | |
9698 | - | while turtle.detectUp() do |
9698 | + | |
9699 | - | turtle.dig() |
9699 | + | |
9700 | - | turtle.digUp() |
9700 | + | |
9701 | at the same time.~blue~ | |
9702 | Build a water canal with towpath.~cyan~ | |
9703 | Build a super-fast ice canal.~brown~ | |
9704 | - | turtle.dig() |
9704 | + | |
9705 | - | T:go("R1F1L1") -- move to right corner |
9705 | + | |
9706 | 1 block lower each time | |
9707 | - | turtle.dig() |
9707 | + | |
9708 | - | turtle.digDown() |
9708 | + | |
9709 | [[ ~lightGray~SPAWNER FARMS:~brown~ | |
9710 | Tools to create mob farms round | |
9711 | - | turtle.dig() |
9711 | + | |
9712 | - | T:go("F1L1F1R1") -- move to left corner (N) |
9712 | + | |
9713 | uses rail collection.~cyan~ | |
9714 | Choice of bubble lift mob dropper | |
9715 | - | --T:setUseLog(true, "treeFarmLog.txt", true) -- T:setUseLog(use, filename, delete) |
9715 | + | |
9716 | - | --dbug = true -- set dbug flag |
9716 | + | |
9717 | built >128 above ground: is ~red~expensive.~gray~ | |
9718 | Re-spawns new mobs when used.~red~ | |
9719 | - | -- if on modem, R.networkFarm has already been set |
9719 | + | |
9720 | - | T:saveToLog("harvestTreeFarm(R) R.networkFarm = "..tostring(R.networkFarm)) |
9720 | + | |
9721 | table.insert(info.main, | |
9722 | - | if R.networkFarm then |
9722 | + | |
9723 | - | local message = network.loadStorageLists() -- initialises or creates lists of where an item can be found: GLOBAL LISTS! |
9723 | + | |
9724 | - | if message ~= nil then return {message} end |
9724 | + | |
9725 | - | network.emptyInventory(R, {"sapling", "propagule", "dirt"}, {"all"}, true) |
9725 | + | |
9726 | Clear hollow and~orange~solid structures.~brown~ | |
9727 | Dig a trench.~gray~ | |
9728 | - | if turtle.getFuelLevel() < turtle.getFuelLimit() / 2 then |
9728 | + | |
9729 | - | local turtleSlot, turtleCount = network.getItemFromNetwork("chest", "log", 16) |
9729 | + | |
9730 | - | if turtleSlot > 0 then |
9730 | + | |
9731 | - | if turtle.craft() then |
9731 | + | |
9732 | ||
9733 | - | T:saveToLog("harvestTreeFarm(R) R.networkFarm = "..tostring(R.networkFarm)) |
9733 | + | |
9734 | table.insert(info.main, | |
9735 | [[ ~blue~WATER AND LAVA TOOLS:~white~ | |
9736 | Used to drain ocean monuments and | |
9737 | shipwrecks. Can also be used to make | |
9738 | - | if R.networkFarm then -- monitor trees for growth |
9738 | + | |
9739 | - | if R.logType == "mangrove" then |
9739 | + | |
9740 | Destructive draining uses solid block | |
9741 | - | T:place("dirt", "up") |
9741 | + | |
9742 | - | T:go("F6x2U1L1") -- move under dirt covering, clear roots from hopper, move level with dirt, face left |
9742 | + | |
9743 | damaging structures.~lightBlue~ | |
9744 | - | T:go("F4R1") -- either in between 2 trees or in gap between double trees at dirt level |
9744 | + | |
9745 | - | if turtle.detect() then -- single trees, move between 1st and 2nd rows |
9745 | + | |
9746 | - | T:go("R1F1 R1F2 R1F1 L1") |
9746 | + | |
9747 | - | else -- using double trees |
9747 | + | |
9748 | - | T:go("R2F1") |
9748 | + | |
9749 | - | if not turtle.detect() then |
9749 | + | |
9750 | - | return {"Unable to determine position"} |
9750 | + | |
9751 | ~orange~Used to build diagonal uphill slope~brown~ | |
9752 | and downhill slope for placing | |
9753 | 45 degree rail tracks.~red~ | |
9754 | - | R = lib.watchFarm(R) -- wait for trees to grow, then start harvest |
9754 | + | |
9755 | rails when above ground level (viaduct) | |
9756 | - | --logType, startHeight, R = lib.initialise(R) -- possible ID tree type + move to correct position 1 above dirt |
9756 | + | |
9757 | - | R, message = lib.initialise(R) -- possible ID tree type + move to correct position next to first dirt |
9757 | + | |
9758 | - | if message ~= "" then |
9758 | + | |
9759 | - | return{message} |
9759 | + | |
9760 | table.insert(info.main, | |
9761 | [[ ~yellow~MEASURING TOOLS: | |
9762 | - | T:saveToLog("R.networkFarm = "..tostring(R.networkFarm)..", logType = "..R.logType..", treeSize = "..R.treeSize) |
9762 | + | |
9763 | - | -- different clearing for different trees: |
9763 | + | |
9764 | - | -- double spruce and jungle: staight up/down or small |
9764 | + | |
9765 | - | if R.logType == "mangrove" then |
9765 | + | |
9766 | - | clearRectangle({width = 13, length = 13, up = true, down = true }) |
9766 | + | |
9767 | - | T:go("U2F2 R1F2L1") |
9767 | + | |
9768 | - | clearSolid({width = 9, length = 9, height = 18, direction ="up"}) |
9768 | + | |
9769 | - | T:go("D3R1 F4R1 F3R2") |
9769 | + | |
9770 | - | network.emptyInventory(R, {"sapling", "propagule", "dirt", "crafting"}, {"all"}, true) |
9770 | + | |
9771 | - | elseif R.logType == "birch" or R.logType == "spruce" or R.logType == "jungle" then -- use column harvest |
9771 | + | |
9772 | - | if R.treeSize == "single" then |
9772 | + | |
9773 | - | lib.harvestSingleRow() |
9773 | + | |
9774 | - | T:go("F1R1F2R1") |
9774 | + | |
9775 | - | lib.harvestSingleRow() |
9775 | + | |
9776 | - | T:go("F1L1F2L1") |
9776 | + | |
9777 | - | lib.harvestSingleRow() |
9777 | + | |
9778 | - | T:go("F1R1F2R1") |
9778 | + | |
9779 | - | lib.harvestSingleRow() |
9779 | + | |
9780 | - | if R.networkFarm then |
9780 | + | |
9781 | - | T:go("F1R1 F3L1 F3R2") |
9781 | + | |
9782 | - | network.emptyInventory(R, {"sapling", "propagule", "dirt", "crafting"}, {"all"}, true) |
9782 | + | |
9783 | ~lightGray~| | | | | | | |
9784 | - | T:go("F1R1 F6L1 F3R2") |
9784 | + | |
9785 | ||
9786 | ]]-- Ladder up/down | |
9787 | - | lib.harvestDouble() |
9787 | + | |
9788 | - | T:go("F3") |
9788 | + | |
9789 | - | lib.harvestDouble() |
9789 | + | |
9790 | - | T:go("R1F4") |
9790 | + | |
9791 | - | lib.harvestDouble() |
9791 | + | |
9792 | - | T:go("R1F4") |
9792 | + | |
9793 | - | lib.harvestDouble() |
9793 | + | |
9794 | - | if R.networkFarm then |
9794 | + | |
9795 | - | T:go("F1R1 F3L1 F3R2") |
9795 | + | |
9796 | - | network.emptyInventory(R, {"sapling", "propagule", "dirt", "crafting"}, {"all"}, true) |
9796 | + | |
9797 | ||
9798 | - | T:go("F1R1 F6L1 F3R2") |
9798 | + | |
9799 | ]] -- Stairs up/down | |
9800 | info.sub[13] = | |
9801 | - | else -- use cube harvest, including mangrove |
9801 | + | |
9802 | - | local size = 10 |
9802 | + | |
9803 | - | local start = "L1F1 L1F1 R2" |
9803 | + | |
9804 | - | local finish = "R1F1 R1F3 R2" |
9804 | + | |
9805 | - | if R.logType == "acacia" then |
9805 | + | |
9806 | - | size = 12 |
9806 | + | |
9807 | - | start = "L1F2 L1F2 R2" |
9807 | + | |
9808 | - | finish = "R1F2 R1F2 R2" |
9808 | + | |
9809 | - | elseif R.logType == "cherry" then |
9809 | + | |
9810 | - | size = 14 |
9810 | + | |
9811 | - | start = "L1F3 L1F3 R2" |
9811 | + | |
9812 | - | finish = "R1F3 R1F1 R2" |
9812 | + | |
9813 | else | |
9814 | - | T:go("U1F1") -- into first log at base of tree |
9814 | + | |
9815 | - | clearRectangle({width = 7, length = 7, up = true, down = true}) |
9815 | + | |
9816 | - | --T:go("L1F2 L1F2 R2") -- rect size 12 |
9816 | + | |
9817 | - | --T:go("L1F1 L1F1 R2") -- rect size 10 |
9817 | + | |
9818 | - | T:go(start) |
9818 | + | |
9819 | - | local height = 0 |
9819 | + | |
9820 | - | local pastLogCount = -1 |
9820 | + | |
9821 | - | local currentLogCount = lib.getLogCount() |
9821 | + | |
9822 | - | --while currentLogCount ~= pastLogCount do |
9822 | + | |
9823 | - | while currentLogCount - pastLogCount > 5 do -- ony continue if at least 5 logs harvested last round |
9823 | + | |
9824 | - | T:up(3) |
9824 | + | |
9825 | ~lightGray~| | | | | | ~red~^ = Turtle facing forward | |
9826 | - | pastLogCount = currentLogCount -- 0 when loop starts |
9826 | + | |
9827 | - | --clearRectangle({width = 12, length = 12, up = true, down = true}) |
9827 | + | |
9828 | - | clearRectangle({width = size, length = size, up = true, down = true}) |
9828 | + | |
9829 | - | currentLogCount = lib.getLogCount() -- eg 20 logs from first round |
9829 | + | |
9830 | - | end |
9830 | + | |
9831 | - | T:down(height + 1) |
9831 | + | |
9832 | - | --T:go("R1F2 R1F2 R2") -- on polished stone rect size 12 |
9832 | + | |
9833 | - | --T:go("R1F1 R1F3 R2") -- on polished stone rect size 10 |
9833 | + | |
9834 | - | T:go(finish) |
9834 | + | |
9835 | - | if R.networkFarm then |
9835 | + | |
9836 | - | T:go("R1F3 L1") -- on modem |
9836 | + | |
9837 | - | network.emptyInventory(R, {"sapling", "propagule", "dirt", "crafting"}, {"all"}, true) |
9837 | + | |
9838 | | |~blue~^~brown~|L|~blue~^~lightGray~| | ~brown~L = ladder | |
9839 | ~lightGray~| | | | | | ~blue~^ = Turtle facing forward | |
9840 | ~lightGray~| | | | | | ~blue~^ = Bubble column above | |
9841 | - | return {} -- if player initiated, stops here. If R.auto then returns to plantTreeFarm() |
9841 | + | |
9842 | ]] -- single column bubble lift | |
9843 | info.sub[16] = | |
9844 | [[~yellow~Place me as below: | |
9845 | 1. On ~blue~floor ~yellow~(feet height) | |
9846 | 2. On ~lime~ceiling ~yellow~(eye height) | |
9847 | ||
9848 | ~lightGray~B|B|B|B|B|B|B ~yellow~W I D T H | |
9849 | ~lightGray~B| | | | | |B ~orange~L | |
9850 | ~lightGray~B| |B|B|B| |B ~orange~E | |
9851 | ~lightGray~B| |B|B|B| |B ~orange~N | |
9852 | ~lightGray~B| |B|B|B| |B ~orange~G | |
9853 | ~lightGray~B|~red~^~lightGray~| | | | |B ~red~^~lightGray~ = Turtle ~orange~T | |
9854 | ~lightGray~B|~cyan~P~lightGray~|B|B|B|B|B ~cyan~P~lightGray~ = Player ~orange~H | |
9855 | ]] -- quick corridor system | |
9856 | info.sub[17] = | |
9857 | [[~yellow~~yellow~Place me as below: | |
9858 | 1. On ~blue~floor ~yellow~(feet height) | |
9859 | 2. On ~lime~ceiling ~yellow~(eye height) | |
9860 | ~lightGray~B|B|B|B|B|B|B | |
9861 | B| | | | | |B | |
9862 | B| |B|B|B| |B | |
9863 | B| |B|B|B| |B | |
9864 | B| |~lime~^~lightGray~|B|B| |B | |
9865 | B|~red~^~lightGray~|~magenta~^~lightGray~| | | |B ~white~^~lightGray~ = turtle | |
9866 | B|~cyan~P~lightGray~|B|B|B|B|B ~cyan~P~lightGray~ = Player | |
9867 | ~yellow~Note colour of ~white~^~yellow~ matches next screen-> | |
9868 | ]] -- quick mine | |
9869 | info.sub[18] = | |
9870 | [[~yellow~Place me level -59 / 5 on the floor to | |
9871 | expose bedrock ~red~(slow and inefficient) | |
9872 | ||
9873 | ~lightGray~| | | |B| |B| ~yellow~W I D T H | |
9874 | ~lightGray~|B| | | | | |B ~orange~L | |
9875 | ~lightGray~| | | |B|B| | ~orange~E | |
9876 | ~lightGray~| | |B| | |B| ~orange~N | |
9877 | ~lightGray~|B| | | |B| | ~orange~G | |
9878 | ~lightGray~| | | | | | |B ~orange~T | |
9879 | ~lightGray~|~red~^~lightGray~| | | |B| |B ~red~^~lightGray~ = Turtle ~orange~H | |
9880 | ]] -- mine all blocks to bedrock pre 1.12 | |
9881 | info.sub[19] = | |
9882 | [[~yellow~Place me on the end wall of a disused | |
9883 | mine in the centre block, 1 block above | |
9884 | the floor. | |
9885 | Provide a ~cyan~diamond ~yellow~sword for | |
9886 | harvesting string from spider webs~lightGray~ | |
9887 | ||
9888 | ~gray~------- - = Ceiling | |
9889 | ~lightGray~| | | | | |
9890 | | |~red~T~lightGray~| | ~red~T = Turtle (facing wall) | |
9891 | ~lightGray~| | | | | |
9892 | ~gray~------- - = Floor | |
9893 | ]] -- salvage mineshaft | |
9894 | info.sub[21] = | |
9895 | [[~yellow~Place me as below. | |
9896 | ~brown~Chest ~yellow~ONLY required if ~blue~0 ~yellow~fuel | |
9897 | ||
9898 | Plan view: | |
9899 | ||
9900 | ~green~ | | | | | |
9901 | ~green~ | |~lime~T~green~| | ~lime~T = Tree | |
9902 | ~green~ | |~red~^~green~| | ~red~^ = Turtle | |
9903 | ~green~ | | | | | |
9904 | ||
9905 | ||
9906 | ||
9907 | ]] -- Fell Tree | |
9908 | info.sub[22] = | |
9909 | [[~yellow~Place me on ground as below ~red~^ | |
9910 | ~lime~|*|~blue~ | | | | | | ~green~or |*|~blue~ | | ~brown~|D| |D| | |
9911 | ~lime~|*|~blue~ | | ~brown~|D|D|~blue~ | ~green~or |*|~blue~ | | | | | | | |
9912 | ~lime~|*|~blue~ | | ~brown~|D|D|~blue~ | ~green~or |*|~blue~ | | ~brown~|D| |D| | |
9913 | ~lime~|*|~blue~ | | | | | | ~green~or |*|~blue~ | | | | | | | |
9914 | ~lime~|*|~blue~ | | | | | | ~green~or |*|~blue~ | | | | | | | |
9915 | ~lime~|*|~blue~ | | | | | | ~green~or |*|~blue~ | | | | | | | |
9916 | ~lime~|~red~^~lime~|*|*|*|~blue~M~lime~|*| | ~green~or |~red~^~green~|*|*|*|~blue~M~green~|*|*| | |
9917 | ~lime~4 ~brown~double ~green~ or 16 ~brown~single | |
9918 | ~brown~D = Dirt, ~red~^ = Turtle, ~blue~M = Marker stone | |
9919 | ]] -- Create treefarm | |
9920 | info.sub[23] = | |
9921 | [[~yellow~Place me on ground as below ~red~^ | |
9922 | ~lime~|*|~blue~ | | | | | | ~green~or |*|~blue~ | | ~brown~|D| |D| | |
9923 | ~lime~|*|~blue~ | | ~brown~|D|D|~blue~ | ~green~or |*|~blue~ | | | | | | | |
9924 | ~lime~|*|~blue~ | | ~brown~|D|D|~blue~ | ~green~or |*|~blue~ | | ~brown~|D| |D| | |
9925 | ~lime~|*|~blue~ | | | | | | ~green~or |*|~blue~ | | | | | | | |
9926 | ~lime~|*|~blue~ | | | | | | ~green~or |*|~blue~ | | | | | | | |
9927 | ~lime~|*|~blue~ | | | | | | ~green~or |*|~blue~ | | | | | | | |
9928 | ~lime~|*|*|*|*|~red~^~lime~|*| | ~green~or |*|*|*|*|~red~^~green~|*|*| | |
9929 | ~green~4 ~brown~double ~green~ or 16 ~brown~single | |
9930 | ~brown~D = dirt,~red~^ = Turtle, ~yellow~Max 16 saplings | |
9931 | Mixed OK. ~lime~Group 4 for double trees | |
9932 | ]] -- Plant treefarm / Harvest treefarm | |
9933 | info.sub[24] = info.sub[23] | |
9934 | info.sub[25] = | |
9935 | [[~yellow~Place me at ~red~^ | |
9936 | ||
9937 | ~lightGray~|F|F|F|F|F|F|F| F = Fence or Wall | |
9938 | ~lightGray~|F|~brown~B~lime~| | | |~brown~B~lightGray~|F| ~brown~B = Barrel (corners) | |
9939 | ~lightGray~|F|~lime~ | | | | ~lightGray~|F| | |
9940 | ~lightGray~|F|~lime~ | | | |~cyan~T~lightGray~|F| ~cyan~T = Tree | |
9941 | ~lightGray~|F|~lime~ |~cyan~T~lime~| | | ~lightGray~|F| | |
9942 | ~lightGray~|F|~lime~ | | | | ~lightGray~|F| | |
9943 | ~lightGray~|F|~brown~B~lime~| |~cyan~T~lime~| |~brown~B~lightGray~|F| | |
9944 | ~lightGray~|~red~^~lightGray~|F|F|F|F|F|F| ~red~^ = Turtle | |
9945 | ~yellow~Fence/Wall follows land contours | |
9946 | ]] -- | |
9947 | info.sub[26] = | |
9948 | [[~yellow~A rectangular walled area of forest: | |
9949 | Place me at ~red~^ | |
9950 | ||
9951 | ~lightGray~|F|F|F|F|F|F|F| F = Fence or wall | |
9952 | ~lightGray~|F|~brown~B~lime~| | | |~brown~B~lightGray~|F| ~brown~B = Barrel (corners) | |
9953 | ~lightGray~|F|~lime~ | | | | ~lightGray~|F| | |
9954 | ~lightGray~|F|~lime~ | | | |~cyan~T~lightGray~|F| ~cyan~T = Tree | |
9955 | ~lightGray~|F|~lime~ |~cyan~T~lime~| | | ~lightGray~|F| | |
9956 | ~lightGray~|F|~lime~ | | | | ~lightGray~|F| | |
9957 | ~lightGray~|F|~red~^~lime~| |~cyan~T~lime~| |~brown~B~lightGray~|F| ~red~^ = Turtle ~brown~(on Barrel) | |
9958 | ~lightGray~|F|F|F|F|F|F|F| | |
9959 | ||
9960 | ]] -- manage walled forest | |
9961 | info.sub[31] = | |
9962 | [[~yellow~Place me on the ground as below ~red~^ | |
9963 | ||
9964 | ~lightGray~|*|~green~ | | | | | | | | ~lightGray~* = Wall | |
9965 | ~lightGray~|*|~green~ | | | | | | | | | |
9966 | ~lightGray~|*|~green~ | | | | | | | | | |
9967 | ~lightGray~|*|~green~ | | | | | | | | | |
9968 | ~lightGray~|*|~green~ | | | | | | | | | |
9969 | ~brown~|B|B~green~| | | | | | | | ~brown~B = Barrel or Chest | |
9970 | ~brown~|B|~blue~W~green~| | | | | | | | ~blue~W = Water | |
9971 | ~lime~|~red~^~lime~|~brown~B|B|~lightGray~*|*|*|*|*|*| ~red~^ = Turtle | |
9972 | ~yellow~ Size = 13 x 13 | |
9973 | ]] -- Create modular crop farm | |
9974 | info.sub[32] = | |
9975 | [[~yellow~Place next to the tree as below ~red~^ | |
9976 | ||
9977 | ~lightGray~|*|~green~ | | | | | | | | ~lightGray~* = Wall | |
9978 | ~lightGray~|*|~green~ | | | | | | | | | |
9979 | ~lightGray~|*|~green~ | | | | | | | | | |
9980 | ~lightGray~|*|~green~ | | | | | | | | | |
9981 | ~lightGray~|*|~green~ | | | | | | | | ~brown~B = Barrel or Chest | |
9982 | ~brown~|B|B~green~| | | | | | | | ~blue~W = Water | |
9983 | ~brown~|B|~blue~W~green~| | | | | | | | ~orange~S = Sapling or Tree | |
9984 | ~orange~|S|~red~^~brown~|B|~lightGray~*|*|*|*|*|*| ~red~^ = Turtle | |
9985 | ~yellow~ Size = 13 x 13 | |
9986 | ]] -- Extend farm | |
9987 | info.sub[33] = | |
9988 | [[~yellow~Place as below (2 choices) ~blue~> ~yellow~or ~red~< | |
9989 | ||
9990 | ~lightGray~|*|~green~ | | | | | | | | ~lightGray~* = Wall | |
9991 | ~lightGray~|*|~green~ | | | | | | | | | |
9992 | ~lightGray~|*|~green~ | | | | | | | | | |
9993 | ~lightGray~|*|~green~ | | | | | | | | ~brown~B = Barrel or Chest | |
9994 | ~lightGray~|*|~green~ | | | | | | | | ~blue~> = turtle on Water | |
9995 | ~brown~|B|B~green~| | | | | | | | C = Crop (first) | |
9996 | ~brown~|B|~blue~>~green~|C| | | | | | | ~orange~S = Sapling or Tree | |
9997 | ~orange~|S|~red~<~brown~|B|~lightGray~*|*|*|*|*|*| ~red~< = Turtle on Chest | |
9998 | ~yellow~Options to harvest or manage to follow. | |
9999 | ]] -- Manual harvest and auto setup | |
10000 | info.sub[34] = | |
10001 | [[~yellow~Build a ~brown~fence ~yellow~or ~lightGray~wall ~yellow~to chosen length. | |
10002 | ||
10003 | Turtle goes ~orange~BACKWARDS ~yellow~when started. | |
10004 | ||
10005 | Start: length = 6, Turtle facing right | |
10006 | ||
10007 | ~lightGray~| |~red~>~lightGray~| | | | | | | ~red~> = Turtle | |
10008 | ||
10009 | Finish: | |
10010 | ||
10011 | ~lightGray~| |F|F|F|F|F|F| | F = Fence or Wall | |
10012 | ]] -- build fence or wall | |
10013 | info.sub[35] = | |
10014 | [[~yellow~Build a ~brown~fence ~yellow~or ~lightGray~wall ~yellow~ | |
10015 | rectangular area. | |
10016 | ||
10017 | ~lightGray~| | | | | | | | ~brown~F = Fence or Wall | |
10018 | ~lightGray~| ~brown~|F|F|F|F|F~lightGray~| | | |
10019 | ~lightGray~| ~brown~|F| | | |F~lightGray~| | | |
10020 | ~lightGray~| ~brown~|F| | | |F~lightGray~| | | |
10021 | ~lightGray~| ~brown~|F| | | |F~lightGray~| | | |
10022 | ~lightGray~| |~red~^~brown~|F|F|F|F| | ~red~^ = Turtle | |
10023 | ~lightGray~| | | | | | | | | |
10024 | ||
10025 | ]] -- build rectangular fence or wall | |
10026 | info.sub[41] = | |
10027 | [[~yellow~Place me on any block on the left | |
10028 | side facing the obsidian field. | |
10029 | ||
10030 | ~gray~|O|O|O|O|O| O = Obsidian | |
10031 | |O|O|O|O|O| | |
10032 | |O|O|O|O|O| | |
10033 | |O|O|O|O|O| | |
10034 | |~red~^~gray~|O|O|O|O| ~red~^ = Turtle | |
10035 | |~red~^~gray~| | | | | | |
10036 | ||
10037 | ]] -- Harvest obsidian | |
10038 | info.sub[42] = | |
10039 | [[~yellow~Place me on the ground as below ~red~> ~pink~^ | |
10040 | ~yellow~Start ~red~> ~yellow~(facing right) or ~pink~^ ~yellow~ahead | |
10041 | ||
10042 | ~lightGray~| |~red~>~lightGray~|O|O|*| | | |*|O|O|*| face view | |
10043 | ~pink~^~lightGray~ |O|~purple~+ +~lightGray~|O| | |
10044 | |O|~purple~+ +~lightGray~|O| | |
10045 | ~yellow~Result (plan) ~lightGray~|O|~purple~+ +~lightGray~|O| | |
10046 | ~lightGray~| |O|O|O|O| | | |*|O|O|*| | |
10047 | ~green~--------- ground | |
10048 | ~yellow~width=4, ~orange~height=5 ~red~(frame size) | |
10049 | ]] -- build Nether portal | |
10050 | info.sub[43] = info.sub[42] -- Demolish Nether portal | |
10051 | info.sub[44] = | |
10052 | [[~yellow~Press F3+G for chunk boundaries | |
10053 | Netherite stripmine plan view | |
10054 | ||
10055 | ~lightGray~|*|*|*~lime~N~lightGray~*|*|*| | |
10056 | ~lightGray~|*|*|*~lime~|~lightGray~*|*|*| ~lime~-| = Chunk Boundaries | |
10057 | ~lightGray~|*|~red~^~lightGray~|*~lime~|~lightGray~*|~red~^~lightGray~|*| ~red~^ = Turtle | |
10058 | ~lime~W*-*-*~blue~+~lime~*-*-*E ~blue~+ = Boundaries junction | |
10059 | ~lightGray~|*|*|*~lime~|~lightGray~*|*|*| | |
10060 | ~lightGray~|*|*|*~lime~|~lightGray~*|*|*| ~yellow~North of WE | |
10061 | ~lightGray~|*|*|*~lime~S~lightGray~*|*|*| ~yellow~1 block from NS | |
10062 | Most generate close to chunk boundaries | |
10063 | ]] -- Netherite stripping | |
10064 | info.sub[45] = | |
10065 | [[~yellow~Place me on the ground ~red~<~yellow~ facing ~red~West. | |
10066 | ||
10067 | ~lime~x | |
10068 | ~lightGray~N | |
10069 | ~lime~a~lightGray~ -1 | | | | | |
10070 | ~lime~x~lightGray~ 0 ~red~W~lightGray~| |~red~<~lightGray~| |E ~red~< = Turtle | |
10071 | ~lime~i~lightGray~ 1 | | | | | |
10072 | ~lime~s~lightGray~ S | |
10073 | ~green~z axis ~lightGray~-1 0 1 | |
10074 | ||
10075 | Centre of the dragon arena ~lime~X = 0, ~green~Z = 0 | |
10076 | ~yellow~ facing ~red~West | |
10077 | ]] -- Find dragon tower centres | |
10078 | info.sub[46] = | |
10079 | [[~yellow~Place turtle in ceiling facing endstone | |
10080 | ||
10081 | Plan view Side view | |
10082 | ~gray~ |*|*|*|*|*| | |
10083 | |*| |*|*|*|*|*| | |
10084 | |*|*|*| |*|*|*|*|*| | |
10085 | |*|*|*|*|*| |*|*|*|*|*| * ~lightGray~= Obsidian | |
10086 | ~gray~|*|*|~yellow~E~gray~|*|*| |*|*|*|*|*| ~yellow~E ~lightGray~= Endstone | |
10087 | ~gray~ |*|~red~^~gray~|*| |*|*|~red~T~gray~|*|*|~red~ ^T ~lightGray~= Turtle | |
10088 | ~gray~ |*| |*|*| |*|*| | |
10089 | |*|*| |*|*| | |
10090 | ]] -- deactivate dragon tower | |
10091 | info.sub[47] = | |
10092 | [[~yellow~Place turtle on the ground at 100,49,0 | |
10093 | ||
10094 | |*|*|*|*|*|*|*|*|*| ~lightGray~= Dragon Island | |
10095 | ||
10096 | ||
10097 | ~yellow~ Facing WEST | |
10098 | ~gray~ |*|*|*|*|*| * ~lightGray~= Obsidian plate | |
10099 | ~gray~ |*|*|*|*|*| | |
10100 | ~yellow~ S ~gray~|*|*|~red~T~gray~|*|*| ~yellow~N ~red~T ~lightGray~= Turtle | |
10101 | ~gray~ |*|*|*|*|*| | |
10102 | |*|*|*|*|*| | |
10103 | ~yellow~ E]] -- build dragon water trap | |
10104 | info.sub[48] = | |
10105 | [[~yellow~Place turtle under end world portal | |
10106 | ||
10107 | ~gray~ |B| B ~lightGray~= Bedrock | |
10108 | ~gray~ |B|B|B| | |
10109 | ~purple~|P| P ~lightGray~= Portal | |
10110 | ~gray~ |B|B|B| | |
10111 | |B| | |
10112 | ~green~| | |
10113 | ~green~| ~lime~Height measured first | |
10114 | ~green~| | |
10115 | ~red~ T T ~lightGray~= Turtle | |
10116 | ~yellow~ |*|*|*|*|*|*| ~red~Inventory AFTER height | |
10117 | ]] -- build end portal minecart | |
10118 | ||
10119 | info.sub[491] = | |
10120 | [[~yellow~Place turtle <64 blocks from shulker | |
10121 | Directly below or 1 block in front | |
10122 | ~lightGray~|*|*|*|*|*|*|*| | |
10123 | ~gray~> ~lime~S ~gray~< > T < = kill positions | |
10124 | ~gray~T | |
10125 | ||
10126 | ||
10127 | ||
10128 | ~red~> T < Attacks ahead / above | |
10129 | ~lightGray~|*|*|*|*|*|*|*| | |
10130 | ||
10131 | ~red~> T <~lightGray~ = Turtle ~lime~S~lightGray~ = Shulker]] -- Shulker is above | |
10132 | ||
10133 | info.sub[492] = | |
10134 | [[~yellow~Place turtle <64 blocks from shulker | |
10135 | - | local function upgradeFarmland(R) |
10135 | + | |
10136 | - | local essences = {":inferium", ":prudentium", ":tertium", ":imperium", ":supremium", ":awakened" , ":insanium"} |
10136 | + | |
10137 | ~red~>~lightGray~ | | | | | |~lime~S~lightGray~| | |
10138 | ||
10139 | ~yellow~Side view: | |
10140 | - | function lib.isHigherTeir(essence, farmLand) |
10140 | + | |
10141 | - | -- eg "ma:prudentium_essence", "mc:farmland" |
10141 | + | |
10142 | - | local teir = 0 |
10142 | + | |
10143 | - | for index = 1, #essences do |
10143 | + | |
10144 | - | if farmLand:find(essences[index]) ~= nil then |
10144 | + | |
10145 | - | teir = index -- 0 if vanilla, else eg 2 for prudentium |
10145 | + | |
10146 | info.sub[493] = | |
10147 | [[~yellow~Place turtle <64 blocks from shulker | |
10148 | Directly above or 1 block in front | |
10149 | - | for index = 1, #essences do |
10149 | + | |
10150 | - | if essence:find(essences[index]) ~= nil then |
10150 | + | |
10151 | - | if index > teir then |
10151 | + | |
10152 | ||
10153 | ||
10154 | ~gray~T | |
10155 | ~gray~> ~lime~S ~gray~< > T < = kill positions | |
10156 | ~lightGray~|*|*|*|*|*|*|*| | |
10157 | ||
10158 | ~red~> T <~lightGray~ = Turtle ~lime~S~lightGray~ = Shulker]] -- Shulker is below | |
10159 | - | function lib.upgrade(essence, slot) |
10159 | + | |
10160 | - | -- essence is the slot no of any essence |
10160 | + | |
10161 | - | turtle.select(slot) |
10161 | + | |
10162 | - | local blockType = T:getBlockType("up") |
10162 | + | |
10163 | - | if blockType:find("farmland") ~= nil then -- farmland found (vanilla or modded) |
10163 | + | |
10164 | - | if lib.isHigherTeir(essence, blockType) then -- eg "ma:inferium", mc:farmland" |
10164 | + | |
10165 | - | turtle.placeUp() |
10165 | + | |
10166 | ~lightGray~|*|~orange~+~lightGray~| | |~red~+~lightGray~| | |~blue~+~lightGray~|*| ~yellow~Plan view | |
10167 | ~lightGray~|*|~orange~+|+|+|~red~+|~blue~+|+|+~lightGray~|*| |*|*|*|*|*| | |
10168 | ~lightGray~|*|*|*|~orange~+|~red~+|~blue~+~lightGray~|*|*|*| |*| |~red~T~lightGray~| |*| | |
10169 | - | -- check if any essence still onboard |
10169 | + | |
10170 | - | T:checkInventoryForItem({"essence"}, {95}, false) |
10170 | + | |
10171 | - | -- return slotData.lastSlot, total, slotData -- integer, integer, table |
10171 | + | |
10172 | - | local name = "" |
10172 | + | |
10173 | - | local slot, amount, data = T:getItemSlot("essence") |
10173 | + | |
10174 | - | name = data.mostName or "" |
10174 | + | |
10175 | - | local empty = T:getFirstEmptySlot() |
10175 | + | |
10176 | clear the roof above and return | |
10177 | - | if slot > 0 then |
10177 | + | |
10178 | - | T:go("D2") |
10178 | + | |
10179 | ~lightGray~|*|~red~<~lightGray~| | | | | | |~red~^~lightGray~|*| ~yellow~area regardless | |
10180 | - | for w = 1, 10 do |
10180 | + | |
10181 | - | for i = 1, 9 do |
10181 | + | |
10182 | - | if turtle.getItemCount(slot) == 0 then |
10182 | + | |
10183 | - | slot, amount, data = T:getItemSlot("essence") |
10183 | + | |
10184 | - | name = data.mostName or "" |
10184 | + | |
10185 | - | if slot == 0 then |
10185 | + | |
10186 | - | slot = empty |
10186 | + | |
10187 | [[~yellow~Place turtle in corner against ceiling | |
10188 | Face ~red~direction ~yellow~shown. It will exit out, | |
10189 | - | lib.upgrade(name, slot) |
10189 | + | |
10190 | - | if w == 1 and i == 1 then |
10190 | + | |
10191 | - | T:go("F1R2 C1R2") |
10191 | + | |
10192 | - | elseif w == 10 and i == 1 then |
10192 | + | |
10193 | - | |
10193 | + | |
10194 | ||
10195 | ~lightGray~|*| | | | | | | | |*| | |
10196 | ~lightGray~|*|~red~V~lightGray~| | | | | | |~red~>~lightGray~|*| | |
10197 | ~lightGray~|*|*|*|*|*|*|*|*|*|*|]] -- Clear outside wall | |
10198 | ||
10199 | - | lib.upgrade(name, slot) |
10199 | + | |
10200 | - | if w == 1 then |
10200 | + | |
10201 | - | T:go("L1F1 L2C1 R1") |
10201 | + | |
10202 | - | elseif w == 9 then |
10202 | + | |
10203 | - | T:go("L1F1 L1F1 L2C1 L2") |
10203 | + | |
10204 | ~blue~ |-|-|-| | |
10205 | ~lightGray~ |*|~red~^~lightGray~|*| ~red~^ = Turtle | |
10206 | ||
10207 | ~yellow~Result:~blue~ |-|~lightGray~*|~blue~-| - = air/water | |
10208 | - | if w < 10 then |
10208 | + | |
10209 | - | lib.upgrade(name, slot) |
10209 | + | |
10210 | ~lightGray~ |*|*|*| * = Solid block | |
10211 | ]] -- Single path | |
10212 | - | T:go("L1F1 L2C1 R2F8 L1U1 C2U2") -- 1 above normal position |
10212 | + | |
10213 | [[~yellow~Place ~red~^ T~yellow~ at start of path or tunnel | |
10214 | ||
10215 | ~yellow~Plan view Face view | |
10216 | ||
10217 | - | -- sometimes original essence pops out of the ground when upgraded, so rescue it |
10217 | + | |
10218 | - | for w = 1, 10 do |
10218 | + | |
10219 | - | for i = 1, 9 do |
10219 | + | |
10220 | - | turtle.suckDown() |
10220 | + | |
10221 | - | turtle.suck() |
10221 | + | |
10222 | ||
10223 | ~green~Floor + ceiling ~yellow~placed for your safety! | |
10224 | ]] -- Covered walkway / tunnel | |
10225 | - | turtle.suckDown() |
10225 | + | |
10226 | - | turtle.suck() |
10226 | + | |
10227 | ||
10228 | ~lightGray~|*|~blue~-|-~lightGray~|*| | |
10229 | - | if w < 10 then |
10229 | + | |
10230 | - | turtle.suckDown() |
10230 | + | |
10231 | - | turtle.suck() |
10231 | + | |
10232 | ||
10233 | ~yellow~New canal ~lime~1 ~orange~2 ~brown~3 ~green~4 ~yellow~ground level-63 | |
10234 | - | T:go("L1F9 L1D1") -- normal position |
10234 | + | |
10235 | ~yellow~Extend existing ~blue~5 ~cyan~6 ~yellow~water level-62 | |
10236 | ]] -- new/existing canal | |
10237 | info.sub[54] = | |
10238 | [[~lime~New ~yellow~ice canal or ~lightBlue~convert ~yellow~existing water | |
10239 | ||
10240 | - | return ({"Farmland Upgraded"}) |
10240 | + | |
10241 | ~lightGray~ |~orange~T~lightGray~|~blue~I~lightGray~| |*| ~blue~I = Ice (packed or blue) | |
10242 | ~lightGray~ |*| | |*| | | = Air (empty block) | |
10243 | ~lightGray~ |*|~blue~I~lightGray~| |~orange~T~lightGray~| ~orange~T = Torch (optional) | |
10244 | ~lime~ 1 2 3 4 New ice canal | |
10245 | ~lightBlue~ 5 6 7 8 Convert water canal | |
10246 | - | function lib.askPlayerForCrops() |
10246 | + | |
10247 | - | local seed = "" |
10247 | + | |
10248 | - | pp.itemColours = {colors.lightGray, colors.red, colors.orange, colors.brown, colors.magenta, colors.yellow} |
10248 | + | |
10249 | - | crops = {"minecraft:wheat_seeds", "minecraft:beetroot_seeds", "minecraft:carrots", "minecraft:potatoes", "mysticalagriculture", "none"} |
10249 | + | |
10250 | - | choices = {"wheat (seeds)", "beetroot (seeds)", "carrot", "potato", "Mystical Agriculture", "Till soil only"} |
10250 | + | |
10251 | [[~yellow~Place ~red~^~yellow~ any level air, water or lava.~lightGray~ | |
10252 | ||
10253 | - | if crop == "none" then |
10253 | + | |
10254 | - | return "", "" |
10254 | + | |
10255 | - | elseif crop == "mysticalagriculture" then |
10255 | + | |
10256 | - | T:checkInventoryForItem({"seeds"}, {95}, true, "Add one type of M. Agriculture seeds") |
10256 | + | |
10257 | | |*|*|*|*|*| | | |
10258 | - | T:checkInventoryForItem({crop}, {95}, true, "Do not mix! add as many as you want") |
10258 | + | |
10259 | | | | | | | | | | |
10260 | - | crop = T:getMostItem("", false) -- not searching for any specific item, not checking stone only |
10260 | + | |
10261 | - | -- crop could be wheat/beetroot seeds, carrots, potatoes or mystical agriculture seeds |
10261 | + | |
10262 | - | seed, crop = lib.getCropSeed(crop) -- seed type or "", crop type |
10262 | + | |
10263 | - | return seed, crop |
10263 | + | |
10264 | [[~yellow~Place ~red~^~yellow~ above water.~lightGray~ | |
10265 | Existing platform replaced below | |
10266 | - | function lib.assessPlot(R) |
10266 | + | |
10267 | - | local crop = T:getBlockType("forward") -- convert ma:inferium_crop to ma:inferium_seeds |
10267 | + | |
10268 | - | local seed = lib.getCropSeed(crop) |
10268 | + | |
10269 | - | turtle.down() -- into water source |
10269 | + | |
10270 | - | local soil = T:getBlockType("forward") |
10270 | + | |
10271 | - | turtle.up() -- at crop level |
10271 | + | |
10272 | - | return crop, seed, soil |
10272 | + | |
10273 | ||
10274 | Blocks placed under the turtle | |
10275 | - | function lib.checkEquipment(R, itemRequired) |
10275 | + | |
10276 | - | -- Check if item is equipped and return it to slot |
10276 | + | |
10277 | [[~yellow~Boat Lift (Ice or Water) | |
10278 | Place turtle left side. ~blue~Source~yellow~ to right | |
10279 | - | local equipped, slot = T:getEquipped("right", false) -- see what is equipped and replace it |
10279 | + | |
10280 | - | if equipped == itemRequired then |
10280 | + | |
10281 | - | equipped, slot = T:getEquipped("right", true) -- remove item and return slot |
10281 | + | |
10282 | - | return slot |
10282 | + | |
10283 | |*|*|*|*| |*|~brown~S|S~lightGray~|*| ~brown~S = ~lightGray~Sand + gate | |
10284 | |~red~^~lightGray~|~blue~W|W~lightGray~|*| |*~blue~|W|W|~lightGray~*| ~red~^ ~lightGray~= Turtle | |
10285 | - | return 0 -- not found |
10285 | + | |
10286 | |*|~blue~ | ~lightGray~|*| |*|~blue~ | ~lightGray~|*| ~yellow~Ice canal needs | |
10287 | ~lightGray~|*|~blue~ | ~lightGray~|*| |*|~blue~ | ~lightGray~|*| ~yellow~2x2 water source | |
10288 | - | function lib.crossFarm(R) |
10288 | + | |
10289 | info.sub[61] = | |
10290 | [[~red~NOT ~yellow~for Blaze spawners! | |
10291 | - | local isReady, cropType, seed, status |
10291 | + | |
10292 | - | isReady, cropType, seed, status, R = lib.isCropReady(R,"down") |
10292 | + | |
10293 | - | -- will go forward until chest, barrel, modem or cobble detected below |
10293 | + | |
10294 | T|*| | | | | |*|T |*| | | | | |*| | |
10295 | |*| | |~magenta~5~lightGray~| | |*| |*| | |~magenta~5~lightGray~| | |*| | |
10296 | |*| |~magenta~5~lightGray~|~orange~S~lightGray~|~magenta~5~lightGray~| |*| |*|~lime~3~lightGray~|~magenta~5|~orange~S~lightGray~|~magenta~5|~green~4~lightGray~|*| Base | |
10297 | |*| | |~magenta~5~lightGray~| | |*| | |
10298 | T|*| | | | | |*|T * = Dungeon Wall | |
10299 | |*|*|*|*|*|*|*| ~orange~S = Spawner | |
10300 | ~lightGray~ T T T = Turtle ~brown~1 ~yellow~2 ~lime~3 ~green~4 | |
10301 | - | elseif blockType:find("barrel") ~= nil or |
10301 | + | |
10302 | - | blockType:find("chest") ~= nil or |
10302 | + | |
10303 | - | blockType:find("modem") ~= nil or |
10303 | + | |
10304 | - | blockType:find("cobble") ~= nil then |
10304 | + | |
10305 | Plan view Side view | |
10306 | ||
10307 | ~lightGray~|*|*|*|*|*|*|*|*| ~lime~> T = Continue build | |
10308 | ~lightGray~|*| | | | | | | | ~red~< T = New build | |
10309 | - | return R, blockType -- either barrel, chest, modem or cobble |
10309 | + | |
10310 | |*| | | |~purple~S~lightGray~| | | |~lime~>~red~< T | |
10311 | ~lightGray~|*| | | | | | | | |*| | | |~purple~S~lightGray~| | | |~red~T | |
10312 | - | function lib.farmAll(R, isFarmToRight, isFarmToFront) |
10312 | + | |
10313 | - | local plotCountR = 0 -- plot a1 harvested |
10313 | + | |
10314 | - | local plotCountF = 0 -- plot a1 harvested |
10314 | + | |
10315 | ~red~T]] -- 9x9 cube round blaze spawner | |
10316 | - | while isFarmToRight do -- do all plots on this axis |
10316 | + | |
10317 | - | R, isFarmToRight = lib.farmToRight(R) -- plot harvested and back to plot origin |
10317 | + | |
10318 | - | plotCountR = plotCountR + 1 |
10318 | + | |
10319 | ~lightGray~ |*| | | | | | | | | |*| |*| | | | | | | |
10320 | - | lib.goToLeft(R, plotCountR) |
10320 | + | |
10321 | |*| | | | | | | | | |*| |*| | | | | | | |
10322 | |*| | | | | | | | | |*| |*| | | | | | | |
10323 | - | while isFarmToFront do -- do all plots on this axis |
10323 | + | |
10324 | - | plotCountR = 0 -- reset |
10324 | + | |
10325 | - | R, isFarmToRight, isFarmToFront = lib.farmInFront(R) |
10325 | + | |
10326 | - | if isFarmToRight then |
10326 | + | |
10327 | - | while isFarmToRight do -- do all plots on this axis |
10327 | + | |
10328 | - | R, isFarmToRight = lib.farmToRight(R) -- plot harvested and back to plot origin |
10328 | + | |
10329 | - | plotCountR = plotCountR + 1 |
10329 | + | |
10330 | [[~yellow~Bubble lift: Plan view at start~lightGray~ | |
10331 | - | lib.goToLeft(R, plotCountR) -- return home and continue with front |
10331 | + | |
10332 | |*| | | | |~brown~F~lightGray~| | | | |*| | |
10333 | - | plotCountF = plotCountF + 1 |
10333 | + | |
10334 | ~brown~|~red~^~brown~|~lightGray~= Turtle on ~brown~Soul Sand | |
10335 | - | lib.goToFront(R, plotCountF) |
10335 | + | |
10336 | ~yellow~Plan view completed~lightGray~ | |
10337 | |*| | | | |~brown~F~lightGray~| | | | |*| | |
10338 | |*|*|*|*|*|~brown~F~lightGray~|*|*|*|*|*| ~brown~F ~lightGray~= Fence | |
10339 | - | function lib.farmInFront(R) |
10339 | + | |
10340 | ~lightGray~|*| ~blue~S ~lightGray~= Bubble lift | |
10341 | - | T:go("U1L1 F11D1 R1") -- on next farm, facing crops |
10341 | + | |
10342 | - | local seed, crop = lib.manageTree(R) -- refuel, gather seeds or other crops |
10342 | + | |
10343 | [[~yellow~Computercraft mob grinder | |
10344 | - | R, isFarmToRight = lib.harvest(R, seed, crop) -- harvest field, store crops |
10344 | + | |
10345 | - | return R, isFarmToRight |
10345 | + | |
10346 | |*~blue~| | | | | | | | | |~lightGray~*| | |
10347 | |*|*|*|*|*~blue~| |~lightGray~*|*|*|*|*| Front | |
10348 | - | function lib.farmToRight(R) |
10348 | + | |
10349 | ||
10350 | - | T:go("U1F11 D1") -- on next farm, facing crops |
10350 | + | |
10351 | - | local seed, crop = lib.manageTree(R) -- refuel, gather seeds and other crops |
10351 | + | |
10352 | - | R, isFarmToRight = lib.harvest(R, seed, crop) -- harvest field, store crops |
10352 | + | |
10353 | - | -- now at starting position of current plot |
10353 | + | |
10354 | - | return R, isFarmToRight |
10354 | + | |
10355 | ]] -- Computercraft mob grinder | |
10356 | info.sub[66] = | |
10357 | - | function lib.getCropSeed(crop) |
10357 | + | |
10358 | - | -- change growing crops into equivalent seed names |
10358 | + | |
10359 | - | -- crop could be seeds, so return equivalent crop |
10359 | + | |
10360 | - | local start = crop:find("_crop") |
10360 | + | |
10361 | - | if start ~= nil then -- only modded seeds have "crop" |
10361 | + | |
10362 | - | return crop:sub(1, start).."seeds", crop |
10362 | + | |
10363 | ||
10364 | - | if crop:find("seeds") ~= nil then -- asked to return crop from seed type |
10364 | + | |
10365 | - | if crop:find("wheat") ~= nil then |
10365 | + | |
10366 | - | return "minecraft:wheat_seeds", "minecraft:wheat" |
10366 | + | |
10367 | ]] -- Build endermen observation tower | |
10368 | - | if crop:find("beetroot") ~= nil then |
10368 | + | |
10369 | - | return "minecraft:beetroot_seeds", "minecraft:beetroot" |
10369 | + | |
10370 | [[~yellow~Clear field | |
10371 | ||
10372 | - | if crop:find("wheat") ~= nil then |
10372 | + | |
10373 | - | return "minecraft:wheat_seeds", "minecraft:wheat" |
10373 | + | |
10374 | ~lightGray~| | | | | | Remove blocks > ground | |
10375 | - | if crop:find("beetroot") ~= nil then |
10375 | + | |
10376 | - | return "minecraft:beetroot_seeds", "minecraft:beetroot" |
10376 | + | |
10377 | |~red~^~lightGray~| | | | | ~red~^ ~lightGray~= Turtle position | |
10378 | - | if crop:find("carrot") ~= nil then |
10378 | + | |
10379 | - | return "", "minecraft:carrot" |
10379 | + | |
10380 | ||
10381 | ]] -- Clear field | |
10382 | - | return "", "minecraft:potato" |
10382 | + | |
10383 | [[~yellow~Clear rectangle | |
10384 | - | -- planted crops are plural, harvested singular: carrots / carrot, pototoes/ potato |
10384 | + | |
10385 | - | return "", crop -- no seed for carrot / potato |
10385 | + | |
10386 | ~lightGray~| | | | | | Optional dig ~lime~up | |
10387 | ~lightGray~| | | | | | Optional dig ~blue~down | |
10388 | - | function lib.getHoe() |
10388 | + | |
10389 | | | | | | | | |
10390 | - | if R.networkFarm then -- get hoe from storage |
10390 | + | |
10391 | - | hoeSlot = network.getItemFromNetwork("barrel", "minecraft:diamond_hoe", 1) |
10391 | + | |
10392 | - | if hoeSlot == 0 then |
10392 | + | |
10393 | - | if T:checkInventoryForItem({"minecraft:diamond_hoe"}, {1}, true, "Diamond Hoe required for planting!") ~= nil then |
10393 | + | |
10394 | - | hoeSlot = T:getItemSlot("minecraft:diamond_hoe") |
10394 | + | |
10395 | ]] -- Clear rectangle | |
10396 | ||
10397 | - | else -- put crafting table into barrel in floor |
10397 | + | |
10398 | - | T:go("L1F1") -- over barrel |
10398 | + | |
10399 | - | local isStorage, storageType = utils.isStorage("down") |
10399 | + | |
10400 | - | if not isStorage then |
10400 | + | |
10401 | - | message = |
10401 | + | |
10402 | ~lightGray~ |*|*|*|*|*|*| | |
10403 | |*|*|*|*|*|*| | |
10404 | |*|*|*|*|*|*| | |
10405 | |*|*|*|*|*|*| | |
10406 | ~lime~T~lightGray~|~green~T~lightGray~|*|*|*|*|*| Base | |
10407 | - | instead. |
10407 | + | |
10408 | T = Turtle top / bottom/ inside / out | |
10409 | ~yellow~Bottom to top or top to bottom | |
10410 | ]] -- Clear wall | |
10411 | - | return 0, message |
10411 | + | |
10412 | [[~yellow~Clear rectangle ~red~perimeter only | |
10413 | - | -- must be storage below to get this far |
10413 | + | |
10414 | - | T:suck("down") -- if hoe already in storage get it out |
10414 | + | |
10415 | - | hoeSlot = T:getItemSlot("minecraft:diamond_hoe") |
10415 | + | |
10416 | - | if hoeSlot == 0 then |
10416 | + | |
10417 | - | if T:checkInventoryForItem({"minecraft:diamond_hoe"}, {1}, true, "Diamond Hoe required for planting!") ~= nil then |
10417 | + | |
10418 | - | hoeSlot = T:getItemSlot("minecraft:diamond_hoe") |
10418 | + | |
10419 | | |*|*|*| | | |
10420 | |~red~^~lightGray~| | | | | ~red~^ ~lightGray~= Turtle position | |
10421 | ~red~ ^ | |
10422 | - | return hoeSlot, "" |
10422 | + | |
10423 | ||
10424 | ]] -- Clear rectangle (perimeter only) | |
10425 | - | function lib.getSaplings(R, direction) |
10425 | + | |
10426 | [[~yellow~Demolish cube structure | |
10427 | Plan view Side view | |
10428 | ~gray~T ~lightBlue~T | |
10429 | ~lightGray~|*|*|*|*|*|*| ~cyan~T~lightGray~|~blue~T~lightGray~|*|*|*|*|*| | |
10430 | - | if R.networkFarm then |
10430 | + | |
10431 | - | network.getItemFromNetwork("barrel", "sapling", 1) |
10431 | + | |
10432 | - | --lib.getItemFromNetworkBarrels(R, "sapling", 1) |
10432 | + | |
10433 | |*|*|*|*|*|*| |*|*|*|*|*|*| | |
10434 | - | while T:suck(direction, 1) do end -- remove saplings/ seeds |
10434 | + | |
10435 | - | T:dropItem("sapling", direction, 1) -- drop all but 1 saplings |
10435 | + | |
10436 | - | if not T:dropItem("seeds", direction, 0) then-- drop all seeds |
10436 | + | |
10437 | - | T:dropItem("seeds", "up", 0) |
10437 | + | |
10438 | info.sub[76] = info.sub[75] | |
10439 | info.sub[77] = | |
10440 | [[~yellow~Dig a trench (Plan view) | |
10441 | - | return T:getItemSlot("sapling") |
10441 | + | |
10442 | ~lightGray~ |~red~>~lightGray~| | | | | | | | |
10443 | ||
10444 | - | function lib.getSeeds(R, direction, seed) |
10444 | + | |
10445 | - | --[[ |
10445 | + | |
10446 | - | seed = name of growing crops seed or "" |
10446 | + | |
10447 | - | turtle facing crops on networked, else facing storage |
10447 | + | |
10448 | - | allow for other seeds from mods eg MysticalAgriculture |
10448 | + | |
10449 | - | get 1 stack of seeds of whatever type is being farmed |
10449 | + | |
10450 | ]] -- Dig a trench | |
10451 | - | if seed == "" then |
10451 | + | |
10452 | - | return "", 0 |
10452 | + | |
10453 | ~yellow~Side view Plan view | |
10454 | - | local inventorySlot, seedCount = 0, 0 |
10454 | + | |
10455 | - | T:saveToLog("Collecting seeds from storage") |
10455 | + | |
10456 | - | if R.networkFarm then |
10456 | + | |
10457 | - | inventorySlot, seedCount = network.getItemFromNetwork("chest", seed, 64) |
10457 | + | |
10458 | ~gray~ |*~lightGray~|*|*|*| ~gray~|*|*~lightGray~|*|*|*|*| ~yellow~G | |
10459 | - | while T:suck(direction, 1) do end -- remove saplings/ seeds |
10459 | + | |
10460 | - | T:dropItem("sapling", direction, 0) -- drop all saplings |
10460 | + | |
10461 | - | T:dropItem("seeds", direction, 64) -- drop all but 64 of any seed type |
10461 | + | |
10462 | - | seedCount = T:getItemCount(seed) |
10462 | + | |
10463 | ]] -- Carve mountain | |
10464 | - | if seedCount > 0 then |
10464 | + | |
10465 | - | T:saveToLog("planting " ..seed) |
10465 | + | |
10466 | ||
10467 | - | return seed, seedCount -- could be: "", 0 or "minecraft:wheat_seeds", 64 |
10467 | + | |
10468 | ~lightGray~| | | | | | |*|*|*|*|*| | |
10469 | | | | | | | T Ceiling | |
10470 | - | function lib.getVeg(R, direction, crop) |
10470 | + | |
10471 | | | | | | | | |
10472 | - | -- local item, itemName, shortName, slot = "", "","", 0 |
10472 | + | |
10473 | - | local inventorySlot, cropCount = 0, 0 |
10473 | + | |
10474 | ||
10475 | - | if R.networkFarm then |
10475 | + | |
10476 | - | inventorySlot, cropCount = network.getItemFromNetwork("chest", crop, 64) |
10476 | + | |
10477 | ]] -- (Re)place floor or ceiling | |
10478 | - | if not R.mysticalAgriculture then |
10478 | + | |
10479 | - | print("Collecting root crops from storage") |
10479 | + | |
10480 | - | direction = direction or "forward" |
10480 | + | |
10481 | - | while T:suck(direction, 1) do end -- remove carrots / potatoes / wheat / beetroot / essence |
10481 | + | |
10482 | - | --item, itemName, shortName, slot = T:getFirstItem() |
10482 | + | |
10483 | - | local found = false |
10483 | + | |
10484 | - | if T:getItemSlot("potato") > 0 then |
10484 | + | |
10485 | - | T:dropItem("potato", direction, 64) -- drop all but 65 potato |
10485 | + | |
10486 | - | found = true |
10486 | + | |
10487 | - | crop = "minecraft:potato" |
10487 | + | |
10488 | ~lightGray~u = up ~cyan~d = down | |
10489 | - | if T:getItemSlot("carrot") > 0 then |
10489 | + | |
10490 | - | T:dropItem("carrot", direction, 64) -- drop all but 64 carrots |
10490 | + | |
10491 | - | found = true |
10491 | + | |
10492 | - | crop = "minecraft:carrot" |
10492 | + | |
10493 | ~yellow~Place me on water/lava surface | |
10494 | - | if not found then |
10494 | + | |
10495 | - | T:dropAll(direction) -- drop everything back |
10495 | + | |
10496 | ~yellow~Place on left corner of area | |
10497 | ||
10498 | - | cropCount = T:getItemCount(crop) |
10498 | + | |
10499 | ~yellow~Place me on the surface of sand. | |
10500 | ||
10501 | - | if cropCount > 0 then |
10501 | + | |
10502 | - | print("planting " ..crop) |
10502 | + | |
10503 | ]] -- Sand based utilities | |
10504 | - | return crop, cropCount -- could be: "", 0 or "minecraft:potato", 64 |
10504 | + | |
10505 | [[~yellow~Turtle position ~red~> T ~gray~(~red~V ~gray~to enclose) | |
10506 | ~yellow~Plan view ~gray~Start:~red~V | |
10507 | - | function lib.goHome(R) |
10507 | + | |
10508 | ~gray~* area | |
10509 | ~yellow~Side view | |
10510 | ~red~T | |
10511 | ~blue~| | | | | | | ~yellow~to ~lightGray~|*|*|*|*|*|*| | |
10512 | ~blue~| | | | | | | ~lightGray~|*|*|*|*|*|*| | |
10513 | - | lib.harvestTree(R, "forward") -- will only harvest if fuel below half of limit |
10513 | + | |
10514 | - | onTree = true -- end on dirt |
10514 | + | |
10515 | ~yellow~|S|S|S|S|S|S| |S|S|S|S|S|S| | |
10516 | - | lib.harvestTree(R, "up") -- end on dirt |
10516 | + | |
10517 | info.sub[83] = | |
10518 | - | elseif T:getItemSlot("log") > 0 then-- tree just harvested |
10518 | + | |
10519 | ||
10520 | ||
10521 | ~yellow~L ~lightGray~|*|*|*|*|*|*| | |
10522 | - | lib.harvestTree(R, "up") -- end on dirt |
10522 | + | |
10523 | ~yellow~n ~lightGray~|*| | | | |*| | |
10524 | - | while turtle.down() do end -- end on dirt |
10524 | + | |
10525 | ~yellow~t ~lightGray~|*|*|*|*|*|*| | |
10526 | ~yellow~h ~red~^ | |
10527 | ~yellow~ W i d t h ~red~^ ~lightGray~= Turtle | |
10528 | - | if onTree then |
10528 | + | |
10529 | - | local success, storage = false, "" |
10529 | + | |
10530 | - | -- tree harvested, sitting on dirt, but direction unknown |
10530 | + | |
10531 | - | T:down(1) -- dig dirt, go down |
10531 | + | |
10532 | - | -- if storage type farm chest/barrel will give position |
10532 | + | |
10533 | - | for turns = 1, 4 do |
10533 | + | |
10534 | Plan view | |
10535 | - | success, storage = utils.isStorage("forward") |
10535 | + | |
10536 | |*|*~blue~| | |~lightGray~*|*~blue~| |~lightGray~*| ~blue~| ~lightGray~= Water | |
10537 | - | T:go("L2U1") |
10537 | + | |
10538 | - | T:place("dirt", "down") |
10538 | + | |
10539 | - | T:go("B1R1 F1D1R1") |
10539 | + | |
10540 | - | R.ready = true |
10540 | + | |
10541 | |*|~red~^~lightGray~|*~blue~| | | | |~lightGray~*| ~red~^ ~lightGray~= Turtle | |
10542 | |*|*|*|*|*|*|*|*| ~yellow~Width~blue~: ~yellow~6, ~orange~length~blue~:~orange~ 6 | |
10543 | ||
10544 | - | -- if networked will be in air 2 blocks above barrel or stone |
10544 | + | |
10545 | info.sub[85] = info.sub[56] -- Sinking platform | |
10546 | - | T:place("dirt", "up") |
10546 | + | |
10547 | - | T:down(1) --should be on corner |
10547 | + | |
10548 | - | for turns = 1, 4 do |
10548 | + | |
10549 | ~red~****** ****** * ~lightGray~= Avoid this area | |
10550 | - | success, storage = utils.isStorage("down") |
10550 | + | |
10551 | - | if storage == "modem" then |
10551 | + | |
10552 | - | T:go("R1F1D1") |
10552 | + | |
10553 | - | R.ready = true |
10553 | + | |
10554 | ******~lime~++++~green~****** ~green~* ~lightGray~= Good position | |
10555 | ~green~**************** | |
10556 | - | T:go("B1R1") |
10556 | + | |
10557 | **************** blocks from edge | |
10558 | ]]-- Ocean monument 85 subChoice 1: 4 corner pillars | |
10559 | ||
10560 | info.sub[862] = | |
10561 | [[~yellow~Turtle positions ~red~> ^ < V | |
10562 | - | return R -- R.ready == false |
10562 | + | |
10563 | ~lightGray~|*|~red~>~lightGray~|*|*|*|*|*|~red~<~lightGray~|*| ~red~NOT ~lightGray~corner blocks! | |
10564 | |~red~V~lightGray~| |~red~V~lightGray~| | |
10565 | - | function lib.goToLeft(R, plotCountR) |
10565 | + | |
10566 | - | T:go("U1R2 F"..plotCountR * 11 .."D1R2") -- return home and continue with front |
10566 | + | |
10567 | - | if R.config ~= nil then |
10567 | + | |
10568 | - | local coord = R.config.currentPlot |
10568 | + | |
10569 | - | for i = 1, plotCountR do |
10569 | + | |
10570 | - | coord = lib.configUpdateCoords(R, coord, "left") |
10570 | + | |
10571 | |*|~red~>~lightGray~|*|*|*|*|*|~red~<~lightGray~|*| ~yellow~Add when asked | |
10572 | - | R.config.currentPlot = coord |
10572 | + | |
10573 | ||
10574 | info.sub[863] = | |
10575 | [[~yellow~Turtle ~red~> < ~yellow~on side walls only | |
10576 | - | function lib.goToFront(R, plotCountF) |
10576 | + | |
10577 | - | T:go("U1R1F"..plotCountF * 11 .."D1L1") |
10577 | + | |
10578 | - | if R.config ~= nil then |
10578 | + | |
10579 | - | local coord = R.config.currentPlot |
10579 | + | |
10580 | - | for i = 1, plotCountF do |
10580 | + | |
10581 | - | coord = lib.configUpdateCoords(R, coord, "back") |
10581 | + | |
10582 | ~lightGray~|~red~>~cyan~| *****+++***** |~red~<~lightGray~| | |
10583 | - | R.config.currentPlot = coord |
10583 | + | |
10584 | ~lightGray~|~red~>~cyan~| ************* |~red~<~lightGray~| | |
10585 | |*|*|*|*|*|*|*|*|*|*| | |
10586 | ]] -- clear plants before sand draining | |
10587 | - | function lib.gotoTree(R) |
10587 | + | |
10588 | info.sub[865] = info.sub[863] | |
10589 | - | if not R.networkFarm then |
10589 | + | |
10590 | - | T:turnRight(1) -- face storage |
10590 | + | |
10591 | [[~yellow~Turtle positions ~red~> ^ < V | |
10592 | - | T:saveToLog("Extracting saplings from storage") |
10592 | + | |
10593 | - | lib.getSaplings(R, "forward") -- gets one sapling only (if present) |
10593 | + | |
10594 | - | T:saveToLog("Moving to tree position") |
10594 | + | |
10595 | - | if R.networkFarm then |
10595 | + | |
10596 | - | T:turnRight(1) -- face wall next to corner barrel |
10596 | + | |
10597 | ~orange~|*|- - - - ~lime~- - - -|*| ~lightGray~6 chests / area | |
10598 | - | T:go("U1F1R1") -- move on top of wall/storage. face tree direction |
10598 | + | |
10599 | ~orange~|*|- - - - ~lime~- - - -|*| | |
10600 | - | -- check if tree or dirt ahead |
10600 | + | |
10601 | - | if turtle.forward() then -- No tree or sapling ahead. assume tree is missing or 2 blocks above |
10601 | + | |
10602 | - | if T:getBlockType("down") == "minecraft:dirt" then |
10602 | + | |
10603 | - | turtle.back() -- older design, return |
10603 | + | |
10604 | [[~yellow~Ladder to water / lava: Plan view | |
10605 | ||
10606 | - | if turtle.detectUp() then -- dirt above = new tree layout |
10606 | + | |
10607 | - | if T:getBlockType("up") == "minecraft:dirt" then |
10607 | + | |
10608 | - | T:go("B1U2") -- check tree in elevated position |
10608 | + | |
10609 | |*|*|*|~red~^~lightGray~|*|*|*| |*|*|*|*|*|*|*| | |
10610 | - | turtle.back() -- not dirt above ? removed or lost |
10610 | + | |
10611 | |*|*|*|*|*|*|*| |*|*|*|*|*|*|*| | |
10612 | ||
10613 | ~red~^ ~lightGray~= Turtle facing water / lava | |
10614 | ~brown~L ~lightGray~= Ladder | |
10615 | - | lib.harvestTree(R, "forward") -- fell tree or plant sapling, ends facing tree / dirt / sapling. sticks already used for fuel. excess saplings placed |
10615 | + | |
10616 | - | T:go("R1F1D1R1") -- return to base, facing crops |
10616 | + | |
10617 | - | if R.networkFarm then |
10617 | + | |
10618 | - | network.sendItemToNetworkStorage(R, "barrel", "sapling", 64) --move saplings to any attached barrel |
10618 | + | |
10619 | Returns max ~blue~d~yellow~epth. ~yellow~Water ~green~p~yellow~lants~yellow~ removed | |
10620 | - | T:turnRight(1) -- facing plot storage |
10620 | + | |
10621 | - | T:saveToLog("Dropping saplings into storage") |
10621 | + | |
10622 | - | T:dropItem("sapling", "forward", 0) -- drop all saplings forward into chest/barrel |
10622 | + | |
10623 | |*|*| ~blue~| | | | | | | | | ~lightGray~|*|*| | |
10624 | |*|*| ~blue~| | | | | | | ~lightGray~|*|*|*|*| | |
10625 | - | -- ends in field facing crops |
10625 | + | |
10626 | |*|*|*| ~blue~| | |~green~p~lightGray~|*|*|*|*|*|*|*| | |
10627 | |*|*|*|*~blue~|d~lightGray~|*|*|*|*|*|*|*|*|*| | |
10628 | - | function lib.harvest(R, seed, crop) |
10628 | + | |
10629 | ]] -- Clear water plants from enclosed area | |
10630 | info.sub[89] = | |
10631 | - | harvest crop if ripe |
10631 | + | |
10632 | of retaining wall facing water | |
10633 | ]] -- Convert all water to source | |
10634 | info.sub[810] = | |
10635 | - | crop is full name. if mixed seeds only one type returned |
10635 | + | |
10636 | of retaining wall facing water. | |
10637 | The source blocks are placed ahead to | |
10638 | selected length | |
10639 | ]] -- Create sloping water | |
10640 | ||
10641 | -- Building and railway | |
10642 | info.sub[91] = | |
10643 | [[~yellow~Build a wall | |
10644 | ||
10645 | - | lib.replant(R, seed, crop) -- check and replant crop below |
10645 | + | |
10646 | ||
10647 | ~red~>~lightGray~| | | | | | | |*|*|*|*|*|*| | |
10648 | |*|*|*|*|*|*| | |
10649 | - | if utils.isStorage("down") then -- chest, barrel or modem |
10649 | + | |
10650 | |*|*|*|*|*|*| | |
10651 | ~red~T~lightGray~|~red~T~lightGray~|*|*|*|*|*| | |
10652 | ||
10653 | ~red~> T~lightGray~ = Turtle | |
10654 | ||
10655 | ]] -- Build a wall | |
10656 | info.sub[92] = | |
10657 | - | lib.replant(R, seed, crop) -- check and replant crop below |
10657 | + | |
10658 | ||
10659 | Plan view Side view | |
10660 | ||
10661 | ~yellow~L ~lightGray~|*|*|*|*|*|*| |*|*|*|*|*|*| | |
10662 | ~yellow~e ~lightGray~|*| | | | |*| |*|*|*|*|*|*| | |
10663 | - | lib.replant(R, seed, crop) |
10663 | + | |
10664 | ~yellow~g ~lightGray~|*| | | | |*| |*|*|*|*|*|*| | |
10665 | ~yellow~t ~lightGray~|~red~^~lightGray~|*|*|*|*|*| ~red~T~lightGray~|~red~T~lightGray~|*|*|*|*|*| | |
10666 | ~yellow~h ~red~^ | |
10667 | ~yellow~ W i d t h ~red~^ T ~lightGray~= Turtle | |
10668 | - | if utils.isStorage("down") then |
10668 | + | |
10669 | ]] -- Build a rectangular structure | |
10670 | info.sub[93] = | |
10671 | [[~yellow~Build a gable roof | |
10672 | - | lib.storeCrops(R) -- rotates from start to deposit seeds and crops, ends facing crops |
10672 | + | |
10673 | - | return R, isFarmToRight, isFarmToFront |
10673 | + | |
10674 | ~gray~+ gable top | |
10675 | ~yellow~L ~lightGray~|*|*|*|*|*| ~gray~+ + + gable end | |
10676 | - | function lib.harvestTree(R, direction) |
10676 | + | |
10677 | ~yellow~n ~lightGray~|*| | | |*| |*|*|*|*|*| top of wall | |
10678 | ~yellow~g ~lightGray~|*| | | |*| |*|*|*|*|*| | |
10679 | ~yellow~t ~lightGray~|*| | | |*| |*|*|*|*|*| | |
10680 | ~yellow~h ~lightGray~|~red~^~lightGray~|*|*|*|*| |*|*|*|*|*| | |
10681 | ~yellow~ W i d t h W i d t h ~red~^T ~lightGray~= Turtle | |
10682 | - | Return to top of storage |
10682 | + | |
10683 | info.sub[94] = | |
10684 | [[~yellow~Build a pitched roof | |
10685 | Width ~red~MUST ~yellow~be ~red~<= ~yellow~Length eg ~red~4~yellow~ x 6 | |
10686 | - | local inFront = T:getBlockType("forward") |
10686 | + | |
10687 | - | print("Checking tree") |
10687 | + | |
10688 | - | if inFront == "" then -- no tree or sapling |
10688 | + | |
10689 | - | print("No sapling: planting sapling") |
10689 | + | |
10690 | - | T:place("sapling", "forward") |
10690 | + | |
10691 | - | elseif inFront:find("log") ~= nil or direction == "up" then -- tree above or in front |
10691 | + | |
10692 | - | -- clsTurtle.harvestTree(self, extend, craftChest, direction) |
10692 | + | |
10693 | - | print("Harvesting tree") |
10693 | + | |
10694 | - | T:harvestTree(false, false, direction) --do not investigate side branches in case chunk unloaded |
10694 | + | |
10695 | - | T:back(1) -- face dirt |
10695 | + | |
10696 | - | -- place(self, blockType, direction, leaveExisting, signText) |
10696 | + | |
10697 | - | T:place("sapling", "forward") |
10697 | + | |
10698 | [[~yellow~Place me on suspended railway stone | |
10699 | - | print("Disposing of apples") |
10699 | + | |
10700 | - | T:dropItem("apple", "up", 0) -- drop any apples |
10700 | + | |
10701 | - | utils.useSticksAsFuel() |
10701 | + | |
10702 | ~lightGray~|*|*|\ ~red~>~lightGray~|*| | |
10703 | - | while turtle.down() do end -- ends facing tree, on top of plot storage |
10703 | + | |
10704 | ~lightGray~|*|______~red~T~lightGray~_________ /~lightGray~|*|~red~! | |
10705 | ~red~!~lightGray~|*|*|*|*|*|*|*|*|\ /|*| | |
10706 | - | function lib.manageTree(R) |
10706 | + | |
10707 | ||
10708 | - | local isReady, crop, seed, status, R = lib.isCropReady(R, "forward") |
10708 | + | |
10709 | - | if crop == "" and not R.auto then -- only ask player if not running via startup |
10709 | + | |
10710 | - | seed, crop = lib.askPlayerForCrops() -- "" or specific seed type, |
10710 | + | |
10711 | info.sub[96] = info.sub[95] | |
10712 | info.sub[97] = | |
10713 | [[~yellow~Place me on last block before up/down | |
10714 | ||
10715 | Build down Build up~lightGray~ | |
10716 | ||
10717 | _____~red~T~lightGray~ ___ | |
10718 | |*|*|*|_ _|*| | |
10719 | |*|_ _|*| | |
10720 | |*|_ _|*| | |
10721 | |*|__________~red~T~lightGray~|*| | |
10722 | |*|*|*|*|*|*| | |
10723 | ~red~T~lightGray~ = Turtle on block, not above rail | |
10724 | ]] -- build down | |
10725 | - | T:saveToLog("Running Tree Manager") |
10725 | + | |
10726 | - | lib.gotoTree(R) -- check for sapling or harvest tree, retuns to facing crops |
10726 | + | |
10727 | --Measurement tools | |
10728 | info.sub[101] = | |
10729 | [[~yellow~Place me on floor.~lightGray~ | |
10730 | - | if logSlot > 0 then --logs onboard, need to equip crafting table |
10730 | + | |
10731 | - | if R.networkFarm then |
10731 | + | |
10732 | - | lib.refuelWithLogs(R, logSlot) -- use any logs for fuel |
10732 | + | |
10733 | |*|*|*| | |
10734 | - | T:go("L1F1") -- move to buried storage chest/barrel |
10734 | + | |
10735 | - | lib.refuelWithLogs(R, logSlot) -- use any logs for fuel |
10735 | + | |
10736 | - | T:go("R2F1") -- facing seed chest/barrel |
10736 | + | |
10737 | |*|*|*| | |
10738 | |*|*|*| | |
10739 | - | if not R.networkFarm then |
10739 | + | |
10740 | ]] -- measure height | |
10741 | info.sub[102] = | |
10742 | [[~yellow~Depth measurement | |
10743 | - | -- get seeds or veg based on what is growing |
10743 | + | |
10744 | - | if seed ~= "" then |
10744 | + | |
10745 | - | local seedType, seedCount = lib.getSeeds(R, "forward", seed) -- table: get 95 of beetroot / wheat / mysticalagriculture seeds |
10745 | + | |
10746 | - | if seedCount == 0 then |
10746 | + | |
10747 | - | T:saveToLog("No seeds available.") |
10747 | + | |
10748 | 3|*|*| | |
10749 | - | else -- seed = "" |
10749 | + | |
10750 | - | local veg, vegCount = "", 0 |
10750 | + | |
10751 | - | if R.networkFarm then |
10751 | + | |
10752 | - | veg, vegCount = lib.getVeg(R, "forward", crop) -- gets any carrots / potatoes |
10752 | + | |
10753 | ]] -- measure depth | |
10754 | - | T:turnRight(1) -- face crop chests |
10754 | + | |
10755 | - | veg, vegCount = lib.getVeg(R, "forward", crop) -- gets any carrots / potatoes |
10755 | + | |
10756 | - | T:turnRight(2) -- face crops |
10756 | + | |
10757 | ~lightGray~1 2 3 4 ~lime~5~lightGray~ 6 ~lime~7 ~cyan~8 ~lightBlue~9~lightGray~ 10 | |
10758 | - | if veg ~= "" then |
10758 | + | |
10759 | - | crop = veg |
10759 | + | |
10760 | ~red~T~lightGray~ |*| ~lightBlue~9. Obstruction | |
10761 | ~lightGray~*|*|*|*|~lime~S~lightGray~|*|*| |*|*| ~lime~5. Search block | |
10762 | ~cyan~8. No block down | |
10763 | - | return seed, crop -- name of seed / "", crop / "" |
10763 | + | |
10764 | ~red~T ~lightGray~= Turtle | |
10765 | ||
10766 | - | function lib.isCropReady(R, direction) |
10766 | + | |
10767 | info.sub[104] = info.sub[88] -- measure deepest section of water | |
10768 | info.sub[105] = | |
10769 | [[~yellow~Place turtle anywhere: | |
10770 | - | local crop, seed = "", "" |
10770 | + | |
10771 | 1. make a ~blue~borehole~yellow~ to chosen level. | |
10772 | ||
10773 | 2. Write a report called: | |
10774 | ||
10775 | 3. ~lime~borehole~blue~X~lime~.txt ~yellow~( ~blue~X ~yellow~= computer ID ) | |
10776 | ||
10777 | 4. ~orange~Return home | |
10778 | ||
10779 | ]] -- Borehole: Analyse blocks below | |
10780 | - | --T:saveToLog("lib.isCropReady(R,".. direction..")") |
10780 | + | |
10781 | - | if success then -- inspect() success |
10781 | + | |
10782 | - | crop = data.name -- name of growing plant |
10782 | + | |
10783 | - | if crop:find("flower") ~= nil then |
10783 | + | |
10784 | - | T:saveToLog("Flower "..crop.." found") |
10784 | + | |
10785 | - | return true, crop, "open" -- eg torchflower |
10785 | + | |
10786 | ||
10787 | - | if data.name:find("beetroot") ~= nil then |
10787 | + | |
10788 | - | status = data.state.age.." / 3" |
10788 | + | |
10789 | - | if data.state.age == 3 then |
10789 | + | |
10790 | - | isReady = true |
10790 | + | |
10791 | ~yellow~Enter 1 to use ~lime~2 ~yellow~turtles or 2 to use ~orange~4]] -- initial menu for water canal | |
10792 | - | else -- all other crops inc Mystical Agriculture |
10792 | + | |
10793 | - | status = data.state.age.." / 7" |
10793 | + | |
10794 | - | if data.state.age == 7 then |
10794 | + | |
10795 | - | isReady = true |
10795 | + | |
10796 | read() | |
10797 | return "" | |
10798 | else -- item specific help | |
10799 | - | seed, crop = lib.getCropSeed(crop) |
10799 | + | |
10800 | line = menu.colourText(line, info.sub[menuItem], true, true) | |
10801 | - | --T:saveToLog("return isReady = "..tostring(isReady)..", crop = "..crop..", seed = "..seed..", status = "..status) |
10801 | + | |
10802 | - | -- crop: "", "minecraft:carrots", "minecraft:beetroot", "minecraft:potatoes", "minecraft:wheat", "mysticalagriculture:*_crop" |
10802 | + | |
10803 | - | return isReady, crop, seed, status, R -- eg true, "minecraft:carrots", "7 / 7" or false, "mysticalagriculture:inferium_crop", "1 / 7" |
10803 | + | |
10804 | if getInteger then | |
10805 | return line -- ready for further input | |
10806 | - | function lib.locateFarm(R) |
10806 | + | |
10807 | - | T:saveToLog("? over water = false") |
10807 | + | |
10808 | menu.enterToContinue() | |
10809 | end | |
10810 | - | detected = i |
10810 | + | |
10811 | term.setCursorPos(1, 13) | |
10812 | term.write("Enter=exit, Any key + Enter=more ") | |
10813 | return read() | |
10814 | - | T:saveToLog("Neighbouring blocks detected at: "..detected) |
10814 | + | |
10815 | - | -- check if on corner |
10815 | + | |
10816 | - | if detected > 0 then |
10816 | + | |
10817 | - | --assume tree / sapling on corner on older farm type |
10817 | + | |
10818 | - | T:saveToLog("Assuming next to tree / sapling. Moving..") |
10818 | + | |
10819 | - | T:go("R"..detected .."F1D1R1") |
10819 | + | |
10820 | - | else -- no surrounding blocks |
10820 | + | |
10821 | options.main = | |
10822 | { | |
10823 | - | success, storage = utils.isStorage("down") |
10823 | + | |
10824 | - | T:saveToLog("i = "..i..",success = "..tostring(success)..". storage = "..storage) |
10824 | + | |
10825 | "Farming", | |
10826 | - | discovered = discovered .. storage |
10826 | + | |
10827 | - | if storage == "modem" then |
10827 | + | |
10828 | - | R.networkFarm = true |
10828 | + | |
10829 | "Area shaping and clearing", | |
10830 | "Lava and Water", | |
10831 | - | if storage == "" then |
10831 | + | |
10832 | - | discovered = discovered .. "_" |
10832 | + | "Measuring tools" |
10833 | } | |
10834 | - | discovered = discovered .. "wall" |
10834 | + | |
10835 | { | |
10836 | "Ladder up or down", | |
10837 | "Stairs up or down", | |
10838 | "Create mine at this level", | |
10839 | "Safe drop to water block", | |
10840 | - | T:saveToLog("Neighbouring blocks found:"..discovered) |
10840 | + | |
10841 | "QuickMine corridor system", | |
10842 | - | -- check discovered for patterns eg {_wall_barrel} |
10842 | + | |
10843 | - | -- |W|*|B| * = turtle on wall |
10843 | + | |
10844 | - | -- | | |M| |
10844 | + | |
10845 | - | if R.networkFarm then |
10845 | + | |
10846 | - | -- E = wall_barrel_, N = _barrel_wall, W = wall_barrel_, S = _wall_barrel |
10846 | + | |
10847 | - | if discovered == "_wall_barrel" then |
10847 | + | |
10848 | - | T:go("F1D1R1") |
10848 | + | |
10849 | - | elseif discovered == "barrel_wall_" then |
10849 | + | "Create tree farm", |
10850 | "Plant tree farm", | |
10851 | - | elseif discovered == "_barrel_wall" then |
10851 | + | |
10852 | - | T:go("R2F1D1R1") |
10852 | + | |
10853 | - | elseif discovered == "wall_barrel_" then |
10853 | + | |
10854 | - | T:go("L1F1D1R1") |
10854 | + | |
10855 | table.insert(options, | |
10856 | - | else -- normal storage farm |
10856 | + | |
10857 | - | if discovered == "_chest_chest" then |
10857 | + | |
10858 | - | T:go("F1D1R1") |
10858 | + | |
10859 | - | elseif discovered == "chest__chest" then |
10859 | + | "Plant, harvest or manage crop farm", |
10860 | "Build a wall or fence", | |
10861 | - | elseif discovered == "_chest_chest" then |
10861 | + | |
10862 | - | T:go("R2F1D1R1") |
10862 | + | |
10863 | - | elseif discovered == "chest_chest_" then |
10863 | + | |
10864 | - | T:go("L1F1D1R1") |
10864 | + | |
10865 | "Dig obsidian field", | |
10866 | "Build Nether Portal", | |
10867 | "Demolish Nether Portal", | |
10868 | "Stripmine Netherite", | |
10869 | "Undermine Dragon Towers", | |
10870 | - | success, storage = utils.isStorage("forward") -- true/false, chest, barrel, modem / "" |
10870 | + | |
10871 | - | if success and storage == "modem" then |
10871 | + | |
10872 | - | R.networkFarm = true |
10872 | + | |
10873 | "Shulker harvester" | |
10874 | }) | |
10875 | table.insert(options, | |
10876 | - | R.ready = true |
10876 | + | |
10877 | "Simple path on air, water or lava", | |
10878 | "Covered path or tunnel", | |
10879 | "Water canal (mulitple options)", | |
10880 | - | function lib.plantCrop(R, seed, crop, direction) |
10880 | + | |
10881 | "Platform", | |
10882 | "Sinking platform", | |
10883 | "Boat bubble lift", | |
10884 | }) | |
10885 | table.insert(options, | |
10886 | - | --T:saveToLog("lib.plantCrop(R, seed = "..seed..", crop = "..crop) |
10886 | + | |
10887 | "Cube around spawner (NOT blaze)", | |
10888 | - | -- place(blockType, direction, leaveExisting, signText, doNotAttack) |
10888 | + | |
10889 | - | if seed == "" then -- must be a crop |
10889 | + | |
10890 | - | success = T:place(crop, direction, true, "", true) |
10890 | + | |
10891 | - | --success = T:place(crop, direction, false, "", true) |
10891 | + | |
10892 | - | --T:saveToLog("Seed = "..seed..". Placing "..crop..": success = "..tostring(success)) |
10892 | + | "Build Endermen observation tower" |
10893 | }) | |
10894 | - | success = T:place(seed, direction, true, "", true) -- eg "mysticalagriculture:air_seeds" |
10894 | + | |
10895 | - | --success = T:place(seed, direction, false, "", true) -- eg "mysticalagriculture:air_seeds" |
10895 | + | |
10896 | - | --T:saveToLog("Placing "..seed..": success = "..tostring(success)) |
10896 | + | |
10897 | "Clear a rectangle (+ u/d opt)", | |
10898 | - | if not success then |
10898 | + | |
10899 | - | success = T:place("seed", direction, true, "", true) -- failsafe |
10899 | + | |
10900 | - | --success = T:place("seed", direction, false, "", true) -- failsafe |
10900 | + | |
10901 | - | --T:saveToLog("Placing generic 'seeds' : success = "..tostring(success)) |
10901 | + | |
10902 | "Dig a trench", | |
10903 | - | return success |
10903 | + | |
10904 | "Place a floor or ceiling", | |
10905 | "Direct control of movement" | |
10906 | - | function lib.replant(R, seed, crop) |
10906 | + | |
10907 | - | -- check crop below. If ripe, dig and replant seed |
10907 | + | |
10908 | - | local isReady, cropType, seedType, status |
10908 | + | |
10909 | - | isReady, cropType, seedType, status, R = lib.isCropReady(R, "down") -- eg true, "minecraft:carrots", "7 / 7" or false, "", "" |
10909 | + | |
10910 | - | if cropType == "" then -- no crop below (above water, storage or dirt) |
10910 | + | |
10911 | - | turtle.digDown("right") -- use hoe |
10911 | + | |
10912 | - | lib.plantCrop(R, seed, crop, "down")-- plant crop |
10912 | + | |
10913 | - | elseif isReady then -- crop below is ready |
10913 | + | |
10914 | - | turtle.digDown("left") -- use pickaxe |
10914 | + | |
10915 | - | lib.plantCrop(R, seedType, cropType, "down") -- plant crop |
10915 | + | |
10916 | "Clear water plants", | |
10917 | "Convert all water to source", | |
10918 | - | return R |
10918 | + | |
10919 | }) | |
10920 | table.insert(options, | |
10921 | - | function lib.refuelWithLogs(R, logSlot) |
10921 | + | |
10922 | - | -- saplings already dropped, apples dumped, sticks used as fuel |
10922 | + | |
10923 | - | -- assume positioned in front of crops if networked, or over buried storage |
10923 | + | |
10924 | "Build a gable end roof", | |
10925 | "Build a pitched roof", | |
10926 | - | -- networked version uses remote storage, turtle faces crops and has modem at back |
10926 | + | |
10927 | - | local slot, count = 0, 0 |
10927 | + | |
10928 | - | T:saveToLog("Sorting Inventory") -- make sure all items collected together |
10928 | + | |
10929 | - | T:sortInventory(true) |
10929 | + | |
10930 | - | T:saveToLog("Logs present: collecting crafting table") |
10930 | + | |
10931 | - | if R.networkFarm then |
10931 | + | |
10932 | - | slot, count = network.getItemFromNetwork("barrel", "minecraft:crafting_table", 1) |
10932 | + | |
10933 | - | --slot = lib.getItemFromNetworkBarrels(R, "minecraft:crafting_table", 1) |
10933 | + | |
10934 | "Measure depth", | |
10935 | - | while T:suck("down") do end -- empty out barrel/chest to find crafting table |
10935 | + | |
10936 | "Measure greatest depth", | |
10937 | "Borehole: Analyse blocks below" | |
10938 | }) | |
10939 | ||
10940 | return options | |
10941 | - | if R.networkFarm then |
10941 | + | |
10942 | - | network.sendItemToNetworkStorage(R, "barrel", "minecraft:diamond_hoe", 1) |
10942 | + | |
10943 | local function getTaskColours() | |
10944 | local options = {} | |
10945 | options.main = | |
10946 | - | T:drop("down", i) -- into water if networked, buried chest otherwise |
10946 | + | |
10947 | colors.lightGray, -- Mining (includes Nether) | |
10948 | colors.lime, -- Forestry | |
10949 | colors.green, -- Farming | |
10950 | colors.red, -- Obsidian, Nether & End Portal | |
10951 | colors.brown, -- Canal, bridge and walkway | |
10952 | colors.lightGray, -- Mob farm tools | |
10953 | colors.orange, -- Area shaping and clearing | |
10954 | colors.blue, -- Lava and Water | |
10955 | - | while logSlot > 0 and turtle.getFuelLevel() < turtle.getFuelLimit() do |
10955 | + | |
10956 | colors.purple -- Measuring tools | |
10957 | - | turtle.refuel() -- refuel using planks |
10957 | + | |
10958 | table.insert(options, | |
10959 | { | |
10960 | - | while T:suck("down") do end -- recover items from water / storage below |
10960 | + | |
10961 | - | --T:unequip("right") |
10961 | + | |
10962 | - | if R.networkFarm then |
10962 | + | |
10963 | - | slot = network.getItemFromNetwork("barrel", "minecraft:diamond_hoe", 1) |
10963 | + | |
10964 | colors.blue, -- Single column bubble lift | |
10965 | - | if not T:equip("right", "minecraft:diamond_hoe") then -- re-equip hoe/remove crafting table |
10965 | + | |
10966 | colors.pink, -- QuickMine rectangle | |
10967 | colors.gray, -- Mine bedrock level | |
10968 | - | if R.networkFarm then |
10968 | + | |
10969 | - | network.sendItemToNetworkStorage(R, "barrel", "minecraft:crafting_table", 1) |
10969 | + | |
10970 | table.insert(options, | |
10971 | - | T:dropItem("minecraft:crafting_table", "down") |
10971 | + | |
10972 | colors.brown, -- Fell Tree | |
10973 | colors.lightGray, -- Create tree farm | |
10974 | colors.lime, -- Plant tree farm | |
10975 | colors.green, -- Harvest tree farm | |
10976 | colors.brown, -- Fence or wall an enclosure | |
10977 | colors.lime -- Harvest and replant forest | |
10978 | }) | |
10979 | - | function lib.storeCrops(R) |
10979 | + | |
10980 | - | -- place crops and seeds into chests. starts facing crops |
10980 | + | |
10981 | colors.yellow, -- Create modular crop farm | |
10982 | colors.green, -- Extend modular crop farm | |
10983 | - | if R.networkFarm then |
10983 | + | |
10984 | - | network.emptyInventory(R, {"sapling", "diamond_hoe", "crafting"}, {"all"}, true) |
10984 | + | |
10985 | colors.brown -- Build rectangle wall or fence | |
10986 | - | T:turnRight(1) -- face seed storage |
10986 | + | |
10987 | - | lib.storeSeeds(R, "forward") |
10987 | + | |
10988 | { | |
10989 | - | if utils.isStorage(direction) then |
10989 | + | |
10990 | - | T:dropAll(direction) -- drops everything including essences |
10990 | + | |
10991 | colors.gray, -- Demolish Nether Portal | |
10992 | - | T:turnRight(2) -- facing crops again |
10992 | + | |
10993 | colors.orange, -- Undermine Dragon Towers | |
10994 | colors.orange, -- Deactivate Dragon Tower | |
10995 | colors.blue, -- Build dragon water trap | |
10996 | - | function lib.storeSeeds(R, direction) |
10996 | + | |
10997 | colors.red -- Shulker harvesting | |
10998 | - | if utils.isStorage(direction) then -- chest exists |
10998 | + | |
10999 | - | if not R.networkFarm then |
10999 | + | |
11000 | - | if T:getItemSlot("minecraft:wheat_seeds") > 0 then |
11000 | + | |
11001 | - | if not T:dropItem("minecraft:wheat_seeds", direction, 0) then |
11001 | + | |
11002 | - | T:dropItem("minecraft:wheat_seeds", "up", 0) |
11002 | + | |
11003 | - | end -- drop all wheat seeds |
11003 | + | |
11004 | - | elseif T:getItemSlot("minecraft:beetroot_seeds") > 0 then |
11004 | + | |
11005 | - | if not T:dropItem("minecraft:beetroot_seeds", direction, 0) then-- drop all beetroot seeds |
11005 | + | |
11006 | - | T:dropItem("minecraft:beetroot_seeds", "up", 0) |
11006 | + | |
11007 | colors.cyan -- Boat bubble lift | |
11008 | - | elseif T:getItemSlot("seeds") > 0 then |
11008 | + | |
11009 | - | if not T:dropItem("seeds", direction, 0) then -- drop all other seeds as chest is full |
11009 | + | |
11010 | - | T:dropItem("seeds", "up", 0) |
11010 | + | |
11011 | - | -- or could print a message and wait for player to empty storage |
11011 | + | |
11012 | colors.red, -- Cube around Blaze spawner | |
11013 | colors.cyan, -- Flood mob farm floor | |
11014 | colors.blue, -- Create mob bubble lift | |
11015 | colors.brown, -- Dig mob drop trench | |
11016 | colors.gray -- Build Endermen observation tower | |
11017 | }) | |
11018 | - | function lib.watchFarm(R) |
11018 | + | |
11019 | { | |
11020 | colors.lime, -- Clear field (inc trees) | |
11021 | colors.magenta, -- Clear a rectangle (+ u/d opt) | |
11022 | colors.pink, -- Clear single wall up/down | |
11023 | colors.purple, -- Clear rectangular wall section | |
11024 | - | local isReady, crop, seed, status -- bool, string, string, integer |
11024 | + | |
11025 | - | isReady, crop, seed, status, R = lib.isCropReady(R, "forward") -- eg true, "minecraft:carrots", "7 / 7" or false, "", "" |
11025 | + | |
11026 | colors.brown, -- Dig a trench | |
11027 | colors.gray, -- Carve mountain side | |
11028 | colors.lightBlue, -- Place a floor or ceiling | |
11029 | colors.red -- Direct control of movement | |
11030 | }) | |
11031 | table.insert(options, | |
11032 | { | |
11033 | colors.yellow, -- Sand based utilities | |
11034 | colors.blue, -- Vertical wall from surface | |
11035 | - | if crop:find("mysticalagriculture") ~= nil then |
11035 | + | |
11036 | - | R.mysticalAgriculture = true |
11036 | + | |
11037 | colors.lightGray, -- Sinking platform | |
11038 | colors.orange, -- Ocean monument utilities | |
11039 | colors.brown, -- Ladder down to water/lava | |
11040 | - | isReady, crop, seed, status, R = lib.isCropReady(R, "forward") -- eg true, "minecraft:carrots", "7 / 7" or false, "", "" |
11040 | + | |
11041 | colors.lightBlue, -- Convert all water to source | |
11042 | - | until isReady |
11042 | + | |
11043 | - | T:saveToLog("Local crops ripe", true) |
11043 | + | |
11044 | - | seed, crop = lib.manageTree(R) -- "", "" or name of seed, crop |
11044 | + | |
11045 | - | return seed, crop |
11045 | + | |
11046 | colors.yellow, -- build a wall | |
11047 | colors.orange, -- build rectangular structure | |
11048 | colors.lightGray, -- gable end roof | |
11049 | - | ENTRY POINT********************************************** |
11049 | + | |
11050 | colors.red, -- Place Redstone:torch level track | |
11051 | colors.red, -- Place Redstone:torch upward track | |
11052 | colors.orange, -- Build downward track | |
11053 | colors.brown -- Build upward track | |
11054 | }) | |
11055 | table.insert(options, | |
11056 | { | |
11057 | - | --T:setUseLog(true, "farmLog.txt", true) -- T:setUseLog(use, filename, delete) |
11057 | + | |
11058 | - | --dbug = true -- set dbug flag |
11058 | + | |
11059 | - | --if not R.auto then -- not running from startup.lua |
11059 | + | |
11060 | - | --utils.waitForInput("Logging and debugging enabled") --utils.waitForInput(message) |
11060 | + | |
11061 | - | --end |
11061 | + | |
11062 | }) | |
11063 | - | R = utils.checkFarmPosition(R) -- should be facing crops, placed above water source. R.ready, R.networkFarm is true/false |
11063 | + | |
11064 | - | if R.networkFarm then |
11064 | + | |
11065 | - | local message = network.loadStorageLists() -- initialises or creates lists of where an item can be found: GLOBAL LISTS! |
11065 | + | |
11066 | - | if message ~= nil then return {message} end |
11066 | + | |
11067 | local function chooseTask(R) | |
11068 | - | if not R.ready then -- not in correct starting place |
11068 | + | |
11069 | - | R = lib.goHome(R) |
11069 | + | |
11070 | - | if not R.ready then -- try to find home |
11070 | + | |
11071 | coloured menu: | |
11072 | local pp = | |
11073 | { | |
11074 | prompt = colors.green, | |
11075 | itemColours = {colors.white, colors.red, ... one for each item}, | |
11076 | - | "barrel or chest to my right and behind", |
11076 | + | |
11077 | - | "(or modem behind if networked farm)" |
11077 | + | |
11078 | choice, modifier = menu.menu or menu.new("Choose your option", options, pp) | |
11079 | ]] | |
11080 | local lib = {} | |
11081 | - | if not T:isEmpty() then -- items in turtle inventory |
11081 | + | |
11082 | - | local logSlot = T:getItemSlot("log") |
11082 | + | |
11083 | local listOfItems = itemsRequired[choice] | |
11084 | - | if R.networkFarm then |
11084 | + | |
11085 | - | lib.refuelWithLogs(R, logSlot) -- use any logs for fuel |
11085 | + | |
11086 | lib.showItems(listOfItems) | |
11087 | - | T:go("L1F1") -- move to buried storage chest/barrel |
11087 | + | |
11088 | - | lib.refuelWithLogs(R, logSlot) -- use any logs for fuel |
11088 | + | |
11089 | - | T:go("R2F1") -- facing seed chest/barrel |
11089 | + | |
11090 | local options ={"Continue with selected task", "return to menu", "Return to main menu","Quit application"} | |
11091 | local option = menu.menu("Choose your option", options, pp, "Type number + Enter ") | |
11092 | - | if not T:isEmpty() then -- still items in turtle inventory |
11092 | + | |
11093 | - | lib.storeCrops(R) |
11093 | + | |
11094 | elseif option == 3 then | |
11095 | choice = 0 -- return to main menu | |
11096 | - | -- in correct position. Check equipment first, harvest tree, re-equip then harvest crops |
11096 | + | |
11097 | - | local hoeSlot = lib.checkEquipment(R, "minecraft:diamond_hoe") -- returns slot or 0 |
11097 | + | |
11098 | -- else return original value of choice | |
11099 | - | if hoeSlot == 0 then -- hoe not in inventory |
11099 | + | |
11100 | - | local message |
11100 | + | |
11101 | - | hoeSlot, message = lib.getHoe() |
11101 | + | |
11102 | - | if message ~= "" then |
11102 | + | |
11103 | - | return {message} |
11103 | + | |
11104 | function lib.showItems(listOfItems) | |
11105 | T:clear() | |
11106 | - | -- hoe present or user cancelled request for hoe. Turtle is ready to exchange items |
11106 | + | |
11107 | - | if hoeSlot > 0 then |
11107 | + | |
11108 | - | T:equip("right", "minecraft:diamond_hoe", 0) -- equip hoe and put crafting chest into barrel |
11108 | + | |
11109 | - | if R.networkFarm then -- drop crafting table into storage |
11109 | + | |
11110 | - | network.sendItemToNetworkStorage(R, "barrel", "minecraft:crafting_table", 1) |
11110 | + | |
11111 | - | else -- put crafting table into barrel in floor |
11111 | + | |
11112 | - | T:dropItem("crafting", "down") |
11112 | + | |
11113 | - | T:go("B1R1") |
11113 | + | |
11114 | menu.colourWrite("Enter to continue", colors.yellow, colors.black, nil, true) | |
11115 | - | else -- hoe not present: return to start and exit |
11115 | + | |
11116 | - | if not R.networkFarm then |
11116 | + | |
11117 | - | T:go("B1R1") |
11117 | + | |
11118 | function lib.getItemList(subChoice, itemsRequired) | |
11119 | local listOfItems = itemsRequired[subChoice] | |
11120 | lib.showItems(listOfItems) | |
11121 | end | |
11122 | ||
11123 | - | local isFarmToRight, isFarmToFront = false, false |
11123 | + | |
11124 | - | local isReady, crop, seed, status |
11124 | + | |
11125 | - | isReady, crop, seed, status, R = lib.isCropReady(R, "forward") |
11125 | + | |
11126 | else -- eg main option 1 (mining), sub-option 1 (create mine) = 1 + 10 = 11 | |
11127 | - | local init = false |
11127 | + | |
11128 | end | |
11129 | - | seed, crop = lib.askPlayerForCrops() |
11129 | + | |
11130 | - | if crop ~= "" or seed ~= "" then -- something has been chosen |
11130 | + | |
11131 | - | T:saveToLog("Initial planting of "..crop, true) |
11131 | + | |
11132 | - | R, isFarmToRight, isFarmToFront = lib.harvest(R, seed, crop) -- harvest plot a1 plots to right / front recorded |
11132 | + | |
11133 | - | init = true |
11133 | + | |
11134 | local prompt = "Choose an option" | |
11135 | - | watch = false -- not watching, continue with planting |
11135 | + | |
11136 | local subPrompt = "Choose (+h = help +i = items eg 3h):" | |
11137 | local options = getTaskOptions() | |
11138 | local menuColours = getTaskColours() | |
11139 | - | if watch and not init then -- init true when farm first planted |
11139 | + | |
11140 | - | seed, crop = lib.watchFarm(R) -- waits if required, returns seed / crop |
11140 | + | |
11141 | - | init = false |
11141 | + | |
11142 | --local pp = utils.getPrettyPrint()-- uses default colours | |
11143 | - | T:saveToLog("Beginning "..crop.. " management", true) |
11143 | + | |
11144 | - | R, isFarmToRight, isFarmToFront = lib.harvest(R, seed, crop) -- harvest plot a1 plots to right / front recorded |
11144 | + | |
11145 | - | lib.farmAll(R, isFarmToRight, isFarmToFront) |
11145 | + | |
11146 | menu returns choice=nil if user enters just q or h | |
11147 | - | if R.networkFarm then |
11147 | + | |
11148 | - | T:unequip("right") -- unequip hoe |
11148 | + | |
11149 | - | network.getItemFromNetwork("barrel", "minecraft:crafting_table", 1) |
11149 | + | |
11150 | - | network.sendItemToNetworkStorage(R, "barrel", "minecraft:diamond_hoe", 1) |
11150 | + | |
11151 | - | T:equip("right", "minecraft:crafting_table", 0) -- equip crafting_table |
11151 | + | |
11152 | Canal, bridge and walkway pink | |
11153 | - | T:go("L1F1") |
11153 | + | |
11154 | - | while T:suck("down") do end -- recover items from storagebelow |
11154 | + | |
11155 | - | T:equip("right", "minecraft:crafting_table", 0) -- equip crafting_table |
11155 | + | |
11156 | - | T:dropItem("minecraft:diamond_hoe", "down") -- drop hoe into storage |
11156 | + | |
11157 | - | T:dropItem("crafting", "down") -- in case spare one picked by mistake |
11157 | + | |
11158 | ]] | |
11159 | ||
11160 | if menuState == 0 then | |
11161 | pp.itemColours = menuColours.main | |
11162 | local mainChoice, modifier = menu.menu(mainPrompt, options.main, pp) -- open main menu options | |
11163 | if modifier == "q" then | |
11164 | R.choice = -1 | |
11165 | return R -- quit application | |
11166 | elseif modifier == "h" then -- get help on main menu items | |
11167 | getTaskHelp(1, mainChoice) -- "" or any return string for more | |
11168 | R.choice = 0 | |
11169 | return R -- quit task system so it re-starts as help menu chosen R.choice = 0 | |
11170 | else | |
11171 | menuState = 1 -- next level so use sub-menu | |
11172 | R.choice = mainChoice -- 1-10 | |
11173 | end | |
11174 | else | |
11175 | pp.prompt = colors.yellow | |
11176 | pp.itemColours = menuColours[R.choice] | |
11177 | subChoice, modifier = menu.menu(subPrompt, options[R.choice], pp, "Back = 'q' or number + Enter: ") -- open submenu options | |
11178 | if modifier == "q" then | |
11179 | R.choice = 0 -- return to root menu. change this to -1 if quit application preferred | |
11180 | return R -- quit task system so it re-starts first menu | |
11181 | elseif modifier == "i" then -- get list of items | |
11182 | local index = lib.getChoice(R.choice, subChoice) | |
11183 | lib.getItemList(index, itemsRequired) -- list of items shown | |
11184 | subChoice = nil -- allow menu to continue | |
11185 | elseif modifier == "h" then -- get help on main menu items | |
11186 | local index = lib.getChoice(R.choice, subChoice) | |
11187 | index = lib.getHelp(index, itemsRequired, pp) | |
11188 | --R = lib.getHelp(R, itemsRequired, pp) -- if R.choice reset to 0 then will continue | |
11189 | if index == -2 then -- redraw sub-menu | |
11190 | subChoice = nil -- allow menu to continue | |
11191 | elseif index == -1 then -- if R.choice reset to 0 then will continue | |
11192 | R.choice = -1 | |
11193 | return R | |
11194 | elseif index == 0 then | |
11195 | R.choice = 0 | |
11196 | menuState = 0 -- if R.choice reset to 0 then back to main menu | |
11197 | end | |
11198 | end | |
11199 | if subChoice ~= nil then | |
11200 | R.choice = lib.getChoice(R.choice, subChoice) | |
11201 | return R -- exit loop | |
11202 | - | --local pp = utils.getPrettyPrint() |
11202 | + | |
11203 | - | local choices = {"Plant or harvest this farm complex"} -- 1. |
11203 | + | |
11204 | end | |
11205 | return R | |
11206 | end | |
11207 | - | table.insert(choices, "Disable automatic farm management") -- 2. |
11207 | + | |
11208 | local function getTask(R) | |
11209 | - | table.insert(choices, "Enable automatic farm management") -- 2. |
11209 | + | -- Called from main(): R = getTask(R) |
11210 | local lib = {} | |
11211 | ||
11212 | - | if not R.networkFarm then |
11212 | + | |
11213 | - | table.insert(choices, "Convert to Network Storage") -- 3. |
11213 | + | |
11214 | - | table.insert(pp.itemColours, colors.magenta) |
11214 | + | |
11215 | return true | |
11216 | - | if R.mysticalAgriculture then |
11216 | + | |
11217 | - | --table.insert(choices, "Convert to Mystical Agriculture") |
11217 | + | |
11218 | - | table.insert(choices, "Upgrade Mystical Agriculture soil") --3/4 |
11218 | + | |
11219 | - | table.insert(pp.itemColours, colors.green) |
11219 | + | |
11220 | ||
11221 | local prompt = "Choose an option" | |
11222 | local noAutoHelp = {24, 47, 49, 53, 54, 81, 85} | |
11223 | if not lib.isAutoHelp(R.choice, noAutoHelp) then -- exclude Water canal, ice canal, sand utilities, monument utilities, dragon trap | |
11224 | getTaskHelp(2, R.choice, true) | |
11225 | menu.clear() | |
11226 | end | |
11227 | -- 01. MINING | |
11228 | if R.choice >= 11 and R.choice <= 13 then -- createLadder, createStaircase, createMine) | |
11229 | --getTaskHelp(2, R.choice, true) | |
11230 | --menu.clear() | |
11231 | elseif R.choice == 14 then -- safe drop to water | |
11232 | - | elseif R.subChoice == 2 then -- enable/disable auto farm |
11232 | + | |
11233 | local destLevel = menu.getInteger("Go down to level? ("..currentLevel - 2 .." to "..bedrock + 5 ..")", bedrock + 5 , currentLevel - 2, nil, colors.blue, nil, bedrock + 5) | |
11234 | R.height = math.abs(destLevel - currentLevel) | |
11235 | elseif R.choice == 15 then -- bubble lift | |
11236 | local currentLevel = menu.getInteger("Current level (F3->Y coord)? ", bedrock + 5 , ceiling, nil, colors.blue, nil, bedrock + 5) | |
11237 | local destLevel = menu.getInteger("Go up to level? ("..currentLevel + 2 .." to "..ceiling ..") ", currentLevel + 2, ceiling, nil, colors.lightGray) | |
11238 | --[[if currentLevel <= bedrock + 5 then | |
11239 | if menu.getBoolean("Confirm close to bedrock (y / n) ", nil, colors.yellow, colors.black) then | |
11240 | R.data = "bedrock" | |
11241 | end | |
11242 | end]] | |
11243 | R.height = math.abs(destLevel - currentLevel) | |
11244 | elseif R.choice == 16 then -- create mining corridor system default: square 17 x 17 | |
11245 | local choices = {"At corridor start, on the floor", | |
11246 | "At corridor start, on the ceiling", | |
11247 | "On floor, move forward to start", | |
11248 | "On ceiling, move forward to start"} | |
11249 | pp.itemColours = {colors.lime, colors.green, colors.magenta, colors.pink} | |
11250 | local userChoice, modifier = menu.menu("Starting position?", choices, pp, "Type number + Enter ") -- 1 to 4 | |
11251 | if modifier == "q" then -- quit chosen | |
11252 | R.data = "quit" | |
11253 | return R | |
11254 | end | |
11255 | R.width = menu.getInteger("Width (2-64 default 17) ", 2, 64, nil, colors.yellow, nil, 17) | |
11256 | R.length = menu.getInteger("Length (2-64 default 17) ", 2, 64, nil, colors.orange, nil, 17) | |
11257 | - | --elseif R.subChoice == 3 and #choices == 4 then -- convert normal farm to network storage |
11257 | + | |
11258 | - | elseif R.subChoice == 3 then -- convert normal farm to network storage |
11258 | + | |
11259 | - | local isMain = false |
11259 | + | |
11260 | end | |
11261 | - | local message = ("~yellow~You have chosen to convert this farm ".. |
11261 | + | |
11262 | - | "to ~magenta~network storage ~yellow~with modems.".. |
11262 | + | |
11263 | - | "All ~brown~chests and barrels ~red~will be removed.\n") |
11263 | + | |
11264 | - | line = menu.colourText(line, message, true, true) |
11264 | + | |
11265 | - | if menu.getBoolean("Is this the main or only plot? (y/n)", line + 3, colors.orange, colors.black) then |
11265 | + | |
11266 | - | isMain = true |
11266 | + | |
11267 | "On floor diagonally to left"} -- just finished corridor | |
11268 | - | T:checkInventoryForItem({"stone"}, {16}) |
11268 | + | |
11269 | - | T:checkInventoryForItem({"dirt"}, {2}) |
11269 | + | |
11270 | if modifier == "q" then -- quit chosen | |
11271 | - | T:checkInventoryForItem({"barrel"}, {1}) |
11271 | + | |
11272 | - | T:checkInventoryForItem({"ladder"}, {5}) |
11272 | + | |
11273 | - | if isMain then |
11273 | + | |
11274 | - | T:checkInventoryForItem({"chest"}, {8}) |
11274 | + | |
11275 | - | T:checkInventoryForItem({"wired_modem_full"}, {3}) |
11275 | + | |
11276 | - | T:checkInventoryForItem({"computercraft:cable"}, {70}) |
11276 | + | |
11277 | - | return createFarm(R, "convertWithStorage") |
11277 | + | |
11278 | --getTaskHelp(2, R.choice, true) | |
11279 | - | T:checkInventoryForItem({"wired_modem_full"}, {2}) |
11279 | + | |
11280 | - | T:checkInventoryForItem({"computercraft:cable"}, {57}) |
11280 | + | |
11281 | - | return createFarm(R, "convert") |
11281 | + | |
11282 | if menu.getBoolean("Leave bedrock exposed? (y/n) ", nil, colors.yellow) then | |
11283 | - | --elseif R.subChoice == 3 and #choices == 3 then -- upgrade farmland with essence (network opt not present) |
11283 | + | |
11284 | - | --elseif R.subChoice == 3 and #choices == 3 then -- upgrade farmland with essence (network opt not present) |
11284 | + | |
11285 | - | --return upgradeFarmland(R) |
11285 | + | |
11286 | - | elseif R.subChoice == 4 then -- upgrade farmland with essence |
11286 | + | |
11287 | - | return upgradeFarmland(R) |
11287 | + | |
11288 | elseif R.choice == 22 then --Create treefarm | |
11289 | R.width = 15 | |
11290 | R.length = 15 | |
11291 | pp.itemColours = {colors.lightGray, colors.green} | |
11292 | choices = {"New tree farm. Start here", "On right side of existing farm" } | |
11293 | local choice = menu.menu(prompt, choices, pp, "Type number + Enter ") | |
11294 | if choice == 2 then | |
11295 | R.data = "existing" | |
11296 | end | |
11297 | R.up = menu.getBoolean({"Any blocks/trees above current level","in a 15 x 15 block area (y/n) "}, nil, {colors.yellow, colors.orange}, colors.black) | |
11298 | elseif R.choice == 23 then -- plant treefarm | |
11299 | local choices = {"16 single trees", "4 double trees any type"} | |
11300 | pp.itemColours = {colors.lime, colors.green} | |
11301 | R.subChoice = menu.menu(prompt, choices, pp, "Type number + Enter ") | |
11302 | --elseif R.choice == 24 then -- Harvest treefarm | |
11303 | ||
11304 | elseif R.choice == 25 then -- Build wall or fence | |
11305 | R.width = menu.getInteger("Width of the area (1-64)", 1, 64, nil, colors.yellow) | |
11306 | R.length = menu.getInteger("Length of the area (1-64)", 1, 64, nil, colors.orange) | |
11307 | R.torchInterval = menu.getInteger("Torch spacing? (0-64)", 0, 64, nil, colors.red) | |
11308 | if menu.getBoolean("Storage barrels in corners? (y/n)", nil, colors.brown) then | |
11309 | R.data = "barrel" | |
11310 | end | |
11311 | elseif R.choice == 26 then -- Harvest and replant natural forest | |
11312 | ||
11313 | ||
11314 | -- 03. FARMING | |
11315 | elseif R.choice == 31 then -- new crop farm | |
11316 | ||
11317 | elseif R.choice == 32 then -- extend crop farm | |
11318 | local choices = {"Add a farm at the back", "Add a farm to the right"} | |
11319 | pp.itemColours = {colors.lime, colors.green} | |
11320 | R.subChoice = menu.menu(prompt, choices, pp, "Type number + Enter ") | |
11321 | elseif R.choice == 33 then -- manage crop farm | |
11322 | ||
11323 | elseif R.choice == 34 then -- fence or wall | |
11324 | R.length = menu.getInteger("Length of wall / fence (1-256)", 1, 256, nil, colors.orange) | |
11325 | R.torchInterval = menu.getInteger("Torch spacing? (0-64)", 0, 64, nil, colors.red) | |
11326 | elseif R.choice == 35 then -- rectangle fence or wall | |
11327 | R.width = menu.getInteger("Width of the area (1-64)", 1, 64, nil, colors.yellow) | |
11328 | R.length = menu.getInteger("Length of the area (1-64)", 1, 64, nil, colors.orange) | |
11329 | R.torchInterval = menu.getInteger("Torch spacing? (0-64)", 0, 64, nil, colors.red) | |
11330 | ||
11331 | -- 04. OBSIDIAN | |
11332 | elseif R.choice == 41 then -- Harvest obsidian | |
11333 | R.width = menu.getInteger("Width of the area (1-64) ", 1, 64, nil, colors.yellow) | |
11334 | R.length = menu.getInteger("Length of the area (1-64) ", 1, 64, nil, colors.orange) | |
11335 | elseif R.choice == 42 or R.choice == 43 then -- build Nether portal / demolish Nether portal | |
11336 | local choices = {"Facing portal: forward, turn right", | |
11337 | "Aligned with portal: start ahead"} | |
11338 | pp.itemColours = {colors.pink, colors.red} | |
11339 | local userChoice, modifier = menu.menu("Starting position?", choices, pp, "Type number + Enter ") -- 1 to 2 | |
11340 | R.subChoice = userChoice | |
11341 | if modifier == "q" then -- quit chosen | |
11342 | R.data = "quit" | |
11343 | return R | |
11344 | end | |
11345 | R.length = menu.getInteger("Portal width", 1, 64, nil, colors.yellow, nil, 4) | |
11346 | R.height = menu.getInteger("Portal height (inc. buried base)", 1, 64, nil, colors.lightGray, nil, 5) | |
11347 | R.width = menu.getInteger("Thickness (Usually 1) Enter = 1)", 1, 64, nil, colors.red, nil, 1) | |
11348 | if menu.getBoolean("Base below surface (y/n)", nil, colors.orange) then | |
11349 | R.data = "bury" | |
11350 | end | |
11351 | elseif R.choice == 44 then -- Netherite stripping | |
11352 | R.width = 1 | |
11353 | while R.length == 0 or R.length % 16 > 0 do | |
11354 | R.length = menu.getInteger("Strip length (divisible by 16) ", 16, 512, 1, colors.orange) | |
11355 | if R.length % 16 > 0 then | |
11356 | menu.colourText(1, "~red~Must be multiple of 16") | |
11357 | end | |
11358 | end | |
11359 | R.torchInterval = 16 | |
11360 | R.data = "seal" | |
11361 | elseif R.choice == 45 then -- undermine dragon towers | |
11362 | ||
11363 | elseif R.choice == 46 then -- deactivate dragon tower | |
11364 | ||
11365 | elseif R.choice == 47 then -- build dragon water trap | |
11366 | local text = | |
11367 | [[~yellow~You ~red~MUST ~yellow~have already constructed a | |
11368 | bridge / tunnel into the dragon island | |
11369 | to allow for safe construction of the | |
11370 | dragon trap. | |
11371 | ||
11372 | If not use toolkit: | |
11373 | ~brown~5.~gray~2 Covered path or tunnel~yellow~ length 100 | |
11374 | ||
11375 | start centre of obsidian platform: | |
11376 | 100,49,0 facing west]] | |
11377 | menu.colourText(1, text) | |
11378 | if menu.getBoolean("Bridge already made? (y/n)", 12, colors.orange) then | |
11379 | getTaskHelp(2, R.choice, true) | |
11380 | menu.clear() | |
11381 | else | |
11382 | R.data = "quit" | |
11383 | return R | |
11384 | end | |
11385 | elseif R.choice == 48 then -- build end portal minecart station | |
11386 | elseif R.choice == 49 then -- Shulker harvesting | |
11387 | local items = | |
11388 | { | |
11389 | "Shulker is above", | |
11390 | "Shulker is ahead", | |
11391 | "Shulker is below", | |
11392 | "Climb tower wall", | |
11393 | "Clear roof above", | |
11394 | "Clear outside walls" | |
11395 | } | |
11396 | pp.itemColours = {colors.lightGray, colors.brown, colors.blue, colors.yellow, colors.orange, colors.lightGray} | |
11397 | R.subChoice = menu.menu("Which utility? ", items, pp) | |
11398 | getTaskHelp(2, R.choice * 10 + R.subChoice, true) -- eg 490 + 1 = 491 | |
11399 | menu.clear() | |
11400 | ||
11401 | -- 05. CANAL BRIDGE | |
11402 | elseif R.choice == 51 then --single path | |
11403 | if menu.getBoolean("Shorten an existing path? (y/n)", nil, colors.brown) then | |
11404 | R.data = "reduce" | |
11405 | end | |
11406 | if R.data == "reduce" then | |
11407 | R.length = menu.getInteger("Reduce by? 0 = here to end", 0, 1024, nil, colors.orange, nil, 64) | |
11408 | else | |
11409 | R.length = menu.getInteger("Path length? 0 = continuous ", 0, 1024, nil, colors.orange, nil, 64) | |
11410 | R.torchInterval = menu.getInteger("Torch spacing? (0-64)", 0, 64, line, colors.red, nil, 0) | |
11411 | end | |
11412 | elseif R.choice == 52 then -- 2 block corridor / covered walkway | |
11413 | R.length = menu.getInteger("Corridor length?", 1, 1024, nil, colors.orange, nil, 64) | |
11414 | R.torchInterval = menu.getInteger("Torch spacing? (0-64)", 0, 64, nil, colors.red) | |
11415 | if menu.getBoolean("Seal off water or lava? (y/n)", nil, colors.brown) then | |
11416 | R.data = "seal" | |
11417 | end | |
11418 | elseif R.choice == 53 then --left/right side of new/existing canal | |
11419 | local line = getTaskHelp(2, 110, true, true) -- request line no of help display if needed for getInteger | |
11420 | R.data = menu.getInteger("Choose method 1 or 2", 1, 2, line + 1, colors.white) -- 2 or 4 turtles | |
11421 | menu.clear() | |
11422 | line = getTaskHelp(2, R.choice, true, true) -- request line no of help display if needed for getInteger | |
11423 | R.subChoice = menu.getInteger("Type position of this turtle", 1, 6, line + 1, colors.white) | |
11424 | local position = "on ground" | |
11425 | local side = "left" | |
11426 | local colour = colors.lime | |
11427 | if R.subChoice == 1 then | |
11428 | R.side = "L" | |
11429 | R.height = 1 | |
11430 | position = "on ground" | |
11431 | colour = colors.lime | |
11432 | elseif R.subChoice == 2 then | |
11433 | R.side = "L" | |
11434 | R.height = 1 | |
11435 | position = "above canal" | |
11436 | colour = colors.orange | |
11437 | elseif R.subChoice == 3 then | |
11438 | R.side = "R" | |
11439 | side = "right" | |
11440 | R.height = 1 | |
11441 | position = "above canal" | |
11442 | colour = colors.brown | |
11443 | elseif R.subChoice == 4 then | |
11444 | R.side = "R" | |
11445 | side = "right" | |
11446 | R.height = 1 | |
11447 | colour = colors.green | |
11448 | elseif R.subChoice == 5 then | |
11449 | R.side = "L" | |
11450 | R.height = 0 | |
11451 | position = "on canal base" | |
11452 | colour = colors.blue | |
11453 | elseif R.subChoice == 6 then | |
11454 | R.side = "R" | |
11455 | side = "right" | |
11456 | R.height = 0 | |
11457 | position = "on canal base" | |
11458 | colour = colors.cyan | |
11459 | end | |
11460 | line = menu.clear() | |
11461 | if R.data == 1 or (R.data == 2 and (R.subChoice == 1 or R.subChoice == 4)) then | |
11462 | R.torchInterval = menu.getInteger("Torch spacing? (0-64)", 0, 64, line, colors.red, nil, 0) | |
11463 | end | |
11464 | -- menu.colourPrint(text, fg, bg, width) | |
11465 | -- menu.colourText(row, text, reset) | |
11466 | menu.colourPrint("Turtle placed "..side.." "..position, colour) | |
11467 | R.length = menu.getInteger("Canal length? 0 = continuous ", 0, 512, line + 2, colors.orange, nil, 64) | |
11468 | elseif R.choice == 54 then --ice canal 4 sections: edge+torch, edge, centre+ice, centre no ice | |
11469 | local line = getTaskHelp(2, R.choice, true, true) -- request line no of help display if needed for getInteger | |
11470 | R.subChoice = menu.getInteger("Type turtle position", 1, 8, line, colors.white) | |
11471 | R.side = "L" | |
11472 | local position = "on towpath" | |
11473 | local side = "left" | |
11474 | local colour = colors.lime | |
11475 | line = menu.clear() | |
11476 | --[[ | |
11477 | new canal | |
11478 | 1 = left towpath- move to centre left | |
11479 | 2 = centre left ice or hollow | |
11480 | 3 = centre right ice or hollow | |
11481 | 4 = right side - move to centre right | |
11482 | convert water canal | |
11483 | 5 = left towpath | |
11484 | 6 = centre left ice or air | |
11485 | 7 = centre right ice or air | |
11486 | 8 = right towpath | |
11487 | ]] | |
11488 | if R.subChoice == 1 or R.subChoice == 4 or R.subChoice == 5 or R.subChoice == 8 then | |
11489 | -- on towpath r/l | |
11490 | R.torchInterval = menu.getInteger("Torch spacing? (0-64)", 0, 64, line, colors.red, nil, 0) | |
11491 | if R.subChoice == 4 or R.subChoice == 8 then | |
11492 | side = "right" | |
11493 | R.side = "R" | |
11494 | end | |
11495 | if R.subChoice <= 4 then -- 1 or 4 only | |
11496 | if menu.getBoolean("Place Ice as well? (y/n)", line + 1, colors.blue) then | |
11497 | R.data = "ice" | |
11498 | end | |
11499 | end | |
11500 | else -- on canal centre r/l | |
11501 | if R.subChoice == 3 or R.subChoice == 7 then | |
11502 | side = "right" | |
11503 | R.side = "R" | |
11504 | end | |
11505 | if R.subChoice == 2 or R.subChoice == 3 then -- new canal | |
11506 | R.torchInterval = menu.getInteger("Torch spacing? (0-64)", 0, 64, line, colors.red, nil, 0) | |
11507 | position = "above air/ice" | |
11508 | end | |
11509 | if menu.getBoolean("Place Ice as well? (y/n)", line + 1, colors.blue) then | |
11510 | R.data = "ice" | |
11511 | if R.subChoice == 6 or R.subChoice == 7 then | |
11512 | position = "alternate air/ice" | |
11513 | colour = colors.lightBlue | |
11514 | end | |
11515 | else | |
11516 | if R.subChoice == 6 or R.subChoice == 7 then | |
11517 | position = "on air spaces" | |
11518 | colour = colors.lighGray | |
11519 | if R.subChoice == 7 then | |
11520 | side = "right" | |
11521 | R.side = "R" | |
11522 | end | |
11523 | end | |
11524 | end | |
11525 | end | |
11526 | R.length = menu.getInteger("Canal length? 0 = continuous ", 0, 1024, line + 2, colors.orange, nil, 64) | |
11527 | menu.colourPrint("Turtle on "..side.." side "..position, colour) | |
11528 | sleep(2) | |
11529 | elseif R.choice == 55 then --platform | |
11530 | R.width = menu.getInteger("Platform width", 1, 256, 1, colors.yellow) | |
11531 | R.length = menu.getInteger("Platform length", 1, 256, 2, colors.orange) | |
11532 | if menu.getBoolean("Remove blocks above? (y/n)",3, colours.red) then | |
11533 | R.up = true | |
11534 | end | |
11535 | ||
11536 | elseif R.choice == 56 then --sinking platform | |
11537 | R.width = menu.getInteger("Width (excluding retaining wall)? ", 1, 1024, nil, colors.yellow) | |
11538 | R.length = menu.getInteger("Length (excluding retaining wall)? ", 1, 1024 / R.width, nil, colors.orange) | |
11539 | R.height = menu.getInteger("Levels to go down?", 1, 1024 / R.width * R.length, nil, colors.blue) | |
11540 | elseif R.choice == 57 then --boat bubble lift | |
11541 | R.height = menu.getInteger("Levels to go up?", 1, ceiling - 2, nil, colors.lightBlue) | |
11542 | ||
11543 | -- 06. MOB SPAWNER TOOLS | |
11544 | elseif R.choice == 61 then -- create cube round mob spawner | |
11545 | local text = | |
11546 | [[~yellow~Turtle placement options: | |
11547 | ||
11548 | ~lime~1. On top or in front of the spawner | |
11549 | ~green~(cave spider OR no chests around) | |
11550 | ~lightGray~2. Outside the dungeon at floor or | |
11551 | ceiling level ~red~1 block from corner | |
11552 | ~yellow~Make sure you have access to the block | |
11553 | facing the spawner, as any chests | |
11554 | found inside will be placed outside | |
11555 | the new dungeon wall at this height | |
11556 | ||
11557 | ~white~Enter to continue | |
11558 | ]] | |
11559 | menu.colourText(nil, text, true) | |
11560 | read() | |
11561 | menu.clear() | |
11562 | R.data = "spawner" | |
11563 | if menu.getBoolean("Any chests around spawner? (y/n)",1, colours.red) then | |
11564 | R.data = "chest" | |
11565 | end | |
11566 | local choices = {"Turtle on spawner (no chests)", | |
11567 | "Outside wall: left side, floor", | |
11568 | "Outside wall: left side, ceiling", | |
11569 | "Outside wall: right side, floor", | |
11570 | "Outside wall: right side, ceiling"} | |
11571 | pp.itemColours = {colors.red, colors.lime, colors.orange, colors.green, colors.yellow} | |
11572 | local userChoice, modifier = menu.new("Select turtle position", choices, pp) -- 1 to 5 | |
11573 | ||
11574 | if modifier == "q" then -- quit chosen | |
11575 | R.data = "quit" | |
11576 | return R | |
11577 | end | |
11578 | R.subChoice = userChoice | |
11579 | if R.subChoice > 1 then -- get dungeon wall dimensions | |
11580 | R.width = menu.getInteger("Dungeon external width ", 0, 11, nil, colors.yellow, nil, 11) | |
11581 | R.length = menu.getInteger("Dungeon external length ", 0, 11, nil, colors.orange, nil, 11) | |
11582 | end | |
11583 | ||
11584 | elseif R.choice == 62 then -- Blaze spawner | |
11585 | local text = | |
11586 | [[~yellow~Turtle placement options: | |
11587 | ||
11588 | ~red~1a On top of the spawner | |
11589 | ||
11590 | ~red~1b ~orange~At the same level in direct line of | |
11591 | spawner.~yellow~ (can be behind a safety wall) | |
11592 | ||
11593 | ~red~1c~lightGray~ Room below spawner (via stairs) | |
11594 | ||
11595 | ~lime~2 Finish build: In brick floor outside | |
11596 | existing cube. (facing player) | |
11597 | ||
11598 | ~white~Enter to continue]] | |
11599 | menu.colourText(nil, text, true) | |
11600 | read() | |
11601 | pp.itemColours = {colors.red, colors.lime} | |
11602 | R.subChoice = menu.new("Choose your option", {"New Blaze spawner", "Complete part build (killzone)"}, pp, "Type number + Enter") -- 1 = new, 2= continue | |
11603 | R.data = "blaze" -- default | |
11604 | if R.subChoice == 1 then -- new blaze spawner | |
11605 | text = | |
11606 | [[~yellow~Turtle placement options: | |
11607 | ~red~1. On top of the spawner | |
11608 | ~orange~2. In direct sight (safety wall ok) | |
11609 | ~lightGray~3. Room below spawner (via stairs) | |
11610 | |*|*|*|*|*| Ceiling | |
11611 | |*|*|~red~T~lightGray~|*|*| Turtle under ceiling | |
11612 | |*|~brown~+~lightGray~|*|~brown~+~lightGray~|*| Top of fence | |
11613 | |*|~brown~+~lightGray~|*|~brown~+~lightGray~|*| | |
11614 | |*|~brown~+~lightGray~|*|~brown~+~lightGray~|*| Bottom of fence | |
11615 | |*|*|*|*|*| Floor level]] | |
11616 | --R.subChoice = menu.new("Choose your position", {"On top of spawner", "In direct sight (safety wall ok)", "Room below spawner"}, pp, "Type number + Enter") | |
11617 | --getInteger(prompt, minValue, maxValue, row, fg, bg, default) | |
11618 | T:clear() | |
11619 | menu.colourText(nil, text, true) | |
11620 | R.subChoice = menu.getInteger("Enter position number", 1, 3, 12, colors.white) | |
11621 | else | |
11622 | R.data = "restart" -- complete part build | |
11623 | end | |
11624 | elseif R.choice == 63 then -- flood spawner cube | |
11625 | local choices = {"Bubble lift", "Computercraft mob softener"} | |
11626 | pp.itemColours = {colors.lime, colors.orange} | |
11627 | local userChoice = menu.menu("Flood for Mob grinder type?", choices, pp, "Type number + Enter ") | |
11628 | R.subChoice = userChoice -- 1 bubble, 2 computercraft | |
11629 | elseif R.choice == 64 then -- create bubble lift at mob spawner | |
11630 | local choices = {"Dropzone on left", "Dropzone on right"} | |
11631 | pp.itemColours = {colors.lime, colors.orange} | |
11632 | local userChoice = menu.menu("Which side do you want the mobs?", choices, pp, "Type number + Enter") | |
11633 | R.subChoice = userChoice -- 1 left, 2 right | |
11634 | elseif R.choice == 65 then -- Computercraft mob grinder | |
11635 | local choices = {"Use Sticky pistons", "Use non-sticky pistons"} | |
11636 | pp.itemColours = {colors.lime, colors.orange} | |
11637 | local userChoice = menu.menu("Which type of pistons?", choices, pp, "Type number + Enter ") | |
11638 | R.subChoice = userChoice -- 1 sticky, 2 normal | |
11639 | ||
11640 | -- 07. AREA CARVING | |
11641 | elseif R.choice == 71 then --Clear field | |
11642 | R.width = menu.getInteger("Width of the area (1-64)", 1, 64, nil, colors.yellow) | |
11643 | R.length = menu.getInteger("Length of the area (1-64)", 1, 64, nil, colors.orange) | |
11644 | if menu.getBoolean("Dirt on the surface (y/n)", nil, colors.brown) then | |
11645 | R.useBlockType = "dirt" | |
11646 | end | |
11647 | elseif R.choice == 72 then -- Clear solid rectangle R.width, R.length | |
11648 | R.width = menu.getInteger("Rectangle width (1-256)", 1, 256, nil, colors.yellow) | |
11649 | R.length = menu.getInteger("Rectangle length (1-256)", 1, 256, nil, colors.orange) | |
11650 | R.up = menu.getBoolean("Remove blocks above?", nil, colors.yellow) | |
11651 | R.down = menu.getBoolean("Remove blocks below?", nil, colors.orange) | |
11652 | if menu.getBoolean("Am I outside clearing zone (y/n)?", nil, colors.yellow) then | |
11653 | T:forward(1) | |
11654 | - | T:place(R.useBlockType, "forward", false) |
11654 | + | |
11655 | elseif R.choice == 73 then -- Clear wall | |
11656 | - | T:place("minecraft:redstone_torch", "forward", true) |
11656 | + | |
11657 | R.length = menu.getInteger("Length of wall (1-256) ", 1, 256, nil, colors.orange) | |
11658 | R.height = menu.getInteger("Height of wall (1-50) ", 1, 50, nil, colors.lightGray) | |
11659 | pp.itemColours = {colors.lime, colors.orange} | |
11660 | R.subChoice = menu.menu("Which direction?", {"Bottom -> Top", "Top -> Bottom"}, pp, "Type number + Enter ") -- open direction menu options | |
11661 | if R.subChoice == 1 then | |
11662 | if menu.getBoolean("Am I outside clearing zone (y/n)?", nil, colors.yellow) then | |
11663 | T:forward(1) | |
11664 | end | |
11665 | else | |
11666 | pp.itemColours = {colors.lightBlue, colors.cyan, colors.blue, colors.gray} | |
11667 | local choice = menu.menu("Exact position?", {"On top of clearing zone", "In front of clearing zone", "Inside clearing zone","Above AND outside"}, pp, "Type number + Enter ") | |
11668 | if choice == 1 then | |
11669 | T:down(1) | |
11670 | - | T:place("minecraft:redstone_torch", "up", false) |
11670 | + | |
11671 | T:forward(1) | |
11672 | elseif choice == 4 then | |
11673 | T:go("D1F1") | |
11674 | end | |
11675 | end | |
11676 | elseif R.choice == 74 then -- Clear rectangle perimeter only R.width, R.length | |
11677 | R.width = menu.getInteger("Perimeter width (1-256) ", 1, 256, nil, colors.yellow) | |
11678 | R.length = menu.getInteger("Perimeter length (1-256) ", 1, 256, nil, colors.orange) | |
11679 | R.height = 1 | |
11680 | if menu.getBoolean("Remove blocks above? (y/n)", 3, colours.red) then | |
11681 | - | -- already known R.networkFarm, R.subChoice (1 = singe, 2 = double, 3 = mangrove) |
11681 | + | |
11682 | - | --T:place(blockType, damageNo, leaveExisting, signText) |
11682 | + | |
11683 | if menu.getBoolean("Remove blocks below? (y/n)", 4, colours.red) then | |
11684 | R.down = true | |
11685 | - | function lib.checkSaplings(firstChoice, secondChoice) |
11685 | + | |
11686 | if menu.getBoolean("Am I outside clearing zone (y/n)?", 5, colors.yellow) then | |
11687 | T:forward(1) | |
11688 | end | |
11689 | elseif R.choice == 75 or R.choice == 76 then -- Clear hollow building floor/walls/ceiling OR clear solid object | |
11690 | R.width = menu.getInteger("Structure width (1-256)", 1, 256, nil, colors.yellow) | |
11691 | R.length = menu.getInteger("Structure length (1-256)", 1, 256, nil, colors.orange) | |
11692 | R.height = menu.getInteger("Depth/Height (1-256)", 1, 256, nil, colors.lightGray) | |
11693 | if R.choice == 75 then -- hollow building so need to check if floors/ceilings to be removed | |
11694 | R.data = {} | |
11695 | R.data.ceiling = false | |
11696 | R.data.floor = false | |
11697 | - | function lib.emptyInventory(R) |
11697 | + | |
11698 | - | if not T:isEmpty() then |
11698 | + | |
11699 | - | utils.useSticksAsFuel() |
11699 | + | |
11700 | - | network.sendItemToNetworkStorage(R, "barrel", "sapling", 64) |
11700 | + | |
11701 | - | network.sendItemToNetworkStorage(R, "barrel", "propagule", 64) |
11701 | + | |
11702 | - | network.sendItemToNetworkStorage(R, "barrel", "apple", 64) |
11702 | + | |
11703 | - | network.sendItemToNetworkStorage(R, "barrel", "dirt", 64) |
11703 | + | |
11704 | - | network.sendItemToNetworkStorage(R, "chest", "all", 0) |
11704 | + | |
11705 | R.subChoice = menu.menu("Which direction?", {"Bottom -> Top", "Top -> Bottom"}, pp, "Type number + Enter ") -- open direction menu options | |
11706 | if R.subChoice == 1 then | |
11707 | if menu.getBoolean("Am I outside clearing zone (y/n)?", nil, colors.yellow) then | |
11708 | - | function lib.getSaplingInventory(R) |
11708 | + | |
11709 | end | |
11710 | else | |
11711 | pp.itemColours = {colors.lightBlue, colors.cyan, colors.blue, colors.gray} | |
11712 | local choice = menu.menu("Exact position?", {"On top of clearing zone", "Outside clearing zone", "Inside clearing zone","Above AND outside"}, pp, "Type number + Enter ") | |
11713 | if choice == 1 then | |
11714 | T:down(1) | |
11715 | elseif choice == 2 then | |
11716 | - | saplings.cherry_sapling = 0 |
11716 | + | |
11717 | - | saplings.mangrove_propagule = 0 |
11717 | + | |
11718 | T:go("D1F1") | |
11719 | end | |
11720 | end | |
11721 | elseif R.choice == 77 then -- Dig a trench | |
11722 | R.height = menu.getInteger("Depth of the trench (1-64) ", 1, 64, nil, colors.blue) | |
11723 | - | if T:getItemSlot("sapling") > 0 then |
11723 | + | |
11724 | - | for i = 1, 16 do |
11724 | + | |
11725 | - | if turtle.getItemCount(i) > 0 then |
11725 | + | |
11726 | - | local data = turtle.getItemDetail(i) |
11726 | + | |
11727 | - | if data.name:find("sapling") ~= nil then |
11727 | + | |
11728 | - | local name = data.name:sub(11) -- removes "minecraft:" |
11728 | + | |
11729 | - | saplings[name] = saplings[name] + data.count |
11729 | + | |
11730 | local items = { "Replacing current floor", | |
11731 | "New floor over existing", | |
11732 | "Replacing current ceiling", | |
11733 | - | elseif T:getItemSlot("propagule") > 0 then |
11733 | + | |
11734 | - | saplings.mangrove_propagule = turtle.getItemCount(T:getItemSlot("propagule")) |
11734 | + | |
11735 | - | else -- no saplings onBoard: ? automated networked farm |
11735 | + | |
11736 | - | if R.networkFarm then |
11736 | + | |
11737 | - | -- networked farms use 1 type of sapling indicated by log embedded to right of modem |
11737 | + | |
11738 | - | -- discovered from utils.assessTreeFarm() on manual Startup |
11738 | + | |
11739 | - | if R.auto then -- called here as NOT manual startup |
11739 | + | |
11740 | - | R = utils.assessTreeFarm(R) |
11740 | + | |
11741 | - | if R.message ~= "" then |
11741 | + | |
11742 | - | return {R.message} -- location of turtle error |
11742 | + | |
11743 | else | |
11744 | R.up = true | |
11745 | - | local turtleSlot, turtleCount = network.getItemFromNetwork("barrel", R.useBlockType, 16) |
11745 | + | |
11746 | - | if turtleCount == 0 then -- ask player for saplings |
11746 | + | |
11747 | - | T:checkInventoryForItem({R.useBlockType}, {16}, true, "Saplings required for tree farm") |
11747 | + | |
11748 | elseif R.choice == 710 or R.choice == 83 then -- Direct movement | |
11749 | - | saplings[R.useBlockType] = saplings[R.useBlockType] + turtleCount |
11749 | + | |
11750 | - | turtleSlot, turtleCount = network.getItemFromNetwork("barrel", "minecraft:dirt", 16) |
11750 | + | |
11751 | - | if turtleCount == 0 then |
11751 | + | |
11752 | - | turtleSlot, turtleCount = network.getItemFromNetwork("chest", "minecraft:dirt", 16) |
11752 | + | |
11753 | choices = {"Command driven", "Menu driven"} | |
11754 | - | if turtleCount == 0 then -- ask player |
11754 | + | |
11755 | - | T:checkInventoryForItem({"minecraft:dirt"}, {16}, true, "Dirt required for tree farm") |
11755 | + | |
11756 | R.data = "cmd" | |
11757 | - | return saplings, R.useBlockType, R.useBlockType |
11757 | + | |
11758 | R.data = "menu" | |
11759 | end | |
11760 | ||
11761 | -- 08. WATER LAVA | |
11762 | elseif R.choice == 81 then -- Sand based utilities | |
11763 | local line = getTaskHelp(2, R.choice, true, true) -- request line no of help display if needed for getInteger | |
11764 | R.subChoice = menu.getInteger("Type number of choice", 1, 4, line, colors.white) | |
11765 | T:clear() | |
11766 | if R.subChoice == 1 then -- drop sand into water or lava surface until solid ground reached | |
11767 | R.width = 1 | |
11768 | R.length = menu.getInteger("Length of sand wall (0=to block) ", 0, 60, nil, colors.orange) | |
11769 | elseif R.subChoice == 2 then -- clear rectangle on top of building and fill with sand | |
11770 | R.width = menu.getInteger("Width of area (<=30) ", 1, 30, nil, colors.yellow) | |
11771 | R.length = menu.getInteger("Length of of area (<=30) ", 1, 30, nil, colors.orange) | |
11772 | elseif R.subChoice == 3 then -- clear sand wall or harvest sand | |
11773 | R.width = 1 | |
11774 | R.length = menu.getInteger("Length of sand (0=auto-detect)", 0, 60, nil, colors.orange) | |
11775 | choices = {"Stay at end of wall", "Return home"} | |
11776 | pp.itemColours = {colors.lime, colors.orange} | |
11777 | userChoice = menu.menu("Choose your preference", choices, pp, "Type number + Enter ") | |
11778 | if userChoice == 2 then | |
11779 | R.data = "return" | |
11780 | - | T:place("dirt", "down", false, "", true) |
11780 | + | |
11781 | elseif R.subChoice == 4 then -- remove sand from cube. start at top | |
11782 | R.width = menu.getInteger("Width of sand (<=30) ", 1, 30, nil, colors.yellow) | |
11783 | R.length = menu.getInteger("Length of of sand (<=30) ", 1, 30, nil, colors.orange) | |
11784 | R.height = 0 | |
11785 | R.data = "down" -- always starts at the top | |
11786 | - | T:place(sapling, "down", false, "", true) |
11786 | + | |
11787 | if menu.getBoolean("Am I outside the active zone (y/n)?", nil, colors.yellow) then | |
11788 | T:forward(1) | |
11789 | end | |
11790 | - | T:place(sapling, "down", false, "", true) |
11790 | + | |
11791 | R.width = 1 | |
11792 | if menu.getBoolean("Going 90 deg. from existing? (y/n)", nil, colors.yellow, colors.black) then | |
11793 | getTaskHelp(2, 852, true) | |
11794 | menu.clear() | |
11795 | R.length = 56 | |
11796 | R.data = "withPath" -- ensures turtle will break through path | |
11797 | R.length = menu.getInteger({"Wall length minus corners","(Ocean monument default 56)","Number -> Enter or Enter only (56)"}, | |
11798 | 1, 64, nil, {colors.yellow, colors.orange, colors.green}, colors.black, 56) | |
11799 | else | |
11800 | R.length = menu.getInteger("Length of the wall (1-60) ", 1, 60, nil, colors.yellow) | |
11801 | R.height = menu.getInteger("Fixed depth or 0 = to floor ", 0, 60, nil, colors.yellow) | |
11802 | end | |
11803 | -- for 83 see 710 | |
11804 | elseif R.choice == 84 then -- Clear area of water bounded by blocks | |
11805 | R.width = menu.getInteger("Width of water (0=autodetect) ", 0, 64, nil, colors.yellow) | |
11806 | if R.width > 0 then | |
11807 | - | T:place("dirt", "down", false, "", true) |
11807 | + | |
11808 | end | |
11809 | - | if not T:place(sapling, "down", false, "", true) then -- try specific sapling |
11809 | + | |
11810 | - | T:place("sapling", "down", false, "", true) -- any available sapling |
11810 | + | |
11811 | R.width = menu.getInteger("Width (excluding retaining wall)? ", 1, 1024, nil, colors.yellow) | |
11812 | R.length = menu.getInteger("Length (excluding retaining wall)? ", 1, 1024 / R.width, nil, colors.orange) | |
11813 | R.height = menu.getInteger("Levels to go down?", 1, 1024 / R.width * R.length, nil, colors.blue) | |
11814 | elseif R.choice == 86 then -- ocean monument utilities | |
11815 | local items = | |
11816 | { | |
11817 | "Build 4 corner marker columns", | |
11818 | "Retaining wall beween 2 columns", | |
11819 | "Clear plants pre sand draining", | |
11820 | "Drop sand wall", | |
11821 | "Recover sand wall", | |
11822 | "Sinking platform", | |
11823 | - | function lib.getMangroveSupplies() |
11823 | + | |
11824 | - | local turtleSlot, turtleCount = network.getItemFromNetwork("barrel", "minecraft:dirt", 169) |
11824 | + | |
11825 | - | if turtleCount < 169 then |
11825 | + | |
11826 | - | turtleSlot, turtleCount = network.getItemFromNetwork("chest", "minecraft:dirt", 169 - turtleCount) |
11826 | + | |
11827 | - | if turtleCount < 169 then -- ask player for saplings |
11827 | + | |
11828 | - | T:checkInventoryForItem({"dirt"}, {169 - turtleCount}) |
11828 | + | |
11829 | end | |
11830 | menu.clear() | |
11831 | - | turtleSlot, turtleCount = network.getItemFromNetwork("barrel", "minecraft:mangrove_propagule", 25) |
11831 | + | |
11832 | - | if turtleCount == 0 then -- ask player for saplings |
11832 | + | |
11833 | - | T:checkInventoryForItem({"mangrove_propagule"}, {25}, true, "Mangrove propagules required") |
11833 | + | |
11834 | elseif R.subChoice == 2 then -- Retaining wall beween 2 columns | |
11835 | R.length = 56 | |
11836 | R.data = "withPath" -- ensures turtle will break through path | |
11837 | - | function lib.plantMangrove() |
11837 | + | |
11838 | - | T:go("L1F6 R1F1 U1") |
11838 | + | |
11839 | - | createFloorCeiling({width = 13, length = 13, up = false, down = true, |
11839 | + | |
11840 | - | height = 0, subChoice = 0, useBlockType = "minecraft:dirt", |
11840 | + | |
11841 | - | inventory = T:getInventory()}) |
11841 | + | |
11842 | R.data = "clearWaterPlants" | |
11843 | - | --T:go("U1F5 R1F5 L1") -- lower left of planting area, facing Back |
11843 | + | |
11844 | - | T:go("U1F4 R1F4 L1") -- lower left of planting area, facing Back |
11844 | + | |
11845 | - | for x = 1, 5 do |
11845 | + | |
11846 | - | for i = 1, 5 do |
11846 | + | |
11847 | - | T:place("propagule", "down") -- left 1 |
11847 | + | |
11848 | - | if i < 5 then |
11848 | + | |
11849 | elseif R.subChoice == 5 then -- remove sand wall using sand utilities | |
11850 | R.width = 1 | |
11851 | R.length = 0 | |
11852 | - | if x % 2 == 1 then |
11852 | + | |
11853 | - | if x < 5 then |
11853 | + | |
11854 | R.length = menu.getInteger("Length (excluding retaining wall)? ", 1, 1024 / R.width, nil, colors.orange) | |
11855 | R.height = menu.getInteger("Levels to go down?", 1, 1024 / R.width * R.length, nil, colors.blue) | |
11856 | elseif R.subChoice == 7 then -- Drain and remove structure | |
11857 | R.width = 28 | |
11858 | R.length = 28 | |
11859 | R.height = menu.getInteger("Go down how far from current", 1, 64, nil, colors.blue) | |
11860 | - | T:go("L1F2 L1F2 D2U2 F7R2 D2") |
11860 | + | |
11861 | elseif R.choice == 87 then -- Ladder to water/lava | |
11862 | - | T:place("propagule", "down") -- left 1 |
11862 | + | |
11863 | elseif R.choice == 88 then -- Clear water plants from enclosed area | |
11864 | - | T:place("propagule", "down") -- left 2 |
11864 | + | |
11865 | R.width = menu.getInteger("water width (0=auto detect) ", 0, 64, nil, colors.yellow) | |
11866 | - | T:place("propagule", "down") -- left 3/top 1 |
11866 | + | |
11867 | elseif R.choice == 89 then -- convert flowing water to source | |
11868 | - | T:go("R1F1") |
11868 | + | |
11869 | - | T:place("propagule", "down") -- top 2 |
11869 | + | |
11870 | R.length = menu.getInteger("water length (0=auto detect) ", 0, 64, nil, colors.orange) | |
11871 | - | T:place("propagule", "down") -- top 3/right 1 |
11871 | + | |
11872 | - | T:go("R1F1") |
11872 | + | |
11873 | elseif R.choice == 810 then -- create sloping water | |
11874 | - | T:place("propagule", "down") -- right 2 |
11874 | + | |
11875 | R.length = menu.getInteger("water slope length ", 1, 64, nil, colors.orange) | |
11876 | - | T:place("propagule", "down") -- right 3/bottom 1 |
11876 | + | |
11877 | - | T:go("R1F1") |
11877 | + | |
11878 | - | T:place("propagule", "down") -- bottom 2]] |
11878 | + | |
11879 | R.width = 1 | |
11880 | - | --T:go("R1F1R2 D2U2 F7R2 D2") |
11880 | + | |
11881 | R.height = menu.getInteger("Height of wall (1-50) ", 1, 50, nil, colors.lightGray) | |
11882 | pp.itemColours = {colors.lime, colors.magenta} | |
11883 | - | function lib.plantSingle(R) |
11883 | + | |
11884 | - | local sapling, count = lib.checkSaplings(firstChoice, secondChoice) |
11884 | + | |
11885 | - | if count >= 1 then |
11885 | + | |
11886 | - | if R.networkFarm then |
11886 | + | |
11887 | - | T:go("U1L1 F3R1 F4") -- outside first area |
11887 | + | |
11888 | pp.itemColours = {colors.lime, colors.magenta} | |
11889 | - | T:go("U1F4") -- outside first area |
11889 | + | |
11890 | elseif R.choice == 93 or R.choice == 94 then -- Build gable roof / pitched roof | |
11891 | - | for i = 1, 3 do -- column 1/4 |
11891 | + | |
11892 | - | lib.createSingle(sapling, "forward") |
11892 | + | |
11893 | elseif R.choice == 97 then -- build downward slope | |
11894 | R.height = menu.getInteger("How many blocks down (0=to ground)?", 0, 256, nil, colors.blue) | |
11895 | - | for i = 1, 2 do |
11895 | + | |
11896 | - | lib.createSingle(sapling, "right") -- place 4th dirt/saling and exit to right |
11896 | + | |
11897 | R.height = menu.getInteger("Go up by how many blocks?", 1, 256, nil, colors.lightGray) | |
11898 | R.up = true | |
11899 | - | for i = 1, 2 do -- column 2/4 |
11899 | + | |
11900 | - | lib.createSingle(sapling, "forward") |
11900 | + | |
11901 | elseif R.choice == 101 then -- measure height | |
11902 | pp.itemColours = {colors.lightBlue, colors.cyan, colors.lime, colors.gray} | |
11903 | - | for i = 1, 2 do |
11903 | + | |
11904 | - | lib.createSingle(sapling, "left") -- place 4th dirt/saling and exit to right |
11904 | + | |
11905 | R.data = menu.getString({"Search for? eg 'ore', 'obsidian'",">"}, false, 3, 20, nil, {colors.lime, colors.yellow}) | |
11906 | end | |
11907 | - | for i = 1, 2 do -- column 3/4 |
11907 | + | |
11908 | - | lib.createSingle(sapling, "forward") |
11908 | + | |
11909 | pp.itemColours = {colors.lime, colors.orange, colors.green} | |
11910 | R.subChoice = menu.menu("Measure using?", {"Water/Lava/Obstruction below", "No further blocks ahead", "Detect specific block ahead"}, pp, "Type number + Enter") -- open direction menu options | |
11911 | - | for i = 1, 2 do |
11911 | + | |
11912 | - | lib.createSingle(sapling, "right") -- place 4th dirt/saling and exit to right |
11912 | + | |
11913 | end | |
11914 | elseif R.choice == 103 then -- measure length | |
11915 | - | for i = 1, 3 do -- column 4/4 |
11915 | + | |
11916 | - | lib.createSingle(sapling, "forward") |
11916 | + | |
11917 | "No further blocks above", | |
11918 | "No further blocks below", | |
11919 | - | if R.networkFarm then |
11919 | + | |
11920 | - | T:go("R1F3 R1F2L1") -- in-between 2 trees |
11920 | + | |
11921 | - | if R.auto then |
11921 | + | |
11922 | - | harvestTreeFarm(R) |
11922 | + | |
11923 | end | |
11924 | - | T:go("L1F4R2D1") |
11924 | + | |
11925 | elseif R.choice == 104 then -- measure greatest depth of water body | |
11926 | pp.itemColours = {colors.lime, colors.orange} | |
11927 | - | T:go("R1F6 L1F2 R2D1") |
11927 | + | |
11928 | -- 1 = player entry, 2 = water length | |
11929 | if R.subChoice == 1 then | |
11930 | - | return "No saplings to plant" |
11930 | + | |
11931 | end | |
11932 | elseif R.choice == 105 then -- drill borehole and write borhole.txt to file | |
11933 | R.height = menu.getInteger("Current level (F3->Y coord)? ", bedrock + 5, ceiling, nil, colors.lightGray) | |
11934 | R.depth = menu.getInteger("Go down to level? ("..R.height - 2 .." to "..bedrock + 5 ..")", bedrock + 5 ,R.height - 2, nil, colors.blue, nil, bedrock + 5) | |
11935 | end | |
11936 | - | function lib.plantDouble(R) |
11936 | + | |
11937 | return R | |
11938 | end | |
11939 | ||
11940 | local function getTaskInventoryTo30(R) | |
11941 | - | if R.networkFarm then |
11941 | + | |
11942 | - | T:go("U1L1 F3R1 F3") -- outside first area |
11942 | + | |
11943 | --local pp = utils.getPrettyPrint() | |
11944 | - | T:go("U1F3") -- outside first area |
11944 | + | |
11945 | if R.choice == 0 then --Missing pickaxe | |
11946 | T:checkInventoryForItem({"minecraft:diamond_pickaxe"}, {1}) | |
11947 | - | sapling, count = lib.checkSaplings(firstChoice, secondChoice) |
11947 | + | |
11948 | T:setEquipment() | |
11949 | elseif R.choice == 1 then --Missing crafting table | |
11950 | - | sapling, count = lib.checkSaplings(firstChoice, secondChoice) |
11950 | + | |
11951 | print("Crafting table being tested...") | |
11952 | T:setEquipment() | |
11953 | - | sapling, count = lib.checkSaplings(firstChoice, secondChoice) |
11953 | + | |
11954 | T:checkInventoryForItem({"minecraft:chest"}, {1}) -- 0 if not present | |
11955 | sleep(1.5) | |
11956 | ||
11957 | - | if R.networkFarm then |
11957 | + | |
11958 | - | T:go("R1F4 R1F1 L1") -- on left side of double tree |
11958 | + | |
11959 | - | if R.auto then |
11959 | + | |
11960 | - | harvestTreeFarm(R) |
11960 | + | |
11961 | pp.itemColours = {colors.blue, colors.lightGray} | |
11962 | - | T:go("L1F4 L1F1 L1D1") -- back to start |
11962 | + | |
11963 | local inAir = false | |
11964 | local inNether = menu.getBoolean("Are you in the nether? (y/n) ", nil, colors.yellow, colors.black) | |
11965 | - | T:go("R1D1 F6L1 F3R2") -- outside first area |
11965 | + | |
11966 | if inNether then | |
11967 | bedrock = 0 | |
11968 | - | return "Insufficient saplings to plant" |
11968 | + | |
11969 | end | |
11970 | local option = menu.menu("Which direction?", {"Going down","Going up"}, pp) | |
11971 | if option == 1 then | |
11972 | R.down = true | |
11973 | - | if R.networkFarm then |
11973 | + | |
11974 | - | local message = network.loadStorageLists() -- initialises or creates lists of where an item can be found: GLOBAL LISTS! |
11974 | + | |
11975 | - | if message ~= nil then return {message} end |
11975 | + | |
11976 | - | lib.emptyInventory(R) |
11976 | + | |
11977 | R.data = "chamber" | |
11978 | - | if R.subChoice == 3 then -- mangrove, R.networkFarm only |
11978 | + | |
11979 | - | lib.getMangroveSupplies() |
11979 | + | |
11980 | - | lib.plantMangrove() |
11980 | + | |
11981 | description = "Creating stairs going down" | |
11982 | - | local saplings, firstChoice, secondChoice = lib.getSaplingInventory(R) |
11982 | + | |
11983 | - | if firstChoice ~= "" then |
11983 | + | |
11984 | - | print("first sapling: "..firstChoice .. " ("..saplings[firstChoice]..")") |
11984 | + | |
11985 | --R.depth = utils.getSize(true,"Current level (F3->Y coord)? ", bedrock + 5, ceiling) | |
11986 | - | if secondChoice ~= "" then |
11986 | + | |
11987 | - | print("second sapling: "..secondChoice .. " ("..saplings[secondChoice]..")") |
11987 | + | |
11988 | R.height = menu.getInteger("Go up to level? ("..R.depth + 2 .." to "..ceiling ..") ", R.depth + 2, ceiling, nil, colors.lightGray) | |
11989 | if R.choice == 11 then | |
11990 | - | -- check type/size of farm |
11990 | + | |
11991 | else | |
11992 | - | if R.subChoice == 1 then -- 16 single trees |
11992 | + | |
11993 | - | message = lib.plantSingle(R) -- always "" |
11993 | + | |
11994 | - | elseif R.subChoice == 2 then -- 4 double trees (4 saplings) |
11994 | + | |
11995 | - | message = lib.plantDouble(R) -- "" or error about numbers |
11995 | + | |
11996 | ||
11997 | if not inAir then | |
11998 | - | if R.networkFarm then |
11998 | + | |
11999 | - | lib.emptyInventory(R) |
11999 | + | |
12000 | --[[ | |
12001 | - | return {message} |
12001 | + | |
12002 | -50 to -59 = -59 -(-50) = -9 down | |
12003 | -59 to -50 = -50 -(-59) = 9 up | |
12004 | 70 to -48 = -48 - 70 = -118 down | |
12005 | 5 to 64 = 64 - 5 = 59 up | |
12006 | ]] | |
12007 | T:checkInventoryForItem({"minecraft:bucket"}, {1}, false) | |
12008 | if R.choice == 11 then -- ladders | |
12009 | utils.checkFuelNeeded(range * 2) | |
12010 | T:checkInventoryForItem({"minecraft:ladder"}, {range}) | |
12011 | T:checkInventoryForItem({"minecraft:torch"}, {math.floor(range / 3)}, false) | |
12012 | if inAir then | |
12013 | range = range * 4 -- more blocks needed | |
12014 | end | |
12015 | T:checkInventoryForItem({"stone"}, {range}) | |
12016 | else -- stairs | |
12017 | utils.checkFuelNeeded(range * 10) -- stairs: each layer needs 10 moves | |
12018 | local numStairsNeeded = range | |
12019 | local data = T:getStock("stairs") | |
12020 | local numStairs = data.total | |
12021 | local cobbleNeeded = math.min(range * 6, 256) | |
12022 | if inAir then | |
12023 | cobbleNeeded = range * 6 -- 5 blocks / layer unless in water or lava | |
12024 | end | |
12025 | if numStairs < numStairsNeeded then | |
12026 | cobbleNeeded = cobbleNeeded + (math.floor((2 * (numStairsNeeded - numStairs)) / 3)) | |
12027 | end | |
12028 | T:checkInventoryForItem({"stairs"}, {numStairsNeeded}, false) | |
12029 | T:checkInventoryForItem({"stone"}, {cobbleNeeded}) | |
12030 | T:checkInventoryForItem({"minecraft:chest"}, {1}) -- needed for crafting | |
12031 | end | |
12032 | menu.colourPrint(description, colors.lightBlue) | |
12033 | os.sleep(2) -- pause for 2 secs to allow time to press esc | |
12034 | if R.choice == 11 then | |
12035 | retValue = createLadder(R) -- "bedrock", 70, -48 | |
12036 | else | |
12037 | retValue = createStaircase(R) | |
12038 | end | |
12039 | elseif R.choice == 13 then --Create Mine at this level | |
12040 | utils.checkFuelNeeded(960) | |
12041 | T:checkInventoryForItem({"minecraft:torch"}, {24}, false) | |
12042 | T:checkInventoryForItem({"minecraft:bucket"}, {1}, false) | |
12043 | T:checkInventoryForItem({"stone"}, {64}) | |
12044 | T:checkInventoryForItem({"minecraft:chest"}, {1}) | |
12045 | menu.colourPrint("CreateMine starting", colors.lightBlue) | |
12046 | sleep(2) | |
12047 | retValue = createMine() | |
12048 | elseif R.choice == 14 then -- safe drop to water | |
12049 | utils.checkFuelNeeded(R.height * 2) | |
12050 | T:checkInventoryForItem({"minecraft:water_bucket"}, {1}) | |
12051 | T:checkInventoryForItem({"stone"}, {R.height * 2}, false) -- estimate only partial cloaking needed | |
12052 | menu.colourPrint("Creating safe drop ".. R.height.. " blocks deep", colors.lightBlue) | |
12053 | menu.colourPrint("Wait for my return!", colors.yellow) | |
12054 | os.sleep(2) -- pause for 2 secs to allow time to press esc | |
12055 | retValue = createSafeDrop(R) | |
12056 | elseif R.choice == 15 then -- single column bubble lift | |
12057 | local needSigns = true | |
12058 | utils.checkFuelNeeded(R.height * 6) | |
12059 | --print(text, fg, bg, width) | |
12060 | menu.colourPrint("Checking if near ladder", colors.red) | |
12061 | T:turnRight(1) | |
12062 | local blockType = T:getBlockType("forward") | |
12063 | if blockType:find("ladder") == nil then | |
12064 | T:turnLeft(2) | |
12065 | blockType = T:getBlockType("forward") | |
12066 | if blockType:find("ladder") == nil then | |
12067 | needSigns = false | |
12068 | end | |
12069 | T:turnRight(1) | |
12070 | else | |
12071 | needSigns = false | |
12072 | T:turnLeft(1) | |
12073 | end | |
12074 | sleep(1) | |
12075 | if needSigns then | |
12076 | T:checkInventoryForItem({"sign"}, {2}, true, "Ladder not found") | |
12077 | else | |
12078 | menu.colourPrint("Ladder found, signs not required", colors.orange) | |
12079 | sleep(1) | |
12080 | end | |
12081 | if T:getBlockType("down"):find("bedrock") == nil then -- NOT bedrock below | |
12082 | T:checkInventoryForItem({"minecraft:water_bucket"}, {3}) | |
12083 | else | |
12084 | T:checkInventoryForItem({"minecraft:water_bucket"}, {2}) | |
12085 | end | |
12086 | T:checkInventoryForItem({"minecraft:soul_sand", "minecraft:dirt"}, {1, 1}, true, "? use dirt as soul sand placeholder") | |
12087 | T:checkInventoryForItem({"stone"}, {R.height * 2}, false) -- estimate only partial cloaking needed | |
12088 | local _, slots = T:getFirstEmptySlot() -- returns first empty slot, no of empty slots | |
12089 | T:checkInventoryForItem({"minecraft:bucket"}, {slots}, false, "Add empty buckets for speed!") | |
12090 | menu.colourPrint("Creating bubble lift ".. R.height.. " blocks high", colors.lime) | |
12091 | if not needSigns then -- ladder present as signs not required | |
12092 | menu.colourPrint("Wait at the top via ladder...", colors.orange) | |
12093 | end | |
12094 | menu.colourPrint("\nSTAND ON THE LADDER FOR SAFETY!", colors.red) | |
12095 | menu.colourPrint("\nEnter to continue", colors.yellow) | |
12096 | read() | |
12097 | retValue = createBubbleLift(R) | |
12098 | elseif R.choice == 16 then --QuickMine corridor | |
12099 | utils.checkFuelNeeded((R.width * 2 + R.length * 2) * 2) | |
12100 | T:checkInventoryForItem({"stone"}, {R.width * 2 + R.length * 2}, false) | |
12101 | T:checkInventoryForItem({"minecraft:torch"}, {math.floor((R.width * 2 + R.length * 2) / R.torchInterval)}, false) | |
12102 | T:checkInventoryForItem({"minecraft:bucket"}, {1}, false) | |
12103 | menu.colourPrint("QuickMine corridor: R.subChoice "..R.width.. " x "..R.length, colors.lightBlue) | |
12104 | retValue = quickMineCorridor(R) | |
12105 | elseif R.choice == 17 then --QuickMine | |
12106 | utils.checkFuelNeeded(R.width * R.length) | |
12107 | T:checkInventoryForItem({"stone"}, {64}) | |
12108 | T:checkInventoryForItem({"minecraft:bucket"}, {1}, false) | |
12109 | menu.colourPrint("QuickMine rectangle: R.subChoice "..R.width.. " x "..R.length, colors.lightBlue) | |
12110 | retValue = quickMine(R) | |
12111 | elseif R.choice == 18 then --Mine bedrock area | |
12112 | utils.checkFuelNeeded(R.width * R.length) | |
12113 | T:checkInventoryForItem({"stone"}, {64}) | |
12114 | T:checkInventoryForItem({"minecraft:bucket"}, {1}, false) | |
12115 | retValue = mineBedrockArea(R) -- R.data = "leaveExposed" or "" | |
12116 | elseif R.choice == 19 then -- salvage mineshaft | |
12117 | local equippedRight, equippedLeft, inInventory = T:setEquipment() -- check for crafting table, sword, pickaxe, Put sword in spare slot | |
12118 | if equippedLeft ~= "minecraft:diamond_pickaxe" and equippedRight ~= "minecraft:diamond_pickaxe" then | |
12119 | T:checkInventoryForItem({"minecraft:diamond_pickaxe"}, {1}, true) | |
12120 | equippedRight, equippedLeft, inInventory = T:setEquipment() -- check for crafting table, sword, pickaxe, Put sword in spare slot | |
12121 | end | |
12122 | if inInventory ~= "minecraft:diamond_sword" then | |
12123 | T:checkInventoryForItem({"minecraft:diamond_sword"}, {1}, false, "To harvest spider webs\nyou need a diamond sword.") --checkInventoryForItem(self, items, quantities, required, message, name) | |
12124 | end | |
12125 | if T:getItemSlot("minecraft:diamond_sword") > 0 then | |
12126 | inInventory = "minecraft:diamond_sword" | |
12127 | end | |
12128 | T:checkInventoryForItem({"minecraft:torch"}, {R.torchInterval}, false) | |
12129 | if inInventory == "minecraft:diamond_sword" then | |
12130 | menu.colourPrint("Clearing Mineshaft and cobwebs", colors.orange) | |
12131 | else | |
12132 | menu.colourPrint("Clearing Mineshaft", colors.yellow) | |
12133 | end | |
12134 | retValue = clearMineshaft(R, equippedRight, equippedLeft, inInventory) -- pass whether the sword is present | |
12135 | ||
12136 | -- FORESTRY | |
12137 | elseif R.choice == 21 then -- Fell tree | |
12138 | if T:isLog("forward") then | |
12139 | if turtle.getFuelLevel() < 30 then | |
12140 | T:checkInventoryForItem({"minecraft:chest"}, {1}, false,"Fuel level critical: "..turtle.getFuelLevel()) | |
12141 | turtle.select(1) | |
12142 | T:dig("forward") | |
12143 | T:craft("planks", 4) | |
12144 | T:refuel() | |
12145 | T:forward(1) | |
12146 | T:up(2) | |
12147 | T:craft("chest", 1) | |
12148 | else | |
12149 | T:forward(1) | |
12150 | end | |
12151 | menu.colourPrint("Felling tree", colors.lime) | |
12152 | os.sleep(2) -- pause for 2 secs to allow time to press esc | |
12153 | T:harvestWholeTree("up") | |
12154 | while turtle.down() do end | |
12155 | retValue = {"Tree Harvested"} | |
12156 | else | |
12157 | retValue = | |
12158 | { | |
12159 | "No log in front..", | |
12160 | "Move me in front of a tree!" | |
12161 | } | |
12162 | end | |
12163 | elseif R.choice == 22 then --Create treefarm | |
12164 | utils.checkFuelNeeded(900) | |
12165 | --T:checkInventoryForItem({"minecraft:dirt"}, {16}) | |
12166 | T:checkInventoryForItem({"stone"}, {320}) | |
12167 | T:checkInventoryForItem({"polished"}, {4}) -- used to mark launch positions | |
12168 | T:checkInventoryForItem({"minecraft:water_bucket"}, {5}) | |
12169 | R.useBlockType = T:getMostItem("", true) | |
12170 | menu.colourPrint("Creating Tree Farm with "..R.useBlockType, colors.lime) | |
12171 | sleep(2) | |
12172 | retValue = createTreefarm(R) | |
12173 | elseif R.choice == 23 then -- Plant treefarm | |
12174 | if R.subChoice == 1 then | |
12175 | utils.checkFuelNeeded(180) | |
12176 | T:checkInventoryForItem({"dirt"}, {16}) | |
12177 | T:checkInventoryForItem({"sapling"}, {16}, false, "Max 16. NOT dark oak") | |
12178 | elseif R.subChoice == 2 then | |
12179 | utils.checkFuelNeeded(180) | |
12180 | T:checkInventoryForItem({"dirt"}, {16}) | |
12181 | T:checkInventoryForItem({"sapling"}, {16}, false, "Max 16. 4 saplings / tree") | |
12182 | end | |
12183 | menu.colourPrint("plantTreefarm starting: size "..R.subChoice, colors.lime) | |
12184 | retValue = plantTreefarm(R) | |
12185 | elseif R.choice == 24 then -- Harvest treefarm | |
12186 | print(thanks) | |
12187 | os.sleep(2) | |
12188 | menu.colourPrint("Harvesting treefarm starting", colors.lime) | |
12189 | retValue = harvestTreeFarm(R) | |
12190 | elseif R.choice == 25 then -- Build wall / fence | |
12191 | utils.checkFuelNeeded(R.width * R.length * 2) | |
12192 | local quantity = math.ceil((R.width + R.length) * 2.3) | |
12193 | T:checkInventoryForItem({"wall", "fence"}, {quantity, quantity}) | |
12194 | if R.torchInterval > 0 then | |
12195 | T:checkInventoryForItem({"minecraft:torch"}, {math.floor(quantity / R.torchInterval)}, false) | |
12196 | end | |
12197 | if R.data == "barrel" then | |
12198 | T:checkInventoryForItem({"barrel"}, {4}, false) | |
12199 | end | |
12200 | R.useBlockType = T:getMostItem("", false) -- no excluded blocks, any block type | |
12201 | menu.colourPrint("Creating "..R.width.." x "..R.length.." walled enclosure", colors.yellow) | |
12202 | menu.colourPrint("Using: "..R.useBlockType, colors.orange) | |
12203 | retValue = createWallOrFence(R) | |
12204 | elseif R.choice == 26 then -- clear natural forest | |
12205 | T:checkInventoryForItem({"minecraft:chest"}, {1}) | |
12206 | T:checkInventoryForItem({"sapling"}, {64}, false) | |
12207 | menu.colourPrint("Clearing and replanting trees", colors.lime) | |
12208 | os.sleep(2) -- pause for 2 secs to allow time to press esc | |
12209 | retValue = clearAndReplantTrees() | |
12210 | end | |
12211 | return retValue | |
12212 | end | |
12213 | ||
12214 | local function getTaskInventoryTo70(R) | |
12215 | local retValue = {} | |
12216 | local thanks = "Thank you.\n\nPress the ESC key\n\nStand Back..\n" | |
12217 | -- FARMING | |
12218 | if R.choice == 31 then -- Create modular farm | |
12219 | utils.checkFuelNeeded(300) | |
12220 | T:checkInventoryForItem({"cobble"}, {64}) | |
12221 | T:checkInventoryForItem({"dirt"}, {128}, false) | |
12222 | T:checkInventoryForItem({"water_bucket"}, {4}) | |
12223 | T:checkInventoryForItem({"chest", "barrel"}, {5,5}) | |
12224 | T:checkInventoryForItem({"sapling"}, {1}) | |
12225 | R.useBlockType = T:getMostItem("dirt", true) -- exclude dirt from count | |
12226 | print(thanks) | |
12227 | os.sleep(2) -- pause for 2 secs to allow time to press esc | |
12228 | print("Creating modular farm with "..R.useBlockType) | |
12229 | retValue = createFarm(R, false) | |
12230 | elseif R.choice == 32 then -- Extend modular farm | |
12231 | utils.checkFuelNeeded(300) | |
12232 | T:checkInventoryForItem({"cobble"}, {64}) | |
12233 | T:checkInventoryForItem({"dirt"}, {128}, false) | |
12234 | T:checkInventoryForItem({"water_bucket"}, {4}) | |
12235 | - | "2 water buckets","192 fence","8 signs","3 ladder","2 soul sand"} -- build endermen observation tower |
12235 | + | T:checkInventoryForItem({"chest", "barrel"}, {5,5}) |
12236 | - | text[67] = {"24 blocks of any type"} -- Cover Trial spawners to prevent mobs escaping |
12236 | + | |
12237 | T:checkInventoryForItem({"crafting"}, {1}) -- will be placed inside barrel / chest next to water source | |
12238 | R.useBlockType = T:getMostItem("dirt", true) -- exclude dirt from count | |
12239 | menu.colourPrint("Checking position...\n", colors.green) | |
12240 | os.sleep(2) -- pause for 2 secs to allow time to press esc | |
12241 | retValue = createFarmExtension(R) -- subChoice = 1 for ahead, 2 for to the right | |
12242 | elseif R.choice == 33 then -- manage modular farm | |
12243 | -- inventory checked in function depending on option taken | |
12244 | R.data = "farm" | |
12245 | retValue = manageFarmSetup(R) | |
12246 | elseif R.choice == 34 then -- build single fence | |
12247 | utils.checkFuelNeeded(R.length) | |
12248 | T:checkInventoryForItem({"wall", "fence"}, {R.length, R.length}) | |
12249 | if R.torchInterval > 0 then | |
12250 | T:checkInventoryForItem({"minecraft:torch"}, {math.ceil(R.length / R.torchInterval)}, false) | |
12251 | end | |
12252 | R.useBlockType = T:getMostItem("minecraft:torch") -- exclude torch | |
12253 | menu.colourPrint("Creating "..R.length.." wall or fence", colors.green) | |
12254 | menu.colourPrint("Using: "..R.useBlockType, colors.orange) | |
12255 | retValue = createWallOrFence(R) -- barrels not included in R.data, R.width = 0 so only single length | |
12256 | elseif R.choice == 35 then -- build fence | |
12257 | utils.checkFuelNeeded(R.width * R.length * 2) | |
12258 | local quantity = math.ceil((R.width + R.length) * 2.3) | |
12259 | T:checkInventoryForItem({"wall", "fence"}, {quantity, quantity}) | |
12260 | if R.torchInterval > 0 then | |
12261 | T:checkInventoryForItem({"minecraft:torch"}, {math.floor(quantity / R.torchInterval)}, false) | |
12262 | end | |
12263 | R.useBlockType = T:getMostItem("minecraft:torch") -- exclude torch | |
12264 | menu.colourPrint("Creating "..R.width.." x "..R.length.." walled enclosure", colors.green) | |
12265 | menu.colourPrint("Using: "..R.useBlockType, colors.orange) | |
12266 | retValue = createWallOrFence(R) -- barrels not included in R.data | |
12267 | -- OBSIDIAN | |
12268 | elseif R.choice == 41 then --harvest obsidian | |
12269 | utils.checkFuelNeeded(R.width * R.length * 3) | |
12270 | T:checkInventoryForItem({"stone"}, {R.width * R.length}) | |
12271 | T:checkInventoryForItem({"minecraft:bucket", "minecraft:lava_bucket"}, {1, 1}, false, "Get extra fuel as well!") | |
12272 | menu.colourPrint("Harvesting obsidian area: size "..R.width.. " x "..R.length, colors.orange) | |
12273 | sleep(2) | |
12274 | retValue = harvestObsidian(R) | |
12275 | elseif R.choice == 42 then --build nether portal | |
12276 | utils.checkFuelNeeded(R.length * R.height * R.width) -- length = width when facing standard = 5 high 4 length 1 width | |
12277 | T:checkInventoryForItem({"minecraft:obsidian"}, {((R.length - 2 + R.height - 2) * R.width * 2)}) | |
12278 | T:checkInventoryForItem({"stone"}, {R.width * 4}) | |
12279 | R.useBlockType = T:getMostItem("obsidian", true) -- exclude obsidian from count | |
12280 | menu.colourPrint("Building Nether portal", colors.orange) | |
12281 | sleep(2) | |
12282 | retValue = createPortal(R) | |
12283 | elseif R.choice == 43 then --demolish nether portal | |
12284 | utils.checkFuelNeeded(20) | |
12285 | print("Demolishing Nether portal") | |
12286 | retValue = demolishPortal(R) | |
12287 | elseif R.choice == 44 then -- Strip mine Netherite | |
12288 | utils.checkFuelNeeded(R.length * 2) | |
12289 | T:checkInventoryForItem({"stone"}, {R.length * 4}) | |
12290 | R.useBlockType = T:getMostItem("", true) -- exclude none, use stone only/netherrack | |
12291 | T:checkInventoryForItem({"cobble"}, {math.floor(R.length / 16) * 4}, true, "For marking Chunk boundaries") | |
12292 | T:checkInventoryForItem({"minecraft:bucket", "minecraft:lava_bucket"}, {1, 1}) | |
12293 | T:checkInventoryForItem({"minecraft:torch"}, {math.floor(R.length / 16)}, false) | |
12294 | retValue = createStripMine(R) | |
12295 | elseif R.choice == 45 then --undermine dragon towers | |
12296 | utils.checkFuelNeeded(500) | |
12297 | T:checkInventoryForItem({"minecraft:cobblestone", "minecraft:cobbled_deepslate"}, {84, 84}) | |
12298 | print("Undermining dragon towers") | |
12299 | retValue = undermineDragonTowers() | |
12300 | elseif R.choice == 46 then --deactivate dragon tower | |
12301 | utils.checkFuelNeeded(50) | |
12302 | print("Deactivating dragon tower") | |
12303 | retValue = deactivateDragonTower() | |
12304 | elseif R.choice == 47 then --build dragon water trap | |
12305 | utils.checkFuelNeeded(256) | |
12306 | T:checkInventoryForItem({"stone"}, {356}) | |
12307 | T:checkInventoryForItem({"minecraft:obsidian"}, {1}) | |
12308 | T:checkInventoryForItem({"minecraft:ladder"}, {145}) | |
12309 | T:checkInventoryForItem({"minecraft:water_bucket"}, {1}) | |
12310 | print("Building dragon water trap") | |
12311 | retValue = createDragonTrap() | |
12312 | elseif R.choice == 48 then --build portal minecart station | |
12313 | utils.checkFuelNeeded(200) | |
12314 | menu.colourPrint("Inventory after height measurement", colors.red) | |
12315 | menu.colourPrint("Enter to start measurement.", colors.lime) | |
12316 | read() | |
12317 | print("Building portal platform") | |
12318 | retValue = createPortalPlatform() | |
12319 | elseif R.choice == 49 then -- shulker harvesting | |
12320 | retValue = harvestShulkers(R) | |
12321 | ||
12322 | -- CANAL BRIDGE | |
12323 | elseif R.choice == 51 then -- continuous path over void/water/lava | |
12324 | utils.checkFuelNeeded(R.length) -- allow for R.length | |
12325 | if R.data ~= "reduce" then | |
12326 | T:checkInventoryForItem({"stone"}, {R.length}, false) | |
12327 | if R.torchInterval > 0 then | |
12328 | T:checkInventoryForItem({"minecraft:torch"}, {math.floor(R.length/R.torchInterval)}, false) | |
12329 | end | |
12330 | print("Building continuous path") | |
12331 | end | |
12332 | retValue = utils.createPath(R) -- returns {numBlocks} | |
12333 | elseif R.choice == 52 then -- simple 2 block corridor | |
12334 | utils.checkFuelNeeded(R.length) | |
12335 | T:checkInventoryForItem({"stone"}, {R.length * 2}, false) | |
12336 | if R.torchInterval > 0 then | |
12337 | T:checkInventoryForItem({"minecraft:torch"}, {math.ceil(R.length / R.torchInterval)}, false) | |
12338 | end | |
12339 | print(thanks) | |
12340 | os.sleep(2) -- pause for 2 secs to allow time to press esc | |
12341 | print("Building simple corridor") | |
12342 | retValue = createCorridor(R) | |
12343 | elseif R.choice == 53 then -- canal management | |
12344 | local torches = 0 | |
12345 | local length = R.length | |
12346 | if length > 0 then | |
12347 | utils.checkFuelNeeded(length * 4) -- allow for 1024 R.length | |
12348 | if R.torchInterval > 0 then | |
12349 | torches = math.floor(length / R.torchInterval) | |
12350 | end | |
12351 | else | |
12352 | utils.checkFuelNeeded(2048) -- allow for 1024 R.length | |
12353 | length = 256 | |
12354 | end | |
12355 | T:checkInventoryForItem({"stone"}, {length}) | |
12356 | R.useBlockType = T:getMostItem("", true) | |
12357 | if R.data == 1 or (R.data == 2 and (R.subChoice == 2 or R.subChoice == 3 or R.subChoice == 5 or R.subChoice == 6)) then | |
12358 | T:checkInventoryForItem({"minecraft:water_bucket"}, {2}) | |
12359 | end | |
12360 | if torches > 0 then | |
12361 | T:checkInventoryForItem({"minecraft:torch"}, {torches}, false) | |
12362 | end | |
12363 | retValue = createWaterCanal(R) | |
12364 | elseif R.choice == 54 then -- ice canal | |
12365 | local default = R.length | |
12366 | if R.length > 0 then | |
12367 | utils.checkFuelNeeded(R.length) | |
12368 | else | |
12369 | default = 64 | |
12370 | utils.checkFuelNeeded(default * 2) -- allow for 128 min R.length | |
12371 | end | |
12372 | --[[ | |
12373 | new canal | |
12374 | 1 = left towpath- move to centre left | |
12375 | 2 = centre left ice or hollow | |
12376 | 3 = centre right ice or hollow | |
12377 | 4 = right side - move to centre right | |
12378 | convert water canal | |
12379 | 5 = left towpath | |
12380 | 6 = centre left ice or air | |
12381 | 7 = centre right ice or air | |
12382 | 8 = right towpath | |
12383 | ]] | |
12384 | if R.subChoice <= 5 or R.subChoice == 8 then -- towpath | |
12385 | T:checkInventoryForItem({"slab"}, {default}, true, "Add slabs to length required") | |
12386 | end | |
12387 | if R.torchInterval > 0 then | |
12388 | --checkInventoryForItem(items, quantities, required, message) | |
12389 | T:checkInventoryForItem({"stone"}, {math.ceil(default / R.torchInterval)}, true, "NOT bricks!") | |
12390 | R.useBlockType = T:getMostItem("", true) | |
12391 | T:checkInventoryForItem({"torch"}, {math.ceil(default / R.torchInterval)}, false) | |
12392 | end | |
12393 | if R.data == "ice" then -- ice canal with 2 spaces above | |
12394 | T:checkInventoryForItem({"minecraft:packed_ice", "minecraft:blue_ice"}, {math.ceil(R.length / 2), math.ceil(R.length / 2)}, false) | |
12395 | end | |
12396 | print(thanks) | |
12397 | os.sleep(2) -- pause for 2 secs to allow time to press esc | |
12398 | print("Building ice canal") | |
12399 | retValue = createIceCanal(R) | |
12400 | elseif R.choice == 55 then -- platform | |
12401 | local volume = R.width * R.length | |
12402 | utils.checkFuelNeeded(volume) | |
12403 | T:checkInventoryForItem({"stone", "dirt"}, {volume, volume}) | |
12404 | R.useBlockType = T:getMostItem("", true) | |
12405 | print(thanks) | |
12406 | os.sleep(2) -- pause for 2 secs to allow time to press esc | |
12407 | print("Building platform") | |
12408 | retValue = createPlatform(R) | |
12409 | elseif R.choice == 56 then -- sinking platform | |
12410 | local volume = (R.width + 1) * (R.length + 1) | |
12411 | utils.checkFuelNeeded(volume * (R.height + 1)) | |
12412 | T:checkInventoryForItem({"stone"}, {volume + ((R.length * 2) + (R.width * 2) * R.height) + 1}) | |
12413 | print(thanks) | |
12414 | os.sleep(2) -- pause for 2 secs to allow time to press esc | |
12415 | print("Building sinking platform") | |
12416 | retValue = createSinkingPlatform(R) | |
12417 | elseif R.choice == 57 then -- boat bubble lift | |
12418 | utils.checkFuelNeeded(R.height * 20) | |
12419 | T:checkInventoryForItem({"minecraft:bucket","minecraft:water_bucket"}, {2, 2}) | |
12420 | T:checkInventoryForItem({"stone"}, {R.height * 10}) | |
12421 | T:checkInventoryForItem({"gate"}, {R.height * 2}) | |
12422 | T:checkInventoryForItem({"minecraft:soul_sand"}, {R.height * 2 + 2}) | |
12423 | print(thanks) | |
12424 | os.sleep(2) -- pause for 2 secs to allow time to press esc | |
12425 | print("Building boat bubble lift") | |
12426 | retValue = createBoatLift(R) | |
12427 | --retValue = createBoatLift(R) -- R.subChoice:0=new, R.subChoice:1=extend, R.length:0=left, 1=right | |
12428 | ||
12429 | -- MOB SPAWNER | |
12430 | elseif R.choice == 61 then -- 9x9 hollow cube cobble lined | |
12431 | utils.checkFuelNeeded(600) -- allow for 600 moves | |
12432 | T:checkInventoryForItem({"slab","stone"}, {1, 3}, true, "Slab can be crafted from 3 stone") | |
12433 | if T:getItemSlot("stone") > 0 and T:getItemSlot("slab") == 0 then -- no slabs, but is stone | |
12434 | local craftOK, message = T:craft("slab") | |
12435 | end | |
12436 | if R.data == "chest" then | |
12437 | menu.colourText(nil, "~yellow~Chest(s) will be emptied first\nWait for me to exit and request\n~orange~around 700 stone!\n\n~lightGray~Enter to continue", true) | |
12438 | read() | |
12439 | else | |
12440 | T:checkInventoryForItem({"stone"}, {512}, false, "Full cube uses ~700 blocks\nEstimate your requirements") | |
12441 | end | |
12442 | print(thanks) | |
12443 | os.sleep(2) -- pause for 2 secs to allow time to press esc | |
12444 | retValue = createMobFarmCube(R) -- R.data = "spawner" or "chest": not blaze | |
12445 | elseif R.choice == 62 then -- Blaze spawner | |
12446 | utils.checkFuelNeeded(2500) -- allow for 2500 moves | |
12447 | if R.data == "blaze" then | |
12448 | T:checkInventoryForItem({"slab"}, {122}, true) | |
12449 | T:checkInventoryForItem({"stone"}, {576}) | |
12450 | print("You will be asked for more assets later") | |
12451 | print("Enter to continue") | |
12452 | read() | |
12453 | end -- else R.data == "restart" | |
12454 | retValue = createMobFarmCube(R) --R.data = "blaze" or R.data = "restart" | |
12455 | elseif R.choice == 63 then -- flood mob spawner | |
12456 | utils.checkFuelNeeded(60) -- allow for 60 moves | |
12457 | T:checkInventoryForItem({"minecraft:water_bucket"}, {2}) | |
12458 | if R.subChoice == 1 then | |
12459 | T:checkInventoryForItem({"fence"}, {2}) | |
12460 | T:checkInventoryForItem({"sign"}, {2}) | |
12461 | T:checkInventoryForItem({"slab"}, {1}) | |
12462 | T:checkInventoryForItem({"minecraft:soul_sand", "minecraft:dirt"}, {1, 1}, true) | |
12463 | end | |
12464 | print(thanks) | |
12465 | os.sleep(2) -- pause for 2 secs to allow time to press esc | |
12466 | retValue = floodMobFarm(R) | |
12467 | elseif R.choice == 64 then -- build bubble lift on top of soul sand | |
12468 | utils.checkFuelNeeded(200) -- allow for 200 moves | |
12469 | T:checkInventoryForItem({"slab","stone"}, {6, 3}, true, "Slabs can be crafted from 3 stone") | |
12470 | if T:getItemSlot("stone") > 0 and T:getItemSlot("slab") == 0 then -- no slabs, but is stone | |
12471 | local craftOK, message = T:craft("slab") | |
12472 | end | |
12473 | T:checkInventoryForItem({"minecraft:water_bucket"}, {2}) | |
12474 | T:checkInventoryForItem({"stone"}, {256}) | |
12475 | if T:getBlockType("down") ~= "minecraft:soul_sand" then | |
12476 | T:checkInventoryForItem({"minecraft:soul_sand"}, {1}) | |
12477 | end | |
12478 | T:checkInventoryForItem({"hopper"}, {1}, false) | |
12479 | if T:getItemSlot("hopper") > 0 then | |
12480 | T:checkInventoryForItem({"chest"}, {2}) | |
12481 | end | |
12482 | print(thanks) | |
12483 | os.sleep(2) -- pause for 2 secs to allow time to press esc | |
12484 | retValue = createMobBubbleLift(R) | |
12485 | elseif R.choice == 65 then -- computercraft mob grinder | |
12486 | utils.checkFuelNeeded(1000) -- allow for 1000 moves | |
12487 | T:checkInventoryForItem({"stone"}, {256}) -- for ceiling, walls and floor of area | |
12488 | R.useBlockType = T:getMostItem("", true) -- stone only, no exclusions | |
12489 | print(thanks) | |
12490 | os.sleep(2) -- pause for 2 secs to allow time to press esc | |
12491 | retValue = createMobGrinder(R) | |
12492 | elseif R.choice == 66 then -- build endermen tower | |
12493 | -- build in 3 sections, base, tower, top | |
12494 | getTaskHelp(2, 66) -- compulsory help display | |
12495 | read() -- pause until user ready | |
12496 | local numFuel = 700 | |
12497 | local choices = | |
12498 | { | |
12499 | "New tower lower base", | |
12500 | "Add tower upper base + killzone", | |
12501 | "128 block tower to existing base" | |
12502 | } | |
12503 | pp.itemColours = {colors.lime, colors.orange, colors.green} | |
12504 | local option, modifier = menu.menu("Select build stage:", choices, pp) | |
12505 | if option == 1 then --lower base | |
12506 | T:checkInventoryForItem({"minecraft:chest"}, {1}) | |
12507 | T:place("chest", -1, "down", false) | |
12508 | T:emptyInventory("up") | |
12509 | utils.checkFuelNeeded(320) -- allow for 320 moves | |
12510 | T:checkInventoryForItem({"stone"}, {144}) -- <3 stacks | |
12511 | T:checkInventoryForItem({"minecraft:water_bucket"}, {2}) | |
12512 | T:checkInventoryForItem({"fence"}, {4}) | |
12513 | T:checkInventoryForItem({"sign"}, {4}) | |
12514 | T:checkInventoryForItem({"door"}, {2}) | |
12515 | T:checkInventoryForItem({"minecraft:soul_sand"}, {1}) | |
12516 | elseif option == 2 then -- upper base | |
12517 | utils.checkFuelNeeded(710) -- allow for 703 moves | |
12518 | T:checkInventoryForItem({"stone"}, {384}) -- 6 stacks | |
12519 | T:checkInventoryForItem({"minecraft:bucket"}, {4}) | |
12520 | T:checkInventoryForItem({"fence"}, {15}) | |
12521 | T:checkInventoryForItem({"sign"}, {4}) | |
12522 | T:checkInventoryForItem({"ladder"}, {3}) | |
12523 | T:checkInventoryForItem({"minecraft:soul_sand"}, {1}) | |
12524 | else -- main tower | |
12525 | utils.checkFuelNeeded(3000) -- allow for 3000 moves | |
12526 | if T:getBlockType("down") ~= "minecraft:chest" then | |
12527 | T:checkInventoryForItem({"minecraft:chest"}, {1}) | |
12528 | T:place("chest", -1, "down", false) | |
12529 | end | |
12530 | T:checkInventoryForItem({"stone"}, {768}) -- 12 stacks | |
12531 | T:checkInventoryForItem({"minecraft:bucket"}, {10}) | |
12532 | T:checkInventoryForItem({"fence"}, {64}) -- 1 stacks | |
12533 | end | |
12534 | print(thanks) | |
12535 | os.sleep(2) -- pause for 2 secs to allow time to press esc | |
12536 | retValue = createEnderTower(option) -- 1, 2, or 3 | |
12537 | end | |
12538 | return retValue | |
12539 | end | |
12540 | ||
12541 | local function getTaskInventory(R) | |
12542 | -- run this loop 2x per second to check if player has put anything in the inventory | |
12543 | -- fuel 1 coal = 60 = 4 planks. 64 planks = 16 coal = 960 units | |
12544 | local retValue = {} | |
12545 | local thanks = "Thank you.\n\nPress the ESC key\n\nStand Back..\n" | |
12546 | ||
12547 | if R.choice < 31 then | |
12548 | - | [[~yellow~New, extend left/back=~red~^ ~orange~Extend Right=^ |
12548 | + | |
12549 | - | ~lightGray~|*|~blue~ | | | | | | ~brown~|D| |D| ~blue~| | ~lightGray~|*| |
12549 | + | |
12550 | - | ~lightGray~|*|~blue~ | | ~brown~|D|D|~blue~ | | | | | | | ~lightGray~|*| |
12550 | + | |
12551 | - | ~lightGray~|*|~blue~ | | ~brown~|D|D|~blue~ | ~brown~|D| |D| ~blue~| | ~lightGray~|*| |
12551 | + | |
12552 | - | ~lightGray~|*|~blue~ | | | | | | | | | | | | ~lightGray~|*| |
12552 | + | |
12553 | - | ~lightGray~|*|~blue~ | | | | | | | | | | | | ~lightGray~|*| |
12553 | + | |
12554 | - | ~lightGray~|*|~blue~ | | | | | | | | | | | | ~lightGray~|*| |
12554 | + | |
12555 | - | ~lightGray~|~red~^~lightGray~|*|*|*|*|*|*~magenta~|M|~lightGray~*|*|*|*|*|*|~orange~^| |
12555 | + | |
12556 | - | ~lime~4 ~brown~double trees~green~ or 16 ~brown~single trees |
12556 | + | |
12557 | - | ~brown~D = Dirt, ~magenta~M = Modem |
12557 | + | |
12558 | - | ~red~^~yellow~ = Turtle ~red~(new/left/back) ~orange~^ on right |
12558 | + | |
12559 | end | |
12560 | print(thanks) | |
12561 | - | [[~yellow~Place me on ground as below ~lightGray~^ ~magenta~^ |
12561 | + | |
12562 | - | ~lime~|*|~blue~ | | | | | | | ~green~or |*|~blue~ | | ~brown~|D| |D| | |
12562 | + | |
12563 | - | ~lime~|*|~blue~ | | ~brown~|D|D|~blue~ | | ~green~or |*|~blue~ | | | | | | | |
12563 | + | |
12564 | - | ~lime~|*|~blue~ | | ~brown~|D|D|~blue~ | | ~green~or |*|~blue~ | | ~brown~|D| |D| | |
12564 | + | |
12565 | - | ~lime~|*|~blue~ | | | | | | | ~green~or |*|~blue~ | | | | | | | |
12565 | + | |
12566 | - | ~lime~|*|~blue~ | | | | | | | ~green~or |*|~blue~ | | | | | | | |
12566 | + | |
12567 | - | ~lime~|*|*|*|*|~lightGray~^~lime~|*| ~magenta~|^| ~green~or |*|*|*|*|~lightGray~^~green~|*|*~magenta~|^| |
12567 | + | |
12568 | - | ~lime~ 4 ~brown~double trees~green~ or 16 ~brown~single trees |
12568 | + | |
12569 | - | ~brown~D = dirt |
12569 | + | |
12570 | - | ~lightGray~^ = Turtle on marker (Legacy storage) |
12570 | + | |
12571 | - | ~magenta~^ = Turtle on Modem (Network storage) |
12571 | + | |
12572 | retValue = clearWall(R) | |
12573 | elseif R.choice == 74 then --Clear single R.height perimeter wall | |
12574 | utils.checkFuelNeeded((R.width + R.length) * 2) | |
12575 | print("Recycling wall section "..R.width.." x "..R.length) | |
12576 | retValue = clearPerimeter(R) | |
12577 | elseif R.choice == 75 then --Clear hollow structure | |
12578 | utils.checkFuelNeeded((R.width * R.length) + ((R.width + R.length) * R.height)) | |
12579 | print("Recycling hollow object "..R.width.." x "..R.length.." height: "..R.height) | |
12580 | retValue = clearBuilding(R) | |
12581 | elseif R.choice == 76 then --Clear solid structure / extend water pool | |
12582 | utils.checkFuelNeeded((R.width * R.length) + ((R.width + R.length) * R.height)) | |
12583 | print("Recycling solid object w:"..R.width..", l:"..R.length..", h:"..R.height) | |
12584 | retValue = clearSolid(R) | |
12585 | elseif R.choice == 77 then -- Dig trench | |
12586 | utils.checkFuelNeeded(R.height * R.length * 2) | |
12587 | print(thanks) | |
12588 | os.sleep(2) -- pause for 2 secs to allow time to press esc | |
12589 | if R.length == 0 then | |
12590 | print("Digging continuous trench "..R.height.." blocks deep") | |
12591 | else | |
12592 | print("Digging trench "..R.length.." blocks long, "..R.height.." blocks deep") | |
12593 | end | |
12594 | retValue = digTrench(R) | |
12595 | elseif R.choice == 78 then --Carve mountain | |
12596 | utils.checkFuelNeeded(R.length * R.width * 10) | |
12597 | print("Carving mountain side "..R.width.." x "..R.length) | |
12598 | retValue = clearMountainSide(R) | |
12599 | elseif R.choice == 79 then -- Place floor or Ceiling | |
12600 | local blocks = R.width * R.length | |
12601 | utils.checkFuelNeeded(blocks) | |
12602 | T:checkInventoryForItem({"stone", "log", "planks"}, {blocks, blocks, blocks}, false) | |
12603 | R.useBlockType = T:getMostItem() | |
12604 | - | ~lightGray~|*|~green~ | | | ~lightGray~|*| ~green~| | ~lightGray~* = Wall |
12604 | + | |
12605 | - | ~lightGray~|*|~green~ | | | ~lightGray~|*| ~green~| | |
12605 | + | |
12606 | - | ~lightGray~|*|~green~ | | | ~lightGray~|*| ~green~| | |
12606 | + | |
12607 | - | ~lightGray~|*|~green~ | | | ~lightGray~|*| ~green~| | |
12607 | + | |
12608 | - | ~lightGray~|*|~green~ | | | ~lightGray~|*| ~green~| | ~magenta~M = Modem |
12608 | + | |
12609 | - | ~brown~|B|B~green~| | |~lightGray~or |*| ~green~| | ~brown~B = Barrel or Chest |
12609 | + | |
12610 | - | ~brown~|B|~blue~W~green~| | |~lightGray~or ~magenta~|M|~blue~W~green~| | ~blue~W = Water |
12610 | + | |
12611 | - | ~lime~|~red~^~lime~|~brown~B|B|~lightGray~*|or ~brown~|~red~^~brown~|~magenta~M|~lightGray~*| ~red~^ = Turtle |
12611 | + | |
12612 | - | ~brown~Legacy ~lightGray~or ~magenta~Network ~yellow~Size = 12 x 12 |
12612 | + | |
12613 | T:checkInventoryForItem({"sand", "gravel"}, {1024, 1024}, false) | |
12614 | if R.length == 0 then | |
12615 | - | [[~yellow~Place on any ~brown~T ~blue~T ~magenta~T~yellow~ facing < > ^ v |
12615 | + | |
12616 | else | |
12617 | - | ~lightGray~|*|~green~ | | | ~lightGray~|*| ~green~| | ~lightGray~* = Wall |
12617 | + | |
12618 | - | ~lightGray~|*|~green~ | | | ~lightGray~|*| ~green~| | |
12618 | + | |
12619 | - | ~lightGray~|*|~green~ | | | ~lightGray~|*| ~green~| | |
12619 | + | |
12620 | - | ~lightGray~|*|~green~ | | | ~lightGray~|*| ~green~| | ~magenta~M = Modem |
12620 | + | |
12621 | - | ~lightGray~|*|~green~ | | | ~lightGray~|*| ~green~| | ~brown~B = Barrel or Chest |
12621 | + | |
12622 | - | ~brown~|B|B~green~| | |~lightGray~or |*| ~green~| | ~blue~W = Water |
12622 | + | |
12623 | - | ~brown~|B~blue~|T| ~green~| |~lightGray~or ~magenta~|M|~blue~T~green~| | ~orange~S = Sapling or Tree |
12623 | + | |
12624 | - | ~orange~|S|~brown~T|B|~lightGray~*|or ~brown~|B~magenta~|T|~lightGray~*| ~brown~T ~lightGray~= Turtle (~blue~T ~magenta~T~lightGray~) |
12624 | + | |
12625 | - | ~brown~Legacy ~lightGray~or ~magenta~Network ~yellow~Size = 12 x 12 |
12625 | + | |
12626 | utils.checkFuelNeeded(200) | |
12627 | if R.length == 0 then | |
12628 | - | [[~yellow~Place as below ~blue~T~yellow~ facing < > ^ v |
12628 | + | |
12629 | else | |
12630 | - | ~lightGray~|*|~green~ | | | ~lightGray~|*| ~green~| | ~lightGray~* = Wall |
12630 | + | |
12631 | - | ~lightGray~|*|~green~ | | | ~lightGray~|*| ~green~| | |
12631 | + | |
12632 | - | ~lightGray~|*|~green~ | | | ~lightGray~|*| ~green~| | |
12632 | + | |
12633 | - | ~lightGray~|*|~green~ | | | ~lightGray~|*| ~green~| | ~magenta~M = Modem |
12633 | + | |
12634 | - | ~lightGray~|*|~green~ | | | ~lightGray~|*| ~green~| | ~brown~B = Barrel or Chest |
12634 | + | |
12635 | - | ~brown~|B|B~green~| | |~lightGray~or |*| ~green~| | C = Crop (first) |
12635 | + | |
12636 | - | ~brown~|B|~blue~T~green~|C| |~lightGray~or ~magenta~|M|~blue~T~green~|C| ~orange~S = Sapling or Tree |
12636 | + | |
12637 | - | ~orange~|S|~brown~B|B|~lightGray~*|or ~magenta~|M|~brown~B|~lightGray~*| ~blue~T = Turtle on Water |
12637 | + | |
12638 | ||
12639 | elseif R.choice == 82 then --build containing wall in water or lava | |
12640 | utils.checkFuelNeeded(R.length * R.length) | |
12641 | local depth = R.height | |
12642 | if depth == 0 then | |
12643 | depth = 20 | |
12644 | end | |
12645 | T:checkInventoryForItem({"stone"}, {R.length * depth}, false) | |
12646 | print("Building retaining wall in lava/water. length "..R.length) | |
12647 | retValue = createRetainingWall(R) | |
12648 | elseif R.choice == 83 then -- create a rectangle path in water/lava | |
12649 | utils.checkFuelNeeded(200) | |
12650 | createRectanglePath(R) | |
12651 | elseif R.choice == 84 then -- Delete water/lava | |
12652 | if R.width == 0 then | |
12653 | utils.checkFuelNeeded(2000) | |
12654 | T:checkInventoryForItem({"stone"}, {256}, false) | |
12655 | print("Deleting water using auto-detection") | |
12656 | else | |
12657 | if R.height == 0 then | |
12658 | utils.checkFuelNeeded(2000) | |
12659 | T:checkInventoryForItem({"stone"}, {256}, false) | |
12660 | else | |
12661 | utils.checkFuelNeeded(R.width * R.length * R.height) | |
12662 | T:checkInventoryForItem({"stone"}, {math.max(R.length, R.width) * 2}, false) | |
12663 | end | |
12664 | print("Deleting enclosed water "..R.width.." x "..R.length.." x ".. R.height) | |
12665 | end | |
12666 | retValue = utils.drainWaterLava(R) | |
12667 | elseif R.choice == 85 then -- Sinking platform | |
12668 | local volume = (R.width + 1) * (R.length + 1) | |
12669 | utils.checkFuelNeeded(volume * (R.height + 1)) | |
12670 | T:checkInventoryForItem({"stone"}, {volume + ((R.length * 2) + (R.width * 2) * R.height) + 1}) | |
12671 | print(thanks) | |
12672 | os.sleep(2) -- pause for 2 secs to allow time to press esc | |
12673 | print("Building sinking platform") | |
12674 | retValue = createSinkingPlatform(R) | |
12675 | elseif R.choice == 86 then -- ocean monument utilities | |
12676 | if R.subChoice == 1 then -- Build 4 corner marker columns | |
12677 | --R.useBlockType = "prismarine", R.data = "oceanMonumentColumns" | |
12678 | T:checkInventoryForItem({"stone"}, {448}) | |
12679 | retValue = oceanMonumentColumns(R) | |
12680 | elseif R.subChoice == 2 then -- Retaining wall beween 2 columns | |
12681 | T:checkInventoryForItem({"stone"}, {1024}) | |
12682 | retValue = createRetainingWall(R) | |
12683 | elseif R.subChoice == 3 then -- Clear plants pre sand draining | |
12684 | retValue = clearWaterPlants(R) | |
12685 | elseif R.subChoice == 4 then -- Use sand draining | |
12686 | utils.checkFuelNeeded(100) | |
12687 | T:checkInventoryForItem({"sand", "gravel"}, {1024, 1024}, false) | |
12688 | if R.length == 0 then | |
12689 | print("Building sand wall. Auto length: ") | |
12690 | else | |
12691 | print("Building sand wall. length: "..R.length) | |
12692 | end | |
12693 | retValue = createSandWall(R) | |
12694 | elseif R.subChoice == 5 then -- remove sand wall | |
12695 | utils.checkFuelNeeded(200) | |
12696 | print("Digging sand from ocean monument") | |
12697 | retValue = clearSandWall(R) | |
12698 | elseif R.subChoice == 6 then -- Drain and remove structure | |
12699 | T:checkInventoryForItem({"stone"}, {1024}) | |
12700 | retValue = utils.drainWaterLava(R) | |
12701 | end | |
12702 | elseif R.choice == 87 then --ladder to water/lava | |
12703 | utils.checkFuelNeeded(R.height * 2) | |
12704 | T:checkInventoryForItem({"minecraft:ladder"}, {R.height}, true, "Add more to be safe!") | |
12705 | local cobble = R.height * 3 + 10 | |
12706 | T:checkInventoryForItem({"stone"}, {cobble}) | |
12707 | print(thanks) | |
12708 | os.sleep(2) -- pause for 2 secs to allow time to press esc | |
12709 | print("Creating ladder to bedrock") | |
12710 | retValue = createLadderToWater() | |
12711 | elseif R.choice == 88 then --remove plants | |
12712 | utils.checkFuelNeeded(R.length * R.width * 4) | |
12713 | T:checkInventoryForItem({"sand", "stone"}, {64, 64}) | |
12714 | local width = R.width | |
12715 | local length = R.length | |
12716 | if width == 0 then | |
12717 | width = "auto" | |
12718 | end | |
12719 | if length == 0 then | |
12720 | length = "auto" | |
12721 | end | |
12722 | print("Removing water plants. length: "..length.." width: "..width) | |
12723 | retValue = clearWaterPlants(R) | |
12724 | elseif R.choice == 89 then -- convert flowing water to source | |
12725 | --utils.checkFuelNeeded(R.length * R.width * 4) -- unknown as size not calculated | |
12726 | T:checkInventoryForItem({"water_bucket", "bucket"}, {12, 12}) | |
12727 | T:checkInventoryForItem({"slab"}, {128}) | |
12728 | print("Converting water to source "..R.width.." x "..R.length.." x ".. R.height) | |
12729 | retValue = convertWater(R) | |
12730 | elseif R.choice == 810 then -- create sloping water | |
12731 | utils.checkFuelNeeded(R.length * R.width * 3) | |
12732 | local buckets = math.floor(R.length / 2) + 1 | |
12733 | T:checkInventoryForItem({"water_bucket", "bucket"}, {buckets, buckets}) | |
12734 | T:checkInventoryForItem({"slab"}, {R.length * R.width}) | |
12735 | print("Creating sloping water field "..R.width.." x "..R.length.." x ".. R.height) | |
12736 | retValue = createSlopingWater(R) | |
12737 | -- BUILDING & RAILWAY | |
12738 | elseif R.choice == 91 then -- Build a wall | |
12739 | local blocks = R.height * R.length | |
12740 | utils.checkFuelNeeded(blocks) | |
12741 | T:checkInventoryForItem({"stone", "planks", "bricks"}, {blocks, blocks, blocks}) | |
12742 | R.useBlockType = T:getMostItem() | |
12743 | print("Building a wall using "..R.useBlockType) | |
12744 | sleep(2) | |
12745 | retValue = buildWall(R) | |
12746 | elseif R.choice == 92 then -- Build a rectangular structure | |
12747 | local blocks = (R.height * R.length * 2) + (R.height * R.width * 2) | |
12748 | utils.checkFuelNeeded(blocks) | |
12749 | T:checkInventoryForItem({"stone", "planks", "bricks"}, {blocks, blocks, blocks}) | |
12750 | R.useBlockType = T:getMostItem() | |
12751 | print("Building a house using "..R.useBlockType) | |
12752 | sleep(2) | |
12753 | retValue = buildStructure(R) | |
12754 | elseif R.choice == 93 or R.choice == 94 then -- Build a gable end roof / pitched roof | |
12755 | local blocks = ((R.width + 2) * (R.length + 2)) | |
12756 | utils.checkFuelNeeded(blocks) | |
12757 | if menu.getBoolean("Using stairs / planks for roof (y/n)", nil, colors.yellow) then | |
12758 | T:checkInventoryForItem({"planks", "stairs"}, {blocks, blocks}) | |
12759 | else | |
12760 | T:checkInventoryForItem({"stone"}, {blocks}) | |
12761 | end | |
12762 | ||
12763 | R.useBlockType = T:getMostItem() | |
12764 | if R.choice == 93 then -- Build a gableroof | |
12765 | if R.width % 2 == 1 then | |
12766 | T:checkInventoryForItem({"slab"}, {R.length + 2}, false, "Match slabs with roof blocks") | |
12767 | end | |
12768 | blocks = (R.width * 6) | |
12769 | T:checkInventoryForItem({"stone", "planks", "bricks"}, {blocks, blocks, blocks}, true, "Match gable with existing building") | |
12770 | else | |
12771 | local isWidthOdd, isLengthOdd, width, length = false, false, 0, 0 | |
12772 | R, isWidthOdd, isLengthOdd, width, length = utils.getRoofStats(R) | |
12773 | if isWidthOdd then | |
12774 | T:checkInventoryForItem({"slab"}, {length - 2}, false, "Match slabs with roof blocks") | |
12775 | end | |
12776 | end | |
12777 | print("Building a roof using "..R.useBlockType) | |
12778 | sleep(2) | |
12779 | if R.choice == 93 then -- Build a gableroof | |
12780 | retValue = buildGableRoof(R) | |
12781 | else -- Build a pitched roof | |
12782 | retValue = buildPitchedRoof(R) | |
12783 | end | |
12784 | elseif R.choice == 95 or R.choice == 96 then --place redstone torch level or downward slope | |
12785 | utils.checkFuelNeeded(10) | |
12786 | if R.choice == 95 then | |
12787 | R.data = "level" | |
12788 | else | |
12789 | R.data = "up" | |
12790 | end | |
12791 | T:checkInventoryForItem({"stone"}, {1}) | |
12792 | R.useBlockType = T:getMostItem("", true) | |
12793 | T:checkInventoryForItem({"minecraft:redstone_torch"}, {1}) | |
12794 | print("Placing redstone torch on ".. R.useBlockType) | |
12795 | retValue = placeRedstoneTorch(R) | |
12796 | elseif R.choice == 97 or R.choice == 98 then --build downward/upward slope | |
12797 | local blocks = R.height * 2 | |
12798 | if R.height == 0 then | |
12799 | blocks = 64 | |
12800 | end | |
12801 | utils.checkFuelNeeded(blocks) | |
12802 | T:checkInventoryForItem({"stone"}, {blocks}) | |
12803 | print("Building slope") | |
12804 | sleep(2) | |
12805 | retValue = createRailway(R) | |
12806 | elseif R.choice == 101 or R.choice == 102 or R.choice == 103 or R.choice == 104 then -- measure height/depth/length | |
12807 | retValue = measure(R) | |
12808 | elseif R.choice == 105 then--Borehole | |
12809 | retValue = createBorehole(R) | |
12810 | end | |
12811 | end | |
12812 | return retValue | |
12813 | end | |
12814 | ||
12815 | local function test(R) | |
12816 | local lib = {} | |
12817 | ||
12818 | function lib.dig(direction, bypass, slot) | |
12819 | direction = direction or "forward" | |
12820 | slot = slot or 1 | |
12821 | bypass = bypass or true | |
12822 | ||
12823 | print("direction: "..direction) | |
12824 | print("bypass: "..tostring(bypass)) | |
12825 | print("slot: "..slot) | |
12826 | ||
12827 | end | |
12828 | lib.dig("down") | |
12829 | read() | |
12830 | end | |
12831 | ||
12832 | local function main() | |
12833 | local lib = {} | |
12834 | ||
12835 | function lib.checkLabel() | |
12836 | if os.getComputerLabel() == nil then | |
12837 | os.setComputerLabel("toolkit") | |
12838 | print("Computer label set to "..os.getComputerLabel()) | |
12839 | end | |
12840 | end | |
12841 | ||
12842 | function lib.checkLibs(libDir, filename) | |
12843 | local fileExists = false | |
12844 | if fs.exists(libDir) then | |
12845 | if not fs.isDir(libDir) then | |
12846 | fs.move(libDir, libDir.."Renamed") | |
12847 | fs.makeDir(libDir) | |
12848 | end | |
12849 | else | |
12850 | fs.makeDir(libDir) | |
12851 | end | |
12852 | if fs.exists(fs.combine(libDir, filename)) or fs.exists(fs.combine(libDir, filename..".lua")) then | |
12853 | fileExists = true | |
12854 | end | |
12855 | return fileExists | |
12856 | end | |
12857 | ||
12858 | local doContinue = true | |
12859 | lib.checkLabel() -- make sure turtle label is set | |
12860 | --check if lib folder exists | |
12861 | if not lib.checkLibs("lib", "clsTurtle") then | |
12862 | -- use pastebin get to download clsTurtle to libs folder | |
12863 | print("Missing clsTurtle.lua in libs directory") | |
12864 | print("Attempting to obtain from Pastebin...") | |
12865 | if shell.run("pastebin","get","tvfj90gK","lib/clsTurtle.lua") then | |
12866 | print("clsTurtle.lua installed from Pastebin") | |
12867 | else | |
12868 | print("failed to install clsTurtle.lua from Pastebin") | |
12869 | doContinue = false | |
12870 | end | |
12871 | end | |
12872 | if not lib.checkLibs("lib", "menu") then | |
12873 | -- use pastebin get to download menu.lua to libs folder | |
12874 | print("Missing menu.lua in libs directory") | |
12875 | print("Attempting to obtain from Pastebin...") | |
12876 | if shell.run("pastebin","get","BhjbYsw4","lib/menu.lua") then | |
12877 | print("menu.lua installed from Pastebin") | |
12878 | else | |
12879 | print("failed to install menu.lua from Pastebin") | |
12880 | doContinue = false | |
12881 | end | |
12882 | end | |
12883 | if doContinue then | |
12884 | local result = {} | |
12885 | local R = | |
12886 | { | |
12887 | choice = 0, | |
12888 | subChoice = 0, | |
12889 | size = 0, | |
12890 | width = 0, | |
12891 | length = 0, | |
12892 | height = 0, | |
12893 | depth = 0, | |
12894 | up = false, | |
12895 | down = false, | |
12896 | silent = false, | |
12897 | data = "", | |
12898 | torchInterval = 0, | |
12899 | useBlockType = "", | |
12900 | auto = false, | |
12901 | side = "" | |
12902 | } | |
12903 | menu = require("lib.menu") | |
12904 | T = require("lib.clsTurtle").new(false) -- true enables logfile to log.txt note dot NOT colon | |
12905 | T:clear() | |
12906 | doContinue = false -- reset | |
12907 | if args[1] ~= nil then | |
12908 | if args[1]:sub(1,1) == "h" then | |
12909 | local help = | |
12910 | [[... = any following characters | |
12911 | ||
12912 | tk v... = mc/ccTweaked versions | |
12913 | tk log = enable logging | |
12914 | tk log d... = enable logging + debug | |
12915 | tk find = writes locate.txt | |
12916 | tk test = runs test(R) | |
12917 | tk farm = runs manageFarm(R) | |
12918 | ||
12919 | ||
12920 | ||
12921 | Enter to exit]] | |
12922 | menu.colourPrint(help, colours.yellow) | |
12923 | read() | |
12924 | elseif args[1] == "log" then | |
12925 | if args[2] ~= nil then | |
12926 | if args[2]:sub(1,1) == "d" then | |
12927 | dbug = true -- set dbug flag | |
12928 | menu.colourPrint("Logging and debugging enabled", colors.lime) | |
12929 | end | |
12930 | else | |
12931 | menu.colourPrint("Logging enabled", colors.lime) | |
12932 | end | |
12933 | if T:getLogExists() then | |
12934 | if menu.getBoolean("Delete existing log file? (y/n)", 3, colors.orange) then | |
12935 | T:deleteLog() | |
12936 | menu.colourPrint("Log file deleted", colors.yellow) | |
12937 | end | |
12938 | end | |
12939 | T:setUseLog(true) | |
12940 | doContinue = true | |
12941 | if dbug then | |
12942 | menu.colourPrint("Enter to continue...", colors.lightBlue) | |
12943 | read() | |
12944 | end | |
12945 | elseif args[1] == "farm" then | |
12946 | R.silent = true | |
12947 | R.data = "farm" | |
12948 | R.auto = true | |
12949 | manageFarm(R) | |
12950 | --elseif args[1] == "tree" then | |
12951 | --manageTreeFarm() -- use file to read status | |
12952 | elseif args[1] == "find" then | |
12953 | -- missing turtle: player used 'tk find' | |
12954 | T:setUseLog(true) | |
12955 | T:setLogFileName("locate.txt") | |
12956 | T:appendLine("Booting succeeded") | |
12957 | T:appendLine("Block ahead: "..T:getBlockType("forward")) | |
12958 | T:appendLine("Block above: "..T:getBlockType("up")) | |
12959 | T:appendLine("Block below: "..T:getBlockType("down")) | |
12960 | elseif args[1] == "test" then | |
12961 | test(R) | |
12962 | elseif args[1]:find("v") ~= nil then | |
12963 | print("_HOST:") | |
12964 | print() | |
12965 | print(_HOST) | |
12966 | print() | |
12967 | print("Minecraft major version: "..mcMajorVersion) | |
12968 | print("Minecraft minor version: "..mcMinorVersion) | |
12969 | print("ccTweaked major version: "..ccMajorVersion) | |
12970 | print("ccTweaked minor version: "..ccMinorVersion) | |
12971 | print("tk version: "..tkVersion) | |
12972 | print("clsTurtle version: "..version) | |
12973 | print("\nEnter to exit") | |
12974 | read() | |
12975 | end | |
12976 | else | |
12977 | doContinue = true | |
12978 | end | |
12979 | if doContinue then | |
12980 | print("Minecraft major version: "..mcMajorVersion) | |
12981 | print("Bedrock level: "..bedrock) | |
12982 | if T:getUseLog() then | |
12983 | if T:saveToLog("Started with logging enabled", true) then | |
12984 | menu.colourPrint("\nEnter to continue...", colors.lightBlue) | |
12985 | read() | |
12986 | end | |
12987 | else | |
12988 | print("Logging disabled") | |
12989 | end | |
12990 | sleep(1) | |
12991 | while R.choice == 0 do | |
12992 | R = chooseTask(R) | |
12993 | end | |
12994 | if R.choice > 0 then | |
12995 | R = getTask(R) | |
12996 | if R.data ~= "quit" then | |
12997 | result = getTaskInventory(R) -- table of comments | |
12998 | end | |
12999 | end | |
13000 | end | |
13001 | T:clear() | |
13002 | table.insert(result, "Thank you for using 'survival toolkit'") | |
13003 | local clr = {colors.yellow, colors.orange, colors.green, colors.lightBlue} | |
13004 | local count = 1 | |
13005 | for _, value in ipairs(result) do | |
13006 | --print(value) | |
13007 | --.print(text, fg, bg, width) | |
13008 | - | info.sub[67] = |
13008 | + | |
13009 | - | [[Turtle moves toward spawner |
13009 | + | |
13010 | - | Place at spawner level. |
13010 | + | |
13011 | count = 1 | |
13012 | - | Can be behind a wall for protection |
13012 | + | |
13013 | - | of player. |
13013 | + | |
13014 | else | |
13015 | - | Embeds in wall with attack working |
13015 | + | |
13016 | end | |
13017 | - | Needs 24 blocks |
13017 | + | |
13018 | ||
13019 | - | ]] -- Build 3*3*3 wall around trial spawner |
13019 | + |