diff --git a/README.md b/README.md index 9f11998..4bfde4f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Bags for VoxeLibre +# Bags for VoxeLibre To many items? Put them in a bag! This mode ads bags - items with chest-like inventory. @@ -7,7 +7,8 @@ Right click with it in hand to open its contents. Roadmap: [x] Retains content on closure [x] Retains content on craft (upgrade) -[ ] Unload content on sneak right click on chest +[x] Unload content on sneak right click on chest +[ ] Color bags to distinguish from each other [ ] Implement upgrade system [ ] Upgrade to retain bag on death [ ] Upgrade to expand bag inventory width diff --git a/init.lua b/init.lua index 9074a33..6816991 100644 --- a/init.lua +++ b/init.lua @@ -1,4 +1,5 @@ local S = minetest.get_translator(minetest.get_current_modname()) +local INV_SUFIX = "_bag_tmp" local function getBagSize(stack) if not stack:get_definition().groups.bag_size then @@ -8,22 +9,16 @@ local function getBagSize(stack) return stack:get_definition().groups.bag_size end -local function openBag( - player, - player_name, - bag_stack, - context --[[opened equipped or inhand]] -) - --minetest.chat_send_all("Enter") - local inv_name = player_name .. "_bag_tmp" +local function create_detached_inventory(player_name, bag_stack) + local inv_name = player_name .. INV_SUFIX --Chaeck if something is broken. To prevent item voiding local inv = minetest.get_inventory({ type = "detached", name = inv_name }) if inv ~= nil then minetest.chat_send_all("Bag is already open!") - return false, "Bag is already open!" + return nil end - minetest.create_detached_inventory(player_name .. "_bag_tmp", { + minetest.create_detached_inventory(inv_name, { --Forbids puting bags into bags allow_put = function(inv, listname, index, stack, player) if minetest.get_item_group(stack:get_name(), "bag_size") > 0 then @@ -48,6 +43,21 @@ local function openBag( end]] end + return inv_name +end + +local function openBag( + player, + player_name, + bag_stack, + context --[[opened equipped or inhand]] +) + --minetest.chat_send_all("Enter") + local inv_name = create_detached_inventory(player_name, bag_stack) + if inv_name == nil then + return + end + local form = "size[9," .. (getBagSize(bag_stack) + 6) .. "]" @@ -73,38 +83,42 @@ local function openBag( minetest.show_formspec(player_name, "bag:" .. context, form) end +local function close_wielded_bag(player) + local bag_stack = player:get_wielded_item() + local inv_name = player:get_player_name() .. INV_SUFIX + local inv = minetest.get_inventory({ type = "detached", name = inv_name }) + + local stacks = {} + for i = 0, inv:get_size("main"), 1 do + stacks[i] = inv:get_stack("main", i):to_string() + end + + bag_stack:get_meta():set_string("bag:content", minetest.serialize(stacks)) + player:set_wielded_item(bag_stack) + minetest.remove_detached_inventory(inv_name) +end + minetest.register_on_player_receive_fields(function(player, formname, fields) --[[ Support for special "bag" slot at player gear. if formname == "bag:equipped" and fields.quit then --minetest.chat_send_all("Exit") local player_inv = player:get_inventory() local bag_stack = player_inv:get_stack("bag", 1) - + local inv_name = player:get_player_name() .. "_bag_tmp" local inv = minetest.get_inventory({ type = "detached", name = inv_name }) local stacks = {} for i = 0, inv:get_size("main"), 1 do stacks[i] = inv:get_stack("main", i):to_string() end - + bag_stack:get_meta():set_string("bag:content", minetest.serialize(stacks)) player_inv:set_stack("backpack", 1, backapack_stack) --minetest.chat_send_all(dump(meta:to_table())) minetest.remove_detached_inventory(inv_name) else]] if formname == "bag:inhand" and fields.quit then - local bag_stack = player:get_wielded_item() - local inv_name = player:get_player_name() .. "_bag_tmp" - local inv = minetest.get_inventory({ type = "detached", name = inv_name }) - - local stacks = {} - for i = 0, inv:get_size("main"), 1 do - stacks[i] = inv:get_stack("main", i):to_string() - end - - bag_stack:get_meta():set_string("bag:content", minetest.serialize(stacks)) - player:set_wielded_item(bag_stack) - minetest.remove_detached_inventory(inv_name) + close_wielded_bag(player) end end) @@ -115,14 +129,14 @@ minetest.register_allow_player_inventory_action(function(player, action, invento and inventory_info.from_list == "main" and inventory_info.from_index == player:get_wield_index() then - local bag_inv = minetest.get_inventory({ type = "detached", name = player:get_player_name() .. "_bag_tmp" }) + local bag_inv = minetest.get_inventory({ type = "detached", name = player:get_player_name() .. INV_SUFIX }) if bag_inv ~= nil then return 0 end end if action == "take" and inventory_info.listname == "main" and inventory_info.index == player:get_wield_index() then - local bag_inv = minetest.get_inventory({ type = "detached", name = player:get_player_name() .. "_bag_tmp" }) + local bag_inv = minetest.get_inventory({ type = "detached", name = player:get_player_name() .. INV_SUFIX }) if bag_inv ~= nil then return 0 end @@ -139,7 +153,7 @@ minetest.register_chatcommand("bag", { if backapack_stack:is_empty() then return false, "No backpack equiped!" end - + openBackpack(player, player_name, backapack_stack, "equipped") return true, "" end, @@ -157,9 +171,61 @@ minetest.register_allow_player_inventory_action(function(player, action, invento end) ]] +local function try_get_destination(node_def, node_pos, user, source_inv, source_list) + local dst_list = "main" + local dst_inv, stack_id + if node_def._mcl_hoppers_on_try_push then + dst_inv, dst_list, stack_id = + node_def._mcl_hoppers_on_try_push(node_pos, user:get_pos(), source_inv, source_list) + else + local dst_meta = minetest.get_meta(node_pos) + dst_inv = dst_meta:get_inventory() + stack_id = mcl_util.select_stack(source_inv, source_list, dst_inv, dst_list, nil, 1) + end + return dst_inv, dst_list, stack_id +end + local function on_bag_place(itemstack, user, pointed_thing) - openBag(user, user:get_player_name(), itemstack, "inhand") - return nil + if pointed_thing.type == "node" then + local node_pos = pointed_thing.under + local node = minetest.get_node(node_pos) + local def = minetest.registered_nodes[node.name] + + if user and user:get_player_control().sneak + --and minetest.get_item_group(pointed_thing.name, "container") == 2 + then + local inv_name = create_detached_inventory(user:get_player_name(), itemstack) + if inv_name == nil then + return + end + local inv = minetest.get_inventory({ type = "detached", name = inv_name }) + local dst_inv, dst_list, stack_id + dst_inv, dst_list, stack_id = try_get_destination(def, node_pos, user, inv, "main") + minetest.chat_send_all(stack_id) + while stack_id do + mcl_util.move_item(inv, "main", stack_id, dst_inv, dst_list) + dst_inv, dst_list, stack_id = try_get_destination(def, node_pos, user, inv, "main") + end + close_wielded_bag(user) + elseif def and def.on_rightclick then + -- Call node's on_rightclick method if defined + def.on_rightclick(node_pos, node, user) + else + openBag(user, user:get_player_name(), itemstack, "inhand") + end + elseif pointed_thing.type == "object" then + local object = pointed_thing.ref + local entity_def = object:get_luaentity() + + if entity_def and entity_def.on_rightclick then + -- Call object's on_rightclick method if defined + entity_def.on_rightclick(entity_def, user) + else + openBag(user, user:get_player_name(), itemstack, "inhand") + end + else + openBag(user, user:get_player_name(), itemstack, "inhand") + end end -- register backapack's @@ -171,7 +237,7 @@ minetest.register_tool("cm_bags:leather", { on_secondary_use = on_bag_place, }) -minetest.register_craftitem("cm_bags:iron", { +minetest.register_tool("cm_bags:iron", { description = S("Iron bag"), inventory_image = "bag_iron.png", groups = { bag_size = 2 }, @@ -179,7 +245,7 @@ minetest.register_craftitem("cm_bags:iron", { on_secondary_use = on_bag_place, }) -minetest.register_craftitem("cm_bags:gold", { +minetest.register_tool("cm_bags:gold", { description = S("Gold bag"), inventory_image = "bag_gold.png", groups = { bag_size = 3 }, @@ -187,7 +253,7 @@ minetest.register_craftitem("cm_bags:gold", { on_secondary_use = on_bag_place, }) -minetest.register_craftitem("cm_bags:diamond", { +minetest.register_tool("cm_bags:diamond", { description = S("Diamond bag"), inventory_image = "bag_diamond.png", groups = { bag_size = 4 }, diff --git a/mod.conf b/mod.conf index db8032b..5ff8f8a 100644 --- a/mod.conf +++ b/mod.conf @@ -1,4 +1,5 @@ name = cm_bags +title = Bags author = Morik666 description = Mode to add bags depends = mcl_core, mcl_formspec, mcl_mobitems, mcl_chests