Auke Kok dbb0d7ee91 Snow ledge node.
Can always be dug by the player (hide stuff under it!) by
hand. Falling node. No items are given to the player that
digs it.
2017-05-01 21:52:58 -07:00

1324 lines
34 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 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
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,
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 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}
local on_destruct
if v[5] then
on_destruct = on_destruct_breakable
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,
on_destruct = on_destruct,
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")
minetest.register_node("nodes:snow_ledge", {
description = "Snow ledge (breakable)",
drop = {},
groups = {node = 1, shovel = 1, dig_immediate = 3, attached_node = 1, falling_node = 1},
sounds = sounds.snow,
tiles = {"snow.png"},
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
{-1/2, -1/2, -1/2, 1/2, -1/4, 1/2},
},
},
})