5768317269
The new change preserves uncombined stacks when digging. For example, if you have dirt on the far right, tools on the far left, and space between, and you dig dirt with the tools on the left, it will create a NEW stack in the space between BEFORE it reaches the dirt on the far right. This behavior is necessary to ensure we can keep stacks separate that we've separated for a specific purpose. We also can't make the behavior vary based on whether using a tool or not, because this would be even MORE jarring.
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 = excess[i]:add_item(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 = snap[j]:add_item(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)
|