2019-03-27 22:10:45 -04:00
|
|
|
-- LUALOCALS < ---------------------------------------------------------
|
|
|
|
local ItemStack, ipairs, minetest
|
|
|
|
= ItemStack, ipairs, minetest
|
|
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
|
|
|
|
local cache = {}
|
|
|
|
|
|
|
|
local function invidx(player, inv, widx)
|
|
|
|
widx = widx or player:get_wield_index()
|
|
|
|
local size = (inv or player:get_inventory()):get_size("main")
|
|
|
|
local idx
|
|
|
|
return function()
|
|
|
|
if not idx then
|
|
|
|
idx = 0
|
|
|
|
return widx
|
|
|
|
end
|
|
|
|
idx = idx + 1
|
|
|
|
if idx == widx then idx = idx + 1 end
|
|
|
|
if idx <= size then return idx end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
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 invidx(player, inv. widx) 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
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if dirty then
|
|
|
|
for i = 1, #excess do
|
|
|
|
local v = excess[i]
|
2019-03-27 22:42:28 -04:00
|
|
|
for j in invidx(player, inv, widx) do
|
|
|
|
if not snap[j]:is_empty() then
|
|
|
|
v = snap[j]:add_item(v)
|
|
|
|
end
|
|
|
|
end
|
2019-03-27 22:10:45 -04:00
|
|
|
for j in invidx(player, inv, widx) 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)
|