Vaerys_Dawn

Turtle_Base

Nov 23rd, 2020 (edited)
702
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. home = {x = nil, y = nil, z = nil, direction = nil, globalRotation = nil}
  2.  
  3. location = {x = nil, y = nil, z = nil, direction = nil}
  4.  
  5. work = {x = nil, y = nil, z = nil, direction = nil}
  6.  
  7. listeners = {}
  8.  
  9. validTools = {crafting = "Crafting", pickaxe = "Pickaxe", axe = "Axe", shovel = "Shovel", hoe = "Hoe", modem = "Modem", none = "None"}
  10. tools = {left = validTools.none, right = validTools.none}
  11.  
  12. fuel = { "minecraft:coal", "minecraft:charcoal" }
  13.  
  14. function init(requiresTools, equippedTools)
  15.   -- open network links
  16.   initRednet()
  17.   -- find out where we are by knowing where we aren't
  18.   local x, y, z, dir, startDir = getInitialPosition()
  19.   initHome(x, y, z, dir)
  20.   location.x = x
  21.   location.y = y
  22.   location.z = z
  23.   location.direction = dir
  24.   rotateTo(startDir)
  25.   if requiresTools and not equippedTools then
  26.     getTools()
  27.   elseif requiresTools and equippedTools then
  28.     tools = equippedTools
  29.   end
  30.   sendStatus("Init Complete")
  31. end
  32.  
  33. function canDig()
  34.   return tools.left == validTools.pickaxe or tools.right == validTools.pickaxe
  35. end
  36.  
  37. -- global rotations
  38. -- 0 = north
  39. -- 1 = east
  40. -- 2 = south
  41. -- 3 = west
  42.  
  43. function convertToLocal(newX, newZ)
  44.   if not newX or not newZ then
  45.     newX = location.x
  46.     newZ = location.z
  47.   end
  48.   if home.globalRotation == 0 then
  49.     return {x = newX, z = newZ}
  50.   elseif home.globalRotation == 1 then
  51.     return {x = -newZ, z = newX}
  52.   elseif home.globalRotation == 2 then
  53.     return {x = -newX, z = -newZ}
  54.   else
  55.     return {x = newZ, z = -newX}
  56.   end
  57. end
  58.  
  59. -- (literal global direction)
  60. -- global rotations:
  61. -- north = 0
  62. -- east = 1
  63. -- south = 2
  64. -- west = 3
  65.  
  66. -- (relative to the rotation of the start position)
  67. -- local rotations
  68. -- forwards = 0
  69. -- right = 1
  70. -- backwards = 2
  71. -- left = 3
  72.  
  73. -- home.globalRotation = 0 local rotation
  74. -- location.direction = relative rotation
  75. -- this function needs to convert local (relative to home) rotation to world rotation
  76. function getGlobalRotation()
  77.   return (location.direction + home.globalRotation) % 4
  78. end
  79.  
  80. function getInitialPosition()
  81.   -- find current global rotation
  82.   local x1, y1, z1 = gps.locate()
  83.   local globalRotation = nil
  84.   foundRotation = false
  85.   attempts = 0
  86.   -- find global rotation by moving and comparing gps position
  87.   while not foundRotation and attempts < 4 do
  88.     move = turtle.forward()
  89.     local x2, y2, z2 = gps.locate()
  90.     if move then
  91.       if (x1 < x2) then globalRotation = 3
  92.       elseif(z1 > z2) then globalRotation = 2
  93.       elseif(x1 > x2) then globalRotation = 1
  94.       elseif(z1 < z2) then globalRotation = 0 end
  95.       foundRotation = true
  96.       turtle.turnLeft()
  97.       turtle.turnLeft()
  98.       turtle.forward()
  99.     else
  100.       turtle.turnLeft()
  101.       attempts = attempts + 1
  102.     end
  103.   end
  104.  
  105.   -- error out if rotation could not be found
  106.   if not foundRotation then
  107.     sendStatus("Could not find rotation")
  108.     error()
  109.   end
  110.  
  111.   local startGlobalRotation = (globalRotation - attempts - 2) % 4
  112.   -- get offset from global Rotation
  113.   home.globalRotation = settings.get("HomeGlobalRotation", startGlobalRotation)
  114.   local direction = globalToLocalRotation(globalRotation)
  115.   -- find initial direction
  116.   local startDirection = globalToLocalRotation(startGlobalRotation)
  117.   return x1, y1, z1, direction, startDirection
  118. end
  119.  
  120. -- get rotation relative to global home rotation
  121. function globalToLocalRotation(globalRotation)
  122.   local direction
  123.   if globalRotation == home.globalRotation then direction = 0
  124.   elseif (globalRotation + 1) % 4 == home.globalRotation then direction = 1
  125.   elseif (globalRotation - 1) % 4 == home.globalRotation then direction = 3
  126.   else direction = 2 end
  127.   return direction
  128. end
  129.  
  130. function initHome(x, y, z, dir)
  131.   settings.load("settings")
  132.   home.x = settings.get("HomeXPos", x)
  133.   home.y = settings.get("HomeYPos", y)
  134.   home.z = settings.get("HomeZPos", z)
  135.   home.direction = settings.get("HomeRotation", dir)
  136.   saveHome()
  137. end
  138.  
  139. function saveHome()
  140.   settings.load("settings")
  141.   settings.set("HomeXPos", home.x)
  142.   settings.set("HomeYPos", home.y)
  143.   settings.set("HomeZPos", home.z)
  144.   settings.set("HomeRotation", home.direction)
  145.   settings.set("HomeGlobalRotation", home.globalRotation)
  146.   settings.save("settings")
  147. end
  148.  
  149. function updateWorklocation()
  150.   work.x = location.x
  151.   work.y = location.y
  152.   work.z = location.z
  153.   work.direction = location.direction
  154. end
  155.  
  156. function moveToPosition(newX, newY, newZ, newDir, name)
  157.   if not newDir then newDir = 0 end
  158.   if not name then name = "Somewhere" end
  159.  
  160.   local blockages = 0
  161.   local newLocation = {x = newX, y = newY, z = newZ, direction = newDir}
  162.   local moved = false
  163.  
  164.   while not compareLocations(location, newLocation, false) and blockages < 10 do
  165.     sendStatus("Moving to "..name.. ":\n["..newX..", "..newY..", "..newZ..", "..newDir.."]")
  166.     -- move to new Y location
  167.     while location.y ~= newY do
  168.       if location.y > newY then
  169.         moved = moveDown()
  170.       elseif location.y < newY then
  171.         moved = moveUp()
  172.       end
  173.       if not moved then
  174.         blockages = blockages +1
  175.         break
  176.       end
  177.     end
  178.     -- move to new X location
  179.     while location.x ~= newX do
  180.       if location.x > newX then
  181.         if getGlobalRotation() ~= 3 then rotateToGlobal(3) end
  182.         moved = moveForward()
  183.       elseif location.x < newX then
  184.         if getGlobalRotation() ~= 1 then rotateToGlobal(1) end
  185.         moved = moveForward()
  186.       end
  187.       if not moved then
  188.         blockages = blockages + 1
  189.         break
  190.       end
  191.     end
  192.     -- move to new Z location
  193.     while location.z ~= newZ do
  194.       if location.z > newZ then
  195.         if getGlobalRotation() ~= 2 then rotateToGlobal(2) end
  196.         moved = moveForward()
  197.       elseif location.z < newZ then
  198.         if getGlobalRotation() ~= 0 then rotateToGlobal(0) end
  199.         moved = moveForward()
  200.       end
  201.       if not moved then
  202.         blockages = blockages + 1
  203.         break
  204.       end
  205.     end
  206.   end
  207.   rotateTo(newDir)
  208.   return compareLocations(location, newLocation)
  209. end
  210.  
  211. function compareLocations(tab1, tab2, includeRotation)
  212.   if includeRotation then
  213.     return tab1.x == tab2.x and tab1.y == tab2.y and tab1.z == tab2.z and tab1.direction == tab2.direction
  214.   else
  215.     return tab1.x == tab2.x and tab1.y == tab2.y and tab1.z == tab2.z
  216.   end
  217. end
  218.  
  219. function locationNil(tab)
  220.   return not tab.x or not tab.y or not tab.z or not tab.direction
  221. end
  222.  
  223. function rotateLeft()
  224.   location.direction = location.direction-1
  225.   if (location.direction == -1) then
  226.     location.direction = 3
  227.   end
  228.   turtle.turnLeft()
  229. end
  230.  
  231. function rotateRight()
  232.   location.direction = location.direction+1
  233.   if (location.direction == 4) then
  234.     location.direction = 0
  235.   end
  236.   turtle.turnRight()
  237. end
  238.  
  239. function rotateTo(newDir)
  240.   if location.direction == newDir then
  241.     return
  242.   elseif (location.direction + 1) % 4 == newDir then
  243.     rotateRight()
  244.   elseif (location.direction - 1) % 4 == newDir then
  245.     rotateLeft()
  246.   else
  247.     while location.direction ~= newDir do
  248.       rotateLeft()
  249.     end
  250.   end
  251. end
  252.  
  253. function rotateToGlobal(newDir)
  254.   local globalRotation = getGlobalRotation()
  255.   print("Rotating to ".. newDir)
  256.   if globalRotation == newDir then
  257.     return
  258.   elseif (globalRotation + 1) % 4 == newDir then
  259.     rotateRight()
  260.   elseif (globalRotation - 1) % 4 == newDir then
  261.     rotateLeft()
  262.   else
  263.     while getGlobalRotation() ~= newDir do
  264.       rotateLeft()
  265.     end
  266.   end
  267. end
  268.  
  269. function moveForward()
  270.   -- if able to dig clear out blocks in front
  271.   if canDig() then
  272.     while turtle.detect() do
  273.       turtle.dig()
  274.     end
  275.   end
  276.   moved = turtle.forward()
  277.   if moved then
  278.     rotation = getGlobalRotation()
  279.     if rotation == 0 then
  280.       location.z = location.z+1
  281.     elseif rotation == 1 then
  282.       location.x = location.x+1
  283.     elseif rotation == 2 then
  284.       location.z = location.z-1
  285.     elseif rotation == 3 then
  286.       location.x = location.x-1
  287.     end
  288.     return true
  289.   else
  290.     return false
  291.   end
  292. end
  293.  
  294. -- returns true on valid movement
  295. function moveUp()
  296.   if canDig() then
  297.     while turtle.detectUp() do
  298.       turtle.digUp()
  299.     end
  300.   end
  301.   local moved = turtle.up()
  302.   if not moved then return false end
  303.   location.y = location.y + 1
  304.   return true
  305. end
  306.  
  307. function moveDown()
  308.   if canDig() then
  309.     while turtle.detectDown() do
  310.       turtle.digDown()
  311.     end
  312.   end
  313.   local moved = turtle.down()
  314.   if not moved then return false end
  315.   location.y = location.y - 1
  316.   return true
  317. end
  318.  
  319. function currentPosition()
  320.   local direction = location.direction or -1
  321.   local x, y, z
  322.   if not x or not y or not z then
  323.     x, y, z = gps.locate()
  324.   else
  325.     x = location.x
  326.     y = location.y
  327.     z = location.z
  328.   end
  329.   return "[".. x..", ".. y..", ".. z..", ".. direction .."]"
  330. end
  331.  
  332. function returnHome()
  333.   local returnedHome = moveToPosition(home.x, home.y, home.z, home.direction, "Home")
  334.   if not returnedHome then
  335.     sendStatus("I'm stuck ;-;")
  336.     error()
  337.   end
  338. end
  339.  
  340. function returnToWork()
  341.   if locationNil(work) then
  342.     sendStatus("attempted to return to work when I have no work location")
  343.     error()
  344.   end
  345.   local returnedToWork = moveToPosition(work.x, work.x, work.z, work.direction, "Work")
  346.   if not returnedToWork then
  347.     sendStatus("I'm stuck ;-;")
  348.     error()
  349.   end
  350. end
  351.  
  352. function getValidToolText()
  353.   local text = ""
  354.   for k, v in pairs(validTools) do
  355.     if text ~= "" then text = text.. ", " end
  356.     text = text .. v
  357.   end
  358.   return text
  359. end
  360.  
  361. function getTools()
  362.   local complete = false
  363.   local toolText = "Valid Tools: ".. getValidToolText()
  364.   local sides = peripheral.getNames()
  365.   if tableContains("left", sides) then
  366.     complete = true
  367.     tools.left = validTools.modem
  368.   end
  369.   while not complete do
  370.     term.clear()
  371.     term.setCursorPos(1,1)
  372.     print(toolText)
  373.     io.write("Enter Left Tool: ")
  374.     local leftTool = io.read()
  375.     local valid, leftTool = validTool(leftTool)
  376.     if valid then
  377.       complete = true
  378.       tools.left = leftTool
  379.     end
  380.   end
  381.   complete = false
  382.   if tableContains("right", sides) then
  383.     complete = true
  384.     tools.right = validTools.modem
  385.   end
  386.   while not complete do
  387.     term.clear()
  388.     term.setCursorPos(1,1)
  389.     print(toolText)
  390.     io.write("Enter Right Tool: ")
  391.     local rightTool = io.read()
  392.     local valid, rightTool = validTool(rightTool)
  393.     if valid then
  394.       complete = true
  395.       tools.right = rightTool
  396.     end
  397.   end
  398. end
  399.  
  400. function validTool(tool)
  401.   for k,v in pairs(validTools) do
  402.     if string.lower(v) == string.lower(tool) then
  403.       return true, v
  404.     end
  405.   end
  406.   return false, validTools.none
  407. end
  408.  
  409. function tableContains(str, table)
  410.   for k, v in pairs(table) do
  411.     if v == str then return true end
  412.   end
  413.   return false
  414. end
  415.  
  416. function resetSettings()
  417.   settings.load("settings")
  418.   settings.clear()
  419.   settings.save("settings")
  420. end
  421.  
  422. function findItem(id)
  423.   local itemTable = {}
  424.   for i = 1, 16, 1 do
  425.     local slotData = turtle.getItemDetail(i)
  426.     if (slotData and slotData.name == id) then
  427.       table.insert(itemTable, i)
  428.     end
  429.   end
  430.   if table.getn(itemTable) > 0 then
  431.     return itemTable
  432.   end
  433.   return nil
  434. end
  435.  
  436. -- returns true if empty slot was found ant item was moved
  437. function moveItemToEmpty(slot)
  438.   turtle.select(slot)
  439.   for i = 1, 16, 1 do
  440.     if i ~= slot then
  441.       if turtle.transferTo(i) then
  442.         return true
  443.       end
  444.     end
  445.   end
  446.   return false
  447. end
  448.  
  449. -- returns true if space remains
  450. function checkSpace()
  451.   for i = 1, 16, 1 do
  452.     if not turtle.getItemDetail(i) then
  453.       return true
  454.     end
  455.   end
  456.   return false
  457. end
  458.  
  459. function minifyStacks()
  460.   for i = 16, 1, -1 do
  461.     local slotData = turtle.getItemDetail(i)
  462.     if slotData then
  463.       slotsTable = findItem(slotData.name)
  464.       if slotsTable and table.getn(slotsTable) > 1 then
  465.         for k,v in pairs(slotsTable or {}) do
  466.           turtle.select(v)
  467.           turtle.transferTo(i, turtle.getItemSpace(i))
  468.         end
  469.       end
  470.     end
  471.   end
  472. end
  473.  
  474. -- returns home and requests more fuel
  475. function giveMeFuel()
  476.   while not hasFuel() do
  477.     sleep(2)
  478.   end
  479.   returnToWork()
  480. end
  481.  
  482. -- attempts to fill fuel slot, returns true if enough fuel is located in the fuel slot.
  483. function hasFuel()
  484.   local fuelSlots = {}
  485.  
  486.   local slotData = turtle.getItemDetail(1)
  487.   -- search the first slot for a valid fuel item
  488.   for k,v in pairs(fuel or {}) do
  489.     -- find if any other slots contain any fuel
  490.     local slotTable = findItem(v)
  491.     table.insert(fuelSlots, slotTable)
  492.  
  493.     -- look in slot one, if contains fuel return
  494.     if (slotData and slotData.name == v) then
  495.       return turtle.getItemCount(1) > 1, slotTable
  496.     end
  497.   end
  498.  
  499.   -- move item out of fuel slot
  500.   if slotData then
  501.     moveItemToEmpty(1)
  502.   end
  503.  
  504.   -- move valid fuel into slot
  505.   for k,v in pairs(fuelSlots or {}) do
  506.     if v then
  507.       if table.getn(v) > 0 then
  508.         turtle.select(v[1])
  509.         turtle.transferTo(1)
  510.       end
  511.       return turtle.getItemCount(1) > 1, v
  512.     end
  513.   end
  514.   return false, nil
  515. end
  516.  
  517. function isFuel(slotData)
  518.   for k,v in pairs(fuel or {}) do
  519.     if slotData.name == v then return true end
  520.   end
  521.   return false
  522. end
  523.  
  524. function getMinFuelLevel()
  525.   if locationNil(work) or locationNil(home) then return 800 end
  526.   return math.abs(work.x) + math.abs(work.z) + math.abs(home.y - work.y) + 50
  527. end
  528.  
  529. -- checks fuel levels and attempts to refuel the turtle
  530. function refuel()
  531.   local hasFuelLeft, fuelSlots = hasFuel()
  532.   if turtle.getFuelLevel() < getMinFuelLevel() then
  533.     if not hasFuelLeft then
  534.       giveMeFuel()
  535.     end
  536.   end
  537.  
  538.   if turtle.getFuelLevel() < 5120 then
  539.     turtle.select(1)
  540.     coalCount = turtle.getItemCount(1)
  541.     if coalCount > 0 then turtle.refuel(coalCount-1) end
  542.   end
  543. end
  544.  
  545. function offsetFromHome()
  546.   return {x = home.x - location.x, y = home.y - location.y, z = home.z - location.z}
  547. end
  548.  
  549. function getListeners()
  550.   listeners = {rednet.lookup("turtle_status")}
  551.   if listeners then
  552.     for k, v in pairs(listeners) do
  553.       rednet.send(v, "request_connect")
  554.     end
  555.   end
  556. end
  557.  
  558. function sendStatus(status)
  559.   for k, v in pairs(listeners) do
  560.     rednet.send(v, status.. "\n" .. currentPosition())
  561.   end
  562. end
  563.  
  564. function dumpExtraStacks(itemId)
  565.   items = findItem(itemId)
  566.   if items and #items > 1 then
  567.     for i = 2, #items, 1 do
  568.       turtle.select(items[i])
  569.       turtle.drop()
  570.     end
  571.   end
  572. end
  573.  
  574. function openRednet()
  575.   side = getModemSide()
  576.   if not side then error("could not find modem") end
  577.   rednet.open(side, 255)
  578. end
  579.  
  580. function getModemSide()
  581.   sides = peripheral.getNames()
  582.   for k, v in pairs(sides) do
  583.     if peripheral.getType(v) == "modem" then return v end
  584.   end
  585.   return nil
  586. end
  587.  
  588. function initRednet()
  589.   term.clear()
  590.   term.setCursorPos(1,1)
  591.   print("Initialising Rednet System")
  592.   openRednet()
  593.   getListeners()
  594. end
  595.  
  596. 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}
  597.  
RAW Paste Data