107 lines
3.7 KiB
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
|
|
|
|
|