Unloading implementation

This commit is contained in:
Kostiantyn 2024-10-08 22:28:24 +03:00
parent 15d8e0c6c8
commit c4d8817b4c
3 changed files with 102 additions and 34 deletions

View File

@ -1,4 +1,4 @@
# Bags for VoxeLibre # Bags for VoxeLibre
To many items? Put them in a bag! To many items? Put them in a bag!
This mode ads bags - items with chest-like inventory. This mode ads bags - items with chest-like inventory.
@ -7,7 +7,8 @@ Right click with it in hand to open its contents.
Roadmap: Roadmap:
[x] Retains content on closure [x] Retains content on closure
[x] Retains content on craft (upgrade) [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 [ ] Implement upgrade system
[ ] Upgrade to retain bag on death [ ] Upgrade to retain bag on death
[ ] Upgrade to expand bag inventory width [ ] Upgrade to expand bag inventory width

130
init.lua
View File

@ -1,4 +1,5 @@
local S = minetest.get_translator(minetest.get_current_modname()) local S = minetest.get_translator(minetest.get_current_modname())
local INV_SUFIX = "_bag_tmp"
local function getBagSize(stack) local function getBagSize(stack)
if not stack:get_definition().groups.bag_size then if not stack:get_definition().groups.bag_size then
@ -8,22 +9,16 @@ local function getBagSize(stack)
return stack:get_definition().groups.bag_size return stack:get_definition().groups.bag_size
end end
local function openBag( local function create_detached_inventory(player_name, bag_stack)
player, local inv_name = player_name .. INV_SUFIX
player_name,
bag_stack,
context --[[opened equipped or inhand]]
)
--minetest.chat_send_all("Enter")
local inv_name = player_name .. "_bag_tmp"
--Chaeck if something is broken. To prevent item voiding --Chaeck if something is broken. To prevent item voiding
local inv = minetest.get_inventory({ type = "detached", name = inv_name }) local inv = minetest.get_inventory({ type = "detached", name = inv_name })
if inv ~= nil then if inv ~= nil then
minetest.chat_send_all("Bag is already open!") minetest.chat_send_all("Bag is already open!")
return false, "Bag is already open!" return nil
end end
minetest.create_detached_inventory(player_name .. "_bag_tmp", { minetest.create_detached_inventory(inv_name, {
--Forbids puting bags into bags --Forbids puting bags into bags
allow_put = function(inv, listname, index, stack, player) allow_put = function(inv, listname, index, stack, player)
if minetest.get_item_group(stack:get_name(), "bag_size") > 0 then if minetest.get_item_group(stack:get_name(), "bag_size") > 0 then
@ -48,6 +43,21 @@ local function openBag(
end]] end]]
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," local form = "size[9,"
.. (getBagSize(bag_stack) + 6) .. (getBagSize(bag_stack) + 6)
.. "]" .. "]"
@ -73,38 +83,42 @@ local function openBag(
minetest.show_formspec(player_name, "bag:" .. context, form) minetest.show_formspec(player_name, "bag:" .. context, form)
end 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) minetest.register_on_player_receive_fields(function(player, formname, fields)
--[[ Support for special "bag" slot at player gear. --[[ Support for special "bag" slot at player gear.
if formname == "bag:equipped" and fields.quit then if formname == "bag:equipped" and fields.quit then
--minetest.chat_send_all("Exit") --minetest.chat_send_all("Exit")
local player_inv = player:get_inventory() local player_inv = player:get_inventory()
local bag_stack = player_inv:get_stack("bag", 1) local bag_stack = player_inv:get_stack("bag", 1)
local inv_name = player:get_player_name() .. "_bag_tmp" local inv_name = player:get_player_name() .. "_bag_tmp"
local inv = minetest.get_inventory({ type = "detached", name = inv_name }) local inv = minetest.get_inventory({ type = "detached", name = inv_name })
local stacks = {} local stacks = {}
for i = 0, inv:get_size("main"), 1 do for i = 0, inv:get_size("main"), 1 do
stacks[i] = inv:get_stack("main", i):to_string() stacks[i] = inv:get_stack("main", i):to_string()
end end
bag_stack:get_meta():set_string("bag:content", minetest.serialize(stacks)) bag_stack:get_meta():set_string("bag:content", minetest.serialize(stacks))
player_inv:set_stack("backpack", 1, backapack_stack) player_inv:set_stack("backpack", 1, backapack_stack)
--minetest.chat_send_all(dump(meta:to_table())) --minetest.chat_send_all(dump(meta:to_table()))
minetest.remove_detached_inventory(inv_name) minetest.remove_detached_inventory(inv_name)
else]] else]]
if formname == "bag:inhand" and fields.quit then if formname == "bag:inhand" and fields.quit then
local bag_stack = player:get_wielded_item() close_wielded_bag(player)
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)
end end
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_list == "main"
and inventory_info.from_index == player:get_wield_index() and inventory_info.from_index == player:get_wield_index()
then 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 if bag_inv ~= nil then
return 0 return 0
end end
end end
if action == "take" and inventory_info.listname == "main" and inventory_info.index == player:get_wield_index() then 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 if bag_inv ~= nil then
return 0 return 0
end end
@ -139,7 +153,7 @@ minetest.register_chatcommand("bag", {
if backapack_stack:is_empty() then if backapack_stack:is_empty() then
return false, "No backpack equiped!" return false, "No backpack equiped!"
end end
openBackpack(player, player_name, backapack_stack, "equipped") openBackpack(player, player_name, backapack_stack, "equipped")
return true, "" return true, ""
end, end,
@ -157,9 +171,61 @@ minetest.register_allow_player_inventory_action(function(player, action, invento
end) 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) local function on_bag_place(itemstack, user, pointed_thing)
openBag(user, user:get_player_name(), itemstack, "inhand") if pointed_thing.type == "node" then
return nil 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 end
-- register backapack's -- register backapack's
@ -171,7 +237,7 @@ minetest.register_tool("cm_bags:leather", {
on_secondary_use = on_bag_place, on_secondary_use = on_bag_place,
}) })
minetest.register_craftitem("cm_bags:iron", { minetest.register_tool("cm_bags:iron", {
description = S("Iron bag"), description = S("Iron bag"),
inventory_image = "bag_iron.png", inventory_image = "bag_iron.png",
groups = { bag_size = 2 }, groups = { bag_size = 2 },
@ -179,7 +245,7 @@ minetest.register_craftitem("cm_bags:iron", {
on_secondary_use = on_bag_place, on_secondary_use = on_bag_place,
}) })
minetest.register_craftitem("cm_bags:gold", { minetest.register_tool("cm_bags:gold", {
description = S("Gold bag"), description = S("Gold bag"),
inventory_image = "bag_gold.png", inventory_image = "bag_gold.png",
groups = { bag_size = 3 }, groups = { bag_size = 3 },
@ -187,7 +253,7 @@ minetest.register_craftitem("cm_bags:gold", {
on_secondary_use = on_bag_place, on_secondary_use = on_bag_place,
}) })
minetest.register_craftitem("cm_bags:diamond", { minetest.register_tool("cm_bags:diamond", {
description = S("Diamond bag"), description = S("Diamond bag"),
inventory_image = "bag_diamond.png", inventory_image = "bag_diamond.png",
groups = { bag_size = 4 }, groups = { bag_size = 4 },

View File

@ -1,4 +1,5 @@
name = cm_bags name = cm_bags
title = Bags
author = Morik666 author = Morik666
description = Mode to add bags description = Mode to add bags
depends = mcl_core, mcl_formspec, mcl_mobitems, mcl_chests depends = mcl_core, mcl_formspec, mcl_mobitems, mcl_chests