3c5d7e200b
If items have a common "stackfamily" property in definition, then they combine stacks; name and metadata are effectively ignored and any name is considered acceptable for the combined stack name. This is used by Lux to allow it to stack naturally instead of the player having to lay them out spaced on the ground to "cool" them all to the same level, since all Lux changes dynamically anyway.
83 lines
2.0 KiB
Lua
83 lines
2.0 KiB
Lua
-- LUALOCALS < ---------------------------------------------------------
|
|
local ItemStack, ipairs, minetest, nodecore
|
|
= ItemStack, ipairs, minetest, nodecore
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
local cache = {}
|
|
|
|
local function handlepickups(player)
|
|
local inv = player:get_inventory()
|
|
local pname = player:get_player_name()
|
|
local cached = cache[pname]
|
|
if cached then
|
|
local snap = {}
|
|
for i = 1, #cached do snap[i] = ItemStack(cached[i]) end
|
|
|
|
local excess = {}
|
|
local dirty
|
|
|
|
local widx = player:get_wield_index()
|
|
for i in nodecore.inv_walk(player, widx, inv) do
|
|
local cur = inv:get_stack("main", i)
|
|
local old = snap[i]
|
|
if old:is_empty() or cur:peek_item(1):to_string()
|
|
== old:peek_item(1):to_string() then
|
|
local def = minetest.registered_items[cur:get_name()]
|
|
if not (def and def.virtual_item) then
|
|
local cc = cur:get_count()
|
|
local oc = old:get_count()
|
|
if cc > oc then
|
|
cur:set_count(cc - oc)
|
|
for i = 1, #excess do
|
|
cur = nodecore.stack_merge(excess[i], cur)
|
|
end
|
|
if not cur:is_empty() then
|
|
excess[#excess + 1] = cur
|
|
end
|
|
dirty = dirty or i ~= widx
|
|
else
|
|
snap[i] = cur
|
|
end
|
|
end
|
|
else
|
|
snap[i] = cur
|
|
end
|
|
end
|
|
|
|
if dirty then
|
|
for i = 1, #excess do
|
|
local v = excess[i]
|
|
for j in nodecore.inv_walk(player, widx, inv) do
|
|
v = nodecore.stack_merge(snap[j], v)
|
|
end
|
|
if not v:is_empty() then
|
|
minetest.log("failed to reinsert item "
|
|
.. v:get_name() .. " " .. v:get_count()
|
|
.. " for " .. pname)
|
|
dirty = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
if dirty then
|
|
dirty = nil
|
|
for i = 1, #cached do
|
|
dirty = dirty or inv:get_stack("main", i)
|
|
:to_string() ~= snap[i]:to_string()
|
|
end
|
|
end
|
|
|
|
if dirty then
|
|
minetest.log("inventory rearranged for " .. pname)
|
|
inv:set_list("main", snap)
|
|
end
|
|
end
|
|
cache[pname] = inv:get_list("main")
|
|
end
|
|
|
|
minetest.register_globalstep(function()
|
|
for _, p in ipairs(minetest.get_connected_players()) do
|
|
handlepickups(p)
|
|
end
|
|
end)
|