--[[ nodes.lua - basic node blocks for Inside The Box ]]-- -- -- visual marker for where breakable nodes can be placed -- local tilecache = {} local get_tiles = function(name) if tilecache[name] then return tilecache[name] else local def = minetest.registered_nodes[name] local tex = minetest.inventorycube( def.tiles[1] and def.tiles[1].name or def.tiles[1], def.tiles[2] and def.tiles[2].name or def.tiles[1] and def.tiles[1].name or def.tiles[1], def.tiles[3] and def.tiles[3].name or def.tiles[2] and def.tiles[2].name or def.tiles[1] and def.tiles[1].name or def.tiles[1] ) 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, "Can only place this node at an empty node. Clear the space first") return itemstack end -- place placeholder information minetest.set_node(pos, {name = "nodes:placeholder"}) 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) 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) return itemstack else minetest.log("info", name .. " attempted to place a " .. place .. " outside a box") return itemstack end end local function 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 placeholder_particles(pos) local meta = minetest.get_meta(pos) local placeable = meta:get_string("placeable") if placeable == "" then return false end local nodes = minetest.parse_json(placeable) for _, obj in pairs(minetest.get_objects_inside_radius(pos, 3)) do if obj:is_player() then local itemstack = obj:get_wielded_item() local name = itemstack:get_name() if itemstack and nodes[name] then minetest.add_particle({ pos = pos, expirationtime = 0.55, size = 5, texture = get_tiles(name), glow = 14, }) end end end return true end minetest.register_node("nodes:placeholder", { description = "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 = placeholder_particles, on_construct = function(pos) minetest.get_node_timer(pos):start(0.5) end, 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 nodes = { {"bricks_clay", true, "pickaxe", sounds.stone}, {"bricks_limestone", true, "pickaxe", sounds.stone}, {"bricks_marble", true, "pickaxe", sounds.stone}, {"bricks_sandstone", true, "pickaxe", sounds.stone}, {"bricks_stone", true, "pickaxe", sounds.stone}, {"bricks_stone_moss", true, "pickaxe", sounds.stone}, {"cobble", true, "pickaxe", sounds.stone}, {"cobble_moss", true, "pickaxe", sounds.stone}, {"limestone", true, "pickaxe", sounds.stone}, {"marble", true, "pickaxe", sounds.stone}, {"sandstone", true, "pickaxe", sounds.stone}, {"stone", true, "pickaxe", sounds.stone}, {"stone_moss", true, "pickaxe", sounds.stone}, {"obsidian", true, false, sounds.stone}, {"bronze", false, "pickaxe", sounds.metal}, {"gold", false, "pickaxe", sounds.metal}, {"emerald", false, "pickaxe", sounds.stone}, {"iron", false, "pickaxe", sounds.metal}, {"clay", false, "shovel", sounds.dirt}, {"dirt", false, "shovel", sounds.dirt}, {"gravel", false, "shovel", sounds.gravel, 1}, {"sand", false, "shovel", sounds.sand, 1}, {"wood_dark", true, "axe", sounds.wood}, {"wood_light", true, "axe", sounds.wood}, {"wood_medium", true, "axe", sounds.wood}, {"grass", false, false, sounds.grass}, {"snow", false, "shovel", sounds.snow}, {"ice", false, "pickaxe", sounds.stone}, {"ore_black", false, "pickaxe", sounds.stone}, {"ore_blue", false, "pickaxe", sounds.stone}, {"ore_brown", false, "pickaxe", sounds.stone}, {"ore_cyan", false, "pickaxe", sounds.stone}, {"ore_gold", false, "pickaxe", sounds.stone}, {"ore_green", false, "pickaxe", sounds.stone}, {"ore_red", false, "pickaxe", sounds.stone}, } local function make_stair_slab(name, groups, b1, b2, snd, tex) if not tex then tex = name end minetest.register_node("nodes:" .. name .. b1 .. "_stairs", { description = name .. " 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 = name .. " 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 _, v in pairs(nodes) do local groups = {node = 1} if v[5] 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 = v[1] .. " (breakable)", tiles = {v[1] .. ".png"}, groups = gg, sounds = v[4], on_place = on_place_breakable, after_dig_node = after_dig_node_breakable, node_placement_prediction = "", }) if v[2] then make_stair_slab(v[1], gg, "_breakable", " (breakable)", v[4]) end frame.register("nodes:" .. v[1] .. "_breakable") end groups.unbreakable = 1 minetest.register_node("nodes:" .. v[1], { description = v[1], tiles = {v[1] .. ".png"}, groups = groups, sounds = v[4], }) if v[2] then make_stair_slab(v[1], groups, "", "") walls.register("nodes:" .. v[1] .. "_wall", v[1] .. " Wall", v[1] .. ".png", v[4], groups) end end minetest.register_node("nodes:marbleb", { description = "Marble border", tiles = {"marble.png"}, unpushable = true, groups = {not_in_creative_inventory = 1, stone = 1}, sounds = sounds.stone, }) minetest.register_node("nodes:bronzeb", { description = "Bronze border", tiles = {"bronze.png"}, unpushable = true, groups = {not_in_creative_inventory = 1}, sounds = sounds.metal, }) -- -- wool -- for _, v in pairs({"yellow", "white", "violet", "red", "pink", "orange", "magenta", "grey", "green", "dark_grey", "dark_green", "cyan", "brown", "blue", "black"}) do minetest.register_node("nodes:wool_" .. v, { description = v .. " wool", tiles = {"itb_wool_" .. v .. ".png"}, groups = {node = 1, unbreakable = 1}, sounds = sounds.cloth, }) minetest.register_node("nodes:carpet_" .. v, { description = v .. " carpet", tiles = {"itb_wool_" .. v .. ".png"}, 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, {node = 1, unbreakable = 1}, "", "", sounds.cloth, "itb_wool_" .. v) minetest.register_node("nodes:wool_" .. v .. "_breakable", { description = v .. " wool (breakable", tiles = {"itb_wool_" .. v .. ".png"}, groups = {axe = 1, node = 1}, sounds = sounds.cloth, on_place = on_place_breakable, after_dig_node = after_dig_node_breakable, node_placement_prediction = "", }) make_stair_slab("wool_" .. v, {axe = 1, node = 1}, "_breakable", " (breakable)", sounds.cloth, "itb_wool_" .. v) frame.register("nodes:wool_" .. v .. "_breakable") end -- trunks and leaves for _, v in pairs({ "light", "medium", "dark" }) do minetest.register_node("nodes:trunk_" .. v .. "_breakable", { description = v .. " trunk (breakable)", tiles = {"trunk_" .. v .. "_top.png", "trunk_" .. v .. "_top.png", "trunk_" .. v .. ".png"}, groups = {axe = 1, node = 1, wood = 1}, paramtype2 = "facedir", sounds = sounds.wood, on_place = on_place_breakable, after_dig_node = after_dig_node_breakable, node_placement_prediction = "", }) minetest.register_node("nodes:trunk_" .. v .. "", { description = v .. " trunk", tiles = {"trunk_" .. v .. "_top.png", "trunk_" .. v .. "_top.png", "trunk_" .. v .. ".png"}, groups = {node = 1, unbreakable = 1, wood = 1}, paramtype2 = "facedir", sounds = sounds.wood, }) frame.register("nodes:trunk_" .. v .. "_breakable") minetest.register_node("nodes:leaves_" .. v .. "_breakable", { description = v .. " leaves (breakable)", drawtype = "allfaces_optional", paramtype = "light", tiles = {"leaves_" .. v .. ".png"}, groups = {node = 1, axe = 1, leaves = 1}, sounds = sounds.leaves, on_place = on_place_breakable, after_dig_node = after_dig_node_breakable, node_placement_prediction = "", }) minetest.register_node("nodes:leaves_" .. v, { description = v .. " leaves", drawtype = "allfaces_optional", paramtype = "light", tiles = {"leaves_" .. v .. ".png"}, groups = {node = 1, unbreakable = 1, leaves = 1}, sounds = sounds.leaves, }) end -- barrier minetest.register_node("nodes:barrier", { description = "Barrier", pointable = true, -- make it easy to understand that it's a barrier drawtype = "airlike", inventory_image = "barrier.png", sunlight_propagates = true, paramtype = "light", unpushable = true, groups = {unbreakable = 1, node = 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 = "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 = "glass (breakable)", drawtype = "glasslike_framed_optional", sunlight_propagates = true, paramtype = "light", tiles = {"glass.png"}, groups = {node = 1, pickaxe = 1}, sounds = sounds.glass, on_place = on_place_breakable, after_dig_node = after_dig_node_breakable, node_placement_prediction = "", }) 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 end else on_untrigger = lamp_on_untrigger end minetest.register_node("nodes:lamp_bar_" .. v, { description = "A 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 = "A Broken 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 = "A Broken 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, }) for _, wood in ipairs({"wood_dark", "wood_light", "wood_medium"}) do fences.register_fence("nodes:fence_" .. wood, { description = wood .. " Fence", texture = wood .. "_fence.png", inventory_image = "default_fence_overlay.png^" .. wood .. ".png^default_fence_overlay.png^[makealpha:255,126,126", wield_image = "default_fence_overlay.png^" .. wood .. ".png^default_fence_overlay.png^[makealpha:255,126,126", groups = {node = 1, unbreakable = 1, wood = 1}, sounds = sounds.wood, }) end -- ladders, rope & vines for _, n in pairs({ {"ladder", "signlike"}, {"rope", "plantlike"}, {"vine", "signlike"}, }) do minetest.register_node("nodes:" .. n[1], { description = n[1], drawtype = n[2], tiles = {n[1] .. ".png"}, inventory_image = n[1] .. ".png", paramtype = "light", paramtype2 = "wallmounted", sunlight_propagates = true, walkable = false, climbable = true, selection_box = n[2] == "signlike" and {type = "wallmounted"}, groups = {node = 1, unbreakable = 1}, sounds = sounds.wood, }) minetest.register_node("nodes:" .. n[1] .. "_breakable", { description = n[1] .. "(breakable)", drawtype = n[2], tiles = {n[1] .. ".png"}, inventory_image = n[1] .. ".png", paramtype = "light", paramtype2 = "wallmounted", sunlight_propagates = true, walkable = false, climbable = true, selection_box = n[2] == "signlike" and {type = "wallmounted"}, groups = {node = 1, axe = 1}, sounds = sounds.wood, on_place = on_place_breakable, after_dig_node = after_dig_node_breakable, node_placement_prediction = "", }) frame.register("nodes:" .. n[1] .. "_breakable") end minetest.register_node("nodes:waterlily", { description = "Waterlily", drawtype = "nodebox", sunlight_propagates = true, tiles = {"waterlily.png"}, 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", on_place = function(itemstack, placer, pointed_thing) local pos = pointed_thing.under if not pos then return itemstack end 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, }) -- special nodes -- liquids minetest.register_node("nodes:water_source", { description = "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, paramtype = "light", walkable = false, pointable = false, diggable = false, buildable_to = true, is_ground_content = false, drop = "", drowning = 1, 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 = "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 = 0.8, }, }, { name = "water_flowing_animated.png", backface_culling = true, animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 0.8, }, }, }, alpha = 160, paramtype = "light", paramtype2 = "flowingliquid", walkable = false, pointable = false, diggable = false, buildable_to = true, is_ground_content = false, drop = "", drowning = 1, 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 = "River Water Source", drawtype = "liquid", tiles = { { name = "river_water_source_animated.png", animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 2.0, }, }, }, special_tiles = { { name = "river_water_source_animated.png", animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 2.0, }, backface_culling = false, }, }, alpha = 160, paramtype = "light", walkable = false, pointable = false, diggable = false, buildable_to = true, is_ground_content = false, drop = "", drowning = 1, 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 = "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, paramtype = "light", paramtype2 = "flowingliquid", walkable = false, pointable = false, diggable = false, buildable_to = true, is_ground_content = false, drop = "", drowning = 1, 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 = "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}, sounds = sounds.water, }) minetest.register_node("nodes:lava_flowing", { description = "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}, sounds = sounds.water, }) -- 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 = "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 = "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}, drop = "", }) frame.register("nodes:fire") -- chests: -- empty (fake) chest -- chest-with-key -- chest-with-tool for _, name in ipairs({ "nothing", "boxes:nexus", "tools:axe", "tools:pickaxe", "tools:shovel", "tools:sword", "tools:flint_and_steel", }) do minetest.register_node("nodes:chest_with_" .. string.gsub(name, ":", "_"), { description = "Chest with " .. name, drawtype = "mesh", paramtype = "light", paramtype2 = "facedir", mesh = "chest_close.obj", tiles = {"chest.png"}, 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, }) end minetest.register_alias("nodes:chest_with_boxes_findme_item", "nodes:chest_with_boxes_nexus") minetest.register_node("nodes:chest_open", { description = "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}, }) -- grass variants -- flowers -- farming plants -- flowerpot combos for _, n in pairs({ {"grass_1", 56}, {"grass_2", 56}, {"grass_3", 56}, {"grass_4", 56}, {"grass_5", 56}, {"rose", 9}, {"dandelion", 9}, {"white_tulip", 9}, {"allium", 9}, {"orchid", 9}, {"daisy", 9}, {"houstonia", 9}, {"paeonia", 9}, {"wheat_stage_0", 11}, {"wheat_stage_1", 11}, {"wheat_stage_2", 11}, {"wheat_stage_3", 11}, {"wheat_stage_4", 11}, {"wheat_stage_5", 11}, {"wheat_stage_6", 11}, {"wheat_stage_7", 11}, {"potatoes_stage_0", 10}, {"potatoes_stage_1", 10}, {"potatoes_stage_2", 10}, {"potatoes_stage_3", 10}, {"carrots_stage_0", 8}, {"carrots_stage_1", 8}, {"carrots_stage_2", 8}, {"carrots_stage_3", 8}, {"sapling_1", 8}, {"sapling_2", 8}, {"sapling_3", 8}, {"sapling_4", 8}, {"sapling_5", 8}, {"sapling_6", 8}, {"mushroom_red", 10}, {"mushroom_brown", 10}, {"fern", 9}, {"reeds", 0}, }) do if n[2] then minetest.register_node("nodes:" .. n[1], { description = n[1], drawtype = "plantlike", place_param2 = n[2], tiles = {n[1] .. ".png"}, 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, }) else minetest.register_node("nodes:" .. n[1], { description = n[1], drawtype = "plantlike", tiles = {n[1] .. ".png"}, paramtype = "light", 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, }) end frame.register("nodes:" .. n[1]) minetest.register_node("nodes:flowerpot_" ..n[1], { description = "Pot with " .. n[1], drawtype = "mesh", mesh = "flowerpot.obj", tiles = { {name = "pot.png"}, {name = n[1] .. ".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.wood, }) end -- empty flowerpot minetest.register_node("nodes:flowerpot_empty", { description = "Pot (empty)", drawtype = "mesh", mesh = "flowerpot.obj", tiles = { {name = "pot.png"}, {name = "itb_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.wood, }) -- soil for _, v in pairs({ "soil", "soil_wet", }) do -- register diggable node version minetest.register_node("nodes:" .. v .. "_breakable", { description = v .. " (breakable)", tiles = {{name = v .. ".png"}, {name = "dirt.png"}}, groups = {node = 1, shovel = 1}, sounds = sounds.dirt, on_place = on_place_breakable, after_dig_node = after_dig_node_breakable, node_placement_prediction = "", }) minetest.register_node("nodes:" .. v, { description = v, tiles = {{name = v .. ".png"}, {name = "dirt.png"}}, groups = {node = 1, unbreakable = 1}, sounds = sounds.dirt, }) frame.register("nodes:" .. v .. "_breakable") end -- dirt with grass, minetest.register_node("nodes:dirt_with_grass_breakable", { description = "Dirt with grass (breakable)", tiles = {"grass.png", "dirt.png", "grass_side.png"}, groups = {node = 1, shovel = 1}, sounds = sounds.dirt, on_place = on_place_breakable, after_dig_node = after_dig_node_breakable, node_placement_prediction = "", }) minetest.register_node("nodes:dirt_with_grass", { description = "Dirt with grass", tiles = {"grass.png", "dirt.png", "grass_side.png"}, groups = {node = 1, unbreakable = 1}, sounds = sounds.dirt, }) frame.register("nodes:dirt_with_grass_breakable") -- dirt with snow minetest.register_node("nodes:dirt_with_snow_breakable", { description = "Dirt with snow (breakable)", tiles = {"snow.png", "dirt.png", "grass_side_snowed.png"}, groups = {node = 1, shovel = 1}, sounds = sounds.snow, on_place = on_place_breakable, after_dig_node = after_dig_node_breakable, node_placement_prediction = "", }) minetest.register_node("nodes:dirt_with_snow", { description = "Dirt with snow", tiles = {"snow.png", "dirt.png", "grass_side_snowed.png"}, groups = {node = 1, unbreakable = 1}, sounds = sounds.snow, }) frame.register("nodes:dirt_with_snow_breakable")