From e941fb462017e328c943d1851d04806dab5242d6 Mon Sep 17 00:00:00 2001 From: Milan2018 Date: Sun, 16 May 2021 13:36:21 +0200 Subject: [PATCH] update --- unified_inventory/README.md | 4 +- unified_inventory/api.lua | 116 +++----- unified_inventory/bags.lua | 80 +++--- unified_inventory/doc/mod_api.txt | 8 - unified_inventory/init.lua | 101 +------ unified_inventory/internal.lua | 260 +++++++++-------- unified_inventory/mod.conf | 4 +- unified_inventory/register.lua | 261 ++++++++---------- unified_inventory/textures/ui_bags_header.png | Bin 0 -> 1241 bytes .../textures/ui_bags_inv_large.png | Bin 0 -> 3401 bytes .../textures/ui_bags_inv_medium.png | Bin 0 -> 2300 bytes .../textures/ui_bags_inv_small.png | Bin 0 -> 1232 bytes unified_inventory/textures/ui_bags_trash.png | Bin 0 -> 1157 bytes .../textures/ui_craftguide_form.png | Bin 0 -> 962 bytes .../textures/ui_crafting_arrow.png | Bin 788 -> 0 bytes .../textures/ui_crafting_form.png | Bin 0 -> 2343 bytes unified_inventory/textures/ui_form_bg.png | Bin 0 -> 1003 bytes .../textures/ui_formbg_9_sliced.png | Bin 240 -> 0 bytes .../textures/ui_main_inventory.png | Bin 0 -> 4467 bytes unified_inventory/textures/ui_misc_form.png | Bin 0 -> 5789 bytes unified_inventory/textures/ui_single_slot.png | Bin 648 -> 629 bytes .../textures/ui_single_slot_bright.png | Bin 1032 -> 0 bytes .../textures/ui_trash_slot_icon.png | Bin 697 -> 0 bytes .../textures/ui_xyz_off_icon.png | Bin 0 -> 8606 bytes unified_inventory/textures/ui_xyz_on_icon.png | Bin 0 -> 2182 bytes unified_inventory/waypoints.lua | 127 ++++----- 26 files changed, 433 insertions(+), 528 deletions(-) create mode 100644 unified_inventory/textures/ui_bags_header.png create mode 100644 unified_inventory/textures/ui_bags_inv_large.png create mode 100644 unified_inventory/textures/ui_bags_inv_medium.png create mode 100644 unified_inventory/textures/ui_bags_inv_small.png create mode 100644 unified_inventory/textures/ui_bags_trash.png create mode 100644 unified_inventory/textures/ui_craftguide_form.png delete mode 100644 unified_inventory/textures/ui_crafting_arrow.png create mode 100644 unified_inventory/textures/ui_crafting_form.png create mode 100644 unified_inventory/textures/ui_form_bg.png delete mode 100644 unified_inventory/textures/ui_formbg_9_sliced.png create mode 100644 unified_inventory/textures/ui_main_inventory.png create mode 100644 unified_inventory/textures/ui_misc_form.png delete mode 100644 unified_inventory/textures/ui_single_slot_bright.png delete mode 100644 unified_inventory/textures/ui_trash_slot_icon.png create mode 100644 unified_inventory/textures/ui_xyz_off_icon.png create mode 100644 unified_inventory/textures/ui_xyz_on_icon.png diff --git a/unified_inventory/README.md b/unified_inventory/README.md index d159c02..8c917ec 100644 --- a/unified_inventory/README.md +++ b/unified_inventory/README.md @@ -24,7 +24,7 @@ Unified Inventory replaces the default survival and creative inventory. ## Requirements - * Minetest 5.4.0+ + * Minetest 5.0.0+ # Licenses @@ -96,4 +96,4 @@ Other files from Wikimedia Commons: RealBadAngel: (CC-BY-4.0) - * Everything else. + * Everything else. \ No newline at end of file diff --git a/unified_inventory/api.lua b/unified_inventory/api.lua index 05a34ee..81dd8f3 100644 --- a/unified_inventory/api.lua +++ b/unified_inventory/api.lua @@ -1,6 +1,5 @@ local S = minetest.get_translator("unified_inventory") local F = minetest.formspec_escape -local ui = unified_inventory -- Create detached creative inventory after loading all mods minetest.after(0.01, function() @@ -9,12 +8,12 @@ minetest.after(0.01, function() if not rev_aliases[target] then rev_aliases[target] = {} end table.insert(rev_aliases[target], source) end - ui.items_list = {} + unified_inventory.items_list = {} for name, def in pairs(minetest.registered_items) do if (not def.groups.not_in_creative_inventory or def.groups.not_in_creative_inventory == 0) and def.description and def.description ~= "" then - table.insert(ui.items_list, name) + table.insert(unified_inventory.items_list, name) local all_names = rev_aliases[name] or {} table.insert(all_names, name) for _, player_name in ipairs(all_names) do @@ -27,30 +26,30 @@ minetest.after(0.01, function() for _,chk in pairs(recipe.items) do local groupchk = string.find(chk, "group:") if (not groupchk and not minetest.registered_items[chk]) - or (groupchk and not ui.get_group_item(string.gsub(chk, "group:", "")).item) + or (groupchk and not unified_inventory.get_group_item(string.gsub(chk, "group:", "")).item) or minetest.get_item_group(chk, "not_in_craft_guide") ~= 0 then unknowns = true end end if not unknowns then - ui.register_craft(recipe) + unified_inventory.register_craft(recipe) end end end end end end - table.sort(ui.items_list) - ui.items_list_size = #ui.items_list - print("Unified Inventory. inventory size: "..ui.items_list_size) - for _, name in ipairs(ui.items_list) do + table.sort(unified_inventory.items_list) + unified_inventory.items_list_size = #unified_inventory.items_list + print("Unified Inventory. inventory size: "..unified_inventory.items_list_size) + for _, name in ipairs(unified_inventory.items_list) do local def = minetest.registered_items[name] -- Simple drops if type(def.drop) == "string" then local dstack = ItemStack(def.drop) if not dstack:is_empty() and dstack:get_name() ~= name then - ui.register_craft({ + unified_inventory.register_craft({ type = "digging", items = {name}, output = def.drop, @@ -116,7 +115,7 @@ minetest.after(0.01, function() end end for itemstring, count in pairs(drop_guaranteed) do - ui.register_craft({ + unified_inventory.register_craft({ type = "digging", items = {name}, output = itemstring .. " " .. count, @@ -124,7 +123,7 @@ minetest.after(0.01, function() }) end for itemstring, count in pairs(drop_maybe) do - ui.register_craft({ + unified_inventory.register_craft({ type = "digging_chance", items = {name}, output = itemstring .. " " .. count, @@ -133,22 +132,22 @@ minetest.after(0.01, function() end end end - for _, recipes in pairs(ui.crafts_for.recipe) do + for _, recipes in pairs(unified_inventory.crafts_for.recipe) do for _, recipe in ipairs(recipes) do local ingredient_items = {} for _, spec in pairs(recipe.items) do - local matches_spec = ui.canonical_item_spec_matcher(spec) - for _, name in ipairs(ui.items_list) do + local matches_spec = unified_inventory.canonical_item_spec_matcher(spec) + for _, name in ipairs(unified_inventory.items_list) do if matches_spec(name) then ingredient_items[name] = true end end end for name, _ in pairs(ingredient_items) do - if ui.crafts_for.usage[name] == nil then - ui.crafts_for.usage[name] = {} + if unified_inventory.crafts_for.usage[name] == nil then + unified_inventory.crafts_for.usage[name] = {} end - table.insert(ui.crafts_for.usage[name], recipe) + table.insert(unified_inventory.crafts_for.usage[name], recipe) end end end @@ -157,9 +156,9 @@ end) -- load_home local function load_home() - local input = io.open(ui.home_filename, "r") + local input = io.open(unified_inventory.home_filename, "r") if not input then - ui.home_pos = {} + unified_inventory.home_pos = {} return end while true do @@ -168,25 +167,25 @@ local function load_home() local y = input:read("*n") local z = input:read("*n") local name = input:read("*l") - ui.home_pos[name:sub(2)] = {x = x, y = y, z = z} + unified_inventory.home_pos[name:sub(2)] = {x = x, y = y, z = z} end io.close(input) end load_home() -function ui.set_home(player, pos) +function unified_inventory.set_home(player, pos) local player_name = player:get_player_name() - ui.home_pos[player_name] = vector.round(pos) + unified_inventory.home_pos[player_name] = vector.round(pos) -- save the home data from the table to the file - local output = io.open(ui.home_filename, "w") - for k, v in pairs(ui.home_pos) do + local output = io.open(unified_inventory.home_filename, "w") + for k, v in pairs(unified_inventory.home_pos) do output:write(v.x.." "..v.y.." "..v.z.." "..k.."\n") end io.close(output) end -function ui.go_home(player) - local pos = ui.home_pos[player:get_player_name()] +function unified_inventory.go_home(player) + local pos = unified_inventory.home_pos[player:get_player_name()] if pos then player:set_pos(pos) return true @@ -195,7 +194,7 @@ function ui.go_home(player) end -- register_craft -function ui.register_craft(options) +function unified_inventory.register_craft(options) if not options.output then return end @@ -206,10 +205,10 @@ function ui.register_craft(options) if options.type == "normal" and options.width == 0 then options = { type = "shapeless", items = options.items, output = options.output, width = 0 } end - if not ui.crafts_for.recipe[itemstack:get_name()] then - ui.crafts_for.recipe[itemstack:get_name()] = {} + if not unified_inventory.crafts_for.recipe[itemstack:get_name()] then + unified_inventory.crafts_for.recipe[itemstack:get_name()] = {} end - table.insert(ui.crafts_for.recipe[itemstack:get_name()],options) + table.insert(unified_inventory.crafts_for.recipe[itemstack:get_name()],options) end @@ -220,7 +219,7 @@ local craft_type_defaults = { } -function ui.craft_type_defaults(name, options) +function unified_inventory.craft_type_defaults(name, options) if not options.description then options.description = name end @@ -229,13 +228,13 @@ function ui.craft_type_defaults(name, options) end -function ui.register_craft_type(name, options) - ui.registered_craft_types[name] = - ui.craft_type_defaults(name, options) +function unified_inventory.register_craft_type(name, options) + unified_inventory.registered_craft_types[name] = + unified_inventory.craft_type_defaults(name, options) end -ui.register_craft_type("normal", { +unified_inventory.register_craft_type("normal", { description = F(S("Crafting")), icon = "ui_craftgrid_icon.png", width = 3, @@ -251,7 +250,7 @@ ui.register_craft_type("normal", { }) -ui.register_craft_type("shapeless", { +unified_inventory.register_craft_type("shapeless", { description = F(S("Mixing")), icon = "ui_craftgrid_icon.png", width = 3, @@ -266,7 +265,7 @@ ui.register_craft_type("shapeless", { }) -ui.register_craft_type("cooking", { +unified_inventory.register_craft_type("cooking", { description = F(S("Cooking")), icon = "default_furnace_front.png", width = 1, @@ -274,60 +273,37 @@ ui.register_craft_type("cooking", { }) -ui.register_craft_type("digging", { +unified_inventory.register_craft_type("digging", { description = F(S("Digging")), icon = "default_tool_steelpick.png", width = 1, height = 1, }) -ui.register_craft_type("digging_chance", { +unified_inventory.register_craft_type("digging_chance", { description = "Digging (by chance)", icon = "default_tool_steelpick.png^[transformFY.png", width = 1, height = 1, }) -function ui.register_page(name, def) - ui.pages[name] = def +function unified_inventory.register_page(name, def) + unified_inventory.pages[name] = def end -function ui.register_button(name, def) +function unified_inventory.register_button(name, def) if not def.action then def.action = function(player) - ui.set_inventory_formspec(player, name) + unified_inventory.set_inventory_formspec(player, name) end end def.name = name - table.insert(ui.buttons, def) + table.insert(unified_inventory.buttons, def) end -function ui.is_creative(playername) + +function unified_inventory.is_creative(playername) return minetest.check_player_privs(playername, {creative=true}) or minetest.settings:get_bool("creative_mode") end - -function ui.single_slot(xpos, ypos, bright) - return string.format("background9[%f,%f;%f,%f;ui_single_slot%s.png;false;16]", - xpos, ypos, ui.imgscale, ui.imgscale, (bright and "_bright" or "") ) -end - -function ui.make_trash_slot(xpos, ypos) - return - ui.single_slot(xpos, ypos).. - "image["..xpos..","..ypos..";1.25,1.25;ui_trash_slot_icon.png]".. - "list[detached:trash;main;"..(xpos + ui.list_img_offset)..","..(ypos + ui.list_img_offset)..";1,1;]" -end - -function ui.make_inv_img_grid(xpos, ypos, width, height, bright) - local tiled = {} - local n=1 - for y = 0, (height - 1) do - for x = 0, (width -1) do - tiled[n] = ui.single_slot(xpos + (ui.imgscale * x), ypos + (ui.imgscale * y), bright) - n = n + 1 - end - end - return table.concat(tiled) -end diff --git a/unified_inventory/bags.lua b/unified_inventory/bags.lua index 14ac875..bcaa520 100644 --- a/unified_inventory/bags.lua +++ b/unified_inventory/bags.lua @@ -7,32 +7,29 @@ License: GPLv3 local S = minetest.get_translator("unified_inventory") local F = minetest.formspec_escape -local ui = unified_inventory +local bags_inv_bg_prefix = "image[-0.1,1.0;10.05," -ui.register_page("bags", { +unified_inventory.register_page("bags", { get_formspec = function(player) local player_name = player:get_player_name() return { formspec = table.concat({ - ui.style_full.standard_inv_bg, - ui.single_slot(0.925, 1.5), - ui.single_slot(3.425, 1.5), - ui.single_slot(5.925, 1.5), - ui.single_slot(8.425, 1.5), - "label["..ui.style_full.form_header_x..","..ui.style_full.form_header_y..";" .. F(S("Bags")) .. "]", - "button[0.6125,2.75;1.875,0.75;bag1;" .. F(S("Bag @1", 1)) .. "]", - "button[3.1125,2.75;1.875,0.75;bag2;" .. F(S("Bag @1", 2)) .. "]", - "button[5.6125,2.75;1.875,0.75;bag3;" .. F(S("Bag @1", 3)) .. "]", - "button[8.1125,2.75;1.875,0.75;bag4;" .. F(S("Bag @1", 4)) .. "]", + string.gsub(unified_inventory.standard_inv_bg, "YYY", "4.4"), + bags_inv_bg_prefix.."1.175;ui_bags_header.png]", + "label[0,0;" .. F(S("Bags")) .. "]", + "button[0,2.2;2,0.5;bag1;" .. F(S("Bag @1", 1)) .. "]", + "button[2,2.2;2,0.5;bag2;" .. F(S("Bag @1", 2)) .. "]", + "button[4,2.2;2,0.5;bag3;" .. F(S("Bag @1", 3)) .. "]", + "button[6,2.2;2,0.5;bag4;" .. F(S("Bag @1", 4)) .. "]", "listcolors[#00000000;#00000000]", - "list[detached:" .. F(player_name) .. "_bags;bag1;1.075,1.65;1,1;]", - "list[detached:" .. F(player_name) .. "_bags;bag2;3.575,1.65;1,1;]", - "list[detached:" .. F(player_name) .. "_bags;bag3;6.075,1.65;1,1;]", - "list[detached:" .. F(player_name) .. "_bags;bag4;8.575,1.65;1,1;]" + "list[detached:" .. F(player_name) .. "_bags;bag1;0.5,1.1;1,1;]", + "list[detached:" .. F(player_name) .. "_bags;bag2;2.5,1.1;1,1;]", + "list[detached:" .. F(player_name) .. "_bags;bag3;4.5,1.1;1,1;]", + "list[detached:" .. F(player_name) .. "_bags;bag4;6.5,1.1;1,1;]" }) } end, }) -ui.register_button("bags", { +unified_inventory.register_button("bags", { type = "image", image = "ui_bags_icon.png", tooltip = S("Bags"), @@ -47,31 +44,33 @@ local function get_player_bag_stack(player, i) end for bag_i = 1, 4 do - ui.register_page("bag" .. bag_i, { + unified_inventory.register_page("bag" .. bag_i, { get_formspec = function(player) local stack = get_player_bag_stack(player, bag_i) local image = stack:get_definition().inventory_image - local slots = stack:get_definition().groups.bagslots - - local formspec = { - ui.style_full.standard_inv_bg, - ui.make_inv_img_grid(0.3, 1.5, 8, slots/8), - "image[9.2,0.4;1,1;" .. image .. "]", - "label[0.3,0.65;" .. F(S("Bag @1", bag_i)) .. "]", + local fs = { + string.gsub(unified_inventory.standard_inv_bg, "YYY", "4.4"), + "image[7,0;1,1;" .. image .. "]", + "label[0,0;" .. F(S("Bag @1", bag_i)) .. "]", "listcolors[#00000000;#00000000]", - "listring[current_player;main]", - string.format("list[current_player;bag%icontents;%f,%f;8,3;]", - bag_i, 0.3 + ui.list_img_offset, 1.5 + ui.list_img_offset), + "list[current_player;bag" .. bag_i .. "contents;0,1.1;8,3;]", "listring[current_name;bag" .. bag_i .. "contents]", + "listring[current_player;main]", } - local n = #formspec + 1 - + local slots = stack:get_definition().groups.bagslots + if slots == 8 then + fs[#fs + 1] = bags_inv_bg_prefix.."1.175;ui_bags_inv_small.png]" + elseif slots == 16 then + fs[#fs + 1] = bags_inv_bg_prefix.."2.35;ui_bags_inv_medium.png]" + elseif slots == 24 then + fs[#fs + 1] = bags_inv_bg_prefix.."3.525;ui_bags_inv_large.png]" + end local player_name = player:get_player_name() -- For if statement. - if ui.trash_enabled - or ui.is_creative(player_name) - or minetest.get_player_privs(player_name).give then - formspec[n] = ui.make_trash_slot(7.8, 0.25) - n = n + 1 + if unified_inventory.trash_enabled + or unified_inventory.is_creative(player_name) + or minetest.get_player_privs(player_name).give then + fs[#fs + 1] = "image[5.91,-0.06;1.21,1.15;ui_bags_trash.png]" + .. "list[detached:trash;main;6,0.1;1,1;]" end local inv = player:get_inventory() for i = 1, 4 do @@ -88,12 +87,11 @@ for bag_i = 1, 4 do end local img = def.inventory_image local label = F(S("Bag @1", i)) .. "\n" .. used .. "/" .. size - formspec[n] = string.format("image_button[%f,0.4;1,1;%s;bag%i;%s]", - (i + 1.35)*1.25, img, i, label) - n = n + 1 + fs[#fs + 1] = string.format("image_button[%i,0;1,1;%s;bag%i;%s]", + i + 1, img, i, label) end end - return { formspec = table.concat(formspec) } + return { formspec = table.concat(fs) } end, }) end @@ -108,7 +106,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) if not stack:get_definition().groups.bagslots then return end - ui.set_inventory_formspec(player, "bag" .. i) + unified_inventory.set_inventory_formspec(player, "bag" .. i) return end end @@ -137,7 +135,7 @@ end local function load_bags_metadata(player, bags_inv) local player_inv = player:get_inventory() local meta = player:get_meta() - local bags_meta = meta:get("unified_inventory:bags") + local bags_meta = meta:get_string("unified_inventory:bags") local bags = bags_meta and minetest.deserialize(bags_meta) or {} local dirty_meta = false if not bags_meta then diff --git a/unified_inventory/doc/mod_api.txt b/unified_inventory/doc/mod_api.txt index 0d100a0..c0be129 100644 --- a/unified_inventory/doc/mod_api.txt +++ b/unified_inventory/doc/mod_api.txt @@ -3,14 +3,6 @@ unified_inventory API This file provides information about the API of unified_inventory. -API revisions within unified_inventory can be checked using: - - (unified_inventory.version or 1) - -**Revision history** - -* Version `1`: Classic formspec layout (no real_coordinates) -* Version `2`: Force formspec version 4 (includes real_coordinates) Misc functions -------------- diff --git a/unified_inventory/init.lua b/unified_inventory/init.lua index 231da9e..7be101c 100644 --- a/unified_inventory/init.lua +++ b/unified_inventory/init.lua @@ -35,101 +35,21 @@ unified_inventory = { -- Trash enabled trash_enabled = (minetest.settings:get_bool("unified_inventory_trash") ~= false), - imgscale = 1.25, - list_img_offset = 0.13, - standard_background = "background9[0,0;1,1;ui_formbg_9_sliced.png;true;16]", - version = 2 -} -local ui = unified_inventory - --- These tables establish position and layout for the two UI styles. --- UI doesn't use formspec_[xy] anymore, but other mods may need them. - -ui.style_full = { - formspec_x = 1, - formspec_y = 1, pagecols = 8, pagerows = 10, - page_x = 10.75, - page_y = 1.45, - craft_x = 2.8, - craft_y = 1.15, - craftresult_x = 7.8, - craft_arrow_x = 6.55, - craft_guide_x = 3.3, - craft_guide_y = 1.15, - craft_guide_arrow_x = 7.05, - craft_guide_result_x = 8.3, - craft_guide_resultstr_x = 0.3, - craft_guide_resultstr_y = 0.6, - give_btn_x = 0.25, - main_button_x = 0.4, - main_button_y = 11.0, - page_buttons_x = 11.60, - page_buttons_y = 10.15, - searchwidth = 3.4, - form_header_x = 0.4, - form_header_y = 0.4, - btn_spc = 0.85, - btn_size = 0.75, - std_inv_x = 0.3, - std_inv_y = 5.75, + page_y = 0, + formspec_y = 1, + main_button_x = 0, + main_button_y = 9, + craft_result_x = 0.3, + craft_result_y = 0.5, + form_header_y = 0, + standard_background = "background[-0.2,-0.2;1,1;ui_form_bg.png;true]", -- the 'true' scales to fill, overrides the 1,1 + standard_inv = "list[current_player;main;0,YYY;8,4;]", -- the YYY's are placeholders which get + standard_inv_bg = "image[-0.1,YYY;10.05,4.70;ui_main_inventory.png]", -- replaced later by string.gsub() } -ui.style_lite = { - formspec_x = 0.6, - formspec_y = 0.6, - pagecols = 4, - pagerows = 6, - page_x = 10.5, - page_y = 1.25, - craft_x = 2.6, - craft_y = 0.75, - craftresult_x = 5.75, - craft_arrow_x = 6.35, - craft_guide_x = 3.1, - craft_guide_y = 0.75, - craft_guide_arrow_x = 7.05, - craft_guide_result_x = 8.3, - craft_guide_resultstr_x = 0.15, - craft_guide_resultstr_y = 0.35, - give_btn_x = 0.15, - main_button_x = 10.5, - main_button_y = 7.9, - page_buttons_x = 10.5, - page_buttons_y = 6.3, - searchwidth = 1.6, - form_header_x = 0.2, - form_header_y = 0.2, - btn_spc = 0.8, - btn_size = 0.7, - std_inv_x = 0.1, - std_inv_y = 4.6, -} - -dofile(modpath.."/api.lua") - -for _, style in ipairs({ui.style_full, ui.style_lite}) do - style.items_per_page = style.pagecols * style.pagerows - style.standard_inv = string.format("list[current_player;main;%f,%f;8,4;]", - style.std_inv_x + ui.list_img_offset, style.std_inv_y + ui.list_img_offset) - - style.standard_inv_bg = ui.make_inv_img_grid(style.std_inv_x, style.std_inv_y, 8, 1, true).. - ui.make_inv_img_grid(style.std_inv_x, style.std_inv_y + ui.imgscale, 8, 3) - - style.craft_grid = table.concat({ - ui.make_inv_img_grid(style.craft_x, style.craft_y, 3, 3), - ui.single_slot(style.craft_x + ui.imgscale*4, style.craft_y), -- the craft result slot - string.format("image[%f,%f;%f,%f;ui_crafting_arrow.png]", - style.craft_arrow_x, style.craft_y, ui.imgscale, ui.imgscale), - string.format("list[current_player;craft;%f,%f;3,3;]", - style.craft_x + ui.list_img_offset, style.craft_y + ui.list_img_offset), - string.format("list[current_player;craftpreview;%f,%f;1,1;]", - style.craftresult_x + ui.list_img_offset, style.craft_y + ui.list_img_offset) - }) -end - -- Disable default creative inventory local creative = rawget(_G, "creative") or rawget(_G, "creative_inventory") if creative then @@ -145,6 +65,7 @@ if sfinv then end dofile(modpath.."/group.lua") +dofile(modpath.."/api.lua") dofile(modpath.."/internal.lua") dofile(modpath.."/callbacks.lua") dofile(modpath.."/match_craft.lua") diff --git a/unified_inventory/internal.lua b/unified_inventory/internal.lua index d92b932..78cba2a 100644 --- a/unified_inventory/internal.lua +++ b/unified_inventory/internal.lua @@ -1,6 +1,5 @@ local S = minetest.get_translator("unified_inventory") local F = minetest.formspec_escape -local ui = unified_inventory -- This pair of encoding functions is used where variable text must go in -- button names, where the text might contain formspec metacharacters. @@ -10,50 +9,78 @@ local ui = unified_inventory -- This is a game engine bug, and in the anticipation that it might be -- fixed some day we don't want to rely on it. So for safety we apply -- an encoding that avoids all formspec metacharacters. - -function ui.mangle_for_formspec(str) +function unified_inventory.mangle_for_formspec(str) return string.gsub(str, "([^A-Za-z0-9])", function (c) return string.format("_%d_", string.byte(c)) end) end -function ui.demangle_for_formspec(str) +function unified_inventory.demangle_for_formspec(str) return string.gsub(str, "_([0-9]+)_", function (v) return string.char(v) end) end +function unified_inventory.get_per_player_formspec(player_name) + local lite = unified_inventory.lite_mode and not minetest.check_player_privs(player_name, {ui_full=true}) -function ui.get_per_player_formspec(player_name) - local draw_lite_mode = ui.lite_mode and not minetest.check_player_privs(player_name, {ui_full=true}) + local ui = {} + ui.pagecols = unified_inventory.pagecols + ui.pagerows = unified_inventory.pagerows + ui.page_y = unified_inventory.page_y + ui.formspec_y = unified_inventory.formspec_y + ui.main_button_x = unified_inventory.main_button_x + ui.main_button_y = unified_inventory.main_button_y + ui.craft_result_x = unified_inventory.craft_result_x + ui.craft_result_y = unified_inventory.craft_result_y + ui.form_header_y = unified_inventory.form_header_y - return table.copy(draw_lite_mode and ui.style_lite or ui.style_full), draw_lite_mode + if lite then + ui.pagecols = 4 + ui.pagerows = 6 + ui.page_y = 0.25 + ui.formspec_y = 0.47 + ui.main_button_x = 8.2 + ui.main_button_y = 6.5 + ui.craft_result_x = 2.8 + ui.craft_result_y = 3.4 + ui.form_header_y = -0.1 + end + + ui.items_per_page = ui.pagecols * ui.pagerows + return ui, lite end -function ui.get_formspec(player, page) +function unified_inventory.get_formspec(player, page) if not player then return "" end local player_name = player:get_player_name() - local ui_peruser,draw_lite_mode = ui.get_per_player_formspec(player_name) + local ui_peruser,draw_lite_mode = unified_inventory.get_per_player_formspec(player_name) - ui.current_page[player_name] = page - local pagedef = ui.pages[page] + unified_inventory.current_page[player_name] = page + local pagedef = unified_inventory.pages[page] if not pagedef then return "" -- Invalid page name end local formspec = { - "formspec_version[4]size[17.75,12.25]", + "size[14,10]", pagedef.formspec_prepend and "" or "no_prepend[]", - ui.standard_background -- Background + unified_inventory.standard_background -- Background } local n = 4 if draw_lite_mode then - formspec[1] = "formspec_version[4]size[14,9.75]" - formspec[3] = ui.standard_background + formspec[1] = "size[11,7.7]" + formspec[3] = unified_inventory.standard_background end - local perplayer_formspec = ui.get_per_player_formspec(player_name) + if unified_inventory.is_creative(player_name) + and page == "craft" then + formspec[n] = "background[0,"..(ui_peruser.formspec_y + 2)..";1,1;ui_single_slot.png]" + n = n+1 + end + + local perplayer_formspec = unified_inventory.get_per_player_formspec(player_name) local fsdata = pagedef.get_formspec(player, perplayer_formspec) formspec[n] = fsdata.formspec @@ -66,7 +93,7 @@ function ui.get_formspec(player, page) local filtered_inv_buttons = {} - for i, def in pairs(ui.buttons) do + for i, def in pairs(unified_inventory.buttons) do if not (draw_lite_mode and def.hide_lite) then table.insert(filtered_inv_buttons, def) end @@ -81,20 +108,21 @@ function ui.get_formspec(player, page) if def.type == "image" then if (def.condition == nil or def.condition(player) == true) then - formspec[n] = string.format("image_button[%f,%f;%f,%f;%s;%s;]", - ui_peruser.main_button_x + ui_peruser.btn_spc * (i - 1) - button_col * ui_peruser.btn_spc * 4, - ui_peruser.main_button_y + button_row * ui_peruser.btn_spc, - ui_peruser.btn_size,ui_peruser.btn_size, - F(def.image), - F(def.name)) - formspec[n+1] = "tooltip["..F(def.name)..";"..(def.tooltip or "").."]" - n = n+2 + formspec[n] = "image_button[" + formspec[n+1] = ( ui_peruser.main_button_x + 0.65 * (i - 1) - button_col * 0.65 * 4) + formspec[n+2] = ","..(ui_peruser.main_button_y + button_row * 0.7)..";0.8,0.8;" + formspec[n+3] = F(def.image)..";" + formspec[n+4] = F(def.name)..";]" + formspec[n+5] = "tooltip["..F(def.name) + formspec[n+6] = ";"..(def.tooltip or "").."]" + n = n+7 else - formspec[n] = string.format("image[%f,%f;%f,%f;%s^[colorize:#808080:alpha]", - ui_peruser.main_button_x + ui_peruser.btn_spc * (i - 1) - button_col * ui_peruser.btn_spc * 4, - ui_peruser.main_button_y + button_row * ui_peruser.btn_spc, - ui_peruser.btn_size,ui_peruser.btn_size,def.image) - n = n+1 + formspec[n] = "image[" + formspec[n+1] = ( ui_peruser.main_button_x + 0.65 * (i - 1) - button_col * 0.65 * 4) + formspec[n+2] = ","..(ui_peruser.main_button_y + button_row * 0.7)..";0.8,0.8;" + formspec[n+3] = F(def.image).."^[colorize:#808080:alpha]" + n = n+4 + end end end @@ -102,7 +130,7 @@ function ui.get_formspec(player, page) if fsdata.draw_inventory ~= false then -- Player inventory formspec[n] = "listcolors[#00000000;#00000000]" - formspec[n+1] = ui_peruser.standard_inv + formspec[n+1] = string.gsub(unified_inventory.standard_inv, "YYY", ui_peruser.formspec_y + 3.5) n = n+2 end @@ -110,52 +138,71 @@ function ui.get_formspec(player, page) return table.concat(formspec, "") end + -- Controls to flip items pages + local start_x = 9.2 + + if not draw_lite_mode then + formspec[n] = + "image_button[" .. (start_x + 0.6 * 0) + .. ",9;.8,.8;ui_skip_backward_icon.png;start_list;]" + .. "tooltip[start_list;" .. F(S("First page")) .. "]" + + .. "image_button[" .. (start_x + 0.6 * 1) + .. ",9;.8,.8;ui_doubleleft_icon.png;rewind3;]" + .. "tooltip[rewind3;" .. F(S("Back three pages")) .. "]" + .. "image_button[" .. (start_x + 0.6 * 2) + .. ",9;.8,.8;ui_left_icon.png;rewind1;]" + .. "tooltip[rewind1;" .. F(S("Back one page")) .. "]" + + .. "image_button[" .. (start_x + 0.6 * 3) + .. ",9;.8,.8;ui_right_icon.png;forward1;]" + .. "tooltip[forward1;" .. F(S("Forward one page")) .. "]" + .. "image_button[" .. (start_x + 0.6 * 4) + .. ",9;.8,.8;ui_doubleright_icon.png;forward3;]" + .. "tooltip[forward3;" .. F(S("Forward three pages")) .. "]" + + .. "image_button[" .. (start_x + 0.6 * 5) + .. ",9;.8,.8;ui_skip_forward_icon.png;end_list;]" + .. "tooltip[end_list;" .. F(S("Last page")) .. "]" + else + formspec[n] = + "image_button[" .. (8.2 + 0.65 * 0) + .. ",5.8;.8,.8;ui_skip_backward_icon.png;start_list;]" + .. "tooltip[start_list;" .. F(S("First page")) .. "]" + .. "image_button[" .. (8.2 + 0.65 * 1) + .. ",5.8;.8,.8;ui_left_icon.png;rewind1;]" + .. "tooltip[rewind1;" .. F(S("Back one page")) .. "]" + .. "image_button[" .. (8.2 + 0.65 * 2) + .. ",5.8;.8,.8;ui_right_icon.png;forward1;]" + .. "tooltip[forward1;" .. F(S("Forward one page")) .. "]" + .. "image_button[" .. (8.2 + 0.65 * 3) + .. ",5.8;.8,.8;ui_skip_forward_icon.png;end_list;]" + .. "tooltip[end_list;" .. F(S("Last page")) .. "]" + end + n = n+1 + -- Search box formspec[n] = "field_close_on_enter[searchbox;false]" + n = n+1 - formspec[n+1] = string.format("field[%f,%f;%f,%f;searchbox;;%s]", - ui_peruser.page_buttons_x, ui_peruser.page_buttons_y, - ui_peruser.searchwidth - 0.1, ui_peruser.btn_size, - F(ui.current_searchbox[player_name])) - formspec[n+2] = string.format("image_button[%f,%f;%f,%f;ui_search_icon.png;searchbutton;]", - ui_peruser.page_buttons_x + ui_peruser.searchwidth, ui_peruser.page_buttons_y, - ui_peruser.btn_size,ui_peruser.btn_size) - formspec[n+3] = "tooltip[searchbutton;" ..F(S("Search")) .. "]" - formspec[n+4] = string.format("image_button[%f,%f;%f,%f;ui_reset_icon.png;searchresetbutton;]", - ui_peruser.page_buttons_x + ui_peruser.searchwidth + ui_peruser.btn_spc, - ui_peruser.page_buttons_y, - ui_peruser.btn_size, ui_peruser.btn_size) - formspec[n+5] = "tooltip[searchresetbutton;"..F(S("Reset search and display everything")).."]" - - n = n + 6 - - -- Controls to flip items pages - - local btnlist = { - { "ui_skip_backward_icon.png", "start_list", S("First page") }, - { "ui_doubleleft_icon.png", "rewind3", S("Back three pages") }, - { "ui_left_icon.png", "rewind1", S("Back one page") }, - { "ui_right_icon.png", "forward1", S("Forward one page") }, - { "ui_doubleright_icon.png", "forward3", S("Forward three pages") }, - { "ui_skip_forward_icon.png", "end_list", S("Last page") }, - } - - if draw_lite_mode then - btnlist[5] = nil - btnlist[2] = nil - end - - local bn = 0 - for _, b in pairs(btnlist) do - formspec[n] = string.format("image_button[%f,%f;%f,%f;%s;%s;]", - ui_peruser.page_buttons_x + ui_peruser.btn_spc*bn, - ui_peruser.page_buttons_y + ui_peruser.btn_spc, - ui_peruser.btn_size, ui_peruser.btn_size, - b[1],b[2]) - formspec[n+1] = "tooltip["..b[2]..";"..F(b[3]).."]" - bn = bn + 1 - n = n + 2 + if not draw_lite_mode then + formspec[n] = "field[9.5,8.325;3,1;searchbox;;" + .. F(unified_inventory.current_searchbox[player_name]) .. "]" + formspec[n+1] = "image_button[12.2,8.1;.8,.8;ui_search_icon.png;searchbutton;]" + .. "tooltip[searchbutton;" ..F(S("Search")) .. "]" + formspec[n+2] = "image_button[12.9,8.1;.8,.8;ui_reset_icon.png;searchresetbutton;]" + .. "tooltip[searchbutton;" ..F(S("Search")) .. "]" + .. "tooltip[searchresetbutton;" ..F(S("Reset search and display everything")) .. "]" + else + formspec[n] = "field[8.5,5.225;2.2,1;searchbox;;" + .. F(unified_inventory.current_searchbox[player_name]) .. "]" + formspec[n+1] = "image_button[10.3,5;.8,.8;ui_search_icon.png;searchbutton;]" + .. "tooltip[searchbutton;" ..F(S("Search")) .. "]" + formspec[n+2] = "image_button[11,5;.8,.8;ui_reset_icon.png;searchresetbutton;]" + .. "tooltip[searchbutton;" ..F(S("Search")) .. "]" + .. "tooltip[searchresetbutton;" ..F(S("Reset search and display everything")) .. "]" end + n = n+3 local no_matches = S("No matching items") if draw_lite_mode then @@ -163,23 +210,23 @@ function ui.get_formspec(player, page) end -- Items list - if #ui.filtered_items_list[player_name] == 0 then - formspec[n] = "label["..ui_peruser.page_x..","..(ui_peruser.page_y+0.15)..";" .. F(no_matches) .. "]" + if #unified_inventory.filtered_items_list[player_name] == 0 then + formspec[n] = "label[8.2,"..ui_peruser.form_header_y..";" .. F(no_matches) .. "]" else - local dir = ui.active_search_direction[player_name] - local list_index = ui.current_index[player_name] + local dir = unified_inventory.active_search_direction[player_name] + local list_index = unified_inventory.current_index[player_name] local page2 = math.floor(list_index / (ui_peruser.items_per_page) + 1) local pagemax = math.floor( - (#ui.filtered_items_list[player_name] - 1) + (#unified_inventory.filtered_items_list[player_name] - 1) / (ui_peruser.items_per_page) + 1) for y = 0, ui_peruser.pagerows - 1 do for x = 0, ui_peruser.pagecols - 1 do - local name = ui.filtered_items_list[player_name][list_index] + local name = unified_inventory.filtered_items_list[player_name][list_index] local item = minetest.registered_items[name] if item then -- Clicked on current item: Flip crafting direction - if name == ui.current_item[player_name] then - local cdir = ui.current_craft_direction[player_name] + if name == unified_inventory.current_item[player_name] then + local cdir = unified_inventory.current_craft_direction[player_name] if cdir == "recipe" then dir = "usage" elseif cdir == "usage" then @@ -187,15 +234,13 @@ function ui.get_formspec(player, page) end else -- Default: use active search direction by default - dir = ui.active_search_direction[player_name] + dir = unified_inventory.active_search_direction[player_name] end local button_name = "item_button_" .. dir .. "_" - .. ui.mangle_for_formspec(name) - formspec[n] = ("item_image_button[%f,%f;%f,%f;%s;%s;]"):format( - ui_peruser.page_x + x * ui_peruser.btn_spc, - ui_peruser.page_y + y * ui_peruser.btn_spc, - ui_peruser.btn_size, ui_peruser.btn_size, + .. unified_inventory.mangle_for_formspec(name) + formspec[n] = ("item_image_button[%f,%f;.81,.81;%s;%s;]"):format( + 8.2 + x * 0.7, ui_peruser.formspec_y + ui_peruser.page_y + y * 0.7, name, button_name ) formspec[n + 1] = ("tooltip[%s;%s \\[%s\\]]"):format( @@ -207,29 +252,26 @@ function ui.get_formspec(player, page) end end end - formspec[n] = string.format("label[%f,%f;%s: %s]", - ui_peruser.page_x, ui_peruser.form_header_y, - F(S("Page")), S("@1 of @2",page2,pagemax)) + formspec[n] = "label[8.2,"..ui_peruser.form_header_y..";"..F(S("Page")) .. ": " + .. S("@1 of @2",page2,pagemax).."]" end n= n+1 - if ui.activefilter[player_name] ~= "" then - formspec[n] = string.format("label[%f,%f;%s:]", - ui_peruser.page_x, ui_peruser.page_y - 0.65, F(S("Filter"))) - formspec[n+1] = string.format("label[%f,%f;%s]", - ui_peruser.page_x, ui_peruser.page_y - 0.25, F(ui.activefilter[player_name])) + if unified_inventory.activefilter[player_name] ~= "" then + formspec[n] = "label[8.2,"..(ui_peruser.form_header_y + 0.4)..";" .. F(S("Filter")) .. ":]" + formspec[n+1] = "label[9.1,"..(ui_peruser.form_header_y + 0.4)..";"..F(unified_inventory.activefilter[player_name]).."]" end return table.concat(formspec, "") end -function ui.set_inventory_formspec(player, page) +function unified_inventory.set_inventory_formspec(player, page) if player then - player:set_inventory_formspec(ui.get_formspec(player, page)) + player:set_inventory_formspec(unified_inventory.get_formspec(player, page)) end end --apply filter to the inventory list (create filtered copy of full one) -function ui.apply_filter(player, filter, search_dir) +function unified_inventory.apply_filter(player, filter, search_dir) if not player then return false end @@ -258,26 +300,26 @@ function ui.apply_filter(player, filter, search_dir) or llocaldesc and string.find(llocaldesc, lfilter, 1, true) end end - ui.filtered_items_list[player_name]={} + unified_inventory.filtered_items_list[player_name]={} for name, def in pairs(minetest.registered_items) do if (not def.groups.not_in_creative_inventory or def.groups.not_in_creative_inventory == 0) and def.description and def.description ~= "" and ffilter(name, def) then - table.insert(ui.filtered_items_list[player_name], name) + table.insert(unified_inventory.filtered_items_list[player_name], name) end end - table.sort(ui.filtered_items_list[player_name]) - ui.filtered_items_list_size[player_name] = #ui.filtered_items_list[player_name] - ui.current_index[player_name] = 1 - ui.activefilter[player_name] = filter - ui.active_search_direction[player_name] = search_dir - ui.set_inventory_formspec(player, - ui.current_page[player_name]) + table.sort(unified_inventory.filtered_items_list[player_name]) + unified_inventory.filtered_items_list_size[player_name] = #unified_inventory.filtered_items_list[player_name] + unified_inventory.current_index[player_name] = 1 + unified_inventory.activefilter[player_name] = filter + unified_inventory.active_search_direction[player_name] = search_dir + unified_inventory.set_inventory_formspec(player, + unified_inventory.current_page[player_name]) end -function ui.items_in_group(groups) +function unified_inventory.items_in_group(groups) local items = {} for name, item in pairs(minetest.registered_items) do for _, group in pairs(groups:split(',')) do @@ -289,7 +331,7 @@ function ui.items_in_group(groups) return items end -function ui.sort_inventory(inv) +function unified_inventory.sort_inventory(inv) local inlist = inv:get_list("main") local typecnt = {} local typekeys = {} diff --git a/unified_inventory/mod.conf b/unified_inventory/mod.conf index 89be528..6894dd2 100644 --- a/unified_inventory/mod.conf +++ b/unified_inventory/mod.conf @@ -5,4 +5,6 @@ description = """ Unified Inventory replaces the default survival and creative inventory. It adds a nicer interface and a number of features, such as a crafting guide. """ -min_minetest_version = 5.4.0 +release = 6744 +title = Unified Inventory +author = RealBadAngel diff --git a/unified_inventory/register.lua b/unified_inventory/register.lua index 3cb5f59..cfc1d7d 100644 --- a/unified_inventory/register.lua +++ b/unified_inventory/register.lua @@ -1,7 +1,6 @@ local S = minetest.get_translator("unified_inventory") local NS = function(s) return s end local F = minetest.formspec_escape -local ui = unified_inventory minetest.register_privilege("creative", { description = S("Can use the creative inventory"), @@ -13,9 +12,10 @@ minetest.register_privilege("ui_full", { give_to_singleplayer = false, }) + local trash = minetest.create_detached_inventory("trash", { --allow_put = function(inv, listname, index, stack, player) - -- if ui.is_creative(player:get_player_name()) then + -- if unified_inventory.is_creative(player:get_player_name()) then -- return stack:get_count() -- else -- return 0 @@ -29,19 +29,19 @@ local trash = minetest.create_detached_inventory("trash", { }) trash:set_size("main", 1) -ui.register_button("craft", { +unified_inventory.register_button("craft", { type = "image", image = "ui_craft_icon.png", tooltip = S("Crafting Grid") }) -ui.register_button("craftguide", { +unified_inventory.register_button("craftguide", { type = "image", image = "ui_craftguide_icon.png", tooltip = S("Crafting Guide") }) -ui.register_button("home_gui_set", { +unified_inventory.register_button("home_gui_set", { type = "image", image = "ui_sethome_icon.png", tooltip = S("Set home position"), @@ -49,8 +49,8 @@ ui.register_button("home_gui_set", { action = function(player) local player_name = player:get_player_name() if minetest.check_player_privs(player_name, {home=true}) then - ui.set_home(player, player:get_pos()) - local home = ui.home_pos[player_name] + unified_inventory.set_home(player, player:get_pos()) + local home = unified_inventory.home_pos[player_name] if home ~= nil then minetest.sound_play("dingdong", {to_player=player_name, gain = 1.0}) @@ -60,7 +60,7 @@ ui.register_button("home_gui_set", { else minetest.chat_send_player(player_name, S("You don't have the \"home\" privilege!")) - ui.set_inventory_formspec(player, ui.current_page[player_name]) + unified_inventory.set_inventory_formspec(player, unified_inventory.current_page[player_name]) end end, condition = function(player) @@ -68,7 +68,7 @@ ui.register_button("home_gui_set", { end, }) -ui.register_button("home_gui_go", { +unified_inventory.register_button("home_gui_go", { type = "image", image = "ui_gohome_icon.png", tooltip = S("Go home"), @@ -76,13 +76,13 @@ ui.register_button("home_gui_go", { action = function(player) local player_name = player:get_player_name() if minetest.check_player_privs(player_name, {home=true}) then - if ui.go_home(player) then + if unified_inventory.go_home(player) then minetest.sound_play("teleport", {to_player = player_name}) end else minetest.chat_send_player(player_name, S("You don't have the \"home\" privilege!")) - ui.set_inventory_formspec(player, ui.current_page[player_name]) + unified_inventory.set_inventory_formspec(player, unified_inventory.current_page[player_name]) end end, condition = function(player) @@ -90,7 +90,7 @@ ui.register_button("home_gui_go", { end, }) -ui.register_button("misc_set_day", { +unified_inventory.register_button("misc_set_day", { type = "image", image = "ui_sun_icon.png", tooltip = S("Set time to day"), @@ -106,7 +106,7 @@ ui.register_button("misc_set_day", { else minetest.chat_send_player(player_name, S("You don't have the settime privilege!")) - ui.set_inventory_formspec(player, ui.current_page[player_name]) + unified_inventory.set_inventory_formspec(player, unified_inventory.current_page[player_name]) end end, condition = function(player) @@ -114,7 +114,7 @@ ui.register_button("misc_set_day", { end, }) -ui.register_button("misc_set_night", { +unified_inventory.register_button("misc_set_night", { type = "image", image = "ui_moon_icon.png", tooltip = S("Set time to night"), @@ -130,7 +130,7 @@ ui.register_button("misc_set_night", { else minetest.chat_send_player(player_name, S("You don't have the settime privilege!")) - ui.set_inventory_formspec(player, ui.current_page[player_name]) + unified_inventory.set_inventory_formspec(player, unified_inventory.current_page[player_name]) end end, condition = function(player) @@ -138,19 +138,19 @@ ui.register_button("misc_set_night", { end, }) -ui.register_button("clear_inv", { +unified_inventory.register_button("clear_inv", { type = "image", image = "ui_trash_icon.png", tooltip = S("Clear inventory"), action = function(player) local player_name = player:get_player_name() - if not ui.is_creative(player_name) then + if not unified_inventory.is_creative(player_name) then minetest.chat_send_player(player_name, S("This button has been disabled outside" .." of creative mode to prevent" .." accidental inventory trashing." .."\nUse the trash slot instead.")) - ui.set_inventory_formspec(player, ui.current_page[player_name]) + unified_inventory.set_inventory_formspec(player, unified_inventory.current_page[player_name]) return end player:get_inventory():set_list("main", {}) @@ -159,42 +159,35 @@ ui.register_button("clear_inv", { {to_player=player_name, gain = 1.0}) end, condition = function(player) - return ui.is_creative(player:get_player_name()) + return unified_inventory.is_creative(player:get_player_name()) end, }) -ui.register_page("craft", { +unified_inventory.register_page("craft", { get_formspec = function(player, perplayer_formspec) - local formheaderx = perplayer_formspec.form_header_x - local formheadery = perplayer_formspec.form_header_y - local craftx = perplayer_formspec.craft_x - local crafty = perplayer_formspec.craft_y + local formspecy = perplayer_formspec.formspec_y + local formheadery = perplayer_formspec.form_header_y local player_name = player:get_player_name() - local formspec = { - perplayer_formspec.standard_inv_bg, - perplayer_formspec.craft_grid, - "label["..formheaderx..","..formheadery..";" ..F(S("Crafting")).."]", - "listcolors[#00000000;#00000000]", - "listring[current_name;craft]", - "listring[current_player;main]" - } - local n=#formspec+1 - - if ui.trash_enabled or ui.is_creative(player_name) or minetest.get_player_privs(player_name).give then - formspec[n] = string.format("label[%f,%f;%s]", craftx + 6.45, crafty + 2.4, F(S("Trash:"))) - formspec[n+1] = ui.make_trash_slot(craftx + 6.25, crafty + 2.5) - n=n + 2 + local formspec = "background[2,"..formspecy..";6,3;ui_crafting_form.png]" + formspec = formspec..string.gsub(unified_inventory.standard_inv_bg, "YYY", (formspecy + 3.4)) + formspec = formspec.."label[0,"..formheadery..";" ..F(S("Crafting")).."]" + formspec = formspec.."listcolors[#00000000;#00000000]" + formspec = formspec.."list[current_player;craftpreview;6,"..formspecy..";1,1;]" + formspec = formspec.."list[current_player;craft;2,"..formspecy..";3,3;]" + if unified_inventory.trash_enabled or unified_inventory.is_creative(player_name) or minetest.get_player_privs(player_name).give then + formspec = formspec.."label[7,"..(formspecy + 1.5)..";" .. F(S("Trash:")) .. "]" + formspec = formspec.."background[7,"..(formspecy + 2)..";1,1;ui_single_slot.png]" + formspec = formspec.."list[detached:trash;main;7,"..(formspecy + 2)..";1,1;]" end - - if ui.is_creative(player_name) then - formspec[n] = ui.single_slot(craftx - 2.5, crafty + 2.5) - formspec[n+1] = string.format("label[%f,%f;%s]", craftx - 2.3, crafty + 2.4,F(S("Refill:"))) - formspec[n+2] = string.format("list[detached:%srefill;main;%f,%f;1,1;]", - F(player_name), craftx - 2.5 + ui.list_img_offset, crafty + 2.5 + ui.list_img_offset) + formspec = formspec.."listring[current_name;craft]" + formspec = formspec.."listring[current_player;main]" + if unified_inventory.is_creative(player_name) then + formspec = formspec.."label[0,"..(formspecy + 1.5)..";" .. F(S("Refill:")) .. "]" + formspec = formspec.."list[detached:"..F(player_name).."refill;main;0,"..(formspecy +2)..";1,1;]" end - return {formspec=table.concat(formspec)} + return {formspec=formspec} end, }) @@ -213,18 +206,18 @@ local function stack_image_button(x, y, w, h, buttonname_prefix, item) local selectitem = name if name:sub(1, 6) == "group:" then local group_name = name:sub(7) - local group_item = ui.get_group_item(group_name) + local group_item = unified_inventory.get_group_item(group_name) show_is_group = not group_item.sole displayitem = group_item.item or "unknown" selectitem = group_item.sole and displayitem or name end local label = show_is_group and "G" or "" - local buttonname = F(buttonname_prefix..ui.mangle_for_formspec(selectitem)) + local buttonname = F(buttonname_prefix..unified_inventory.mangle_for_formspec(selectitem)) local button = string.format("item_image_button[%f,%f;%f,%f;%s;%s;%s]", x, y, w, h, F(displayitem), buttonname, label) if show_is_group then - local groupstring, andcount = ui.extract_groupnames(name) + local groupstring, andcount = unified_inventory.extract_groupnames(name) local grouptip if andcount == 1 then grouptip = S("Any item belonging to the @1 group", groupstring) @@ -264,33 +257,26 @@ local other_dir = { usage = "recipe", } -ui.register_page("craftguide", { +unified_inventory.register_page("craftguide", { get_formspec = function(player, perplayer_formspec) - local craftguidex = perplayer_formspec.craft_guide_x - local craftguidey = perplayer_formspec.craft_guide_y - local craftguidearrowx = perplayer_formspec.craft_guide_arrow_x - local craftguideresultx = perplayer_formspec.craft_guide_result_x - local formheaderx = perplayer_formspec.form_header_x - local formheadery = perplayer_formspec.form_header_y - local give_x = perplayer_formspec.give_btn_x + local formspecy = perplayer_formspec.formspec_y + local formheadery = perplayer_formspec.form_header_y + local craftresultx = perplayer_formspec.craft_result_x + local craftresulty = perplayer_formspec.craft_result_y local player_name = player:get_player_name() local player_privs = minetest.get_player_privs(player_name) - - local formspec = { - perplayer_formspec.standard_inv_bg, - "label["..formheaderx..","..formheadery..";" .. F(S("Crafting Guide")) .. "]", + local fs = { + string.gsub(unified_inventory.standard_inv_bg, "YYY", (formspecy + 3.4)), + "label[0,"..formheadery..";" .. F(S("Crafting Guide")) .. "]", "listcolors[#00000000;#00000000]" } - - local item_name = ui.current_item[player_name] + local item_name = unified_inventory.current_item[player_name] if not item_name then - return { formspec = table.concat(formspec) } + return { formspec = table.concat(fs) } end - local n = 4 - local item_name_shown if minetest.registered_items[item_name] and minetest.registered_items[item_name].description then @@ -300,60 +286,51 @@ ui.register_page("craftguide", { item_name_shown = item_name end - local dir = ui.current_craft_direction[player_name] + local dir = unified_inventory.current_craft_direction[player_name] local rdir = dir == "recipe" and "usage" or "recipe" - local crafts = ui.crafts_for[dir][item_name] - local alternate = ui.alternate[player_name] + local crafts = unified_inventory.crafts_for[dir][item_name] + local alternate = unified_inventory.alternate[player_name] local alternates, craft if crafts and #crafts > 0 then alternates = #crafts craft = crafts[alternate] end - local has_give = player_privs.give or ui.is_creative(player_name) + local has_give = player_privs.give or unified_inventory.is_creative(player_name) - formspec[n] = string.format("image[%f,%f;%f,%f;ui_crafting_arrow.png]", - craftguidearrowx, craftguidey, ui.imgscale, ui.imgscale) - - formspec[n+1] = string.format("textarea[%f,%f;10,1;;%s: %s;]", - perplayer_formspec.craft_guide_resultstr_x, perplayer_formspec.craft_guide_resultstr_y, - F(role_text[dir]), item_name_shown) - n = n + 2 - - local giveme_form = table.concat({ - "label[".. (give_x+0.1)..",".. (craftguidey + 2.7) .. ";" .. F(S("Give me:")) .. "]", - "button["..(give_x)..",".. (craftguidey + 2.9) .. ";0.75,0.5;craftguide_giveme_1;1]", - "button["..(give_x+0.8)..",".. (craftguidey + 2.9) .. ";0.75,0.5;craftguide_giveme_10;10]", - "button["..(give_x+1.6)..",".. (craftguidey + 2.9) .. ";0.75,0.5;craftguide_giveme_99;99]" - }) + fs[#fs + 1] = "background[0.5,"..(formspecy + 0.2)..";8,3;ui_craftguide_form.png]" + fs[#fs + 1] = string.format("textarea[%f,%f;10,1;;%s: %s;]", + craftresultx, craftresulty, F(role_text[dir]), item_name_shown) + fs[#fs + 1] = stack_image_button(0, formspecy, 1.1, 1.1, + "item_button_" .. rdir .. "_", ItemStack(item_name)) if not craft then -- No craft recipes available for this item. - formspec[n] = string.format("label[%f,%f;%s]", craftguidex+2.5, craftguidey+1.5, F(no_recipe_text[dir])) - local no_pos = dir == "recipe" and (craftguidex+2.5) or craftguideresultx - local item_pos = dir == "recipe" and craftguideresultx or (craftguidex+2.5) - formspec[n+1] = "image["..no_pos..","..craftguidey..";1.2,1.2;ui_no.png]" - formspec[n+2] = stack_image_button(item_pos, craftguidey, 1.2, 1.2, + fs[#fs + 1] = "label[5.5,"..(formspecy + 2.35)..";" + .. F(no_recipe_text[dir]) .. "]" + local no_pos = dir == "recipe" and 4.5 or 6.5 + local item_pos = dir == "recipe" and 6.5 or 4.5 + fs[#fs + 1] = "image["..no_pos..","..formspecy..";1.1,1.1;ui_no.png]" + fs[#fs + 1] = stack_image_button(item_pos, formspecy, 1.1, 1.1, "item_button_" .. other_dir[dir] .. "_", ItemStack(item_name)) if has_give then - formspec[n+3] = giveme_form + fs[#fs + 1] = "label[0," .. (formspecy + 2.10) .. ";" .. F(S("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]" + .. "button[1.3," .. (formspecy + 2.7) .. ";0.8,0.5;craftguide_giveme_99;99]" end - return { formspec = table.concat(formspec) } - else - formspec[n] = stack_image_button(craftguideresultx, craftguidey, 1.2, 1.2, - "item_button_" .. rdir .. "_", ItemStack(craft.output)) - n = n + 1 + return { formspec = table.concat(fs) } end - local craft_type = ui.registered_craft_types[craft.type] or - ui.craft_type_defaults(craft.type, {}) + local craft_type = unified_inventory.registered_craft_types[craft.type] or + unified_inventory.craft_type_defaults(craft.type, {}) if craft_type.icon then - formspec[n] = string.format("image[%f,%f;%f,%f;%s]", - craftguidearrowx+0.35, craftguidey, 0.5, 0.5, craft_type.icon) - n = n + 1 + fs[#fs + 1] = string.format("image[%f,%f;%f,%f;%s]", + 5.7, (formspecy + 0.05), 0.5, 0.5, craft_type.icon) end - formspec[n] = string.format("label[%f,%f;%s]", craftguidearrowx + 0.15, craftguidey + 1.4, F(craft_type.description)) - n = n + 1 + fs[#fs + 1] = "label[5.5,"..(formspecy + 1)..";" .. F(craft_type.description).."]" + fs[#fs + 1] = stack_image_button(6.5, formspecy, 1.1, 1.1, + "item_button_usage_", ItemStack(craft.output)) local display_size = craft_type.dynamic_display_size and craft_type.dynamic_display_size(craft) @@ -364,12 +341,11 @@ ui.register_page("craftguide", { -- This keeps recipes aligned to the right, -- so that they're close to the arrow. - local xoffset = craftguidex+3.75 - local bspc = 1.25 + local xoffset = 5.5 -- Offset factor for crafting grids with side length > 4 local of = (3/math.max(3, math.max(display_size.width, display_size.height))) local od = 0 - -- Minimum grid size at which size optimization measures kick in + -- Minimum grid size at which size optimazation measures kick in local mini_craft_size = 6 if display_size.width >= mini_craft_size then od = math.max(1, display_size.width - 2) @@ -378,12 +354,12 @@ ui.register_page("craftguide", { -- Size modifier factor local sf = math.min(1, of * (1.05 + 0.05*od)) -- Button size - local bsize = 1.2 * sf - - if display_size.width >= mini_craft_size then -- it's not a normal 3x3 grid - bsize = 0.8 * sf + local bsize_h = 1.1 * sf + local bsize_w = bsize_h + if display_size.width >= mini_craft_size then + bsize_w = 1.175 * sf end - if (bsize > 0.35 and display_size.width) then + if (bsize_h > 0.35 and display_size.width) then for y = 1, display_size.height do for x = 1, display_size.width do local item @@ -393,53 +369,48 @@ ui.register_page("craftguide", { -- Flipped x, used to build formspec buttons from right to left local fx = display_size.width - (x-1) -- x offset, y offset - local xof = ((fx-1) * of + of) * bspc - local yof = ((y-1) * of + 1) * bspc + local xof = (fx-1) * of + of + local yof = (y-1) * of + 1 if item then - formspec[n] = stack_image_button( - xoffset - xof, craftguidey - 1.25 + yof, bsize, bsize, + fs[#fs + 1] = stack_image_button( + xoffset - xof, formspecy - 1 + yof, bsize_w, bsize_h, "item_button_recipe_", ItemStack(item)) else -- Fake buttons just to make grid - formspec[n] = string.format("image_button[%f,%f;%f,%f;ui_blank_image.png;;]", - xoffset - xof, craftguidey - 1.25 + yof, bsize, bsize) + fs[#fs + 1] = string.format("image_button[%f,%f;%f,%f;ui_blank_image.png;;]", + xoffset - xof, formspecy - 1 + yof, bsize_w, bsize_h) end - n = n + 1 end end else -- Error - formspec[n] = string.format("label[2,%f;%s]", - craftguidey, F(S("This recipe is too@nlarge to be displayed."))) - n = n + 1 + fs[#fs + 1] = string.format("label[2,%f;%s]", + formspecy, F(S("This recipe is too@nlarge to be displayed."))) end if craft_type.uses_crafting_grid and display_size.width <= 3 then - formspec[n] = "label["..(give_x+0.1)..",".. (craftguidey + 1.7) .. ";" .. F(S("To craft grid:")) .. "]" - formspec[n+1] = "button[".. (give_x)..",".. (craftguidey + 1.9) .. ";0.75,0.5;craftguide_craft_1;1]" - formspec[n+2] = "button[".. (give_x+0.8)..",".. (craftguidey + 1.9) .. ";0.75,0.5;craftguide_craft_10;10]" - formspec[n+3] = "button[".. (give_x+1.6)..",".. (craftguidey + 1.9) .. ";0.75,0.5;craftguide_craft_max;" .. F(S("All")) .. "]" - n = n + 4 + fs[#fs + 1] = "label[0," .. (formspecy + 0.9) .. ";" .. F(S("To craft grid:")) .. "]" + .. "button[0, " .. (formspecy + 1.5) .. ";0.6,0.5;craftguide_craft_1;1]" + .. "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(S("All")) .. "]" end - if has_give then - formspec[n] = giveme_form - n = n + 1 + fs[#fs + 1] = "label[0," .. (formspecy + 2.1) .. ";" .. F(S("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]" + .. "button[1.3," .. (formspecy + 2.7) .. ";0.8,0.5;craftguide_giveme_99;99]" end if alternates and alternates > 1 then - formspec[n] = string.format("label[%f,%f;%s]", - craftguidex+4, craftguidey + 2.3, F(S(recipe_text[dir], alternate, alternates))) - formspec[n+1] = string.format("image_button[%f,%f;1.1,1.1;ui_left_icon.png;alternate_prev;]", - craftguidearrowx+0.2, craftguidey + 2.6) - formspec[n+2] = string.format("image_button[%f,%f;1.1,1.1;ui_right_icon.png;alternate;]", - craftguidearrowx+1.35, craftguidey + 2.6) - formspec[n+3] = "tooltip[alternate_prev;" .. F(prev_alt_text[dir]) .. "]" - formspec[n+4] = "tooltip[alternate;" .. F(next_alt_text[dir]) .. "]" + fs[#fs + 1] = "label[5.5," .. (formspecy + 1.6) .. ";" + .. F(S(recipe_text[dir], alternate, alternates)) .. "]" + .. "image_button[5.5," .. (formspecy + 2) .. ";1,1;ui_left_icon.png;alternate_prev;]" + .. "image_button[6.5," .. (formspecy + 2) .. ";1,1;ui_right_icon.png;alternate;]" + .. "tooltip[alternate_prev;" .. F(prev_alt_text[dir]) .. "]" + .. "tooltip[alternate;" .. F(next_alt_text[dir]) .. "]" end - - return { formspec = table.concat(formspec) } + return { formspec = table.concat(fs) } end, }) @@ -447,7 +418,7 @@ local function craftguide_giveme(player, formname, fields) local player_name = player:get_player_name() local player_privs = minetest.get_player_privs(player_name) if not player_privs.give and - not ui.is_creative(player_name) then + not unified_inventory.is_creative(player_name) then minetest.log("action", "[unified_inventory] Denied give action to player " .. player_name) return @@ -462,7 +433,7 @@ local function craftguide_giveme(player, formname, fields) amount = tonumber(amount) or 0 if amount == 0 then return end - local output = ui.current_item[player_name] + local output = unified_inventory.current_item[player_name] if (not output) or (output == "") then return end local player_inv = player:get_inventory() @@ -483,21 +454,21 @@ local function craftguide_craft(player, formname, fields) local player_name = player:get_player_name() - local output = ui.current_item[player_name] or "" + local output = unified_inventory.current_item[player_name] or "" if output == "" then return end - local crafts = ui.crafts_for[ - ui.current_craft_direction[player_name]][output] or {} + local crafts = unified_inventory.crafts_for[ + unified_inventory.current_craft_direction[player_name]][output] or {} if #crafts == 0 then return end - local alternate = ui.alternate[player_name] + local alternate = unified_inventory.alternate[player_name] local craft = crafts[alternate] if craft.width > 3 then return end - ui.craftguide_match_craft(player, "main", "craft", craft, amount) + unified_inventory.craftguide_match_craft(player, "main", "craft", craft, amount) - ui.set_inventory_formspec(player, "craft") + unified_inventory.set_inventory_formspec(player, "craft") end minetest.register_on_player_receive_fields(function(player, formname, fields) diff --git a/unified_inventory/textures/ui_bags_header.png b/unified_inventory/textures/ui_bags_header.png new file mode 100644 index 0000000000000000000000000000000000000000..f9bf1dd8fc6f88bb368143f28bace184e5125001 GIT binary patch literal 1241 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 O5abzWn@TIc+y4QNH<3{Q literal 0 HcmV?d00001 diff --git a/unified_inventory/textures/ui_bags_inv_medium.png b/unified_inventory/textures/ui_bags_inv_medium.png new file mode 100644 index 0000000000000000000000000000000000000000..5924f54661010db89ab6dba906da683e608da064 GIT binary patch literal 2300 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 NSeP(uXnXJx+J8?}Q>Op` literal 0 HcmV?d00001 diff --git a/unified_inventory/textures/ui_bags_trash.png b/unified_inventory/textures/ui_bags_trash.png new file mode 100644 index 0000000000000000000000000000000000000000..824713092ff04d8eae8d59dc1e90c489d472c28d GIT binary patch literal 1157 zcmV;01bX|4P) zohN_;NKvF5BD3~WM8cFcr{O>Ag>Uw{L<#H2%yS_xl+i4vvyBvqbk=N2Bkcdt)(gC0& zB__qz7P`iuJ6Y2m09s-uOi3zFNCb$@0~X1hF(V-*t)*BpBY+MPt=cDdMvOzCYdUnq zK;A*3Rr};7I5bfW#FCL>$vQ~1YNOVeGbUsN$hipSIAU@V0`i)8ny6c~QES4Kzp+Tv z-1#vjVTMH#V2N9)TeVTEB`wz<#B(WL?r)-Q)kdv3pvVaTi+iKLiMmxAwfgU}{_0k3 z)atK#e|4`N!D8*nRuRn02wDuL+cjuOn85|L`dV6k3fNk)>QKem1y%Z|I3@Pn8`k>o z07*!KB_VBel=`>G2WUc%JgD{5r-`sQVk`oQ^o*m$k>L=SqUTuqq`VfO#6UR;u}H>5 zgnpwJrq#1!MwqpK;Mx%syj+QOs9)dOr_3EK@R6RdS1BzRDx}2F%Nn7XN<8w9UAcv1*L zkD-S*V3D#JF)7p9D1F@}p)m}+TTsskifZnhdaAw{8x1^$9*x$Z1adNu0c2sCkO2eF zky9fT7l}6BDb@|=3(CI&Y6QkJg6Hp;dH@W(hnJo0#oKdZVe1bI!7@OxCGnHUxqEkN zy8w%K09oz*Ud1I}<(|sC3JVDdG3ZwdfcB}~IG)CoL-x@x3xLU~W3z}7!;mo{A*0hp zz~_kr*|3~;5xs~#_8Fqkh-V9cKga1~P=shSqDM@DX2_TW-r`yTc=B1iq~x54{l5+l z4FPWM>cmy+Rw9WQGGbJm!C$^Udf=9BA77dMKg?l>MxlDzSpo!#kO2mPz`dN_{y1K_ zzkMytqv5wvt2Z0|fC7asLUJ?sw!7k*S&l9&YU?DD0Sh&h3V6$&jy3{ z@8AFZ`}fP2FFC&Zb+qMBM1zNFg-MYBAxE(uo zT)TEHKR^Hb_wT;GzCfn}-5eSkdh6D$($dnhva+>n*S5B{-nemN(xgd1m)P6ecXoDe z*|KHRrcDbMF5IEakt5%>0vYjH@RK*PmzE^3^O67SyW z<*TgQv3vLL|K@3qj-g?bSy}hkr5FD{5FT58S@tw2lA++hiHsDtuW2dAKHPZa(ZhQ^ zZ++*U6@K^kZnV9$=+}dbtNEP+)z+-v@+Ca)Z`jH|HPc?*w~Vcct`SN-H0@-PrIc~{ zb+gE|{^qyfXNSYQv&$TO!0WITMQhe4QOUahm;sKg-WAUuTYdS2nD=@0K>lLh`>U z%x_@&Mb{OHjw=y@D>rKWqMth^|`6r5!k z7#JMFmmG8WlX`>uKpcY_S>__#V%_+~C9A|Gi^nbN%TakYpy>>M7?>Cv4hjF;KN-aH MboFyt=akR{0KFTassI20 literal 0 HcmV?d00001 diff --git a/unified_inventory/textures/ui_crafting_arrow.png b/unified_inventory/textures/ui_crafting_arrow.png deleted file mode 100644 index 6901c58888398695f07f51a97b6815b92c7c482e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 788 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H0wgodS2{2-Fx~caaSW-r_4dYDZ;?b9_7CsR zXuQ@t|7O?ajGihj8yCSVXT3{GBwyJJbl%&rNZjbeo1<|$hSiEX!m1q?irN1P{}SF) za+S|fV2au_WB>NT;On8~->;l`|9hui@sGOi55MnWaKQ$?*jr~@`!;vx6sB+fWml#g z_3~moZqJrmohG*BhG@c~r(3M=C3fg4G;~ihes?=ddxf_b$@YX$p7wwy!O+_y> zl`Tm)vaDrS{X+Aw1SbDK1!X(hm|iWM(D_rR;~cxhr~0#fU6M`F#}n_}_`RyYF@fJ-mFPvvN_uw6FVuBla0>%gOy2Yg&=#QBN>|8!^VS#^6s zlkDPRhXzrWXfwO*7QeRaTXJmG9zJ;oYpEomde-}9xp{$qmVNy({p##h_nG^Y_>IN* zmG*yRjsGaj>oK*Pzc#q{+6RS20!lqcAH^R~uW4(pefs$O%7=6J-QU)5_+uq6GegPi zO&@<>y^t5aw1tCF!sB3^eC>tpS0CSf-^F?Bd+>>cl6pY5?9SRS>2y(2-rtv7fApR> z)UC6k(zs~wEk4~SE zsn=z1m(QX5V0YZ5ZsDZI%%`ggi|)0=c)xc!&i*XrxVjPs(0Z=#c479d8~ZI*15-PL Mr>mdKI;Vst09D^+`v3p{ diff --git a/unified_inventory/textures/ui_crafting_form.png b/unified_inventory/textures/ui_crafting_form.png new file mode 100644 index 0000000000000000000000000000000000000000..904328799f0095583663358921550fe04a99fb02 GIT binary patch literal 2343 zcma)8c|4Ts9)D?$Gs!Yz%dup7W$AD%sgRv9hA`Br6lIyIAraY^XeLQUldWcuu_SJX zvd(ZRLndp7QehCHLy}R^plP@>y61Cm=bn4+eg1eqzvuV3VB zTgDZwqRH;}TB?T3J91Xb&yM=p^5mcK+aZ_|V`=u4u?*URM)Oh*d`=?O#&BOjesjnp z5IbC%%Q0q{2NkGBp5?q54U*iXp1luiy@U11B*m+jX0d4adx_=N-i7G!t&*Y{0cZeg z6wG@4^VHIQW05-VJulCmi8+%vlmFddtu-z-^Mma7Yn@}u*HBLqUW6w;4APRNompkr zgU{pw`in;9-#xf4;?MMJOq6NW(u)(TxufM1t%Pe>qeuetN1T^2ptkODK>gu!qmUgT zlqg`hlFBJS`T)r0oeJuLSuO{oc?tDPA^(@zwWM_{m}-rLr)Z19?GeRLq#Pjygt
ZEv7VNgIIfqiM#UpE34`10a@rQScZjR5> zXw+Z-qBUw`P6wG^j7e#5!?byX=-ySn>(E9 z3Jx4ewT=u`Q}31ya5r%19bb`lxv^@Q7$STvt8w0O?3q1lFYXPe%qJ*YO)Mw?ortl? zxr+9__1B4%bNW^Yv-jspdgTZes9>J`jvCeS^|r*BQp1`&wSKeU1w+zOBwGBywh7vP z?yg!#IJ$M0PF^JS=xr#gI;n?xJk@$Sa>(*jPJ$wdpIeF8{LSXK7?k!6p@fjjf}+t> z%WEAXLpT?nd_O;{NqGfqH7MOV+1cgjXeV}ot5eF;g1?jMa@b~2+LiUJ#F6ynSRh1r zrU`vPZLon+Hk=Gab}NWDxKi|XuBOyS-rMBQJl!}x^l{W_sx7kIrLYhoT;XYwL+IIYLn^oY0~$>1{=4hq$+jU2id2avdWTuHF|fH>@HSg%X`k9i1u$u;_BSy zT{Zg<+sh9ampWFJ;-0&s)RFN@FG7#Q49?gr#IN#*dqX|HCC%-vTf38oO2noSe{bAu@14#l$Cxws=`QH z?9rR}$j=YuNofI0lw9jGF57o`n%w(xz(AY#Q?*D2Y;X#3&NPnuxZ`WVRM@L8WQVAy z2v|-s#9;3f%Gq^~D>GcynzyGIx@}}U2H*Ng7nVcAePI!-YL@x8-~s|WHq7H5X8knI zK;v>jmwn+)`48%M0rP{&;0o(xpY`5P5DCmhiNW<6kwX5k8|2dMEj~zUtQZ->`6y-0 zqZdIXE_50{@`G%|V8)Mvqssgv9siW0|9|o^@K0KQv&0~6)`;;m;k-66DQR{wTIGVv zK%MuN)Ix&3j083pB;UN5y&DJkGxy51a?;~pi(qrjO5;p82}B}VJEGlpcMg^iBNJU8QIRMqEape*v^(?vVH0nHJaYGR$I5D;}P7wslhf zoN>IG&bf41%-NsmDkpNE7M3_%e^Ei#FI)3UKxRa|78XjYsNE`VVgrOq(Dk7zAygq*Mk3U1?s62 z)%^S@1+PBQj9JHajLM37+_;sJ4ewA^(uk|3Is0P}30bIKy6? z-HLy?cxQPEYTE^mRtldr#Gq6@zMYI{7dFr|p{scJ@M1V2CKXH2;kx(RrH%$RM^A_e zY+K$Q_$w(B$W62le5Gyhf)6_82QWG6R0|9iuFqrGOGw{a>^7;=_J_@U@|QQGw? jlec05o}Jtfv9&D{HJrW~MBtj>2MBPqcSYW_^&$QP6{$O_ literal 0 HcmV?d00001 diff --git a/unified_inventory/textures/ui_form_bg.png b/unified_inventory/textures/ui_form_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..7111fac93eb3b59de8228df357c6dc6d3bee9312 GIT binary patch literal 1003 zcmeAS@N?(olHy`uVBq!ia0y~yU;;838#q{iRH3Gj2?GQ3CQlc~kcwMxuPO2|88WzB zY&79`_5Dvww|0XbQ)`0xoyN-ZSNt#CpO^Ptbiu_l5tX+Xy?RwDZ!o^fac2mNyVjs} z{XV}!WMwohAEqTvQwx!j0YudUN$|)(WHJ$o&?biGTx0bEnKC^xM zaxZj>`LUXMr{g)dx0O^rzw=(wV)?aQDV6X4{t)O7@`_wl!;x6WeRfiD+@hME!e4Ln zPB8X)30(yd6lo#^8%3Ik zUaAQ_moB|00-8t-5JDg!$t3E`oi(%8%$IlG^Wl_rPM&9qRuZXpP3U8ih60sA{TsNsUDgVEL3bbydm%~ zo-hh(j`tN%eQ-1Mv1jN|bBAPwd0Xc~cPDjG*?e@;&pR}rr_%sW4e0{TcmGbHhI2OV z2Cds42Z2DVcz~3io%uOAWkwL(cUCBJTM|A$O;^rh(SYn>$~wV9o8=ew=eGIL`R0ns zP$!TA;x3xSauDDhM4(G#a?B}XipwRrXue##e8SjfEhNXJ(-3~WM)C{3{y6P>5yB`3xYe6;D1S?0cBz zcC)+ptIl54@3&9LTZo**PQ#vOevR>Aokt@`S7AX@zd{judJiY#FB(4Bxgvpel)C4* zsF6$sd!_lBc8f=vwvCiXb5LuYjgvnE7us#l89J@EZD`pi#yVe!Vsv8nVOZRD5g(@+ z^vbs>D&26<6~cPRFpBH@Ot;jyzoG6GPqFgYf;%(|x~}F|-T2DL-KC3m;l5bK+&IA7 zd@QdG4q6-2b*+$3D%+)ll6cK~i+)6e(|6sb_@}tls)6DCb|?0>_Pr-)g6Y?1E@dGaL3}0xJKvx2{?X)n5(oI9dC2R@ z8;u`X>8;#uHgws>0-GNKjubs8Y7!OGB5?YLMlP$&hA#=};K}GKocWxBm{`G2X(`Pm&KPh4SD~d1dd>;ziw7aOuUCd_L79%FFXO)*W}2)v ztclEtN&bwB>Rd8*I6am+3aU4RQm3+*d0VcAvPwTvKY*ye z*zJrCU5*`9h%;(YBT5YIe8UK8p2ooosPnd*bxar?{>Y$fG!|U+qpT9T-NMqvBBhER z)JYjMa!|(gQEAW)N+S3m)S|W02Wt_yk*KEJH2~hw*@)7~B!TFvKNZYvJ?|KqhXzXL z{Pi^Lr6P@~oO$3zt)x;heX)A98dg$+AqgHbY2h_s($5Ao_mma*a6`Yp@NV3t7MK*D zQS8=ce)4CpwC&^qy{^4;h8ga`F|D z)qSvLz&P(@^rifvn@~y2MBw+cING~o^QfB)ZK@mGF7>G8oXabuNw_EeayrAYrz8Z3 zrWwp4&?8??!EU*{gMFxL2W@w52PXIdz|#s?Ql=<{^ko(QysHKZo|Lw*ymdjUx57%| z)@d;)nHE`#qQS-_Ppzs$@7x)&IL62pkygMkl+~9fiT3*H`sE_(O|z>x!A93-7pcWe z-_G^kRY5(=1!*a1(A4>FkQM`hAl4lD15|0dC#PoBUL*RgV<^MCO*Wxrc!KmXOh?=@ z9nP`;wy06qmyShLmLXRfAEUJ?WF8eOl}tRVOTNZ2mhB(J@6O#-oNZpUcIYuG1x^e^ zKfuyXz6)7Oj8zug7c=h)tVEjQ744&zwS~iSj7|32L?zM+x~H|MC^^FCVRj;|-P#?; zs9vl!`>Yq6>KVEvNW$1y+q`ew<^;rq5M})!%qDHcf*%8sO*l<}Pu)5pkUr)$iVLY2 z++7A?Mb4TNkr-Vko@|WPI0~l^;Qt@l@Nck@2LPgHZQFk*DbWU9feF|wT*vyiHxW%z z$r0rpIhVQ_U$+>8${E-SYfxW#WW$%R47y-*a|F0iY-w+VRhrd0tDc(>)5Y=RRj0#SyR;xo4DDH87 zOUyKM69o}IcBxjBypJAxqfGZ0Vx1(d1W=O`XC0OA6=tPtNZ#?Y=ITLly^DR26R1m? zYdk@wx(?xob-(kOF3J<}bpp6&a6>V+RAk)L(^s|H> z2n$Q^S|z6l*1C6PJjIEMRBLDYajZBuj?AN~%u7d=*2Ys#j-dsI%TT3^ytw;cQ&D>z z{t|(MRaJ{5`d0o0qdzk26I`1MIhSl~Qik}HFBQp#PGCfoCss7G z`RY*FXzd;x69zzxxzGi{NzcxMtjCD4h7pHe9GAE?wOEJU((|cU63WjJSCV@p$vU;s zV_^_5Tt@Ag-OLK(+wj&OH89gV4(fXa{LPckHsRueP%m(GT#RCw0q2aj5qb;2te#iO z0Ri=;5HhBpiZ~BI)mB^RO*C0d0%K%$&2ZZNFEOWM)hdDW?6f-rmF(1|w2vI*RL5tQ z89E!Sj;zh0?cPUEmz!g+2T+3JpB84UlB!n~6DkER(ruUKuV7Z`m5^XG` zDAJ^$Qa2E$R!Gu%BrIt>q|vEKND0BodGrpmX*8MVa=G)vo8^kd|cYpT<2CZsin03e+@Ma6-36e&r2{-|OR4 zTP3l}X1}6rGVilVe6h^(Nmr&!oT*Hp$`R>FgBOQ3sV!dNWIfCmb3k4^|orY zCPh?8`@cAib2Hm-^ydy0!pFv&4j~k41}Nr!=Yd34-rLHaOxuOv`5#`g^Oxl9(eB;B07|Ka!jtHhq-3}hiQw|!3n=C#-9t*Wb`W(midV3v{nL*>ViRaUr~kL!8!vE z2vfY-h}f`a7*0!bvgZ}cw-v!IKr&0W?nN0(VO}Piv(+^i`RGXT0u6G&oU@zD3K?xT zMhFc?sN6O_%zh^ZXHV+zDUvzf!CX`j($`R<%%|Kn2;Rz!6U(x zaMvCGqm{;g$AttSqG3(-nl>znXJqY&UBqk5)wA_e!VdK#*T5%{H0Fps8MkaI20E}$ zK~5ZdF9dAuEWUA|?u!x)M#T5wvBR4>;UYVCy*DezRCQn-9DUH<@w<;mDQkUn(j*M@ z{KHP8Q<#K6>u(&dSka1h-JGN1;@v3`dPKhVEt0KxVgU z%K)uhWSkAp3bk>FY4Tn^La0CEdH?8@r}yvEAMNw|cv+Kh`vO;_L4gWuC1@T+T*yE) z?7umShun!Mm`xKmNUkI@_}XejH+qWDQ=?oLP=Yoh$l>|;j=zN@{vbwGv+?MK@F;^l zz`1=i>LjiWC!f@^_95w>Wy@vLw^T?KqNnkmvd5JrVamRv_-!e32z7}x{>KP^*q?qy z3%NXIT3x5>x1+J9~#eQ@e_6h^uH2 z`bHn#hnomf)G5SJP`{W`NI&@(PfDr5?CYCU$EeBD>(1?v*qGnbo&P{%&>voNrQB;6nF*O&_{;F8RxS``=pF{`i~x z+k@=v{a-fPy*gNB*=u-n->VPt8qNzRwF}{qAXli1`@R$bvOk~-Or^4xUp4Xcsw&aH zghm+4VpK`r1f;JoK{s>Ixucnm3S<8N@Bab<<3`^+lZ`IzNhFxYz!-#!fsL(MiNh^; zkow@ro4@oGyHWYkwY1vPg=WjQU%zC$VKGwTHW-)ICZ_GhGzg;Wds=QUx0~oF2PiU3HGZBTAmtn4X zA8+kXX}ZGJidG}R)@f?ZILZ5f{$e+=x}mG`BVrgEVH7^oDWJvcpcjPgiW&Zp-}=d0#wp{ZoUqy4O1WO9kYkYf_x#l zQ>n}Bb`Zyw{e&5jzzPHQOJH0r3`1_uV+gX_3v|hLAW^S2o4}66H>glk5hhUL)0php zJh}KX;p_N#%;**t0RZ<38<$+?#tfM2^RaTx z9C})hn=QJ~OMBD_mh1DCCSP_)K8>k!B6Wb5EK7M&h81|+-n>KR9br8HDWrkHzNhW; z?AJWEHoNEJ7B@qtgVIrsyoVi)r>qMrQRtHt1(fp^;tV-!=mQxRpuu%{P44-4 z6LWw(biV%8nJ{YdnGl&wzP9k_^jK{-%J*cT)F$rrrVC-Y;_kv}ZD=Ui7Qnic=Ac7d zX4_L%$H}46?+&l_K{J%a^P2GKah*MwyR2CGzGu7M+{ncWNm=U{7BTCmccj#fP_M=X zUaufORq`>DpWyYg@G|W${qU(~0+d3r=-KUQGsXl999at=q(f1MA z2=6w(n)`7TLMtGWJRCF6mR$E-o@}vHaGT1f1?n9d^~$`+Lm!-d${pD5f(DJnJ;*!d z`}jk#wW@Zo_$+zXFe3|PHy_ED^bgs;x+!eH^m+KD|3|yS35#t!8V@k2W^Fw4``5N9 zB7K(CsdOIFsq&-c-ru!8JL;pPqW|ZcHJ?x1k%7OUOq;397oLE^C39`z>wafKsYpMd&F$q%KvCPFSH6JO$P>_DfZ+e5H zG6V{iR-{w&xSV=P9ju+M_~`QV(>E!Y(QkLBwsCZ)9r{C0q9NC!X6c(ZMI)iAY{w8d z%TF6c&KP?`5Alp%<8F%PNqDcRc#qDNARirB_Z1x!Ikgl}3olFxM8I>NW67YoRY6tU zbtk7SDoj?A4M)S#Pbc1&)rgsz@;Rpn9H_yglgrPL`dTnusv&JRmy^$4eGPyW$FO!` zJAx?~lU4M&B7gL1V~yvQseFyAC+`gKcF(kayww^f$>7FGLrTq4A|k{^9-UzE6^jm+ z>O)KnG^`ZxBQ#L2A{jBG>wCHgN`yf1WCH;SVQSrxMyo4(S1vcPiB|J7G8Is|E?Y2H zV$!^P&5!3rTgG>P)!9wk(cMy7hn8LD({8I8v41+-9volU1J`Lj=Q<=W``ku8-5~Tc zy{-VdUu>uN8CFE!O|QEb*yxbAO=a<*$5V@q7ePMBxauYUC^uUoV#uF77$-`s3ou?k z_GWaMn#$PD6#SkbP4#}31?a{uN8zc8wDwkD8L{L)(_4TdJLvFkSfEFYLku{_V~OKi z!?>IB_tYPPPxK>qopyB8NZ}ngKB6P+vb;F|`F#i``Apq*cAOr6(G)egw*hd?4a~i7 zsAj*ML#dC9=d>L8cu^VlFmLe9$7aiCrp187VuSP!>WBP1rh>>{B_e_?CO7%^KN%!! zbuR8k<8QPzhmRjH%?9*EXH2JbazMj*m#h;n-aD8t+_}?Y@*ChoG^2H_#e!S6Ft`-= z8-2u`aO-B=#>!K9l#CczGbbDc#K$vat4j;!Y_YI8q*KI0nq)F58mT@n6xiTb{KVvX z3IAtsBME@>eT;qckr{g!EPBg%rV{06jGupTgJhf1U?8C6GJ;|T&DL7>aJ_c|Jx|)E z1@o|2+Ik??DL_5R;TdT(e-kdhNUEWVz3+Xfy1dh0*{y(LZ5n7En_9Q; zdld6v84czQ`;+hc{cXrK0f)`co)L+Lby5w`Em+ddRv0N~%#QV35 zMwcs+Jyqijn9+CsHni1uCR!UI?7Bii7#(nfgNVAG8q=}B?h5!vt>)-GA*vmS=iU(z zhx~{nva#`PUG(V#1xTM&QTf4Qz-Y&9Cu+_K8`COLl+<7o0ZE-`H8*!X6A`7T^jt6s zc~3qo(qYX#5f1;%eml1>K#;jam7< zW?<{)MNn@xV?b;Zau6rdihJ3(ET&F7krAf6G|#kPIsVcro0N+)q%L}k$B!S*o(CK? z!N=Qc63;o+()bt~O>$c3|2Snbi2zY?zmIoE&eb%waMUnjZ|bm<{`Hd;cAy z?<>Y(%O@nX9$XqrT1A+ZX9X*=DL4^!Y}$O6HuRhVey)aTo2THW!w0}MrHGj77#{= zSsm{Ft3xzoY0RsrQbfub$A_qOU7wV*B?`rA*3Cz-J+8y#UH5bKfJ;$(RuP`q7rK{_ zwX&Z1=7+t|zf*@~Fftzw8tv6a<LBXDG(% z%HF;$YUuTM6qUj=^{)WqN{K&kznE`H5>A^8v=rnUn1wf$|OP2M`G<%#))HbBxYNEmy7@&dA{vam5*BeWu z+K2j9Vbw9Ttr#%Gf}{{b;b3@;9R4!epX~(8;;g;GE@2W+@0;qF{~)lssczkXXpgoUnNy&<0ilzgDz(i0ro_snlGsNOP-*KoZgkGHV6 zh_Gvv)#r?jBa2N2{zwwssMF14Alh4a$P_@A%@4^vhyIl&jGZ=gZATGtk=c3p>Eo=nWl|ND(|{MlYwtupK10aL*YNaO>LuJ<3<+jld6!whN_!+NNI4ZpyDx%0H( zU;6B_sv7fKKTy2EZOxq+PU2fp9`~<2iG4_m-hL9YBT828ohaK0RwGECnOQ{gDy}|q z;?ZbWPv@m5x6N+j`IkGx@)d`Ra^axmoYxN(858fA>ekz@2jnnz`$XTpF`FGn;(YT7 zUgo%DuE5Azp;dO!zTQ*T9f~mL75kjLI;71#G5b4E;gJ~J8T3N}9V^t5-$k#INkkK3 zSP#^;VK~IsMBoeU+hAn8$Og5--ii*Y~Zh- z%|@S0boM7_Jka&K5dNG$v@S)rY=jj6q#5%l5f-OI-j5UyuvCH}ZS4ay_|+KT} z9=;$+HI0;@Kjl$TnG2YYbaN<&uGIAv#fMnXPVA`3xTiSoFV-L5*OR~Ab8@@O&KmJu J>7|?h`B$Kb45I)5 literal 0 HcmV?d00001 diff --git a/unified_inventory/textures/ui_single_slot.png b/unified_inventory/textures/ui_single_slot.png index 2451623c93dec16b8c9c7d9a1c156857930ec58a..63da98d9188248e4fc8fa0f1d0a626af809e2b0f 100644 GIT binary patch literal 629 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 literal 0 HcmV?d00001 diff --git a/unified_inventory/textures/ui_xyz_on_icon.png b/unified_inventory/textures/ui_xyz_on_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..003ea63344be5dbf1f7a2b5da8eb6911e4aeb329 GIT binary patch literal 2182 zcmaKu`9Bkm1I8!i*i}f5ZKO}BIX{lcIoHV9D9W9jIhyO!T5^R*V#<~KEZd7*ZTL=fbaM9dYI!>XEw ztCMvHMkKG;PZ*znC}1cLB4Eo>@xVRciLTcv(<;n!RWltG$_bA<0x~RF7ieNZ=Kfpl zq|4kD1F3~VR=RTa^e%qj>yN6IZKsDdE!$KD!&Arqx8iGr1wte%E*7fC>v5hgyDdF& zIMepR$}?Cp8||xR91h9NIHJdi5BOof!n9 zNr{YjQ913cMtkkT;kcjka&pVNMlwaxhP)1E6x#)-Hcl%hL1@Ax!7+Bf#E6VB-LY43 zLK#YukOBwmpojFXGFk*h#On0|d07SVJWvzTGi5)MZO!X^IOlBBZ&tLQsW{HsD=m;H z3nu9*t_mKe60XZfBo%69txNRJ2}fy@eGx(ICYAj&0|5pes~~JJZ`NWs zXfGc@WgS{3{qo)L@4;|pkr*B+; zpl__~81Q_Y6M6lKltEtB=6&Dgvlh`JML)7q{0om}8-1=LZw+^>wHM`Yn1hmhi{mqI zkUlEWXx5Q@E#*^fAp8FLsDw;n$^-^Mpk4?7VCCLBS0ioxefJQph}Y8WDxHYKC%DaQ z;S}S{SxnxrX!9e)2O$3D(a}s)^K?Fsnr)dgYAEgs*N+MRAcFhsAtt+nKqn3tX!>A| z1ov$oM*^>J27j`N+!YN9YUgUVDi7_^D2K1$;313Dr4NYEy>ZC!n*?sr4bU`n7X_G# zK{&~O*Kj((kKI=w2WB+EPWcc2#H<)eJ^{NJXi}UR;}%KD1hd!U zrzlkqN2*Y`%i5Uh*xC->5p`nn-txzl!Q3n>dHca*Bh5TYHps&g{ozy;zTt|o>Edl1 zGZb36Bo{vk=IC2nMpmFtP|UePYO|={)YE6oFFjRlt+Ky3`lS|;{=(+14mjMnLPXRb z=%$uxJ8-$2t1#y^7}V6~%B{VevlrJm-VD{LLA%dpIAwU1e_iR|;d?CfdWxB= zbsW0u$iNG4;z#+L&BAYpyDkSmLkQhz!>PXr4Wh^EF6jZqi?k>6M9#OAM$mg?TH!|z zmtluqC?B?WV@!9!nCU3Log)4<+f4e6Xv<*!cX^+(t@wu;i^$T0m~&{ch3VWE>q%i@ z1|2ucYMEm`;RBBJz*}ENv~w%L)W*&Tt-A_Vmb=pl`O3pB)+I4u19?_`g6$m=UUoOV zJ4iCLa6=0jw*LJ2E|pO;mt)v>qz=b(0&q-;>~<%wlal}}*J=NwXP!y~Ka7dufwZCc zol_l@ld4hwn4up9~Ohll2w^?KZn@|4IqM>?o2sYWdzV=I#HaV4u@Z%+cb-$ls zJ)&m>qI_b9TkysleiNE|}Mrvu3O^xpPCH&hbs5@O@OD1J2IZc;z z;MeFgh5WE#L^LQRpJxS@BKg;*Nw~$Ij%|EYr!}tbnB~J73wyNN;N&?QgghL{OL2?S zhrvSmF>G}ayjIFgH+X8geB)a`}fF^>uc>{K*ChO1tmvbO|6}R z=ezexO#6VrJKM+E49hPQJ7>FqzH(^hYZ`_~!CVW9*%J`$*eCXwJFz5zxb3$#)ykbT z8x$eyO*@5UW=Xu=kbUHN!4sfUzG_eqvaXeQ%fZknc{kp6`(02^9}=Vt8$F-7VM|5< z7(1@))*4XvhUK9jV?b^@>u>ToJDB%?ucy?n2yfYnknr z@#~Cu(b|LlVuc*tWFK}5W