Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- home = {x = nil, y = nil, z = nil, direction = nil, globalRotation = nil}
- location = {x = nil, y = nil, z = nil, direction = nil}
- work = {x = nil, y = nil, z = nil, direction = nil}
- listeners = {}
- validTools = {crafting = "Crafting", pickaxe = "Pickaxe", axe = "Axe", shovel = "Shovel", hoe = "Hoe", modem = "Modem", none = "None"}
- tools = {left = validTools.none, right = validTools.none}
- fuel = { "minecraft:coal", "minecraft:charcoal" }
- function init(requiresTools, equippedTools)
- -- open network links
- initRednet()
- -- find out where we are by knowing where we aren't
- local x, y, z, dir, startDir = getInitialPosition()
- initHome(x, y, z, dir)
- location.x = x
- location.y = y
- location.z = z
- location.direction = dir
- rotateTo(startDir)
- if requiresTools and not equippedTools then
- getTools()
- elseif requiresTools and equippedTools then
- tools = equippedTools
- end
- sendStatus("Init Complete")
- end
- function canDig()
- return tools.left == validTools.pickaxe or tools.right == validTools.pickaxe
- end
- -- global rotations
- -- 0 = north
- -- 1 = east
- -- 2 = south
- -- 3 = west
- function convertToLocal(newX, newZ)
- if not newX or not newZ then
- newX = location.x
- newZ = location.z
- end
- if home.globalRotation == 0 then
- return {x = newX, z = newZ}
- elseif home.globalRotation == 1 then
- return {x = -newZ, z = newX}
- elseif home.globalRotation == 2 then
- return {x = -newX, z = -newZ}
- else
- return {x = newZ, z = -newX}
- end
- end
- -- (literal global direction)
- -- global rotations:
- -- north = 0
- -- east = 1
- -- south = 2
- -- west = 3
- -- (relative to the rotation of the start position)
- -- local rotations
- -- forwards = 0
- -- right = 1
- -- backwards = 2
- -- left = 3
- -- home.globalRotation = 0 local rotation
- -- location.direction = relative rotation
- -- this function needs to convert local (relative to home) rotation to world rotation
- function getGlobalRotation()
- return (location.direction + home.globalRotation) % 4
- end
- function getInitialPosition()
- -- find current global rotation
- local x1, y1, z1 = gps.locate()
- local globalRotation = nil
- foundRotation = false
- attempts = 0
- -- find global rotation by moving and comparing gps position
- while not foundRotation and attempts < 4 do
- move = turtle.forward()
- local x2, y2, z2 = gps.locate()
- if move then
- if (x1 < x2) then globalRotation = 3
- elseif(z1 > z2) then globalRotation = 2
- elseif(x1 > x2) then globalRotation = 1
- elseif(z1 < z2) then globalRotation = 0 end
- foundRotation = true
- turtle.turnLeft()
- turtle.turnLeft()
- turtle.forward()
- else
- turtle.turnLeft()
- attempts = attempts + 1
- end
- end
- -- error out if rotation could not be found
- if not foundRotation then
- sendStatus("Could not find rotation")
- error()
- end
- local startGlobalRotation = (globalRotation - attempts - 2) % 4
- -- get offset from global Rotation
- home.globalRotation = settings.get("HomeGlobalRotation", startGlobalRotation)
- local direction = globalToLocalRotation(globalRotation)
- -- find initial direction
- local startDirection = globalToLocalRotation(startGlobalRotation)
- return x1, y1, z1, direction, startDirection
- end
- -- get rotation relative to global home rotation
- function globalToLocalRotation(globalRotation)
- local direction
- if globalRotation == home.globalRotation then direction = 0
- elseif (globalRotation + 1) % 4 == home.globalRotation then direction = 1
- elseif (globalRotation - 1) % 4 == home.globalRotation then direction = 3
- else direction = 2 end
- return direction
- end
- function initHome(x, y, z, dir)
- settings.load("settings")
- home.x = settings.get("HomeXPos", x)
- home.y = settings.get("HomeYPos", y)
- home.z = settings.get("HomeZPos", z)
- home.direction = settings.get("HomeRotation", dir)
- saveHome()
- end
- function saveHome()
- settings.load("settings")
- settings.set("HomeXPos", home.x)
- settings.set("HomeYPos", home.y)
- settings.set("HomeZPos", home.z)
- settings.set("HomeRotation", home.direction)
- settings.set("HomeGlobalRotation", home.globalRotation)
- settings.save("settings")
- end
- function updateWorklocation()
- work.x = location.x
- work.y = location.y
- work.z = location.z
- work.direction = location.direction
- end
- function moveToPosition(newX, newY, newZ, newDir, name)
- if not newDir then newDir = 0 end
- if not name then name = "Somewhere" end
- local blockages = 0
- local newLocation = {x = newX, y = newY, z = newZ, direction = newDir}
- local moved = false
- while not compareLocations(location, newLocation, false) and blockages < 10 do
- sendStatus("Moving to "..name.. ":\n["..newX..", "..newY..", "..newZ..", "..newDir.."]")
- -- move to new Y location
- while location.y ~= newY do
- if location.y > newY then
- moved = moveDown()
- elseif location.y < newY then
- moved = moveUp()
- end
- if not moved then
- blockages = blockages +1
- break
- end
- end
- -- move to new X location
- while location.x ~= newX do
- if location.x > newX then
- if getGlobalRotation() ~= 3 then rotateToGlobal(3) end
- moved = moveForward()
- elseif location.x < newX then
- if getGlobalRotation() ~= 1 then rotateToGlobal(1) end
- moved = moveForward()
- end
- if not moved then
- blockages = blockages + 1
- break
- end
- end
- -- move to new Z location
- while location.z ~= newZ do
- if location.z > newZ then
- if getGlobalRotation() ~= 2 then rotateToGlobal(2) end
- moved = moveForward()
- elseif location.z < newZ then
- if getGlobalRotation() ~= 0 then rotateToGlobal(0) end
- moved = moveForward()
- end
- if not moved then
- blockages = blockages + 1
- break
- end
- end
- end
- rotateTo(newDir)
- return compareLocations(location, newLocation)
- end
- function compareLocations(tab1, tab2, includeRotation)
- if includeRotation then
- return tab1.x == tab2.x and tab1.y == tab2.y and tab1.z == tab2.z and tab1.direction == tab2.direction
- else
- return tab1.x == tab2.x and tab1.y == tab2.y and tab1.z == tab2.z
- end
- end
- function locationNil(tab)
- return not tab.x or not tab.y or not tab.z or not tab.direction
- end
- function rotateLeft()
- location.direction = location.direction-1
- if (location.direction == -1) then
- location.direction = 3
- end
- turtle.turnLeft()
- end
- function rotateRight()
- location.direction = location.direction+1
- if (location.direction == 4) then
- location.direction = 0
- end
- turtle.turnRight()
- end
- function rotateTo(newDir)
- if location.direction == newDir then
- return
- elseif (location.direction + 1) % 4 == newDir then
- rotateRight()
- elseif (location.direction - 1) % 4 == newDir then
- rotateLeft()
- else
- while location.direction ~= newDir do
- rotateLeft()
- end
- end
- end
- function rotateToGlobal(newDir)
- local globalRotation = getGlobalRotation()
- print("Rotating to ".. newDir)
- if globalRotation == newDir then
- return
- elseif (globalRotation + 1) % 4 == newDir then
- rotateRight()
- elseif (globalRotation - 1) % 4 == newDir then
- rotateLeft()
- else
- while getGlobalRotation() ~= newDir do
- rotateLeft()
- end
- end
- end
- function moveForward()
- -- if able to dig clear out blocks in front
- if canDig() then
- while turtle.detect() do
- turtle.dig()
- end
- end
- moved = turtle.forward()
- if moved then
- rotation = getGlobalRotation()
- if rotation == 0 then
- location.z = location.z+1
- elseif rotation == 1 then
- location.x = location.x+1
- elseif rotation == 2 then
- location.z = location.z-1
- elseif rotation == 3 then
- location.x = location.x-1
- end
- return true
- else
- return false
- end
- end
- -- returns true on valid movement
- function moveUp()
- if canDig() then
- while turtle.detectUp() do
- turtle.digUp()
- end
- end
- local moved = turtle.up()
- if not moved then return false end
- location.y = location.y + 1
- return true
- end
- function moveDown()
- if canDig() then
- while turtle.detectDown() do
- turtle.digDown()
- end
- end
- local moved = turtle.down()
- if not moved then return false end
- location.y = location.y - 1
- return true
- end
- function currentPosition()
- local direction = location.direction or -1
- local x, y, z
- if not x or not y or not z then
- x, y, z = gps.locate()
- else
- x = location.x
- y = location.y
- z = location.z
- end
- return "[".. x..", ".. y..", ".. z..", ".. direction .."]"
- end
- function returnHome()
- local returnedHome = moveToPosition(home.x, home.y, home.z, home.direction, "Home")
- if not returnedHome then
- sendStatus("I'm stuck ;-;")
- error()
- end
- end
- function returnToWork()
- if locationNil(work) then
- sendStatus("attempted to return to work when I have no work location")
- error()
- end
- local returnedToWork = moveToPosition(work.x, work.x, work.z, work.direction, "Work")
- if not returnedToWork then
- sendStatus("I'm stuck ;-;")
- error()
- end
- end
- function getValidToolText()
- local text = ""
- for k, v in pairs(validTools) do
- if text ~= "" then text = text.. ", " end
- text = text .. v
- end
- return text
- end
- function getTools()
- local complete = false
- local toolText = "Valid Tools: ".. getValidToolText()
- local sides = peripheral.getNames()
- if tableContains("left", sides) then
- complete = true
- tools.left = validTools.modem
- end
- while not complete do
- term.clear()
- term.setCursorPos(1,1)
- print(toolText)
- io.write("Enter Left Tool: ")
- local leftTool = io.read()
- local valid, leftTool = validTool(leftTool)
- if valid then
- complete = true
- tools.left = leftTool
- end
- end
- complete = false
- if tableContains("right", sides) then
- complete = true
- tools.right = validTools.modem
- end
- while not complete do
- term.clear()
- term.setCursorPos(1,1)
- print(toolText)
- io.write("Enter Right Tool: ")
- local rightTool = io.read()
- local valid, rightTool = validTool(rightTool)
- if valid then
- complete = true
- tools.right = rightTool
- end
- end
- end
- function validTool(tool)
- for k,v in pairs(validTools) do
- if string.lower(v) == string.lower(tool) then
- return true, v
- end
- end
- return false, validTools.none
- end
- function tableContains(str, table)
- for k, v in pairs(table) do
- if v == str then return true end
- end
- return false
- end
- function resetSettings()
- settings.load("settings")
- settings.clear()
- settings.save("settings")
- end
- function findItem(id)
- local itemTable = {}
- for i = 1, 16, 1 do
- local slotData = turtle.getItemDetail(i)
- if (slotData and slotData.name == id) then
- table.insert(itemTable, i)
- end
- end
- if table.getn(itemTable) > 0 then
- return itemTable
- end
- return nil
- end
- -- returns true if empty slot was found ant item was moved
- function moveItemToEmpty(slot)
- turtle.select(slot)
- for i = 1, 16, 1 do
- if i ~= slot then
- if turtle.transferTo(i) then
- return true
- end
- end
- end
- return false
- end
- -- returns true if space remains
- function checkSpace()
- for i = 1, 16, 1 do
- if not turtle.getItemDetail(i) then
- return true
- end
- end
- return false
- end
- function minifyStacks()
- for i = 16, 1, -1 do
- local slotData = turtle.getItemDetail(i)
- if slotData then
- slotsTable = findItem(slotData.name)
- if slotsTable and table.getn(slotsTable) > 1 then
- for k,v in pairs(slotsTable or {}) do
- turtle.select(v)
- turtle.transferTo(i, turtle.getItemSpace(i))
- end
- end
- end
- end
- end
- -- returns home and requests more fuel
- function giveMeFuel()
- while not hasFuel() do
- sleep(2)
- end
- returnToWork()
- end
- -- attempts to fill fuel slot, returns true if enough fuel is located in the fuel slot.
- function hasFuel()
- local fuelSlots = {}
- local slotData = turtle.getItemDetail(1)
- -- search the first slot for a valid fuel item
- for k,v in pairs(fuel or {}) do
- -- find if any other slots contain any fuel
- local slotTable = findItem(v)
- table.insert(fuelSlots, slotTable)
- -- look in slot one, if contains fuel return
- if (slotData and slotData.name == v) then
- return turtle.getItemCount(1) > 1, slotTable
- end
- end
- -- move item out of fuel slot
- if slotData then
- moveItemToEmpty(1)
- end
- -- move valid fuel into slot
- for k,v in pairs(fuelSlots or {}) do
- if v then
- if table.getn(v) > 0 then
- turtle.select(v[1])
- turtle.transferTo(1)
- end
- return turtle.getItemCount(1) > 1, v
- end
- end
- return false, nil
- end
- function isFuel(slotData)
- for k,v in pairs(fuel or {}) do
- if slotData.name == v then return true end
- end
- return false
- end
- function getMinFuelLevel()
- if locationNil(work) or locationNil(home) then return 800 end
- return math.abs(work.x) + math.abs(work.z) + math.abs(home.y - work.y) + 50
- end
- -- checks fuel levels and attempts to refuel the turtle
- function refuel()
- local hasFuelLeft, fuelSlots = hasFuel()
- if turtle.getFuelLevel() < getMinFuelLevel() then
- if not hasFuelLeft then
- giveMeFuel()
- end
- end
- if turtle.getFuelLevel() < 5120 then
- turtle.select(1)
- coalCount = turtle.getItemCount(1)
- if coalCount > 0 then turtle.refuel(coalCount-1) end
- end
- end
- function offsetFromHome()
- return {x = home.x - location.x, y = home.y - location.y, z = home.z - location.z}
- end
- function getListeners()
- listeners = {rednet.lookup("turtle_status")}
- if listeners then
- for k, v in pairs(listeners) do
- rednet.send(v, "request_connect")
- end
- end
- end
- function sendStatus(status)
- for k, v in pairs(listeners) do
- rednet.send(v, status.. "\n" .. currentPosition())
- end
- end
- function dumpExtraStacks(itemId)
- items = findItem(itemId)
- if items and #items > 1 then
- for i = 2, #items, 1 do
- turtle.select(items[i])
- turtle.drop()
- end
- end
- end
- function openRednet()
- side = getModemSide()
- if not side then error("could not find modem") end
- rednet.open(side, 255)
- end
- function getModemSide()
- sides = peripheral.getNames()
- for k, v in pairs(sides) do
- if peripheral.getType(v) == "modem" then return v end
- end
- return nil
- end
- function initRednet()
- term.clear()
- term.setCursorPos(1,1)
- print("Initialising Rednet System")
- openRednet()
- getListeners()
- end
- return {home = home, fuel = fuel, location = location, work = work, validTools = validTools, tools = tools, canDig = canDig, getInitialPosition = getInitialPosition, initHome = initHome, saveHome = saveHome, updateWorklocation = updateWorklocation, moveToPosition = moveToPosition, compareLocations = compareLocations, locationNil = locationNil, rotateLeft = rotateLeft, rotateRight = rotateRight, rotateTo = rotateTo, moveForward = moveForward, moveUp = moveUp, moveDown = moveDown, returnHome = returnHome, returnToWork = returnToWork, init = init, getValidToolText = getValidToolText, getTools = getTools, validTool = validTool, tableContains = tableContains, resetSettings = resetSettings, findItem = findItem, moveItemToEmpty = moveItemToEmpty, checkSpace = checkSpace, minifyStacks = minifyStacks, giveMeFuel = giveMeFuel, hasFuel = hasFuel, getMinFuelLevel = getMinFuelLevel, refuel = refuel, sendStatus = sendStatus, currentPosition = currentPosition, convertToLocal = convertToLocal, getGlobalRotation = getGlobalRotation, dumpExtraStacks = dumpExtraStacks, offsetFromHome = offsetFromHome, rotateToGlobal = rotateToGlobal}
Add Comment
Please, Sign In to add comment