inventory = {}
types = {
unknown = "unknown",
dirt = "dirt",
grass = "dirt",
sapling = "sapling",
log = "wood",
wood = "wood",
dropoff = "dropoff", --not actual item type, but can be refered to
}
-- position for each type
-- while standing at target location facing desired direction
-- turtle should be able to do a turtle.suck() to grab the material
-- if dir=up suckUp() if dir=down suckDown()
position = {}
-- if you have a small tunnel towards your storage for the turtle
-- addStoragePathCheckpoint(x,y,z) to add enterance
-- ^ can be used multiple times if you have a complicated path
-- turtle will follow the path in revese when it exits
storageEnterancePath = {}
local differenceRecord = {}
function update()
for slot = 1,16 do
local oldType = nil
if type(inventory[slot])=="table" then oldType=inventory[slot].type end
inventory[slot] = {
type = oldType or types.unknown,
qty = turtle.getItemCount(slot),
}
if inventory[slot].qty==0 then
inventory[slot].type = nil
end
end
end
-- gets all global variables
function init( global )
update()
setfenv(1,global)
end
function recordDifference()
differenceRecord = {}
for slot=1,16 do
differenceRecord[slot] = {
type = inventory[slot].type,
qty = inventory[slot].qty,
}
end
end
function getDifference()
local difference = {}
update()
for slot=1,16 do
local qtyDifference = inventory[slot].qty - differenceRecord[slot].qty
if qtyDifference~=0 or inventory[slot].type~=differenceRecord[slot].type then
difference[slot] = {}
difference[slot].qty = qtyDifference
difference[slot].type = differenceRecord[slot].type
if inventory[slot].type~=differenceRecord[slot].type then
difference[slot].oldType = differenceRecord[slot].type
end
end
end
return difference
end
function setItemAccess( item,x,y,z,dir )
position[item] = {x=x,y=y,z=z,dir=dir}
end
function getItemAccess( item )
return position[item].x,position[item].y,position[item].z,position[item].dir
end
function addStoragePathCheckpoint( x,y,z )
storageEnterancePath[#storageEnterancePath+1] = {x=x,y=y,z=z}
end
function getStoragePathCheckpoint( step )
if type(storageEnterancePath[step])=="table" then
return (storageEnterancePath[step].x or _),(storageEnterancePath[step].y or _),(storageEnterancePath[step].z or _)
end
end
function resetStoragePath()
storageEnterancePath = {}
end
-- reverse = boolean
function followStoragePath( reverse )
if type(reverse)~="boolean" then reverse = false end
local start = 1
local stop = #storageEnterancePath
if reverse then start=stop stop=1 end
for step = start,stop,mult(stop-start) do
gps.goto(getStoragePathCheckpoint(step))
end
end
function getItemCount( item )
update()
local count = 0
for slot = 1,16 do
if inventory[slot].type == item then
count = count + inventory[slot].qty
end
end
return count
end
-- gotoStorageRoom = (boolean) wether or not it should follow the storage path
function dropoff( gotoStorageRoom )
if type(gotoStorageRoom)~="boolean" then gotoStorageRoom = false end
-- dropoff must have a location
local x,y,z,dir = getItemAccess(types.dropoff)
if type(x)~="number" or type(y)~="number"
or type(z)~="number" or type(dir)~="string" then
return false
end
if gotoStorageRoom then
followStoragePath()
end
gps.goto(x,y,z,dir)
for slot=1,16 do
local count = turtle.getItemCount(slot)
while count~=0 do
turtle.select(slot)
if dir==gps.up then
turtle.dropUp(count)
elseif dir==gps.down then
turtle.dropDown(count)
else
turtle.drop(count)
end
count = turtle.getItemCount(slot)
end
end
-- exit the storage room
if gotoStorageRoom then
followStoragePath(true)
end
end
-- tries to get item from storage canceles if it has enough
-- returns true on success and false when it fails for some reason
-- noEnterancePath=true if you dont want it to go through the storage enterance path
function getItem( item,minQty,noEnterancePath )
if type(minQty)~="number" then minQty=64 end
if type(noEnterancePath)~="boolean" then noEnterancePath=false end
-- count quantity already in inventory
local qtyRequired = minQty - getItemCount(item)
if qtyRequired < 1 then
-- already got enough of target item
return true
end
-- item must be obtainable
local x,y,z,dir = getItemAccess(item)
if type(x)~="number" or type(y)~="number"
or type(z)~="number" or type(dir)~="string" then
return false
end
if not noEnterancePath then
followStoragePath()
end
-- check if inv is full
update()
local invFull = true
for slot=1,16 do
if inventory[slot].qty == 0 then
invFull = false
break
end
end
if invFull then
dropoff(false)
end
gps.goto(x,y,z,dir)
local qtyInInv-- number
repeat
recordDifference()
if dir == gps.up then
turtle.suckUp()
elseif dir == gps.down then
turtle.suckDown()
else
turtle.suck()
end
-- check how many slots changed when you sucked for items
local diff = getDifference()
local slotsChanged = 0
for slot,item in pairs(diff) do
slotsChanged = slotsChanged + 1
end
if slotsChanged == 0 then
-- didn't obtain anything when trying to get items
-- gonna have to loop through again and again
--break
elseif slotsChanged > 1 then
-- more than one slot changed, might be 'cause of player interaction
-- go empty out and try again just so we know for sure we can keep track of the item
dropoff(false)
gps.goto(x,y,z,dir)
elseif slotsChanged == 1 then
-- one slot changed, record it, gotta keep track of it
for slot in pairs(diff) do
inventory[slot].type = item
end
end
qtyInInv = getItemCount(item)
until qtyInInv >= qtyRequired
if not noEnterancePath then
followStoragePath(true)
end
return true
end
-- example input
-- t = { "dirt", "sapling" } minQty = 64: gets 64 dirt and 64 saplings
function getItems( t,minQty )
for num,item in ipairs(t) do
if num == 1 then
followStoragePath(false)
end
getItem(item,minQty,true)
if num == #t then
followStoragePath(true)
end
end
end
function select( item )
for slot=1,16 do
if inventory[slot].type == item then
turtle.select(slot)
return true
end
end
return false
end
Comments