mirror of
https://github.com/kepler155c/opus
synced 2024-11-04 16:06:16 +00:00
863 lines
19 KiB
Lua
863 lines
19 KiB
Lua
if not turtle then
|
|
return
|
|
end
|
|
|
|
local function noop() end
|
|
|
|
turtle.point = { x = 0, y = 0, z = 0, heading = 0 }
|
|
turtle.status = 'idle'
|
|
turtle.abort = false
|
|
|
|
function turtle.getPoint()
|
|
return turtle.point
|
|
end
|
|
|
|
local state = {
|
|
moveAttack = noop,
|
|
moveDig = noop,
|
|
moveCallback = noop,
|
|
locations = {},
|
|
coordSystem = 'relative', -- type of coordinate system being used
|
|
}
|
|
|
|
function turtle.getState()
|
|
return state
|
|
end
|
|
|
|
function turtle.setPoint(pt)
|
|
turtle.point.x = pt.x
|
|
turtle.point.y = pt.y
|
|
turtle.point.z = pt.z
|
|
if pt.heading then
|
|
turtle.point.heading = pt.heading
|
|
end
|
|
return true
|
|
end
|
|
|
|
function turtle.reset()
|
|
turtle.point.x = 0
|
|
turtle.point.y = 0
|
|
turtle.point.z = 0
|
|
turtle.point.heading = 0
|
|
turtle.abort = false -- should be part of state
|
|
--turtle.status = 'idle' -- should be part of state
|
|
state.moveAttack = noop
|
|
state.moveDig = noop
|
|
state.moveCallback = noop
|
|
state.locations = {}
|
|
state.coordSystem = 'relative'
|
|
|
|
return true
|
|
end
|
|
|
|
local actions = {
|
|
up = {
|
|
detect = turtle.native.detectUp,
|
|
dig = turtle.native.digUp,
|
|
move = turtle.native.up,
|
|
attack = turtle.native.attackUp,
|
|
place = turtle.native.placeUp,
|
|
drop = turtle.native.dropUp,
|
|
suck = turtle.native.suckUp,
|
|
compare = turtle.native.compareUp,
|
|
inspect = turtle.native.inspectUp,
|
|
side = 'top'
|
|
},
|
|
down = {
|
|
detect = turtle.native.detectDown,
|
|
dig = turtle.native.digDown,
|
|
move = turtle.native.down,
|
|
attack = turtle.native.attackDown,
|
|
place = turtle.native.placeDown,
|
|
drop = turtle.native.dropDown,
|
|
suck = turtle.native.suckDown,
|
|
compare = turtle.native.compareDown,
|
|
inspect = turtle.native.inspectDown,
|
|
side = 'bottom'
|
|
},
|
|
forward = {
|
|
detect = turtle.native.detect,
|
|
dig = turtle.native.dig,
|
|
move = turtle.native.forward,
|
|
attack = turtle.native.attack,
|
|
place = turtle.native.place,
|
|
drop = turtle.native.drop,
|
|
suck = turtle.native.suck,
|
|
compare = turtle.native.compare,
|
|
inspect = turtle.native.inspect,
|
|
side = 'front'
|
|
},
|
|
back = {
|
|
detect = noop,
|
|
dig = noop,
|
|
move = turtle.native.back,
|
|
attack = noop,
|
|
place = noop,
|
|
suck = noop,
|
|
compare = noop,
|
|
side = 'back'
|
|
},
|
|
}
|
|
|
|
function turtle.getAction(direction)
|
|
return actions[direction]
|
|
end
|
|
|
|
-- [[ Heading data ]] --
|
|
local headings = {
|
|
[ 0 ] = { xd = 1, zd = 0, yd = 0, heading = 0, direction = 'east' },
|
|
[ 1 ] = { xd = 0, zd = 1, yd = 0, heading = 1, direction = 'south' },
|
|
[ 2 ] = { xd = -1, zd = 0, yd = 0, heading = 2, direction = 'west' },
|
|
[ 3 ] = { xd = 0, zd = -1, yd = 0, heading = 3, direction = 'north' },
|
|
[ 4 ] = { xd = 0, zd = 0, yd = 1, heading = 4, direction = 'up' },
|
|
[ 5 ] = { xd = 0, zd = 0, yd = -1, heading = 5, direction = 'down' }
|
|
}
|
|
|
|
local namedHeadings = {
|
|
east = headings[0],
|
|
south = headings[1],
|
|
west = headings[2],
|
|
north = headings[3],
|
|
up = headings[4],
|
|
down = headings[5]
|
|
}
|
|
|
|
function turtle.getHeadings()
|
|
return headings
|
|
end
|
|
|
|
function turtle.getHeadingInfo(heading)
|
|
if heading and type(heading) == 'string' then
|
|
return namedHeadings[heading]
|
|
end
|
|
heading = heading or turtle.point.heading
|
|
return headings[heading]
|
|
end
|
|
|
|
-- [[ Basic turtle actions ]] --
|
|
local function _attack(action)
|
|
if action.attack() then
|
|
repeat until not action.attack()
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
function turtle.attack() return _attack(actions.forward) end
|
|
function turtle.attackUp() return _attack(actions.up) end
|
|
function turtle.attackDown() return _attack(actions.down) end
|
|
|
|
local function _place(action, indexOrId)
|
|
|
|
local slot
|
|
|
|
if indexOrId then
|
|
slot = turtle.getSlot(indexOrId)
|
|
if not slot then
|
|
return false, 'No items to place'
|
|
end
|
|
end
|
|
|
|
if slot and slot.qty == 0 then
|
|
return false, 'No items to place'
|
|
end
|
|
|
|
return Util.tryTimes(3, function()
|
|
if slot then
|
|
turtle.select(slot.index)
|
|
end
|
|
local result = { action.place() }
|
|
if result[1] then
|
|
return true
|
|
end
|
|
if not state.moveDig(action) then
|
|
state.moveAttack(action)
|
|
end
|
|
return unpack(result)
|
|
end)
|
|
end
|
|
|
|
function turtle.place(slot) return _place(actions.forward, slot) end
|
|
function turtle.placeUp(slot) return _place(actions.up, slot) end
|
|
function turtle.placeDown(slot) return _place(actions.down, slot) end
|
|
|
|
local function _drop(action, count, indexOrId)
|
|
|
|
if indexOrId then
|
|
local slot = turtle.getSlot(indexOrId)
|
|
if not slot or slot.qty == 0 then
|
|
return false, 'No items to drop'
|
|
end
|
|
turtle.select(slot.index)
|
|
end
|
|
if not count then
|
|
return action.drop() -- wtf
|
|
end
|
|
return action.drop(count)
|
|
end
|
|
|
|
function turtle.drop(count, slot) return _drop(actions.forward, count, slot) end
|
|
function turtle.dropUp(count, slot) return _drop(actions.up, count, slot) end
|
|
function turtle.dropDown(count, slot) return _drop(actions.down, count, slot) end
|
|
|
|
--[[
|
|
function turtle.dig() return state.dig(actions.forward) end
|
|
function turtle.digUp() return state.dig(actions.up) end
|
|
function turtle.digDown() return state.dig(actions.down) end
|
|
--]]
|
|
|
|
function turtle.isTurtleAtSide(side)
|
|
local sideType = peripheral.getType(side)
|
|
return sideType and sideType == 'turtle'
|
|
end
|
|
|
|
turtle.attackPolicies = {
|
|
none = noop,
|
|
|
|
attack = function(action)
|
|
return _attack(action)
|
|
end,
|
|
}
|
|
|
|
turtle.digPolicies = {
|
|
none = noop,
|
|
|
|
dig = function(action)
|
|
return action.dig()
|
|
end,
|
|
|
|
turtleSafe = function(action)
|
|
if action.side == 'back' then
|
|
return false
|
|
end
|
|
if not turtle.isTurtleAtSide(action.side) then
|
|
return action.dig()
|
|
end
|
|
return Util.tryTimes(6, function()
|
|
-- if not turtle.isTurtleAtSide(action.side) then
|
|
-- return true --action.dig()
|
|
-- end
|
|
os.sleep(.25)
|
|
if not action.detect() then
|
|
return true
|
|
end
|
|
end)
|
|
end,
|
|
|
|
digAndDrop = function(action)
|
|
if action.detect() then
|
|
local slots = turtle.getInventory()
|
|
if action.dig() then
|
|
turtle.reconcileInventory(slots)
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
}
|
|
|
|
turtle.policies = {
|
|
none = { dig = turtle.digPolicies.none, attack = turtle.attackPolicies.none },
|
|
digOnly = { dig = turtle.digPolicies.dig, attack = turtle.attackPolicies.none },
|
|
attackOnly = { dig = turtle.digPolicies.none, attack = turtle.attackPolicies.attack },
|
|
digAttack = { dig = turtle.digPolicies.dig, attack = turtle.attackPolicies.attack },
|
|
turtleSafe = { dig = turtle.digPolicies.turtleSafe, attack = turtle.attackPolicies.attack },
|
|
}
|
|
|
|
function turtle.setPolicy(policy)
|
|
if type(policy) == 'string' then
|
|
policy = turtle.policies[policy]
|
|
end
|
|
if not policy then
|
|
return false, 'Invalid policy'
|
|
end
|
|
state.moveDig = policy.dig
|
|
state.moveAttack = policy.attack
|
|
return true
|
|
end
|
|
|
|
function turtle.setDigPolicy(policy)
|
|
state.moveDig = policy
|
|
end
|
|
|
|
function turtle.setAttackPolicy(policy)
|
|
state.moveAttack = policy
|
|
end
|
|
|
|
function turtle.setMoveCallback(cb)
|
|
state.moveCallback = cb
|
|
end
|
|
|
|
function turtle.clearMoveCallback()
|
|
state.moveCallback = noop
|
|
end
|
|
|
|
local function infoMoveCallback()
|
|
local pt = turtle.point
|
|
print(string.format('x:%d y:%d z:%d heading:%d', pt.x, pt.y, pt.z, pt.heading))
|
|
end
|
|
-- TESTING
|
|
--turtle.setMoveCallback(infoMoveCallback)
|
|
|
|
-- [[ Locations ]] --
|
|
function turtle.getLocation(name)
|
|
return state.locations[name]
|
|
end
|
|
|
|
function turtle.saveLocation(name, pt)
|
|
pt = pt or turtle.point
|
|
state.locations[name] = { x = pt.x, y = pt.y, z = pt.z }
|
|
end
|
|
|
|
function turtle.gotoLocation(name)
|
|
local pt = turtle.getLocation(name)
|
|
if pt then
|
|
return turtle.goto(pt.x, pt.z, pt.y, pt.heading)
|
|
end
|
|
end
|
|
|
|
function turtle.storeLocation(name, pt)
|
|
pt = pt or turtle.point
|
|
Util.writeTable(name .. '.pt', pt)
|
|
return true
|
|
end
|
|
|
|
function turtle.loadLocation(name)
|
|
return Util.readTable(name .. '.pt')
|
|
end
|
|
|
|
function turtle.gotoStoredLocation(name)
|
|
local pt = turtle.loadLocation(name)
|
|
if pt then
|
|
return turtle.gotoPoint(pt)
|
|
end
|
|
end
|
|
|
|
-- [[ Heading ]] --
|
|
function turtle.getHeading()
|
|
return turtle.point.heading
|
|
end
|
|
|
|
function turtle.turnRight()
|
|
turtle.setHeading(turtle.point.heading + 1)
|
|
return turtle.point
|
|
end
|
|
|
|
function turtle.turnLeft()
|
|
turtle.setHeading(turtle.point.heading - 1)
|
|
return turtle.point
|
|
end
|
|
|
|
function turtle.turnAround()
|
|
turtle.setHeading(turtle.point.heading + 2)
|
|
return turtle.point
|
|
end
|
|
|
|
function turtle.setNamedHeading(headingName)
|
|
local headingInfo = namedHeadings[headingName]
|
|
if headingInfo then
|
|
return turtle.setHeading(headingInfo.heading)
|
|
end
|
|
return false, 'Invalid heading'
|
|
end
|
|
|
|
function turtle.setHeading(heading)
|
|
if not heading then
|
|
return
|
|
end
|
|
|
|
heading = heading % 4
|
|
if heading ~= turtle.point.heading then
|
|
while heading < turtle.point.heading do
|
|
heading = heading + 4
|
|
end
|
|
if heading - turtle.point.heading == 3 then
|
|
turtle.native.turnLeft()
|
|
turtle.point.heading = turtle.point.heading - 1
|
|
else
|
|
local turns = heading - turtle.point.heading
|
|
while turns > 0 do
|
|
turns = turns - 1
|
|
turtle.point.heading = turtle.point.heading + 1
|
|
turtle.native.turnRight()
|
|
end
|
|
end
|
|
|
|
turtle.point.heading = turtle.point.heading % 4
|
|
state.moveCallback('turn', turtle.point)
|
|
end
|
|
|
|
return turtle.point
|
|
end
|
|
|
|
function turtle.headTowardsX(dx)
|
|
if turtle.point.x ~= dx then
|
|
if turtle.point.x > dx then
|
|
turtle.setHeading(2)
|
|
else
|
|
turtle.setHeading(0)
|
|
end
|
|
end
|
|
end
|
|
|
|
function turtle.headTowardsZ(dz)
|
|
if turtle.point.z ~= dz then
|
|
if turtle.point.z > dz then
|
|
turtle.setHeading(3)
|
|
else
|
|
turtle.setHeading(1)
|
|
end
|
|
end
|
|
end
|
|
|
|
function turtle.headTowards(pt)
|
|
local xd = math.abs(turtle.point.x - pt.x)
|
|
local zd = math.abs(turtle.point.z - pt.z)
|
|
if xd > zd then
|
|
turtle.headTowardsX(pt.x)
|
|
else
|
|
turtle.headTowardsZ(pt.z)
|
|
end
|
|
end
|
|
|
|
-- [[ move ]] --
|
|
local function _move(action)
|
|
while not action.move() do
|
|
if not state.moveDig(action) and not state.moveAttack(action) then
|
|
return false
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
function turtle.up()
|
|
if _move(actions.up) then
|
|
turtle.point.y = turtle.point.y + 1
|
|
state.moveCallback('up', turtle.point)
|
|
return true, turtle.point
|
|
end
|
|
end
|
|
|
|
function turtle.down()
|
|
if _move(actions.down) then
|
|
turtle.point.y = turtle.point.y - 1
|
|
state.moveCallback('down', turtle.point)
|
|
return true, turtle.point
|
|
end
|
|
end
|
|
|
|
function turtle.forward()
|
|
if _move(actions.forward) then
|
|
turtle.point.x = turtle.point.x + headings[turtle.point.heading].xd
|
|
turtle.point.z = turtle.point.z + headings[turtle.point.heading].zd
|
|
state.moveCallback('forward', turtle.point)
|
|
return true, turtle.point
|
|
end
|
|
end
|
|
|
|
function turtle.back()
|
|
if _move(actions.back) then
|
|
turtle.point.x = turtle.point.x - headings[turtle.point.heading].xd
|
|
turtle.point.z = turtle.point.z - headings[turtle.point.heading].zd
|
|
state.moveCallback('back', turtle.point)
|
|
return true, turtle.point
|
|
end
|
|
end
|
|
|
|
function turtle.moveTowardsX(dx)
|
|
|
|
local direction = dx - turtle.point.x
|
|
local move
|
|
|
|
if direction == 0 then
|
|
return true
|
|
end
|
|
|
|
if direction > 0 and turtle.point.heading == 0 or
|
|
direction < 0 and turtle.point.heading == 2 then
|
|
move = turtle.forward
|
|
else
|
|
move = turtle.back
|
|
end
|
|
|
|
repeat
|
|
if not move() then
|
|
return false
|
|
end
|
|
until turtle.point.x == dx
|
|
return true
|
|
end
|
|
|
|
function turtle.moveTowardsZ(dz)
|
|
|
|
local direction = dz - turtle.point.z
|
|
local move
|
|
|
|
if direction == 0 then
|
|
return true
|
|
end
|
|
|
|
if direction > 0 and turtle.point.heading == 1 or
|
|
direction < 0 and turtle.point.heading == 3 then
|
|
move = turtle.forward
|
|
else
|
|
move = turtle.back
|
|
end
|
|
|
|
repeat
|
|
if not move() then
|
|
return false
|
|
end
|
|
until turtle.point.z == dz
|
|
return true
|
|
end
|
|
|
|
-- [[ go ]] --
|
|
-- 1 turn goto (going backwards if possible)
|
|
function turtle.gotoSingleTurn(dx, dz, dy, dh)
|
|
|
|
dy = dy or turtle.point.y
|
|
|
|
local function gx()
|
|
if turtle.point.x ~= dx then
|
|
turtle.moveTowardsX(dx)
|
|
end
|
|
if turtle.point.z ~= dz then
|
|
if dh and dh % 2 == 1 then
|
|
turtle.setHeading(dh)
|
|
else
|
|
turtle.headTowardsZ(dz)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function gz()
|
|
if turtle.point.z ~= dz then
|
|
turtle.moveTowardsZ(dz)
|
|
end
|
|
if turtle.point.x ~= dx then
|
|
if dh and dh % 2 == 0 then
|
|
turtle.setHeading(dh)
|
|
else
|
|
turtle.headTowardsX(dx)
|
|
end
|
|
end
|
|
end
|
|
|
|
repeat
|
|
local x, z
|
|
local y = turtle.point.y
|
|
|
|
repeat
|
|
x, z = turtle.point.x, turtle.point.z
|
|
|
|
if turtle.point.heading % 2 == 0 then
|
|
gx()
|
|
gz()
|
|
else
|
|
gz()
|
|
gx()
|
|
end
|
|
until x == turtle.point.x and z == turtle.point.z
|
|
|
|
if turtle.point.y ~= dy then
|
|
turtle.gotoY(dy)
|
|
end
|
|
|
|
if turtle.point.x == dx and turtle.point.z == dz and turtle.point.y == dy then
|
|
return true
|
|
end
|
|
|
|
until x == turtle.point.x and z == turtle.point.z and y == turtle.point.y
|
|
|
|
return false
|
|
end
|
|
|
|
local function gotoEx(dx, dz, dy)
|
|
|
|
-- determine the heading to ensure the least amount of turns
|
|
-- first check is 1 turn needed - remaining require 2 turns
|
|
if turtle.point.heading == 0 and turtle.point.x <= dx or
|
|
turtle.point.heading == 2 and turtle.point.x >= dx or
|
|
turtle.point.heading == 1 and turtle.point.z <= dz or
|
|
turtle.point.heading == 3 and turtle.point.z >= dz then
|
|
-- maintain current heading
|
|
-- nop
|
|
elseif dz > turtle.point.z and turtle.point.heading == 0 or
|
|
dz < turtle.point.z and turtle.point.heading == 2 or
|
|
dx < turtle.point.x and turtle.point.heading == 1 or
|
|
dx > turtle.point.x and turtle.point.heading == 3 then
|
|
turtle.turnRight()
|
|
else
|
|
turtle.turnLeft()
|
|
end
|
|
|
|
if (turtle.point.heading % 2) == 1 then
|
|
if not turtle.gotoZ(dz) then return false end
|
|
if not turtle.gotoX(dx) then return false end
|
|
else
|
|
if not turtle.gotoX(dx) then return false end
|
|
if not turtle.gotoZ(dz) then return false end
|
|
end
|
|
|
|
if dy then
|
|
if not turtle.gotoY(dy) then return false end
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
-- fallback goto - will turn around if was previously moving backwards
|
|
local function gotoMultiTurn(dx, dz, dy)
|
|
|
|
if gotoEx(dx, dz, dy) then
|
|
return true
|
|
end
|
|
|
|
local moved
|
|
repeat
|
|
local x, y, z = turtle.point.x, turtle.point.y, turtle.point.z
|
|
|
|
-- try going the other way
|
|
if (turtle.point.heading % 2) == 1 then
|
|
turtle.headTowardsX(dx)
|
|
else
|
|
turtle.headTowardsZ(dz)
|
|
end
|
|
|
|
if gotoEx(dx, dz, dy) then
|
|
return true
|
|
end
|
|
|
|
if dy then
|
|
turtle.gotoY(dy)
|
|
end
|
|
|
|
moved = x ~= turtle.point.x or y ~= turtle.point.y or z ~= turtle.point.z
|
|
until not moved
|
|
|
|
return false
|
|
end
|
|
|
|
function turtle.gotoPoint(pt)
|
|
return turtle.goto(pt.x, pt.z, pt.y, pt.heading)
|
|
end
|
|
|
|
-- go backwards - turning around if necessary to fight mobs / break blocks
|
|
function turtle.goback()
|
|
local hi = headings[turtle.point.heading]
|
|
return turtle.goto(turtle.point.x - hi.xd, turtle.point.z - hi.zd, turtle.point.y, turtle.point.heading)
|
|
end
|
|
|
|
function turtle.gotoYfirst(pt)
|
|
if turtle.gotoY(pt.y) then
|
|
if turtle.goto(pt.x, pt.z, nil, pt.heading) then
|
|
turtle.setHeading(pt.heading)
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
function turtle.gotoYlast(pt)
|
|
if turtle.goto(pt.x, pt.z, nil, pt.heading) then
|
|
if turtle.gotoY(pt.y) then
|
|
turtle.setHeading(pt.heading)
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
function turtle.goto(dx, dz, dy, dh)
|
|
if not turtle.gotoSingleTurn(dx, dz, dy, dh) then
|
|
if not gotoMultiTurn(dx, dz, dy) then
|
|
return false
|
|
end
|
|
end
|
|
turtle.setHeading(dh)
|
|
return true
|
|
end
|
|
|
|
function turtle.gotoX(dx)
|
|
turtle.headTowardsX(dx)
|
|
|
|
while turtle.point.x ~= dx do
|
|
if not turtle.forward() then
|
|
return false
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
function turtle.gotoZ(dz)
|
|
turtle.headTowardsZ(dz)
|
|
|
|
while turtle.point.z ~= dz do
|
|
if not turtle.forward() then
|
|
return false
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
function turtle.gotoY(dy)
|
|
while turtle.point.y > dy do
|
|
if not turtle.down() then
|
|
return false
|
|
end
|
|
end
|
|
|
|
while turtle.point.y < dy do
|
|
if not turtle.up() then
|
|
return false
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
-- [[ Slot management ]] --
|
|
function turtle.getSlot(indexOrId, slots)
|
|
|
|
if type(indexOrId) == 'string' then
|
|
slots = slots or turtle.getInventory()
|
|
local _,c = string.gsub(indexOrId, ':', '')
|
|
if c == 2 then -- combined id and dmg .. ie. minecraft:coal:0
|
|
return Util.find(slots, 'iddmg', indexOrId)
|
|
end
|
|
return Util.find(slots, 'id', indexOrId)
|
|
end
|
|
|
|
local detail = turtle.getItemDetail(indexOrId)
|
|
if detail then
|
|
return {
|
|
qty = detail.count,
|
|
dmg = detail.damage,
|
|
id = detail.name,
|
|
iddmg = detail.name .. ':' .. detail.damage,
|
|
index = indexOrId,
|
|
}
|
|
end
|
|
|
|
return {
|
|
qty = 0,
|
|
index = indexOrId,
|
|
}
|
|
end
|
|
|
|
function turtle.selectSlot(indexOrId)
|
|
|
|
local s = turtle.getSlot(indexOrId)
|
|
if s then
|
|
turtle.select(s.index)
|
|
return s
|
|
end
|
|
|
|
return false, 'Inventory does not contain item'
|
|
end
|
|
|
|
function turtle.getInventory(slots)
|
|
slots = slots or { }
|
|
for i = 1, 16 do
|
|
slots[i] = turtle.getSlot(i)
|
|
end
|
|
return slots
|
|
end
|
|
|
|
function turtle.emptyInventory(dropAction)
|
|
dropAction = dropAction or turtle.drop
|
|
for i = 1, 16 do
|
|
turtle.emptySlot(i, dropAction)
|
|
end
|
|
end
|
|
|
|
function turtle.emptySlot(slot, dropAction)
|
|
dropAction = dropAction or turtle.drop
|
|
local count = turtle.getItemCount(slot)
|
|
if count > 0 then
|
|
turtle.select(slot)
|
|
return dropAction(count)
|
|
end
|
|
return false, 'No items to drop'
|
|
end
|
|
|
|
function turtle.getFilledSlots(startSlot)
|
|
startSlot = startSlot or 1
|
|
|
|
local slots = { }
|
|
for i = startSlot, 16 do
|
|
local count = turtle.getItemCount(i)
|
|
if count > 0 then
|
|
slots[i] = turtle.getSlot(i)
|
|
end
|
|
end
|
|
return slots
|
|
end
|
|
|
|
function turtle.eachFilledSlot(fn)
|
|
local slots = turtle.getFilledSlots()
|
|
for _,slot in pairs(slots) do
|
|
fn(slot)
|
|
end
|
|
end
|
|
|
|
function turtle.reconcileInventory(slots, dropAction)
|
|
dropAction = dropAction or turtle.native.drop
|
|
for _,s in pairs(slots) do
|
|
local qty = turtle.getItemCount(s.index)
|
|
if qty > s.qty then
|
|
turtle.select(s.index)
|
|
dropAction(qty-s.qty, s)
|
|
end
|
|
end
|
|
end
|
|
|
|
function turtle.selectSlotWithItems(startSlot)
|
|
startSlot = startSlot or 1
|
|
for i = startSlot, 16 do
|
|
if turtle.getItemCount(i) > 0 then
|
|
turtle.select(i)
|
|
return i
|
|
end
|
|
end
|
|
end
|
|
|
|
function turtle.selectOpenSlot(startSlot)
|
|
return turtle.selectSlotWithQuantity(0, startSlot)
|
|
end
|
|
|
|
function turtle.selectSlotWithQuantity(qty, startSlot)
|
|
startSlot = startSlot or 1
|
|
|
|
for i = startSlot, 16 do
|
|
if turtle.getItemCount(i) == qty then
|
|
turtle.select(i)
|
|
return i
|
|
end
|
|
end
|
|
end
|
|
|
|
function turtle.condense(startSlot)
|
|
startSlot = startSlot or 1
|
|
local aslots = turtle.getInventory()
|
|
|
|
for _,slot in ipairs(aslots) do
|
|
if slot.qty < 64 then
|
|
for i = slot.index + 1, 16 do
|
|
local fslot = aslots[i]
|
|
if fslot.qty > 0 then
|
|
if slot.qty == 0 or slot.iddmg == fslot.iddmg then
|
|
turtle.select(fslot.index)
|
|
turtle.transferTo(slot.index, 64)
|
|
local transferred = turtle.getItemCount(slot.index) - slot.qty
|
|
slot.qty = slot.qty + transferred
|
|
fslot.qty = fslot.qty - transferred
|
|
slot.iddmg = fslot.iddmg
|
|
if slot.qty == 64 then
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|