diff --git a/mods/bg_api/init.lua b/mods/bg_api/init.lua index c3f7650..e2aff33 100644 --- a/mods/bg_api/init.lua +++ b/mods/bg_api/init.lua @@ -23,6 +23,7 @@ load_file("random_tick") load_file("increasing_abm") load_file("loose_node") load_file("fall_fix") +load_file("leveled_node") load_file("privs") diff --git a/mods/bg_api/leveled_node.lua b/mods/bg_api/leveled_node.lua new file mode 100644 index 0000000..f08e3ad --- /dev/null +++ b/mods/bg_api/leveled_node.lua @@ -0,0 +1,85 @@ +local decomposing_leaves_layers = 4 + +local function is_same_kind (pos, basename) + local node = minetest.get_node(pos) + local node_basename = minetest.registered_items[node.name].basename + return basename == node_basename +end + +local function after_place_stack (pos) + local node = minetest.get_node(pos) + if not blockgame.item_matches(node.name, {"groups:leveled"}) then return end + local def = minetest.registered_nodes[node.name] + local basename = def.basename + local level_max = def.level_max + + local below = pos + blockgame.vector.dirs.down + if is_same_kind(below, basename) then + local below_node = minetest.get_node(pos) + local below_def = minetest.registered_nodes[below_node.name] + + if below_def.level ~= level_max then + local max_diff = level_max - below_def.level + local diff = math.min(max_diff, def.level) + + minetest.swap_node(below, {name = basename .. "_" .. (below_def.level + diff)}) + if diff == def.level then + minetest.remove_node(pos) + else + minetest.swap_node(pos, {name = basename .. "_" .. (def.level - diff)}) + end + end + end + + local above = pos:offset(0, 1, 0) + if is_same_kind(above, basename) then + after_place_stack(above) + end +end + +local function register_layer (basename, def, level) + local description = def.description .. " (" .. level .. "/" .. def.level_max .. ")" + if level == level_max then description = def.description end + def.description = description + + local height = level / def.level_max + + local drawtype = "nodebox" + local node_box = { + ["type"] = "fixed", + fixed = { -0.5, -0.5, -0.5, 0.5, -0.5 + height, 0.5 }, + } + if level == level_max then + drawtype = def.drawtype + node_box = nil + end + def.drawtype = drawtype + def.node_box = node_box + + def.on_construct = after_place_stack + def.after_place_node = after_place_stack + def.after_land = after_place_stack + + def.groups = def.groups or {} + def.groups = blockgame.underride(def.groups, { + leveled = level, + }) + + local layer_modname = minetest.get_current_modname() + def.drop = def.drop or layer_modname .. ":" .. basename .. "_1 " .. level + + blockgame.register_node(basename .. "_" .. level, def) +end + +function blockgame.register_leveled_node (basename, def) + local level_max = def.level_max + if not level_max then return false end + + def.basename = basename + + for level=1, level_max do + register_layer(basename, def, level) + end + minetest.register_alias(basename, basename .. "_" .. level_max) + return true +end diff --git a/mods/bg_api/util_table.lua b/mods/bg_api/util_table.lua index 6de7ee8..f743277 100644 --- a/mods/bg_api/util_table.lua +++ b/mods/bg_api/util_table.lua @@ -16,6 +16,18 @@ function blockgame.shallow_copy_table (tab) return result end +function blockgame.naive_deep_copy (tab) + local result = {} + for key, value in pairs(tab) do + if type(value) == "table" then + result[key] = blockgame.naive_deep_copy(value) + else + result[key] = value + end + end + return result +end + function blockgame.shuffle (tab) local keys = blockgame.get_keys(tab) local result = {} @@ -43,9 +55,13 @@ end function blockgame.underride (tab, template) local tab = tab or {} - local result = blockgame.shallow_copy_table(template) + local result = blockgame.naive_deep_copy(template) for key, value in pairs(tab) do - result[key] = value + if type(value) == "table" then + result[key] = blockgame.underride(value, template[key] or {}) + else + result[key] = value + end end return result end diff --git a/mods/bg_tree/node_leaves.lua b/mods/bg_tree/node_leaves.lua index e983329..d4cecc9 100644 --- a/mods/bg_tree/node_leaves.lua +++ b/mods/bg_tree/node_leaves.lua @@ -1,24 +1,25 @@ local modname = minetest.get_current_modname() -local function reg_leaves (name, def) - local texture = def.texture or name - - def = blockgame.underride(def, { - description = name, - - texture = texture, - tiles = {modname .. "_" .. texture .. ".png"}, - - drawtype = "allfaces_optional", - paramtype = "light", - sunlight_propagates = true, - }) - - def.groups = blockgame.underride(def.groups, { +local base_def = { + drawtype = "allfaces_optional", + paramtype = "light", + sunlight_propagates = true, + groups = { planty = 1, extends_leaves_support = 1, air_flowable = 1, falling_node = 1, + }, +} + +local function reg_leaves (name, def) + def = blockgame.underride(def, base_def) + + local texture = def.texture or name + def = blockgame.underride(def, { + description = name, + tiles = {modname .. "_" .. texture .. ".png"}, + }) blockgame.register_node(name, def) @@ -63,14 +64,17 @@ reg_leaves("leaves_alive", { }, }) +--[[ local function check_decompose (pos) local node = minetest.get_node(pos) return blockgame.item_matches(node.name, {"group:leaves_decomposing"}) end +]]-- -- TODO: generalize stacking node registration and put into API. local decomposing_leaves_layers = 4 +--[[ local function after_place_stack (pos) if not check_decompose(pos) then return end @@ -117,26 +121,24 @@ local function reg_decomposing (level) node_box = nil end - reg_leaves("leaves_decomposing_" .. level, { - description = description, - level = level, - level_max = decomposing_leaves_layers, - texture = "leaves_decomposing", - drawtype = drawtype, - node_box = node_box, - on_construct = after_place_stack, - after_place_node = after_place_stack, - after_land = after_place_stack, - drop = modname .. ":leaves_decomposing_1 " .. level, - groups = { - leaves_decomposing = level, - }, - walkable = false, - supports_falling = true, - }) + reg_leaves("leaves_decomposing_" .. level, ) end for level=1, decomposing_leaves_layers do reg_decomposing(level) end minetest.register_alias(modname .. ":leaves_decomposing", modname .. ":leaves_decomposing_" .. decomposing_leaves_layers) +]]-- + +blockgame.register_leveled_node("leaves_decomposing", blockgame.underride({ + description = "Decomposing Leaves", + level_max = decomposing_leaves_layers, + tiles = { + modname .. "_leaves_decomposing.png", + }, + groups = { + leaves_decomposing = level, + }, + walkable = false, + supports_falling = true, +}, base_def))