improve placement of leveled nodes.

they now stack when placed on top of each other, even if there's a node
in the position above the targetted stack.
This commit is contained in:
trans_soup 2023-10-22 22:13:46 +02:00
parent 249a698b52
commit 512847f8f6

View file

@ -4,6 +4,12 @@ local function is_same_kind (pos, kindname)
return kindname and node_kindname and kindname == node_kindname
end
local function transfer_levels (source, target, max)
local max_diff = max - target
local diff = math.min(max_diff, source)
return source - diff, target + diff
end
local function stack_attempt (pos, source_level)
local node = minetest.get_node(pos)
local def = minetest.registered_nodes[node.name]
@ -12,11 +18,10 @@ local function stack_attempt (pos, source_level)
local level_max = def.level_max
local kindname = def.kindname
local max_diff = level_max - def.level
local diff = math.min(max_diff, source_level)
local source_level, target_level = transfer_levels(source_level, def.level, level_max)
minetest.swap_node(pos, {name = kindname .. "_" .. (def.level + diff)})
return source_level - diff
minetest.swap_node(pos, {name = kindname .. "_" .. (target_level)})
return source_level
end
function blockgame.check_for_stacking (pos)
@ -43,6 +48,40 @@ end
local function on_place (itemstack, placer, pointed)
local function fallback_to_default ()
return minetest.item_place(itemstack, placer, pointed)
end
local placed_def = minetest.registered_items[itemstack:get_name()]
if not placed_def.level_max then return fallback_to_default() end
if not is_same_kind(pointed.under, placed_def.kindname) then return fallback_to_default() end
local above = pointed.under + vector.new(0, 1, 0)
local is_top = above == pointed.above
if not is_top then return fallback_to_default() end
local above_node = minetest.get_node(above)
local target_node = minetest.get_node(pointed.under)
local target_def = minetest.registered_items[target_node.name]
if target_def.level_max == target_def.level then return fallback_to_default() end
local source_level, target_level = transfer_levels(placed_def.level, target_def.level, placed_def.level_max)
if source_level > 0 and above_node.name ~= "air" then return fallback_to_default() end
local left_over = stack_attempt(pointed.under, placed_def.level)
if above_node.name == "air" then
minetest.set_node(pointed.above, {name = target_def.kindname .. "_" .. left_over})
end
itemstack:set_count(itemstack:get_count() - 1)
return itemstack
end
local function register_layer (kindname, def, level, modname)
local def = blockgame.naive_deep_copy(def)
def.level = level
@ -60,6 +99,7 @@ local function register_layer (kindname, def, level, modname)
end
def.on_construct = blockgame.check_for_stacking
def.on_place = on_place
def.after_place_node = blockgame.check_for_stacking
def.after_land = blockgame.check_for_stacking