diff --git a/apis/builder/turtle.lua b/apis/builder/turtle.lua index b512a73..bb0847f 100644 --- a/apis/builder/turtle.lua +++ b/apis/builder/turtle.lua @@ -440,7 +440,7 @@ function TurtleBuilder:inAirDropoff() self:log('Received supply location') os.sleep(0) - turtle._goto(pt.x, pt.z, pt.y) + turtle._goto(pt) os.sleep(.1) -- random computer is not connected error local chestAdapter = Adapter.wrap({ direction = 'down', wrapSide = 'top' }) @@ -502,7 +502,7 @@ function TurtleBuilder:inAirResupply() self:log('Received supply location') os.sleep(0) - turtle._goto(pt.x, pt.z, pt.y) + turtle._goto(pt) os.sleep(.1) -- random computer is not connected error local chestAdapter = Adapter.wrap({ direction = 'down', wrapSide = 'top' }) @@ -553,12 +553,11 @@ function TurtleBuilder:sendSupplyRequest(lastBlock) if device.wireless_modem then local slots = self:getAirResupplyList(lastBlock) self.slotUid = os.clock() - Message.broadcast('supplyList', { uid = self.slotUid, slots = slots }) end end -local function closestEdgePoint(pt, pts, rpt) +local function closestEdgePoint(pt, pts, rpt, y) pt = Point.copy(pt) pt.heading = rpt.heading @@ -583,16 +582,18 @@ local function closestEdgePoint(pt, pts, rpt) cpt.z = rpt.z end + cpt.y = y return cpt end function TurtleBuilder:getBuildingCorner(y) - local box = { - x = -1, ex = self.schematic.width, - y = y, ey = y, - z = -1, ez = self.schematic.length, + local pts = { + { x = -1, z = -1, y = 0 }, + { x = -1, z = self.schematic.length, y = 0 }, + { x = self.schematic.width, z = -1, y = 0 }, + { x = self.schematic.width, z = self.schematic.length, y = 0 }, } - return Point.closestPointInBox(turtle.getPoint(), box) + return closestEdgePoint(self.supplyPoint, pts, turtle.getPoint(), y) end function TurtleBuilder:gotoSupplyPoint() @@ -601,7 +602,7 @@ function TurtleBuilder:gotoSupplyPoint() -- go to the corner closest to the supplies point -- pathfind the rest of the way local pt = self:getBuildingCorner(turtle.point.y) - turtle._goto(pt.x, pt.z) + turtle._goto({ x = pt.x, z = pt.z }) turtle.setPolicy('none') turtle.pathfind(self.supplyPoint) os.sleep(.1) -- random 'Computer is not connected' error... @@ -809,7 +810,7 @@ function TurtleBuilder:placePiston(b) end function TurtleBuilder:_goto(x, z, y, heading) - if not turtle._goto(x, z, y, heading) then + if not turtle._goto({ x = x, z = z, y = y, heading = heading }) then print('stuck') print('Press enter to continue') os.sleep(1) diff --git a/apis/turtle/home.lua b/apis/turtle/home.lua new file mode 100644 index 0000000..29a1cbc --- /dev/null +++ b/apis/turtle/home.lua @@ -0,0 +1,42 @@ +local Config = require('config') +local GPS = require('gps') + +local turtle = _G.turtle + +local Home = { } + +function Home.go() + local config = { } + Config.load('gps', config) + + if config.home then + if turtle.enableGPS() then + return turtle.pathfind(config.home) + end + end +end + +function Home.set() + local config = { } + Config.load('gps', config) + + local pt = GPS.getPoint() + if pt then + local originalHeading = turtle.point.heading + local heading = GPS.getHeading() + if heading then + local turns = (turtle.point.heading - originalHeading) % 4 + pt.heading = (heading - turns) % 4 + config.home = pt + Config.update('gps', config) + + pt = GPS.getPoint() + pt.heading = heading + turtle.setPoint(pt, true) + turtle._goto(config.home) + return config.home + end + end +end + +return Home diff --git a/apis/turtle/level.lua b/apis/turtle/level.lua index 45d077d..452f251 100644 --- a/apis/turtle/level.lua +++ b/apis/turtle/level.lua @@ -158,7 +158,7 @@ function turtle.level(startPt, endPt, firstPt, verbose) local node = closestPoint(turtle.point, nodes) node = getAdjacentPoint(node) - if not turtle.gotoPoint(node) then + if not turtle._goto(node) then break end until turtle.isAborted() diff --git a/apps/crafter.lua b/apps/crafter.lua index 9c6f367..1444724 100644 --- a/apps/crafter.lua +++ b/apps/crafter.lua @@ -44,6 +44,16 @@ local function getItem(items, inItem, ignoreDamage) end end +local function getItemCount(items, inItem) + inItem.count = 0 + for _,item in pairs(items) do + if item.name == inItem.name and item.damage == inItem.damage and item.nbtHash == inItem.nbtHash then + inItem.count = item.count + break + end + end +end + local function uniqueKey(item) return table.concat({ item.name, item.damage, item.nbtHash }, ':') end @@ -107,69 +117,138 @@ local function clearGrid() end local function gotoMachine(machine) - - local index - if type(machine) == 'number' then - index = machine - else - local _, k = Util.find(machines, 'name', machine) - - if not k then - error('Unable to locate machine: ' .. tostring(machine)) + for _ = 1, machine do + if not turtle.back() then + return end - index = k - 1 - end - - for _ = 1, index do - turtle.back() end + return true end local function canCraft(recipe, items, count) count = math.ceil(count / recipe.count) + local icount = Util.size(recipe.ingredients) + local maxSlots = math.floor(16 / icount) +debug(maxSlots) for key,qty in pairs(recipe.ingredients) do local item = getItem(items, itemDB:splitKey(key)) if not item then return 0, itemDB:getName(key) end - local x = math.min(math.floor(item.count / qty), item.maxCount) + local x = math.min(math.floor(item.count / qty), item.maxCount * maxSlots) count = math.min(x, count) +debug(count) end - return count + return count, '' end local function craftItem(recipe, items, cItem, count) repeat until not turtle.forward() - local missing - count, missing = canCraft(recipe, items, count) +-- local missing +-- count, missing = canCraft(recipe, items, count) +-- if count == 0 then +-- cItem.status = 'missing ' .. missing +-- return false +-- end if count == 0 then - cItem.status = 'missing ' .. missing + cItem.status = 'missing something' return false end local slot = 1 for key,qty in pairs(recipe.ingredients) do - local item = itemDB:splitKey(key) - inventoryAdapter:provide(item, count * qty, slot) - if turtle.getItemCount(slot) ~= count * qty then - cItem.status = 'failed' - return false + local item = itemDB:get(key) + local c = count * qty + while c > 0 do + local maxCount = math.min(c, item.maxCount) + inventoryAdapter:provide(item, maxCount, slot) + if turtle.getItemCount(slot) == 0 then -- ~= maxCount then FIXXX !!! + cItem.status = 'failed' +debug(item) +debug({ c, maxCount, count }) +read() + return false + end + c = c - maxCount + slot = slot + 1 end - slot = slot + 1 end - gotoMachine(recipe.machine) - turtle.emptyInventory(turtle.dropDown) - if #turtle.getFilledSlots() ~= 0 then - cItem.status = 'machine busy' + if not gotoMachine(recipe.machine) then + cItem.status = 'failed to find machine' else - cItem.status = 'crafting' + turtle.emptyInventory(turtle.dropDown) + if #turtle.getFilledSlots() ~= 0 then + cItem.status = 'machine busy' + else + cItem.status = 'crafting' + end + end +end + +local function expandList(list) + local items = lastItems + + local function getCraftable(recipe, count) + local maxSlots = math.floor(16 / Util.size(recipe.ingredients)) + + for key,qty in pairs(recipe.ingredients) do + local item = getItem(items, itemDB:splitKey(key)) + if not item then + item = itemDB:get(key) + item.count = 0 + end + local need = qty * count +debug({ key, count, need }) + local irecipe = recipes[key] + if item.count < need and irecipe then + need = math.ceil((need - item.count) / irecipe.count) + if not list[key] then + list[key] = Util.shallowCopy(item) + list[key].ocount = need + list[key].count = 0 + else + list[key].ocount = list[key].ocount + need + end +debug('adding ' .. key .. ' ' .. need) + local icount = getCraftable(irecipe, need) + + list[key].count = list[key].count + icount + end + local x = math.min(math.floor(item.count / qty), item.maxCount * maxSlots) + count = math.min(x, count) + item.count = math.max(0, item.count - (count * qty)) + end + + return count + end + +--[[ +list = { } +debug(getCraftable(recipes['minecraft:brick:0'], 512)) +for key, item in pairs(list) do + debug(item.name .. ' : ' .. item.ocount .. ':' .. item.count) +end +read() +]] + + for key, item in pairs(Util.shallowCopy(list)) do + local recipe = recipes[key] + item.count = math.ceil(item.count / recipe.count) + item.ocount = item.count + if recipe then + item.count = getCraftable(recipe, item.count) + end end end local function craftItems(craftList) + expandList(craftList) + jobListGrid:update() + jobListGrid:draw() + jobListGrid:sync() for key, item in pairs(craftList) do local recipe = recipes[key] if recipe then @@ -304,9 +383,10 @@ local function jobMonitor() parent = mon, sortColumn = 'displayName', columns = { - { heading = 'Qty', key = 'count', width = 6 }, - { heading = 'Crafting', key = 'displayName', width = mon.width / 2 - 10 }, - { heading = 'Status', key = 'status', width = mon.width - 10 }, + { heading = 'Qty', key = 'ocount', width = 6 }, + { heading = 'Qty', key = 'count', width = 6 }, + { heading = 'Crafting', key = 'displayName', width = (mon.width - 18) / 2 }, + { heading = 'Status', key = 'status', }, }, }) diff --git a/apps/mwm.lua b/apps/mwm.lua index 7682781..98dda2f 100644 --- a/apps/mwm.lua +++ b/apps/mwm.lua @@ -22,7 +22,7 @@ local UID = 0 local multishell = { } local processes = { } local parentTerm = term.current() -local sessionFile = args[1] or syntax() +local sessionFile = args[1] or 'config/mwm' local running local monitor diff --git a/apps/shapes.lua b/apps/shapes.lua index 168dc3c..e50a005 100644 --- a/apps/shapes.lua +++ b/apps/shapes.lua @@ -1,284 +1,47 @@ -requireInjector(getfenv(1)) +_G.requireInjector() local GPS = require('gps') local Socket = require('socket') local UI = require('ui') local Util = require('util') +local multishell = _ENV.multishell +local textutils = _G.textutils + multishell.setTitle(multishell.getCurrent(), 'Shapes') local args = { ... } local turtleId = args[1] or error('Supply turtle ID') turtleId = tonumber(turtleId) -local script = [[ - -requireInjector(getfenv(1)) - -local GPS = require('gps') -local ChestAdapter = require('chestAdapter18') -local Point = require('point') -local Util = require('util') - -local itemAdapter - -function dumpInventory() - - for i = 1, 16 do - local qty = turtle.getItemCount(i) - if qty > 0 then - itemAdapter:insert(i, qty) - end - if turtle.getItemCount(i) ~= 0 then - print('Adapter is full or missing - make space or replace') - print('Press enter to continue') - read() - end - end - turtle.select(1) -end - -local function refuel() - while turtle.getFuelLevel() < 4000 do - print('Refueling') - turtle.select(1) - - itemAdapter:provide({ name = 'minecraft:coal', damage = 0 }, 64, 1) - if turtle.getItemCount(1) == 0 then - print('Out of fuel, add fuel to chest/ME system') - turtle.setStatus('waiting') - os.sleep(5) - else - turtle.refuel(64) - end - end -end - -local function goto(pt) - while not turtle.gotoPoint(pt) do - print('stuck') - os.sleep(5) - end -end - -local function pathTo(pt) - while not turtle.pathfind(pt) do - print('stuck') - os.sleep(5) - end -end - -local function resupply() - - if data.suppliesPt then - pathTo(data.suppliesPt) - - itemAdapter = ChestAdapter({ direction = 'up', wrapSide = 'bottom' }) - dumpInventory() - refuel() - end -end - -local function makePlane(y) - local pt = { x = math.min(data.startPt.x, data.endPt.x), - ex = math.max(data.startPt.x, data.endPt.x), - z = math.min(data.startPt.z, data.endPt.z), - ez = math.max(data.startPt.z, data.endPt.z) } - - local blocks = { } - for z = pt.z, pt.ez do - for x = pt.x, pt.ex do - table.insert(blocks, { x = x, y = y, z = z }) - end - end - - return blocks -end - -local function optimizeRoute(plane, ptb) - - local maxDistance = 99999999 - - local function getNearestNeighbor(p, pt, threshold) - local key, block, heading - local moves = maxDistance - - local function getMoves(b, k) - local distance = math.abs(pt.x - b.x) + math.abs(pt.z - b.z) - - if distance < moves then - -- this operation is expensive - only run if distance is close - local c, h = Point.calculateMoves(pt, b, distance) - if c < moves then - block = b - key = k - moves = c - heading = h - end - end - end - - local function blockReady(b) - return not b.u - end - - local mid = pt.index - local forward = mid + 1 - local backward = mid - 1 - while forward <= #p or backward > 0 do - if forward <= #p then - local b = p[forward] - if blockReady(b) then - getMoves(b, forward) - if moves <= threshold then - break - end - if moves < maxDistance and math.abs(b.z - pt.z) > moves and pt.index > 0 then - forward = #p - end - end - forward = forward + 1 - end - if backward > 0 then - local b = p[backward] - if blockReady(b) then - getMoves(b, backward) - if moves <= threshold then - break - end - if moves < maxDistance and math.abs(pt.z - b.z) > moves then - backward = 0 - end - end - backward = backward - 1 - end - end - pt.x = block.x - pt.z = block.z - pt.y = block.y - pt.heading = heading - pt.index = key - block.u = true - return block - end - - local throttle = Util.throttle() - local t = { } - ptb.index = 0 - local threshold = 0 - for i = 1, #plane do - local b = getNearestNeighbor(plane, ptb, threshold) - table.insert(t, b) - throttle() - threshold = 1 - end - - return t -end - -local function clear() - - local pt = Util.shallowCopy(data.startPt) - pt.y = math.min(data.startPt.y, data.endPt.y) - pt.heading = 0 - - local osy = pt.y - local sy = osy + 1 - local ey = math.max(data.startPt.y, data.endPt.y) - local firstPlane = true - - resupply() - - while true do - - if sy > ey then - sy = ey - end - - local plane = makePlane(sy) - plane = optimizeRoute(plane, pt) - - if firstPlane then - turtle.pathfind(plane[1]) - turtle.setPolicy(turtle.policies.digAttack) - firstPlane = false - end - - for _,b in ipairs(plane) do - turtle.gotoPoint(b) - if sy < ey then - turtle.digUp() - end - if sy > osy then - turtle.digDown() - end - if turtle.isAborted() then - break - end - end - - if turtle.isAborted() then - break - end - if sy + 1 >= ey then - break - end - - sy = sy + 3 - end - turtle.setPolicy(turtle.policies.none) - resupply() -end - -turtle.run(function() - turtle.setStatus('Clearing') - - if turtle.enableGPS() then - - local pt = Util.shallowCopy(turtle.point) - local s, m = pcall(clear) - pathTo(pt) - - if not s and m then - error(m) - read() - end - end -end) -]] - local levelScript = [[ + requireInjector(getfenv(1)) -requireInjector(getfenv(1)) + local Util = require('util') -local Util = require('util') + local s, m = turtle.run(function() + turtle.addFeatures('level') + turtle.setStatus('Leveling') -local s, m = turtle.run(function() + if turtle.enableGPS() then + local pt = Util.shallowCopy(turtle.point) + local s, m = pcall(function() + turtle.level(data.startPt, data.endPt, data.firstPt) + end) - turtle.addFeatures('level') - turtle.setStatus('Leveling') + turtle.pathfind(pt) - if turtle.enableGPS() then - - local pt = Util.shallowCopy(turtle.point) - local s, m = pcall(function() - turtle.level(data.startPt, data.endPt, data.firstPt) - end) - - turtle.pathfind(pt) - - if not s and m then - error(m) + if not s and m then + error(m) + end end + end) + + if not s then + error(m) end -end) - -if not s then - error(m) -end ]] - local data = Util.readTable('/usr/config/shapes') or { } local page = UI.Page { @@ -296,7 +59,6 @@ local page = UI.Page { } function page.info:draw() - local function size(a, b) return (math.abs(a.x - b.x) + 1) * (math.abs(a.y - b.y) + 1) * @@ -322,13 +84,12 @@ function page:getPoint() end function page:runFunction(id, script) - --Util.writeFile('script.tmp', script) self.notification:info('Connecting') local fn, msg = loadstring(script, 'script') if not fn then self.notification:error('Error in script') --- debug(msg) + debug(msg) return end @@ -389,6 +150,4 @@ function page:eventHandler(event) end UI:setPage(page) - UI:pullEvents() -UI.term:reset() diff --git a/apps/treefarm.lua b/apps/treefarm.lua index 1dccced..62abe5b 100644 --- a/apps/treefarm.lua +++ b/apps/treefarm.lua @@ -268,7 +268,7 @@ local function getCobblestone(count) until turtle.getItemCount(COBBLESTONE) >= count - turtle.gotoPoint(pt) + turtle._goto(pt) turtle.placeDown(DIRT) turtle.drop(DIRT) diff --git a/etc/recipes.db b/etc/recipes.db index bfe2ca8..deb27a1 100644 --- a/etc/recipes.db +++ b/etc/recipes.db @@ -412,6 +412,17 @@ [ 6 ] = "minecraft:iron_ingot:0", }, }, + [ "minecraft:brick_stairs:0" ] = { + count = 4, + ingredients = { + "minecraft:brick_block:0", + [ 9 ] = "minecraft:brick_block:0", + [ 10 ] = "minecraft:brick_block:0", + [ 11 ] = "minecraft:brick_block:0", + [ 5 ] = "minecraft:brick_block:0", + [ 6 ] = "minecraft:brick_block:0", + }, + }, [ "minecraft:iron_block:0" ] = { count = 1, ingredients = { @@ -514,20 +525,6 @@ [ 6 ] = "minecraft:planks:2", }, }, - [ "minecraft:gold_block:0" ] = { - count = 63, - ingredients = { - "minecraft:gold_block:0", - "minecraft:gold_block:0", - "minecraft:gold_block:0", - [ 9 ] = "minecraft:gold_block:0", - [ 10 ] = "minecraft:gold_block:0", - [ 11 ] = "minecraft:gold_block:0", - [ 5 ] = "minecraft:gold_block:0", - [ 6 ] = "minecraft:gold_block:0", - [ 7 ] = "minecraft:gold_block:0", - }, - }, [ "minecraft:carpet:10" ] = { count = 3, ingredients = { @@ -535,13 +532,6 @@ [ 6 ] = "minecraft:wool:10", }, }, - [ "minecraft:stone:5" ] = { - count = 2, - ingredients = { - "minecraft:stone:3", - "minecraft:cobblestone:0", - }, - }, [ "minecraft:jungle_fence_gate:0" ] = { count = 1, ingredients = { @@ -553,6 +543,24 @@ [ 7 ] = "minecraft:stick:0", }, }, + [ "minecraft:stone:5" ] = { + count = 2, + ingredients = { + "minecraft:stone:3", + "minecraft:cobblestone:0", + }, + }, + [ "minecraft:oak_stairs:0" ] = { + count = 8, + ingredients = { + "minecraft:planks:0", + [ 9 ] = "minecraft:planks:0", + [ 10 ] = "minecraft:planks:0", + [ 11 ] = "minecraft:planks:0", + [ 5 ] = "minecraft:planks:0", + [ 6 ] = "minecraft:planks:0", + }, + }, [ "minecraft:noteblock:0" ] = { count = 1, ingredients = { @@ -567,15 +575,18 @@ [ 7 ] = "minecraft:planks:0", }, }, - [ "minecraft:oak_stairs:0" ] = { - count = 8, + [ "minecraft:gold_block:0" ] = { + count = 1, ingredients = { - "minecraft:planks:0", - [ 9 ] = "minecraft:planks:0", - [ 10 ] = "minecraft:planks:0", - [ 11 ] = "minecraft:planks:0", - [ 5 ] = "minecraft:planks:0", - [ 6 ] = "minecraft:planks:0", + "minecraft:gold_ingot:0", + "minecraft:gold_ingot:0", + "minecraft:gold_ingot:0", + [ 5 ] = "minecraft:gold_ingot:0", + [ 6 ] = "minecraft:gold_ingot:0", + [ 7 ] = "minecraft:gold_ingot:0", + [ 9 ] = "minecraft:gold_ingot:0", + [ 10 ] = "minecraft:gold_ingot:0", + [ 11 ] = "minecraft:gold_ingot:0", }, }, [ "minecraft:chest:0" ] = { @@ -745,10 +756,12 @@ [ 6 ] = "minecraft:dye:10", }, }, - [ "minecraft:sugar:0" ] = { - count = 1, + [ "minecraft:tripwire_hook:0" ] = { + count = 2, ingredients = { - [ 6 ] = "minecraft:reeds:0", + "minecraft:iron_ingot:0", + [ 9 ] = "minecraft:planks:0", + [ 5 ] = "minecraft:stick:0", }, }, [ "minecraft:ladder:0" ] = { @@ -824,6 +837,12 @@ [ 6 ] = "minecraft:iron_ingot:0", }, }, + [ "minecraft:sugar:0" ] = { + count = 1, + ingredients = { + [ 6 ] = "minecraft:reeds:0", + }, + }, [ "minecraft:stained_glass:6" ] = { count = 8, ingredients = { @@ -838,20 +857,6 @@ [ 7 ] = "minecraft:glass:0", }, }, - [ "minecraft:piston:0" ] = { - count = 1, - ingredients = { - "minecraft:planks:0", - "minecraft:planks:0", - "minecraft:planks:0", - [ 9 ] = "minecraft:cobblestone:0", - [ 10 ] = "minecraft:redstone:0", - [ 11 ] = "minecraft:cobblestone:0", - [ 5 ] = "minecraft:cobblestone:0", - [ 6 ] = "minecraft:iron_ingot:0", - [ 7 ] = "minecraft:cobblestone:0", - }, - }, [ "minecraft:planks:0" ] = { count = 4, ingredients = { @@ -895,12 +900,18 @@ [ 7 ] = "minecraft:hardened_clay:0", }, }, - [ "minecraft:tripwire_hook:0" ] = { - count = 2, + [ "minecraft:piston:0" ] = { + count = 1, ingredients = { - "minecraft:iron_ingot:0", - [ 9 ] = "minecraft:planks:0", - [ 5 ] = "minecraft:stick:0", + "minecraft:planks:0", + "minecraft:planks:0", + "minecraft:planks:0", + [ 9 ] = "minecraft:cobblestone:0", + [ 10 ] = "minecraft:redstone:0", + [ 11 ] = "minecraft:cobblestone:0", + [ 5 ] = "minecraft:cobblestone:0", + [ 6 ] = "minecraft:iron_ingot:0", + [ 7 ] = "minecraft:cobblestone:0", }, }, [ "minecraft:carpet:14" ] = { diff --git a/etc/scripts/goHome b/etc/scripts/goHome index 26681ed..8581bed 100644 --- a/etc/scripts/goHome +++ b/etc/scripts/goHome @@ -1 +1,2 @@ -turtle.run(turtle.gotoGPSHome) +local Home = require('turtle.home') +turtle.run(Home.go) diff --git a/etc/scripts/obsidian b/etc/scripts/obsidian index 99ff542..438313a 100644 --- a/etc/scripts/obsidian +++ b/etc/scripts/obsidian @@ -67,7 +67,7 @@ local function findObsidian() end node = Point.closest(turtle.point, nodes) - if not turtle.gotoPoint(node) then + if not turtle._goto(node) then break end until turtle.isAborted() @@ -91,7 +91,7 @@ turtle.run(function() if not turtle.select('minecraft:water_bucket') then break end - turtle._goto(0, 0) + turtle._goto({ x = 0, z = 0 }) turtle.placeDown() os.sleep(2) turtle.placeDown() @@ -104,5 +104,5 @@ turtle.run(function() error(m) end - turtle._goto(0, 0, 0, 0) + turtle._goto({ x = 0, y = 0, z = 0, heading = 0 }) end) diff --git a/etc/scripts/setHome b/etc/scripts/setHome index fe4ed90..709627d 100644 --- a/etc/scripts/setHome +++ b/etc/scripts/setHome @@ -1 +1,2 @@ -turtle.run(turtle.setGPSHome) +local Home = require('turtle.home') +turtle.run(Home.set) diff --git a/etc/scripts/summon b/etc/scripts/summon index 159b1a3..44b1b14 100644 --- a/etc/scripts/summon +++ b/etc/scripts/summon @@ -32,7 +32,7 @@ local function summon(id) local function doGPS() tFixes = { } for i = 1, 4 do - if not turtle.gotoPoint(pts[i]) then + if not turtle._goto(pts[i]) then error('turtle: Unable to perform GPS maneuver') end local distance = getDistance()