1288 lines
33 KiB
Lua

--[[
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.5,
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
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")