123 lines
2.9 KiB
Lua
123 lines
2.9 KiB
Lua
multidecor.placement = {}
|
|
|
|
function multidecor.placement.check_for_free_space(pos, size_bbox)
|
|
local free = true
|
|
|
|
for x = size_bbox[1], size_bbox[4] do
|
|
for y = size_bbox[2], size_bbox[5] do
|
|
for z = size_bbox[3], size_bbox[6] do
|
|
local shift_pos = pos + vector.new(x, y, z)
|
|
|
|
if not vector.equals(pos, shift_pos) then
|
|
local shift_node_def = minetest.registered_nodes[minetest.get_node(shift_pos).name]
|
|
|
|
if shift_node_def.drawtype ~= "airlike" or shift_node_def.walkable then
|
|
free = false
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
if not free then break end
|
|
end
|
|
|
|
if not free then break end
|
|
end
|
|
|
|
return free
|
|
end
|
|
|
|
function multidecor.placement.box_repair(box)
|
|
local rep_box = table.copy(box)
|
|
|
|
if rep_box[1] > rep_box[4] then
|
|
local x = rep_box[1]
|
|
rep_box[1] = rep_box[4]
|
|
rep_box[4] = x
|
|
end
|
|
|
|
if rep_box[2] > rep_box[5] then
|
|
local y = rep_box[2]
|
|
rep_box[2] = rep_box[5]
|
|
rep_box[5] = y
|
|
end
|
|
|
|
if rep_box[3] > rep_box[6] then
|
|
local z = rep_box[3]
|
|
rep_box[3] = rep_box[6]
|
|
rep_box[6] = z
|
|
end
|
|
|
|
return rep_box
|
|
end
|
|
|
|
function multidecor.placement.calc_place_space_size(bboxes)
|
|
local max_bbox = {0, 0, 0, 0, 0, 0}
|
|
|
|
for box_id, _ in ipairs(bboxes) do
|
|
local new_box = multidecor.placement.box_repair(bboxes[box_id])
|
|
|
|
for i, v in ipairs(new_box) do
|
|
if i < 4 then
|
|
max_bbox[i] = box_id == 1 and v or math.min(max_bbox[i], v)
|
|
else
|
|
max_bbox[i] = math.max(max_bbox[i], v)
|
|
end
|
|
end
|
|
end
|
|
|
|
for i, coord in ipairs(max_bbox) do
|
|
local int, frac = math.modf(coord)
|
|
local sgn = math.sign(coord)
|
|
max_bbox[i] = math.abs(frac) > 0.5 and sgn*math.ceil(math.abs(coord)) or sgn*math.floor(math.abs(coord))
|
|
end
|
|
|
|
return max_bbox
|
|
end
|
|
|
|
function multidecor.placement.check_for_placement(pos, placer, itemstack)
|
|
local nodename = minetest.get_node(pos).name
|
|
local def = minetest.registered_nodes[nodename]
|
|
|
|
if def.drawtype ~= "mesh" and def.drawtype ~= "nodebox" then
|
|
return itemstack
|
|
end
|
|
|
|
if def.prevent_placement_check then
|
|
return itemstack
|
|
end
|
|
|
|
local bboxes
|
|
|
|
if def.drawtype == "nodebox" then
|
|
bboxes = def.node_box.fixed
|
|
else
|
|
bboxes = def.collision_box.fixed
|
|
end
|
|
|
|
local max_bbox = multidecor.placement.calc_place_space_size(bboxes)
|
|
|
|
local rot_bbox = {}
|
|
rot_bbox.min = multidecor.helpers.rotate_to_node_dir(pos,
|
|
vector.rotate_around_axis(vector.new(max_bbox[1], max_bbox[2], max_bbox[3]), vector.new(0, 1, 0), math.pi)
|
|
)
|
|
rot_bbox.max = multidecor.helpers.rotate_to_node_dir(pos,
|
|
vector.rotate_around_axis(vector.new(max_bbox[4], max_bbox[5], max_bbox[6]), vector.new(0, 1, 0), math.pi)
|
|
)
|
|
|
|
max_bbox = multidecor.placement.box_repair({
|
|
rot_bbox.min.x, rot_bbox.min.y, rot_bbox.min.z,
|
|
rot_bbox.max.x, rot_bbox.max.y, rot_bbox.max.z
|
|
})
|
|
|
|
local can_be_placed = multidecor.placement.check_for_free_space(pos, max_bbox)
|
|
|
|
if not can_be_placed then
|
|
minetest.remove_node(pos)
|
|
else
|
|
itemstack:set_count(itemstack:get_count()-1)
|
|
end
|
|
|
|
return itemstack
|
|
end
|