--[[ ITB (insidethebox) minetest game - Copyright (C) 2017-2018 sofar & nore This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ]]-- local S = minetest.get_translator("nodes") --[[ nodes.lua - basic node blocks for Inside The Box ]]-- -- -- visual marker for where breakable nodes can be placed -- local function nm(s) local ss = string.gsub(s, "_", " ") return ss:gsub("^%l", string.upper) end -- tilecache API nodes = {} local tilecache = {} function nodes.get_tiles(name) if tilecache[name] then return tilecache[name] else local def = minetest.registered_nodes[name] local tex if def.inventory_image and def.inventory_image ~= "" then tex = def.inventory_image elseif def.drawtype ~= "normal" then tex = def.tiles[1] and def.tiles[1].name or def.tiles[1] else tex = minetest.inventorycube( def.tiles[1] and def.tiles[1].name or def.tiles[1], def.tiles[3] and def.tiles[3].name or def.tiles[3] or def.tiles[2] and def.tiles[2].name or def.tiles[2] or def.tiles[1] and def.tiles[1].name or def.tiles[1], def.tiles[3] and def.tiles[3].name or def.tiles[3] or def.tiles[2] and def.tiles[2].name or def.tiles[2] or def.tiles[1] and def.tiles[1].name or def.tiles[1] ) end tilecache[name] = tex return tex end end -- -- handle placement for breakable nodes -- local on_place_breakable = function(itemstack, placer, pointed_thing) -- not a node? if not pointed_thing or pointed_thing.type ~= "node" then return itemstack end -- pass through? local under = minetest.get_node(pointed_thing.under) local udef = minetest.registered_nodes[under.name] if udef.on_rightclick then return udef.on_rightclick(pointed_thing.under, under, placer, itemstack, pointed_thing) end -- placeable here? local pos = pointed_thing.above local node = minetest.get_node(pos) local place = itemstack:get_name() local name = placer:get_player_name() -- editing or playing? if boxes.players_editing_boxes[name] then -- holding SHIFT? if placer:get_player_control().sneak then -- param2 local def = minetest.registered_nodes[place] local param2 = 0 if def.place_param2 ~= nil then param2 = def.place_param2 elseif def.paramtype2 == "wallmounted" then param2 = minetest.dir_to_wallmounted(vector.subtract( pointed_thing.under, pointed_thing.above)) elseif def.paramtype2 == "facedir" then param2 = minetest.dir_to_facedir(vector.subtract( pointed_thing.under, pointed_thing.above)) end minetest.set_node(pos, {name = place, param2 = param2}) return itemstack end if node.name ~= "air" and node.name ~= "nodes:placeholder" then minetest.chat_send_player(name, S("Can only place this node at an empty node. Clear the space first!")) return itemstack end -- place placeholder information if node.name ~= "nodes:placeholder" then minetest.set_node(pos, {name = "nodes:placeholder"}) end local meta = minetest.get_meta(pos) local placeable = meta:get_string("placeable") if placeable == "" then meta:set_string("placeable", minetest.write_json({[place] = true})) else local t = minetest.parse_json(placeable) t[place] = true meta:set_string("placeable", minetest.write_json(t)) end elseif boxes.players_in_boxes[name] then -- check meta if we can place here local meta = minetest.get_meta(pos) if meta:get_string("placed") ~= "" then return itemstack end local placeable = meta:get_string("placeable") if placeable == "" then return itemstack end local t = minetest.parse_json(placeable) if not t[place] then return itemstack end -- place and remove one from itemstack itemstack:take_item() -- param2 local def = minetest.registered_nodes[place] local param2 = 0 if def.place_param2 ~= nil then param2 = def.place_param2 elseif def.paramtype2 == "wallmounted" then param2 = minetest.dir_to_wallmounted(vector.subtract( pointed_thing.under, pointed_thing.above)) elseif def.paramtype2 == "facedir" then param2 = minetest.dir_to_facedir(vector.subtract( pointed_thing.under, pointed_thing.above)) end minetest.set_node(pos, {name = place, param2 = param2}) minetest.check_for_falling(pos) -- preserve metadata meta = minetest.get_meta(pos) meta:set_string("placeable", placeable) -- but set placed to true to avoid fast-rightclick bug meta:set_string("placed", "true") return itemstack else minetest.log("info", name .. " attempted to place a " .. place .. " outside a box") return itemstack end end function nodes.after_dig_node_breakable(pos, oldnode, oldmetadata, digger) -- preserve metadata minetest.set_node(pos, {name = "nodes:placeholder"}) if not oldmetadata.fields or not oldmetadata.fields.placeable then return end local meta = minetest.get_meta(pos) meta:set_string("placeable", oldmetadata.fields.placeable) end local function on_destruct_breakable(pos) -- preserve metadata local placeable = minetest.get_meta(pos):get_string("placeable") minetest.after(0, function(p) local node = minetest.get_node(pos) if node.name == "air" then -- put the placeholder back if the node was removed minetest.set_node(pos, {name = "nodes:placeholder"}) end local meta = minetest.get_meta(pos) meta:set_string("placeable", p) end, placeable) end function nodes.placeholder_particles(pos) local meta = minetest.get_meta(pos) local placeable = meta:get_string("placeable") if placeable == "" then return false end local nodelist = minetest.parse_json(placeable) for _, obj in pairs(minetest.get_objects_inside_radius(pos, 3)) do if obj:is_player() then local pname = obj:get_player_name() local itemstack = obj:get_wielded_item() local name = itemstack:get_name() if itemstack and nodelist[name] then minetest.add_particle({ pos = pos, expirationtime = 0.55, size = 5, texture = nodes.get_tiles(name), glow = 14, playername = pname, }) end end end return true end minetest.register_node("nodes:placeholder", { description = S("Placeable node location placeholder"), inventory_image = "air.png", wield_image = "air.png", drawtype = "airlike", paramtype = "light", sunlight_propagates = true, walkable = false, pointable = false, diggable = false, buildable_to = true, floodable = true, air_equivalent = true, drop = "", groups = {not_in_creative_inventory=1}, on_timer = nodes.placeholder_particles, on_construct = function(pos) minetest.get_node_timer(pos):start(0.5) end, on_destruct = on_destruct_breakable, after_box_construct = function(pos) minetest.get_node_timer(pos):start(0.5) end, }) -- table format: -- [1] name, also used for texture -- [2] true for stair/slab -- [3] tool if diggable version needs to be added -- [4] sounds -- [5] falling node local nodelist = { {"bricks_clay", true, "pickaxe", sounds.stone, "clay bricks"}, {"bricks_limestone", true, "pickaxe", sounds.stone, "chiseled limestone"}, {"bricks_marble", true, "pickaxe", sounds.stone, "chiseled marble"}, {"bricks_sandstone", true, "pickaxe", sounds.stone, "sandstone bricks"}, {"bricks_stone", true, "pickaxe", sounds.stone, "stone bricks"}, {"bricks_stone_moss", true, "pickaxe", sounds.stone, "mossy stone bricks"}, {"cobble", true, "pickaxe", sounds.stone, "cobblestone"}, {"cobble_moss", true, "pickaxe", sounds.stone, "mossy cobblestone"}, {"limestone", true, "pickaxe", sounds.stone, "limestone"}, {"marble", true, "pickaxe", sounds.stone, "marble"}, {"sandstone", true, "pickaxe", sounds.stone, "sandstone"}, {"stone", true, "pickaxe", sounds.stone, "stone"}, {"stone_moss", true, "pickaxe", sounds.stone, "mossy stone"}, {"obsidian", true, false, sounds.stone, "obsidian"}, {"bedrock", true, false, sounds.stone, "bedrock"}, {"redrock", true, false, sounds.stone, "red rock"}, {"bronze", false, "pickaxe", sounds.metal, "bronze"}, {"gold", false, "pickaxe", sounds.metal, "gold"}, {"emerald", false, "pickaxe", sounds.stone, "emerald"}, {"iron", false, "pickaxe", sounds.metal, "iron"}, {"clay", false, "shovel", sounds.dirt, "clay"}, {"dirt", false, "shovel", sounds.dirt, "dirt"}, {"gravel", false, "shovel", sounds.gravel, "gravel", 1}, {"sand", false, "shovel", sounds.sand, "sand", 1}, {"wood_dark", true, "axe", sounds.wood, "dark wood"}, {"wood_light", true, "axe", sounds.wood, "light wood"}, {"wood_medium", true, "axe", sounds.wood, "medium wood"}, {"grass", false, false, sounds.grass, "grass block"}, {"snow", false, "shovel", sounds.snow, "snow"}, {"ice", false, "pickaxe", sounds.stone, "ice"}, {"ore_black", false, "pickaxe", sounds.stone, "black ore"}, {"ore_blue", false, "pickaxe", sounds.stone, "blue ore"}, {"ore_brown", false, "pickaxe", sounds.stone, "brown ore"}, {"ore_cyan", false, "pickaxe", sounds.stone, "cyan ore"}, {"ore_gold", false, "pickaxe", sounds.stone, "gold ore"}, {"ore_green", false, "pickaxe", sounds.stone, "green ore"}, {"ore_red", false, "pickaxe", sounds.stone, "red ore"}, } local function make_stair_slab(name, desc, groups, b1, b2, snd, tex) if not tex then tex = name end minetest.register_node("nodes:" .. name .. b1 .. "_stairs", { description = nm(desc .. " stairs" .. b2), tiles = {tex .. ".png"}, drawtype = "mesh", mesh = "stairs_stair.obj", paramtype = "light", paramtype2 = "facedir", groups = groups, selection_box = { type = "fixed", fixed = { {-1/2, -1/2, -1/2, 1/2, 0, 1/2}, {-1/2, 0, 0, 1/2, 1/2, 1/2}, }, }, collision_box = { type = "fixed", fixed = { {-1/2, -1/2, -1/2, 1/2, 0, 1/2}, {-1/2, 0, 0, 1/2, 1/2, 1/2}, }, }, sounds = snd, }) minetest.register_node("nodes:" .. name .. b1 .. "_slab", { description = nm(desc .. " slab" .. b2), tiles = {tex .. ".png"}, drawtype = "nodebox", paramtype = "light", paramtype2 = "facedir", groups = groups, node_box = { type = "fixed", fixed = {-1/2, -1/2, -1/2, 1/2, 0, 1/2}, }, sounds = snd, }) end for n, v in pairs(nodelist) do local tex = "blocks_tiles.png^[sheet:8x8:" .. (n - 1) % 8 .. "," .. math.floor((n - 1) / 8) local groups = {node = 1} if v[6] then groups.falling_node = 1 end if v[4] == sounds.stone then groups.stone = 1 elseif v[4] == sounds.wood then groups.wood = 1 end if v[3] then -- register diggable node version local gg = table.copy(groups) gg[v[3]] = 3 minetest.register_node("nodes:" .. v[1] .. "_breakable", { description = nm(v[5]), tiles = {tex}, groups = gg, sounds = v[4], }) if v[2] then make_stair_slab(v[1], v[5], gg, "_breakable", "", v[4], tex) end frame.register("nodes:" .. v[1] .. "_breakable") end groups.unbreakable = 1 minetest.register_node("nodes:" .. v[1], { description = nm(v[5]), tiles = {tex}, groups = groups, sounds = v[4], }) if v[2] then make_stair_slab(v[1], v[5], groups, "", "", v[4], tex) if groups.stone then walls.register("nodes:" .. v[1] .. "_wall", nm(v[5] .. " wall"), nm("Middle " .. v[5] .. " wall"), tex, v[4], groups, {"group:stone"}) else walls.register("nodes:" .. v[1] .. "_wall", nm(v[5] .. " wall"), nm("Middle " ..v[5] .. " wall"), tex, v[4], groups, {"group:wood"}) end end end minetest.register_node("nodes:marble_pillar", { description = S("Marble pillar"), paramtype2 = "facedir", tiles = {"marble_pillar_top.png", "marble_pillar_bottom.png", "marble_pillar_side.png"}, groups = {node = 1, unbreakable = 1}, sounds = sounds.stone, }) minetest.register_node("nodes:marbleb", { description = S("Marble border"), tiles = {"blocks_tiles.png^[sheet:8x8:1,1"}, unpushable = true, groups = {not_in_creative_inventory = 1}, sounds = sounds.stone, }) minetest.register_node("nodes:bronzeb", { description = S("Bronze border"), tiles = {"blocks_tiles.png^[sheet:8x8:0,2"}, unpushable = true, groups = {not_in_creative_inventory = 1}, sounds = sounds.metal, }) -- -- wool -- for n, v in pairs({"yellow", "white", "violet", "red", "pink", "orange", "magenta", "grey", "green", "dark_grey", "dark_green", "cyan", "brown", "blue", "black"}) do local tex = "wool_tiles.png^[sheet:4x4:" .. (n - 1) % 4 .. "," .. math.floor((n - 1) / 4) minetest.register_node("nodes:wool_" .. v, { description = nm(v .. " wool"), tiles = {tex}, groups = {node = 1, unbreakable = 1}, sounds = sounds.cloth, }) minetest.register_node("nodes:carpet_" .. v, { description = nm(v .. " carpet"), tiles = {tex}, groups = {node = 1, unbreakable = 1}, sounds = sounds.cloth, sunlight_propagates = true, paramtype = "light", paramtype2 = "facedir", drawtype = "nodebox", node_box = { type = "fixed", fixed = { {-7/16, -1/2, -7/16, 7/16, -7/16, 7/16}, }, }, }) make_stair_slab("wool_" .. v, nm(v .. " wool"), {node = 1, unbreakable = 1}, "", "", sounds.cloth, tex) minetest.register_node("nodes:wool_" .. v .. "_breakable", { description = nm(v .. " wool"), tiles = {tex}, groups = {axe = 1, node = 1}, sounds = sounds.cloth, }) make_stair_slab("wool_" .. v, nm(v .. " wool"), {axe = 1, node = 1}, "_breakable", "", sounds.cloth, tex) frame.register("nodes:wool_" .. v .. "_breakable") end -- hardened clay for n, v in pairs({"black", "violet", "brown", "cyan", "gray", "green", "blue", "lime", "pink", "orange", "magenta", "purple", "red", "silver", "light_brown", "cream", "yellow"}) do local tex = "hardened_clay_tiles.png^[sheet:4x5:" .. (n - 1) % 4 .. "," .. math.floor((n - 1) / 4) minetest.register_node("nodes:hardened_clay_" .. v, { description = nm(v .. " hardened clay"), tiles = {tex}, groups = {node = 1, unbreakable = 1}, sounds = sounds.stone, }) make_stair_slab("hardened_clay_" .. v, nm(v .. " hardened clay"), {node = 1, unbreakable = 1}, "", "", sounds.stone, tex) minetest.register_node("nodes:hardened_clay_" .. v .. "_breakable", { description = nm(v .. " hardened clay"), tiles = {tex}, groups = {pickaxe = 1, node = 1}, sounds = sounds.stone, }) make_stair_slab("hardened_clay_" .. v, nm(v .. " hardened clay"), {pickaxe = 1, node = 1}, "_breakable", "", sounds.stone, tex) frame.register("nodes:hardened_clay_" .. v .. "_breakable") end -- trunks and leaves for _, v in pairs({ {"light", 1}, {"medium", 1}, {"dark", 1}, {"fall"}, {"jungle"}, }) do if v[2] then minetest.register_node("nodes:trunk_" .. v[1] .. "_breakable", { description = nm(v[1] .. " trunk"), tiles = {"trunk_" .. v[1] .. "_top.png", "trunk_" .. v[1] .. "_top.png", "trunk_" .. v[1] .. ".png"}, groups = {axe = 1, node = 1, wood = 1, tree = 1}, paramtype2 = "facedir", sounds = sounds.wood, }) minetest.register_node("nodes:trunk_" .. v[1] .. "", { description = nm(v[1] .. " trunk"), tiles = {"trunk_" .. v[1] .. "_top.png", "trunk_" .. v[1] .. "_top.png", "trunk_" .. v[1] .. ".png"}, groups = {node = 1, unbreakable = 1, wood = 1, tree = 1}, paramtype2 = "facedir", sounds = sounds.wood, }) frame.register("nodes:trunk_" .. v[1] .. "_breakable") end minetest.register_node("nodes:leaves_" .. v[1] .. "_breakable", { description = nm(v[1] .. " leaves"), drawtype = "allfaces_optional", paramtype = "light", tiles = {"leaves_" .. v[1] .. ".png"}, groups = {node = 1, axe = 1, leaves = 1}, sounds = sounds.leaves, }) minetest.register_node("nodes:leaves_" .. v[1], { description = nm(v[1] .. " leaves"), drawtype = "allfaces_optional", paramtype = "light", tiles = {"leaves_" .. v[1] .. ".png"}, groups = {node = 1, unbreakable = 1, leaves = 1}, sounds = sounds.leaves, }) end -- barrier minetest.register_node("nodes:barrier", { description = S("Barrier"), pointable = true, -- make it easy to understand that it's a barrier drawtype = "airlike", inventory_image = "barrier.png", wield_image = "barrier.png", sunlight_propagates = true, paramtype = "light", unpushable = true, groups = {not_in_creative_inventory = 1, fall_damage_add_percent = 1000}, collision_box = { type = "fixed", -- oversized to prevent crawling through fixed = {-1,-0.5,-1,1,1,1}, }, }) local function lamp_on_untrigger(pos) local meta = minetest.get_meta(pos) local node = minetest.get_node(pos) meta:set_string("on_name", node.name) node.name = "nodes:lamp_bar_0" minetest.swap_node(pos, node) end -- glass minetest.register_node("nodes:glass", { description = S("Glass"), drawtype = "glasslike_framed_optional", sunlight_propagates = true, paramtype = "light", tiles = {"glass.png"}, groups = {node = 1, unbreakable = 1}, sounds = sounds.glass, }) minetest.register_node("nodes:glass_breakable", { description = S("Glass"), drawtype = "glasslike_framed_optional", sunlight_propagates = true, paramtype = "light", tiles = {"glass.png"}, groups = {node = 1, pickaxe = 1}, sounds = sounds.glass, }) frame.register("nodes:glass_breakable") -- light fixtures for _, v in pairs({14, 11, 8, 0}) do local on_trigger = function(pos) end local on_untrigger = function(pos) end if v == 0 then on_trigger = function(pos) local meta = minetest.get_meta(pos) local node = minetest.get_node(pos) local new_name = meta:get_string("on_name") if new_name ~= "" then node.name = new_name minetest.swap_node(pos, node) if string.find(new_name, "broken") then minetest.get_node_timer(pos):start(math.random(50)/10) end end minetest.sound_play("lamp_on", {pos = pos, max_hear_distance = 16, gain = 0.2}) end else on_untrigger = lamp_on_untrigger end minetest.register_node("nodes:lamp_bar_" .. v, { description = "Wall lamp (" .. v .. ")", light_source = v, sunlight_propagates = true, tiles = {"lamp_bar.png"}, paramtype = "light", paramtype2 = "facedir", walkable = false, drawtype = "nodebox", node_box = { type = "fixed", fixed = {-1, 1/4, 1/4, 1, 1/2, 1/2}, }, groups = {node = 1, unbreakable = 1}, sounds = sounds.glass, on_rotate = screwdriver.rotate_simple, on_trigger = on_trigger, on_untrigger = on_untrigger, after_dig_node = mech.after_dig, }) end minetest.register_node("nodes:lamp_bar_broken", { description = S("Broken wall lamp (flickering)"), light_source = 8, sunlight_propagates = true, tiles = {"lamp_bar.png"}, paramtype = "light", paramtype2 = "facedir", walkable = false, drawtype = "nodebox", node_box = { type = "fixed", fixed = {-1, 1/4, 1/4, 1, 1/2, 1/2}, }, groups = {node = 1, unbreakable = 1}, sounds = sounds.glass, on_rotate = screwdriver.rotate_simple, on_trigger = function(pos) end, on_untrigger = lamp_on_untrigger, on_timer = function(pos) local node = minetest.get_node(pos) minetest.set_node(pos, {name = "nodes:lamp_bar_broken_off", param2 = node.param2}) end, on_construct = function(pos) minetest.get_node_timer(pos):start(math.random(50)/10) end, after_dig_node = mech.after_dig, }) minetest.register_node("nodes:lamp_bar_broken_off", { description = S("Broken wall lamp (flickering, off)"), sunlight_propagates = true, tiles = {"lamp_bar.png"}, paramtype = "light", paramtype2 = "facedir", walkable = false, drawtype = "nodebox", node_box = { type = "fixed", fixed = {-1, 1/4, 1/4, 1, 1/2, 1/2}, }, groups = {node = 1, unbreakable = 1}, sounds = sounds.glass, on_rotate = screwdriver.rotate_simple, on_trigger = function(pos) end, on_untrigger = lamp_on_untrigger, on_timer = function(pos) local node = minetest.get_node(pos) minetest.set_node(pos, {name = "nodes:lamp_bar_broken", param2 = node.param2}) end, on_construct = function(pos) minetest.get_node_timer(pos):start(math.random(50)/10) end, after_dig_node = mech.after_dig, }) -- glowblock minetest.register_node("nodes:glowblock", { description = S("Glowblock"), tiles = {"glowblock.png"}, light_source = 13, groups = {node = 1, unbreakable = 1}, sounds = sounds.glass, }) -- lamp blocks for _, v in pairs({14, 11, 8, 0}) do local on_trigger = function(pos) end local on_untrigger = function(pos) end local tiles = {"lamp_block_on.png"} if v == 0 then on_trigger = function(pos) local meta = minetest.get_meta(pos) local node = minetest.get_node(pos) local new_name = meta:get_string("on_name") if new_name ~= "" then node.name = new_name minetest.swap_node(pos, node) end minetest.sound_play("lamp_on", {pos = pos, max_hear_distance = 16, gain = 0.2}) end tiles = {"lamp_block_off.png"} else on_untrigger = function(pos) local meta = minetest.get_meta(pos) local node = minetest.get_node(pos) meta:set_string("on_name", node.name) node.name = "nodes:lamp_block_0" minetest.swap_node(pos, node) end end minetest.register_node("nodes:lamp_block_" .. v, { description = S("Lamp block (@1)", v), tiles = tiles, light_source = v, groups = {node = 1, unbreakable = 1}, sounds = sounds.glass, on_trigger = on_trigger, on_untrigger = on_untrigger, after_dig_node = mech.after_dig, }) end local wood_fences = { { "wood_dark", S("Dark wood fence") }, { "wood_light", S("Light wood fence") }, { "wood_medium", S("Medium wood fence") }, } for n, wood in ipairs(wood_fences) do fences.register_fence("nodes:fence_" .. wood[1], { description = wood[2], texture = "blocks_tiles.png^[sheet:8x8:" .. n - 1 ..",3", inventory_image = "default_fence_overlay.png^" .. "blocks_tiles.png^[sheet:8x8:" .. n - 1 ..",3" .. "^default_fence_overlay.png^[makealpha:255,126,126", wield_image = "default_fence_overlay.png^" .. "blocks_tiles.png^[sheet:8x8:" .. n - 1 ..",3" .. "^default_fence_overlay.png^[makealpha:255,126,126", groups = {node = 1, unbreakable = 1, wood = 1}, sounds = sounds.wood, }) end minetest.register_node("nodes:bookshelf", { description = S("Bookshelf"), tiles = {"blocks_tiles.png^[sheet:8x8:2,3", "blocks_tiles.png^[sheet:8x8:2,3", "bookshelf.png", "bookshelf.png", "blocks_tiles.png^[sheet:8x8:2,3"}, sounds = sounds.wood, paramtype2 = "facedir", on_rotate = screwdriver.rotate_simple, groups = {node = 1, unbreakable = 1, wood = 1}, }) minetest.register_node("nodes:workbench", { description = S("Workbench"), tiles = {"workbench_top.png", "workbench_top.png", "workbench_side.png"}, sounds = sounds.wood, paramtype2 = "facedir", groups = {node = 1, unbreakable = 1, wood = 1}, }) minetest.register_node("nodes:furnace", { description = S("Furnace (off)"), tiles = {"furnace_top.png", "furnace_top.png", "furnace_side.png", "furnace_side.png", "furnace_side.png", "furnace_front_off.png"}, sounds = sounds.stone, paramtype2 = "facedir", groups = {node = 1, unbreakable = 1, stone = 1, mech = 1}, on_trigger = function(pos) local node = minetest.get_node(pos) node.name = "nodes:furnace_on" minetest.swap_node(pos, node) end, }) minetest.register_node("nodes:furnace_on", { description = S("Furnace (on)"), tiles = {"furnace_top.png", "furnace_top.png", "furnace_side.png", "furnace_side.png", "furnace_side.png", "furnace_front_on.png"}, sounds = sounds.stone, paramtype2 = "facedir", light_source = 5, groups = {node = 1, unbreakable = 1, stone = 1, mech = 1}, on_trigger = function() end, on_untrigger = function(pos) local node = minetest.get_node(pos) node.name = "nodes:furnace" minetest.swap_node(pos, node) end }) -- melon, pumpkin, hay minetest.register_node("nodes:melon", { description = S("Melon"), tiles = {"melon_top.png", "melon_top.png", "melon_side.png"}, sounds = sounds.wood, paramtype2 = "facedir", groups = {node = 1, unbreakable = 1}, }) minetest.register_node("nodes:melon_breakable", { description = S("Melon"), tiles = {"melon_top.png", "melon_top.png", "melon_side.png"}, sounds = sounds.wood, paramtype2 = "facedir", groups = {node = 1, hand = 1}, }) frame.register("nodes:melon_breakable") minetest.register_node("nodes:pumpkin", { description = S("Pumpkin"), tiles = {"pumpkin_top.png", "pumpkin_top.png", "pumpkin_side.png"}, sounds = sounds.wood, paramtype2 = "facedir", groups = {node = 1, unbreakable = 1}, }) minetest.register_node("nodes:pumpkin_breakable", { description = S("Pumpkin"), tiles = {"pumpkin_top.png", "pumpkin_top.png", "pumpkin_side.png"}, sounds = sounds.wood, paramtype2 = "facedir", groups = {node = 1, hand = 1}, }) frame.register("nodes:pumpkin_breakable") minetest.register_node("nodes:hay", { description = S("Hay"), tiles = {"hay_top.png", "hay_top.png", "hay_side.png"}, sounds = sounds.grass, paramtype2 = "facedir", groups = {node = 1, unbreakable = 1}, }) minetest.register_node("nodes:hay_breakable", { description = S("Hay"), tiles = {"hay_top.png", "hay_top.png", "hay_side.png"}, sounds = sounds.grass, paramtype2 = "facedir", groups = {node = 1, hand = 1}, }) frame.register("nodes:hay_breakable") -- ladders, rope & vines for _, n in pairs({ {"ladder", "signlike", sounds.wood, S("Ladder")}, {"rope", "plantlike", nil, S("Rope")}, {"vine", "signlike", sounds.leaves, S("Vine")}, }) do local tex if n[1] == "vine" then tex = "plant_tiles.png^[sheet:8x8:2,5" else tex = n[1] .. ".png" end minetest.register_node("nodes:" .. n[1], { description = n[4], drawtype = n[2], tiles = {tex}, inventory_image = tex, wield_image = tex, paramtype = "light", paramtype2 = n[2] == "signlike" and "wallmounted" or nil, sunlight_propagates = true, walkable = false, climbable = true, selection_box = n[2] == "signlike" and {type = "wallmounted"} or { type = "fixed", fixed = {-3/16, -1/2, -3/16, 3/16, 1/2, 3/16} }, groups = {node = 1, unbreakable = 1}, sounds = n[3], }) minetest.register_node("nodes:" .. n[1] .. "_breakable", { description = n[4], drawtype = n[2], tiles = {tex}, inventory_image = tex, wield_image = tex, paramtype = "light", paramtype2 = n[2] == "signlike" and "wallmounted" or nil, sunlight_propagates = true, walkable = false, climbable = true, selection_box = n[2] == "signlike" and {type = "wallmounted"} or { type = "fixed", fixed = {-3/16, -1/2, -3/16, 3/16, 1/2, 3/16} }, groups = {node = 1, axe = 1}, sounds = n[3], }) frame.register("nodes:" .. n[1] .. "_breakable") end minetest.register_node("nodes:waterlily", { description = S("Waterlily"), drawtype = "nodebox", sunlight_propagates = true, tiles = {"plant_tiles.png^[sheet:8x8:3,5"}, inventory_image = "plant_tiles.png^[sheet:8x8:3,5", wield_image = "plant_tiles.png^[sheet:8x8:3,5", walkable = true, node_box = { type = "fixed", fixed = {-1/2, -1/2, -1/2, 1/2, -7/16, 1/2} }, liquids_pointable = true, paramtype = "light", paramtype2 = "facedir", groups = { node = 1 }, on_place = function(itemstack, placer, pointed_thing) local pos = pointed_thing.under if not pos then return itemstack end -- fixme pass through on_rightclick if present (item frame) local node = minetest.get_node(pos) if not node then return itemstack end local name = itemstack:get_name() local rng = PseudoRandom(pos.x % 16 + ((pos.z % 16) * 16) + ((pos.y % 16) * 256)) minetest.set_node(pointed_thing.above, {name = name, param2 = rng:next(0, 3)}) end, }) --frame.register("nodes:waterlily") -- Trampolines for _, v in pairs({20, 40, 60, 80}) do minetest.register_node("nodes:trampoline_" .. v , { description = S("Trampoline (@1%)", v), tiles = {"trampoline_top.png", "trampoline_top.png", "trampoline_side.png"}, paramtype = "light", paramtype2 = "facedir", groups = {node = 1, bouncy = v, fall_damage_add_percent = -v}, sounds = sounds.wood, }) end -- Sponge (cushion, nojump broken in 0.4.16) minetest.register_node("nodes:sponge", { description = S("Sponge"), tiles = {"sponge.png"}, paramtype = "light", groups = {node = 1, fall_damage_add_percent = -25, disable_jump = 1}, sounds = sounds.dirt, -- fall ~25 nodes, normal node = 1 heart left, sponge = 5 hearts left }) -- TNT local function tnt_explode(pos) minetest.remove_node(pos) minetest.sound_play("tnt_explosion", {pos = pos, max_hear_distance = 64, gain = 1.0}) minetest.add_particlespawner({ amount = 128, time = 1.0, minpos = vector.add(pos, -2.5), maxpos = vector.add(pos, 2.5), minvel = {x = 0, y = 0, z = 0}, maxvel = {x = 0, y = 0, z = 0}, minacc = {x = 0, y = 0, z = 0}, maxacc = {x = 0, y = 0, z = 0}, minexptime = 0.4, maxexptime = 0.4, minsize = 8, maxsize = 16, texture = "explosion_effect_animated.png", glow = 14, animation = { type = "sheet_2d", frames_w = 8, frames_h = 1, frame_length = 0.05, }, }) end minetest.register_node("nodes:tnt", { description = S("TNT"), tiles = {"itb_tnt_top.png", "itb_tnt_bottom.png", "itb_tnt_side.png"}, paramtype = "light", groups = {node = 1}, on_trigger = tnt_explode, sounds = sounds.wood, }) minetest.register_node("nodes:tnt_diggable", { description = S("TNT"), tiles = {"itb_tnt_top.png", "itb_tnt_bottom.png", "itb_tnt_side.png"}, paramtype = "light", groups = {node = 1, hand = 1}, on_trigger = tnt_explode, sounds = sounds.wood, }) frame.register("nodes:tnt_diggable") -- special nodes -- liquids minetest.register_node("nodes:water_source", { description = S("Water source"), drawtype = "liquid", tiles = { { name = "water_source_animated.png", animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 2.0, }, }, }, special_tiles = { -- New-style water source material (mostly unused) { name = "water_source_animated.png", animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 2.0, }, backface_culling = false, }, }, --alpha = 160, use_texture_alpha = "blend", paramtype = "light", walkable = false, pointable = false, diggable = false, buildable_to = true, is_ground_content = false, drop = "", drowning = 2, liquidtype = "source", liquid_alternative_flowing = "nodes:water_flowing", liquid_alternative_source = "nodes:water_source", liquid_viscosity = 1, post_effect_color = {a = 203, r = 30, g = 60, b = 90}, groups = {water = 3, liquid = 3, puts_out_fire = 1, cools_lava = 1}, sounds = sounds.water, }) minetest.register_node("nodes:water_flowing", { description = S("Flowing water"), drawtype = "flowingliquid", tiles = {"water.png"}, special_tiles = { { name = "water_flowing_animated.png", backface_culling = false, animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 3.2, }, }, { name = "water_flowing_animated.png", backface_culling = true, animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 3.2, }, }, }, --alpha = 160, use_texture_alpha = "blend", paramtype = "light", paramtype2 = "flowingliquid", walkable = false, pointable = false, diggable = false, buildable_to = true, is_ground_content = false, drop = "", drowning = 2, liquidtype = "flowing", liquid_alternative_flowing = "nodes:water_flowing", liquid_alternative_source = "nodes:water_source", liquid_viscosity = 1, post_effect_color = {a = 203, r = 30, g = 60, b = 90}, groups = {water = 3, liquid = 3, puts_out_fire = 1, not_in_creative_inventory = 1, cools_lava = 1}, sounds = sounds.water, }) minetest.register_node("nodes:river_water_source", { description = S("River water source"), drawtype = "liquid", tiles = { { name = "river_water_source_animated.png", animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 3.2, }, }, }, special_tiles = { { name = "river_water_source_animated.png", animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 3.2, }, backface_culling = false, }, }, --alpha = 160, use_texture_alpha = "blend", paramtype = "light", walkable = false, pointable = false, diggable = false, buildable_to = true, is_ground_content = false, drop = "", drowning = 2, liquidtype = "source", liquid_alternative_flowing = "nodes:river_water_flowing", liquid_alternative_source = "nodes:river_water_source", liquid_viscosity = 1, liquid_renewable = false, liquid_range = 2, post_effect_color = {a = 203, r = 30, g = 76, b = 90}, groups = {water = 3, liquid = 3, puts_out_fire = 1, cools_lava = 1}, sounds = sounds.water, }) minetest.register_node("nodes:river_water_flowing", { description = S("Flowing river water"), drawtype = "flowingliquid", tiles = {"river_water.png"}, special_tiles = { { name = "river_water_flowing_animated.png", backface_culling = false, animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 0.8, }, }, { name = "river_water_flowing_animated.png", backface_culling = true, animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 0.8, }, }, }, --alpha = 160, use_texture_alpha = "blend", paramtype = "light", paramtype2 = "flowingliquid", walkable = false, pointable = false, diggable = false, buildable_to = true, is_ground_content = false, drop = "", drowning = 2, liquidtype = "flowing", liquid_alternative_flowing = "nodes:river_water_flowing", liquid_alternative_source = "nodes:river_water_source", liquid_viscosity = 1, liquid_renewable = false, liquid_range = 2, post_effect_color = {a = 203, r = 30, g = 76, b = 90}, groups = {water = 3, liquid = 3, puts_out_fire = 1, not_in_creative_inventory = 1, cools_lava = 1}, sounds = sounds.water, }) minetest.register_node("nodes:lava_source", { description = S("Lava source"), drawtype = "liquid", tiles = { { name = "lava_source_animated.png", animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 3.0, }, }, }, special_tiles = { -- New-style lava source material (mostly unused) { name = "lava_source_animated.png", animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 3.0, }, backface_culling = false, }, }, paramtype = "light", light_source = 8, walkable = false, pointable = false, diggable = false, buildable_to = true, is_ground_content = false, drop = "", drowning = 1, liquidtype = "source", liquid_alternative_flowing = "nodes:lava_flowing", liquid_alternative_source = "nodes:lava_source", liquid_viscosity = 7, liquid_renewable = false, damage_per_second = 4 * 2, post_effect_color = {a = 191, r = 255, g = 64, b = 0}, groups = {lava = 3, liquid = 2, igniter = 1}, }) minetest.register_node("nodes:lava_flowing", { description = S("Flowing lava"), drawtype = "flowingliquid", tiles = {"lava.png"}, special_tiles = { { name = "lava_flowing_animated.png", backface_culling = false, animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 3.3, }, }, { name = "lava_flowing_animated.png", backface_culling = true, animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 3.3, }, }, }, paramtype = "light", paramtype2 = "flowingliquid", light_source = 8, walkable = false, pointable = false, diggable = false, buildable_to = true, is_ground_content = false, drop = "", drowning = 1, liquidtype = "flowing", liquid_alternative_flowing = "nodes:lava_flowing", liquid_alternative_source = "nodes:lava_source", liquid_viscosity = 7, liquid_renewable = false, damage_per_second = 4 * 2, post_effect_color = {a = 191, r = 255, g = 64, b = 0}, groups = {lava = 3, liquid = 2, igniter = 1, not_in_creative_inventory = 1}, }) -- lava cooling ABM lava_check_pos = { {x = 0, y = 1, z = 0}, {x = 1, y = 0, z = 0}, {x = 0, y = 0, z = 1}, {x = -1, y = 0, z = 0}, {x = 0, y = 0, z = -1}, {x = 0, y = -1, z = 0}, } minetest.register_abm({ label = "lava cooling abm", nodenames = {"group:lava"}, neighbors = {"group:cools_lava"}, interval = 1, -- as fast as server allows, usually 1 chance = 1, action = function(pos) for k, v in pairs(lava_check_pos) do local node = minetest.get_node(vector.add(pos, v)) local def = minetest.registered_nodes[node.name] if def.groups.cools_lava then if k == 1 and minetest.get_node(pos).name == "nodes:lava_source" then minetest.set_node(pos, {name = "nodes:obsidian"}) else minetest.set_node(pos, {name = "nodes:cobble_breakable"}) end return end end end, }) -- -- particles -- minetest.register_abm({ label = "smoke", nodenames = {"group:torch", "nodes:fire"}, neighbors = {"air"}, interval = 0.1, chance = 100, catch_up = false, action = function(pos, node) pos.y = pos.y + 0.5 minetest.add_particle({ pos = vector.add(pos, math.random(50)/100 - 0.25), velocity = {x = math.random(20)/100 - 0.1, y = 0.3, z = math.random(20)/100 - 0.1}, expirationtime = 2.3, size = math.random(10)/5 + 2, texture = "smoke_animated.png", animation = { type = "sheet_2d", frames_w = 8, frames_h = 1, frame_length = 0.3, }, }) end, }) minetest.register_abm({ label = "water_bubble", nodenames = {"group:water"}, neighbors = {"air"}, interval = 0.2, chance = 800, catch_up = false, action = function(pos, node, a, b) minetest.add_particle({ pos = vector.add(pos, math.random(50)/100 - 0.25), velocity = {x = 0, y = 0.3, z = 0}, expirationtime = 0.78, size = math.random(10)/5 + 1, texture = "bubble_effect_animated.png", animation = { type = "sheet_2d", frames_w = 8, frames_h = 1, frame_length = 0.1, }, }) end, }) minetest.register_abm({ label = "lava_bubble", nodenames = {"group:lava"}, neighbors = {"air"}, interval = 0.1, chance = 200, catch_up = false, action = function(pos, node, a, b) pos.y = pos.y + 0.5 minetest.add_particle({ pos = vector.add(pos, math.random(50)/100 - 0.25), velocity = {x = 0, y = 0.2, z = 0}, expirationtime = 0.78, size = math.random(10)/5 + 1, texture = "lava_bubble_animated.png", glow = 13, animation = { type = "sheet_2d", frames_w = 8, frames_h = 1, frame_length = 0.1, }, }) end, }) -- tnt -- fire minetest.register_node("nodes:fire", { description = S("Fire"), drawtype = "firelike", tiles = { { name = "fire_animated.png", animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 1.6, }, }, }, inventory_image = "fire.png", paramtype = "light", light_source = 13, walkable = false, buildable_to = true, sunlight_propagates = true, damage_per_second = 4, groups = {igniter = 2}, selection_box = {type = "fixed", fixed = {-7/16, -1/2, -7/16, 7/16, 6/16, 7/16}}, drop = "", }) frame.register("nodes:fire") -- chests: -- empty (fake) chest -- chest-with-key -- chest-with-tool for _, names in ipairs({ { "nothing", S("Empty chest") }, { "boxes:nexus", S("Chest with nexus") }, { "tools:axe", S("Chest with axe") }, { "tools:pickaxe", S("Chest with pickaxe") }, { "tools:shovel", S("Chest with shovel") }, { "tools:sword", S("Chest with sword") }, { "tools:flint_and_steel", S("Chest with flint and steel") }, }) do local name = names[1] local desc = names[2] minetest.register_node("nodes:chest_with_" .. string.gsub(name, ":", "_"), { description = desc, drawtype = "mesh", paramtype = "light", paramtype2 = "facedir", mesh = "chest_close.obj", tiles = {"chest.png"}, groups = { node = 1, trigger = 1 }, on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) minetest.sound_play("chest_open", {pos = pos}) node.name = "nodes:chest_open" mech.trigger(pos) minetest.after(1.0, mech.untrigger, pos) minetest.swap_node(pos, node) minetest.get_node_timer(pos):start(3.0) if name ~= "nothing" then if itemstack:item_fits(name) then itemstack:add_item(name) return itemstack end clicker:get_inventory():add_item("main", name) end return itemstack end, sounds = sounds.wood, }) end minetest.register_alias("nodes:chest_with_boxes_findme_item", "nodes:chest_with_boxes_nexus") minetest.register_node("nodes:chest_open", { description = S("Open chest"), drawtype = "mesh", paramtype = "light", paramtype2 = "facedir", mesh = "chest_open.obj", tiles = {"chest.png"}, on_timer = function(pos) minetest.sound_play("chest_close", {pos = pos}) local node = minetest.get_node(pos) minetest.swap_node(pos, {name = "nodes:chest_with_nothing", param2 = node.param2}) end, groups = {node = 0}, sounds = sounds.wood, }) -- grass variants -- flowers -- farming plants -- flowerpot combos for _, n in pairs({ {"grass_1", "3,3", 56, "grass (1)"}, {"grass_2", "4,3", 56, "grass (2)"}, {"grass_3", "5,3", 56, "grass (3)"}, {"grass_4", "6,3", 56, "grass (4)"}, {"grass_5", "7,3", 56, "grass (5)"}, {"dead_bush", "1,3", 56, "dead bush"}, {"rose", "6,4", 9, "rose"}, {"dandelion", "0,3", 9, "dandelion"}, {"white_tulip", "4,5", 9, "white tulip"}, {"allium", "6,2", 9, "allium"}, {"orchid", "3,4", 9, "orchid"}, {"daisy", "7,2", 9, "daisy"}, {"houstonia", "0,4", 9, "bluet"}, {"paeonia", "4,4", 9, "peony"}, {"wheat_stage_0", "0,1", 11, "wheat (stage 0)"}, {"wheat_stage_1", "1,1", 11, "wheat (stage 1)"}, {"wheat_stage_2", "2,1", 11, "wheat (stage 2)"}, {"wheat_stage_3", "3,1", 11, "wheat (stage 3)"}, {"wheat_stage_4", "4,1", 11, "wheat (stage 4)"}, {"wheat_stage_5", "5,1", 11, "wheat (stage 5)"}, {"wheat_stage_6", "6,1", 11, "wheat (stage 6)"}, {"wheat_stage_7", "7,1", 11, "wheat (stage 7)"}, {"potatoes_stage_0", "4,0", 10, "potatoes (stage 0)"}, {"potatoes_stage_1", "5,0", 10, "potatoes (stage 1)"}, {"potatoes_stage_2", "6,0", 10, "potatoes (stage 2)"}, {"potatoes_stage_3", "7,0", 10, "potatoes (stage 3)"}, {"carrots_stage_0", "0,0", 8, "carrots (stage 0)"}, {"carrots_stage_1", "1,0", 8, "carrots (stage 1)"}, {"carrots_stage_2", "2,0", 8, "carrots (stage 2)"}, {"carrots_stage_3", "3,0", 8, "carrots (stage 3)"}, {"sapling_1", "0,2", 8, "light sapling", true}, {"sapling_2", "1,2", 8, "medium sapling", true}, {"sapling_3", "2,2", 8, "jungle sapling", true}, {"sapling_4", "3,2", 8, "dark sapling", true}, {"sapling_5", "4,2", 8, "fall sapling", true}, {"sapling_6", "5,2", 8, "pine sapling", true}, {"mushroom_red", "2,4", 10, "red mushroom", true}, {"mushroom_brown", "1,4", 10, "brown mushroom", true}, {"fern", "2,3", 9, "fern"}, {"reeds", "5,4", 0, "reeds"}, }) do local tex = "plant_tiles.png^[sheet:8x8:" .. n[2] minetest.register_node("nodes:" .. n[1], { description = nm(n[4]), drawtype = "plantlike", place_param2 = n[3], tiles = {tex}, inventory_image = tex, wield_image = tex, paramtype = "light", paramtype2 = "meshoptions", sunlight_propagates = true, walkable = false, buildable_to = true, floodable = true, selection_box = { type = "fixed", fixed = {-1/4, -1/2, -1/4, 1/4, 1/4, 1/4}, }, sounds = sounds.grass, groups = {node = 1}, }) if n[5] then minetest.register_node("nodes:" .. n[1] .. "_breakable", { description = nm(n[4]), drawtype = "plantlike", place_param2 = n[3], tiles = {tex}, inventory_image = tex, wield_image = tex, paramtype = "light", paramtype2 = "meshoptions", sunlight_propagates = true, walkable = false, buildable_to = true, floodable = true, selection_box = { type = "fixed", fixed = {-1/4, -1/2, -1/4, 1/4, 1/4, 1/4}, }, sounds = sounds.grass, groups = {node = 1, hand = 1}, }) frame.register("nodes:" .. n[1] .. "_breakable") else frame.register("nodes:" .. n[1]) end minetest.register_node("nodes:flowerpot_" ..n[1], { description = S("Pot with @1", n[4]), drawtype = "mesh", mesh = "flowerpot.obj", tiles = { {name = "pot.png"}, {name = tex}, {name = "itb_blank.png"}, }, paramtype = "light", paramtype2 = "facedir", on_rotate = screwdriver.rotate_simple, sunlight_propagates = true, collision_box = { type = "fixed", fixed = {-1/4, -1/2, -1/4, 1/4, -1/8, 1/4}, }, selection_box = { type = "fixed", fixed = {-1/4, -1/2, -1/4, 1/4, 1/2, 1/4}, }, sounds = sounds.stone, groups = {node = 1}, }) end -- seeds for _, m in pairs({ {"melon", "0,5", S("Melon seeds")}, {"wheat", "1,5", S("Wheat seeds")}, {"pumpkin", "7,4", S("Pumpkin seeds")}, }) do local n = m[1] local tex = "plant_tiles.png^[sheet:8x8:" .. m[2] minetest.register_node("nodes:" .. n .. "_seeds", { description = m[3], drawtype = "signlike", tiles = {tex}, inventory_image = tex, wield_image = tex, paramtype = "light", paramtype2 = "wallmounted", sunlight_propagates = true, walkable = false, buildable_to = true, floodable = true, selection_box = { type = "fixed", fixed = {-7/16, -1/2, -7/16, 7/16, -7/16, 7/16}, }, sounds = sounds.grass, groups = {node = 1}, }) minetest.register_node("nodes:" .. n .. "_seeds_breakable", { description = m[3], drawtype = "signlike", tiles = {tex}, inventory_image = tex, wield_image = tex, paramtype = "light", paramtype2 = "wallmounted", sunlight_propagates = true, walkable = false, buildable_to = true, floodable = true, selection_box = { type = "fixed", fixed = {-7/16, -1/2, -7/16, 7/16, -7/16, 7/16}, }, sounds = sounds.grass, groups = {node = 1, hand = 1}, }) frame.register("nodes:" .. n .. "_seeds_breakable") end -- empty flowerpot minetest.register_node("nodes:flowerpot_empty", { description = S("Empty pot"), drawtype = "mesh", mesh = "flowerpot.obj", tiles = { {name = "pot.png"}, {name = "blank.png"}, }, paramtype = "light", sunlight_propagates = true, collision_box = { type = "fixed", fixed = {-1/4, -1/2, -1/4, 1/4, -1/8, 1/4}, }, selection_box = { type = "fixed", fixed = {-1/4, -1/2, -1/4, 1/4, 1/2, 1/4}, }, sounds = sounds.stone, groups = {node = 1}, }) -- soil for _, v in pairs({ { "soil", S("Soil") }, { "soil_wet", S("Wet soil") }, }) do -- register diggable node version minetest.register_node("nodes:" .. v[1] .. "_breakable", { description = v[2], tiles = {v[1] .. ".png", "blocks_tiles.png^[sheet:8x8:5,2"}, groups = {node = 1, shovel = 1}, sounds = sounds.dirt, }) minetest.register_node("nodes:" .. v[1], { description = v[2], tiles = {v[1] .. ".png", "blocks_tiles.png^[sheet:8x8:5,2"}, groups = {node = 1, unbreakable = 1}, sounds = sounds.dirt, }) frame.register("nodes:" .. v[1] .. "_breakable") end -- dirt with grass, minetest.register_node("nodes:dirt_with_grass_breakable", { description = S("Dirt with grass"), tiles = {"blocks_tiles.png^[sheet:8x8:3,3", "blocks_tiles.png^[sheet:8x8:5,2", "grass_side.png"}, groups = {node = 1, shovel = 1}, sounds = sounds.dirt, }) minetest.register_node("nodes:dirt_with_grass", { description = S("Dirt with grass"), tiles = {"blocks_tiles.png^[sheet:8x8:3,3", "blocks_tiles.png^[sheet:8x8:5,2", "grass_side.png"}, groups = {node = 1, unbreakable = 1}, sounds = sounds.dirt, }) frame.register("nodes:dirt_with_grass_breakable") -- dirt with podzol minetest.register_node("nodes:dirt_with_podzol_breakable", { description = S("Dirt with podzol"), tiles = {"podzol.png", "blocks_tiles.png^[sheet:8x8:5,2", "podzol_side.png"}, groups = {node = 1, shovel = 1}, sounds = sounds.dirt, }) minetest.register_node("nodes:dirt_with_podzol", { description = S("Dirt with podzol"), tiles = {"podzol.png", "blocks_tiles.png^[sheet:8x8:5,2", "podzol_side.png"}, groups = {node = 1, unbreakable = 1}, sounds = sounds.dirt, }) frame.register("nodes:dirt_with_podzol_breakable") -- mycelium minetest.register_node("nodes:mycelium_breakable", { description = S("Mycelium"), tiles = {"mycelium_top.png", "blocks_tiles.png^[sheet:8x8:5,2", "mycelium_side.png"}, groups = {node = 1, shovel = 1}, sounds = sounds.dirt, }) minetest.register_node("nodes:mycelium", { description = S("Mycelium"), tiles = {"mycelium_top.png", "blocks_tiles.png^[sheet:8x8:5,2", "mycelium_side.png"}, groups = {node = 1, unbreakable = 1}, sounds = sounds.dirt, }) frame.register("nodes:mycelium_breakable") -- dirt with snow minetest.register_node("nodes:dirt_with_snow_breakable", { description = S("Dirt with snow"), tiles = {"blocks_tiles.png^[sheet:8x8:4,3", "blocks_tiles.png^[sheet:8x8:5,2", "grass_side_snowed.png"}, groups = {node = 1, shovel = 1}, sounds = sounds.snow, }) minetest.register_node("nodes:dirt_with_snow", { description = S("Dirt with snow"), tiles = {"blocks_tiles.png^[sheet:8x8:4,3", "blocks_tiles.png^[sheet:8x8:5,2", "grass_side_snowed.png"}, groups = {node = 1, unbreakable = 1}, sounds = sounds.snow, }) frame.register("nodes:dirt_with_snow_breakable") minetest.register_node("nodes:snow_ledge", { description = S("Snow ledge"), paramtype = "light", drop = {}, groups = {node = 1, hand = 1, dig_immediate = 3, attached_node = 1, falling_node = 1}, sounds = sounds.snow, tiles = {"blocks_tiles.png^[sheet:8x8:4,3"}, drawtype = "nodebox", node_box = { type = "fixed", fixed = { {-1/2, -1/2, -1/2, 1/2, -1/4, 1/2}, }, }, }) local lines = { { "blue", S("Blue line"), "line" }, { "gray", S("Gray line"), "line" }, { "green", S("Green line"), "line" }, { "rail", S("Rail"), "rail" }, { "red", S("Red line"), "line" }, } for i, v in ipairs(lines) do minetest.register_node("nodes:line_" .. v[1], { description = v[2], drawtype = "raillike", paramtype = "light", sunlight_propagates = true, walkable = false, tiles = { "line_tiles.png^[sheet:4x5:2," .. i-1, "line_tiles.png^[sheet:4x5:1," .. i-1, "line_tiles.png^[sheet:4x5:3," .. i-1, "line_tiles.png^[sheet:4x5:0," .. i-1, }, wield_image = "line_tiles.png^[sheet:4x5:2," .. i-1, inventory_image = "line_tiles.png^[sheet:4x5:2," .. i-1, selection_box = {type = "fixed", fixed = {-1/2, -1/2, -1/2, 1/2, -7/16, 1/2}, }, groups = {node = 1, unbreakable = 1, connect_to_raillike = minetest.raillike_group(v[3]) }, sounds = sounds.wood, }) end -- attach breakable callbacks to everything for name, def in pairs(minetest.registered_nodes) do assert(def.groups) if def.groups.shovel or def.groups.axe or def.groups.pickaxe or def.groups.hand then local toolinfo = S("Can be obtained by the player") if def.groups.shovel then toolinfo = S("Can be dug with a shovel by the player") elseif def.groups.axe then toolinfo = S("Can be chopped with an axe by the player") elseif def.groups.pickaxe then toolinfo = S("Can be dug with a pickaxe by the player") elseif def.groups.hand then toolinfo = S("Can be picked up by the player") end local desc = def.description minetest.override_item(name, { description = desc .. "\n" .. toolinfo, on_place = on_place_breakable, on_destruct = on_destruct_breakable, after_dig_node = nodes.after_dig_node_breakable, node_placement_prediction = "", }) end end