people/actions/stash_and_retrieve.lua

158 lines
4.6 KiB
Lua

local dbg
if moddebug then dbg=moddebug.dbg("people") else dbg={v1=function() end,v2=function() end,v3=function() end} end
local function move_items(srcinv, destinv, itemspec)
local removespec
local single = true
local keepstack = nil
if type(itemspec) == "string" then
removespec = itemspec
else
removespec = itemspec[1]
if itemspec.keep then
keepstack = srcinv:remove_item("main", ItemStack(removespec.." "..itemspec.keep))
end
end
if not removespec:find(" ") then
removespec = removespec.." 99"
single = false
end
local count = 0
while true do
local stack = srcinv:remove_item("main", ItemStack(removespec))
dbg.v3("remove_item of '"..removespec.."' removed a stack of "..stack:get_count())
if stack:get_count() == 0 then break end
count = count + stack:get_count()
local leftover = destinv:add_item("main", stack)
count = count - leftover:get_count()
if leftover:get_count() ~= 0 then
srcinv:add_item("main", stack)
break
end
if single then break end
end
if keepstack then
srcinv:add_item("main", keepstack)
end
return removespec, count
end
people.actions.stash = function(state)
if not (state.action.dest or state.action.pos) or
not state.action.items or type(state.action.items) ~= "table" then
dbg.v1(state.ent.name.." has invalid stash action")
return true, false
end
local foundpos = state.action.pos
if not foundpos then
foundpos = minetest.find_node_near(vector.round(state.pos), 3, state.action.dest)
end
if not foundpos then
dbg.v1(state.ent.name.." can't find "..state.action.dest.." to stash in")
return true, false
end
local yaw = vector.get_yaw(state.pos, foundpos)
-- Need to be fuzzy about comparing this, because of the
-- lua double/minetest float issue
if math.abs(yaw - state.yaw) > 0.2 then
dbg.v3(state.ent.name.." turning to face stash target")
state.action = {"face", yaw=yaw, prevaction=state.action}
return false
end
state.anim = "mine"
if not state.action.stashtime then
state.action.stashtime = 0.5
return false
end
state.action.stashtime = state.action.stashtime - state.dtime
if state.action.stashtime > 0 then
return false
end
local meta = minetest.get_meta(foundpos)
if not meta then
dbg.v1(state.ent.name.." can't get stash node meta")
return true, false
end
local itemname, count = move_items(state.ent.inventory,
meta:get_inventory(), state.action.items[1])
dbg.v1(state.ent.name.." stashed "..count.." "..itemname)
table.remove(state.action.items, 1)
if #state.action.items > 0 then return false end
dbg.v2(state.ent.name.." finished stashing")
return true, true
end
people.actions.retrieve = function(state)
if not (state.action.dest or state.action.pos) or
not state.action.items or type(state.action.items) ~= "table" then
dbg.v1(state.ent.name.." has invalid retrieve action")
return true, false
end
local foundpos = state.action.pos
if not foundpos then
foundpos = minetest.find_node_near(vector.round(state.pos), 3, state.action.dest)
end
if not foundpos then
dbg.v1(state.ent.name.." can't find "..state.action.dest.." to retrieve from")
return true, false
end
local yaw = vector.get_yaw(state.pos, foundpos)
-- Need to be fuzzy about comparing this, because of the
-- lua double/minetest float issue
if math.abs(yaw - state.yaw) > 0.2 then
dbg.v3(state.ent.name.." turning to face retrieve target")
state.action = {"face", yaw=yaw, prevaction=state.action}
return false
end
state.anim = "mine"
if not state.action.retrievetime then
state.action.retrievetime = 0.5
return false
end
state.action.retrievetime = state.action.retrievetime - state.dtime
if state.action.retrievetime > 0 then
return false
end
local meta = minetest.get_meta(foundpos)
if not meta then
dbg.v1(state.ent.name.." can't get retrieve node meta")
return true, false
end
local itemname, count = move_items(meta:get_inventory(),
state.ent.inventory, state.action.items[1])
dbg.v1(state.ent.name.." retrieved "..count.." "..itemname)
table.remove(state.action.items, 1)
if #state.action.items > 0 then return false end
dbg.v2(state.ent.name.." finished retrieving")
return true, true
end