New way of registering stairs.

The old one still works.

Adding stairs becomes a lot easier, the groups, sounds and a lot more (see https://github.com/HybridDog/minetest_game/blob/stairsupdate/mods/stairs/init.lua#L150-L153) are added automatically to the stair.
This commit is contained in:
Rui 2015-07-15 19:22:44 +09:00 committed by HybridDog
parent 7d2dfe4101
commit f94eb53e0f
2 changed files with 324 additions and 215 deletions

View file

@ -195,29 +195,20 @@ Stairs API
The stairs API lets you register stairs and slabs and ensures that they are registered the same way as those The stairs API lets you register stairs and slabs and ensures that they are registered the same way as those
delivered with Minetest Game, to keep them compatible with other mods. delivered with Minetest Game, to keep them compatible with other mods.
stairs.register_stair(subname, recipeitem, groups, images, description, sounds) stairs.register_stair({origin = string[, fixed_name = string, recipe = string, add_crafting = bool}, extradef])
-> Registers a stair. -> Registers a stair.
-> subname: Basically the material name (e.g. cobble) used for the stair name. Nodename pattern: "stairs:stair_subname" -> origin is the node the stair consists of, selected parts of the node definition of origin are copied and used for the stair, TODO: find out why it copies weird stuff although dumping the def of the original node (superpick mod) doesn't show them and try to avoid it
-> recipeitem: Item used in the craft recipe, e.g. "default:cobble" -> fixed_name can be used to avoid giving the stair a name automatically, do not use it for register_stair_and_slab
-> groups: see [Known damage and digging time defining groups] -> recipe is the craft recipe, if omitted origin is used
-> images: see [Tile definition] -> add_crafting can be set to false to disable adding a craft recipe for the stair
-> description: used for the description field in the stair's definition -> extradef is a custom node definition table, it can be used e.g. to give the slab a specific drop
-> sounds: see [#Default sounds]
stairs.register_slab(subname, recipeitem, groups, images, description, sounds) stairs.register_slab is like register_stair but adds a slab
-> Registers a slabs stairs.register_stair_and_slab calls register_stair and register_slab
-> subname: Basically the material name (e.g. cobble) used for the stair name. Nodename pattern: "stairs:stair_subname"
-> recipeitem: Item used in the craft recipe, e.g. "default:cobble"
-> groups: see [Known damage and digging time defining groups]
-> images: see [Tile definition]
-> description: used for the description field in the stair's definition
-> sounds: see [#Default sounds]
stairs.register_stair_and_slab(subname, recipeitem, groups, images, desc_stair, desc_slab, sounds) For example, following code adds a stone slab and stair:
-> A wrapper for stairs.register_stair and stairs.register_slab stairs.register_stair_and_slab({origin = "default:stone"})
-> Uses almost the same arguments as stairs.register_stair The stair is named "default:stair_stone" and contains groups, sounds, etc. from "default:stone".
-> desc_stair: Description for stair node
-> desc_slab: Description for slab node
Xpanes API Xpanes API
---------- ----------

View file

@ -7,259 +7,345 @@
stairs = {} stairs = {}
-- Register aliases for new pine node names
minetest.register_alias("stairs:stair_pinewood", "stairs:stair_pine_wood")
minetest.register_alias("stairs:slab_pinewood", "stairs:slab_pine_wood")
-- Get setting for replace ABM -- Get setting for replace ABM
local replace = minetest.setting_getbool("enable_stairs_replace_abm") local replace = minetest.setting_getbool("enable_stairs_replace_abm")
-- Register stairs. -- link functions instead of redefining them every time
-- Node will be called stairs:stair_<subname>
function stairs.register_stair(subname, recipeitem, groups, images, description, sounds) local function on_place_stair(itemstack, placer, pointed_thing)
groups.stair = 1 if pointed_thing.type ~= "node" then
minetest.register_node(":stairs:stair_" .. subname, { return itemstack
description = description, end
drawtype = "mesh",
mesh = "stairs_stair.obj", local p0 = pointed_thing.under
tiles = images, local p1 = pointed_thing.above
paramtype = "light", local param2 = 0
paramtype2 = "facedir",
is_ground_content = false, local placer_pos = placer:getpos()
groups = groups, if placer_pos then
sounds = sounds, local dir = {
selection_box = { x = p1.x - placer_pos.x,
type = "fixed", y = p1.y - placer_pos.y,
fixed = { z = p1.z - placer_pos.z
{-0.5, -0.5, -0.5, 0.5, 0, 0.5}, }
{-0.5, 0, 0, 0.5, 0.5, 0.5}, param2 = minetest.dir_to_facedir(dir)
}, end
},
collision_box = { if p0.y - 1 == p1.y then
type = "fixed", param2 = param2 + 20
fixed = { if param2 == 21 then
{-0.5, -0.5, -0.5, 0.5, 0, 0.5}, param2 = 23
{-0.5, 0, 0, 0.5, 0.5, 0.5}, elseif param2 == 23 then
}, param2 = 21
}, end
on_place = function(itemstack, placer, pointed_thing) end
if pointed_thing.type ~= "node" then
return itemstack return minetest.item_place(itemstack, placer, pointed_thing, param2)
end
local function on_place_slab(itemstack, placer, pointed_thing, slabname, recipeitem)
if pointed_thing.type ~= "node" then
return itemstack
end
-- If it's being placed on an another similar one, replace it with
-- a full block
local slabpos = nil
local slabnode = nil
local p0 = pointed_thing.under
local p1 = pointed_thing.above
local n0 = minetest.get_node(p0)
local n1 = minetest.get_node(p1)
local param2 = 0
local n0_is_upside_down = (n0.name == slabname and
n0.param2 >= 20)
if n0.name == slabname and not n0_is_upside_down and
p0.y + 1 == p1.y then
slabpos = p0
slabnode = n0
elseif n1.name == slabname then
slabpos = p1
slabnode = n1
end
if slabpos then
-- Remove the slab at slabpos
minetest.remove_node(slabpos)
-- Make a fake stack of a single item and try to place it
local fakestack = ItemStack(recipeitem)
fakestack:set_count(itemstack:get_count())
pointed_thing.above = slabpos
local success
fakestack, success = minetest.item_place(fakestack, placer,
pointed_thing)
-- If the item was taken from the fake stack, decrement original
if success then
itemstack:set_count(fakestack:get_count())
-- Else put old node back
else
minetest.set_node(slabpos, slabnode)
end
return itemstack
end
-- Upside down slabs
if p0.y - 1 == p1.y then
-- Turn into full block if pointing at a existing slab
if n0_is_upside_down then
-- Remove the slab at the position of the slab
minetest.remove_node(p0)
-- Make a fake stack of a single item and try to place it
local fakestack = ItemStack(recipeitem)
fakestack:set_count(itemstack:get_count())
pointed_thing.above = p0
local success
fakestack, success = minetest.item_place(fakestack, placer,
pointed_thing)
-- If the item was taken from the fake stack, decrement original
if success then
itemstack:set_count(fakestack:get_count())
-- Else put old node back
else
minetest.set_node(p0, n0)
end end
return itemstack
end
local p0 = pointed_thing.under -- Place upside down slab
local p1 = pointed_thing.above param2 = 20
local param2 = 0 end
local placer_pos = placer:getpos() -- If pointing at the side of a upside down slab
if placer_pos then if n0_is_upside_down and p0.y + 1 ~= p1.y then
local dir = { param2 = 20
x = p1.x - placer_pos.x, end
y = p1.y - placer_pos.y,
z = p1.z - placer_pos.z
}
param2 = minetest.dir_to_facedir(dir)
end
if p0.y - 1 == p1.y then return minetest.item_place(itemstack, placer, pointed_thing, param2)
param2 = param2 + 20 end
if param2 == 21 then
param2 = 23
elseif param2 == 23 then
param2 = 21
end
end
return minetest.item_place(itemstack, placer, pointed_thing, param2)
end, -- boxes for stairs and slabs
})
local stairbox = {
type = "fixed",
fixed = {
{-0.5, -0.5, -0.5, 0.5, 0, 0.5},
{-0.5, 0, 0, 0.5, 0.5, 0.5},
},
}
local slabbox = {
type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5},
}
-- contents of the node definition which gets copied
local to_copy = {"tiles", "use_texture_alpha", "post_effect_color",
"is_ground_content", "walkable", "pointable", "diggable", "climbable",
"buildable_to", "light_source", "damage_per_second", "sounds", "groups",
"sunlight_propagates"}
-- Node will be called like origin, just with "stair_" after the ":"
function stairs.register_stair(data, extradef, groups, images, description, sounds)
if groups then
-- support the previous function using a tail call
local ldata = {
fixed_name = "stairs:stair_" .. data,
origin = extradef,
}
if replace then
ldata.upside_down = ldata.fixed_name .. "upside_down"
end
return stairs.register_stair(
ldata,
{
description = description,
tiles = images,
groups = groups,
sounds = sounds,
}
)
end
local origname = data.origin
local origdef = minetest.registered_nodes[origname]
if not origdef then
origdef = {}
minetest.log("error", "[stairs] "..origname.." should exist before adding a stair for it.")
end
local def = {}
for _,i in pairs(to_copy) do
def[i] = rawget(origdef, i)
end
if origdef.description then
def.description = origdef.description.." Stair"
end
def.drawtype = "mesh"
def.mesh = "stairs_stair.obj"
def.paramtype = "light"
def.paramtype2 = "facedir"
def.selection_box = stairbox
def.collision_box = stairbox
def.on_place = on_place_stair
if extradef then
for i,v in pairs(extradef) do
def[i] = v
end
end
def.groups = def.groups or {}
def.groups.stair = 1
local name = data.fixed_name
if not name then
local modname, nodename = unpack(string.split(origname, ":"))
name = modname..":stair_"..nodename
end
minetest.register_node(":"..name, def)
-- for replace ABM -- for replace ABM
if replace then if data.upside_down then
minetest.register_node(":stairs:stair_" .. subname .. "upside_down", { minetest.register_node(":"..data.upside_down, {
replace_name = "stairs:stair_" .. subname, replace_name = name,
groups = {slabs_replace = 1}, groups = {slabs_replace = 1},
}) })
end end
if data.add_crafting == false then
return
end
local input = data.recipe or origname
minetest.register_craft({ minetest.register_craft({
output = 'stairs:stair_' .. subname .. ' 6', output = name .. " 6",
recipe = { recipe = {
{recipeitem, "", ""}, {input, "", ""},
{recipeitem, recipeitem, ""}, {input, input, ""},
{recipeitem, recipeitem, recipeitem}, {input, input, input},
}, },
}) })
-- Flipped recipe for the silly minecrafters -- Flipped recipe for the silly minecrafters
minetest.register_craft({ minetest.register_craft({
output = 'stairs:stair_' .. subname .. ' 6', output = name .. " 6",
recipe = { recipe = {
{"", "", recipeitem}, {"", "", input},
{"", recipeitem, recipeitem}, {"", input, input},
{recipeitem, recipeitem, recipeitem}, {input, input, input},
}, },
}) })
end end
-- Node will be called like origin, just with "slab_" after the ":"
function stairs.register_slab(data, extradef, groups, images, description, sounds)
if groups then
-- support the previous function using a tail call
local ldata = {
fixed_name = "stairs:slab_" .. data,
origin = extradef,
}
if replace then
ldata.upside_down = ldata.fixed_name .. "upside_down"
end
return stairs.register_slab(
ldata,
{
description = description,
tiles = images,
groups = groups,
sounds = sounds,
}
)
end
-- Register slabs. local origname = data.origin
-- Node will be called stairs:slab_<subname> local origdef = minetest.registered_nodes[origname]
if not origdef then
origdef = {}
minetest.log("error", "[stairs] "..origname.." should exist before adding a slab for it.")
end
function stairs.register_slab(subname, recipeitem, groups, images, description, sounds) local def = {}
groups.slab = 1 for _,i in pairs(to_copy) do
minetest.register_node(":stairs:slab_" .. subname, { def[i] = rawget(origdef, i)
description = description, end
drawtype = "nodebox",
tiles = images,
paramtype = "light",
paramtype2 = "facedir",
is_ground_content = false,
groups = groups,
sounds = sounds,
node_box = {
type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5},
},
on_place = function(itemstack, placer, pointed_thing)
if pointed_thing.type ~= "node" then
return itemstack
end
-- If it's being placed on an another similar one, replace it with if origdef.description then
-- a full block def.description = origdef.description.." Slab"
local slabpos = nil end
local slabnode = nil
local p0 = pointed_thing.under
local p1 = pointed_thing.above
local n0 = minetest.get_node(p0)
local n1 = minetest.get_node(p1)
local param2 = 0
local n0_is_upside_down = (n0.name == "stairs:slab_" .. subname and def.drawtype = "nodebox"
n0.param2 >= 20) def.paramtype = "light"
def.paramtype2 = "facedir"
def.node_box = slabbox
if n0.name == "stairs:slab_" .. subname and not n0_is_upside_down and local name = data.fixed_name
p0.y + 1 == p1.y then if not name then
slabpos = p0 local modname, nodename = unpack(string.split(origname, ":"))
slabnode = n0 name = modname..":slab_"..nodename
elseif n1.name == "stairs:slab_" .. subname then end
slabpos = p1
slabnode = n1
end
if slabpos then
-- Remove the slab at slabpos
minetest.remove_node(slabpos)
-- Make a fake stack of a single item and try to place it
local fakestack = ItemStack(recipeitem)
fakestack:set_count(itemstack:get_count())
pointed_thing.above = slabpos def.on_place = function(itemstack, placer, pointed_thing)
local success return on_place_slab(itemstack, placer, pointed_thing, name, origname)
fakestack, success = minetest.item_place(fakestack, placer, end
pointed_thing)
-- If the item was taken from the fake stack, decrement original
if success then
itemstack:set_count(fakestack:get_count())
-- Else put old node back
else
minetest.set_node(slabpos, slabnode)
end
return itemstack
end
-- Upside down slabs if extradef then
if p0.y - 1 == p1.y then for i,v in pairs(extradef) do
-- Turn into full block if pointing at a existing slab def[i] = v
if n0_is_upside_down then end
-- Remove the slab at the position of the slab end
minetest.remove_node(p0)
-- Make a fake stack of a single item and try to place it
local fakestack = ItemStack(recipeitem)
fakestack:set_count(itemstack:get_count())
pointed_thing.above = p0 def.groups = def.groups or {}
local success def.groups.slab = 1
fakestack, success = minetest.item_place(fakestack, placer,
pointed_thing)
-- If the item was taken from the fake stack, decrement original
if success then
itemstack:set_count(fakestack:get_count())
-- Else put old node back
else
minetest.set_node(p0, n0)
end
return itemstack
end
-- Place upside down slab minetest.register_node(":"..name, def)
param2 = 20
end
-- If pointing at the side of a upside down slab
if n0_is_upside_down and p0.y + 1 ~= p1.y then
param2 = 20
end
return minetest.item_place(itemstack, placer, pointed_thing, param2)
end,
})
-- for replace ABM -- for replace ABM
if replace then if data.upside_down then
minetest.register_node(":stairs:slab_" .. subname .. "upside_down", { minetest.register_node(":"..data.upside_down, {
replace_name = "stairs:slab_".. subname, replace_name = name,
groups = {slabs_replace = 1}, groups = {slabs_replace = 1},
}) })
end end
if data.add_crafting == false then
return
end
local input = data.recipe or origname
minetest.register_craft({ minetest.register_craft({
output = 'stairs:slab_' .. subname .. ' 6', output = name .. " 6",
recipe = { recipe = {
{recipeitem, recipeitem, recipeitem}, {input, input, input},
}, },
}) })
end end
-- Optionally replace old "upside_down" nodes with new param2 versions.
-- Disabled by default.
if replace then
minetest.register_abm({
nodenames = {"group:slabs_replace"},
interval = 16,
chance = 1,
action = function(pos, node)
node.name = minetest.registered_nodes[node.name].replace_name
node.param2 = node.param2 + 20
if node.param2 == 21 then
node.param2 = 23
elseif node.param2 == 23 then
node.param2 = 21
end
minetest.set_node(pos, node)
end,
})
end
-- Stair/slab registration function. -- Stair/slab registration function.
-- Nodes will be called stairs:{stair,slab}_<subname> -- If groups etc. given (deprecated), nodes will be called stairs:{stair,slab}_<subname>
function stairs.register_stair_and_slab(subname, recipeitem, groups, images, function stairs.register_stair_and_slab(subname, recipeitem, groups, images, desc_stair, desc_slab, sounds)
desc_stair, desc_slab, sounds)
stairs.register_stair(subname, recipeitem, groups, images, desc_stair, sounds) stairs.register_stair(subname, recipeitem, groups, images, desc_stair, sounds)
stairs.register_slab(subname, recipeitem, groups, images, desc_slab, sounds) stairs.register_slab(subname, recipeitem, groups, images, desc_slab, sounds)
end end
-- Register default stairs and slabs -- Register default stairs and slabs
-- TODO: put this into default and use the new way of adding stairs and slabs
stairs.register_stair_and_slab("wood", "default:wood", stairs.register_stair_and_slab("wood", "default:wood",
{snappy = 2, choppy = 2, oddly_breakable_by_hand = 2, flammable = 3}, {snappy = 2, choppy = 2, oddly_breakable_by_hand = 2, flammable = 3},
@ -407,3 +493,35 @@ stairs.register_stair_and_slab("goldblock", "default:goldblock",
"Gold Block Stair", "Gold Block Stair",
"Gold Block Slab", "Gold Block Slab",
default.node_sound_stone_defaults()) default.node_sound_stone_defaults())
-- legacy
-- Register aliases for new pine node names
minetest.register_alias("stairs:stair_pinewood", "stairs:stair_pine_wood")
minetest.register_alias("stairs:slab_pinewood", "stairs:slab_pine_wood")
-- Optionally replace old "upside_down" nodes with new param2 versions.
-- Disabled by default.
if replace then
minetest.register_abm({
nodenames = {"group:slabs_replace"},
interval = 16,
chance = 1,
action = function(pos, node)
node.name = minetest.registered_nodes[node.name].replace_name
node.param2 = node.param2 + 20
if node.param2 == 21 then
node.param2 = 23
elseif node.param2 == 23 then
node.param2 = 21
end
minetest.set_node(pos, node)
end,
})
end