From 2e7dcd714d41c89a23036b6d5ff5ea5abe3d05d7 Mon Sep 17 00:00:00 2001 From: Jean-Patrick Guerrero Date: Sun, 14 Nov 2021 21:39:48 +0100 Subject: [PATCH] Totally rework how bags work + other cool stuff --- API.md | 9 +- README.md | 18 ++- init.lua | 30 ++--- sounds/i3_cannot.ogg | Bin 0 -> 28026 bytes src/api.lua | 45 +++---- src/bags.lua | 176 +++++++++++++++++++++------ src/{inventory.lua => callbacks.lua} | 117 +++--------------- src/common.lua | 68 +++++++++-- src/detached_inv.lua | 32 +++++ src/gui.lua | 91 ++++++++------ src/styles.lua | 5 +- tests/test_tabs.lua | 16 +-- textures/i3_arrow_content.png | Bin 0 -> 7590 bytes textures/i3_bg_content.png | Bin 0 -> 26240 bytes textures/i3_blank.png | Bin 0 -> 527 bytes 15 files changed, 366 insertions(+), 241 deletions(-) create mode 100644 sounds/i3_cannot.ogg rename src/{inventory.lua => callbacks.lua} (77%) create mode 100644 src/detached_inv.lua create mode 100644 textures/i3_arrow_content.png create mode 100644 textures/i3_bg_content.png create mode 100644 textures/i3_blank.png diff --git a/API.md b/API.md index a3fc9bd..0b0f95a 100644 --- a/API.md +++ b/API.md @@ -7,8 +7,7 @@ Custom tabs can be added to the `i3` inventory as follow (example): ```Lua -i3.new_tab { - name = "stuff", +i3.new_tab("stuff", { description = "Stuff", image = "image.png", -- Optional, adds an image next to the tab description @@ -28,16 +27,16 @@ i3.new_tab { fields = function(player, data, fields) end, -} +}) ``` - `player` is an `ObjectRef` to the user. - `data` are the user data. - `fs` is the formspec table which is callable with a metamethod. Each call adds a new entry. -#### `i3.set_fs(player[, extra_formspec])` +#### `i3.set_fs(player)` -Updates the current formspec. `extra_formspec` adds an additional formspec string. +Updates the current formspec. #### `i3.remove_tab(tabname)` diff --git a/README.md b/README.md index 7275178..293d6cb 100644 --- a/README.md +++ b/README.md @@ -10,20 +10,20 @@ This mod features a modern, powerful inventory menu with a good user experience. This mod requires **Minetest 5.4+** #### List of features: - - Crafting Guide (only in survival mode) + - Crafting Guide (survival mode only) - Progressive Mode¹ - Quick Crafting - - Backpacks - - 3D Player Model Preview - - Inventory Sorting (with optional compression) + - 3D Player Model Real-Time Preview + - Inventory Sorting (+ options: compression, reverse mode, automation, etc.) + - Item List Compression (**`moreblocks`** is supported) - Item Bookmarks - Waypoints - - Item List Compression (**`moreblocks`** is supported) + - Bags + - Home **¹** *This mode is a Terraria-like system that shows recipes you can craft from items you ever had in your inventory. To enable it: `i3_progressive_mode = true` in `minetest.conf`.* - #### This mod officially supports the following mods: - [**`3d_armor`**](https://content.minetest.net/packages/stu/3d_armor/) - [**`skinsdb`**](https://content.minetest.net/packages/bell07/skinsdb/) @@ -46,12 +46,10 @@ value of the setting `display_density_factor` in your `minetest.conf`. Note that `i3` uses a larger inventory than the usual inventories in Minetest games. Thus, most chests will be unadapted to this inventory size. -The `i3` inventory is 9 slots wide by default (without backpack), such as Minecraft. +The `i3` inventory is 9 slots wide by default, such as Minecraft. -Report any bug on the [**Bug Tracker**](https://github.com/minetest-mods/i3/issues). +Report bugs on the [**Bug Tracker**](https://github.com/minetest-mods/i3/issues). Love this mod? Donations are appreciated: https://www.paypal.me/jpg84240 -Demo video (outdated): https://www.youtube.com/watch?v=25nCAaqeacU - ![Preview](https://user-images.githubusercontent.com/7883281/140816791-693a5c8a-a7d1-47d4-a45d-883cc008ae8a.png) diff --git a/init.lua b/init.lua index 5176231..633defc 100644 --- a/init.lua +++ b/init.lua @@ -15,13 +15,6 @@ i3 = { MIN_FORMSPEC_VERSION = 4, SAVE_INTERVAL = 600, -- Player data save interval (in seconds) - BAG_SIZES = { - 4*9 + 3, - 4*9 + 6, - 4*9 + 9, - 4*9 + 25, - }, - SUBCAT = { "bag", "armor", @@ -36,7 +29,7 @@ i3 = { bag_size = true, waypoints = true, inv_items = true, - reject_items = true, + drop_items = true, known_recipes = true, }, @@ -56,18 +49,19 @@ i3 = { files = { api = lf("/src/api.lua"), bags = lf("/src/bags.lua"), + callbacks = lf("/src/callbacks.lua"), common = lf("/src/common.lua"), compress = lf("/src/compress.lua"), + detached = lf("/src/detached_inv.lua"), groups = lf("/src/groups.lua"), gui = lf("/src/gui.lua"), - inventory = lf("/src/inventory.lua"), model_alias = lf("/src/model_aliases.lua"), progressive = lf("/src/progressive.lua"), recipes = lf("/src/recipes.lua"), styles = lf("/src/styles.lua"), }, - progressive_mode = core.settings:get_bool "i3_progressive_mode", + progressive_mode = core.settings:get_bool"i3_progressive_mode", item_compression = core.settings:get_bool("i3_item_compression", true), } @@ -75,14 +69,16 @@ i3.files.common() i3.files.api() i3.files.compress() i3.files.groups() -i3.files.inventory() +i3.files.callbacks() local storage = core.get_mod_storage() -local slz, dslz, str_to_pos, add_hud_waypoint = i3.get("slz", "dslz", "str_to_pos", "add_hud_waypoint") +local slz, dslz, ESC, str_to_pos, add_hud_waypoint = + i3.get("slz", "dslz", "ESC", "str_to_pos", "add_hud_waypoint") i3.data = dslz(storage:get_string "data") or {} -local init_backpack = i3.files.bags() +local init_bags = i3.files.bags() +local init_inventories = i3.files.detached() local init_recipes = i3.files.recipes() local function get_lang_code(info) @@ -146,6 +142,7 @@ local function init_data(player, info) i3.data[name] = i3.data[name] or {} local data = i3.data[name] + data.player_name = ESC(name) data.filter = "" data.pagenum = 1 data.items = i3.init_items @@ -165,6 +162,9 @@ local function init_data(player, info) data.lang_code = get_lang_code(info) data.fs_version = info.formspec_version + local inv = player:get_inventory() + inv:set_size("main", i3.INV_SIZE) + core.after(0, i3.set_fs, player) end @@ -216,12 +216,12 @@ core.register_on_joinplayer(function(player) local info = core.get_player_information and core.get_player_information(name) if not info or get_formspec_version(info) < i3.MIN_FORMSPEC_VERSION then - i3.data[name] = nil return outdated(name) end init_data(player, info) - init_backpack(player) + init_bags(player) + init_inventories(player) init_waypoints(player) init_hudbar(player) end) diff --git a/sounds/i3_cannot.ogg b/sounds/i3_cannot.ogg new file mode 100644 index 0000000000000000000000000000000000000000..8f97186a995d94b02dbb3e4dc7ddd44239417ae5 GIT binary patch literal 28026 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 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 inv = player:get_inventory() - inv:set_size("main", data.bag_size and i3.BAG_SIZES[data.bag_size] or i3.INV_SIZE) + 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") - data.bag = core.create_detached_inventory(fmt("%s_backpack", name), { - allow_put = function(_inv, listname, _, stack) - local empty = _inv:get_stack(listname, 1):is_empty() - local item_group = minetest.get_item_group(stack:get_name(), "bag") - - if empty and item_group > 0 and item_group <= #i3.BAG_SIZES then + if empty and item_group > 0 and item_group <= 4 then return 1 end - msg(name, S"This is not a backpack") - return 0 + 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) - local stackname = stack:get_name() - data.bag_item = stackname - data.bag_size = minetest.get_item_group(stackname, "bag") + 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 - inv:set_size("main", i3.BAG_SIZES[data.bag_size]) i3.set_fs(player) end, on_take = function() - for i = i3.INV_SIZE + 1, i3.BAG_SIZES[data.bag_size] do - local stack = inv:get_stack("main", i) - - if not stack:is_empty() then - spawn_item(player, stack) - end - end - data.bag_item = nil data.bag_size = nil - inv:set_size("main", i3.INV_SIZE) + local content = get_content_inv(name) + content:set_list("main", {}) + i3.set_fs(player) end, - }) + }, name) - data.bag:set_size("main", 1) + bag:set_size("main", 1) if data.bag_item then - data.bag:set_stack("main", 1, data.bag_item) + 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 @@ -60,21 +166,21 @@ local bag_recipes = { {"group:wool", "group:wool", "group:wool"}, {"group:wool", "group:wool", "group:wool"}, }, - size = 1, + size = 2, }, medium = { rcp = { {"farming:string", "i3:bag_small", "farming:string"}, {"farming:string", "i3:bag_small", "farming:string"}, }, - size = 2, + size = 3, }, large = { rcp = { {"farming:string", "i3:bag_medium", "farming:string"}, {"farming:string", "i3:bag_medium", "farming:string"}, }, - size = 3, + size = 4, }, } @@ -84,12 +190,12 @@ for size, item in pairs(bag_recipes) do 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, - groups = {bag = item.size} }) - core.register_craft {output = bagname, recipe = item.rcp} - core.register_craft {type = "fuel", recipe = bagname, burntime = 3} + core.register_craft{output = bagname, recipe = item.rcp} + core.register_craft{type = "fuel", recipe = bagname, burntime = 3} end -return init_backpack +return init_bags diff --git a/src/inventory.lua b/src/callbacks.lua similarity index 77% rename from src/inventory.lua rename to src/callbacks.lua index e597286..3bb34fd 100644 --- a/src/inventory.lua +++ b/src/callbacks.lua @@ -1,20 +1,18 @@ local _, get_inventory_fs = i3.files.gui() local S, clr = i3.get("S", "clr") -local min, ceil, random = i3.get("min", "ceil", "random") +local min, random = i3.get("min", "random") local reg_items, reg_aliases = i3.get("reg_items", "reg_aliases") local fmt, find, match, sub, lower, split = i3.get("fmt", "find", "match", "sub", "lower", "split") local vec_new, vec_eq, vec_round = i3.get("vec_new", "vec_eq", "vec_round") local sort, copy, insert, remove, indexof = i3.get("sort", "copy", "insert", "remove", "indexof") -local is_group, extract_groups, groups_to_items = - i3.get("is_group", "extract_groups", "groups_to_items") -local msg, is_fav, pos_to_str, str_to_pos, add_hud_waypoint = - i3.get("msg", "is_fav", "pos_to_str", "str_to_pos", "add_hud_waypoint") +local msg, is_fav, pos_to_str, str_to_pos, add_hud_waypoint, play_sound = + i3.get("msg", "is_fav", "pos_to_str", "str_to_pos", "add_hud_waypoint", "play_sound") local search, get_sorting_idx, sort_inventory, sort_by_category, get_recipes = i3.get("search", "get_sorting_idx", "sort_inventory", "sort_by_category", "get_recipes") -local show_item, get_stack, clean_name, compressible, check_privs, safe_teleport = - i3.get("show_item", "get_stack", "clean_name", "compressible", "check_privs", "safe_teleport") +local show_item, get_stack, craft_stack, clean_name, compressible, check_privs, safe_teleport = + i3.get("show_item", "get_stack", "craft_stack", "clean_name", "compressible", "check_privs", "safe_teleport") local function reset_data(data) data.filter = "" @@ -40,13 +38,12 @@ local function reset_data(data) end end -i3.new_tab { - name = "inventory", +i3.new_tab("inventory", { description = S"Inventory", formspec = get_inventory_fs, fields = function(player, data, fields) - local name = player:get_player_name() + local name = data.player_name local inv = player:get_inventory() local sb_inv = fields.scrbar_inv @@ -56,9 +53,9 @@ i3.new_tab { skins.set_player_skin(player, _skins[id]) end - if fields.reject_items then - local items = split(fields.reject_items, ",") - data.reject_items = items + if fields.drop_items then + local items = split(fields.drop_items, ",") + data.drop_items = items end for field in pairs(fields) do @@ -176,6 +173,7 @@ i3.new_tab { for _, v in ipairs(data.waypoints) do if vec_eq(vec_round(pos), vec_round(str_to_pos(v.pos))) then + play_sound(name, "i3_cannot", 0.8) return msg(name, "You already set a waypoint at this position") end end @@ -201,9 +199,9 @@ i3.new_tab { return i3.set_fs(player) end, -} +}) -local function select_item(player, name, data, _f) +local function select_item(player, data, _f) local item for field in pairs(_f) do @@ -271,7 +269,7 @@ local function select_item(player, name, data, _f) item = reg_aliases[item] or item if not reg_items[item] then return end - if core.is_creative_enabled(name) then + if core.is_creative_enabled(data.player_name) then local stack = ItemStack(item) local stackmax = stack:get_stack_max() stack = fmt("%s %s", item, stackmax) @@ -294,55 +292,7 @@ local function select_item(player, name, data, _f) end end -local function craft_stack(player, data, craft_rcp) - local inv = player:get_inventory() - local rcp_usg = craft_rcp and "recipe" or "usage" - local output = craft_rcp and data.recipes[data.rnum].output or data.usages[data.unum].output - output = ItemStack(output) - local stackname, stackcount, stackmax = output:get_name(), output:get_count(), output:get_stack_max() - local scrbar_val = data[fmt("scrbar_%s", craft_rcp and "rcp" or "usg")] or 1 - - for name, count in pairs(data.export_counts[rcp_usg].rcp) do - local items = {[name] = count} - - if is_group(name) then - items = {} - local groups = extract_groups(name) - local item_groups = groups_to_items(groups, true) - local remaining = count - - for _, item in ipairs(item_groups) do - for _name, _count in pairs(data.export_counts[rcp_usg].inv) do - if item == _name and remaining > 0 then - local c = min(remaining, _count) - items[item] = c - remaining = remaining - c - end - - if remaining == 0 then break end - end - end - end - - for k, v in pairs(items) do - inv:remove_item("main", fmt("%s %s", k, v * scrbar_val)) - end - end - - local count = stackcount * scrbar_val - local iter = ceil(count / stackmax) - local leftover = count - - for _ = 1, iter do - local c = min(stackmax, leftover) - local stack = ItemStack(fmt("%s %s", stackname, c)) - get_stack(player, stack) - leftover = leftover - stackmax - end -end - local function rcp_fields(player, data, fields) - local name = player:get_player_name() local sb_rcp, sb_usg = fields.scrbar_rcp, fields.scrbar_usg if fields.cancel then @@ -431,7 +381,7 @@ local function rcp_fields(player, data, fields) data.scrbar_usg = 1 end else - select_item(player, name, data, fields) + select_item(player, data, fields) end end @@ -439,11 +389,12 @@ core.register_on_player_receive_fields(function(player, formname, fields) local name = player:get_player_name() if formname == "i3_outdated" then - return false, core.kick_player(name, "Come back when your client is up-to-date.") + return false, core.kick_player(name, S"Come back when your client is up-to-date.") elseif formname ~= "" then return false end + --print(dump(fields)) local data = i3.data[name] if not data then return end @@ -456,6 +407,7 @@ core.register_on_player_receive_fields(function(player, formname, fields) data.pagenum = 1 data.itab = tonumber(f:sub(-1)) sort_by_category(data) + break end end @@ -486,15 +438,6 @@ core.register_on_dieplayer(function(player) local data = i3.data[name] if not data then return end - if data.bag_size then - data.bag_item = nil - data.bag_size = nil - data.bag:set_list("main", {}) - - local inv = player:get_inventory() - inv:set_size("main", i3.INV_SIZE) - end - i3.set_fs(player) end) @@ -524,27 +467,3 @@ core.register_on_player_inventory_action(function(player, _, _, info) i3.set_fs(player) end end) - -local trash = core.create_detached_inventory("i3_trash", { - allow_put = function(_, _, _, stack) - return stack:get_count() - end, - on_put = function(inv, listname, _, _, player) - inv:set_list(listname, {}) - - local name = player:get_player_name() - core.sound_play("i3_trash", {to_player = name, gain = 1.0}, true) - - if not core.is_creative_enabled(name) then - i3.set_fs(player) - end - end, -}) - -trash:set_size("main", 1) - -local output_rcp = core.create_detached_inventory("i3_output_rcp", {}) -output_rcp:set_size("main", 1) - -local output_usg = core.create_detached_inventory("i3_output_usg", {}) -output_usg:set_size("main", 1) diff --git a/src/common.lua b/src/common.lua index dad5e69..5ea32f0 100644 --- a/src/common.lua +++ b/src/common.lua @@ -349,9 +349,60 @@ local function get_stack(player, stack) end end +local function craft_stack(player, data, craft_rcp) + local inv = player:get_inventory() + local rcp_usg = craft_rcp and "recipe" or "usage" + local output = craft_rcp and data.recipes[data.rnum].output or data.usages[data.unum].output + output = ItemStack(output) + local stackname, stackcount, stackmax = output:get_name(), output:get_count(), output:get_stack_max() + local scrbar_val = data[fmt("scrbar_%s", craft_rcp and "rcp" or "usg")] or 1 + + for name, count in pairs(data.export_counts[rcp_usg].rcp) do + local items = {[name] = count} + + if is_group(name) then + items = {} + local groups = extract_groups(name) + local item_groups = groups_to_items(groups, true) + local remaining = count + + for _, item in ipairs(item_groups) do + for _name, _count in pairs(data.export_counts[rcp_usg].inv) do + if item == _name and remaining > 0 then + local c = math.min(remaining, _count) + items[item] = c + remaining = remaining - c + end + + if remaining == 0 then break end + end + end + end + + for k, v in pairs(items) do + inv:remove_item("main", fmt("%s %s", k, v * scrbar_val)) + end + end + + local count = stackcount * scrbar_val + local iter = math.ceil(count / stackmax) + local leftover = count + + for _ = 1, iter do + local c = math.min(stackmax, leftover) + local stack = ItemStack(fmt("%s %s", stackname, c)) + get_stack(player, stack) + leftover = leftover - stackmax + end +end + +local function play_sound(name, sound, volume) + core.sound_play(sound, {to_player = name, gain = volume}, true) +end + local function safe_teleport(player, pos) local name = player:get_player_name() - core.sound_play("i3_teleport", {to_player = name, gain = 1.0}, true) + play_sound(name, "i3_teleport", 1.0) pos.y = pos.y + 0.5 local vel = player:get_velocity() @@ -446,7 +497,7 @@ local function compress_items(list, start_i) return new_inv end -local function reject_items(player, inv, list, start_i, rej) +local function drop_items(player, inv, list, start_i, rej) for i = start_i, #list do local stack = list[i] local name = stack:get_name() @@ -459,17 +510,17 @@ local function reject_items(player, inv, list, start_i, rej) end end - return inv:get_list("main") + return inv:get_list"main" end local function sort_inventory(player, data) local inv = player:get_inventory() - local list = inv:get_list("main") - local size = inv:get_size("main") + local list = inv:get_list"main" + local size = inv:get_size"main" local start_i = data.ignore_hotbar and 10 or 1 - if true_table(data.reject_items) then - list = reject_items(player, inv, list, start_i, data.reject_items) + if true_table(data.drop_items) then + list = drop_items(player, inv, list, start_i, data.drop_items) end if data.inv_compress then @@ -540,9 +591,11 @@ local _ = { -- Misc. functions get_stack = get_stack, + craft_stack = craft_stack, show_item = show_item, spawn_item = spawn_item, clean_name = clean_name, + play_sound = play_sound, safe_teleport = safe_teleport, add_hud_waypoint = add_hud_waypoint, @@ -554,6 +607,7 @@ local _ = { pos_to_str = core.pos_to_string, str_to_pos = core.string_to_pos, check_privs = core.check_player_privs, + create_inventory = core.create_detached_inventory, -- Registered items reg_items = core.registered_items, diff --git a/src/detached_inv.lua b/src/detached_inv.lua new file mode 100644 index 0000000..9b4ceb2 --- /dev/null +++ b/src/detached_inv.lua @@ -0,0 +1,32 @@ +local fmt, play_sound, create_inventory = i3.get("fmt", "play_sound", "create_inventory") + +local trash = create_inventory("i3_trash", { + allow_put = function(_, _, _, stack) + return stack:get_count() + end, + + on_put = function(inv, listname, _, _, player) + inv:set_list(listname, {}) + + local name = player:get_player_name() + play_sound(name, "i3_trash", 1.0) + + if not core.is_creative_enabled(name) then + i3.set_fs(player) + end + end, +}) + +trash:set_size("main", 1) + +local function init_inventories(player) + local name = player:get_player_name() + + local output_rcp = create_inventory(fmt("i3_output_rcp_%s", name), {}, name) + output_rcp:set_size("main", 1) + + local output_usg = create_inventory(fmt("i3_output_usg_%s", name), {}, name) + output_usg:set_size("main", 1) +end + +return init_inventories diff --git a/src/gui.lua b/src/gui.lua index b084a17..c979e12 100644 --- a/src/gui.lua +++ b/src/gui.lua @@ -124,10 +124,8 @@ local function get_stack_max(inv, data, is_recipe, rcp) return max_stacks end -local function get_inv_slots(data, fs) - local inv_x, inv_y = 0.22, 6.9 - local width, size, spacing = i3.HOTBAR_LEN, 1, 0.1 - local bag = data.bag_size +local function get_inv_slots(fs) + local inv_x, inv_y, size, spacing = 0.22, 6.9, 1, 0.1 fs("style_type[box;colors=#77777710,#77777710,#777,#777]") @@ -138,14 +136,9 @@ local function get_inv_slots(data, fs) fs(fmt("style_type[list;size=%f;spacing=%f]", size, spacing), fmt("list[current_player;main;%f,%f;%u,1;]", inv_x, inv_y, i3.HOTBAR_LEN)) - if bag then - local params = {{10, 0.892}, {11, 0.8}, {12, 0.726}, {13, 0.663}} - width, size = unpack(params[bag]) - end - fs(fmt("style_type[list;size=%f;spacing=%f]", size, spacing), fmt("list[current_player;main;%f,%f;%u,%u;%u]", inv_x, inv_y + 1.15, - width, (bag and i3.BAG_SIZES[data.bag_size] or i3.INV_SIZE) / width, i3.HOTBAR_LEN), + i3.HOTBAR_LEN, i3.INV_SIZE / i3.HOTBAR_LEN, i3.HOTBAR_LEN), "style_type[list;size=1;spacing=0.15]") fs("listring[current_player;craft]listring[current_player;main]") @@ -294,8 +287,8 @@ local function get_waypoint_fs(fs, data, player, yextra, ctn_len) end local function get_container(fs, data, player, yoffset, ctn_len, award_list, awards_unlocked, award_list_nb) - local name = player:get_player_name() - add_subtitle(fs, "player_name", 0, ctn_len, 22, true, ESC(name)) + local name = data.player_name + add_subtitle(fs, "player_name", 0, ctn_len, 22, true, name) if damage_enabled then local hp = data.hp or player:get_hp() or 20 @@ -342,20 +335,39 @@ local function get_container(fs, data, player, yoffset, ctn_len, award_list, awa local function not_installed(modname) fs("hypertext", 0, yextra + 0.9, ctn_len, 0.6, "not_installed", - fmt("
not installed
", modname)) + fmt("
not installed
", + modname)) end if data.subcat == 1 then - fs(fmt("list[detached:%s_backpack;main;0,%f;1,1;]", ESC(name), yextra + 0.7)) + fs(fmt("list[detached:i3_bag_%s;main;0,%f;1,1;]", name, yextra + 0.7)) - if not data.bag:get_stack("main", 1):is_empty() then - fs("hypertext", 1.2, yextra + 0.89, ctn_len - 1.9, 0.8, "bpk", - ES("The inventory is extended by @1 slots", i3.BAG_SIZES[data.bag_size] - i3.INV_SIZE)) + local inv = core.get_inventory { + type = "detached", + name = fmt("i3_bag_%s", data.player_name) + } + + if not inv:is_empty"main" then + fs("image", 0.5, yextra + 1.85, 0.6, 0.6, PNG.arrow_content) + fs(fmt("style[content;bgimg=%s;fgimg=i3_blank.png;bgimg_middle=10,10;sound=]", PNG.bg_content)) + fs("image_button", 1.1, yextra + 0.5, 4.75, 4.75, "", "content", "") + fs("hypertext", 1.3, yextra + 0.8, 4.3, 0.6, "content", + fmt("
%s
", ES"Content")) + + local x, size, spacing = 1.45, 0.9, 0.12 + + if data.bag_size == 4 then + x, size, spacing = 1.7, 0.8, 0.1 + end + + fs(fmt("style_type[list;size=%f;spacing=%f]", size, spacing)) + fs(fmt("list[detached:i3_bag_content_%s;main;%f,%f;4,%u;]", name, x, yextra + 1.3, data.bag_size)) + fs("style_type[list;size=1;spacing=0.15]") end elseif data.subcat == 2 then if i3.modules.armor then - fs(fmt("list[detached:%s_armor;armor;0,%f;3,2;]", ESC(name), yextra + 0.7)) + fs(fmt("list[detached:%s_armor;armor;0,%f;3,2;]", name, yextra + 0.7)) local armor_def = armor.def[name] @@ -438,13 +450,18 @@ local function show_popup(fs, data) fs("button", 5.8, 9.25, 1.8, 0.55, "setting_misc", "Misc.") if show_home then - local home_pos = data.home or "" - home_pos = home_pos:gsub(",", ", "):sub(2,-2):gsub("%.%d", ""):gsub( - "(%-?%d+)", clr("#dbeeff", "%1")) - local home_str = fmt("Home position: %s", home_pos) - home_str = data.home and home_str or ES"No home set" + local coords, c, str = {"X", "Y", "Z"}, 0, ES"No home set" - fs("button", 2.1, 9.7, 6, 0.8, "", home_str) + if data.home then + str = data.home:gsub(",", " "):sub(2,-2):gsub("%.%d", ""):gsub( + "(%-?%d+)", function(a) + c = c + 1 + return fmt("%s: ", + coords[c], a) + end) + end + + fs("hypertext", 2.1, 9.9, 6, 0.6, "home_pos", fmt("
%s
", str)) fs("image_button", 4.2, 10.4, 1.8, 0.7, "", "set_home", "Set home") elseif show_sorting then @@ -476,11 +493,11 @@ local function show_popup(fs, data) fs("box", 5.4, 10.68, 2.4, 0.45, "#707070") end - fs("style[reject_items;font_size=15;font=mono;textcolor=#dbeeff]") - fs(fmt("field[5.4,10.68;2.4,0.45;reject_items;Reject items:;%s]", - ESC(concat(data.reject_items or {}, ",")))) - fs("field_close_on_enter[reject_items;false]") - fs(fmt("tooltip[reject_items;%s;#707070;#fff]", + fs("style[drop_items;font_size=15;font=mono;textcolor=#dbeeff]") + fs(fmt("field[5.4,10.68;2.4,0.45;drop_items;Drop items:;%s]", + ESC(concat(data.drop_items or {}, ",")))) + fs("field_close_on_enter[drop_items;false]") + fs(fmt("tooltip[drop_items;%s;#707070;#fff]", ES"Format:" .. "\n" .. ("mod:item,mod:item, ..."):gsub("(%a+:%a+)", clr("#bddeff", "%1")))) end @@ -490,11 +507,9 @@ end local function get_inventory_fs(player, data, fs) fs("listcolors[#bababa50;#bababa99]") - get_inv_slots(data, fs) + get_inv_slots(fs) local props = player:get_properties() - local name = player:get_player_name() - local ctn_len, ctn_hgt = 5.7, 6.3 local yoffset = 0 @@ -522,7 +537,10 @@ local function get_inventory_fs(player, data, fs) local awards_unlocked = 0 local max_val = damage_enabled and 12 or 7 - if i3.modules.armor and data.subcat == 2 then + if data.subcat == 1 and data.bag_size then + max_val = max_val + 32 + + elseif i3.modules.armor and data.subcat == 2 then if data.scrbar_inv >= max_val then data.scrbar_inv = data.scrbar_inv + 10 end @@ -530,7 +548,7 @@ local function get_inventory_fs(player, data, fs) max_val = max_val + 10 elseif i3.modules.awards and data.subcat == 4 then - award_list = awards.get_award_states(name) + award_list = awards.get_award_states(data.player_name) award_list_nb = #award_list for i = 1, award_list_nb do @@ -710,19 +728,18 @@ local function get_output_fs(fs, data, rcp, is_recipe, shapeless, right, btn_siz fs(fmt("style_type[list;size=%f]", i3.ITEM_BTN_SIZE)) fs("listcolors[#bababa50;#bababa99]") - fs(fmt("list[detached:i3_output_%s;main;%f,%f;1,1;]", rcp_usg, X + 0.11, Y)) + fs(fmt("list[detached:i3_output_%s_%s;main;%f,%f;1,1;]", rcp_usg, data.player_name, X + 0.11, Y)) fs("button", X + 0.11, Y, i3.ITEM_BTN_SIZE, i3.ITEM_BTN_SIZE, _name, "") local inv = core.get_inventory { type = "detached", - name = fmt("i3_output_%s", rcp_usg) + name = fmt("i3_output_%s_%s", rcp_usg, data.player_name) } inv:set_stack("main", 1, item) pos = {x = X + 0.11, y = Y} else fs("image", X, Y - 0.11, bt_s, bt_s, PNG.slot) - fs("item_image_button", X + 0.11, Y, i3.ITEM_BTN_SIZE, i3.ITEM_BTN_SIZE, fmt("%s %u", name, count * (is_recipe and data.scrbar_rcp or data.scrbar_usg or 1)), diff --git a/src/styles.lua b/src/styles.lua index 3218592..ad4b17e 100644 --- a/src/styles.lua +++ b/src/styles.lua @@ -1,6 +1,7 @@ local PNG = { bg = "i3_bg.png", bg_full = "i3_bg_full.png", + bg_content = "i3_bg_content.png", bar = "i3_bar.png", hotbar = "i3_hotbar.png", search = "i3_search.png", @@ -10,6 +11,7 @@ local PNG = { prev = "i3_next.png^\\[transformFX", next = "i3_next.png", arrow = "i3_arrow.png", + arrow_content = "i3_arrow_content.png", trash = "i3_trash.png", sort = "i3_sort.png", settings = "i3_settings.png", @@ -66,9 +68,10 @@ local styles = string.format([[ style_type[field;border=false;bgcolor=transparent] style_type[label,field;font_size=16] style_type[button;border=false;content_offset=0] - style_type[image_button,item_image_button,checkbox;border=false;sound=i3_click] + style_type[image_button,item_image_button,checkbox,dropdown;border=false;sound=i3_click] style_type[item_image_button;bgimg_hovered=%s] + style[nofav;sound=i3_cannot] style[pagenum,no_item,no_rcp;font=bold;font_size=18] style[exit;fgimg=%s;fgimg_hovered=%s;content_offset=0] style[cancel;fgimg=%s;fgimg_hovered=%s;content_offset=0] diff --git a/tests/test_tabs.lua b/tests/test_tabs.lua index 7d0b5ec..207fd6a 100644 --- a/tests/test_tabs.lua +++ b/tests/test_tabs.lua @@ -1,25 +1,22 @@ -i3.new_tab { - name = "test1", +i3.new_tab("test1", { description = "Test 1 Test 1", image = "i3_heart.png", formspec = function(player, data, fs) fs("label[3,1;Test 1]") end, -} +}) -i3.new_tab { - name = "test2", +i3.new_tab("test2", { description = "Test 2", image = "i3_mesepick.png", formspec = function(player, data, fs) fs("label[3,1;Test 2]") end, -} +}) -i3.new_tab { - name = "test3", +i3.new_tab("test3", { description = "Test 3", access = function(player, data) @@ -36,10 +33,9 @@ i3.new_tab { fields = function(player, data, fields) i3.set_fs(player, "label[3,2;Test extra_fs]") end, -} +}) i3.override_tab("test2", { - name = "test2", description = "Test override", image = "i3_mesepick.png", diff --git a/textures/i3_arrow_content.png b/textures/i3_arrow_content.png new file mode 100644 index 0000000000000000000000000000000000000000..e9074938ccd044a0ba720a1bbb2eb43e74b7ffa3 GIT binary patch literal 7590 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 literal 0 HcmV?d00001 diff --git a/textures/i3_bg_content.png b/textures/i3_bg_content.png new file mode 100644 index 0000000000000000000000000000000000000000..955072581ec35fda7fb0b8d2b43d2aaf4b6c90e5 GIT binary patch literal 26240 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 R1)Bf>002ovPDHLkV1kZ^+NS^j literal 0 HcmV?d00001