Skip to content

Commit

Permalink
Allow stacking tools with compatible data (#17)
Browse files Browse the repository at this point in the history
* 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 <sx@minetest>
  • Loading branch information
S-S-X and SX committed May 23, 2020
1 parent c24ea95 commit 8cfc515
Showing 1 changed file with 39 additions and 3 deletions.
42 changes: 39 additions & 3 deletions metatool/api.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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, {
Expand All @@ -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,
Expand All @@ -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'
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 8cfc515

Please sign in to comment.