people/actions/place.lua

107 lines
3.7 KiB
Lua

local dbg
if moddebug then dbg=moddebug.dbg("people") else dbg={v1=function() end,v2=function() end,v3=function() end} end
people.actions.place = function(state)
if not state.action.pos or type(state.action.pos) ~= "table" or not state.action.item then
dbg.v1(state.ent.name.." has invalid place action")
return true, false
end
local distance = vector.distance(state.pos, state.action.pos)
if distance > 5.5 then
dbg.v1(state.ent.name.." too far away to place - distance is "..distance)
return true, false
end
local yaw = vector.get_yaw(state.pos, state.action.pos)
-- 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 place position")
state.action = {"face", yaw=yaw, prevaction=state.action}
return false
end
state.anim = "mine"
if not state.action.placetime then
state.action.placetime = 1
return false
end
state.action.placetime = state.action.placetime - state.dtime
if state.action.placetime > 0 then
return false
end
-- Do the placing
local inv = state.ent.inventory
local ii = ItemStack(state.action.item.." 1")
if not inv:contains_item("main", ii) then
dbg.v1(state.ent.name.." doesn't have "..state.action.item.." to place")
return true, {"need", item=state.action.item}
end
-- We need a node to build against...
local trydirs, todir
if state.action.againstdir then
trydirs = {state.action.againstdir}
else
trydirs = {{x=0, y=-1, z=0},
{x=0, y=1, z=0},
{x=-1, y=0, z=0},
{x=1, y=0, z=0},
{x=0, y=0, z=-1},
{x=0, y=0, z=1}}
end
local reasons = ""
for _, trydir in pairs(trydirs) do
local n = minetest.get_node(vector.add(state.action.pos, trydir))
-- Certainly can't place against air (but maybe that's covered
-- by buildable_to? Check TODO
if n.name ~= "air" then
-- Don't try and place a slab against a slab of the same kind,
-- because they can end up combinining
if n.name:sub(1, 11) == "stairs:slab" and
n.name == state.action.item then
reasons = reasons.."/similar slab at "..minetest.pos_to_string(trydir)
else
local def = minetest.registered_nodes[n.name]
if def and not def.buildable_to then
todir = trydir
break
else
reasons = reasons.."/unknown or buildable_to node at "..minetest.pos_to_string(trydir)
end
end
else
reasons = reasons.."/air at "..minetest.pos_to_string(trydir)
end
end
if not todir then
dbg.v1(state.ent.name.." can't place - nothing to build against : "..reasons)
return true, false
end
local pointed_thing = {type="node",
under=vector.add(state.action.pos, todir),
above=vector.new(state.action.pos)}
onplace = minetest.registered_items[state.action.item].on_place
if not onplace then onplace = minetest.item_place end
-- Setting the param2 here, but nil is acceptable if it wasn't given as a
-- parameter to the action (normally it shouldn't need to be - maybe just
-- for stairs?)
rstack = onplace(ii, people.get_fake_player(state.ent), pointed_thing, state.action.param2)
inv:remove_item("main", ItemStack(state.action.item.." 1"))
dbg.v1(state.ent.name.." placed "..state.action.item.." at "..minetest.pos_to_string(state.action.pos))
return true, true
end