Forte40

Turtle Movement API

Aug 19th, 2014
305
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 13.64 KB | None | 0 0
  1. -- allow for direct manipulation of the global environment of the calling script
  2. local env = {}
  3. setmetatable(env, {__index = _G})
  4. setfenv(2, env)
  5. setfenv(1, env)
  6.  
  7. loadfile("config")()
  8.  
  9. -- check if API already loaded
  10. if turtle and not turtle.act then
  11.   turtle.act = true
  12.  
  13.   -- replace os.pullEvent to not eat events
  14.   -- this breaks the parellel api
  15.   os.pullEvent = function (...)
  16.     local events = {}
  17.     local event
  18.     while true do
  19.       event = {os.pullEventRaw()}
  20.       if event[1] == "terminate" then
  21.         error("Terminated", 0)
  22.       end
  23.       local matched = true
  24.       for i = 1, arg.n do
  25.         if arg[i] and arg[i] ~= event[i] then
  26.           matched = false
  27.           break
  28.         end
  29.       end
  30.       if matched then
  31.         for i, e in ipairs(events) do
  32.           os.queueEvent(unpack(e))
  33.         end
  34.         return unpack(event)
  35.       elseif event[1] == "modem_message" then
  36.         table.insert(events, event)
  37.       end
  38.     end
  39.   end
  40.  
  41.   -- replace sleep function
  42.   sleep = function (time)
  43.     local timer = os.startTimer(time)
  44.     event = os.pullEvent("timer", timer)
  45.   end  
  46.  
  47.   -- track relative direction and coordinates
  48.   turtle.x = 0
  49.   turtle.y = 0
  50.   turtle.z = 0
  51.   turtle.facing = 0
  52.   turtle.fuel = turtle.getFuelLevel()
  53.   -- how much to change x and z when moving in a direction                      
  54.   local coord_change = {[0] = { 0,  1}, -- south / forward
  55.                         [1] = {-1,  0}, -- west  / right
  56.                         [2] = { 0, -1}, -- north / behind
  57.                         [3] = { 1,  0}} -- east  / left
  58.  
  59.   turtle.setLocation = function (x, y, z, facing)
  60.     turtle.x = x or 0
  61.     turtle.y = y or 0
  62.     turtle.z = z or 0
  63.     turtle.facing = facing or turtle.facing
  64.     turtle.saveLocation()
  65.   end
  66.  
  67.   turtle.saveLocation = function (move)
  68.     config.save(".act.location", {x=turtle.x, y=turtle.y, z=turtle.z, facing=turtle.facing,
  69.                           fuel=turtle.getFuelLevel(), selected=turtle.getSelectedSlot(), move=move})
  70.     turtle.move = nil
  71.   end
  72.  
  73.   turtle.loadLocation = function ()
  74.     local loc = config.load(".act.location")
  75.     if loc then
  76.       turtle.x = loc.x
  77.       turtle.y = loc.y
  78.       turtle.z = loc.z
  79.       turtle.facing = loc.facing
  80.       turtle.fuel = loc.fuel
  81.       if turtle.getSelectedSlot() ~= loc.selected then
  82.         turtle.select(loc.selected)
  83.       end
  84.       turtle.move = loc.move
  85.     end
  86.   end
  87.   turtle.loadLocation()
  88.  
  89.   turtle.updateLocation = function ()
  90.     if turtle.move then
  91.       local currFuel = turtle.getFuelLevel()
  92.       if turtle.fuel == currFuel and turtle.move ~= "l" and turtle.move ~= "r" then
  93.         return false -- no update occured
  94.       elseif turtle.fuel == currFuel + 1 or turtle.move ~= "l" or turtle.move ~= "r"  then
  95.         turtle.update(turtle.move)
  96.         return true -- location updated
  97.       else
  98.         -- server rollback?
  99.         error("possible server rollback, aborted")
  100.         return nil
  101.       end
  102.     else
  103.       return false -- no update occured
  104.     end
  105.   end
  106.  
  107.   -- waypoints ----------------------------------------------------------------
  108.   turtle.waypoint = {}
  109.   turtle.loadWaypoints = function ()
  110.     local waypoints = config.load(".act.waypoint")
  111.     if waypoints then
  112.       turtle.waypoint = waypoints
  113.     end
  114.   end
  115.   turtle.loadWaypoints()
  116.  
  117.   turtle.setWaypoint = function (name, x, y, z, facing)
  118.     if y ~= nil and z ~= nil then
  119.       -- absolute coordinates
  120.       turtle.waypoint[name] = {x=x, y=y, z=z, facing=facing}
  121.     else
  122.       -- current coordinates
  123.       local useFacing = x
  124.       if useFacing == nil then useFacing = true end
  125.       if useFacing then
  126.         turtle.waypoint[name] = {x=turtle.x, y=turtle.y, z=turtle.z, facing=turtle.facing}
  127.       else
  128.         turtle.waypoint[name] = {x=turtle.x, y=turtle.y, z=turtle.z}
  129.       end
  130.     end
  131.     config.save(".act.waypoint", turtle.waypoint)
  132.   end
  133.  
  134.   turtle.goToWaypoint = function (x, y, z, facing, priority)
  135.     return toWaypoint(x, y, z, facing, priority, turtle.goForward, turtle.goUp, turtle.goDown)
  136.   end
  137.  
  138.   turtle.moveToWaypoint = function (x, y, z, facing, priority)
  139.     return toWaypoint(x, y, z, facing, priority, turtle.moveForward, turtle.moveUp, turtle.moveDown)
  140.   end
  141.  
  142.   turtle.toWaypoint = function (x, y, z, facing, priority)
  143.     return toWaypoint(x, y, z, facing, priority, turtle.forward, turtle.up, turtle.down)
  144.   end
  145.  
  146.   turtle.distanceTo = function (x, y, z)
  147.     local waypoint = {x=x, y=y, z=z}
  148.     if type(x) == "string" then
  149.       if turtle.waypoint[x] then
  150.         waypoint = turtle.waypoint[x]
  151.       else
  152.         return nil
  153.       end
  154.       return math.abs(turtle.x - waypoint.x) + math.abs(turtle.y - waypoint.y) + math.abs(turtle.z - waypoint.z)
  155.     end
  156.   end
  157.  
  158.   function toWaypoint (x, y, z, facing, priority, forward, up, down)
  159.     local waypoint = {x=x, y=y, z=z, facing=facing}
  160.     if type(x) == "string" then
  161.       if turtle.waypoint[x] then
  162.         waypoint = turtle.waypoint[x]
  163.         priority = y
  164.       else
  165.         return false
  166.       end
  167.     end
  168.     turtle.updateLocation()
  169.     -- go to coordinates
  170.     if type(priority) ~= "string" or
  171.         not priority:find("x") or
  172.         not priority:find("y") or
  173.         not priority:find("z") or
  174.         #priority ~= 3 then
  175.       priority = "yxz"
  176.     end
  177.  
  178.     for c in priority:gmatch(".") do
  179.       if c == "y" then
  180.         -- move up or down
  181.         local dy = waypoint.y - turtle.y
  182.         if dy > 0 then
  183.           for i = 1, dy do
  184.             up()
  185.           end
  186.         elseif dy < 0 then
  187.           for i = 1, -dy do
  188.             down()
  189.           end
  190.         end
  191.       elseif c == "x" then
  192.         -- move east or west
  193.         local dx = waypoint.x - turtle.x
  194.         if dx > 0 then -- east
  195.           turtle.face(3)
  196.           for i = 1, dx do
  197.             forward()
  198.           end
  199.         elseif dx < 0 then -- west
  200.           turtle.face(1)
  201.           for i = 1, -dx do
  202.             forward()
  203.           end
  204.         end
  205.       elseif c == "z" then
  206.         -- move north or south
  207.         local dz = waypoint.z - turtle.z
  208.         if dz > 0 then -- south
  209.           turtle.face(0)
  210.           for i = 1, dz do
  211.             forward()
  212.           end
  213.         elseif dz < 0 then -- north
  214.           turtle.face(2)
  215.           for i = 1, -dz do
  216.             forward()
  217.           end
  218.         end
  219.       end
  220.     end
  221.  
  222.     -- face proper direction
  223.     if waypoint.facing then
  224.       turtle.face(waypoint.facing)
  225.     end
  226.  
  227.     return true
  228.   end
  229.  
  230.   turtle.gps = function (getFacing)
  231.     local x, y, z = gps.locate()
  232.     if x ~= nil then
  233.       turtle.x = x
  234.       turtle.y = y
  235.       turtle.z = z
  236.       if getFacing then
  237.           turtle.forward()
  238.           local dx, dy, dz = gps.locate()
  239.           if dx ~= nil then
  240.             if x == dx then
  241.               if z < dz then
  242.                 turtle.facing = 0  --south
  243.               else
  244.                 turtle.facing = 2  --north
  245.               end
  246.             else
  247.               if x < dx then
  248.                 turtle.facing = 3  --east
  249.               else
  250.                 turtle.facing = 1  --west
  251.               end
  252.             end
  253.           end
  254.           turtle.back()
  255.         end
  256.       return true
  257.     else
  258.       return false
  259.     end
  260.   end
  261.  
  262.   turtle.update = function (move)
  263.     if move == "f" then
  264.       turtle.x = turtle.x + coord_change[turtle.facing][1]
  265.       turtle.z = turtle.z + coord_change[turtle.facing][2]
  266.       turtle.fuel = turtle.fuel - 1
  267.     elseif move == "b" then
  268.       turtle.x = turtle.x - coord_change[turtle.facing][1]
  269.       turtle.z = turtle.z - coord_change[turtle.facing][2]
  270.       turtle.fuel = turtle.fuel - 1
  271.     elseif move == "u" then
  272.       turtle.y = turtle.y + 1
  273.       turtle.fuel = turtle.fuel - 1
  274.     elseif move == "d" then
  275.       turtle.y = turtle.y - 1
  276.       turtle.fuel = turtle.fuel - 1
  277.     elseif move == "l" then
  278.       turtle.facing = (turtle.facing - 1) % 4
  279.     elseif move == "r" then
  280.       turtle.facing = (turtle.facing + 1) % 4
  281.     end
  282.     turtle.saveLocation()
  283.   end
  284.  
  285.   turtle.face = function (facing)
  286.     local new_facing = (facing - turtle.facing) % 4
  287.     if new_facing == 1 then
  288.         turtle.turnRight()
  289.     elseif new_facing == 2 then
  290.         turtle.turnRight()
  291.         turtle.turnRight()
  292.     elseif new_facing == 3 then
  293.         turtle.turnLeft()
  294.     end
  295.   end
  296.  
  297.   -- replace movement functions
  298.   turtle._turnLeft = turtle.turnLeft
  299.   turtle.turnLeft = function ()
  300.     turtle.saveLocation("l")
  301.     if turtle._turnLeft() then
  302.       turtle.update("l")
  303.       return true
  304.     else
  305.       turtle.saveLocation()
  306.       return false
  307.     end
  308.   end
  309.  
  310.   turtle._turnRight = turtle.turnRight
  311.   turtle.turnRight = function ()
  312.     turtle.saveLocation("r")
  313.     if turtle._turnRight() then
  314.       turtle.update("r")
  315.       return true
  316.     else
  317.       turtle.saveLocation()
  318.       return false
  319.     end
  320.   end
  321.  
  322.   turtle._forward = turtle.forward
  323.   turtle.forward = function ()
  324.     turtle.saveLocation("f")
  325.     if turtle._forward() then
  326.       turtle.update("f")
  327.       return true
  328.     else
  329.       turtle.saveLocation()
  330.       return false
  331.     end
  332.   end
  333.  
  334.   turtle._back = turtle.back
  335.   turtle.back = function ()
  336.     turtle.saveLocation("b")
  337.     if turtle._back() then
  338.       turtle.update("b")
  339.       return true
  340.     else
  341.       turtle.saveLocation()
  342.       return false
  343.     end
  344.   end
  345.  
  346.   turtle._up = turtle.up
  347.   turtle.up = function ()
  348.     turtle.saveLocation("u")
  349.     if turtle._up() then
  350.       turtle.update("u")
  351.       return true
  352.     else
  353.       turtle.saveLocation()
  354.       return false
  355.     end
  356.   end
  357.  
  358.   turtle._down = turtle.down
  359.   turtle.down = function ()
  360.     turtle.saveLocation("d")
  361.     if turtle._down() then
  362.       turtle.update("d")
  363.       return true
  364.     else
  365.       turtle.saveLocation()
  366.       return false
  367.     end
  368.   end
  369.  
  370.   turtle._refuel = turtle.refuel
  371.   turtle.refuel = function (...)
  372.     turtle._refuel(...)
  373.     turtle.fuel = turtle.getFuelLevel()
  374.     turtle.saveLocation()
  375.   end
  376.  
  377.   turtle._select = turtle.select
  378.   turtle.select = function (slot)
  379.     if turtle._select(slot) then
  380.       turtle.selected = slot
  381.       return slot
  382.     end
  383.   end
  384.  
  385.   turtle._getItemSpace = turtle.getItemSpace
  386.   turtle.getItemSpace = function (slot)
  387.     slot = slot or turtle.getSelectedSlot()
  388.     return turtle._getItemSpace(slot)
  389.   end
  390.  
  391.   turtle._getItemCount = turtle.getItemCount
  392.   turtle.getItemCount = function (slot)
  393.     slot = slot or turtle.getSelectedSlot()
  394.     return turtle._getItemCount(slot)
  395.   end
  396.  
  397.   -- Go, move or wait to be cleared
  398.   turtle.goForward = function ()
  399.     while not turtle.forward() do
  400.       sleep(1)
  401.     end
  402.     return true
  403.   end
  404.  
  405.   turtle.goBack = function ()
  406.     while not turtle.back() do
  407.       sleep(1)
  408.     end
  409.     return true
  410.   end
  411.  
  412.   turtle.goUp = function ()
  413.     while not turtle.up() do
  414.       sleep(1)
  415.     end
  416.     return true
  417.   end
  418.  
  419.   turtle.goDown = function ()
  420.     while not turtle.down() do
  421.       sleep(1)
  422.     end
  423.     return true
  424.   end
  425.  
  426.  
  427.   -- Move, move or dig or attack until moved
  428.   turtle.moveForward = function ()
  429.     while not turtle.forward() do
  430.       if turtle.detect() then
  431.         turtle.dig()
  432.       else
  433.         turtle.attack()
  434.       end
  435.     end
  436.     return true
  437.   end
  438.  
  439.   turtle.moveUp = function ()
  440.     while not turtle.up() do
  441.       if turtle.detectUp() then
  442.         turtle.digUp()
  443.       else
  444.         turtle.attackUp()
  445.       end
  446.     end
  447.     return true
  448.   end
  449.  
  450.   turtle.moveDown = function ()
  451.     while not turtle.down() do
  452.       if turtle.detectDown() then
  453.         turtle.digDown()
  454.       else
  455.         turtle.attackDown()
  456.       end
  457.     end
  458.     return true
  459.   end
  460.  
  461.   turtle.findSimilar = function ()
  462.     for s = 1, 16 do
  463.       if s ~= turtle.getSelectedSlot() then
  464.         if turtle.compareTo(s) then
  465.           return s
  466.         end
  467.       end
  468.     end
  469.     return nil
  470.   end
  471.  
  472.   -- Build, place block with automatic resupply if needed
  473.   turtle.build = function ()
  474.     if turtle.getItemCount(turtle.getSelectedSlot()) == 1 then
  475.       local resupplySlot = turtle.findSimilar()
  476.       if resupplySlot then
  477.         if turtle.place() then
  478.           local currentSlot = turtle.getSelectedSlot()
  479.           turtle.select(resupplySlot)
  480.           turtle.transferTo(currentSlot, turtle.getItemCount(resupplySlot))
  481.           turtle.select(currentSlot)
  482.           return true
  483.         else
  484.           return false
  485.         end
  486.       else
  487.         return turtle.place()
  488.       end
  489.     else
  490.       return turtle.place()
  491.     end
  492.   end
  493.  
  494.   turtle.buildUp = function ()
  495.     if turtle.getItemCount(turtle.getSelectedSlot()) == 1 then
  496.       local resupplySlot = turtle.findSimilar()
  497.       if resupplySlot then
  498.         if turtle.placeUp() then
  499.           local currentSlot = turtle.getSelectedSlot()
  500.           turtle.select(resupplySlot)
  501.           turtle.transferTo(currentSlot, turtle.getItemCount(resupplySlot))
  502.           turtle.select(currentSlot)
  503.           return true
  504.         else
  505.           return false
  506.         end
  507.       else
  508.         return turtle.placeUp()
  509.       end
  510.     else
  511.       return turtle.placeUp()
  512.     end
  513.   end
  514.  
  515.   turtle.buildDown = function ()
  516.     if turtle.getItemCount(turtle.getSelectedSlot()) == 1 then
  517.       local resupplySlot = turtle.findSimilar()
  518.       if resupplySlot then
  519.         if turtle.placeDown() then
  520.           local currentSlot = turtle.getSelectedSlot()
  521.           turtle.select(resupplySlot)
  522.           turtle.transferTo(currentSlot, turtle.getItemCount(resupplySlot))
  523.           turtle.select(currentSlot)
  524.           return true
  525.         else
  526.           return false
  527.         end
  528.       else
  529.         return turtle.placeDown()
  530.       end
  531.     else
  532.       return turtle.placeDown()
  533.     end
  534.   end
  535.  
  536. end
Advertisement
Add Comment
Please, Sign In to add comment