From 8cfc515a6eda1f43917c1765d8c6f4035929e2d4 Mon Sep 17 00:00:00 2001 From: SX <50966843+S-S-X@users.noreply.github.com> Date: Sun, 24 May 2020 02:28:01 +0300 Subject: [PATCH] Allow stacking tools with compatible data (#17) * Allow stacking tools with compatible data * declare `separated` as local Best to test in production, tried to test most situations but there is possibility for item duplication or loss of items. Not that bad with these tools even if it happens. Co-authored-by: SX --- metatool/api.lua | 42 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/metatool/api.lua b/metatool/api.lua index 98b53ce..726bcd8 100644 --- a/metatool/api.lua +++ b/metatool/api.lua @@ -30,7 +30,7 @@ local register_metatool_item = function(name, definition) local texture = definition.texture or 'metatool_wand.png' local liquids_pointable = definition.liquids_pointable == nil and false or definition.liquids_pointable local craft_count = definition.craft_count or 1 - local stack_max = definition.stack_max or 1 + local stack_max = definition.stack_max or 99 craft_count = craft_count > stack_max and stack_max or craft_count minetest.register_craftitem(itemname, { @@ -41,7 +41,6 @@ local register_metatool_item = function(name, definition) wield_image = texture, wield_scale = { x = 0.8, y = 1, z = 0.8 }, liquids_pointable = liquids_pointable, - node_placement_prediction = nil, on_use = function(...) return metatool:on_use(itemname_clean, unpack({...})) end, @@ -61,6 +60,39 @@ local register_metatool_item = function(name, definition) return itemname_clean end +local separate_stack = function(itemstack) + if itemstack:get_count() > 1 then + local toolname = itemstack:get_name() + local separated = ItemStack(toolname) + separated:set_count(1) + itemstack:take_item(1) + return itemstack, separated + end + return itemstack, false +end + +local return_itemstack = function(player, itemstack, separated) + if separated then + -- stack was separated, try to recombine + local meta1 = itemstack:get_meta() + local meta2 = separated:get_meta() + if meta1:equals(meta2) then + -- stacks can be recombinined, do it + itemstack:set_count(itemstack:get_count() + 1) + else + -- stacks cannot be recombined, give or drop new stack + local inv = player:get_inventory() + if inv:room_for_item("main", separated) then + -- item fits to inventory + inv:add_item("main", separated) + else + -- item will not fit to inventory + minetest.item_drop(separated, player, player:get_pos()) + end + end + end +end + local validate_tool_definition = function(definition) local function F(key) local res = type(definition[key]) == 'function' @@ -97,7 +129,11 @@ metatool = { if controls.aux1 or controls.sneak then -- Execute on_read_node when tool is used on node and special or sneak is held local data, group, description = tooldef.itemdef.on_read_node(tooldef, player, pointed_thing, node, pos) - metatool.write_data(itemstack, {data=data,group=group}, description) + local separated + itemstack, separated = separate_stack(itemstack) + metatool.write_data(separated or itemstack, {data=data,group=group}, description) + -- if stack was separated give missing items to player + return_itemstack(player, itemstack, separated) else local data = metatool.read_data(itemstack) if type(data) == 'table' then