summaryrefslogtreecommitdiff
path: root/bags.lua
diff options
context:
space:
mode:
authorSmallJoker <SmallJoker@users.noreply.github.com>2018-06-21 21:23:21 +0200
committerGitHub <noreply@github.com>2018-06-21 21:23:21 +0200
commitc43074f5c27d982199860aad0eb69b01ae2d33aa (patch)
treef4988676ec5f6c07ae8bdef21e14d7cc2be75ef2 /bags.lua
parent2ab5a7c90a59db14c60bdb07d306eac89987e9f5 (diff)
Move bag storage to player attributes
Compatible with 0.4.16 or later Fixes an item duplication bug for the four player inventory slots on each join Clean up old player lists after saving
Diffstat (limited to 'bags.lua')
-rw-r--r--bags.lua141
1 files changed, 99 insertions, 42 deletions
diff --git a/bags.lua b/bags.lua
index 6d0842f..e93a317 100644
--- a/bags.lua
+++ b/bags.lua
@@ -31,11 +31,18 @@ unified_inventory.register_button("bags", {
hide_lite=true
})
+local function get_player_bag_stack(player, i)
+ return minetest.get_inventory({
+ type = "detached",
+ name = player:get_player_name() .. "_bags"
+ }):get_stack("bag" .. i, 1)
+end
+
for i = 1, 4 do
local bi = i
unified_inventory.register_page("bag"..bi, {
get_formspec = function(player)
- local stack = player:get_inventory():get_stack("bag"..bi, 1)
+ local stack = get_player_bag_stack(player, bi)
local image = stack:get_definition().inventory_image
local formspec = ("image[7,0;1,1;"..image.."]"
.."label[0,0;"..F("Bag @1", bi).."]"
@@ -58,7 +65,7 @@ for i = 1, 4 do
end
local inv = player:get_inventory()
for i = 1, 4 do
- local def = inv:get_stack("bag"..i, 1):get_definition()
+ local def = get_player_bag_stack(player, i):get_definition()
local button
if def.groups.bagslots then
local list_name = "bag"..i.."contents"
@@ -89,7 +96,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end
for i = 1, 4 do
if fields["bag"..i] then
- local stack = player:get_inventory():get_stack("bag"..i, 1)
+ local stack = get_player_bag_stack(player, i)
if not stack:get_definition().groups.bagslots then
return
end
@@ -99,67 +106,117 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end
end)
+local function save_bags_metadata(player, bags_inv)
+ local is_empty = true
+ local bags = {}
+ for i = 1, 4 do
+ local bag = "bag"..i
+ if not bags_inv:is_empty(bag) then
+ -- Stack limit is 1, otherwise use stack:to_string()
+ bags[i] = bags_inv:get_stack(bag, 1):get_name()
+ is_empty = false
+ end
+ end
+ if is_empty then
+ player:set_attribute("unified_inventory:bags", nil)
+ else
+ player:set_attribute("unified_inventory:bags",
+ minetest.serialize(bags))
+ end
+end
+
+local function load_bags_metadata(player, bags_inv)
+ local player_inv = player:get_inventory()
+ local bags_meta = player:get_attribute("unified_inventory:bags")
+ local bags = bags_meta and minetest.deserialize(bags_meta) or {}
+ local dirty_meta = false
+ if not bags_meta then
+ -- Backwards compatiblity
+ for i = 1, 4 do
+ local bag = "bag"..i
+ if not player_inv:is_empty(bag) then
+ -- Stack limit is 1, otherwise use stack:to_string()
+ bags[i] = player_inv:get_stack(bag, 1):get_name()
+ dirty_meta = true
+ end
+ end
+ end
+ -- Fill detached slots
+ for i = 1, 4 do
+ local bag = "bag"..i
+ bags_inv:set_size(bag, 1)
+ bags_inv:set_stack(bag, 1, bags[i] or "")
+ end
+
+ if dirty_meta then
+ -- Requires detached inventory to be set up
+ save_bags_metadata(player, bags_inv)
+ end
+
+ -- Clean up deprecated garbage after saving
+ for i = 1, 4 do
+ local bag = "bag"..i
+ player_inv:set_size(bag, 0)
+ end
+end
+
minetest.register_on_joinplayer(function(player)
local player_inv = player:get_inventory()
local player_name = player:get_player_name()
local bags_inv = minetest.create_detached_inventory(player_name.."_bags",{
on_put = function(inv, listname, index, stack, player)
- player:get_inventory():set_stack(listname, index, stack)
player:get_inventory():set_size(listname.."contents",
stack:get_definition().groups.bagslots)
- end,
- on_take = function(inv, listname, index, stack, player)
- player:get_inventory():set_stack(listname, index, nil)
+ save_bags_metadata(player, inv)
end,
allow_put = function(inv, listname, index, stack, player)
local new_slots = stack:get_definition().groups.bagslots
- if new_slots then
- local player_inv = player:get_inventory()
- local old_slots = player_inv:get_size(listname.."contents")
+ if not new_slots then
+ return 0
+ end
+ local player_inv = player:get_inventory()
+ local old_slots = player_inv:get_size(listname.."contents")
- if new_slots >= old_slots then
- return 1
- else
- -- using a smaller bag, make sure it fits
- local old_list = player_inv:get_list(listname.."contents")
- local new_list = {}
- local slots_used = 0
- local use_new_list = false
-
- for i, v in ipairs(old_list) do
- if v and not v:is_empty() then
- slots_used = slots_used + 1
- use_new_list = i > new_slots
- new_list[slots_used] = v
- end
- end
- if new_slots >= slots_used then
- if use_new_list then
- player_inv:set_list(listname.."contents", new_list)
- end
- return 1
- end
+ if new_slots >= old_slots then
+ return 1
+ end
+
+ -- using a smaller bag, make sure it fits
+ local old_list = player_inv:get_list(listname.."contents")
+ local new_list = {}
+ local slots_used = 0
+ local use_new_list = false
+
+ for i, v in ipairs(old_list) do
+ if v and not v:is_empty() then
+ slots_used = slots_used + 1
+ use_new_list = i > new_slots
+ new_list[slots_used] = v
end
end
- return 0
+ if new_slots >= slots_used then
+ if use_new_list then
+ player_inv:set_list(listname.."contents", new_list)
+ end
+ return 1
+ end
end,
allow_take = function(inv, listname, index, stack, player)
if player:get_inventory():is_empty(listname.."contents") then
return stack:get_count()
- else
- return 0
end
+ return 0
end,
- allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
+ on_take = function(inv, listname, index, stack, player)
+ player:get_inventory():set_size(listname.."contents", 0)
+ save_bags_metadata(player, inv)
+ end,
+ allow_move = function()
return 0
end,
}, player_name)
- for i=1,4 do
- local bag = "bag"..i
- player_inv:set_size(bag, 1)
- bags_inv:set_size(bag, 1)
- bags_inv:set_stack(bag, 1, player_inv:get_stack(bag, 1))
- end
+
+ load_bags_metadata(player, bags_inv)
end)
-- register bag tools