-- Lazarr! 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 -- If set to true, will print a list of translatable strings -- for the registered nodes to the console so it can -- be copied into this source file. local GENERATE_TRANSLATABLE_STRING_LIST = false 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. -- CAN be rotated. -- 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 new_groups.rotatable = 3 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 = { -- This stairs nodebox is unusual and differs from most other Minetest games. -- The segments have been made slightly different so that a laser will alway -- be completely blocked off from any direction. type = "fixed", fixed = { {-0.5, -0.5, -0.5, 0.5, 1/16, 0.5}, {-0.5, 1/16, -1/16, 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. -- CAN'T be rotated to simplify the code. -- Rotation code MAY be added, as long the node remains compatible with lasers. -- Registers two nodes: -- * stairs:slab_ for the normal slab and -- * stairs:slab_laser_ for the slab with laser from above function stairs.register_slab(subname, recipeitem, groups, images, description, sounds, worldaligntex) local src_def = minetest.registered_nodes[recipeitem] -- Use first tile only, for slab mesh local slab_images = table.copy(images) if type(slab_images[1]) == "string" then -- Add backface culling because otherwise z-fighting occurs when -- inside the node slab_images[1] = { name = slab_images[1], backface_culling = true } end if not slab_images[2] then slab_images[2] = slab_images[1] end if not slab_images[3] then slab_images[3] = slab_images[2] end slab_images[4] = "blank.png" slab_images[5] = nil slab_images[6] = nil local laser_slab_images = table.copy(slab_images) laser_slab_images[4] = lzr_laser.LASER_TILE local new_groups = table.copy(groups) new_groups.slab = 1 new_groups.laser_block = 1 lzr_laser.register_element(":stairs:slab_" .. subname, { description = description, drawtype = "mesh", mesh_off = "lzr_stairs_slab_laser.obj", mesh_on = "lzr_stairs_slab_laser.obj", tiles_off = slab_images, tiles_on = laser_slab_images, use_texture_alpha = "blend", paramtype = "light", is_ground_content = false, groups = new_groups, sounds = sounds, collision_box = { type = "fixed", -- The slab nodebox is slightly higher than half of a node -- so that an incoming laser from any direction (except the top) -- will be visually blocked. fixed = {-0.5, -0.5, -0.5, 0.5, 1/16, 0.5}, }, selection_box = { type = "fixed", fixed = {-0.5, -0.5, -0.5, 0.5, 1/16, 0.5}, }, light_source_on = lzr_globals.LASER_GLOW, }, { group = "laser_element_slab_"..subname } ) 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 = { -- Unusual stairs nodebox (see stairs comment) type = "fixed", fixed = { {-0.5, -0.5, -0.5, 0.5, 1/16, 0.5}, {-0.5, 1/16, -1/16, 0.5, 0.5, 0.5}, {-0.5, 1/16, -0.5, 1/16, 0.5, -1/16}, }, }, 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 = { -- Unusual stairs nodebox (see stairs comment) type = "fixed", fixed = { {-0.5, -0.5, -0.5, 0.5, 1/16, 0.5}, {-0.5, 1/16, -1/16, 1/16, 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(subname, recipeitem, groups, images, desc_stair, 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)) end local function my_register_stair_and_slab(subname, recipeitem, groups, images, desc_stair, desc_slab, sounds, worldaligntex) my_register_stair(subname, recipeitem, groups, images, desc_stair, sounds, worldaligntex) stairs.register_slab(subname, recipeitem, groups, images, S(desc_slab), sounds, worldaligntex) if GENERATE_TRANSLATABLE_STRING_LIST then for _,x in ipairs({"","Inner ","Outer "}) do print(("S(%q)"):format(x..desc_stair)) end print(("S(%q)"):format(desc_slab)) end end -- Register default stairs and slabs my_register_stair_and_slab( "wood", "lzr_core:wood", {breakable=1}, {"default_wood.png"}, "Wooden Stair", "Wooden Slab", lzr_sounds.node_sound_wood_defaults(), true ) my_register_stair_and_slab( "wood_mossy", "lzr_core:wood_mossy", {breakable=1}, {"lzr_core_wood_mossy.png"}, "Mossy Wooden Stair", "Mossy Wooden Slab", lzr_sounds.node_sound_wood_defaults(), true ) my_register_stair_and_slab( "palm_wood", "lzr_core:palm_wood", {breakable=1}, {"lzr_core_palm_wood.png"}, "Palm Wood Stair", "Palm Wood Slab", lzr_sounds.node_sound_wood_defaults(), true ) my_register_stair_and_slab( "coconut_wood", "lzr_core:coconut_wood", {breakable=1}, {"lzr_core_coconut_wood.png"}, "Coconut Wood Stair", "Coconut Wood Slab", lzr_sounds.node_sound_wood_defaults(), true ) my_register_stair_and_slab( "stone", "lzr_core:stone", {breakable=1}, {"default_stone.png"}, "Stone Stair", "Stone Slab", lzr_sounds.node_sound_stone_defaults(), true ) my_register_stair_and_slab( "ocean_stone", "lzr_decor:ocean_stone", {breakable=1}, {"xocean_stone.png"}, "Ocean Stone Stair", "Ocean Stone Slab", lzr_sounds.node_sound_stone_defaults(), true ) my_register_stair_and_slab( "ocean_cobble", "lzr_decor:ocean_cobble", {breakable=1}, {"xocean_cobble.png"}, "Ocean Cobblestone Stair", "Ocean Cobblestone Slab", lzr_sounds.node_sound_stone_defaults(), true ) my_register_stair_and_slab( "thatch", "lzr_decor:thatch", {breakable=1}, {"dryplants_thatch.png"}, "Thatch Stair", "Thatch Slab", lzr_sounds.node_sound_leaves_defaults(), true ) my_register_stair_and_slab( "thatch_wet", "lzr_decor:thatch_wet", {breakable=1}, {"dryplants_thatch_wet.png"}, "Wet Thatch Stair", "Wet Thatch Slab", lzr_sounds.node_sound_leaves_defaults(), true ) -- Dummy calls to S() to allow translation scripts to detect the strings. -- MUST be updated before release when new nodes have arrived. -- To update this, set GENERATE_TRANSLATABLE_STRING_LIST to true -- and paste the console output here: --[[ S("Wooden Stair") S("Inner Wooden Stair") S("Outer Wooden Stair") S("Wooden Slab") S("Mossy Wooden Stair") S("Inner Mossy Wooden Stair") S("Outer Mossy Wooden Stair") S("Mossy Wooden Slab") S("Palm Wood Stair") S("Inner Palm Wood Stair") S("Outer Palm Wood Stair") S("Palm Wood Slab") S("Coconut Wood Stair") S("Inner Coconut Wood Stair") S("Outer Coconut Wood Stair") S("Coconut Wood Slab") S("Stone Stair") S("Inner Stone Stair") S("Outer Stone Stair") S("Stone Slab") S("Ocean Stone Stair") S("Inner Ocean Stone Stair") S("Outer Ocean Stone Stair") S("Ocean Stone Slab") S("Ocean Cobblestone Stair") S("Inner Ocean Cobblestone Stair") S("Outer Ocean Cobblestone Stair") S("Ocean Cobblestone Slab") S("Thatch Stair") S("Inner Thatch Stair") S("Outer Thatch Stair") S("Thatch Slab") S("Wet Thatch Stair") S("Inner Wet Thatch Stair") S("Outer Wet Thatch Stair") S("Wet Thatch Slab") ]] -- Aliases for the pre-laser color era minetest.register_alias("stairs:slab_wood_laser", "stairs:slab_wood_on_1") minetest.register_alias("stairs:slab_wood_mossy_laser", "stairs:slab_wood_mossy_on_1") minetest.register_alias("stairs:slab_palm_wood_laser", "stairs:slab_palm_wood_on_1") minetest.register_alias("stairs:slab_coconut_wood_laser", "stairs:slab_coconut_wood_on_1") minetest.register_alias("stairs:slab_stone_laser", "stairs:slab_stone_on_1") minetest.register_alias("stairs:slab_ocean_stone_laser", "stairs:slab_ocean_stone_on_1") minetest.register_alias("stairs:slab_ocean_cobble_laser", "stairs:slab_ocean_cobble_on_1") minetest.register_alias("stairs:slab_thatch_laser", "stairs:slab_thatch_on_1") minetest.register_alias("stairs:slab_thatch_wet_laser", "stairs:slab_thatch_wet_on_1")