Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- version = 20230927.1400
- local tkVersion = version -- otherwise over-written by clsTurtle when loaded
- --[[
- **********Toolkit v2**********
- https://pastebin.com/UFvjc1bw
- Last edited: see version YYYYMMDD.HHMM
- if NOT online:
- Make sure you create a folder 'lib' and place menu.lua and clsTurtle.lua into it
- else
- lib folder will be created and files obtained automatically!
- end
- ]]
- args = {...} -- eg "farm", "tree"
- local menu, T
- --[[
- Computercraft started with mc version 1.7.10 and went to 1.8.9
- ccTweaked started around mc 1.12.2 and currently at 1.18
- mc 1.18 has new blocks and bedrock at -64, so needs to be taken into account.
- _HOST = The ComputerCraft and Minecraft version of the current computer environment.
- For example, ComputerCraft 1.93.0 (Minecraft 1.15.2).
- ]]
- local dbug = false -- debug is reserved word
- local bedrock = 0
- local netherBedrock = 0
- local ceiling = 255
- local deletesWater = false
- local brick = "minecraft:nether_brick" -- pre 1.16+ name
- local ccMajorVersion = _HOST:sub(15, _HOST:find("Minecraft") - 2) --eg ComputerCraft 1.93.0 (Minecraft 1.15.2)
- local ccMinorVersion = 0
- --[[
- Netherite level stand on 14
- Chunk borders F3+G or:
- math.floor(x / 16) * 16 add 16 for each border. same for z
- ]]
- function string:split(sSeparator, nMax, bRegexp, noEmpty)
- --[[return a table split with sSeparator. noEmpty removes empty elements
- use: tblSplit = SplitTest:split('~',[nil], [nil], false) or tblSplit = string.split(SplitTest, '~')]]
- assert(sSeparator ~= '','separator must not be empty string')
- assert(nMax == nil or nMax >= 1, 'nMax must be >= 1 and not nil')
- if noEmpty == nil then noEmpty = true end
- local aRecord = {}
- local newRecord = {}
- -- self refers to the 'string' being split
- if self:len() > 0 then
- local bPlain = not bRegexp
- nMax = nMax or -1
- local nField, nStart = 1, 1
- local nFirst,nLast = self:find(sSeparator, nStart, bPlain)
- while nFirst and nMax ~= 0 do
- aRecord[nField] = self:sub(nStart, nFirst-1)
- nField = nField+1
- nStart = nLast+1
- nFirst,nLast = self:find(sSeparator, nStart, bPlain)
- nMax = nMax-1
- end
- aRecord[nField] = self:sub(nStart)
- if noEmpty then --split on newline preserves empty values
- for i = 1, #aRecord do
- if aRecord[i] ~= "" then
- table.insert(newRecord, aRecord[i])
- end
- end
- else
- newRecord = aRecord
- end
- end
- return newRecord
- end
- if tonumber(ccMajorVersion) == nil then -- 1.93.0 NAN
- --ccMajorVersion = ccMajorVersion:sub(1, ccMajorVersion:find(".", 3, true) - 1)
- local parts = ccMajorVersion:split(".")
- ccMajorVersion = parts[1]
- if parts[2] ~= nil then
- ccMajorVersion = ccMajorVersion.."."..parts[2]
- end
- ccMajorVersion = tonumber(ccMajorVersion)
- if parts[3] ~= nil then
- ccMinorVersion = tonumber(parts[3])
- end
- end
- local mcMajorVersion = _HOST:sub(_HOST:find("Minecraft") + 10, _HOST:find("\)") - 1) -- eg 1.18 or 1.20 -> 1.18, 1.20
- local mcMinorVersion = 0
- if tonumber(mcMajorVersion) == nil then -- 1.18.3 NAN
- --mcMajorVersion = tonumber(_HOST:sub(_HOST:find("Minecraft") + 10, _HOST:find("\)") - 3)) -- eg 1.19.4 -> 1.19
- local parts = mcMajorVersion:split(".")
- mcMajorVersion = parts[1]
- if parts[2] ~= nil then
- mcMajorVersion = mcMajorVersion.."."..parts[2]
- end
- mcMajorVersion = tonumber(mcMajorVersion)
- if parts[3] ~= nil then
- mcMinorVersion = tonumber(parts[3])
- end
- end
- if mcMajorVersion < 1.7 and mcMajorVersion >= 1.18 then -- 1.12 to 1.??
- bedrock = -64
- ceiling = 319
- end
- if mcMajorVersion < 1.7 and mcMajorVersion >= 1.16 then -- 1.12 to 1.??
- brick = "minecraft:nether_bricks"
- end
- if mcMajorVersion < 1.7 and mcMajorVersion <= 1.12 then --- turtle in source deletes it. 1.7.10 to 1.12
- deletesWater = true
- end
- local utils = {}
- function utils.tableConcat(tbl, sep)
- local output = ""
- for i,value in pairs(tbl) do
- output = output .. tostring(value)
- if i ~= #tbl then
- output = output .. sep
- end
- end
- return output
- end
- function utils.calculateDimensions(R)
- if R.data == "" then -- not being called from other functions
- if R.width == 0 then -- user chose auto settings
- R.length = utils.calculateDistance(R.length) -- still facing forward
- print("Calculated Length = "..R.length)
- T:turnRight(1) -- ready to check width
- R.width = utils.calculateDistance(R.width) -- now facing right
- print("Calculated width = "..R.width)
- T:go("R2F"..R.width - 1 .."L1".. "F"..R.length - 1 .."R2") -- back at start. width/length confirmed
- end
- end
- if R.height == 0 then -- use auto settings based on water detection
- R.height = 64
- end
- return R
- end
- function utils.calculateDistance(estDistamcMajorVersionnce)
- --[[
- measure length
- movement stops when either solid block in front or solid below
- called from utils.calculateDimensions
- ]]
- local moves = 1
- local nonSolidBelow = utils.clearVegetation("down")
- if estDistance == 0 then
- while nonSolidBelow and turtle.forward() do -- while able to move and air/water below
- moves = moves + 1
- nonSolidBelow = utils.clearVegetation("down")
- end
- else
- while moves < estDistance * 2 do -- loop can only run for max of double estimated distance
- if turtle.forward() then -- able to move forward
- moves = moves + 1
- else
- break
- end
- if not utils.clearVegetation("down") then -- solid below
- turtle.back()
- moves = moves - 1
- break
- end
- end
- end
- return moves
- end
- function utils.checkFuelNeeded(quantity)
- local fuelNeeded = quantity - turtle.getFuelLevel() -- eg 600
- if fuelNeeded > 0 then
- if T:checkInventoryForItem({"minecraft:lava_bucket"}, {1}, false) == nil then
- if T:checkInventoryForItem({"coal"}, {math.ceil(fuelNeeded / 60)}, false) == nil then
- T:checkInventoryForItem({"planks"}, {math.ceil(fuelNeeded / 15)})
- end
- end
- T:refuel(quantity, true)
- end
- end
- function utils.clearVegetation(direction)
- local isAirWaterLava = true -- default true value air/water/lava presumed
- -- blockType, blockModifier, data
- local blockType, blockModifier = T:getBlockType(direction)
- if blockType ~= "" then --not air
- if T:isVegetation(blockType) then
- T:dig(direction)
- elseif blockType:find("water") == nil
- and blockType:find("lava") == nil
- and blockType:find("bubble") == nil
- and blockType:find("ice") == nil then
- -- NOT water, ice or lava
- isAirWaterLava = false -- solid block
- end
- end
- return isAirWaterLava --clears any grass or sea plants, returns true if air or water, bubble column or ice
- end
- function utils.createPath(R) -- 51
- --[[places a path in air/lava/water. R can also be of type int]]
- local length = 0
- local reduce = false
- local torchInterval = 8
- if type(R) == "table" then
- length = R.length
- if R.data == "reduce" then
- reduce = true
- end
- torchInterval = R.torchInterval
- else
- length = R
- end
- local numBlocks = 0
- if reduce then
- T:forward(1)
- local blockType = T:getBlockType("down")
- local useBlock = blockType
- while blockType == useBlock do
- T:go("x2F1")
- numBlocks = numBlocks + 1
- blockType = T:getBlockType("down")
- end
- utils.goBack(numBlocks + 1)
- else
- for i = 1, 2 do
- T:fillVoid("down", {}, false)
- T:forward(1)
- numBlocks = numBlocks + 1
- end
- local place = utils.clearVegetation("down")
- while place do -- while air, water, normal ice, bubble column or lava below
- if T:fillVoid("down", {}, false) then -- false if out of blocks
- T:forward(1)
- numBlocks = numBlocks + 1
- if numBlocks % torchInterval == 1 or numBlocks == 0 then
- if T:getItemSlot("minecraft:torch", -1) > 0 then
- T:turnRight(2)
- T:place("minecraft:torch", -1, "forward", false)
- T:turnRight(2)
- end
- end
- else
- break
- end
- if length > 0 and numBlocks >= length then -- not infinite path (length = 0)
- break
- end
- place = utils.clearVegetation("down")
- end
- end
- return {numBlocks} -- returned as a table in case called as task 51 back to main()
- end
- function utils.createWalledSpace(D)
- --[[
- D.width = #
- D.length = #
- D.height = #
- D.ceiling = false
- D.floor = false
- D.vDirection = "U" or "D"
- D.hDirection = "LR" or "RL"
- D.goHome = true
- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
- ]]
- local turn = "R1"
- local oTurn = "L1"
- if D.hDirection == "RL" then
- turn = "L1"
- oTurn = "R1"
- end
- local placeF = "C1"
- local lib = {}
- function lib.getPlace(D, start, finish)
- if start then -- start of build
- if D.vDirection == "U" then -- bottom and going up
- if D.floor then
- return "C2"
- end
- else -- D.vDirection == "D"
- if D.ceiling then
- return "C0"
- end
- end
- elseif finish then -- end of build
- if D.vDirection == "U" then -- bottom and going up
- if D.ceiling then
- return "C0"
- end
- else
- if D.floor then
- return "C2"
- end
- end
- end
- return "" -- start and finish both false
- end
- function lib.layer(D, start, finish)
- local outward = true
- local place = lib.getPlace(D, start, finish)
- for width = 1, D.width do
- for length = 1, D.length do
- if start or finish then
- T:go(place, false, 0, true)-- place floor / ceiling
- end
- if width == 1 then
- T:go(oTurn..placeF..turn, false, 0, true) -- face wall and check if block
- elseif width == D.width then -- checking opposite wall
- if outward then -- travelling away from start
- T:go(turn..placeF..oTurn, false, 0, true) -- face wall and check if block
- else -- travelling towards start
- T:go(oTurn..placeF..turn, false, 0, true) -- face wall and check if block
- end
- end
- -- move forward
- if length < D.length then
- T:forward(1)
- end
- end
- if width < D.width then
- -- change direction
- if outward then
- T:go(placeF..turn.."F1"..oTurn..place..placeF..turn..turn, false, 0, true)
- else
- T:go(placeF..oTurn.."F1"..turn..place..placeF..oTurn..oTurn, false, 0, true)
- end
- outward = not outward
- else
- if outward then
- T:go(placeF..oTurn.."F"..D.width -1 ..oTurn.."F"..D.length - 1 .."C1R2", false, 0, true)
- else
- T:go(placeF..turn.."F"..D.width -1 ..oTurn..placeF..turn..turn, false, 0, true)
- end
- end
- end
- end
- T:go("R2"..placeF.."R2", false, 0, true) -- place block behind
- for height = 1, D.height do
- if height == 1 then
- lib.layer(D, true, false) -- first layer, so start = true, finish = false
- elseif height == D.height then
- lib.layer(D, false, true) -- final layer, so start = false, finish = true
- else
- lib.layer(D, false, false) -- mid build layer, so start = false, finish = false
- end
- if height < D.height then -- go up or down unless finished build
- T:go(D.vDirection.."1")
- end
- end
- if D.goHome then-- ends at starting point
- if D.vDirection == "U" then
- T:down(D.height - 1)
- else
- T:up(D.height - 1)
- end
- end
- end
- function utils.createWaterSource(level)
- if level == nil then
- level = 0
- end
- if level > 0 then
- T:up(level)
- elseif level < 0 then
- T:down(math.abs(level))
- end
- -- assume on flat surface, but allow for blocks above
- T:go("x0C2F1 x0C2F1 x0C2F1 x0C2R1 F1 x0C2F1 x0C2F1 x0C2R1 F1 x0C2F1 x0C2F1 x0C2R1 F1 x0C2F1 x0C2", false, 0, false)
- T:go("R1F1D1", false, 0, false) --move to corner and drop down
- T:go("C2F1R1 C2F1R1 C2F1R1 C2F1R1", false, 0, false)
- T:go("U1")
- for i = 1, 2 do
- T:placeWater("down")
- T:go("F1R1F1R1", false, 0, false)
- end
- -- refill water buckets
- for i = 1, 2 do
- sleep(0.5)
- T:placeWater("down")
- end
- T:go("R2F1R1F1R1")
- -- end above lower left of pond (starting point)
- return {}
- end
- function utils.drainWaterLava(R) -- 84
- local lib = {}
- function lib.startCorner()
- -- assume starting mid 3 high column
- T:go("D1C1R1C1 U1C1 L1C1 U1C1 R1C1 L1D1 C2C0", false, 0, true)
- -- finished on same mid 3 high column with wall in front and right completed
- end
- function lib.midWall()
- -- assume starting mid 3 high column
- T:go("D1R1C1 U1C1 U1C1 L1D1 C2C0", false, 0, true)
- -- finished on same mid 3 high column with wall on right completed
- end
- function lib.endCorner()
- -- assume starting mid 3 high column
- T:go("D1R1C1 R1C1 U1C1 L1C1 U1C1 R1C1 L2D1 C2C0", false, 0, true)
- -- finished on same mid 3 high column with wall behind and right completed
- end
- function lib.backTurn(offset)
- -- assume starting mid 3 high column with completed wall behind
- T:go("L1F"..offset.."L2C1 R1D1C1 U1C1 U1C1 D1")
- -- end next row along the width, facing the back, mid point
- -- wall ahead completed
- end
- function lib.frontTurn()
- -- assume starting mid 3 high column facing back
- -- next move is to turn toward previous wall and remove
- T:go("L2D1C1 U1C1 U1C1 D1R1 C2C0 F1R2C1 L1")
- -- end facing back ready to remove wall
- end
- function lib.placeRetainingWall(distance)
- -- assume starting above 3 block high area facing front (player)
- --T:down(1)
- for i = 1, distance do
- if i == 1 then -- start wall
- lib.startCorner()
- else
- if i < distance then -- mid wall
- lib.midWall()
- else -- end of the wall
- lib.endCorner()
- end
- end
- if i < distance then
- if not turtle.back() then
- T:go("R2F1R2")
- end
- T:go("C1", false, 0, true)
- end
- end
- return 1
- end
- function lib.placeDam(distance)
- --T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
- local waterPresent = false
- for i = 1, distance do
- if T:isWater("down") then
- waterPresent = true
- end
- T:go("C0C2")
- if i < distance then
- if not turtle.back() then
- T:go("R2F1R2")
- end
- T:go("C1", false, 0, true)
- end
- end
- return waterPresent
- end
- function lib.removeDam(distance)
- -- facing towards back, dig wall up down and ahead
- for i = 1, distance do
- T:go("x0x2")
- if i < distance then
- T:forward(1)
- end
- end
- T:turnRight(2)
- -- end up back to retaining wall, mid point
- end
- if R.data == "" then
- if turtle.detectDown() then -- on solid surface
- turtle.forward()
- end
- end
- if deletesWater then --turtle replaces source so use clearSolid()
- R.silent = true
- R.down = true
- R.up = false
- clearSolid(R)
- else -- mc 1.12.15+ turtle does NOT replace source blocks
- -- place first stone along the length of water and measure length
- R = utils.calculateDimensions(R)
- local depth = 0
- for h = 1, R.height do
- local waterPresent = false -- resets at each level
- local row = 0
- T:go("R2D2", false, 0, true) -- at start, level 2, facing towards the front, move backards
- --lib.startCorner()
- row = row + lib.placeRetainingWall(R.length)
- lib.backTurn(1)
- if lib.placeDam(R.length) then
- waterPresent = true
- end
- row = row + 1
- -- left side wall has been built, 2 rows of walls laid. row = 2
- while row < R.width - 1 do -- eg width=2, row=2, this will not run. width=5, row=2
- lib.frontTurn()
- lib.removeDam(R.length)
- lib.backTurn(2)
- if lib.placeDam(R.length) then
- waterPresent = true
- end
- row = row + 1
- end
- -- lay right wall
- lib.frontTurn()
- lib.removeDam(R.length)
- lib.backTurn(2)
- row = row + lib.placeRetainingWall(R.length)
- lib.frontTurn()
- lib.removeDam(R.length) -- faces to front on finish
- T:go("L1F1R1")
- lib.removeDam(R.length) -- faces to front on finish
- depth = depth + 3
- T:go("L1F"..R.width - 1 .."R1D1")
- if depth == R.height or not waterPresent then -- still replacing water
- T:up(depth - 1) -- when h == R.height will go up
- break -- in case water dries up before loop has completed
- end
- end
- end
- return {}
- end
- function utils.dropSand()
- while not turtle.detectDown() do -- over water. will be infinite loop if out of sand
- if not T:place("sand", -1, "down", false) then
- print("Out of sand. Add more to continue...")
- sleep(2)
- end
- end
- return true --will only get to this point if turtle.detectDown() = true
- end
- function utils.pause(R)
- --[[
- allows 2 turtles to co-operate
- When they face each other and move together
- R.side = "R" or "L"
- ]]
- local rsIn = rs.getAnalogueInput("front")
- local rsOut = 1
- local present = false
- local confirmed = false
- local timer = 0
- local endTimer = 0
- local finished = false
- T:go(R.side.."1")
- rs.setAnalogueOutput("front", 0) -- switch off output
- local blockType = T:getBlockType("forward")
- while blockType:find("turtle") == nil do
- menu.colourWrite("Waiting for other turtle "..endTimer, colors.orange, nil, nil, false, true)
- blockType = T:getBlockType("forward")
- sleep(0.1)
- timer = timer + 0.1
- if timer >= 1 then
- timer = 0
- endTimer = endTimer + 1
- end
- end
- timer = 0
- endTimer = 0
- while not finished do
- if endTimer == 0 then
- if present then
- if confirmed then
- menu.colourWrite("Turtle confirmed: input = "..rsIn.." output = "..rsOut, colors.orange, nil, nil, false, true)
- else
- menu.colourWrite("Other turtle ok: input = "..rsIn.." output = "..rsOut, colors.orange, nil, nil, false, true)
- end
- else
- menu.colourWrite("Waiting: input = "..rsIn.." output = "..rsOut, colors.orange, nil, nil, false, true)
- end
- end
- sleep(0.1)
- timer = timer + 1
- if endTimer > 0 then
- endTimer = endTimer + 1
- end
- if endTimer >= 10 then -- allows time for other computer to get ready
- finished = true
- end
- rs.setAnalogueOutput("front", 1) -- output 1 as a signal initially
- if present then
- rs.setAnalogueOutput("front", rsOut) -- output 1 as a signal initially
- end
- rsIn = rs.getAnalogueInput("front")
- if rsIn == 1 then
- present = true
- if not confirmed then
- rsOut = 7
- end
- elseif rsIn == 7 then
- present = true
- confirmed = true
- rsOut = 15
- elseif rsIn == 15 or confirmed then
- menu.colourWrite("endTimer active = "..endTimer, colors.orange, nil, nil, false, true)
- endTimer = endTimer + 1 -- start endTimer
- end
- end
- T:go(R.side.."3")
- return rsIn -- 15
- end
- function utils.startWaterFunction(inWater, onWater, maxDescent, goIn)
- --[[
- Use with utils.getWaterStatus
- could be inWater and not onWater if on single layer of water with floor below
- ]]
- maxDescent = maxDescent or 1 -- prevents continuous down due to lack of water
- if goIn == nil then -- turtle should submerge
- goIn = true
- end
- local descent = 0 -- counter for going down
- if inWater then -- job done
- return inWater, onWater
- end
- if onWater and goIn then --inWater already returned so must be false
- if turtle.down() then
- if T:getBlockType("forward"):find("water") ~= nil or T:getBlockType("forward"):find("bubble") ~= nil then
- inWater = true
- return inWater, onWater
- end
- end
- end
- if not onWater then
- T:forward(1)
- end
- -- should now be above water, but may be further down so onWater still false
- while T:getBlockType("down"):find("water") == nil and T:getBlockType("down"):find("bubble") == nil do-- go down until water below
- if turtle.down() then
- descent = descent + 1
- if descent >= maxDescent then -- limit descent in case no water present
- onWater = false
- return inWater, onWater -- false,false
- end
- else
- onWater = false
- return inWater, onWater -- false,false
- end
- end
- -- now above water
- if goIn then
- turtle.down() -- now inside water block
- inWater = true
- end
- return inWater, onWater
- end
- function utils.fillBucket(direction)
- if T:getWater(direction) then
- sleep(0.3)
- return true
- else
- return false
- end
- end
- function utils.getEmptyBucketCount()
- local lastSlot, leastModifier, total, slotData = T:getItemSlot("minecraft:bucket", -1)
- return total
- end
- function utils.getRoofStats(R)
- local isWidthOdd = R.width % 2 == 1 -- is the width odd or even?
- local isLengthOdd = R.length % 2 == 1 -- is the length odd or even?
- if isWidthOdd then
- R.height = math.floor(R.width / 2) -- eg 7 x 5 roof, layers = 5 / 2 = 2
- else
- R.height = R.width / 2 -- eg 17 x 8 roof, layers = 8 / 2 = 4
- end
- local width = 2 -- assume even width with 2 block roof ridge
- local length = R.length - R.height - 1 -- assume even width with 2 block roof ridge
- if isWidthOdd then
- width = 3 -- adjust to allow for single width roof ridge
- end
- if isLengthOdd then
- length = R.length - R.height -- adjust as 1 layer less
- end
- return R, isWidthOdd, isLengthOdd, width, length
- end
- function utils.getWater()
- if deletesWater then
- T:getWater("down") -- take water from source
- sleep(0.2)
- T:getWater("down") -- take water from source
- else
- if not turtle.detectDown() then
- T:go("C2", false, 0, false)
- end
- T:getWater("forward") -- take water from source
- sleep(0.2)
- T:getWater("forward") -- take water from source
- end
- end
- function utils.getWaterBucketCount()
- -- lastSlot, leastModifier, total, slotData = T:getItemSlot(item, useDamage)
- local lastSlot, leastModifier, total, slotData = T:getItemSlot("minecraft:water_bucket", -1)
- return total
- end
- function utils.getWaterStatus()
- --[[ Usage:
- local inWater, onWater = utils.getWaterStatus() -- returns turtle position near water
- utils.startWaterFunction(onWater, inWater, 2, true) -- move INTO water max 2 blocks down
- utils.startWaterFunction(onWater, inWater, 5, false) -- move ABOVE water max 5 blocks down
- ]]
- local onWater = false
- local inWater = false
- for i = 1, 4 do
- if T:getBlockType("forward"):find("water") ~= nil or T:getBlockType("forward"):find("bubble") ~= nil then
- inWater = true
- end
- T:turnRight(1)
- end
- if T:getBlockType("down"):find("water") ~= nil or T:getBlockType("down"):find("bubble") ~= nil then
- onWater = true
- end
- return inWater, onWater
- end
- function utils.goBack(blocks)
- blocks = blocks or 1
- local success = true
- for i = 1, blocks do
- if not turtle.back() then
- success = false
- T:go("R2F1R2")
- end
- end
- return success
- end
- function utils.getPrettyPrint(promptColour, menuPromptColour)
- promptColour = promptColour or colors.yellow
- menuPromptColour = menuPromptColour or colors.white
- local pp = {}
- pp.prompt = promptColour
- pp.itemColours = {}
- pp.menuPrompt = menuPromptColour
- pp.allowModifier = true -- can the menu return 'q' or 'h' / 'i'
- return pp
- end
- function utils.move(R, blocks, reverse)
- if reverse == nil then
- reverse = false
- end
- if reverse then
- if R.subChoice == 2 then -- reverse direction
- T:up(blocks)
- else
- T:down(blocks)
- end
- return blocks * -1
- else
- if R.subChoice == 1 then
- T:up(blocks)
- else
- T:down(blocks)
- end
- return blocks
- end
- end
- function utils.setStorageOptions()
- local storage = ""
- local storageBackup = ""
- if T:getItemSlot("barrel") > 0 then
- storage = "barrel"
- storageBackup = "barrel"
- end
- if T:getItemSlot("chest") > 0 then
- if storage == "" then
- storage = "chest"
- end
- storageBackup = "chest"
- end
- return storage, storageBackup
- end
- local pp = utils.getPrettyPrint()
- local function buildWall(R)
- -- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
- local lib = {}
- function lib.singleLayer(R)
- for l = 1, R.length do
- if l == R.length and R.data == "house" then
- T:turnRight(1)
- end
- utils.goBack(1)
- T:go("C1", false, 0, false, R.useBlockType)
- end
- end
- function lib.doubleLayer(R)
- for l = 1, R.length do
- T:go("C2", false, 0, false, R.useBlockType)
- if l == R.length and R.data == "house" then
- T:turnRight(1)
- end
- utils.goBack(1)
- T:go("C1", false, 0, false, R.useBlockType)
- end
- end
- function lib.tripleLayer(R)
- for l = 1, R.length do
- T:go("C2C0", false, 0, false, R.useBlockType)
- if l == R.length and R.data == "house" then
- T:turnRight(1)
- end
- utils.goBack(1)
- T:go("C1", false, 0, false, R.useBlockType)
- end
- end
- -- R.width preset to 1
- local remaining = R.height
- if R.subChoice == 1 then
- T:forward(1) -- face forward, move over first block
- end
- if R.height > 1 then
- T:up(1) -- go up 1 block
- end
- if R.data ~= "house" then
- T:turnRight(2) -- rotate 180
- end
- if R.height == 1 then -- single block: place in front
- lib.singleLayer(R)
- elseif R.height == 2 then -- 2 blocks, go backwards, place below and ahead
- lib.doubleLayer(R)
- else
- while remaining >= 3 do
- lib.tripleLayer(R)
- remaining = remaining - 3
- if remaining == 1 then
- T:go("U2F1R2")
- elseif remaining > 1 then
- T:go("U3F1R2")
- end
- end
- if remaining == 1 then
- lib.singleLayer(R)
- elseif remaining == 2 then
- lib.doubleLayer(R)
- end
- end
- if not R.silent then
- while turtle.down() do end
- end
- return {}
- end
- local function buildStructure(R)
- local lib = {}
- function lib.goDown(R)
- --T:go("L1F1 R1F1 L1") -- now on ground floor
- if R.height > 1 then
- T:down(1)
- end
- end
- local buildHeight = R.height
- local height = R.height
- local width = R.width
- local length = R.length
- if R.subChoice == 1 then
- T:forward(1) -- face forward, move over first block
- end
- if R.height > 3 then
- R.height = 3
- end
- T:turnRight(2)
- R.data = "house"
- R.silent = true -- prevent return to ground after buildWall(R)
- R.subChoice = 2 -- do not move forward when building walls
- while height > 0 do
- buildWall(R)
- lib.goDown(R)
- R.length = width - 1
- buildWall(R)
- lib.goDown(R)
- R.length = length - 1
- buildWall(R)
- lib.goDown(R)
- R.length = width - 2
- buildWall(R)
- height = height - R.height -- 1, 2 or 3
- if height > 0 then
- T:go("U2 R1F1 L1F1")
- R.height = height
- if height > 3 then
- R.height = 3
- end
- R.length = length
- end
- end
- T:go("U2F2")
- while turtle.down() do end
- T:go("R1F1R1")
- return {}
- end
- local function buildGableRoof(R)
- --[[
- stairs placement:
- _| up
- T L forward
- _
- | down
- ]]
- local lib = {}
- function lib.placeRoof(R, outward)
- for i = 1, R.length + 2 do
- if R.useBlockType:find("stairs") ~= nil then
- T:place("stairs", 0, "up")
- else
- T:go("C0", false, 0, false, R.useBlockType)
- end
- if i < R.length + 2 then
- if outward then
- T:go("L1F1R1")
- else
- T:go("R1F1L1")
- end
- end
- end
- end
- function lib.placeGable(R, outward)
- local width = R.width
- for h = 1, R.height do
- for w = 1, width do
- T:go("C1")
- if w < width then
- if outward then
- T:go("L1F1R1")
- else
- T:go("R1F1L1")
- end
- end
- end
- if h < R.height then
- if outward then
- T:go("R1F1L1U1")
- else
- T:go("L1F1R1U1")
- end
- end
- width = width - 2
- outward = not outward
- end
- return outward
- end
- local outward = true
- -- go to centre of end wall if odd no, or half width if even
- R.height = math.floor(R.width / 2)
- local isOdd = R.width % 2 == 1
- utils.goBack(1)
- T:go("R1F"..R.height - 1 .."U"..R.height - 1) -- top of roof, under top layer
- for h = 1, R.height + 1 do -- place tiles on left side of roof
- lib.placeRoof(R, outward)
- if h < R.height + 1 then
- utils.goBack(1)
- T:down(1)
- outward = not outward
- end
- end
- if isOdd then
- T:go("F"..R.height + 2 .."R2U"..R.height)
- else
- T:go("F"..R.height + 1 .."R2U"..R.height)
- end
- for h = 1, R.height + 1 do -- place tiles on right side of roof
- lib.placeRoof(R, outward)
- if h < R.height + 1 then
- utils.goBack(1)
- T:down(1)
- outward = not outward
- end
- end
- -- gable ends
- if outward then
- T:go("F1R1U1")
- else
- T:go("F1L1U1")
- end
- outward = lib.placeGable(R, outward)
- T:go("F2R2 C1R2F"..R.length - 1 .."D"..R.height - 1)
- if outward then
- T:go("R1F"..R.height - 1 .."R1")
- else
- T:go("L1F"..R.height - 1 .."L1")
- end
- outward = not outward
- outward = lib.placeGable(R, outward)
- if isOdd then
- if outward then
- T:go("L1F1R1U2F1")
- else
- T:go("R1F1L1U2F1")
- end
- for i = 1, R.length do
- T:go("C2F1", false, 0, false)
- end
- for i = 1, R.length + 2 do
- utils.goBack(1)
- T:place("slab", 0, "forward")
- end
- end
- while turtle.down() do end
- return {}
- end
- local function buildPitchedRoof(R)
- --[[
- stairs placement:
- _| up
- T L forward
- _
- | down
- ]]
- local lib = {}
- function lib.placeRoofSection(length)
- -- starts facing centre of building
- for i = 1, length do
- if i < length then
- if R.useBlockType:find("stairs") ~= nil then
- T:place("stairs", 0, "up")
- else
- T:go("C0", false, 0, false, R.useBlockType)
- end
- T:go("L1F1R1")
- end
- end
- -- ends facing centre of building
- end
- function lib.placeRoof(R, width, length)
- lib.placeRoofSection(length)
- T:go("R1")
- lib.placeRoofSection(width)
- T:go("R1")
- lib.placeRoofSection(length)
- T:go("R1")
- lib.placeRoofSection(width)
- end
- function lib.placeSlabs(length)
- -- add slabs at top
- T:go("U2F1L1")
- if length > 1 then
- T:forward(length - 3)
- for i = 1, length - 3 do
- T:place("slab", 0, "forward")
- utils.goBack(1)
- end
- T:place("slab", 0, "forward")
- else
- T:place("slab", 0, "forward")
- end
- T:go("D2R1")
- utils.goBack(1)
- end
- --[[
- Turtle MUST be placed on left corner of shortest dimension
- **** or T******
- **** *******
- **** *******
- ****
- T***
- shortest dimension is R.width
- if width is odd, ignore top layer as is only 1 block wide
- ]]
- local isWidthOdd, isLengthOdd, width, length = false, false, 0, 0
- R, isWidthOdd, isLengthOdd, width, length = utils.getRoofStats(R)
- T:go("F"..R.height - 1 .."R1F"..R.height - 1 .."U"..R.height - 1) -- top of roof, under top layer
- if isWidthOdd then
- lib.placeSlabs(length)
- end
- for h = 1, R.height + 1 do -- place tiles on left side of roof
- lib.placeRoof(R, width, length)
- length = length + 2 -- increase dimensions
- width = width + 2
- if h < R.height + 1 then
- utils.goBack(1)
- T:go("D1R1")
- utils.goBack(1)
- end
- end
- while turtle.down() do end
- return {}
- end
- local function clearAndReplantTrees() -- 25
- --[[ clear all trees in a rectangle area defined by walls, fences or non-dirt blocks
- replant with same type of sapling. If original tree 2 blocks wide, replant 4 if possible. ]]
- local lib = {}
- function lib.getSaplingFromLogType(log)
- --[[ get type of sapling to plant from log type ]]
- if log:find("oak") ~= nil then
- return "minecraft:oak_sapling"
- elseif log:find("spruce") ~= nil then
- return "minecraft:spruce_sapling"
- elseif log:find("birch") ~= nil then
- return "minecraft:birch_sapling"
- elseif log:find("jungle") ~= nil then
- return "minecraft:jungle_sapling"
- elseif log:find("acacia") ~= nil then
- return "minecraft:acacia_sapling"
- elseif log:find("dark_oak") ~= nil then
- return "minecraft:dark_oak_sapling"
- end
- return "sapling"
- end
- function lib.plantSapling(sapling, double)
- --[[ plant sapling(s) ]]
- if sapling == "" or sapling == nil then sapling = "sapling" end
- T:up(1)
- lib.suck()
- if double then -- check if enough saplings
- --slotData.lastSlot, slotData.leastModifier, total, slotData = T:getItemSlot(sapling, -1)
- local a, b, total, _ = T:getItemSlot(sapling, -1)
- if total >= 4 then
- for i = 1, 4 do
- T:place(sapling, -1, "down")
- T:go("F1R1")
- end
- T:forward(1) -- above pre-planted sapling
- else
- if not T:place(sapling, -1, "down") then
- T:place("sapling", -1, "down")
- end
- end
- else
- if not T:place(sapling, -1, "down") then
- T:place("sapling", -1, "down")
- end
- end
- turtle.select(1)
- end
- function lib.suck()
- --[[ Collect saplings, sticks and apples ]]
- turtle.select(1)
- turtle.suck()
- turtle.suckUp()
- turtle.suckDown()
- end
- function lib.turn(direction)
- --[[ change direction and return new value for direction ]]
- if direction == "r" then
- T:turnRight(1)
- direction = "l"
- else
- T:turnLeft(1)
- direction = "r"
- end
- return direction -- will only change direction variable if return value is used
- end
- function lib.emptyInventory(blockTypeD)
- --[[ Empty all except 32 of each sapling and 1 chest ]]
- if blockTypeD == nil then
- blockTypeD = T:getBlockType("down")
- end
- if blockTypeD:find("chest") ~= nil or blockTypeD:find("barrel") ~= nil then
- -- empty logs, apples, sticks and all but 1 stack of each sapling type
- T:emptyInventorySelection("down", {"chest", "oak_sapling", "birch_sapling", "spruce_sapling", "acacia_sapling", "jungle_sapling","dark_oak_sapling"},{1, 32, 32, 32, 32, 32, 32})
- return true
- else
- return false
- end
- end
- function lib.moveDown(blockTypeD)
- --[[ move down until hit ground. Break leaves and continue ]]
- if blockTypeD == nil then
- blockTypeD = T:getBlockType("down")
- end
- while blockTypeD == "" or blockTypeD:find("leaves") ~= nil do -- move down, breaking leavse
- T:down(1)
- lib.suck()
- blockTypeD = T:getBlockType("down")
- end
- return blockTypeD
- end
- function lib.moveForward()
- --[[ Move forward 1 block only, go down to ground while air or leaves below ]]
- local blockTypeF = T:getBlockType("forward")
- local blockTypeD = T:getBlockType("down")
- if blockTypeF == "" or blockTypeF:find("leaves") ~= nil then -- air or leaves ahead
- T:forward(1) -- move forward, breaking leaves
- T:dig("up") -- remove leaves / low branches above to allow space for player
- lib.suck()
- blockTypeD = lib.moveDown()
- if not lib.emptyInventory(blockTypeD) then -- check if above a corner chest / barrel
- if lib.isBorder(blockTypeD) then -- not above chest so check if above border
- return false, blockTypeD -- above a border block so stop
- end
- end
- blockTypeF = T:getBlockType("forward")
- return true, blockTypeF -- moved ok, could be air or block in front
- end
- return false, blockTypeF -- did not move, obstacle in front NOT leaves or air
- end
- function lib.moveUp(blockTypeF)
- --[[ Move up until air in front (dig leaves / harvest tree) ]]
- if blockTypeF == nil then
- blockTypeF = T:getBlockType("forward")
- end
- while blockTypeF:find("dirt") ~= nil or
- blockTypeF:find("grass_block") ~= nil or
- T:isVegetation(blockTypeF) do -- go up while dirt, grass-block or any vegetation in front
- T:up(1)
- blockTypeF = T:getBlockType("forward")
- if blockTypeF:find("log") ~= nil then
- lib.harvestTree(blockTypeF)
- return T:getBlockType("forward")
- elseif blockTypeF:find("leaves") ~= nil then
- T:dig("forward")
- return ""
- end
- end
- return blockTypeF -- should be "" (air) or any border block
- end
- function lib.harvestTree(blockTypeF)
- --[[ Fell tree, returns true if double size ]]
- -- clsTurtle.harvestTree(extend, craftChest, direction)
- local saplingType = lib.getSaplingFromLogType(blockTypeF)
- local double = T:harvestTree(false, false, "forward") -- assume single tree, will auto-discover
- lib.plantSapling(saplingType, double)
- end
- function lib.safeMove()
- --[[ move forward until border reached. loop breaks at that point ]]
- local blockTypeF = ""
- local success = true
- while success do
- success, blockTypeF = lib.moveForward() -- move forward 1 block, return block type ahead
- if not success then -- did not move forwards, block in the way: either log, dirt/grass, border block or vegetation
- if blockTypeF:find("log") then -- tree found
- lib.harvestTree(blockTypeF)
- success = true -- block (log) removed, try again
- else
- success = not lib.isBorder(blockTypeF) -- Is at border?: if is at border success = false so loop stops
- if success then -- Not at border. Dirt/grass vegetation in front
- blockTypeF = lib.moveUp(blockTypeF) -- move up until leaves/log/air
- success = not lib.isBorder(blockTypeF) -- Is at border?: if is at border success = false so loop stops
- if success then -- keep moving forward
- if blockTypeF:find("log") then -- tree found
- lib.harvestTree(blockTypeF)
- end
- -- else blockTypeF is air/leaves border has been checked
- end
- end
- end
- end -- else success = true, 1 block moved so continue
- end
- end
- function lib.isBorder(blockType)
- --[[ Is the block log, dirt, grass_block, vegetation: non-border, or other:border]]
- if blockType == nil then -- not passed as parameter
- blockType = T:getBlockType("forward")
- end
- if blockType == "" then -- air ahead: not border
- return false, ""
- else -- could be border or other
- if blockType:find("dirt") ~= nil or blockType:find("grass_block") ~= nil or blockType:find("log") ~= nil then -- either dirt, grass block or log
- return false, blockType -- dirt, grass, log: not border
- end
- if T:isVegetation(blockType) then -- vegetation found: not border
- return false, blockType
- end
- end
- return true, blockType -- dirt, grass_block, log and vegetation eliminated:must be border
- end
- function lib.inPosition()
- --[[ check if in lower left corner ]]
- local inPosition = true -- assume correct
- if not turtle.detectDown() then -- hanging in mid-air
- return false
- end
- T:turnLeft(1)
- if lib.isBorder() then
- -- so far so good
- T:turnLeft(1)
- if not lib.isBorder() then -- not in correct place
- inPosition = false
- end
- T:turnRight(2) -- return to original position
- else
- inPosition = false
- T:turnRight(1) -- return to original position
- end
- return inPosition
- end
- function lib.findBorder()
- --[[ assume started after reset. if log above harvest tree else return to ground. Find starting corner]]
- local blockType = T:getBlockType("up") -- dig any logs above, return to ground
- local log = "sapling"
- if blockType:find("log") ~= nil then -- originally felling a tree so complete it
- log = lib.getSaplingFromLogType(blockType)
- local double = T:harvestTree(false, false, "up") -- assume single tree, will auto-discover
- lib.plantSapling(log, double)
- else -- no log above so go downm
- blockType = lib.moveDown() -- return to ground (or vegetation)
- end
- lib.safeMove() -- move forward until border reached
- T:turnRight(1)
- lib.safeMove() -- move forward until second border reached
- T:turnRight(1) -- should now be in correct position
- lib.emptyInventory() -- empty inventory if above a chest
- end
- local direction = "r"
- local blockTypeF = ""
- local success = false
- if not lib.inPosition() then
- lib.findBorder()
- end
- local secondBorderFound = false
- while not secondBorderFound do
- lib.safeMove() -- moves forward until reaches border forward or below
- lib.turn(direction) -- turn r or l. direction is not changed
- success, blockTypeF = lib.isBorder() -- no blockType passed as parameter so will return current block in new forward direction
- if success then
- secondBorderFound = true -- game over
- elseif blockTypeF:find("log") ~= nil then -- tree in front
- lib.harvestTree(blockTypeF)
- elseif blockTypeF == "" or blockTypeF:find("leaves") ~= nil then -- air or leaves in front
- T:forward(1) -- move forward 1 block
- lib.moveDown() -- go down if required
- elseif blockTypeF:find("dirt") ~= nil or
- blockTypeF:find("grass_block") ~= nil or
- T:isVegetation(blockTypeF) then -- dirt, grass_block or vegetation in front
- blockTypeF = lib.moveUp(blockTypeF) -- move up until air or border ahead.
- if lib.isBorder(blockTypeF) then -- border ahead
- secondBorderFound = true
- else -- air ahead
- T:forward(1) -- move forward 1 block
- end
- end
- direction = lib.turn(direction) -- turn r or l. direction is changed to opposite
- end
- lib.moveDown() -- return to ground level
- lib.emptyInventory()
- return {}
- end
- local function clearArea(R) -- 71, called from 22
- local evenWidth = false
- local evenHeight = false
- local loopWidth
- -- go(path, useTorch, torchInterval, leaveExisting)
- if R.width % 2 == 0 then
- evenWidth = true
- loopWidth = R.width / 2
- else
- loopWidth = math.ceil(R.width / 2)
- end
- if R.length % 2 == 0 then
- evenHeight = true
- end
- turtle.select(1)
- -- clear an area between 2 x 4 and 32 x 32
- -- if R.width is even no, then complete the up/down run
- -- if R.width odd no then finish at top of up run and reverse
- -- should be on flat ground, check voids below, harvest trees
- for x = 1, loopWidth do
- -- Clear first column (up)
- for y = 1, R.length do
- if R.useBlockType == "dirt" then
- if not turtle.detectDown() then
- T:place("minecraft:dirt", -1, "down", true)
- else --if not water, dirt, grass , stone then replace with dirt
- blockType, blockModifier = T:getBlockType("down")
- if blockType ~= "" then
- if blockType ~= "minecraft:dirt" and blockType ~= "minecraft:grass_block" then
- turtle.digDown()
- T:place("minecraft:dirt", -1, "down", true)
- end
- end
- end
- end
- if y < R.length then
- T:go("F1+1", false,0,false)
- end
- end
- -- clear second column (down)
- if x < loopWidth or (x == loopWidth and evenWidth) then -- go down if on R.width 2,4,6,8 etc
- T:go("R1F1+1R1", false,0,false)
- for y = 1, R.length do
- if R.useBlockType == "dirt" then
- if not turtle.detectDown() then
- T:place("minecraft:dirt", -1, "down", true)
- else
- blockType, blockModifier = T:getBlockType("down")
- if blockType ~= "" then
- if blockType ~= "minecraft:dirt" and blockType ~= "minecraft:grass_block" then
- turtle.digDown()
- T:place("minecraft:dirt", -1, "down", true)
- end
- end
- end
- end
- if y < R.length then
- T:go("F1+1", false, 0, false)
- end
- end
- if x < loopWidth then
- T:go("L1F1+1L1", false,0,false)
- else
- T:turnRight(1)
- T:forward(R.width - 1)
- T:turnRight(1)
- end
- else -- equals R.width but is 1,3,5,7 etc
- T:turnLeft(2) --turn round 180
- T:forward(R.length - 1)
- T:turnRight(1)
- T:forward(R.width - 1)
- T:turnRight(1)
- end
- end
- return {}
- end
- local function clearRectangle(R) -- 72
- --local function clearRectangle(width, length, up, down)
- -- height = 0: one level, 1 = +up, 2 = +down, 3 = +up/down
- local lib = {}
- function lib.UpDown(length)
- for l = 1, length do
- T:go("x0x2F1x0x2")
- end
- end
- function lib.Up(length)
- for l = 1, length do
- T:go("x0F1x0")
- end
- end
- function lib.Down(length)
- for l = 1, length do
- T:go("x2F1x2")
- end
- end
- function lib.Forward(length)
- T:forward(length)
- end
- -- could be 1 wide x xx R.length (trench) R.up and return
- -- could be 2+ x 2+
- -- even no of runs return after last run
- -- odd no of runs forward, back, forward, reverse and return
- turtle.select(1)
- if R.width == 1 then -- single block trench ahead only
- if R.up and R.down then -- single block wide trench dig R.up and R.down = 3 blocks deep
- lib.UpDown(R.length - 1)
- elseif R.up then -- single block wide trench dig R.up = 2 blocks deep
- lib.Up(R.length - 1)
- elseif R.down then -- single block wide trench dig R.down = 2 blocks deep
- lib.Down(R.length - 1)
- else -- single block wide = 1 block deep
- lib.Forward(R.length - 1)
- end
- T:turnRight(2) -- turn at the top of the run
- T:forward(R.length - 1) -- return to start
- T:turnRight(2) -- turn round to original position
- else -- R.width 2 or more blocks
- local iterations = 0 -- R.width = 2, 4, 6, 8 etc
- if R.width % 2 == 1 then -- R.width = 3, 5, 7, 9 eg R.width 7
- iterations = (R.width - 1) / 2 -- iterations 1, 2, 3, 4 for widths 3, 5, 7, 9
- else
- iterations = R.width / 2 -- iterations 1, 2, 3, 4 for widths 2, 4, 6, 8
- end
- for i = 1, iterations do -- eg 3 blocks wide, iterations = 1
- if R.up and R.down then -- dig R.up and R.down
- lib.UpDown(R.length - 1)
- T:go("x0x2R1F1x0x2R1x0x2") -- turn round
- lib.UpDown(R.length - 1)
- elseif R.up then -- dig R.up
- lib.Up(R.length - 1)
- T:go("x0R1F1x0R1x0")
- lib.Up(R.length - 1)
- elseif R.down then -- dig R.down
- lib.Down(R.length - 1)
- T:go("x2R1F1x2R1x2")
- lib.Down(R.length - 1)
- else -- no digging R.up or R.down
- lib.Forward(R.length - 1)
- T:go("R1F1R1")
- lib.Forward(R.length - 1)
- end
- -- if 1 less than end, reposition for next run
- if i < iterations then
- T:go("L1F1L1", false, 0, false)
- end
- end
- if R.width % 2 == 1 then -- additional run and return to base needed
- T:go("L1F1L1", false, 0, false)
- if R.up and R.down then
- lib.UpDown(R.length - 1)
- elseif R.up then
- lib.Up(R.length - 1)
- elseif R.down then
- lib.Down(R.length - 1)
- else
- lib.Forward(R.length - 1)
- end
- T:turnRight(2)
- T:forward(R.length - 1)
- end
- T:go("R1F"..R.width - 1 .."R1", false, 0, false)
- end
- return {}
- end
- local function clearPerimeter(R) -- 74
- local lib = {}
- function lib.UpDown(length)
- for l = 1, length do
- T:go("x0x2F1x0x2")
- end
- end
- function lib.Up(length)
- for l = 1, length do
- T:go("x0F1x0")
- end
- end
- function lib.Down(length)
- for l = 1, length do
- T:go("x2F1x2")
- end
- end
- function lib.Forward(length)
- T:forward(length)
- end
- if R.up and R.down then
- for i = 1, 2 do
- lib.UpDown(R.length - 1)
- T:turnRight(1)
- lib.UpDown(R.width - 1)
- T:turnRight(1)
- end
- elseif R.up then
- for i = 1, 2 do
- lib.Up(R.length - 1)
- T:turnRight(1)
- lib.Up(R.width - 1)
- T:turnRight(1)
- end
- elseif R.down then
- for i = 1, 2 do
- lib.Down(R.length - 1)
- T:turnRight(1)
- lib.Down(R.width - 1)
- T:turnRight(1)
- end
- else
- for i = 1, 2 do
- lib.Forward(R.length - 1)
- T:turnRight(1)
- lib.Forward(R.width - 1)
- T:turnRight(1)
- end
- end
- return {}
- end
- local function clearBuilding(R) -- 75, 43
- --[[
- Clear the outer shell of a building, leaving inside untouched. Optional floor/ceiling removal
- clearBuilding(R)
- R.subChoice = 1-'up' or 2-'down'
- R.data.ceiling = true / false
- R.data.floor = true / false
- ]]
- local height = 1
- local remaining = R.height -- eg 5
- local start = true
- local finish = false
- local lib = {}
- function lib.floorOrCeiling(R)
- T:go("F1R1 F1L1")
- R.length = R.length - 2
- R.width = R.width - 2
- clearRectangle(R)
- R.length = R.length + 2
- R.width = R.width + 2
- T:go("L1F1R1")
- utils.goBack(1)
- end
- function lib.singleLayer(R)
- R.up = false
- R.down = false
- if start then
- if R.data.ceiling or R.data.floor then -- floor / ceiling to go. only one layer, so clearRectangle
- lib.floorOrCeiling(R)
- end
- start = false
- end
- if finish then
- if R.data.ceiling or R.data.floor then -- floor / ceiling to go. only one layer, so clearRectangle
- lib.floorOrCeiling(R)
- end
- finish = false
- end
- clearPerimeter(R) -- no floor / ceiling
- end
- function lib.doubleLayer(R)
- R.up = false
- R.down = false
- if start then
- if R.data.floor and R.subChoice == 1 then -- going up and floor needs removing
- lib.floorOrCeiling(R) -- remove floor/ceiling
- elseif R.data.ceiling and R.subChoice == 2 then -- going down and ceiling needs removing
- lib.floorOrCeiling(R) -- remove floor/ceiling
- end
- start = false
- end
- if finish then
- if R.data.ceiling and R.subChoice == 1 then -- going down and ceiling needs removing
- lib.floorOrCeiling(R) -- remove floor/ceiling
- elseif R.data.floor and R.subChoice == 2 then -- going down and floor needs removing
- lib.floorOrCeiling(R) -- remove floor/ceiling
- end
- finish = false
- end
- if R.subChoice == 1 then
- R.up = true
- else
- R.down = true
- end
- clearPerimeter(R)
- end
- function lib.tripleLayer(R)
- -- turtle in centre layer
- R.up = false
- R.down = false
- if start then
- if R.data.floor and R.subChoice == 1 then -- going up and floor needs removing
- height = height + utils.move(R, 1, true) -- move down 1 block
- lib.floorOrCeiling(R) -- remove floor/ceiling
- height = height + utils.move(R, 1) -- move up 1 block
- elseif R.data.ceiling and R.subChoice == 2 then -- going down and ceiling needs removing
- height = height + utils.move(R, 1, true) -- move up 1 block
- lib.floorOrCeiling(R) -- remove floor/ceiling
- height = height + utils.move(R, 1) -- move down 1 block
- end
- start = false
- end
- if finish then
- if R.data.ceiling and R.subChoice == 1 then -- going up and ceiling needs removing
- height = height + utils.move(R, 1, true) -- move down 1 block
- lib.floorOrCeiling(R) -- remove floor/ceiling
- height = height + utils.move(R, 1) -- move up 1 block
- elseif R.data.floor and R.subChoice == 2 then -- going down and floor needs removing
- height = height + utils.move(R, 1, true) -- move up 1 block
- lib.floorOrCeiling(R) -- remove floor/ceiling
- height = height + utils.move(R, 1) -- move up 1 block
- end
- finish = false
- end
- R.up = true
- R.down = true
- clearPerimeter(R)
- end
- --[[
- R.data = "up" or "down" as direction of travel
- R.up = true to remove ceiling
- R.down = true to remove floor
- ]]
- R.silent = true
- if R.height < 3 then --1-3 layers only
- if R.height == 1 then --one layer only
- lib.singleLayer(R)
- elseif R.height == 2 then --2 layers only current + dig up/down
- lib.doubleLayer(R)
- end
- else -- 3 or more levels
- height = height + utils.move(R, 1) -- move up/down 1 block for first layer
- while remaining >= 3 do -- min 3 levels
- lib.tripleLayer(R)
- remaining = remaining - 3
- if remaining == 0 then -- all finished
- break
- elseif remaining == 1 then
- height = height + utils.move(R, 2) -- move up/down 2 blocks
- lib.singleLayer(R)
- elseif remaining == 2 then
- height = height + utils.move(R, 2) -- move up/down 2 blocks
- lib.doubleLayer(R)
- else
- height = height + utils.move(R, 3) -- move up/down 3 blocks
- if remaining == 3 then
- finish = true
- else
- --height = height + 3
- end
- end
- end
- end
- if height > 1 then
- utils.move(R, height - 1, true) -- reverse direction
- end
- return {}
- end
- local function clearMineshaft(R, equippedRight, equippedLeft, inInventory) -- 19
- local lib = {}
- function lib.checkCobweb(directions, inInventory)
- assert(type(directions) == "table", "directions must be a table eg {'up','down'}")
- for _, direction in ipairs(directions) do
- local blockType = T:getBlockType(direction)
- if inInventory == "minecraft:diamond_sword" then -- using a sword
- local side = "left"
- if blockType:find("cobweb") ~= nil then
- --clsTurtle.equip(self, side, useItem, useDamage)
- if equippedRight == "minecraft:diamond_pickaxe" then
- side = "right"
- end
- T:equip(side, "minecraft:diamond_sword")
- T:dig(direction)
- T:equip(side, "minecraft:diamond_pickaxe")
- elseif blockType ~= "" then
- T:dig(direction)
- end
- else
- T:dig(direction)
- end
- end
- end
- -- check position by rotating until facing away from wall
- length = 0
- torch = 0
- turns = 0
- while not turtle.detect() do
- T:turnRight(1)
- turns = turns + 1
- if turns > 4 then
- return {"I am not facing a wall. Unable to continue"}
- end
- end
- T:turnRight(2)
- -- move forward until obstructed, digging up/down. place torches
- while not turtle.detect() do
- lib.checkCobweb({"up","down"}, inInventory) -- dig cobweb or any other block up/down
- length = length + 1
- torch = torch + 1
- if torch == R.torchInterval then
- torch = 0
- T:place("minecraft:torch", -1, "down", false) ---(self, blockType, damageNo, direction, leaveExisting, signText)
- end
- lib.checkCobweb({"forward"}, inInventory) -- dig cobweb or any other block in front
- T:forward(1)
- end
- -- turn right, forward, right, return to start with up/down dig
- T:go("R1")
- lib.checkCobweb({"up","down"}, inInventory) -- dig cobweb or any other block up/down
- T:go("F1R1")
- for i = 1, length, 1 do
- lib.checkCobweb({"up", "down", "forward"}, inInventory) -- dig cobweb or any other block up/down/forward
- T:forward(1)
- end
- -- move to other wall and repeat.
- T:go("R1")
- lib.checkCobweb({"up","down"}, inInventory) -- dig cobweb or any other block up/down
- T:go("F1")
- lib.checkCobweb({"up","down"}, inInventory) -- dig cobweb or any other block up/down
- T:go("F1R1")
- lib.checkCobweb({"up","down"}, inInventory) -- dig cobweb or any other block up/down
- for i = 1, length, 1 do
- lib.checkCobweb({"up", "down", "forward"}, inInventory) -- dig cobweb or any other block up/down/forward
- T:forward(1)
- end
- lib.checkCobweb({"up", "down"}, inInventory) -- dig cobweb or any other block up/down/forward
- return {}
- end
- local function clearMonumentLayer(R) -- 85
- R.up = true
- R.down = true
- R.silent = true
- if R.subChoice == 0 then
- R.up = false
- R.down = false
- end
- -- send turtle down until it hits bottom
- -- then clear rectangle of given size
- -- start above water, usually on cobble scaffold above monument
- if T:detect("down") then -- in case not over wall
- T:forward(1)
- end
- local height = 1
- -- go down until solid block detected
- while utils.clearVegetation("down") do
- T:down(1)
- height = height + 1
- end
- T:down(1)
- height = height + 1
- clearRectangle(R)
- T:up(height - 1)
- return {}
- end
- local function clearWaterPlants(R) -- 87
- local lib = {}
- function lib.getLength()
- local length = 1
- print("Checking water length")
- while utils.clearVegetation("forward") do
- T:forward(1)
- length = length + 1
- end
- for i = 1, length do
- turtle.back()
- end
- return length
- end
- function lib.clearDown(D)
- while utils.clearVegetation("down") do --clears any grass or sea plants, returns true if air or water, bubble column or ice
- T:down(1)
- D.depth = D.depth + 1
- end
- -- if slab at bottom, replace with solid block
- D.blockType = T:getBlockType("down")
- if D.blockType:find("slab") ~= nil then
- T:go("C2")
- end
- if D.depth > D.maxDepth then
- D.maxDepth = D.depth
- end
- return D
- end
- function lib.clearLength(D)
- local moves = 0
- local blockHeight = 1
- D.floorLength = 0 -- reset
- while moves < D.length - 1 do
- if utils.clearVegetation("forward") then
- T:forward(1)
- moves = moves + 1
- if turtle.detectUp() then -- could be on monument going under arch, or faulty monument floor
- if not D.monumentArchesClear then
- D = lib.checkArches(D)
- end
- end
- local temp = D.depth
- D = lib.clearDown(D) -- go down if in water/air
- if blockHeight == 4 and D.depth - temp == 3 then -- could be just gone over 3 block high column in ocean monument
- if not D.monumentTopClear then
- D = lib.checkTop(D)
- end
- blockHeight = 1
- end
- if D.useBlockType == "prismarine" then
- if D.blockType:find("prismarine") == nil then
- -- on monument floor so restrict forward movement to 8 blocks
- D.floorLength = D.floorLength + 1
- if D.floorLength == 8 then
- D.blockType = T:getBlockType("forward")
- while D.blockType:find("prismarine") == nil do
- T:up(1)
- D.blockType = T:getBlockType("forward")
- end
- D.floorLength = 0
- end
- end
- end
- if moves >= D.length - 1 then
- D.width = D.width + 1 -- another length completed so increase width
- return D
- end
- else -- block in front
- blockHeight = 1
- local waterAbove = utils.clearVegetation("up")
- local waterAhead = utils.clearVegetation("forward") -- true if air/water in front
- while not waterAhead do -- solid block in front
- if waterAbove then -- move up
- T:up(1)
- D.depth = D.depth - 1
- blockHeight = blockHeight + 1
- if D.depth < 1 then
- D.width = D.width + 1 -- another length completed so increase width
- return D
- end
- else -- block above so go back
- while not waterAbove do
- utils.goBack() -- returns true if no object behind, but moves anyway
- waterAbove = utils.clearVegetation("up")
- moves = moves - 1
- if moves == 0 then
- T:up(1)
- D.depth = D.depth - 1
- waterAbove = utils.clearVegetation("up")
- while not waterAbove do
- T:up(1)
- D.depth = D.depth - 1
- end
- end
- end
- -- go up 1 to prevent loop
- T:up(1)
- D.depth = D.depth - 1
- end
- waterAbove = utils.clearVegetation("up")
- waterAhead = utils.clearVegetation("forward")
- end
- end
- end
- D.width = D.width + 1 -- another length completed so increase width
- D.maxDepth = D.maxDepth + 1 -- +1 to allow for starting pos in top layer
- return D
- end
- function lib.checkArches(D)
- -- gone under a block so could be monument arch (6)
- if T:getBlockType("up"):find("prismarine") ~= nil then -- confirm on monument, not previously cleared
- local direction = "" -- initialise direction
- T:go("B1U2F1R1")
- if T:getBlockType("forward"):find("prismarine") ~= nil then -- correct guess
- direction = "R"
- else -- wrong direction. turn round and check other side
- T:go("R2")
- if T:getBlockType("forward"):find("prismarine") ~= nil then
- direction = "L"
- end
- end
- local path = "U1F1 U1F3 D1F1 D1R2 U2F5 D2"
- --for i = 1, 6 do
- T:go(path) -- clears arch top 1 and returns
- T:go(direction.."1F6"..direction.."1")
- T:go(path) -- clears arch top 2 and returns
- T:go(direction.."1F6"..direction.."1")
- T:go(path) -- clears arch top 3 and returns
- T:go(direction.."1F9"..direction.."1")
- T:go(path) -- clears arch top 4 and returns
- T:go(direction.."1F6"..direction.."1")
- T:go(path) -- clears arch top 5 and returns
- T:go(direction.."1F6"..direction.."1")
- T:go(path) -- clears arch top 6 and returns
- T:go(direction.."3F34"..direction.."2D2F1")
- D.monumentArchesClear = true
- end
- return D
- end
- function lib.checkTop(D)
- -- gone over 3 block column so could be at the top of ocean monument
- if T:getBlockType("down"):find("prismarine") ~= nil then -- confirm on monument, not previously cleared
- local direction = "" -- initialise direction
- T:go("U3R1") -- up to top of column and try right side
- if T:getBlockType("forward"):find("prismarine") ~= nil then -- correct guess
- direction = "L"
- else -- wrong direction. turn round and check other side
- T:go("R2")
- if T:getBlockType("forward"):find("prismarine") ~= nil then
- direction = "R"
- end
- end
- if direction ~= "" then -- facing single block on layer 2
- T:go("U1F6"..direction.."1F5".. direction.."1F5"..direction.."1F5"..direction.."1") -- clear 4 single blocks
- T:go("F1U1"..direction.."1F1"..direction.."3") -- on top of monument
- T:go("F3".. direction.."1F3"..direction.."1F3"..direction.."1F3"..direction.."3") -- clear top, face return
- T:go("F2D5"..direction.."3B1")
- end
- D.monumentTopClear = true
- end
- return D
- end
- function lib.findBlockTypeEnd(D)
- D.blockType = "" -- reset
- repeat
- if utils.clearVegetation("forward") then
- T:forward(1)
- D = lib.clearDown(D) -- go down if in water/air, D.blockType is updated with floor type
- else -- block in front
- local waterAbove = utils.clearVegetation("up")
- local waterAhead = utils.clearVegetation("forward") -- true if air/water in front
- while not waterAhead do -- solid block in front
- if waterAbove then -- move up
- T:up(1)
- else -- block above so go back
- while not waterAbove do
- utils.goBack() -- returns true if no object behind, but moves anyway
- waterAbove = utils.clearVegetation("up")
- end
- end
- waterAbove = utils.clearVegetation("up")
- waterAhead = utils.clearVegetation("forward")
- end
- end
- until D.blockType:find(D.useBlockType) == nil
- -- now above a non-prismarine block, facing away from monument
- T:turnRight(2) -- facing monument
- D.blockType = T:getBlockType("forward")
- while D.blockType:find(D.useBlockType) ~= nil do
- T:up(1)
- D.blockType = T:getBlockType("forward")
- end
- T:go("F1L1")
- D.blockType = T:getBlockType("down")
- while D.blockType:find(D.useBlockType) ~= nil do
- T:forward(1)
- D.blockType = T:getBlockType("down")
- end
- turtle.back()
- -- should now be at end of monument base
- end
- function lib.turn(D)
- local direction = "R"
- if not D.facingForward then
- direction = "L"
- end
- T:go(direction.. 1)
- if utils.clearVegetation("forward") then
- T:forward(1)
- --D.depth = D.depth + lib.clearDown(depth)
- D = lib.clearDown(D)
- else
- while not utils.clearVegetation("forward") do
- T:up(1)
- D.depth = D.depth - 1
- end
- T:forward(1)
- end
- T:go(direction.. 1)
- D.facingForward = not D.facingForward
- return D
- end
- local D = {}
- D.depth = 0
- D.maxDepth = 0
- D.blockType = ""
- D.useBlockType = R.useBlockType -- "" or "prismarine"
- D.length = 0 -- copy of R.length used in lib.clearLength
- D.width = 0 -- increased every iteration
- D.facingForward = true
- D.monumentTopClear = false
- D.monumentArchesClear = false
- D.inWater = false
- D.onWater = false
- D.inWater, D.onWater = utils.getWaterStatus()
- D.floorLength = 0 -- used on monument floor
- if R.data == "clearWaterPlants" then -- NOT monument corner discovery
- D.inWater, D.onWater = utils.startWaterFunction(D.onWater, D.inWater, 2, true) -- move into water
- if R.length == 0 then
- R.length = lib.getLength()
- end
- if R.width == 0 then
- T:turnRight(1)
- R.width = lib.getLength()
- T:turnLeft(1)
- end
- end
- D.length = R.length
- D = lib.clearDown(D) -- go down to floor, set depth, maxDepth, blockType
- if R.data == "clearWaterPlants" then -- NOT monument corner discovery
- if R.width == 1 then
- print("Single row clearing")
- D = lib.clearLength(D) --D.width also increased
- else
- while D.width < R.width do -- D.width starts at 0
- -- now on floor, move along sea/river bed following contour
- D = lib.clearLength(D) --D.width also increased
- -- now turn and repeat
- if D.width < R.width then
- D = lib.turn(D)
- if D.depth <= 0 then
- break
- end
- end
- end
- end
- -- finished so return to surface
- T:up(1) -- up 1 to check for water below
- while T:getBlockType("down"):find("water") ~= nil do
- T:up(1)
- end
- T:down(2) -- return to surface
- --[[while utils.clearVegetation("forward") do
- T:forward(1)
- end]]
- elseif R.data == "oceanMonumentColumns" then -- monument corner discovery
- -- this function used to find edge of monument base
- if D.blockType:find(D.useBlockType) ~= nil then
- lib.findBlockTypeEnd(D)
- return {""}
- else
- T:up(D.depth)
- return {"Prismarine not found on ocean floor"}
- end
- end
- if R.silent then
- return {D.maxDepth, R.length}
- else
- return {""}
- end
- end
- local function clearMountainSide(R) -- 78
- --[[
- First row outward l s f mid (length, start, finish, midPoint)
- >|*|*| true lib.clearRow() moves: 7-5=2, midPoint starts at 2
- +|*|*|
- +|*|*|
- ^|*|*| < false 7 5 6 2 lib.clearRow() moves: 9-2=7, midPoint starts at -4 -1 = -5
- |*|*|*| +
- |*|*|*|*|*| +
- > |*|*|*|*|*| ^ true 9 2 6 -4 lib.getStartingLength(). Ends 1 block after block finish
- ^|*|*|*|*|*|*|*|*| starts here, moves up 1
- 1 2 3 4 5 6 7 8 block index
- Second row outward l s f mid
- < false
- +
- |*|*| +
- >|*|*|*|*|^ true
- +|*|*|*|*|
- +|*|*|*|*|
- ^|*|*|*|*| < false 6 5 6 2
- |*|*|*|*|*|*| +
- |*|*|*|*|*|*|*|*| +
- |*|*|*|>|*|*|*|*| ^ true 7+5 5 -7 lib.getHalf(R); goBack(7)
- |*|*|*|*|*|*|*|*|*|*|*| starts at midPoint of previous row eg block 4
- 0 1 2 3 4 5 6 7 8 9 10
- ]]
- -- variables declared before lib for them to be used within lib as part of scope
- local turn = "R"
- local oTurn = "L"
- if R.subChoice == 1 then -- remove left side
- turn = "L"
- oTurn = "R"
- end
- local outward = true -- direction flag
- local lib = {}
- function lib.isAnyAbove(above)
- for k,v in ipairs(above) do
- if v then
- return true
- end
- end
- return false
- end
- function lib.clearLevel(R, above) -- eg 9, 2, 6, -4 from lib.getStartingLength OR 7, 5, 6, 3 from previous
- -- clearLevel always follows either lib.getStartingLength or a previous lib.clearLevel
- -- midPoint should be adjusted as turtle moves to reflect current row length
- if #above == 0 then return above, 1 end
- local index = 0
- local minMoves = math.floor(#above / 2)
- local up, forward, down = lib.getDetect()
- if outward then -- follow table indexes
- for x = 1, minMoves do -- clear first half
- above[x] = up -- reset this with new value
- T:go("x0x2F1") -- clear and move forward
- up, forward, down = lib.getDetect()
- index = index + 1
- end
- for x = minMoves + 1, #above do -- check remaing half and clear
- if above[x] then -- is a block recorded as present?(now below)
- above[x] = up -- reset this with new value
- T:go("x0x2F1") -- clear and move forward
- up, forward, down = lib.getDetect()
- index = index + 1
- else
- break
- end
- end
- else -- iterate table in reverse
- index = #above
- for x = #above, minMoves, -1 do -- clear first half
- above[x] = up -- reset this with new value
- T:go("x0x2F1") -- clear and move forward
- up, forward, down = lib.getDetect()
- index = index - 1
- end
- for x = minMoves, 1, -1 do -- check remaing half and clear
- if above[x] then -- is a block recorded as present?(now below)
- above[x] = up -- reset this with new value
- T:go("x0x2F1") -- clear and move forward
- up, forward, down = lib.getDetect()
- index = index - 1
- else
- break
- end
- end
- end
- T:go("R2x0x2") -- face opposite direction, delete blocks above and below
- outward = not outward -- switch direction flag
- return above, index -- eg {false, true, true, true, false}, 5
- end
- function lib.getDetect()
- return turtle.detectUp(), turtle.detect(), turtle.detectDown()
- end
- function lib.getStartingLength(R)
- --[[
- length of column by excavating blocks above, ahead or below
- Rotate 180 at end of run ready to return
- already 1 block above ground
- ]]
- local above = {} -- empty table of boolean values
- local length = 0 -- used as counter
- T:forward(1) -- start check 1 block ahead
- local up, forward, down = lib.getDetect() -- check if anything around current block
- if up or forward or down then -- block found nearby: continue
- while up or forward or down do -- while blocks ahead / up / down move forward
- table.insert(above, up)
- T:go("x0x2F1")
- up, forward, down = lib.getDetect() -- check if anything around current block
- length = length + 1
- if length >= R.length then -- check if going out of range
- T:saveToLog("lib.getStartingLength(R) : outward = "..tostring(outward).." MaxLength "..maxLength.." reached", false)
- break
- end
- end
- T:go("R2x0x2") -- Rotate 180 and clear blocks above/below
- else -- no blocks nearby: exit
- T:go("R2F1") -- return to start position rotated 180
- end
- outward = not outward
- return above -- above = {false, true, true, true, true, false, false}
- end
- function lib.firstRow(R)
- local height = 1 -- starts at ground level, but forced up 1
- T:up(1)
- local above = lib.getStartingLength(R) -- clear the ground level and 1 above eg 9, 2, 5, 4
- if T:saveToLog("startLength: "..#above, true) then
- T:saveToLog(utils.tableConcat(above, ", "), false)
- if dbug then read() end
- end -- at end of first row as already turned 180, outward set to false in getStartingLength
- while lib.isAnyAbove(above) do
- T:go("U3") -- go up 3
- height = height + 3
- above, index = lib.clearLevel(R, above, index) -- returns start and finish of blocks above, rotates 180
- if T:saveToLog("checking level: "..height, true) then
- T:saveToLog(utils.tableConcat(above, ", "), false)
- if dbug then read() end
- end
- end -- first row all levels completed.
- T:down(height) -- now on ground + 1, facing last column cleared.
- return above
- end
- function lib.deepCopy(tbl)
- local copy = {}
- for key, value in ipairs(tbl) do
- table.insert(copy, value)
- end
- return copy
- end
- function lib.getHalf(R, above)
- -- already 1 block above ground
- local maxLength = R.length
- local temp = {}
- local retValue = {}
- if #above > 0 then -- not empty table, so must be second half
- temp = lib.deepCopy(above) -- copy existing table
- above = {} -- initialise above
- end
- local up, forward, down = lib.getDetect()
- while up or forward or down do -- while blocks ahead / up / down move forward
- T:go("x0x2F1")
- table.insert(above, up)
- up, forward, down = lib.getDetect() -- check if anything around current block
- if #above >= math.floor(maxLength / 2) then -- check if going out of range
- T:saveToLog("lib.getHalf(R) : outward = "..tostring(outward).." MaxLength "..maxLength.." reached", false)
- T:go("x0x2")
- break
- end
- end
- T:turnRight(2) -- ready for next half or return
- outward = not outward
- if #temp > 0 then -- completing a second half measurement
- for i = #above, 1, -1 do
- table.insert(retValue, above[i]) -- combine 2 tables into 1
- end
- for i = 1, #temp do
- table.insert(retValue, temp[i])
- end
- else
- retValue = above
- end
- return retValue
- end
- function lib.nextRow(R)
- local height = 1
- T:saveToLog("lib.nextRow(R)", false)
- T:up(1)
- local pattern = turn.."1F1"..turn.."1"
- if not outward then
- pattern = oTurn.."1F1"..oTurn.."1"
- end
- T:go(pattern)
- T:saveToLog(" T:go("..pattern..")", false)
- outward = not outward -- reverse direction flag
- -- now in next vertical row
- local above = lib.getHalf(R, {})
- local index = 0
- if T:saveToLog("\t first half Length: "..#above.." Enter", true) and dbug then read() end
- lib.returnToMidPoint(#above) -- return to starting point
- above = lib.getHalf(R, above) -- returns length - 1 eg 5, 4
- local midPoint = math.floor(#above / 2)
- if T:saveToLog("\t total length: "..#above.." Enter", true) and dbug then read() end
- while lib.isAnyAbove(above) do
- T:go("U3") -- go up 3
- height = height + 3 -- increment height
- T:saveToLog("\tClear height loop: height = "..height, false)
- above, index = lib.clearLevel(R, above) -- returns start and finish of blocks above
- end
- T:down(height) -- now on ground + 1
- lib.returnToMidPoint(above)
- end
- function lib.returnToMidPoint(above)
- --[[ value can be integer or table]]
- if type(above) == "table" then
- T:saveToLog("lib.returnToMidPoint("..#above..")", false)
- if #above > 0 then
- local midPoint = math.floor(#above / 2)
- T:saveToLog(" T:forward("..midPoint..")", false)
- T:forward(midPoint)
- end
- else
- T:saveToLog("lib.returnToMidPoint("..above..")", false)
- if above > 0 then
- T:saveToLog(" T:forward("..above..")", false)
- T:forward(above)
- end
- end
- -- now back at starting point
- end
- -- Start here
- -- if "tk log d.." typed instead of "tk" will start logfile and display comments. read() will be activated for debugging
- T:saveToLog("Starting function clearMountainSide", false)
- local above = lib.firstRow(R) -- outward depends on height eg 1-2 = false, 3-5 = true, 6-8 = false
- lib.returnToMidPoint(above) -- return to mid first row of blocks
- for row = 1, R.width -1 do
- lib.nextRow(R)
- end
- return {}
- end
- local function clearSandWall(R) -- 81
- --dig down while on top of sand/red_sand/soul_sand
- local lib = {}
- function lib.checkAbove(height)
- if turtle.detectUp() then -- moved under a ledge
- T:go("B1U1")
- height = height - 1
- end
- return height
- end
- function lib.moveDown(height)
- blockType = T:getBlockType("down")
- while blockType:find("sand") ~= nil do
- T:down(1)
- height = height + 1
- blockType = T:getBlockType("down")
- end
- return height
- end
- function lib.moveForward(length)
- lib.digForward()
- T:forward(1)
- length = length + 1
- local blockType = T:getBlockType("forward")
- return length, blockType
- end
- function lib.digForward()
- while T:dig("forward") do
- while T:suck("forward") do end
- while T:suck("up") do end
- end
- end
- local moves = 0
- local height = 0
- local length = 0
- local search = 0
- local reverse = false
- local blockType = T:getBlockType("down")
- if R.length == 0 then
- R.length = 64
- end
- print("Checking for sand below")
- while blockType:find("sand") == nil do --move forward until sand detected or 3 moves
- T:forward(1)
- search = search + 1
- blockType = T:getBlockType("down")
- if search > 3 then
- T:go("B"..search)
- return {"Unable to locate sand"}
- end
- end
- -- must be sand below
- height = lib.moveDown(height) -- go down if sand below
- -- repeat until height == 0
- repeat -- starts at bottom of sand wall
- blockType = T:getBlockType("forward")
- if blockType:find("sand") ~= nil then -- sand in front
- length, blockType = lib.moveForward(length) -- move forward 1 and dig sand
- if blockType == "" or blockType:find("sand") ~= nil then -- sand or nothing in front
- height = lib.moveDown(height) -- go down if sand below
- end
- else -- solid block, air or water, not sand so move up
- if turtle.detect() then -- block in front
- blockType = T:getBlockType("down")
- if blockType:find("sand") ~= nil then -- sand below
- T:dig("down")
- end
- T:up(1)
- height = height - 1
- else -- air/water in front so move forward
- if length < 60 then -- in case missing wall and in open ocean
- length, blockType = lib.moveForward(length) -- move forward 1 and dig sand
- height = lib.checkAbove(height)
- else -- already > monument length of 56
- T:up(1)
- height = height - 1
- end
- end
- end
- until height == 0 or length == R.length
- blockType = T:getBlockType("down")
- if blockType:find("sand") ~= nil then -- sand below
- T:dig("down")
- end
- if height > 0 then -- finished as length ran out
- T:up(height)
- end
- -- stay at end of cleared wall unless user chose to return
- if R.data == "return" then
- T:go("R2F"..length.."R2")
- end
- return {}
- end
- local function clearSolid(R) -- 76
- --[[ direction = R.subChoice = 1 up or 2 down ]]
- local height = 1
- local remaining = R.height
- local lib = {}
- function lib.singleLayer(R)
- R.up = false
- R.down = false
- clearRectangle(R)
- end
- function lib.doubleLayer(R)
- R.up = false
- R.down = false
- if R.subChoice == 1 then
- R.up = true
- else
- R.down = true
- end
- clearRectangle(R)
- end
- function lib.tripleLayer(R)
- -- turtle in centre layer
- R.up = true
- R.down = true
- clearRectangle(R)
- end
- R.silent = true
- if R.height < 3 then --1-3 layers only
- if R.height == 1 then --one layer only
- lib.singleLayer(R)
- elseif R.height == 2 then --2 layers only current + dig up/down
- lib.doubleLayer(R)
- end
- else -- 3 or more levels
- height = height + utils.move(R, 1) -- move up/down 1 block for first layer
- while remaining >= 3 do -- min 3 levels
- lib.tripleLayer(R)
- remaining = remaining - 3
- if remaining == 0 then -- all finished
- break
- elseif remaining == 1 then
- height = height + utils.move(R, 2) -- move up/down 2 blocks
- lib.singleLayer(R)
- elseif remaining == 2 then
- height = height + utils.move(R, 2) -- move up/down 2 blocks
- lib.doubleLayer(R)
- else
- height = height + utils.move(R, 3) -- move up/down 3 blocks
- if remaining == 3 then
- finish = true
- end
- end
- end
- end
- if height > 1 then
- utils.move(R, height - 1, true) -- reverse direction
- end
- return {}
- end
- local function clearSandCube(R) -- 81
- R.data = ""
- for w = 1, R.width do
- clearSandWall(R)
- if w < R.width then
- if w % 2 == 1 then
- T:go("R1F1R1")
- else
- T:go("L1F1L1")
- end
- end
- end
- return {}
- end
- local function clearWall(R) -- 73
- local lib = {}
- function lib.move(direction, blocks, reverse)
- --[[ Move up or down by blocks count ]]
- if reverse == nil then
- reverse = false
- end
- if reverse then
- if direction == "down" then -- reverse direction
- T:up(blocks)
- else
- T:down(blocks)
- end
- else
- if direction == "up" then
- T:up(blocks)
- else
- T:down(blocks)
- end
- end
- return blocks
- end
- function lib.singleLayer(length)
- T:go("F"..length - 1)
- end
- function lib.doubleLayer(modifier, length)
- for i = 1, length do
- if i < length then
- T:go("x"..modifier.."F1")
- else
- T:go("x"..modifier)
- end
- end
- end
- function lib.tripleLayer(direction, length)
- for i = 1, length do
- if i < length then
- T:go("x0x2F1")
- else
- T:go("x0x2")
- end
- end
- end
- -- R.width preset to 1
- -- R.subChoice = 1 up / 2 down
- if R.height < 3 then
- R.silent = true
- end
- -- dig along and up/down for specified R.length
- local modifier = "0"
- local direction = "U"
- local outbound = true
- local height = 0
- if R.subChoice == 2 then
- modifier = "2"
- direction = "D"
- end
- if R.height == 1 then -- single block so dig and return
- lib.singleLayer(R.length)
- elseif R.height == 2 then
- lib.doubleLayer(modifier, R.length)
- else -- 4 blocks or more. start with bulk 3 blocks
- local remaining = R.height
- T:go(direction.."1") -- up 1 or down 1
- height = 1
- while remaining >= 3 do
- lib.tripleLayer(direction, R.length)
- remaining = remaining - 3
- if remaining == 0 then -- no more, return home, already in position
- elseif remaining == 1 or remaining == 2 then
- T:go(direction.."2")
- height = height + 2
- else
- T:go(direction.."3")
- height = height + 3
- if remaining >= 3 then -- another iteration
- T:go("R2")
- outbound = not outbound
- end
- end
- end
- -- 0, 1 or 2 layers left
- if remaining > 0 then
- T:go("R2")
- outbound = not outbound
- if remaining == 1 then
- lib.singleLayer(R.length)
- elseif remaining == 2 then
- lib.doubleLayer(modifier, R.length)
- end
- end
- end
- if outbound then
- T:go("R2F"..R.length)
- else
- T:forward(1)
- end
- direction = "D" -- reverse direction
- if R.subChoice == 2 then
- direction = "U"
- end
- if height > 0 then
- T:go(direction..height.."R2")
- else
- T:go("R2")
- end
- return {}
- end
- local function convertWater(R) -- 88
- --[[
- if dry need enough buckets to place along (width + length - 1) / 2
- use 12 buckets
- start on floor + 1
- place slab down and water up along 2 edges. stay on this level
- return round same 2 edges removing slabs and and placing them 1 above
- placeUp water onto slabs on both edges
- repeat recover slabs, place 1 above , placeUp water
- for sloping water, place full area with slabs
- place sloping water on top of slabs
- remove slabs
- ]]
- local lib = {}
- function lib.checkStartPosition()
- --[[
- 0 T -- T=turtle, W=wall, S=source, F=flowing
- 1 W|S|F|F|F|F|F -- sloping flowing water
- 2 W|F|F|F|F|F|F -- blocks removed after placing flowing water above
- 3 W|S|S|S|S|S|S -- original sources
- 4 W|?|?|?|?|?|? -- may be sources
- ]]
- -- need to be on floor or R.height if specified
- local depth = 0
- local blockType = T:getBlockType("down")
- local isWaterUp, isSourceUp = T:isWater("up")
- local isWaterForward, isSourceForward = T:isWater("forward")
- local isWaterDown, isSourceDown = T:isWater("down")
- print("Block below is "..blockType)
- print("Water above is "..tostring(isWaterUp))
- print("Water forward is "..tostring(isWaterForward))
- print("Water below is "..tostring(isWaterDown))
- if blockType:find("water") == nil then -- on at least level 0
- print("Moving forward in 2 seconds...")
- sleep(2)
- T:forward(1)
- blockType = T:getBlockType("down")
- if blockType:find("water") ~= nil then
- print("Water found. Going down to floor")
- depth = -1
- else
- T:down(1)
- blockType = T:getBlockType("down")
- if blockType:find("water") ~= nil then
- depth = -2
- else
- return 0, "Not close to water. Aborting..."
- end
- end
- end
- while turtle.down() do
- depth = depth + 1
- end
- local emptyBuckets = utils.getEmptyBucketCount()
- for i = depth, 0, -1 do
- if emptyBuckets > 0 then
- lib.fillBuckets()
- emptyBuckets = utils.getEmptyBucketCount()
- end
- turtle.up()
- end
- return depth, ""
- end
- function lib.fillBuckets()
- local emptyBuckets = utils.getEmptyBucketCount()
- local direction = "forward"-- start with forward
- local isWater, isSource, isIce = T:isWater(direction)
- if emptyBuckets > 0 then
- if not isSource then
- direction = "down"
- isWater, isSource, isIce = T:isWater(direction)
- if not isSource then
- direction = "up"
- isWater, isSource, isIce = T:isWater(direction)
- if not isSource then
- direction = ""
- end
- end
- end
- if direction == "" then
- print("Unable to locate water source")
- else
- for i = 1, emptyBuckets do
- if utils.fillBucket(direction) then
- print("Bucket filled "..direction)
- sleep(0.3)
- else
- print("Unable to fill bucket ".. i .." / "..emptyBuckets)
- end
- end
- end
- end
- return utils.getWaterBucketCount()
- end
- function lib.placeSlabs(length)
- for i = 1, length do
- T:place("slab", -1, "down", false)
- if i < length then
- T:forward(1)
- end
- end
- end
- function lib.placeSources(length, place)
- local moves = 1
- local waterBuckets = utils.getWaterBucketCount()
- -- place sources alternate positions + start and finish
- while moves < length do
- if place then
- if T:placeWater("up") then
- print("Placed source up")
- waterBuckets = waterBuckets - 1
- end
- end
- place = not place
- if moves < length then
- T:forward(1)
- moves = moves + 1
- end
- if waterBuckets == 0 then
- T:down(1) -- break the slab below
- waterBuckets = lib.fillBuckets()
- T:up(1)
- T:place("slab", -1, "down", false)
- end
- end
- if T:placeWater("up") then -- end of length
- print("Placed final source up")
- end
- return place
- end
- function lib.moveSlabs(length)
- for i = 1, length do
- T:dig("down")
- T:up(1)
- T:place("slab", -1, "down", true)
- if i < length then
- T:forward(1)
- T:down(1)
- end
- end
- end
- function lib.recoverSlabs(length)
- for i = 1, length do
- T:dig("down")
- if i < length then
- T:forward(1)
- end
- end
- end
- local depth, message = lib.checkStartPosition()
- if message ~= "" then
- return {message}
- end
- local maxDepth = R.height
- local buckets = utils.getWaterBucketCount()
- R = utils.calculateDimensions(R) -- if R.width or R.length == 0
- T:down(depth)
- lib.placeSlabs(R.length)
- T:go("R1")
- lib.placeSlabs(R.width)
- T:go("R2")
- while depth > 0 do
- local place = true
- lib.fillBuckets()
- place = lib.placeSources(R.width, place)
- T:go("L1")
- place = lib.placeSources(R.length, place)
- lib.fillBuckets()
- T:go("R2")
- lib.moveSlabs(R.length) -- dig slab from below, move up and replace below
- T:go("R1F1D1")
- lib.moveSlabs(R.width - 1)
- T:go("R2") -- now moved up 1 layer
- depth = depth - 1
- if depth == 0 then
- place = lib.placeSources(R.width, true)
- T:go("L1")
- place = lib.placeSources(R.length, place)
- T:go("R2")
- lib.recoverSlabs(R.length)
- T:go("R1")
- lib.recoverSlabs(R.width)
- end
- end
- return {}
- end
- local function createBoatLift(R) -- 59 state:0=new, size:1=extend, side:0=left, 1=right
- -- build stepped lift with fencing gates and soul sand
- local lib = {}
- function lib.getWater(backToWater, downToWater)
- if backToWater > 0 then
- utils.goBack(backToWater)
- end
- if downToWater > 0 then
- T:down(downToWater)
- end
- T:getWater("down") -- take water from source
- sleep(0.2)
- T:getWater("down") -- take water from source
- if downToWater > 0 then
- T:up(downToWater)
- end
- if backToWater > 0 then
- T:forward(backToWater)
- end
- end
- --T:place(blockType, damageNo, direction, leaveExisting, signText)
- local backToWater = 0
- local downToWater = 0
- T:go("R1F1L1") -- over canal facing forward
- for h = 1, R.height do
- lib.getWater(backToWater, downToWater) -- check water supplies, return to starting position
- T:go("L1C1 R1D1 L1C1 R1", false, 0, false) -- place towpath, forward, down, place towpath, face forward
- T:place("soul", -1, "down", false) -- place soulsand down
- T:place("soul", -1, "forward", false) -- place soulsand forward
- T:go("R1F1C1L1", false, 0, false) -- place right towpath face forward
- T:place("soul", -1, "down", false) -- place soulsand down
- T:place("soul", -1, "forward", false) -- place soulsand forward
- T:go("U1 R1C1 L1") -- place towpath, face forward
- T:placeWater("down") -- place water down
- utils.goBack(1)
- T:place("gate", -1, "forward", false) -- place fence gate
- T:go("R1C1 U1C1 D1 L2F1 C1R1 F1 L1C1R1") -- over left soul sand
- T:placeWater("down") -- place water down
- utils.goBack(1)
- T:place("gate", -1, "forward", false) -- place fence gate
- T:go("U1 L1C1 R1F1 L1C1 R1x1") -- facing forward first unit complete
- T:go("R1F1 L1x1 R1C1")
- utils.goBack(1)
- T:go("L1F1")
- if backToWater == 0 then
- backToWater = 1
- end
- backToWater = backToWater + 1
- downToWater = downToWater + 1
- end
- -- now finish the canal
- lib.getWater(backToWater, downToWater)
- T:go("D1 L1C1 U1C1") -- build left towpath, facing towpath, above water level
- T:go("R1F1 L1C1 D1C1") -- move forward, build towpath, facing towpath ground level
- T:go("R1C1 R1F1 L1C1 R1C1 U1C1") -- build right towpath, facing towpath, above water level
- T:go("R1F1 L1C1 D1C1 U1") -- build right towpath next to gate, facing towpath, above water level
- T:placeWater("down")
- utils.goBack(1)
- T:go("L1F1")
- T:placeWater("down")
- return {}
- end
- local function createBorehole(R)
- --[[go down to bedrock and return. Chart all blocks dug/ passed through]]
- local diary = {}
- local lib = {}
- local depth = R.height -- eg 63 start position
- local moves = 0
- --R.height = current level
- function lib.addBlock(depth, blockType, diary)
- if blockType == "" then
- blockType = "air"
- end
- table.insert(diary, blockType)
- --[[if blockType ~= "" then
- local add = true
- for k,v in pairs(diary) do
- if blockType == v then
- add = false
- break
- end
- end
- if add then
- diary[depth] = blockType
- end
- end]]
- return diary
- end
- function lib.processItem(item)
- if item:find("minecraft") ~= nil then
- return item:sub(11)
- end
- return item
- end
- function lib.writeReport(R, diary)
- local numLevels = #diary -- eg 125 levels
- local levelsPerCol = math.ceil(numLevels / 4) -- eg 31.25 -> 32
- local lines = {}
- for l = 1, levelsPerCol do -- add 32 empty strings
- table.insert(lines, "")
- end
- local lineNo = 1
- for k, v in ipairs(diary) do
- local level = R.height - k -- eg 63 range 63 to -59
- local lev = " "
- local item = lib.processItem(v)
- if level < -9 then
- lev = tostring(level).." " -- "-10 " to "-59 "
- elseif level < 0 then
- lev = "-0"..math.abs(level).." " -- "-09 " to "-01 "
- elseif level < 10 then
- lev = " 0"..level.." " -- " 01 " to " 09 "
- elseif level < 100 then
- lev = " "..level.." " -- " 10 " to " 99 "
- else
- lev = " "..level.." " -- " 100 " to " 319 "
- end
- local output = lev..item -- eg "-10 grass_block"
- if #output > 20 then -- eg "-10 some_long_block_name"
- output = output:sub(1, 20) -- eg "-10 some_long_block_"
- else
- output = menu.padRight(output, 20, " ") -- eg "-10 grass_block "
- end
- lines[lineNo] = lines[lineNo]..output -- add new entry to this line
- lineNo = lineNo + 1 -- increase line no
- if lineNo > levelsPerCol then -- past last line number
- lineNo = 1 -- reset to 1
- end
- end
- local fileName = "borehole"..os.getComputerID()..".txt"
- local handle = fs.open(fileName, "w") --create file eg "borehole0.txt"
- handle.writeLine("Level Block Level Block Level Block Level Block")
- for k,v in ipairs(lines) do
- handle.writeLine(v)
- end
- handle.close()
- return fileName
- end
- local blockType = T:getBlockType("down")
- while T:down(1) do
- depth = depth - 1
- moves = moves + 1
- if depth == R.depth then
- break
- end
- diary = lib.addBlock(depth, blockType, diary)
- blockType = T:getBlockType("down")
- end
- local fileName = lib.writeReport(R, diary)
- T:up(moves)
- return {"File '"..fileName.."' written"}
- end
- local function createBubbleLift(R) -- 15
- local lib = {}
- function lib.addLayer()
- T:go("F2 L1C1 R1C1 R1C1 L1", false, 0, true)
- turtle.back()
- T:dig("up") -- clear block above so completed lift can be found
- T:placeWater("forward")
- turtle.back()
- T:go("C1x0")
- end
- function lib.addSign()
- turtle.back()
- T:placeWater("forward")
- T:go("L1B1")
- T:place("sign", -1, "forward")
- end
- function lib.buildLift(toHeight)
- local built = lib.goToWater() -- returns lift blocks already placed, total height of drop from starting point
- local toBuild = toHeight - built -- no of blocks remaining to increase lift size
- local water = 0
- while toBuild > 0 do -- at least 1 block height remaining
- water = lib.fillBuckets(toBuild, false) -- no of water buckets onboard (could be more than required)
- if water > toBuild then -- more water than required
- water = toBuild -- reduce to correct amount
- end
- T:up(built) -- climb to top of existing lift
- while water > 0 and toBuild > 0 do
- lib.addLayer()
- water = water - 1
- T:up(1)
- toBuild = toBuild - 1
- end
- -- may still be some height to complete, but needs refill
- if toBuild > 0 then
- built = lib.goToWater() --return to source
- toBuild = toHeight - built
- --lib.fillBuckets(toBuild)
- end
- end
- end
- function lib.cleanUp(fromHeight)
- local plug = false
- T:turnRight(2)
- for i = 1, fromHeight do
- plug = false
- if turtle.detect() then
- plug = true
- end
- turtle.down()
- if plug then
- T:place("stone", -1, "up")
- end
- end
- T:go("D1 C1R1x1 R1C1 R1F1 R1x1 L2x1 L1C1 x1") -- delete water sources
- T:go("D1 C1R1x1 R1")
- local blockType = T:getBlockType("forward")
- if blockType:find("dirt") == nil and blockType:find("soul") == nil then -- not dirt or soul sand in front
- T:go("C1")
- end
- T:go("R1F1 R1x1 L2x1 L1C1 x1")
- end
- function lib.fillBuckets(toBuild, withSort)
- local emptySlots, water = lib.stackBuckets(withSort)-- gets no of empty slots + no of water buckets
- if water < toBuild then -- no of water buckets onboard less than required quantity
- for i = 1, toBuild do -- fill required no of buckets up to max space in inventory
- if emptySlots == 0 then -- inventory full
- break
- else
- if T:getWater("down") then
- water = water + 1
- sleep(0.5)
- end
- end
- emptySlots = lib.getEmptySlots()
- end
- end
- return water
- end
- function lib.getEmptySlots()
- local empty = 0
- for i = 1, 16 do
- if turtle.getItemCount(i) == 0 then
- empty = empty + 1
- end
- end
- return empty
- end
- function lib.goToWater()
- local built = 0 -- measures completed lift height
- while turtle.down() do -- takes turtle to bottom of water source
- if turtle.detect() then
- built = built + 1
- end
- end
- T:up(1) -- above watersource ready to fill buckets
- -- height = height - 1
- -- built = built - 1 not required as next block is water source: not detected
- return built -- , height
- end
- function lib.stackBuckets(withSort)
- if withSort == nil then withSort = false end
- local data = {}
- local bucketSlot = 0
- local emptySlots = 0
- local water = 0
- if withSort then
- T:sortInventory()
- end
- for i = 1, 16 do
- -- find first empty bucket
- if turtle.getItemCount(i) > 0 then
- data = turtle.getItemDetail(i)
- if data.name == "minecraft:bucket" then
- if bucketSlot == 0 then
- bucketSlot = i
- else
- turtle.select(i)
- turtle.transferTo(bucketSlot)
- end
- elseif data.name == "minecraft:water_bucket" then
- water = water + 1
- end
- else
- emptySlots = emptySlots + 1
- end
- end
- return emptySlots, water
- end
- T:go("C1R1") -- place block next to ladder support block, turn right to check ladder
- local blockType = T:getBlockType("forward") -- Is there a ladder to the right?
- if blockType:find("ladder") == nil then
- T:go("C1L2") -- Place block as ladder not present
- else -- ladder present
- T:go("L2") -- ready to check other side
- end
- blockType = T:getBlockType("forward")
- if blockType:find("ladder") == nil then
- T:go("C1R1")
- else
- T:go("R1")
- end
- blockType = T:getBlockType("down")
- local dirt = "minecraft:dirt"
- if T:getItemSlot("minecraft:soul_sand") > 0 then
- dirt = "minecraft:soul_sand"
- end
- if blockType:find("bedrock") ~= nil then
- utils.goBack(1)
- T:place(dirt, -1, "forward", false) -- placed at end of potential water source, next to ladder
- else
- T:place(dirt, -1, "down", false) -- placed in ground, next to ladder
- utils.goBack(1)
- T:placeWater("forward") -- place extra water source
- end
- T:go("R1C1 R2C1 L1F1C2 R1C1 L2C1 R1F1C2 R1C1 L1C1 L1C1 L1F1", false, 0, true)
- -- ready for water sources to be placed
- T:placeWater("forward") -- place front water source
- T:turnRight(2) -- facing backward
- T:placeWater("forward") -- place back water source
- T:go("R2U1") -- facing forward, U1, above centre of water source
- lib.fillBuckets(R.height, true) -- fill as many buckets as required or until inventory full, sort inventory as well
- local nextToLadder = false
- --T:go("F2R1")
- T:go("x0F1 x0F1C1 R1") -- move forward 2 taking out blocks above, plug behind soul sand
- if T:getBlockType("forward"):find("ladder") == nil then -- no ladder here
- T:turnLeft(2)
- if T:getBlockType("forward"):find("ladder") ~= nil then -- ladder here
- nextToLadder = true
- end
- T:turnRight(1)
- else
- nextToLadder = true
- T:turnLeft(1)
- end
- -- now above soul sand, facing forward
- if nextToLadder then -- if nextToLadder, no need for signs
- utils.goBack(2) -- return to source centre
- else
- T:go("F2 L1C1R1C1R1C1L1", false, 0, true) -- prepare layer 1
- lib.addSign()
- T:go("U1F1R1F1 L1C1R1C1R1C1L1", false, 0, true) -- prepare layer 2
- lib.addSign()
- T:go("L1F1 R1F1R1", false, 0, true) -- above source, level 2
- end
- -- ready to build lift
- lib.buildLift(R.height - 1)
- lib.cleanUp(R.height - 1)
- return {"Bubble lift created", "Check correct operation", "Check exit before using" }
- end
- local function createBubbleTrap(R) -- 34
- --[[
- Replace floor of existing volume of water with soulsand
- Used in river biome for squid farm. Area should be enclosed
- with solid walls surface to floor.
- Usually 7 blocks wide
- ]]
- local lib = {}
- function lib.clearDown(depth)
- while utils.clearVegetation("down") do
- T:down(1)
- depth = depth + 1
- end
- T:place("soul_sand", -1, "down", false)
- return depth
- end
- function lib.clearLength(length, depth)
- local moves = 0
- while moves < length - 1 do
- if utils.clearVegetation("forward") then
- T:forward(1)
- moves = moves + 1
- depth = lib.clearDown(depth) -- go down if in water/air
- if moves >= length - 1 then
- return depth
- end
- else -- block in front
- local waterAhead = utils.clearVegetation("forward") -- true if air/water in front
- while not waterAhead do -- solid block in front
- T:up(1)
- depth = depth - 1
- if depth < 1 then
- return 0
- end
- waterAhead = utils.clearVegetation("forward")
- end
- end
- end
- return depth
- end
- function lib.turn(facingForward, depth)
- local direction = "R"
- if not facingForward then
- direction = "L"
- end
- T:go(direction.. 1)
- if utils.clearVegetation("forward") then
- T:forward(1)
- depth = depth + lib.clearDown(depth)
- else
- while not utils.clearVegetation("forward") do
- T:up(1)
- depth = depth - 1
- end
- end
- T:go(direction.. 1)
- return depth
- end
- local depth = 0
- local length = 0
- local width = 0
- local outbound = true
- local facingForward = true
- local inWater, onWater = utils.getWaterStatus()
- inWater, onWater = utils.startWaterFunction(onWater, inWater, 2 ,true) -- move into water, max descent 2
- if R.length == 0 then
- R.length = lib.getLength()
- end
- if R.width == 0 then
- T:turnRight(1)
- R.width = lib.getLength()
- T:turnLeft(1)
- end
- -- go down to floor
- depth = lib.clearDown(depth)
- while width < R.width do
- -- now on floor, move along sea/river bed following contour
- depth = lib.clearLength(R.length, depth)
- width = width + 1
- -- now turn and repeat
- if width < R.width then
- depth = lib.turn(facingForward, depth)
- facingForward = not facingForward
- end
- end
- -- finished so return to surface
- T:up(1) -- up 1 to check for water below
- while T:isWater("down") do
- T:up(1)
- end
- return {}
- end
- local function createCorridor(R) -- 52
- --[[create a corridoor 2 blocks high, with floor and ceiling guaranteed]]
- local lib = {}
- function lib.continue(R, currentSteps, totalSteps)
- if not R.silent then
- if currentSteps >= 64 and R.length == 0 then
- -- request permission to continue if infinite
- T:clear()
- print("Completed "..totalSteps..". Ready for 64 more")
- print("Do you want to continue? (y/n)")
- response = read()
- if response:lower() ~= "y" then
- return true, 0
- else
- return false, currentSteps
- end
- end
- end
- return true, currentSteps
- end
- function lib.seal()
- local blockType = T:getBlockType("forward")
- if blockType:find("water") ~= nil then
- T:place("stone", 0, "forward", false)
- return "water" -- water found
- elseif blockType:find("lava") ~= nil then
- T:place("stone", 0, "forward", false)
- return "lava" -- lava found
- end
- return "" -- no water or lava
- end
- function lib.checkSeal(R)
- local fluidType = ""
- if R.data == "seal" then -- check for lava/water at the sides
- T:turnRight(1)
- fluidType = lib.seal() -- could be "", "water", "lava"
- T:turnLeft(2)
- local blockType = lib.seal()
- if fluidType == "" then -- no water / lava so far
- fluidType = blockType -- could be "", "water", "lava"
- end
- T:turnRight(1)
- end
- return fluidType -- could be "", "water", "lava"
- end
- function lib.placeTorch(R, torchSpaces, totalSteps)
- if R.torchInterval > 0 then -- torches onboard
- if torchSpaces == R.torchInterval then -- time to place another torch
- if totalSteps < R.length then -- not at end of run
- if T:getItemSlot("minecraft:torch") > 0 then
- T:place("minecraft:torch", -1, "down")
- end
- torchSpaces = 1
- end
- end
- end
- return torchSpaces -- original value or 1
- end
- local currentSteps = 0 -- counter for infinite length. pause every 64 blocks
- local totalSteps = 0 -- counter for all steps so far
- local torchSpaces = R.torchInterval -- if torches present, counter to place with 8 blocks between
- local fluidType = ""
- local damLength = 0
- local damStarted = false
- local doContinue = true
- if T:getItemSlot("minecraft:torch") == 0 then
- R.torchInterval = 0 -- set to default 9 in getTask()
- end
- for steps = 1, R.length do
- -- starts on floor of tunnel
- doContinue, currentSteps = lib.continue(R, currentSteps, totalSteps) -- continue tunnelling?
- if not doContinue then
- break
- end
- T:go("C2U1C0", false, 0, true) -- place floor, up 1, place ceiling
- fluidType = lib.checkSeal(R) -- if R.data == "seal", check for water/lava at ceiling level
- if fluidType == "" then -- either R.data ~= "seal" or no fluid found
- torchSpaces = lib.placeTorch(R, torchSpaces, totalSteps) -- original value or 1 if torch placed
- T:go("F1D1", false, 0, true)
- elseif fluidType == "water" then
- T:go("F1R2 C1D1 C1L2")
- damStarted = true
- damLength = damLength + 1
- else --lava
- T:go("F1D1", false, 0, true)
- end
- blockType = lib.checkSeal(R)
- if blockType ~= "" then
- fluidType = blockType
- end
- currentSteps = currentSteps + 1
- totalSteps = totalSteps + 1
- torchSpaces = torchSpaces + 1
- if damStarted and fluidType == "" then -- was in water, but no more
- T:go("R2 F"..damLength + 1 .."U1L2F"..damLength + 1 .."D1")
- damStarted = false
- end
- end
- if fluidType ~= "" then -- water or lava found while tunnelling
- T:go("U1C0")
- lib.checkSeal(R)
- T:go("C1")
- T:down(1)
- end
- return {}
- end
- local function createDragonTrap() -- 49
- local lib = {}
- function lib.attack()
- local totalHitsF = 0
- local totalHitsU = 0
- local totalHitsD = 0
- while true do
- local hitF = false
- local hitU = false
- local hitD = false
- if turtle.attackUp() then
- hitU = true
- totalHitsU = totalHitsU + 1
- end
- if turtle.attackDown() then
- hitD = true
- totalHitsD = totalHitsD + 1
- end
- if turtle.attack() then
- hitF = true
- totalHitsF = totalHitsF + 1
- end
- if hitF or hitU or hitD then
- print("hits forward: "..totalHitsF..", up: "..totalHitsU..", down: "..totalHitsD)
- end
- end
- end
- -- build up 145 blocks with ladders
- for i = 1, 145 do
- T:go("U1C2")
- turtle.back()
- T:place("minecraft:ladder", -1, "down")
- turtle.forward()
- end
- T:go("R2F1C1 L1C1 L2C1 R1")
- for i = 1, 100 do
- T:go("F1C2U1C0D1")
- end
- T:forward(1)
- T:place("minecraft:obsidian", -1, "down")
- T:go("R2F1x2R2")
- T:placeWater("forward")
- T:go("R2F6R2")
- lib.attack()
- return {}
- end
- local function createEnderTower(stage) -- 66
- --[[ lower base = stage 1, upper base = 2, tower = 3 ]]
- local lib = {}
- --[[ go(path, useTorch, torchInterval, leaveExisting, preferredBlock) ]]
- function lib.getEmptySlots()
- local empty = 0
- for i = 1, 16 do
- if turtle.getItemCount(i) == 0 then
- empty = empty + 1
- end
- end
- return empty
- end
- function lib.getStone(direction, stacks)
- --[[ get block user wants to use ]]
- local suck = turtle.suck
- if direction == "down" then
- suck = turtle.suckDown
- end
- if T:getBlockType(direction) == "minecraft:chest" then
- T:sortInventory()
- local slot = T:getFirstEmptySlot() --find spare slot
- if slot > 0 then --empty slot found
- turtle.select(1)
- if stacks == 0 then
- while suck() do end
- else
- for i = 1, stacks do -- get # stacks of stone from chest
- suck()
- end
- end
- if T:getSlotContains(slot) == "" then
- return T:getMostItem() -- empty chest
- else
- return T:getSlotContains(slot) -- use this as default building block
- end
- else
- return T:getMostItem() -- full inventory
- end
- else
- return T:getMostItem() -- no chest
- end
- end
- function lib.stackBuckets()
- local data = {}
- local bucketSlot = 0
- local emptySlots = 0
- local water = 0
- T:sortInventory()
- for i = 1, 16 do
- -- find first empty bucket
- if turtle.getItemCount(i) > 0 then
- data = turtle.getItemDetail(i)
- if data.name == "minecraft:bucket" then
- if bucketSlot == 0 then
- bucketSlot = i
- else
- turtle.select(i)
- turtle.transferTo(bucketSlot)
- end
- elseif data.name == "minecraft:water_bucket" then
- water = water + 1
- end
- else
- emptySlots = emptySlots + 1
- end
- end
- return emptySlots, water
- end
- function lib.countWaterBuckets()
- local data = {}
- local buckets = 0
- for i = 1, 16 do
- data = turtle.getItemDetail(i)
- if data.name == "minecraft:water_bucket" then
- buckets = buckets + 1
- end
- end
- return buckets
- end
- function lib.baseRun(preferredBlock, count, turn)
- for i = 1, count do
- T:go("C2F1", false, 0, false, preferredBlock)
- end
- T:go("C2"..turn, false, 0, false, preferredBlock)
- end
- function lib.outsideRun(preferredBlock)
- T:place("fence", -1, "down", false)
- T:forward(1)
- T:place(preferredBlock, -1, "down", false)
- T:forward(1)
- T:place(preferredBlock, -1, "down", false)
- T:forward(2)
- T:place(preferredBlock, -1, "down", false)
- end
- function lib.signRun(preferredBlock ,message)
- T:place(preferredBlock, -1, "down", false)
- T:forward(4)
- T:place(preferredBlock, -1, "down", false)
- turtle.back()
- turtle.back()
- T:down(1)
- T:place("sign", -1, "forward", false, message)
- T:go("U1F2")
- end
- function lib.goToWater(height)
- local built = 0 -- measures completed lift height
- while turtle.down() do -- takes turtle to bottom of water source
- height = height + 1
- if turtle.detect() then
- built = built + 1
- end
- end
- T:up(1) -- above watersource assuming it is 1-1.5 blocks deep
- height = height - 1
- -- built = built - 1 not required as next block is water source: not detected
- return built, height
- end
- function lib.fillBuckets(toBuild)
- local emptySlots, water = lib.stackBuckets() -- gets no of empty slots + no of water buckets
- if water < toBuild then -- no of water buckets onboard less than required quantity
- for i = 1, toBuild do -- fill required no of buckets up to max space in inventory
- emptySlots = lib.getEmptySlots()
- if emptySlots == 0 then -- inventory full
- break
- else
- if T:getWater("down") then
- water = water + 1
- sleep(0.5)
- end
- end
- end
- end
- return water
- end
- function lib.buildLift(preferredBlock)
- local built = 0 -- measures completed lift height
- local height = 0 -- measures total height from starting position
- built, height = lib.goToWater(height) -- returns lift blocks already placed, total height of drop from starting point
- local toBuild = height - built -- no of blocks to increase lift size
- while toBuild > 0 do -- at least 1 block height remaining
- local water = lib.fillBuckets(toBuild) -- no of water buckets onboard (could be more than required)
- if water > toBuild then
- water = toBuild
- end
- while turtle.detect() do -- climb to top of existing lift
- turtle.up()
- height = height - 1
- end
- T:forward(1)
- for i = 1, water do -- build lift by no of water buckets
- if T:placeWater("forward") then
- T:up(1)
- height = height - 1
- toBuild = toBuild - 1
- T:place(preferredBlock, -1, "down", false)
- end
- end
- turtle.back()
- -- may still be some height to complete, but needs refill
- if toBuild > 0 then
- lib.goToWater(0) --return to source
- lib.fillBuckets(toBuild)
- end
- end
- if height > 0 then -- if any remaining distance
- T:up(height)
- end
- end
- function lib.buildSection(preferredBlock, solid)
- -- builds a section without any blocks in the centre
- -- second layer of each section end walls have fence posts
- T:go("F1C2 F2C2 F1R1", false, 0, false, preferredBlock) -- first side solid row
- if solid then -- first layer of each section
- T:go("F1C2 F1R1", false, 0, false, preferredBlock) -- top side solid row
- else
- T:go("F1") -- top side solid row
- if not T:place("fence", -1, "down", false) then-- first side
- T:place(preferredBlock, -1, "down", false)
- end
- T:go("F1R1") -- top side solid row
- end
- T:go("F1C2 F2C2 F1R1", false, 0, false, preferredBlock) -- far side solid row
- T:go("F1C2 F1R1U1", false, 0, false, preferredBlock) -- bottom side solid row
- end
- --[[
- clsTurtle methods:
- clsTurtle.place(self, blockType, damageNo, direction, leaveExisting)
- clsTurtle.go(self, path, useTorch, torchInterval, leaveExisting, preferredBlock)
- ]]
- -- remove 1 stack stone from chest
- local preferredBlock = lib.getStone("down", 1) -- use this as default building block
- if stage == 1 then
- -- build base floor
- --T:go("R2F2R1F3R1", false, 0, false, preferredBlock)
- T:go("R2F1C2R1F1C2F1C2F1C2R1", false, 0, false, preferredBlock)
- for i = 1, 2 do
- lib.baseRun(preferredBlock, 8, "R1F1R1")
- lib.baseRun(preferredBlock, 8, "L1F1L1")
- lib.baseRun(preferredBlock, 8, "R1F4R1")
- end
- -- move back to centre, build water source, with soul sand at base of first source
- --T:go("R1F3L1C2F1C2F2D1", false, 0, false, preferredBlock) --just behind chest, 1 below ground level
- T:go("R1F3L1F2C2F1D1", false, 0, false, preferredBlock) --1 block behind chest, 1 below ground level
- T:place("minecraft:soul_sand", -1, "down", false) -- over block 1 of water source
- T:go("F1C2F1C2", false, 0, false, preferredBlock) -- over block 2 of water source
- T:go("F1C2U1C2", false, 0, false, preferredBlock) -- over block 4 of water source
- T:go("F1C2F1C2R2F5R2", false, 0, false, preferredBlock) -- over block 1 of water source
- T:placeWater("down")
- T:forward(2) -- over block 3 of water source
- T:placeWater("down")
- turtle.back() -- over block 2 of water source
- T:getWater("down")
- T:go("F2D1R2C2") -- over block 4 of water source
- T:go("U1", false, 0, false, preferredBlock)
- T:placeWater("down")
- T:forward(4)
- lib.stackBuckets() -- put all buckets in same slot
- T:dropItem("minecraft:dirt", "up", 0) -- drop dirt up: clsTurtle.dropItem(self, item, direction, keepAmount)
- preferredBlock = lib.getStone("down", 6)
- T:go("R1F2R1U1") -- move to start position
- for i = 1, 2 do
- -- build first level of tower: 2 x outside run, 2 x sign run
- lib.outsideRun(preferredBlock)
- if i == 1 then -- place door
- T:go("L1F1L1F1L1D1")
- T:place("door", -1, "forward", false)
- T:go("U1L1F1R1F1L1")
- end
- T:go("R1F1R1")
- lib.signRun(preferredBlock, "Pint size\nzombies\nProhibited")
- T:go("L1F1L1C2", false, 0, false, preferredBlock)
- T:forward(4) -- miss out centre block
- T:place(preferredBlock, -1, "down", false)
- T:go("R1F1R1")
- lib.signRun(preferredBlock, "Pint size\nzombies\nProhibited")
- T:go("L1F1L1")
- lib.outsideRun(preferredBlock)
- if i == 1 then -- layer 1
- T:go("R1F1R1F1R1D1") -- place door
- T:place("door", -1, "forward", false)
- T:go("U1 R1F1 L1F5 L1U1 F2D1 F2R2 U1") -- go over door
- else -- layer 2
- T:go("L1F5L1F6R2U1") -- over corner of lower platform
- end
- end
- for i = 1, 2 do -- build both sides of platform, leave centre missing
- lib.baseRun(preferredBlock, 8, "R1F1R1")
- lib.baseRun(preferredBlock, 8, "L1F1L1")
- lib.baseRun(preferredBlock, 8, "R1F4R1")
- end
- T:go("R1F3L1C2F1C2F1C2F4C2F1C2F1C2", false, 0, false, preferredBlock) --fill in centre row
- --T:go("R2F6R1F1R1U1") -- go to start of tower base
- T:go("R2F7R2D3") -- go to start on top of chest
- T:sortInventory()
- elseif stage == 2 then
- -- start on top of chest, should have sufficient stone in inventory
- T:go("U3L1F1R1F1U1") -- go to start of tower base
- for i = 1, 7 do -- build 14 block high tower
- lib.buildSection(preferredBlock, false)
- lib.buildSection(preferredBlock, true)
- end
- T:go("R2F4R1F4R1", false, 0, false, preferredBlock) -- build upper platform (154 blocks remaining)
- for i = 1, 2 do -- build both sides of upper platform, leave centre missing
- lib.baseRun(preferredBlock, 12, "R1F1R1")
- lib.baseRun(preferredBlock, 12, "L1F1L1")
- lib.baseRun(preferredBlock, 12, "R1F1R1")
- lib.baseRun(preferredBlock, 12, "L1F1L1")
- lib.baseRun(preferredBlock, 12, "R1F6R1")
- end
- T:go("R1F5 L1C2 F1C2 F1C2 F1C2 F1C2 F4C2 F1C2 F1C2 F1C2 F1C2 ", false, 0, false, preferredBlock) --fill in centre row
- T:go("R2F5") -- return to drop area
- lib.buildLift(preferredBlock) -- build bubble lift
- T:go("F3R1F1R1U1") -- go to start of tower base
- T:go("C2F4 C2R1F1R1", false, 0, false, preferredBlock) -- left side layer 21
- T:go("F2C2 F2C2 L1F1L1", false, 0, false, preferredBlock) -- centre layer 21
- T:go("C2F4 C2R2U1", false, 0, false, preferredBlock) -- right side layer 21
- T:go("C2F4 C2R1F1R1", false, 0, false, preferredBlock) -- right side layer 22
- T:place("fence", -1, "down", false) -- fence centre of bottom side layer 22
- T:go("F2C2 F2L1F1L1", false, 0, false, preferredBlock) -- centre layer 22
- T:go("C2F4 C2R2F2L1F1R2D2", false, 0, false, preferredBlock) --ready to place ladder
- T:place("ladder", -1, "forward", false)
- T:up(1)
- T:place("ladder", -1, "forward", false)
- --T:go("U2R1F4R1F1R1") -- ready to make upper part of tower base
- T:go("U2R1F4R1F1R1") -- ready to make upper part of tower base
- for i = 1, 2 do -- build both sides of platform, leave centre missing
- lib.baseRun(preferredBlock, 8, "R1F1R1")
- lib.baseRun(preferredBlock, 8, "L1F1L1")
- lib.baseRun(preferredBlock, 8, "R1F4R1")
- end
- T:go("R1F3 L1C2 F1C2 F1C2 F1", false, 0, false, preferredBlock) --fill in centre row
- T:place("minecraft:soul_sand", -1, "down", false)
- T:go("F1C2 F2C2 F1C2 F1C2", false, 0, false, preferredBlock)
- T:go("R2F6R1F1R1U1") -- go to start of tower base
- -- build 2 levels, finish signs and ladders
- T:go("C2F2 R1D2 U1", false, 0, false, preferredBlock)
- T:place("ladder", -1, "down", false)
- T:turnRight(1)
- T:place("sign", -1, "forward", false, "UP\n^\n|\n|")
- T:go("U1R2F2C2 R1F2C2 R1", false, 0, false, preferredBlock) --top right corner
- T:go("F4C2B2D1", false, 0, false, preferredBlock)
- T:place("sign", -1, "forward", false, "UP\n^\n|\n|")
- T:go("U1F2R1F1C2F1R1U1", false, 0, false, preferredBlock) --ready for second level
- T:go("C2F2 R2D1", false, 0, false, preferredBlock)
- T:place("sign", -1, "forward", false, "UP\n^\n|\n|")
- T:go("U1R2F2C2R1", false, 0, false, preferredBlock) --top left corner
- T:go("F1R1C2F4C2", false, 0, false, preferredBlock) --mid bottom row
- T:go("L1F1L1C2", false, 0, false, preferredBlock) -- bottom right corner
- T:go("F2R2D1", false, 0, false, preferredBlock)
- T:place("sign", -1, "forward", false, "UP\n^\n|\n|")
- T:go("U1R2F2C2", false, 0, false, preferredBlock) -- top right corner
- -- return to chest
- T:go("L1F1L1 F5D23R2", false, 0, false, preferredBlock) -- return to chest
- T:sortInventory()
- elseif stage == 3 then
- --[[ move to top of structure
- | 4 |
- |3 5|
- | X |
- |2 6|
- | 1 |
- ]]
- local towerHeight = 128 -- even no only suggest 128
- while turtle.detect() do
- turtle.up()
- end
- T:go("F1U1", false, 0, false, preferredBlock) -- return to finish tower
- for i = 1, towerHeight do -- 1
- T:go("C2U1", false, 0, false, preferredBlock)
- end
- T:go("F1L1F1R1D2")
- while turtle.down() do -- 2
- T:fillVoid("up", {preferredBlock})
- end
- T:go("F1R2C1R2F1D1", false, 0, false, preferredBlock)
- for i = 1, towerHeight / 2 do -- 3
- T:go("U2C2", false, 0, false, preferredBlock)
- end
- T:go("U1F1R1F1R1D1", false, 0, false, preferredBlock) -- back of tower facing front
- local deviate = false
- while turtle.down() do -- 4
- T:place("fence", -1, "up", false)
- if turtle.down() then
- T:fillVoid("up", {preferredBlock})
- else
- T:go("F1R2C1R1F1R1D1", false, 0, false, preferredBlock)
- deviate = true
- break
- end
- end
- if not deviate then
- T:go("F1L1F1R1D1", false, 0, false, preferredBlock)
- end
- for i = 1, towerHeight / 2 do -- 5
- T:go("U2C2", false, 0, false, preferredBlock)
- end
- T:go("F2R2", false, 0, false, preferredBlock) -- facing back of tower
- while turtle.down() do -- 6
- T:fillVoid("up", {preferredBlock}) --layer 129
- end
- T:go("F1L2C1U"..towerHeight)
- T:go("F4R1F3R1U1", false, 0, false, preferredBlock)
- -- add small platform at the top
- lib.baseRun(preferredBlock, 8, "R1F1R1")
- lib.baseRun(preferredBlock, 8, "L1F3L1")
- lib.baseRun(preferredBlock, 8, "L1F1L1")
- lib.baseRun(preferredBlock, 8, "R1F1R1")
- T:go("C2 F1C2 F1C2 F4C2 F1C2 F1C2 R2F3", false, 0, false, preferredBlock) --fill in centre row
- lib.buildLift(preferredBlock) -- build bubble lift
- end
- return {}
- end
- local function createFarm(R, extend) -- 31
- -- if extend ~= nil then this has been called from createFarmExtension()
- -- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
- local lib = {}
- function lib.addWaterSource(R, pattern, storage)
- -- pattern = {"d","c","c","d"} t = place crafting instead of dirt
- -- place(self, blockType, damageNo, direction, leaveExisting, signText)
- T:go("D1x2C2", false, 0, false, R.useBlockType)
- for i = 1, 4 do
- T:dig("forward")
- if pattern[i] == "d" then
- T:place("dirt", -1, "forward", false)
- elseif pattern[i] == "t" then
- --if not T:place("minecraft:crafting_table", -1, "forward", false) then
- if T:place(storage, -1, "forward", false) then
- if T:dropItem("crafting", "forward", 0) then
- print("Crafting table -> buried storage")
- end
- else
- T:place("dirt", -1, "forward", false) -- dirt if no storage available
- end
- else
- T:place(R.useBlockType, -1, "forward", false)
- end
- T:turnRight(1)
- end
- T:up(1)
- T:placeWater("down")
- end
- function lib.placeDirt(count, atCurrent)
- if atCurrent then
- local blockType = T:getBlockType("down")
- if blockType:find("dirt") == nil and blockType:find("grass_block") == nil then
- T:place("dirt", -1, "down", false)
- end
- end
- for i = 1, count do
- T:forward(1)
- T:dig("up")
- local blockType = T:getBlockType("down")
- if blockType:find("dirt") == nil and blockType:find("grass_block") == nil then
- T:place("dirt", -1, "down", false)
- end
- end
- end
- function lib.placeStorage(storage, storageBackup)
- T:dig("down")
- if not T:place(storage, -1, "down", false) then-- place barrel/chest below
- T:place(storageBackup, -1, "down", false) -- place chest below
- end
- end
- -- extend "", "right" or "forward". only adds a single new farm.
- -- right adds farm and checks for existing front extensions, dealt with separately
- -- clsTurtle.place(blockType, damageNo, direction, leaveExisting)
- if extend == nil then
- extend = ""
- end
- local blockType = ""
- -- extend = "right": placed on cobble corner of existing farm facing right side
- -- extend = "front": placed on cobble corner of existing farm facing front
- -- else placed on ground at corner of potential new farm facing front
- local storage, storageBackup = utils.setStorageOptions()
- -- step 1 dig ditch round perimeter wall
- if extend == "right" then
- -- move to front corner ground ready for ditch
- T:go("F1L1F12D1R1", false, 0, false, R.useBlockType)
- -- cut ditch round new farm extension
- for i = 1, 12 do
- T:go("x0F1")
- end
- T:go("R1x0")
- for i = 1, 13 do
- T:go("x0F1")
- end
- T:go("R1x0")
- -- now at lower right corner. if extension below, do not cut ditch
- blockType = T:getBlockType("forward")
- if blockType:find("stone") ~= nil then -- already a farm extension on left side
- -- return to start for adding chests and walls
- T:go("U1R1F1L1F12", false, 0, false, R.useBlockType)
- else -- finish ditch
- for i = 1, 12 do
- T:go("x0F1")
- end
- T:go("R1U1F1") -- on corner of new extension
- end
- elseif extend == "forward" then
- T:go("L1F2R1D1", false, 0, false, R.useBlockType)
- -- cut ditch round new farm extension
- for i = 1, 12 do
- T:go("x0F1", false, 0, false, R.useBlockType)
- end
- T:go("R1x0", false, 0, false, R.useBlockType)
- for i = 1, 13 do
- T:go("x0F1", false, 0, false, R.useBlockType)
- end
- T:go("R1x0", false, 0, false, R.useBlockType)
- for i = 1, 11 do
- T:go("x0F1", false, 0, false, R.useBlockType)
- end
- T:go("U1x0F1R1F12R1", false, 0, false, R.useBlockType) -- on corner of new extension
- else -- new farm. cut a groove round the entire farm base
- -- move to left side of intended wall
- T:go("L1F1x0R1", false, 0, false, R.useBlockType)
- for j = 1, 4 do
- for i = 1, 12 do
- T:go("x0F1", false, 0, false, R.useBlockType)
- end
- T:go("R1x0F1", false, 0, false, R.useBlockType)
- end
- T:go("R1F1L1U1", false, 0, false, R.useBlockType)
- end
- -- stage 2 place sapling and double barrel/chest
- T:dig("down") --remove cobble if present
- T:place("dirt", -1, "down", false)
- T:go("F1R2")
- T:place("sapling", -1, "forward", false) -- plant sapling
- T:go("L1")
- lib.placeStorage(storage, storageBackup)
- T:go("L1F1R1")
- lib.placeStorage(storage, storageBackup)
- T:turnLeft(1)
- if extend == "right" then -- cobble wall exists so go forward to its end
- T:forward(9)
- else -- new farm or extend forward
- for i = 1, 9 do -- complete left wall to end of farm
- T:go("F1x0x2C2", false, 0, false, R.useBlockType)
- end
- end
- T:go("R1F1 R1x0 x2C2 F1D1", false, 0, false, R.useBlockType)-- turn round ready for first dirt col
- lib.addWaterSource(R, {"d","c","c","d"}, storage) -- water at top of farm
- lib.placeDirt(9, false) -- place dirt back to start
- lib.addWaterSource(R, {"c","c","t","d"}, storage) -- water source next to chests, includes crafting table
- T:go("U1F1R2")
- if T:getBlockType("down"):find(storage) == nil and T:getBlockType("down"):find(storageBackup) == nil then
- lib.placeStorage(storage, storageBackup)
- end
- T:go("R1F1L1")
- if T:getBlockType("down"):find(storage) == nil and T:getBlockType("down"):find(storageBackup) == nil then
- lib.placeStorage(storage, storageBackup)
- end
- T:go("F1D1")
- lib.placeDirt(9, true)
- local turn = "R"
- for i = 1, 7 do
- T:go("F1U1x0C2"..turn.."1F1"..turn.."1x0x2C2F1D1", false, 0, false, R.useBlockType)
- lib.placeDirt(9, true)
- if turn == "R" then
- turn = "L"
- else
- turn = "R"
- end
- end
- T:go("F1U1x0C2"..turn.."1F1"..turn.."1x0x2C2F1D1", false, 0, false, R.useBlockType)
- lib.addWaterSource(R, {"d","c","c","d"}, storage)
- lib.placeDirt(9, false)
- lib.addWaterSource(R, {"c","c","d","d"}, storage)
- T:go("F1U1R1C2x0F1x0x2C2R1", false, 0, false, R.useBlockType)
- for i = 1, 11 do
- T:go("F1x0x2C2", false, 0, false, R.useBlockType)
- end
- -- add barrel/chest to any existing farm extension to the right
- T:go("L1F1L1")
- if T:getBlockType("down"):find("stone") == nil then -- farm extension already exists to right
- lib.placeStorage(storage, storageBackup)
- end
- T:go("L1F11")
- return {"Modular farm completed"}
- end
- local function createFarmExtension(R) -- 32
- -- assume inventory contains 4 chests, 64 cobble, 128 dirt, 4 water, 1 sapling
- -- check position by rotating to face tree/sapling
- local doContinue = true
- local treePresent = false
- local extend = "right" -- default
- if R.subChoice == 1 then
- extend = "forward"
- end
- local storage, storageBackup = utils.setStorageOptions()
- local blockType = T:getBlockType("down")
- if blockType:find(storage) == nil and blockType:find(storageBackup) == nil then
- return
- {
- "Barrel or chest not present below\n",
- "Unable to calculate position",
- "Move me next to/front of the tree/sapling",
- "lower left corner of the existing farm."
- }
- else
- for i = 1, 4 do
- blockType = T:getBlockType("forward")
- if blockType:find("log") ~= nil or blockType:find("sapling") ~= nil then
- treePresent = true
- break
- end
- T:turnRight()
- end
- if not treePresent then
- return
- {
- "Unable to locate tree or sapling",
- "Plant a sapling on the lower left",
- "corner of the farm, or move me there"
- }
- end
- end
- if doContinue then -- facing tree. check if on front or l side of farm
- if extend == "forward" then
- T:go("R1F11") -- to other side of farm. may be stone or barrel/chest below
- blockType = T:getBlockType("down")
- if blockType:find(storage) ~= nil or blockType:find(storageBackup) ~= nil then
- doContinue = false
- end
- else
- T:go("R2F9") -- to right of farm, may be sapling/tree in front
- blockType = T:getBlockType("forward")
- if blockType:find("log") ~= nil or blockType:find("sapling") ~= nil then
- doContinue = false
- end
- end
- if doContinue then -- extend farm.
- createFarm(R, extend)
- else
- return
- {
- "This farm has already been extended",
- "Move me next to/front of the tree / sapling",
- "of the last extension in this direction."
- }
- end
- end
- return {"Modular crop farm extended"}
- end
- local function createFloorCeiling(R) -- 79 size integer 1 to 4
- --[[
- R.up = true for ceiling
- R.down = true for floor
- R.height = 0 for normal
- R.height combined with R.up/R.down used for remote access
- ]]
- local useBlock = T:getSlotContains(1)
- local waterPresent = false
- if R.useBlockType ~= "" then
- useBlock = R.useBlockType
- end
- print("Using ".. useBlock)
- local direction = "down"
- if R.up then
- direction = "up"
- end
- if R.height > 0 then -- remote placing. go up/down R.height first
- R.silent = true
- local depth = 0
- if R.down then -- floor could be under water
- while turtle.down() do
- depth = depth + 1
- end
- elseif R.up then
- while turtle.up() do
- depth = depth + 1
- if depth > R.height + 3 then
- break
- end
- end
- end
- if not(R.height - depth <= 2 or depth - R.height <= 2) then
- T:up(depth)
- return {"Measured depth/height of "..depth.." > setting: "..R.height}
- end
- -- not returned so depth acceptable
- end
- -- check if block above/below
- local blockBelow = turtle.detectDown()
- local blockAbove = turtle.detectUp()
- if R.subChoice == 2 then -- New floor over existing
- -- if no block below, assume in correct position and continue
- -- else move up 1 and continue
- if blockBelow then T:up(1) end
- elseif R.subChoice == 4 then -- New ceiling under existing
- -- if no block above, assume in correct position and continue
- -- else move down 1 and continue
- if blockAbove then T:down(1) end
- end
- local evenWidth = false
- local evenHeight = false
- local loopWidth
- -- go(path, useTorch, torchInterval, leaveExisting)
- if R.width % 2 == 0 then
- evenWidth = true
- loopWidth = R.width / 2
- else
- loopWidth = math.ceil(R.width / 2)
- end
- if R.length % 2 == 0 then
- evenHeight = true
- end
- -- if R.width is even no, then complete the up/down run
- -- if R.width odd no then finish at top of up run and reverse
- for x = 1, loopWidth do
- -- Clear first column (up)
- local tAvailable = T:getStock(useBlock, -1)
- if tAvailable.total < R.length and not R.silent then
- return {"Insufficient resources to complete current row"}
- end
- for y = 1, R.length do
- local blockType = T:getBlockType("forward")
- if not waterPresent then
- if blockType:find("lava") ~= nil or blockType:find("water") ~= nil then
- waterPresent = true
- end
- end
- T:place(useBlock, -1, direction, false) -- leaveExisting = false
- if y < R.length then
- T:go("F1", false, 0, false)
- end
- end
- -- clear second column (down)
- if x < loopWidth or (x == loopWidth and evenWidth) then -- go down if on R.width 2,4,6,8 etc
- T:go("R1F1R1", false,0,false)
- tAvailable = T:getStock(useBlock, -1)
- if tAvailable.total < R.length and not R.silent then
- return {"Insufficient resources to complete current row"}
- end
- for y = 1, R.length do
- T:place(useBlock, -1, direction, false) -- leaveExisting = false
- if y < R.length then
- T:go("F1", false, 0, false)
- end
- end
- if x < loopWidth then
- T:go("L1F1L1", false,0,false)
- else
- T:turnRight(1)
- T:forward(R.width - 1)
- T:turnRight(1)
- end
- else -- equals R.width but is 1,3,5,7 etc
- T:turnLeft(2) --turn round 180
- T:forward(R.length - 1)
- T:turnRight(1)
- T:forward(R.width - 1)
- T:turnRight(1)
- end
- end
- if waterPresent then
- return {"water or lava found"}
- end
- return {""}
- end
- local function createIceCanal(R) -- 55
- --[[
- R.subChoice =
- 1: move right into canal, build left towpath
- 2: build left towpath
- 3: build right towpath
- 4: move left into canal, build right towpath
- 5/8: clear path 3 blocks high, place slabs/torches
- 6/7: build alternating ice road / create 3 block high air gap (2 over water)
- ]]
- local oTurn = "R"
- if R.side == "R" then
- oTurn = "L"
- end
- local lib = {}
- function lib.convertTowpath(R)
- -- only used to convert existing water canal, so assume towpath already present
- -- starting position 1 block above existing towpath
- for i = 1, R.length do
- if turtle.detectDown() then -- eg existing torch
- T:dig("down")
- end
- local placeSlab = true
- if R.torchInterval > 0 then -- place torches
- if i == 1 or i % R.torchInterval == 0 then -- ready to place torch
- --go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
- T:go("C2x0", false, 0, false, R.useBlockType)-- place solid block below
- T:go("F1R2x0")
- T:place("torch", 0, "forward") -- place torch, move forward
- T:turnRight(2) -- turn round
- placeSlab = false
- end
- end
- if placeSlab then
- T:dig("up")
- if not T:place("slab", 0, "down") then -- break if out of slabs
- break
- end
- if i < R.length then
- T:forward(1) -- move forward
- end
- end
- end
- end
- function lib.iceCanalTowpath(R)
- -- move forward placing slabs along the way. If existing water canal, ceiling will be raised by 1 block
- local torchInterval = 0
- local placeIce = true
- for i = 1, R.length do
- local addTorch = false
- if R.torchInterval > 0 then
- if i == 1 then addTorch = true end
- if torchInterval >= R.torchInterval then
- addTorch = true
- torchInterval = 0
- end
- end
- lib.iceCanalEdge(R, addTorch, i, placeIce)
- torchInterval = torchInterval + 1
- placeIce = not placeIce
- end
- T:go(oTurn.."1")
- end
- function lib.iceCanalEdge(R, addTorch, numBlocks, placeIce)
- -- starting position facing canal side
- local blockType = T:getBlockType("forward") -- ? air / slab / other
- local isWater, isSource, isIce = T:isWater("down") -- water / ice below
- if blockType:find("slab") == nil then -- add slab
- if addTorch then -- check if torch needed
- -- T:place(blockType, damageNo, direction, leaveExisting, signText)
- if not T:place("stone", -1, "forward", false) then
- T:checkInventoryForItem({"stone"}, {math.ceil(R.length / R.torchInterval)}, true)
- end
- T:go("U1x1 U1x1 D1") -- water level to 2 above water level
- if T:getItemSlot("minecraft:torch", -1) > 0 then
- T:place("torch", -1, "forward", false)
- end
- T:down(1) -- back to above water level
- if not isIce then -- break block below if NOT ice
- T:dig("down")
- end
- else
- if not T:place("slab", -1, "forward", false) then
- T:checkInventoryForItem({"slab"}, {R.length - numBlocks}, true)
- end
- if not isSource then -- NOT on water, so dig above
- T:go("U1x1 U1x1 D2")
- end
- if not isIce and not isSource then
- T:dig("down")
- end
- end
- else -- slab already on side
- if addTorch then -- check if torch needed
- T:dig("forward")
- if not T:place("stone", -1, "forward", false) then
- T:checkInventoryForItem({"stone"}, {math.ceil(R.length / R.torchInterval)}, true)
- end
- T:go("U1x1 U1x1 D1") -- water level to 2 above water level
- if T:getItemSlot("minecraft:torch", -1) > 0 then
- T:place("torch", -1, "forward", false)
- end
- T:down(1) -- back to above water level
- if not isIce then -- break block below if NOT ice
- T:dig("down")
- end
- end
- end
- if R.data == "ice" and placeIce and not isIce then -- R.data = "ice", placeIce = true, not already ice present
- T:place("ice", -1, "down", true)
- end
- if numBlocks < R.length then
- T:go(oTurn.."1F1"..R.side.."1")
- end
- end
- function lib.convertIcepath(length)
- -- use only for placing ice to convert a water canal
- -- place ice on alternate blocks until length reached or run out of ice
- local placeIce = true
- for i = 1, length do
- if T:getBlockType("down"):find("ice") == nil then -- no ice below
- T:dig("down") -- remove any existing block
- if placeIce then
- if not T:place("ice", -1, "down", true) then -- out of ice
- break
- end
- if i == length - 1 then
- break
- end
- end
- else -- ice already below
- placeIce = true
- end
- T:go("U1x0 D1F1")
- placeIce = not placeIce -- reverse action
- end
- end
- function lib.convertToAir(length)
- -- use only for converting a water canal. start at ground level
- -- dig up/down/forward to clear space
- for i = 1, length + 1 do
- T:go("U1x0D1")
- if i < length + 1 then
- T:go("x2F1")
- else
- T:dig("down")
- end
- end
- end
- function lib.initialise(R)
- if R.subChoice == 1 or R.subChoice == 4 then
- local blockType = T:getBlockType("down") -- ? at ground/water level or on top of existing slab
- if blockType:find("slab") ~= nil then -- slab already present
- T:go(oTurn.."1F1D1"..R.side.."2") -- move right/left forward, down onto ice canal top, face canal wall
- elseif blockType:find("torch") ~= nil then
- T:go(oTurn.."1F1D2"..R.side.."2") -- move right/left forward, down onto ice canal top, face canal wall
- else -- assume on ground / water level
- T:go(oTurn.."1F1"..R.side.."2") -- move right/left forward onto ice canal top, face canal wall
- end
- else
- if T:isWater("forward") then -- player put turtle inside canal water
- T:up(1)
- end
- T:go(R.side.."1") -- face canal wall
- end
- end
- if R.length == 0 then R.length = 1024 end
- if R.subChoice <= 4 then -- towpath 1,2,3,4
- lib.initialise(R) -- reposition
- lib.iceCanalTowpath(R) -- build towpath
- elseif R.subChoice == 5 or R.subChoice == 8 then -- assume placed on towpath
- if T:getBlockType("down"):find("slab") ~= nil then -- slab already present
- T:go("F1")
- else
- T:up(1)
- end
- lib.convertTowpath(R)
- elseif R.subChoice == 6 or R.subChoice == 7 then
- if R.data == "ice" then -- assume placed on existing ice or initial ice position
- lib.convertIcepath(R.length)-- place ice
- else -- assume placed on empty path
- lib.convertToAir(R.length) -- clear 3 high area
- end
- end
- return {}
- end
- local function createLadder(R) -- 12
- -- createLadder(R.data ="bedrock", R.height = 70, R.depth = -48)
- -- go(path, useTorch, torchInterval, leaveExisting)
- -- place(blockType, damageNo, direction, leaveExisting)
- local lib = {}
- function lib.placeLadder(direction, ledge, i, height)
- -- 1 check both sides and behind
- local fluid = false
- local block = T:isWaterOrLava("forward", ledge)
- if block:find("water") ~= nil or block:find("lava") ~= nil then
- --[[ surround 2 block shaft with blocks ]]
- T:go("R1C1 R1C1 R1C1 R1F1 L1C1 R1C1 R1C1 R1C1F1 R2C1 x1")
- else
- --[[ no water/lava so prepare ladder site]]
- T:go("F1 L1C1 R1C1 R1C1 L1B1", false, 0, true)
- end
- if not T:place("ladder", -1, "forward", false) then
- T:checkInventoryForItem({"ladder"}, {height - i}, false)
- end
- -- 3 check if ledge, torch
- if ledge == 0 and i > 1 then -- place block above unless new ladder
- T:place("common", -1, direction, false) -- any common block
- elseif ledge == 1 then
- T:place("minecraft:torch", -1, direction, false)
- elseif ledge == 2 then
- ledge = -1
- end
- return ledge
- end
- local retValue = {}
- local ledge = 0
- local height = math.abs(R.depth - R.height) --height of ladder
- local blockType = T:getBlockType("forward")
- if R.up then -- create ladder from current level to height specified
- for i = 1, height do -- go up, place ladder as you go
- ledge = lib.placeLadder("down", ledge, i, height) -- ladder placed forward, stone ledge for torch placed down
- if i < height then
- T:up(1)
- ledge = ledge + 1
- end
- end
- else -- R.down = true: ladder towards bedrock
- local success = true
- local numBlocks, errorMsg = 0, ""
- T:down(1)
- for i = 1, height do -- go down, place ladder as you go
- ledge = lib.placeLadder("up", ledge, i, heigt) -- ladder placed forward, stone torch placed up
- --success, blocksMoved, errorMsg, blockType = clsTurtle.down(self, steps, getBlockType)
- if i < height then
- success, numBlocks, errorMsg, blockType = T:down(1, true) -- true = return blockType
- ledge = ledge + 1
- end
- -- if looking for stronghold then check for stone_bricks
- if blockType:find("stone_bricks") ~= nil then
- table.insert(retValue, "Stronghold discovered")
- break -- stop descent at stronghold
- end
- end
- -- if user requested shelter create chamber at this level
- if R.data == "chamber" then -- user has chosen to build a chamber
- table.insert(retValue, "Shelter constucted at level".. R.depth)
- if blockType:find("bedrock") ~= nil then
- T:findBedrockTop(0) -- test to check if on safe level immediately above tallest bedrock
- end
- -- In shaft, facing start direction, on lowest safe level
- -- create a square space round shaft base, end facing original shaft, 1 space back
- T:go("L1n1 R1n3 R1n2 R1n3 R1n1", false, 0, true)
- T:go("U1Q1 R1Q3 R1Q2 R1Q3 R1Q1 R1D1", false, 0, true)
- end
- end
- return retValue
- end
- local function createLadderToWater(R) -- 86
- -- go down to water/lava with alternaate solid/open layers
- -- create a working area at the base
- -- Return to surface facing towards player placing ladders
- local inAir = true
- local numBlocks, errorMsg = 0, ""
- local height = 2
- local blockType = T:getBlockType("down")
- if blockType ~= "" then -- not over air
- T:forward(1)
- end
- T:go("R2D1") -- face player, go down 2
- while inAir do --success = false when hits water/lava
- blockType = T:isWaterOrLava("down")
- if blockType:find("water") ~= nil or blockType:find("lava") ~= nil then
- inAir = false
- end
- T:go("C1R1 C1R2 C1R1", false, 0, false) -- surround front and sides with cobble
- if inAir then
- T:down(1)
- height = height + 1
- end
- T:place("ladder", 0, "up")
- end
- -- In shaft, facing opposite start direction, on water/lava, ladders above
- T:go("C2", false, 0, false)
- utils.goBack(1)
- T:place("ladder", 0, "forward")
- T:up(3)
- height = height - 3
- for i = 1, height do
- if i < height then
- T:go("C2U1", false, 0, false)
- else
- T:go("C2", false, 0, false)
- end
- end
- return {}
- end
- local function createMine() -- 11
- -- go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
- T:clear()
- T:go("m32U1R2M16", true, 8, true) -- mine ground level, go up, reverse and mine ceiling to mid-point
- T:go("U2D2") -- create space for chest
- T:place("minecraft:chest", -1, "up", false)
- T:emptyTrash("up")
- T:go("D1R1m16U1R2M16", true, 8, true) -- mine floor/ceiling of right side branch
- T:emptyTrash("up")
- T:go("D1m16U1R2M16", true, 8, true) -- mine floor/ceiling of left side branch
- T:emptyTrash("up")
- T:go("L1M15F1R1D1", true, 8, true) -- mine ceiling of entry corridor, turn right
- T:go("F1x0 F1x0 n14 R1n32 R1n32 R1n32 R1n14 F1x0 F1U1", true, 8, true)-- mine floor of 36 x 36 square corridor
- T:go("R1F16R2") --return to centre
- T:emptyTrash("up")
- T:go("F16R1") --return to entry shaft
- T:go("F2Q14R1Q32R1Q32R1Q32R1Q14F2R1", true, 8, true) --mine ceiling of 36x36 square corridor. return to entry shaft + 1
- T:go("F16R2") --return to centre
- T:emptyTrash("up")
- -- get rid of any remaining torches
- while T:getItemSlot("minecraft:torch", -1) > 0 do
- turtle.select(T:getItemSlot("minecraft:torch", -1))
- turtle.dropUp()
- end
- T:go("F16R1F1R1") --return to shaft + 1
- for i = 1, 8 do
- T:go("N32L1F1L1", true, 8, true)
- T:go("N16L1F"..(i * 2).."R2", true, 8, true)
- T:emptyTrash("up")
- if i < 8 then
- T:go("F"..(i * 2).."L1N16R1F1R1", true, 8, true)
- else
- T:go("F"..(i * 2).."L1N16L1", true, 8, true)
- end
- end
- T:go("F17L1") -- close gap in wall, return to ladder + 1
- for i = 1, 8 do
- T:go("N32R1F1R1", true, 8, true)
- T:go("N16R1F"..(i * 2).."R2", true, 8, true)
- T:emptyTrash("up")
- if i < 8 then
- T:go("F"..(i * 2).."R1N16L1F1L1", true, 8, true)
- else
- T:go("F"..(i * 2).."R1N16R1", true, 8, true)
- end
- end
- T:go("F16R1")
- T:clear()
- return{"Mining operation complete"}
- end
- local function createMobFarmCube(R) -- 61, 62
- --[[
- Part 1 / 3 Mob Spawner Farm
- blaze = true: blaze spawner in nether
- R.subChoice is set to:
- 1 = on top of spawner
- 2 = line of sight
- 3 = room below
- blaze = false: overworld mob spawner
- R.subChoice is set to:
- 1 = on top of spawner
- 2 = bottom left corner
- 3 = top left corner
- 4 = bottom right, corner
- 5 = top right corner
- R.width / R.length set by player (external size)
- ]]
- local blaze = true
- if R.data == "spawner" or R.data == "chest" then
- blaze = false
- end
- local continue = false
- if R.data == "restart" then
- continue = true
- end
- R.direction = "clock" -- starting on right side
- if not blaze then
- print("R.width: "..tostring(R.width))
- R.width = R.width - 2 -- internal width
- R.length = R.length - 2 -- internal length
- if R.subChoice == 2 or R.subChoice == 3 then
- R.direction = "anticlock"
- end
- end
- -- R.data allows for 2-part operation "blaze" = main cube, "restart" = killzone
- T:clear()
- local lib = {}
- function lib.floorSection(length)
- for i = 1, length do -- starts on top left corner
- T:go("C2")
- if i < length then
- T:forward(1)
- else
- T:go("R1F1")
- end
- end
- end
- function lib.wallSection(blaze)
- blaze = blaze or false
- for i = 1, 4 do
- for j = 1, 11 do
- if blaze then
- T:place("slab", 0, "up", false)
- T:go("C2", false, 0, false)
- else
- T:go("C0C2", false, 0, false)
- end
- if j < 11 then
- T:forward(1)
- T:go("R2C1L2", false, 0, false)
- else
- T:turnRight(1)
- end
- end
- end
- end
- function lib.ceiling(blaze)
- -- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
- -- all outer walls complete, now for remaining 9x9 ceiling
- blaze = blaze or false
- for i = 1, 9 do
- for j = 1, 9 do
- if blaze then
- T:place("slab", 0, "up", false)
- T:dig("down")
- else
- T:go("C0x2", false, 0, true)
- end
- if j < 9 then
- T:forward(1)
- else -- end of length
- local place = false
- if i%2 == 1 then -- odd numbers 1,3,5,7,9
- if i < 9 then
- place = true
- T:go("R1F1 R1")
- end
- else
- place = true
- T:go("L1F1 L1")
- end
- if place then
- if blaze then
- T:place("slab", 0, "up", false)
- T:dig("down")
- else
- T:go("C0x2", false, 0, true)
- end
- end
- end
- end
- end
- end
- function lib.clearWall(length)
- for i = 1, 4 do
- for j = 1, length do
- if j < length then
- T:go("x0x2F1")
- else
- T:go("x0x2R1")
- end
- end
- end
- end
- function lib.isSpawner()
- local blockType = T:getBlockType("down")
- if blockType:find("spawner") ~= nil then
- return true, "top"
- end
- blockType = T:getBlockType("up")
- if blockType:find("spawner") ~= nil then
- return true, "bottom"
- end
- blockType = T:getBlockType("forward")
- if blockType:find("spawner") ~= nil then
- return true, "forward"
- end
- return false, ""
- end
- function lib.placeFloor(width, length, blockType)
- -- T:place(blockType, damageNo, direction, leaveExisting, signText)
- for i = 1, width do
- for j = 1, length do
- T:place(blockType, -1, "down", false)
- if j < length then
- T:forward(1)
- else
- if i%2 == 1 then -- odd numbers 1,3,5,7,9
- if i < width then
- T:go("R1F1R1", false, 0, true)
- end
- else
- T:go("L1F1L1", false, 0, true)
- end
- end
- end
- end
- end
- function lib.searchStrip(distance)
- --go forward until hit either a wall or a chest
- local blocks = 1
- print("Searching strip, distance = "..distance)
- while blocks < distance do --max travel is external width/length
- if turtle.forward() then
- blocks = blocks + 1
- else
- print("Checking for chest")
- if lib.isChest("forward") then
- if turtle.forward() then
- blocks = blocks + 1
- end
- else
- break
- end
- end
- end
- end
- function lib.findChests(R)
- for i = 1, 4 do
- print("Searching wall "..i)
- if i == 1 or i == 3 then
- lib.searchStrip(R.width) -- find and empty chests along width
- else
- lib.searchStrip(R.length) -- find and empty chests along length
- end
- if R.direction == "clock" then
- T:turnRight(1)
- else
- T:turnLeft(1)
- end
- end
- -- checked all walls
- T:go("F".. math.floor(R.width / 2)) -- now at mid-dungeon, next to wall
- if T:getItemSlot("chest") > 0 then
- if R.direction == "clock" then
- T:turnLeft(1)
- else
- T:turnRight(1)
- end
- -- now at mid-dungeon, facing wall
- -- deposit chest outside the dungeon
- while turtle.back() do end -- backing spawner
- T:go("x0 F1x0 F1x0 F1x0 F1x0 F1x0 F1x0 x1x2")
- -- place(self, blockType, damageNo, direction, leaveExisting, signText)
- T:place("chest", -1, "forward", false)
- -- empty out all except stone and slab
- T:emptyInventorySelection("forward", {"cobble", "tuff", "slab", "granite", "andesite", "diorite" }, {0,0,0,0,0,0})
- T:turnLeft(2)
- T:checkInventoryForItem({"stone"}, {512}, false, "Full cube uses ~700 blocks\nEstimate your requirements")
- while turtle.forward() do end -- facing spawner
- else
- if R.direction == "clock" then
- T:turnRight(1)
- else
- T:turnLeft(1)
- end
- end -- now at mid-dungeon, facing spawner
- end
- function lib.enterDungeon(R)
- --[[ find and empty any chests, return to dungeon wall ]]
- print("Entering dungeon")
- local blockType = T:getBlockType("forward")
- if blockType == "" then -- nothing in front.Error
- return false, "No block in front: Check position."
- else -- attempt entry into dungeon wall
- if R.subChoice == 2 then -- bottom left
- T:go("R1F1 L1U2 F2R1")
- elseif R.subChoice == 3 then -- top left
- T:go("R1F1 L1D1 F2R1")
- elseif R.subChoice == 4 then -- bottom right
- T:go("L1F1 R1U2 F2L1")
- elseif R.subChoice == 5 then -- top right
- T:go("L1F1 R1D1 F2L1")
- end
- while turtle.down() do end -- either on floor or chest
- if lib.isChest("down") then
- turtle.down()
- end
- print("Searching for chests")
- lib.findChests(R) -- go round inside walls emptying chests. Finish mid-wall
- end
- return true, ""-- success, message
- end
- function lib.isChest(direction)
- direction = direction or "forward"
- local blockType = T:getBlockType(direction)
- if blockType:find("chest") ~= nil then -- chest found. early stages so empty and break it
- print("Chest found")
- while T:suck(direction) do end
- T:dig(direction, false) -- false prevents checking for chests
- return true
- elseif blockType:find("torch") ~= nil then
- print("Torch found")
- T:dig(direction, false) -- false prevents checking for chests
- return true
- end
- return false
- end
- function lib.findSpawner(blaze)
- local moves = 0
- local quit = false
- -- assume turtle placed on centre of inside spawner wall in front of spawner
- -- or as close as possible in Nether
- print("Checking if next to spawner")
- local found, position = lib.isSpawner() -- true/false, top/bottom/nil
- if not found then -- move forward towards spawner
- print("Not close to spawner")
- while turtle.forward() and not quit do
- moves = moves + 1
- if moves > 16 then
- quit = true
- end
- end
- found, position = lib.isSpawner() -- true/false, top/bottom/nil
- if not found then
- if blaze then -- could be behind a wall
- print("Assuming blaze spawner behind a wall")
- T:forward(1)
- moves = moves + 1
- while turtle.forward() and not quit do
- moves = moves + 1
- if moves > 16 then
- quit = true
- end
- end
- found, position = lib.isSpawner() -- true/false, top/bottom/nil
- if not found then
- T:go("R2F"..moves + 2 .."R2")
- end
- end
- end
- end
- return found, position
- end
- if not continue then -- new mob cube either dungeon or blaze
- -- clsTurtle.go(self, path, useTorch, torchInterval, leaveExisting, preferredBlock)
- -- determine spawner position level 4, move to top of spawner (level 6)
- print("Checking if already at spawner")
- local found, position = lib.isSpawner() -- already on spawner?
- if blaze then
- if not found then -- away from spawner
- if R.subChoice == 3 then
- T:go("U5")
- end
- found, position = lib.findSpawner(blaze)
- end
- else -- go to bottom of dungeon and empty chests
- if not found then --outside dungeon
- local success, message = lib.enterDungeon(R)
- if not success then
- return {message}
- end
- found, position = lib.findSpawner(blaze) -- is spawner in front / above / below?
- end
- end
- if found then -- true: move to correct starting position
- --[[
- 1 |c|c|c|c|c|c|c|c|c|c|c|
- 2 |w| | | | | | | | | |w|
- 3 |w| | | | | | | | | |w|
- 4 |w| | | | | | | | | |w|
- 5 |w| | | | | | | | | |w|
- 6 |w| | | | |s| | | | |w|
- 7 |w| | | | | | | | | |w|
- 8 |w| | | | | | | | | |w|
- 9 |w| | | | | | | | | |w|
- 10 |w| | | | | | | | | |w| exit level for overworld
- 11 |f|f|f|f|f|f|f|f|f|f|f|
- 12 |f|f|f|f|f|f|f|f|f|f|f| sub floor for overworld
- 1 2 3 4 5 6 7 8 9 1 1
- 0 1
- ]]
- -- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
- if position == "bottom" then
- T:go("B1U2F1")
- elseif position == "forward" then
- T:go("U1F1")
- end
- T:up(1)
- T:place("slab", -1, "down", true) -- place slab on top T:place(blockType, damageNo, direction, leaveExisting)
- -- go up 2 blocks, forward 5, right, forward 5, right
- T:go("U2F5 R1F5 R1") -- Level 2: now placed 1 below ceiling inside wall, top right corner of new dungeon
- lib.wallSection(blaze) -- fix layers 1, 2, 3 including ceiling margin turtle at Level 2
- T:go("F1R2 C1L1 F1R2 C1R1", false, 0, false) -- exit wall, repair behind, still Level 2
- lib.ceiling(blaze) -- fix ceiling, end opposite corner to start
- T:go("R2D3") -- clear the inner walls inside original dungeon
- lib.clearWall(9) -- clear the 9 x 9 area around the spawner
- T:go("F1R1F1L1")
- lib.clearWall(7) -- clear the 7 x 7 area around the spawner
- T:go("F1R1F1L1")
- lib.clearWall(5) -- clear the 5 x 5 area around the spawner. Also needed for cave spiders
- T:go("R2F1R1F1R1")
- T:go("F7R1 F8L1F1R2", false, 0, false) -- return from ceiling, enter wall below previous section: Level 5
- lib.wallSection() -- deal with areas from spawner level up (4,5,6). walls only
- T:go("F1R2 C1L1 F1R2 C1R1 D3", false, 0, false) -- exit wall, repair behind, embed 1 below original floor: Level 8
- clearRectangle({width = 9, length = 9, up = true, down = true}) -- clear levels 7,8,9
- T:go("L1F1 L1F1L2", false,