From c43074f5c27d982199860aad0eb69b01ae2d33aa Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Thu, 21 Jun 2018 21:23:21 +0200 Subject: [PATCH 1/2] 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 --- bags.lua | 139 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 98 insertions(+), 41 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 + if new_slots >= old_slots then + return 1 + end - 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 + -- 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 From edd00f222c02f2e0f42f0c9bf52de74c41bf12b9 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Sat, 23 Jun 2018 14:56:27 +0200 Subject: [PATCH 2/2] Replace deprecated function names, unify creative check --- api.lua | 2 +- init.lua | 8 ++++---- register.lua | 6 ++++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/api.lua b/api.lua index 2b63922..42fc167 100644 --- a/api.lua +++ b/api.lua @@ -303,6 +303,6 @@ end function unified_inventory.is_creative(playername) return minetest.check_player_privs(playername, {creative=true}) - or minetest.setting_getbool("creative_mode") + or minetest.settings:get_bool("creative_mode") end diff --git a/init.lua b/init.lua index 6929600..f76acb8 100644 --- a/init.lua +++ b/init.lua @@ -1,4 +1,4 @@ --- Unified Inventory for Minetest 0.4.8+ +-- Unified Inventory for Minetest >= 0.4.16 local modpath = minetest.get_modpath(minetest.get_current_modname()) local worldpath = minetest.get_worldpath() @@ -44,10 +44,10 @@ unified_inventory = { fgettext = function(...) return minetest.formspec_escape(mygettext(...)) end, -- "Lite" mode - lite_mode = minetest.setting_getbool("unified_inventory_lite"), + lite_mode = minetest.settings:get_bool("unified_inventory_lite"), -- Trash enabled - trash_enabled = (minetest.setting_getbool("unified_inventory_trash") ~= false), + trash_enabled = (minetest.settings:get_bool("unified_inventory_trash") ~= false), pagecols = 8, pagerows = 10, @@ -80,7 +80,7 @@ dofile(modpath.."/internal.lua") dofile(modpath.."/callbacks.lua") dofile(modpath.."/register.lua") -if minetest.setting_getbool("unified_inventory_bags") ~= false then +if minetest.settings:get_bool("unified_inventory_bags") ~= false then dofile(modpath.."/bags.lua") end diff --git a/register.lua b/register.lua index bd6a13b..a1901e7 100644 --- a/register.lua +++ b/register.lua @@ -290,6 +290,8 @@ unified_inventory.register_page("craftguide", { alternates = #crafts craft = crafts[alternate] end + local has_creative = player_privs.give or player_privs.creative or + minetest.settings:get_bool("creative_mode") formspec = formspec.."background[0.5,"..(formspecy + 0.2)..";8,3;ui_craftguide_form.png]" formspec = formspec.."textarea["..craftresultx..","..craftresulty @@ -305,7 +307,7 @@ unified_inventory.register_page("craftguide", { formspec = formspec.."image["..no_pos..","..formspecy..";1.1,1.1;ui_no.png]" formspec = formspec..stack_image_button(item_pos, formspecy, 1.1, 1.1, "item_button_" ..other_dir[dir].."_", ItemStack(item_name)) - if player_privs.give == true or player_privs.creative == true or minetest.setting_getbool("creative_mode") == true then + if has_creative then formspec = formspec.."label[0,"..(formspecy + 2.10)..";" .. F("Give me:") .. "]" .."button[0, "..(formspecy + 2.7)..";0.6,0.5;craftguide_giveme_1;1]" .."button[0.6,"..(formspecy + 2.7)..";0.7,0.5;craftguide_giveme_10;10]" @@ -382,7 +384,7 @@ unified_inventory.register_page("craftguide", { .."button[0.6,"..(formspecy + 1.5)..";0.7,0.5;craftguide_craft_10;10]" .."button[1.3,"..(formspecy + 1.5)..";0.8,0.5;craftguide_craft_max;" .. F("All") .. "]" end - if player_privs.give == true or player_privs.creative == true or minetest.setting_getbool("creative_mode") == true then + if has_creative then formspec = formspec.."label[0,"..(formspecy + 2.1)..";" .. F("Give me:") .. "]" .."button[0, "..(formspecy + 2.7)..";0.6,0.5;craftguide_giveme_1;1]" .."button[0.6,"..(formspecy + 2.7)..";0.7,0.5;craftguide_giveme_10;10]"