minetest-i4/src/bags.lua
2021-11-15 00:09:06 +01:00

201 lines
4.2 KiB
Lua

local S, ES, fmt, clr, msg, slz, dslz = i3.get("S", "ES", "fmt", "clr", "msg", "slz", "dslz")
local play_sound, create_inventory = i3.get("play_sound", "create_inventory")
local function get_content_inv(name)
return core.get_inventory {
type = "detached",
name = fmt("i3_bag_content_%s", name)
}
end
local function get_content(content)
local t = {}
for i, v in pairs(content) do
local stack = ItemStack(v.name)
if v.meta then
local m = stack:get_meta()
m:from_table(v.meta)
end
if v.wear then
stack:set_wear(v.wear)
end
t[i] = stack
end
return t
end
local function safe_format(stack)
local meta = stack:get_meta():to_table()
local wear = stack:get_wear()
local has_meta = next(meta.fields)
local info = {}
info.name = fmt("%s %u", stack:get_name(), stack:get_count())
if has_meta then
info.meta = meta
end
if wear > 0 then
info.wear = wear
end
return info
end
local function init_bags(player)
local name = player:get_player_name()
local data = i3.data[name]
local bag = create_inventory(fmt("i3_bag_%s", name), {
allow_put = function(inv, _, _, stack)
local empty = inv:is_empty"main"
local item_group = core.get_item_group(stack:get_name(), "bag")
if empty and item_group > 0 and item_group <= 4 then
return 1
end
if not empty then
msg(name, S"There is already a bag")
else
msg(name, S"This is not a bag")
end
return 0, play_sound(name, "i3_cannot", 0.8)
end,
on_put = function(_, _, _, stack)
data.bag_item = safe_format(stack)
data.bag_size = core.get_item_group(stack:get_name(), "bag")
local meta = stack:get_meta()
local content = dslz(meta:get_string"content")
if content then
local inv = get_content_inv(name)
inv:set_list("main", get_content(content))
end
i3.set_fs(player)
end,
on_take = function()
data.bag_item = nil
data.bag_size = nil
local content = get_content_inv(name)
content:set_list("main", {})
i3.set_fs(player)
end,
}, name)
bag:set_size("main", 1)
if data.bag_item then
bag:set_list("main", get_content{data.bag_item})
end
local function save_content(inv)
local bagstack = bag:get_stack("main", 1)
local meta = bagstack:get_meta()
if inv:is_empty("main") then
meta:set_string("description", "")
meta:set_string("content", "")
else
local list = inv:get_list"main"
local t = {}
for i = 1, #list do
local stack = list[i]
if not stack:is_empty() then
t[i] = safe_format(stack)
end
end
local function count_items()
local c = 0
for _ in pairs(t) do
c = c + 1
end
return c
end
meta:set_string("description", "")
meta:set_string("description", ES("@1 (contains @2 / @3 stacks)",
bagstack:get_short_description(), clr("#ff0", count_items()), data.bag_size * 4))
meta:set_string("content", slz(t))
end
bag:set_stack("main", 1, bagstack)
data.bag_item = safe_format(bagstack)
i3.set_fs(player)
end
local bag_content = create_inventory(fmt("i3_bag_content_%s", name), {
on_move = save_content,
on_put = save_content,
on_take = save_content,
}, name)
bag_content:set_size("main", 4*4)
if data.bag_item then
local meta = bag:get_stack("main", 1):get_meta()
local content = dslz(meta:get_string"content") or {}
bag_content:set_list("main", get_content(content))
end
end
local bag_recipes = {
small = {
rcp = {
{"", "farming:string", ""},
{"group:wool", "group:wool", "group:wool"},
{"group:wool", "group:wool", "group:wool"},
},
size = 2,
},
medium = {
rcp = {
{"farming:string", "i3:bag_small", "farming:string"},
{"farming:string", "i3:bag_small", "farming:string"},
},
size = 3,
},
large = {
rcp = {
{"farming:string", "i3:bag_medium", "farming:string"},
{"farming:string", "i3:bag_medium", "farming:string"},
},
size = 4,
},
}
for size, item in pairs(bag_recipes) do
local bagname = fmt("i3:bag_%s", size)
core.register_craftitem(bagname, {
description = fmt("%s Backpack", size:gsub("^%l", string.upper)),
inventory_image = fmt("i3_bag_%s.png", size),
groups = {bag = item.size},
stack_max = 1,
})
core.register_craft{output = bagname, recipe = item.rcp}
core.register_craft{type = "fuel", recipe = bagname, burntime = 3}
end
return init_bags