-- stairs/init.lua -- Minetest 0.4 mod: stairs -- See README.txt for licensing and other information. -- Global namespace for functions stairs = {} -- Load support for MT game translation. local S = minetest.get_translator("stairs") -- Same as S, but will be ignored by translation file update scripts local T = S local function rotate_and_place(itemstack, placer, pointed_thing) local p0 = pointed_thing.under local p1 = pointed_thing.above local param2 = 0 if placer then local placer_pos = placer:get_pos() if placer_pos then param2 = minetest.dir_to_facedir(vector.subtract(p1, placer_pos)) end local finepos = minetest.pointed_thing_to_face_pos(placer, pointed_thing) local fpos = finepos.y % 1 if p0.y - 1 == p1.y or (fpos > 0 and fpos < 0.5) or (fpos < -0.5 and fpos > -0.999999999) then param2 = param2 + 20 if param2 == 21 then param2 = 23 elseif param2 == 23 then param2 = 21 end end end return minetest.item_place(itemstack, placer, pointed_thing, param2) end -- Register stair -- Node will be called stairs:stair_ function stairs.register_stair(subname, recipeitem, groups, images, description, sounds, worldaligntex) local src_def = minetest.registered_nodes[recipeitem] -- Set backface culling and world-aligned textures local stair_images = {} for i, image in ipairs(images) do if type(image) == "string" then stair_images[i] = { name = image, backface_culling = true, } if worldaligntex then stair_images[i].align_style = "world" end else stair_images[i] = table.copy(image) if stair_images[i].backface_culling == nil then stair_images[i].backface_culling = true end if worldaligntex and stair_images[i].align_style == nil then stair_images[i].align_style = "world" end end end local new_groups = table.copy(groups) new_groups.stair = 1 minetest.register_node(":stairs:stair_" .. subname, { description = description, drawtype = "nodebox", tiles = stair_images, use_texture_alpha = src_def and src_def.use_texture_alpha, paramtype = "light", paramtype2 = "facedir", is_ground_content = false, groups = new_groups, sounds = sounds, node_box = { type = "fixed", fixed = { {-0.5, -0.5, -0.5, 0.5, 0.0, 0.5}, {-0.5, 0.0, 0.0, 0.5, 0.5, 0.5}, }, }, on_place = function(itemstack, placer, pointed_thing) if pointed_thing.type ~= "node" then return itemstack end return rotate_and_place(itemstack, placer, pointed_thing) end, }) end -- Register slab -- Node will be called stairs:slab_ function stairs.register_slab(subname, recipeitem, groups, images, description, sounds, worldaligntex) local src_def = minetest.registered_nodes[recipeitem] -- Set world-aligned textures local slab_images = {} for i, image in ipairs(images) do if type(image) == "string" then slab_images[i] = { name = image, } if worldaligntex then slab_images[i].align_style = "world" end else slab_images[i] = table.copy(image) if worldaligntex and image.align_style == nil then slab_images[i].align_style = "world" end end end local new_groups = table.copy(groups) new_groups.slab = 1 minetest.register_node(":stairs:slab_" .. subname, { description = description, drawtype = "nodebox", tiles = slab_images, use_texture_alpha = src_def and src_def.use_texture_alpha, paramtype = "light", paramtype2 = "facedir", is_ground_content = false, groups = new_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) local under = minetest.get_node(pointed_thing.under) local wield_item = itemstack:get_name() local player_name = placer and placer:get_player_name() or "" if under and under.name:find("^stairs:slab_") then -- place slab using under node orientation local dir = minetest.dir_to_facedir(vector.subtract( pointed_thing.above, pointed_thing.under), true) local p2 = under.param2 -- Placing a slab on an upside down slab should make it right-side up. if p2 >= 20 and dir == 8 then p2 = p2 - 20 -- same for the opposite case: slab below normal slab elseif p2 <= 3 and dir == 4 then p2 = p2 + 20 end -- else attempt to place node with proper param2 minetest.item_place_node(ItemStack(wield_item), placer, pointed_thing, p2) if not minetest.is_creative_enabled(player_name) then itemstack:take_item() end return itemstack else return rotate_and_place(itemstack, placer, pointed_thing) end end, }) end -- Register inner stair -- Node will be called stairs:stair_inner_ function stairs.register_stair_inner(subname, recipeitem, groups, images, description, sounds, worldaligntex, full_description) local src_def = minetest.registered_nodes[recipeitem] -- Set backface culling and world-aligned textures local stair_images = {} for i, image in ipairs(images) do if type(image) == "string" then stair_images[i] = { name = image, backface_culling = true, } if worldaligntex then stair_images[i].align_style = "world" end else stair_images[i] = table.copy(image) if stair_images[i].backface_culling == nil then stair_images[i].backface_culling = true end if worldaligntex and stair_images[i].align_style == nil then stair_images[i].align_style = "world" end end end local new_groups = table.copy(groups) new_groups.stair = 1 if full_description then description = full_description else description = "Inner " .. description end minetest.register_node(":stairs:stair_inner_" .. subname, { description = description, drawtype = "nodebox", tiles = stair_images, use_texture_alpha = src_def and src_def.use_texture_alpha, paramtype = "light", paramtype2 = "facedir", is_ground_content = false, groups = new_groups, sounds = sounds, node_box = { type = "fixed", fixed = { {-0.5, -0.5, -0.5, 0.5, 0.0, 0.5}, {-0.5, 0.0, 0.0, 0.5, 0.5, 0.5}, {-0.5, 0.0, -0.5, 0.0, 0.5, 0.0}, }, }, on_place = function(itemstack, placer, pointed_thing) if pointed_thing.type ~= "node" then return itemstack end return rotate_and_place(itemstack, placer, pointed_thing) end, }) end -- Register outer stair -- Node will be called stairs:stair_outer_ function stairs.register_stair_outer(subname, recipeitem, groups, images, description, sounds, worldaligntex, full_description) local src_def = minetest.registered_nodes[recipeitem] -- Set backface culling and world-aligned textures local stair_images = {} for i, image in ipairs(images) do if type(image) == "string" then stair_images[i] = { name = image, backface_culling = true, } if worldaligntex then stair_images[i].align_style = "world" end else stair_images[i] = table.copy(image) if stair_images[i].backface_culling == nil then stair_images[i].backface_culling = true end if worldaligntex and stair_images[i].align_style == nil then stair_images[i].align_style = "world" end end end local new_groups = table.copy(groups) new_groups.stair = 1 if full_description then description = full_description else description = "Outer " .. description end minetest.register_node(":stairs:stair_outer_" .. subname, { description = description, drawtype = "nodebox", tiles = stair_images, use_texture_alpha = src_def and src_def.use_texture_alpha, paramtype = "light", paramtype2 = "facedir", is_ground_content = false, groups = new_groups, sounds = sounds, node_box = { type = "fixed", fixed = { {-0.5, -0.5, -0.5, 0.5, 0.0, 0.5}, {-0.5, 0.0, 0.0, 0.0, 0.5, 0.5}, }, }, on_place = function(itemstack, placer, pointed_thing) if pointed_thing.type ~= "node" then return itemstack end return rotate_and_place(itemstack, placer, pointed_thing) end, }) end -- Stair/slab registration function. -- Nodes will be called stairs:{stair,slab}_ function stairs.register_stair_and_slab(subname, recipeitem, groups, images, desc_stair, desc_slab, sounds, worldaligntex, desc_stair_inner, desc_stair_outer) stairs.register_stair(subname, recipeitem, groups, images, desc_stair, sounds, worldaligntex) stairs.register_stair_inner(subname, recipeitem, groups, images, desc_stair, sounds, worldaligntex, desc_stair_inner) stairs.register_stair_outer(subname, recipeitem, groups, images, desc_stair, sounds, worldaligntex, desc_stair_outer) stairs.register_slab(subname, recipeitem, groups, images, desc_slab, sounds, worldaligntex) end -- Local function so we can apply translations local function my_register_stair_and_slab(subname, recipeitem, groups, images, desc_stair, desc_slab, sounds, worldaligntex) stairs.register_stair(subname, recipeitem, groups, images, S(desc_stair), sounds, worldaligntex) stairs.register_stair_inner(subname, recipeitem, groups, images, "", sounds, worldaligntex, T("Inner " .. desc_stair)) stairs.register_stair_outer(subname, recipeitem, groups, images, "", sounds, worldaligntex, T("Outer " .. desc_stair)) stairs.register_slab(subname, recipeitem, groups, images, S(desc_slab), sounds, worldaligntex) end -- Register default stairs and slabs my_register_stair_and_slab( "wood", "lzr_core:wood", {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, {"default_wood.png"}, "Wooden Stair", "Wooden Slab", lzr_sounds.node_sound_wood_defaults(), true ) -- Dummy calls to S() to allow translation scripts to detect the strings. -- To update this add this code to my_register_stair_and_slab: -- for _,x in ipairs({"","Inner ","Outer "}) do print(("S(%q)"):format(x..desc_stair)) end -- print(("S(%q)"):format(desc_slab)) --[[ S("Wooden Stair") S("Inner Wooden Stair") S("Outer Wooden Stair") S("Wooden Slab") ]]