Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- pastebin get neAN4a60 PotatoFarmer
- local numberLevels = ...
- if numberLevels then
- numberLevels = tonumber(numberLevels)
- else
- numberLevels = 1
- end
- local turtlePos, direction
- local startPos, startDir
- local Settings = {
- vertDiff = 5
- }
- 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
- -- === 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")
- moveForward()
- -- 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 goToLift()
- local coord = add(startPos, startDir)
- local deltaX = coord.x - turtlePos.x
- 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}))
- moveForward()
- 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)}))
- moveForward()
- deltaZ = coord.z - turtlePos.z
- end
- end
- if dirX == 0 then
- moveToEqualX()
- moveToEqualZ()
- elseif dirZ == 0 then
- moveToEqualZ()
- moveToEqualX()
- end
- end
- 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}))
- moveForward()
- 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)}))
- moveForward()
- deltaZ = coord.z - turtlePos.z
- end
- end
- local function moveToEqualY()
- while not (deltaY == 0) do
- if deltaY > 0 then
- moveUp()
- elseif deltaY < 0 then
- moveDown()
- end
- deltaY = coord.y - turtlePos.y
- end
- end
- if not (deltaY == 0) then
- goToLift()
- moveToEqualY()
- deltaX = coord.x - turtlePos.x
- deltaZ = coord.z - turtlePos.z
- end
- if dirX == 0 then
- moveToEqualZ()
- moveToEqualX()
- elseif dirZ == 0 then
- moveToEqualX()
- moveToEqualZ()
- end
- end
- -- === Tasks ===
- local function isPotato(item)
- if not item or not item.name then return false end
- return item.name == "minecraft:potatoes" or item.name == "minecraft:potato"
- end
- local function getAge(item)
- return item.state and item.state.age or nil
- end
- local function getPotatoCount()
- local numPotatoes = 0
- for i = 1, 16 do
- local item = turtle.getItemDetail(i)
- if isPotato(item) then
- numPotatoes = numPotatoes + turtle.getItemCount(i)
- end
- end
- return numPotatoes
- end
- local function selectPotatoSlot()
- for i = 1, 16 do
- local item = turtle.getItemDetail(i)
- if isPotato(item) then
- turtle.select(i)
- return true
- end
- end
- return false
- end
- local function harvestAndPlantPotato()
- local success, item = turtle.inspectDown()
- if (not success) or (isPotato(item) and getAge(item) == 7) then
- turtle.digDown()
- selectPotatoSlot()
- turtle.placeDown()
- end
- end
- local function harvestField()
- -- Get in position
- goToLift()
- turnInDirection(getTurnDirection(direction, startDir))
- moveUp()
- local cntRow = 1
- local notFinished = true
- local function turnToNextRow(turnDir)
- turnInDirection(turnDir)
- if not moveForward() then
- return false
- end
- if cntRow % 6 == 3 then
- if not moveForward() then
- return false
- end
- end
- turnInDirection(turnDir)
- return true
- end
- while true do
- -- Move forward till wall then turn next row
- if isEqual(direction, startDir) then
- if not moveForward() then
- if not turnToNextRow("right") then
- -- stops at last harvested block, does not go back
- break
- else
- cntRow = cntRow + 1
- end
- end
- -- Move forward till distance of 2 in start directional coordinate to startPos
- else
- local testCoord = add(turtlePos, multiply(2, direction))
- local condition1 = (not (startDir.x == 0)) and (testCoord.x == startPos.x)
- local condition2 = (not (startDir.z == 0)) and (testCoord.z == startPos.z)
- if condition1 or condition2 then
- if not turnToNextRow("left") then
- -- stops at last harvested block, does not go back
- break
- else
- cntRow = cntRow + 1
- end
- else
- moveForward()
- end
- end
- -- harvest block below
- harvestAndPlantPotato()
- end
- end
- -- === Inventory Management ===
- local function dumpInventoryKeepPotatoes()
- 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 potatoesKept = 0
- for slot = 1, 16 do
- local item = turtle.getItemDetail(slot)
- if item then
- turtle.select(slot)
- if isPotato(item) and potatoesKept < 10 then
- local keep = math.min(item.count, 10 - potatoesKept)
- local drop = item.count - keep
- if drop > 0 then
- turtle.drop(drop)
- end
- potatoesKept = potatoesKept + keep
- else
- 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
- goToPos(startPos)
- end
- print("Turtle needs more fuel")
- return true
- end
- return false
- end
- -- === Initialization ===
- local function saveStartingParameters()
- local parameterList = {pos = turtlePos, dir = direction, numLevels = numberLevels}
- local file = fs.open("startingParameters.txt", "w")
- file.write(textutils.serialize(parameterList))
- file.close()
- end
- local function loadStartingParameters()
- if not fs.exists("startingParameters.txt") then return false end
- local file = fs.open("startingParameters.txt", "r")
- local data = textutils.unserialize(file.readAll())
- file.close()
- startPos = data.pos
- startDir = data.dir
- numberLevels = data.numLevels
- return true
- end
- local function initProgram()
- turtlePos = getGPSPosition()
- if not turtlePos then error("GPS failure, cannot run the program") end
- getDirection()
- if not loadStartingParameters() then
- startPos = turtlePos
- startDir = direction
- saveStartingParameters()
- end
- end
- local function main()
- local cnt = 0
- while true do
- if turtleNeedsFuel() then
- return
- end
- local level = cnt % numberLevels
- local posLift = add(startPos, startDir)
- local vecUp = {x = 0, y = Settings.vertDiff * level, z = 0}
- local posNextField = add(posLift, vecUp)
- -- Go to field and harvest it
- goToPos(posNextField)
- harvestField()
- -- Go to start and dump inventory
- if cnt % 2 == 1 then
- goToPos(startPos)
- turnInDirection(getTurnDirection(direction, negative(startDir)))
- dumpInventoryKeepPotatoes()
- end
- cnt = cnt + 1
- end
- end
- initProgram()
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement