Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local turtlePos, direction
- local startPos, startDir
- local function getGPSPosition()
- local x, y, z = gps.locate()
- if not x then print("Error: GPS not available") return nil end
- return {x = math.floor(x), y = math.floor(y), z = math.floor(z)}
- end
- local function negative(vec)
- return {x = -vec.x, y = -vec.y, z = -vec.z}
- end
- local function add(vec1, vec2)
- return {x = vec1.x + vec2.x, y = vec1.y + vec2.y, z = vec1.z + vec2.z}
- end
- local function sub(vec1, vec2)
- return add(vec1, negative(vec2))
- end
- local function multiply(s, vec)
- return {x = s * vec.x, y = s * vec.y, z = s * vec.z}
- end
- local function getSign(number)
- return number / math.abs(number)
- end
- local function isEqual(vec1, vec2)
- return vec1.x == vec2.x and vec1.y == vec2.y and vec1.z == vec2.z
- end
- -- === Basic Movement ===
- local function moveForward()
- if turtle.forward() then
- turtlePos = add(turtlePos, direction)
- return true
- end
- return false
- end
- local function moveUp()
- if turtle.up() then
- turtlePos.y = turtlePos.y + 1
- return true
- end
- return false
- end
- local function moveDown()
- if turtle.down() then
- turtlePos.y = turtlePos.y - 1
- return true
- end
- return false
- end
- local function forceMoveForward()
- while not moveForward() do turtle.dig() end
- end
- local function forceMoveUp()
- while not moveUp() do turtle.digUp() end
- end
- local function forceMoveDown()
- while not moveDown() do turtle.digDown() end
- end
- -- === Basic Turning ===
- local function turnInDirection(dir)
- if not direction then return end
- if dir == "left" then
- turtle.turnLeft()
- direction = {x = direction.z, y = 0, z = -direction.x}
- elseif dir == "right" then
- turtle.turnRight()
- direction = {x = -direction.z, y = 0, z = direction.x}
- elseif dir == "around" then
- turtle.turnLeft()
- turtle.turnLeft()
- direction = {x = -direction.x, y = 0, z = -direction.z}
- end
- end
- local function getTurnDirection(from, to)
- local function vectorsEqual(a, b)
- return a.x == b.x and a.z == b.z
- end
- if vectorsEqual(from, to) then return nil end
- local left = {x = from.z, y = 0, z = -from.x}
- local right = {x = -from.z, y = 0, z = from.x}
- local back = {x = -from.x, y = 0, z = -from.z}
- if vectorsEqual(to, left) then
- return "left"
- elseif vectorsEqual(to, right) then
- return "right"
- elseif vectorsEqual(to, back) then
- return "around"
- else
- error("Invalid target direction")
- end
- end
- local function getDirection()
- local pos1 = getGPSPosition()
- if not pos1 then error("GPS failure, cannot get direction") end
- for i = 1, 4 do
- if turtle.forward() then
- local pos2 = getGPSPosition()
- if not pos2 then error("GPS failure after move") end
- -- turtlePos = pos2
- -- Richtung berechnen
- direction = sub(pos2, pos1)
- -- zurück zur ursprünglichen Position
- turnInDirection("around")
- forceMoveForward()
- -- Sicherheitsprüfung
- local posBack = getGPSPosition()
- if not isEqual(pos1, posBack) then
- error("Warnung: Position hat sich beim Rückweg verschoben!")
- turtlePos = posBack -- explizit wieder auf GPS setzen
- else
- turtlePos = pos1
- end
- turnInDirection("around")
- return
- else
- turtle.turnLeft()
- end
- end
- error("Unable to move forward in any direction for direction detection")
- end
- -- === Positioning ===
- local function goToPos(coord)
- local deltaX = coord.x - turtlePos.x
- local deltaY = coord.y - turtlePos.y
- local deltaZ = coord.z - turtlePos.z
- local dirX = startDir.x
- local dirZ = startDir.z
- local function moveToEqualX()
- while not (deltaX == 0) do
- turnInDirection(getTurnDirection(direction, {x = getSign(deltaX), y = 0, z = 0}))
- forceMoveForward()
- deltaX = coord.x - turtlePos.x
- end
- end
- local function moveToEqualZ()
- while not (deltaZ == 0) do
- turnInDirection(getTurnDirection(direction, {x = 0, y = 0, z = getSign(deltaZ)}))
- forceMoveForward()
- deltaZ = coord.z - turtlePos.z
- end
- end
- local function moveToEqualY()
- while not (deltaY == 0) do
- if deltaY > 0 then
- forceMoveUp()
- elseif deltaY < 0 then
- forceMoveDown()
- end
- deltaY = coord.y - turtlePos.y
- end
- end
- if dirX == 0 then
- moveToEqualZ()
- moveToEqualX()
- elseif dirZ == 0 then
- moveToEqualX()
- moveToEqualZ()
- end
- if not (deltaY == 0) then
- moveToEqualY()
- deltaX = coord.x - turtlePos.x
- deltaZ = coord.z - turtlePos.z
- end
- end
- ------------------------- Startpos adapten
- local function goToStartOfTree()
- startTreePos = add(startPos, multiply(5, startDir))
- goToPos(startTreePos)
- turnInDirection(getTurnDirection(direction, startDir))
- end
- -- === Tasks ===
- local function isSapling(item)
- if not item or not item.name then return false end
- local saplingSuffix = "pale_oak_sapling"
- return item.name:match(":.*" .. saplingSuffix .. "$") ~= nil
- end
- local function isBoneMeal(item)
- if not item or not item.name then return false end
- return item.name == "minecraft:bone_meal"
- end
- local function isLog(item)
- if not item or not item.name then return false end
- local logSuffix = "_log"
- return item.name:match(":.*" .. logSuffix .. "$") ~= nil
- end
- local function getBoneMealCount()
- local num = 0
- for i = 1, 16 do
- local item = turtle.getItemDetail(i)
- if isBoneMeal(item) then
- num = num + turtle.getItemCount(i)
- end
- end
- return num
- end
- local function getSaplingCount()
- local num = 0
- for i = 1, 16 do
- local item = turtle.getItemDetail(i)
- if isSapling(item) then
- num = num + turtle.getItemCount(i)
- end
- end
- return num
- end
- local function selectSaplingSlot()
- for i = 1, 16 do
- local item = turtle.getItemDetail(i)
- if isSapling(item) then
- turtle.select(i)
- return true
- end
- end
- return false
- end
- local function selectBoneMealSlot()
- for i = 1, 16 do
- local item = turtle.getItemDetail(i)
- if isBoneMeal(item) then
- turtle.select(i)
- return true
- end
- end
- return false
- end
- local function plantSapling()
- if not selectSaplingSlot() then return false end
- if not turtle.place() then return false end
- return true
- end
- local function plantAllSaplings()
- local function plantSaplingDown()
- if not selectSaplingSlot() then return false end
- if not turtle.placeDown() then
- suc, item = turtle.inspectDown()
- if suc and isSapling(item) then return true end
- return false
- end
- return true
- end
- goToStartOfTree()
- forceMoveUp()
- suc, item = turtle.inspect()
- if suc and isLog(item) then
- goToStartOfTree()
- return false
- end
- local returnValue = true
- forceMoveForward()
- returnValue = returnValue and plantSaplingDown()
- forceMoveForward()
- returnValue = returnValue and plantSaplingDown()
- turnInDirection("right")
- forceMoveForward()
- turnInDirection("right")
- returnValue = returnValue and plantSaplingDown()
- forceMoveForward()
- returnValue = returnValue and plantSaplingDown()
- goToStartOfTree()
- return returnValue
- end
- local function fellTillLeaves_GetTurnDir(cnt)
- local sucUp, itemUp = turtle.inspectUp()
- local sucFor, itemFor = turtle.inspect()
- local topTurnDir = "left"
- while (not (sucUp and itemUp.name == "minecraft:pale_oak_leaves")) and cnt < 13 do
- if sucFor and isLog(itemFor) then
- turtle.dig()
- end
- forceMoveUp()
- sucUp, itemUp = turtle.inspectUp()
- sucFor, itemFor = turtle.inspect()
- cnt = cnt + 1
- end
- if (not (sucFor and itemFor.name == "minecraft:pale_oak_leaves") and cnt < 13) then
- topTurnDir = "right"
- forceMoveForward()
- sucUp, itemUp = turtle.inspectUp()
- while (not (sucUp and itemUp.name == "minecraft:pale_oak_leaves")) and cnt < 13 do
- forceMoveUp()
- sucUp, itemUp = turtle.inspectUp()
- cnt = cnt + 1
- end
- end
- return topTurnDir
- end
- local function fellAtPos(startFellPos)
- goToPos(startFellPos)
- turnInDirection(getTurnDirection(direction, startDir))
- local cnt = turtlePos.y - startFellPos.y
- local topTurnDir = fellTillLeaves_GetTurnDir(cnt)
- cnt = turtlePos.y - startFellPos.y
- turnInDirection("right")
- forceMoveForward()
- turnInDirection(topTurnDir)
- topTurnDir = fellTillLeaves_GetTurnDir(cnt)
- if topTurnDir == "right" then
- turnInDirection("around")
- end
- while turtlePos.y > startFellPos.y do
- local sucFor, itemFor = turtle.inspect()
- if sucFor and isLog(itemFor) then
- turtle.dig()
- end
- forceMoveDown()
- end
- sucFor, itemFor = turtle.inspect()
- if sucFor and isLog(itemFor) then
- turtle.dig()
- end
- end
- local function fellTree()
- local forwDir = startDir
- turnInDirection("left")
- local leftDir = direction
- local diffRight = negative(multiply(2, leftDir))
- local diffFor = multiply(2, forwDir)
- local startFellPos1 = add(negative(forwDir),add(turtlePos, multiply(2, leftDir)))
- local startFellPos2 = add(startFellPos1, diffRight)
- local startFellPos3 = add(startFellPos2, diffRight)
- local startFellPos4 = add(startFellPos3, diffFor)
- local startFellPos5 = add(startFellPos2, diffFor)
- local startFellPos6 = add(startFellPos1, diffFor)
- local startFellPos7 = add(startFellPos6, diffFor)
- local startFellPos8 = add(startFellPos5, diffFor)
- local startFellPos9 = add(startFellPos4, diffFor)
- fellAtPos(startFellPos1)
- fellAtPos(startFellPos2)
- fellAtPos(startFellPos3)
- fellAtPos(startFellPos4)
- fellAtPos(startFellPos5)
- fellAtPos(startFellPos6)
- fellAtPos(startFellPos7)
- fellAtPos(startFellPos8)
- fellAtPos(startFellPos9)
- goToStartOfTree()
- end
- -- === Inventory Management ===
- local function compactInventory()
- for i = 1, 16 do
- local itemI = turtle.getItemDetail(i)
- if itemI and itemI.count < 64 then
- for j = i + 1, 16 do
- local itemJ = turtle.getItemDetail(j)
- if itemJ and itemJ.name == itemI.name then
- turtle.select(j)
- turtle.transferTo(i)
- -- Aktuellen Slot updaten
- itemI = turtle.getItemDetail(i)
- if not itemI or itemI.count == 64 then
- break
- end
- end
- end
- end
- end
- turtle.select(1) -- zum Standard zurückkehren
- end
- -- Keep saplings
- local function dumpInventoryKeepSaplings(n)
- local success, chest = turtle.inspect()
- while not (success and chest.name == "minecraft:chest") do
- print("No chest found. Pls place one in front.")
- print("Press enter to continue.")
- read()
- success, chest = turtle.inspect()
- end
- local saplingsKept = 0
- for slot = 1, 16 do
- local item = turtle.getItemDetail(slot)
- if item then
- turtle.select(slot)
- if isSapling(item) and saplingsKept < n then
- local keep = math.min(item.count, n - saplingsKept)
- local drop = item.count - keep
- if drop > 0 then
- turtle.drop(drop)
- end
- saplingsKept = saplingsKept + keep
- elseif not isBoneMeal(item) then
- turtle.drop()
- end
- end
- end
- turtle.select(1)
- end
- local function turtleNeedsFuel()
- local fuelLevel = turtle.getFuelLevel()
- if fuelLevel < 1000 then
- if not isEqual(startPos, turtlePos) then
- diffX = math.abs(startPos.x - turtlePos.x)
- diffY = math.abs(startPos.y - turtlePos.y)
- diffZ = math.abs(startPos.z - turtlePos.z)
- if not (fuelLevel < diffX + diffY + diffZ +5) then
- goToPos(startPos)
- end
- end
- print("Turtle needs more fuel")
- return true
- end
- return false
- end
- -- gets specified item in given amount (min(available, requested)) from chest
- local function suckSpecificItem(itemName, count, strDir)
- local chest = peripheral.wrap(strDir)
- if not chest or not chest.list then
- return false
- end
- local chestItems = chest.list()
- local foundSlots = {}
- local totalAvailable = 0
- -- 1. Scanne Kiste nach dem gewünschten Item
- for slot, item in pairs(chestItems) do
- if item.name == itemName then
- table.insert(foundSlots, {slot = slot, count = item.count})
- totalAvailable = totalAvailable + item.count
- end
- end
- count = math.min(totalAvailable, count)
- if count == 0 then
- return false
- end
- -- 2. Finde freien Slot in der Turtle für gecachtes Item
- local cachedItemSlot = nil
- for i = 1, 16 do
- if turtle.getItemCount(i) == 0 then
- cachedItemSlot = i
- break
- end
- end
- if not cachedItemSlot then
- print("Kein freier Slot zum Zwischenspeichern des Kisten-Items.")
- return false
- end
- turtle.select(cachedItemSlot)
- local cachedItem = nil
- local list = chest.list()
- if list[1] and list[1].name ~= itemName then
- if strDir == "front" then
- if turtle.suck(64) then
- cachedItem = turtle.getItemDetail(cachedItemSlot)
- end
- elseif strDir == "top" then
- if turtle.suckUp(64) then
- cachedItem = turtle.getItemDetail(cachedItemSlot)
- end
- elseif strDir == "bottom" then
- if turtle.suckDown(64) then
- cachedItem = turtle.getItemDetail(cachedItemSlot)
- end
- end
- end
- -- 3. Erstes gewünschtes Item in Slot 1 schieben
- local nextSlotIndex = 1
- if not chest.getItemDetail(1) then
- local nextSource = foundSlots[nextSlotIndex]
- chest.pushItems(strDir, nextSource.slot, nextSource.count, 1)
- nextSlotIndex = nextSlotIndex + 1
- elseif (chest.getItemDetail(1) and chest.getItemDetail(1).name == itemName) then
- nextSlotIndex = nextSlotIndex + 1
- end
- -- 4. Gecachtes Item zurückgeben
- if cachedItem then
- turtle.select(cachedItemSlot)
- if strDir == "front" then
- turtle.drop() -- Kiste verteilt es automatisch auf einen freien Slot ≠ 1
- elseif strDir == "top" then
- turtle.dropUp() -- Kiste verteilt es automatisch auf einen freien Slot ≠ 1
- elseif strDir == "bottom" then
- turtle.dropDown() -- Kiste verteilt es automatisch auf einen freien Slot ≠ 1
- end
- end
- -- 5. Zielitems absaugen
- local collected = 0
- turtle.select(cachedItemSlot) -- Wiederverwenden für Einsammeln
- while collected < count do
- local remaining = count - collected
- local slot1Item = chest.getItemDetail(1)
- local pullCount = math.min(slot1Item.count, remaining)
- if strDir == "front" then
- if turtle.suck(pullCount) then
- collected = collected + pullCount
- end
- elseif strDir == "top" then
- if turtle.suckUp(pullCount) then
- collected = collected + pullCount
- end
- elseif strDir == "bottom" then
- if turtle.suckDown(pullCount) then
- collected = collected + pullCount
- end
- end
- if collected < count and nextSlotIndex <= #foundSlots then
- local nextSource = foundSlots[nextSlotIndex]
- chest.pushItems(strDir, nextSource.slot, nextSource.count, 1)
- nextSlotIndex = nextSlotIndex + 1
- end
- end
- return true
- end
- local function processAndStockInventory()
- goToPos(startPos)
- turnInDirection(getTurnDirection(direction, negative(startDir)))
- dumpInventoryKeepSaplings(64)
- if getSaplingCount() < 8 then
- suckSpecificItem("minecraft:pale_oak_sapling", 64 - getSaplingCount(), "bottom")
- bFirst = true
- while getSaplingCount() < 8 do
- if bFirst then print("Waiting for new Saplings!") bFirst = false end
- if not suckSpecificItem("minecraft:pale_oak_sapling", 64 - getSaplingCount(), "bottom") then sleep(5) end
- end
- end
- if getBoneMealCount() < 64 then
- suckSpecificItem("minecraft:bone_meal", 64 - getBoneMealCount(), "top")
- bFirst = true
- while getBoneMealCount() < 10 do
- if bFirst then print("Waiting for new Bone Meal!") bFirst = false end
- if not suckSpecificItem("minecraft:bone_meal", 64 - getBoneMealCount(), "top") then sleep(5) end
- end
- end
- compactInventory()
- goToStartOfTree()
- end
- -- === Initialization ===
- local function destroyTreeBlocks()
- local suc, item = turtle.inspect()
- if not suc then
- return
- end
- local treeBlocks = {"minecraft:pale_oak_leaves", "minecraft:pale_oak_log", "minecraft:pale_hanging_moss"}
- cnt = 1
- while cnt <= 3 do
- if item.name == treeBlocks[cnt] then
- turtle.dig()
- return
- end
- cnt = cnt + 1
- end
- end
- local function saveStartingParameters()
- local parameterList = {pos = turtlePos, dir = direction}
- local file = fs.open("paleOakStartingParameters.txt", "w")
- file.write(textutils.serialize(parameterList))
- file.close()
- end
- local function loadStartingParameters()
- if not fs.exists("paleOakStartingParameters.txt") then return false end
- local file = fs.open("paleOakStartingParameters.txt", "r")
- local data = textutils.unserialize(file.readAll())
- file.close()
- startPos = data.pos
- startDir = data.dir
- return true
- end
- local function initProgram()
- turtlePos = getGPSPosition()
- if not turtlePos then error("GPS failure, cannot run the program") end
- destroyTreeBlocks()
- getDirection()
- if not loadStartingParameters() then
- startPos = turtlePos
- startDir = direction
- saveStartingParameters()
- end
- end
- -- === Main ===
- local function main()
- bSaplingPlanted = true
- while turtle.getFuelLevel() < 5 do
- print("Turtle needs more fuel")
- return
- end
- initProgram()
- if turtleNeedsFuel() then return end
- if (getBoneMealCount() == 0) or (getSaplingCount() < 4) then
- processAndStockInventory()
- end
- goToStartOfTree()
- plantAllSaplings()
- while true do
- if turtleNeedsFuel() then return end
- if bSaplingPlanted then
- suc, item = turtle.inspect()
- if suc and isSapling(item) then
- if selectBoneMealSlot() then
- turtle.place()
- else
- processAndStockInventory()
- end
- else
- if suc and isLog(item) then
- fellTree()
- bSaplingPlanted = false
- end
- slotCount = turtle.getItemCount(16)
- if slotCount > 0 then
- processAndStockInventory()
- end
- end
- else
- if not plantAllSaplings() then
- processAndStockInventory()
- if not plantAllSaplings() then
- fellTree()
- bSaplingPlanted = false
- end
- if not plantAllSaplings() then
- goToPos(startPos)
- print("Error: Saplings cannot be planted!")
- return
- end
- end
- bSaplingPlanted = true
- end
- if (getBoneMealCount() == 0) or (getSaplingCount() < 8) then
- processAndStockInventory()
- end
- end
- end
- main()
Advertisement
Add Comment
Please, Sign In to add comment