turtle api
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
64
apis/turtle/crafting.lua
Normal file
64
apis/turtle/crafting.lua
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user