diff --git a/apis/builder/turtle.lua b/apis/builder/turtle.lua index 9fd7fdf..b512a73 100644 --- a/apis/builder/turtle.lua +++ b/apis/builder/turtle.lua @@ -586,14 +586,13 @@ local function closestEdgePoint(pt, pts, rpt) return cpt end -function TurtleBuilder:getBuildingCorner() - 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 }, +function TurtleBuilder:getBuildingCorner(y) + local box = { + x = -1, ex = self.schematic.width, + y = y, ey = y, + z = -1, ez = self.schematic.length, } - return closestEdgePoint(self.supplyPoint, pts, turtle.getPoint()) + return Point.closestPointInBox(turtle.getPoint(), box) end function TurtleBuilder:gotoSupplyPoint() @@ -601,7 +600,7 @@ function TurtleBuilder:gotoSupplyPoint() -- so we don't end up pathfinding through a building -- go to the corner closest to the supplies point -- pathfind the rest of the way - local pt = self:getBuildingCorner() + local pt = self:getBuildingCorner(turtle.point.y) turtle._goto(pt.x, pt.z) turtle.setPolicy('none') turtle.pathfind(self.supplyPoint) @@ -1085,7 +1084,6 @@ end function TurtleBuilder:build() local direction = 1 local last = #self.schematic.blocks - local travelPlane = 0 local minFuel = self.schematic.height + self.schematic.width + self.schematic.length + 100 local throttle = Util.throttle() @@ -1094,11 +1092,12 @@ function TurtleBuilder:build() last = 1 turtle.setStatus('destroying') else - travelPlane = self:findTravelPlane(self.index) turtle.setStatus('building') end - local pt = self:getBuildingCorner() + local travelPlane = self:findTravelPlane(self.index) + + local pt = self:getBuildingCorner(travelPlane) turtle.pathfind({ x = pt.x, z = pt.z, y = travelPlane }) turtle.setPolicy('digAttack') @@ -1210,22 +1209,21 @@ function TurtleBuilder:build() end function TurtleBuilder:begin() + turtle.reset() + self:dumpInventory() + self:refuel() + self:getTurtleFacing() + if self.loc.x then self.supplyPoint = { x = self.loc.x - self.loc.rx - 1, y = self.loc.y - self.loc.ry, z = self.loc.z - self.loc.rz - 1, } + Point.rotate(self.supplyPoint, self.facing) else self.supplyPoint = { x = -1, y = 0, z = -1 } end - - turtle.reset() - self:dumpInventory() - self:refuel() - self:getTurtleFacing() - - Point.rotate(self.supplyPoint, self.facing) turtle.setPoint(self.supplyPoint) -- reset piston cache in case wrench was substituted diff --git a/apis/turtle/craft.lua b/apis/turtle/craft.lua index b0457d4..3dd89dc 100644 --- a/apis/turtle/craft.lua +++ b/apis/turtle/craft.lua @@ -2,7 +2,9 @@ local Util = require('util') local turtle = _G.turtle -local Craft = { } +local Craft = { + recipes = Util.readTable('usr/etc/recipes.db') or { }, +} local function clearGrid(inventoryAdapter) for i = 1, 16 do @@ -41,7 +43,6 @@ local function getItemCount(items, key) end local function turtleCraft(recipe, qty, inventoryAdapter) - clearGrid(inventoryAdapter) for k,v in pairs(recipe.ingredients) do @@ -57,6 +58,12 @@ local function turtleCraft(recipe, qty, inventoryAdapter) end function Craft.craftRecipe(recipe, count, inventoryAdapter) + if type(recipe) == 'string' then + recipe = Craft.recipes[recipe] + if not recipe then + return false, 'No recipe' + end + end local items = inventoryAdapter:listItems() @@ -103,18 +110,16 @@ end -- given a certain quantity, return how many of those can be crafted function Craft.getCraftableAmount(recipe, count, items, missing) - - local function sumItems(recipe, items, summedItems, count) - + local function sumItems(recipe, summedItems, count) local canCraft = 0 - for i = 1, count do + for _ = 1, count do for _,item in pairs(recipe.ingredients) do local summedItem = summedItems[item] or getItemCount(items, item) local irecipe = Craft.recipes[item] if irecipe and summedItem <= 0 then - summedItem = summedItem + sumItems(irecipe, items, summedItems, 1) + summedItem = summedItem + sumItems(irecipe, summedItems, 1) end if summedItem <= 0 then if missing then @@ -130,7 +135,7 @@ function Craft.getCraftableAmount(recipe, count, items, missing) return canCraft end - return sumItems(recipe, items, { }, math.ceil(count / recipe.count), missing) + return sumItems(recipe, { }, math.ceil(count / recipe.count)) end function Craft.canCraft(item, count, items) @@ -149,13 +154,15 @@ function Craft.getCraftableAmountTest() { name = 'minecraft:planks', damage = 0, count = 5 }, { name = 'minecraft:log', damage = 0, count = 2 }, } - results[1] = { item = 'chest', expected = 1, got = Craft.getCraftableAmount(Craft.recipes['minecraft:chest:0'], 2, items) } + results[1] = { item = 'chest', expected = 1, + got = Craft.getCraftableAmount(Craft.recipes['minecraft:chest:0'], 2, items) } items = { { name = 'minecraft:log', damage = 0, count = 1 }, { name = 'minecraft:coal', damage = 1, count = 1 }, } - results[2] = { item = 'torch', expected = 4, got = Craft.getCraftableAmount(Craft.recipes['minecraft:torch:0'], 4, items) } + results[2] = { item = 'torch', expected = 4, + got = Craft.getCraftableAmount(Craft.recipes['minecraft:torch:0'], 4, items) } return results end diff --git a/apis/turtle/crafting.lua b/apis/turtle/crafting.lua new file mode 100644 index 0000000..22ad5ff --- /dev/null +++ b/apis/turtle/crafting.lua @@ -0,0 +1,64 @@ +local Adapter = require('inventoryAdapter') +local Craft = require('turtle.craft') + +local turtle = _G.turtle + +local CRAFTING_TABLE = 'minecraft:crafting_table' + +local function clearGrid(inventory) + for i = 1, 16 do + local count = turtle.getItemCount(i) + if count > 0 then + inventory:insert(i, count) + if turtle.getItemCount(i) ~= 0 then + return false + end + end + end + return true +end + +function turtle.craftItem(item, count, inventoryInfo) + local success + + local inventory = Adapter.wrap(inventoryInfo) + if not inventory then + return false, 'Invalid inventory' + end + + local equipped, side + if not turtle.isEquipped('workbench') then + local modemSide = turtle.isEquipped('modem') or 'right' + local osides = { left = 'right', right = 'left' } + side = osides[modemSide] + if not turtle.select(CRAFTING_TABLE) then + clearGrid(inventory) + if not turtle.selectOpenSlot() then + return false, 'Inventory is full' + end + if not inventory:provide({ name = CRAFTING_TABLE, damage = 0 }, 1) then + return false, 'Missing crafting table' + end + end + + local slot = turtle.select(CRAFTING_TABLE) + turtle.equip(side, CRAFTING_TABLE) + equipped = turtle.getItemDetail(slot) + end + + success = Craft.craftRecipe(item, count or 1, inventory) + + if equipped then + turtle.selectOpenSlot() + inventory:provide({ name = equipped.name, damage = equipped.damage }, 1) + turtle.equip(side, equipped.name .. ':' .. equipped.damage) + end + + return success +end + +function turtle.canCraft(item, count, items) + return Craft.canCraft(item, count, items) +end + +return true diff --git a/apis/turtle/level.lua b/apis/turtle/level.lua index 9e86ae2..45d077d 100644 --- a/apis/turtle/level.lua +++ b/apis/turtle/level.lua @@ -113,7 +113,7 @@ local function getAdjacentPoint(pt) return closestPoint(turtle.getPoint(), t) end -return function(startPt, endPt, firstPt, verbose) +function turtle.level(startPt, endPt, firstPt, verbose) checkedNodes = { } nodes = { } box = { } @@ -166,3 +166,5 @@ return function(startPt, endPt, firstPt, verbose) turtle.resetState() turtle.setMoveCallback(oldCallback) end + +return true diff --git a/apps/shapes.lua b/apps/shapes.lua index c501bee..168dc3c 100644 --- a/apps/shapes.lua +++ b/apps/shapes.lua @@ -251,17 +251,18 @@ local levelScript = [[ requireInjector(getfenv(1)) -local Level = require('turtle.level') local Util = require('util') local s, m = turtle.run(function() + + turtle.addFeatures('level') turtle.setStatus('Leveling') if turtle.enableGPS() then local pt = Util.shallowCopy(turtle.point) local s, m = pcall(function() - Level(data.startPt, data.endPt, data.firstPt) + turtle.level(data.startPt, data.endPt, data.firstPt) end) turtle.pathfind(pt) diff --git a/apps/treefarm.lua b/apps/treefarm.lua index 18b61f2..1dccced 100644 --- a/apps/treefarm.lua +++ b/apps/treefarm.lua @@ -6,7 +6,7 @@ _G.requireInjector() Area around turtle must be flat and can only be dirt or grass (10 blocks in each direction from turtle) Turtle must have: crafting table, chest - Turtle must have a pick equipped on the left side + Turtle must have a pick equipped Optional: Add additional sapling types that can grow with a single sapling @@ -20,12 +20,8 @@ _G.requireInjector() place the turtle in the original position before restarting the program. ]]-- -local ChestAdapter = require('chestAdapter18') -local Craft = require('turtle.craft') -local Level = require('turtle.level') -local Pathing = require('turtle.pathfind') -local Point = require('point') -local Util = require('util') +local Point = require('point') +local Util = require('util') local os = _G.os local read = _G.read @@ -80,9 +76,6 @@ local state = Util.readTable('usr/config/treefarm') or { } local clock = os.clock() -local recipes = Util.readTable('usr/etc/recipes.db') or { } - -Craft.setRecipes(recipes) local function inspect(fn) local s, item = fn() @@ -125,28 +118,17 @@ local function safePlaceBlock(item) end local function craftItem(item, qty) - local success if safePlaceBlock(CHEST) then - if turtle.equip('left', 'minecraft:crafting_table') then - - local chestAdapter = ChestAdapter({ + Util.print('Crafting %d %s', (qty or 1), item) + success = turtle.craftItem(item, qty or 1, { wrapSide = 'top', direction = 'down', }) - if not chestAdapter:isValid() then - print('invalid chestAdapter') - read() - end + repeat until not turtle.suckUp() - Util.print('Crafting %d %s', (qty or 1), item) - success = Craft.craftRecipe(recipes[item], qty or 1, chestAdapter) - - repeat until not turtle.suckUp() - end - turtle.equip('left', 'minecraft:diamond_pickaxe') turtle.digUp() end @@ -360,7 +342,7 @@ local function createChests() end if state.perimeter and turtle.getFuelLevel() > FUEL_GOOD and - Craft.canCraft(CHEST, 4, turtle.getSummedInventory()) then + turtle.canCraft(CHEST, 4, turtle.getSummedInventory()) then print('Adding storage') if craftItem(CHEST, 4) then @@ -435,7 +417,7 @@ local function placeTorches() end if turtle.getFuelLevel() > 100 and - Craft.canCraft(TORCH, 4, turtle.getSummedInventory()) then + turtle.canCraft(TORCH, 4, turtle.getSummedInventory()) then print('Placing torches') @@ -498,7 +480,7 @@ local function fellTree(pt) desperateRefuel(FUEL_DIRE) if turtle.digUpAt(Point.above(pt)) then - Level( + turtle.level( { x = GRID_WIDTH-1, y = 1, z = GRID_WIDTH-1 }, { x = -(GRID_WIDTH-1), y = 50, z = -(GRID_WIDTH-1) }, Point.above(pt)) @@ -638,10 +620,7 @@ local function findHome() end print('Determining location') - - turtle.point.heading = getTurtleFacing(CHEST) - turtle.setHeading(state.facing) - turtle.point.heading = 0 + turtle.point.heading = (getTurtleFacing(CHEST) - state.facing) % 4 local pt = Point.copy(turtle.point) @@ -668,7 +647,7 @@ local function findHome() }) -- when pathfinding - don't leave this box - Pathing.setBox({ + turtle.setPathingBox({ x = GRID.TL.x, y = GRID.TL.y, z = GRID.TL.z, @@ -730,6 +709,7 @@ local tasks = { local s, m = turtle.run(function() + turtle.addFeatures('level', 'crafting') turtle.setPolicy("attack") while not turtle.isAborted() do