Added API for registration of banisters and their automatic placement logic on blocks

This commit is contained in:
Andrey2470T 2024-03-22 00:42:49 +03:00
parent 6215821400
commit a3c9a08a90
21 changed files with 224 additions and 17 deletions

180
decor_api/banister.lua Normal file
View File

@ -0,0 +1,180 @@
multidecor.banister = {}
function multidecor.banister.check_for_foot_node(pos)
local foot_node = minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z})
local stair = minetest.get_item_group(foot_node.name, "stair")
local spiral = minetest.get_item_group(foot_node.name, "spiral")
return stair == 1, spiral == 1
end
local function ndef(pos)
return minetest.registered_nodes[minetest.get_node(pos).name]
end
function multidecor.banister.check_for_free_space(pos, invert_second_cond)
local node_def = ndef(pos)
local down_node_def = ndef({x=pos.x, y=pos.y-1, z=pos.z})
local second_cond = down_node_def.drawtype == "airlike" or
not down_node_def.walkable
if invert_second_cond then
second_cond = not second_cond
end
return node_def.drawtype == "airlike" and second_cond
end
local function rotate_vert(dir, sign)
return vector.rotate_around_axis(dir, vector.new(0, 1, 0), sign*math.pi/2)
end
function multidecor.banister.place_banister(pos, common_name, itemstack)
local is_stair, is_spiral = multidecor.banister.check_for_foot_node(pos)
local shape = ""
if is_stair then
shape = "raised"
end
if is_spiral then
shape = "spiral"
end
local name = "multidecor:" .. common_name .. (shape ~= "" and "_" .. shape or "")
minetest.remove_node(pos)
if shape == "" then
local sides_fdirs_map = {
["forward"] = {x=1, y=0, z=0},
["backward"] = {x=-1, y=0, z=0},
["left"] = {x=0, y=0, z=1},
["right"] = {x=0, y=0, z=-1}
}
local function check_and_set_banister(pos, dir_to_pos, side)
local bpos = vector.add(pos, dir_to_pos)
local res1 = multidecor.banister.check_for_free_space(bpos)
if res1 then
local fwd_dir = rotate_vert(dir_to_pos, -1)
local bwd_dir = rotate_vert(dir_to_pos, 1)
local res2 = multidecor.banister.check_for_free_space(bpos + fwd_dir, true)
local res3 = multidecor.banister.check_for_free_space(bpos + bwd_dir, true)
local param2
local cname = name
if res2 then
param2 = minetest.dir_to_facedir(rotate_vert(fwd_dir, 1))
cname = cname .. "_corner"
elseif res3 then
param2 = minetest.dir_to_facedir(fwd_dir)
cname = cname .. "_corner"
else
param2 = minetest.dir_to_facedir(sides_fdirs_map[side])
end
minetest.set_node(bpos, {name=cname, param2=param2})
itemstack:take_item()
end
end
check_and_set_banister(pos, {x=-1, y=0, z=0}, "left")
check_and_set_banister(pos, {x=1, y=0, z=0}, "right")
check_and_set_banister(pos, {x=0, y=0, z=1}, "forward")
check_and_set_banister(pos, {x=0, y=0, z=-1}, "backward")
elseif shape == "raised" then
local dir = multidecor.helpers.get_dir({x=pos.x, y=pos.y-1, z=pos.z})*-1
local dir_to_param2 = minetest.dir_to_facedir(dir)
local left_pos = pos + rotate_vert(dir, 1)
local right_pos = pos + rotate_vert(dir, -1)
if multidecor.banister.check_for_free_space(left_pos) then
minetest.set_node(left_pos, {name=name.."_left", param2=dir_to_param2})
itemstack:take_item()
end
if multidecor.banister.check_for_free_space(right_pos) then
minetest.set_node(right_pos, {name=name.."_right", param2=dir_to_param2})
itemstack:take_item()
end
--[[local left_node_def = ndef(left_pos)
local right_node_def = ndef(right_pos)
local down_left_node_def = ndef({x=left_pos.x, y=left_pos.y-1, z=left_pos.z})
local down_right_node_def = ndef({x=right_pos.x, y=right_pos.y-1, z=right_pos.z})
if left_node_def.drawtype == "airlike" and (down_left_node_def.drawtype == "airlike" or not down_left_node_def.walkable) then
minetest.set_node(left_pos, {name=name.."_left", param2=dir_to_param2})
itemstack:take_item()
end
if right_node_def.drawtype == "airlike" and (down_right_node_def.drawtype == "airlike" or not down_right_node_def.walkable) then
minetest.set_node(right_pos, {name=name.."_right", param2=dir_to_param2})
itemstack:take_item()
end]]
elseif shape == "spiral" then
local dir = multidecor.helpers.get_dir({x=pos.x, y=pos.y-1, z=pos.z})*-1
local dir_to_param2 = minetest.dir_to_facedir(dir)
minetest.set_node(pos, {name=name, param2=dir_to_param2})
itemstack:take_item()
end
return itemstack
end
function multidecor.banister.default_after_place_node(pos, placer, itemstack)
local add_properties = ndef(pos).add_properties
return multidecor.banister.place_banister(pos, add_properties.common_name, itemstack)
end
function multidecor.register.register_banister(name, base_def, add_def, craft_def)
local def = table.copy(base_def)
def.type = "banister"
def.paramtype2 = "facedir"
-- additional properties
if add_def then
if add_def.recipe then
craft_def = add_def
else
def.add_properties = add_def
end
end
def.callbacks = def.callbacks or {}
def.callbacks.after_place_node = def.callbacks.after_place_node or multidecor.banister.default_after_place_node
multidecor.register.register_furniture_unit(name, def, craft_def)
if def.add_properties and def.add_properties.banister_shapes then
local banister_shapes = def.add_properties.banister_shapes
local bshape_def = table.copy(def)
bshape_def.groups = bshape_def.groups or {}
bshape_def.groups.not_in_creative_inventory = 1
bshape_def.callbacks.after_place_node = nil
local function register_banister_shape(shape)
local shape_def = table.copy(bshape_def)
shape_def.mesh = banister_shapes[shape].mesh
shape_def.bounding_boxes = banister_shapes[shape].bboxes
multidecor.register.register_furniture_unit(name .. "_" .. shape, shape_def)
end
register_banister_shape("raised_left")
register_banister_shape("raised_right")
register_banister_shape("spiral")
register_banister_shape("corner")
end
end

View File

@ -6,7 +6,8 @@ function multidecor.helpers.get_dir(pos)
local node = minetest.get_node(pos)
local def = minetest.registered_nodes[node.name]
local dir = def.paramtype2 == "facedir" and vector.copy(minetest.facedir_to_dir(node.param2)) or
def.paramtype2 == "wallmounted" and vector.copy(minetest.wallmounted_to_dir(node.param2))
def.paramtype2 == "wallmounted" and vector.copy(minetest.wallmounted_to_dir(node.param2)) or
vector.new(0, 0, 0)
dir = dir*-1
return dir

View File

@ -9,6 +9,7 @@ dofile(modpath .. "/connecting.lua")
dofile(modpath .. "/register.lua")
dofile(modpath .. "/banister.lua")
dofile(modpath .. "/clock.lua")
dofile(modpath .. "/curtains.lua")
dofile(modpath .. "/door.lua")

View File

@ -75,18 +75,22 @@ function multidecor.placement.calc_place_space_size(bboxes)
return max_bbox
end
function multidecor.placement.check_for_placement(pos, placer)
function multidecor.placement.check_for_placement(pos, placer, itemstack)
local nodename = minetest.get_node(pos).name
local def = minetest.registered_nodes[nodename]
--minetest.debug("check_for_placement()")
if def.drawtype ~= "mesh" and def.drawtype ~= "nodebox" then
return
return itemstack
end
--minetest.debug("continue check_for_placement() (1)")
if def.prevent_placement_check then
return
return itemstack
end
--minetest.debug("continue check_for_placement() (2)")
local bboxes
if def.drawtype == "nodebox" then
@ -113,10 +117,9 @@ function multidecor.placement.check_for_placement(pos, placer)
local can_be_placed = multidecor.placement.check_for_free_space(pos, max_bbox)
if not can_be_placed then
local return_item = ItemStack(nodename)
minetest.remove_node(pos)
placer:get_inventory():add_item("main", return_item)
return return_item
itemstack:set_count(itemstack:get_count()+1)
return itemstack
end
end

View File

@ -5,6 +5,7 @@ multidecor.register = {}
-- Default furniture types
multidecor.register.supported_types = {
"banister",
"seat",
"table",
"shelf",
@ -95,7 +96,7 @@ function multidecor.register.build_description(name, base_desc)
end
function multidecor.register.after_place_node(pos, placer, itemstack)
local leftover = multidecor.placement.check_for_placement(pos, placer)
local leftover = multidecor.placement.check_for_placement(pos, placer, itemstack)
return leftover
end
@ -229,9 +230,9 @@ function multidecor.register.register_furniture_unit(name, def, craft_def)
if f_def.after_place_node then
local prev_after_place = f_def.after_place_node
local function after_place(pos, placer, itemstack)
prev_after_place(pos, placer, itemstack)
local itemstack = prev_after_place(pos, placer, itemstack)
return multidecor.register.after_place_node(pos, placer)
return multidecor.register.after_place_node(pos, placer, itemstack)
end
f_def.after_place_node = after_place

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -33,6 +33,15 @@ local banister_bboxes = {
{0.45, -0.5, -0.5, 0.55, 0.5, 0.5}
}
local right_banister_bbox = {
{-0.55, -0.5, -0.5, -0.45, 0.5, 0.5}
}
local corner_banister_bboxes = {
{0.45, -0.5, -0.5, 0.55, 0.5, 0.5},
{-0.5, -0.5, -0.55, 0.5, 0.5, -0.45}
}
local spiral_banister_bboxes = {
{0.45, -1.0, -0.5, 0.6, 0.8, 0}, -- banister
{0.25, -1.0, 0, 0.5, 0.8, 0.25},
@ -67,6 +76,7 @@ for _, stair in ipairs(stairs_data) do
description = upper_name .. " Ledged Stair Segment",
mesh = "multidecor_ledged_stair_segment.b3d",
tiles = {stair.tex},
groups = {stair=1},
bounding_boxes = stair_ledged_bboxes
})
@ -87,6 +97,7 @@ for _, stair in ipairs(stairs_data) do
description = "Spiral " .. upper_name .. " Stair Segment",
mesh = "multidecor_spiral_stair_segment.b3d",
tiles = {stair.tex},
groups = {stair=1, spiral=1},
bounding_boxes = sstair_bboxes
})
@ -97,6 +108,7 @@ for _, stair in ipairs(stairs_data) do
description = "Spiral " .. upper_name .. " Ledged Stair Segment",
mesh = "multidecor_spiral_ledged_stair_segment.b3d",
tiles = {stair.tex},
groups = {stair=1, spiral=1},
bounding_boxes = sstair_bboxes
})
end
@ -141,6 +153,7 @@ for _, sstair in ipairs(spiral_stairs_data) do
description = "Spiral " .. upper_name .. "Plank Stair Segment",
mesh = "multidecor_spiral_plank_stair_segment.b3d",
tiles = sstair.tex,
groups = {stair=1, spiral=1},
bounding_boxes = sstair_plank_bboxes
})
@ -154,8 +167,7 @@ for _, sstair in ipairs(spiral_stairs_data) do
bounding_boxes = sstair_plank_bboxes_wban
})
multidecor.register.register_furniture_unit("spiral_" .. sstair.name .. "_banister", {
type = "decoration",
--[[multidecor.register.register_banister("spiral_" .. sstair.name .. "_banister", {
style = "modern",
material = sstair.name == "sequoia" and "wood" or sstair.name,
description = "Spiral " .. upper_name .. " Banister",
@ -163,10 +175,10 @@ for _, sstair in ipairs(spiral_stairs_data) do
tiles = sstair.tex,
bounding_boxes = spiral_banister_bboxes,
prevent_placement_check = true
})
})]]
multidecor.register.register_furniture_unit(sstair.name .. "_banister", {
type = "decoration",
local banister_common_name = sstair.name .. "_banister"
multidecor.register.register_banister(banister_common_name, {
style = "modern",
material = sstair.name == "sequoia" and "wood" or sstair.name,
description = upper_name .. " Banister",
@ -174,9 +186,18 @@ for _, sstair in ipairs(spiral_stairs_data) do
tiles = sstair.tex,
bounding_boxes = banister_bboxes,
prevent_placement_check = true
},
{
common_name = banister_common_name,
banister_shapes = {
["raised_left"] = {mesh="multidecor_banister_raised_left.b3d", bboxes=banister_bboxes},
["raised_right"] = {mesh="multidecor_banister_raised_right.b3d", bboxes=right_banister_bbox},
["spiral"] = {mesh="multidecor_spiral_banister.b3d", bboxes=spiral_banister_bboxes},
["corner"] = {mesh="multidecor_banister_corner.b3d", bboxes=corner_banister_bboxes}
}
})
multidecor.register.register_furniture_unit(sstair.name .. "_banister_raised", {
--[[multidecor.register.register_banister(sstair.name .. "_banister_raised", {
type = "decoration",
style = "modern",
material = sstair.name == "sequoia" and "wood" or sstair.name,
@ -185,5 +206,5 @@ for _, sstair in ipairs(spiral_stairs_data) do
tiles = sstair.tex,
bounding_boxes = banister_bboxes,
prevent_placement_check = true
})
})]]
end