mirror of
https://github.com/minetest-mods/i3.git
synced 2025-07-03 09:00:23 +02:00
Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
d9a16bf39d | |||
2a2837dd0c | |||
080579b2a4 | |||
b711f8f195 | |||
00a258afea | |||
dd8657ab56 | |||
34fa63519e | |||
066e0a5d9d | |||
8fc01b7ece | |||
a1af79a870 |
16
API.md
16
API.md
@ -12,23 +12,31 @@ Custom tabs can be added to the `i3` inventory as follow (example):
|
||||
```Lua
|
||||
i3.new_tab("stuff", {
|
||||
description = "Stuff",
|
||||
image = "image.png", -- Optional, adds an image next to the tab description
|
||||
image = "image.png", -- Optional, add an image next to the tab description
|
||||
|
||||
-- Determine if the tab is visible by a player, `false` or `nil` hide the tab
|
||||
--
|
||||
-- The functions below are all optional
|
||||
--
|
||||
|
||||
-- Determine if the tab is visible by a player, return false to hide the tab
|
||||
access = function(player, data)
|
||||
local name = player:get_player_name()
|
||||
return name == "singleplayer"
|
||||
end,
|
||||
|
||||
formspec = function(player, data, fs)
|
||||
fs"label[3,1;This is just a test]"
|
||||
fs("label", 3, 1, "Just a test")
|
||||
fs"label[3,2;Lorem Ipsum]"
|
||||
-- No need to return anything
|
||||
end,
|
||||
|
||||
-- Events handling happens here
|
||||
fields = function(player, data, fields)
|
||||
if fields.mybutton then
|
||||
do_things()
|
||||
-- Do things
|
||||
end
|
||||
|
||||
i3.set_fs(player) -- Update the formspec, mandatory
|
||||
end,
|
||||
})
|
||||
```
|
||||
|
5
init.lua
5
init.lua
@ -20,7 +20,7 @@ local function lf(path)
|
||||
end
|
||||
|
||||
i3 = {
|
||||
version = 1121,
|
||||
version = 1123,
|
||||
data = core.deserialize(storage:get_string"data") or {},
|
||||
|
||||
settings = {
|
||||
@ -111,6 +111,7 @@ i3 = {
|
||||
i3.files.common()
|
||||
i3.files.api(http)
|
||||
i3.files.compress()
|
||||
i3.files.detached()
|
||||
i3.files.groups()
|
||||
i3.files.callbacks(http, storage)
|
||||
|
||||
@ -120,7 +121,7 @@ end
|
||||
|
||||
if i3.settings.debug_mode then
|
||||
lf("/tests/test_tabs.lua")()
|
||||
lf("/tests/test_operators.lua")()
|
||||
-- lf("/tests/test_operators.lua")()
|
||||
lf("/tests/test_compression.lua")()
|
||||
lf("/tests/test_custom_recipes.lua")()
|
||||
end
|
||||
|
@ -1,7 +1,6 @@
|
||||
local http, storage = ...
|
||||
local init_bags = i3.files.bags()
|
||||
local fill_caches = i3.files.caches(http)
|
||||
local init_detached = i3.files.detached()
|
||||
local init_hud = i3.files.hud()
|
||||
local set_fs = i3.set_fs
|
||||
|
||||
@ -203,16 +202,14 @@ local function init_data(player, info)
|
||||
local name = player:get_player_name()
|
||||
i3.data[name] = i3.data[name] or {}
|
||||
local data = i3.data[name]
|
||||
local default = {}
|
||||
|
||||
for k, v in pairs(i3.default_data) do
|
||||
default[k] = data[k]
|
||||
|
||||
if data[k] == nil then
|
||||
default[k] = v
|
||||
local val = data[k]
|
||||
if val == nil then
|
||||
val = v
|
||||
end
|
||||
|
||||
data[k] = default[k]
|
||||
data[k] = val
|
||||
end
|
||||
|
||||
data.player_name = name
|
||||
@ -264,7 +261,6 @@ insert(core.registered_on_joinplayers, 1, function(player)
|
||||
|
||||
init_data(player, info)
|
||||
init_bags(player)
|
||||
init_detached(player)
|
||||
init_hud(player)
|
||||
end)
|
||||
|
||||
|
@ -327,8 +327,12 @@ local function apply_recipe_filters(recipes, player)
|
||||
return recipes
|
||||
end
|
||||
|
||||
local function recipe_filter_set()
|
||||
return next(i3.recipe_filters)
|
||||
end
|
||||
|
||||
local function compression_active(data)
|
||||
return data.collapse and not next(i3.recipe_filters) and data.filter == ""
|
||||
return data.collapse and not recipe_filter_set() and data.filter == ""
|
||||
end
|
||||
|
||||
local function compressible(item, data)
|
||||
@ -684,6 +688,7 @@ local _ = {
|
||||
get_recipes = get_recipes,
|
||||
sort_inventory = sort_inventory,
|
||||
sort_by_category = sort_by_category,
|
||||
recipe_filter_set = recipe_filter_set,
|
||||
apply_recipe_filters = apply_recipe_filters,
|
||||
|
||||
-- Type checks
|
||||
|
@ -1,5 +1,5 @@
|
||||
local set_fs = i3.set_fs
|
||||
IMPORT("fmt", "play_sound", "create_inventory")
|
||||
IMPORT("play_sound", "create_inventory")
|
||||
|
||||
local trash = create_inventory("i3_trash", {
|
||||
allow_put = function(_, _, _, stack)
|
||||
@ -22,15 +22,3 @@ local trash = create_inventory("i3_trash", {
|
||||
})
|
||||
|
||||
trash:set_size("main", 1)
|
||||
|
||||
local function init_detached(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_detached
|
||||
|
89
src/gui.lua
89
src/gui.lua
@ -10,11 +10,11 @@ local VoxelArea, VoxelManip = VoxelArea, VoxelManip
|
||||
IMPORT("vec", "vec_round")
|
||||
IMPORT("find", "match", "sub", "upper")
|
||||
IMPORT("clr", "ESC", "msg", "check_privs")
|
||||
IMPORT("compression_active", "compressible")
|
||||
IMPORT("min", "max", "floor", "ceil", "round")
|
||||
IMPORT("true_str", "is_fav", "is_num", "str_to_pos")
|
||||
IMPORT("reg_items", "reg_nodes", "reg_tools", "reg_entities")
|
||||
IMPORT("get_bag_description", "get_detached_inv", "get_recipes")
|
||||
IMPORT("compression_active", "compressible", "recipe_filter_set")
|
||||
IMPORT("S", "ES", "translate", "ItemStack", "toupper", "utf8_len")
|
||||
IMPORT("maxn", "sort", "concat", "copy", "insert", "remove", "unpack")
|
||||
IMPORT("extract_groups", "groups_to_items", "is_group", "item_has_groups", "get_group")
|
||||
@ -297,7 +297,7 @@ local function get_isometric_view(fs, pos, X, Y, t, cubes, depth, high)
|
||||
end
|
||||
|
||||
shift += (base_depth and 0.45 or 0.95)
|
||||
image(2.7, Y + shift, 0.3, 0.3, PNG.flag)
|
||||
animated_image(2.75, Y + shift, 3/14, 0.3, "i3_flag_anim.png", 4, 150)
|
||||
end
|
||||
|
||||
local function get_waypoint_fs(fs, data, player, yextra, ctn_len)
|
||||
@ -380,9 +380,9 @@ local function get_waypoint_fs(fs, data, player, yextra, ctn_len)
|
||||
fs"style_type[label;font=normal;font_size=16;textcolor=#fff]"
|
||||
end
|
||||
|
||||
local function get_bag_fs(fs, data, name, esc_name, bag_size, yextra)
|
||||
fs("list[detached:i3_bag_%s;main;0,%f;1,1;]", esc_name, yextra + 0.7)
|
||||
local bag = get_detached_inv("bag", name)
|
||||
local function get_bag_fs(fs, data, bag_size, yextra)
|
||||
fs("list[detached:i3_bag_%s;main;0,%f;1,1;]", data.player_name, yextra + 0.7)
|
||||
local bag = get_detached_inv("bag", data.player_name)
|
||||
if bag:is_empty"main" then return end
|
||||
|
||||
local v = {{1.9, 2, 0.12}, {3.05, 5, 0.06}, {4.2, 10}, {4.75, 10}}
|
||||
@ -416,12 +416,13 @@ local function get_bag_fs(fs, data, name, esc_name, bag_size, yextra)
|
||||
end
|
||||
|
||||
fs("style_type[list;size=%f;spacing=%f]", size, spacing)
|
||||
fs("list[detached:i3_bag_content_%s;main;%f,%f;4,%u;]", esc_name, x, yextra + 1.3, bag_size)
|
||||
fs("list[detached:i3_bag_content_%s;main;%f,%f;4,%u;]", data.player_name, x, yextra + 1.3, bag_size)
|
||||
fs"style_type[list;size=1;spacing=0.15]"
|
||||
end
|
||||
|
||||
local function get_container(fs, data, player, yoffset, ctn_len, award_list, awards_unlocked, award_list_nb, bag_size)
|
||||
local name = data.player_name
|
||||
local nametag = player:get_nametag_attributes()
|
||||
local name = true_str(nametag.text) and nametag.text or data.player_name
|
||||
local esc_name = ESC(name)
|
||||
|
||||
add_subtitle(fs, "player_name", 0, ctn_len, 22, true, esc_name)
|
||||
@ -474,14 +475,14 @@ local function get_container(fs, data, player, yoffset, ctn_len, award_list, awa
|
||||
end
|
||||
|
||||
if data.subcat == 1 then
|
||||
get_bag_fs(fs, data, name, esc_name, bag_size, yextra)
|
||||
get_bag_fs(fs, data, bag_size, yextra)
|
||||
|
||||
elseif data.subcat == 2 then
|
||||
if not i3.modules.armor then
|
||||
return not_installed "3d_armor"
|
||||
end
|
||||
|
||||
local armor_def = armor.def[name]
|
||||
local armor_def = armor.def[data.player_name]
|
||||
local _, armor_inv = armor:get_valid_player(player, "3d_armor")
|
||||
|
||||
fs("list[detached:%s_armor;armor;0,%f;5,1;]", esc_name, yextra + 0.7)
|
||||
@ -522,7 +523,7 @@ local function get_container(fs, data, player, yoffset, ctn_len, award_list, awa
|
||||
return not_installed "skinsdb"
|
||||
end
|
||||
|
||||
local _skins = skins.get_skinlist_for_player(name)
|
||||
local _skins = skins.get_skinlist_for_player(data.player_name)
|
||||
local skin_name = skins.get_player_skin(player).name
|
||||
local spp, add_y = 24, 0
|
||||
|
||||
@ -608,7 +609,7 @@ local function show_settings(fs, data)
|
||||
local X = 2.5
|
||||
button(X, 9.1, 1.6, 0.55, "setting_home", "Home")
|
||||
button(X + 1.7, 9.1, 1.6, 0.55, "setting_style", "Style")
|
||||
button(X + 3.38, 9.1, 1.6, 0.55, "setting_sorting", "Sorting")
|
||||
button(X + 3.4, 9.1, 1.6, 0.55, "setting_sorting", "Sorting")
|
||||
image_button(X + 5.12, 9.2, 0.25, 0.25, PNG.cancel_hover .. "^\\[brighten", "close_settings", "")
|
||||
|
||||
if show_home then
|
||||
@ -631,8 +632,8 @@ local function show_settings(fs, data)
|
||||
checkbox(2.6, 10.4, "cb_legacy_inventory", "Legacy inventory", tostring(data.legacy_inventory))
|
||||
checkbox(2.6, 10.85, "cb_wielditem_hud", "HUD description", tostring(data.wielditem_hud))
|
||||
|
||||
if not next(i3.recipe_filters) then
|
||||
checkbox(5.3, 10.85, "cb_collapse", "Collapse inventory", tostring(data.collapse))
|
||||
if not recipe_filter_set() then
|
||||
checkbox(5.3, 10.85, "cb_collapse", "Collapse list", tostring(data.collapse))
|
||||
end
|
||||
|
||||
local sign = (data.font_size > 0 and "+") or (data.font_size > 0 and "-") or ""
|
||||
@ -640,7 +641,7 @@ local function show_settings(fs, data)
|
||||
|
||||
local range = 5
|
||||
fs("scrollbaroptions[min=-%u;max=%u;smallstep=1;largestep=1;thumbsize=2]", range, range)
|
||||
fs("scrollbar[5.3,10.2;2.45,0.3;horizontal;sb_font_size;%d]", data.font_size)
|
||||
fs("scrollbar[5.3,10.2;2.55,0.3;horizontal;sb_font_size;%d]", data.font_size)
|
||||
|
||||
fs("tooltip[cb_hide_tabs;%s;#707070;#fff]",
|
||||
ES"Enable this option to change the style of the right panel")
|
||||
@ -649,7 +650,7 @@ local function show_settings(fs, data)
|
||||
fs("tooltip[cb_wielditem_hud;%s;#707070;#fff]",
|
||||
ES"Enable this option to show the wielded item description in your HUD")
|
||||
fs("tooltip[cb_collapse;%s;#707070;#fff]",
|
||||
ES"Enable this option to collapse certain items in your inventory")
|
||||
ES"Enable this option to collapse the inventory list by grouping some items")
|
||||
|
||||
elseif show_sorting then
|
||||
checkbox(2.6, 9.95, "cb_inv_compress", "Compression", tostring(data.inv_compress))
|
||||
@ -790,7 +791,7 @@ local function get_inventory_fs(player, data, fs)
|
||||
show_settings(fs, data)
|
||||
end
|
||||
|
||||
local function get_tooltip(item, info, pos, lang_code)
|
||||
local function get_tooltip(item, info, lang_code)
|
||||
local tooltip
|
||||
|
||||
if info.groups then
|
||||
@ -863,11 +864,6 @@ local function get_tooltip(item, info, pos, lang_code)
|
||||
end
|
||||
end
|
||||
|
||||
if pos then
|
||||
local btn_size = i3.settings.item_btn_size
|
||||
return fmt("tooltip", pos.x, pos.y, btn_size, btn_size, ESC(tooltip))
|
||||
end
|
||||
|
||||
return fmt("tooltip[%s;%s]", item, ESC(tooltip))
|
||||
end
|
||||
|
||||
@ -939,28 +935,16 @@ local function get_output_fs(fs, data, rcp, is_recipe, is_usage, shapeless, righ
|
||||
local meta = item:get_meta()
|
||||
local name = item:get_name()
|
||||
local count = item:get_count()
|
||||
local wear = item:get_wear()
|
||||
local _name = fmt("_%s", name)
|
||||
local pos
|
||||
|
||||
if meta:get_string"color" ~= "" or meta:get_string"palette_index" ~= "" then
|
||||
local rcp_usg = is_recipe and "rcp" or "usg"
|
||||
local size = BTN_SIZE * 1.2
|
||||
slot(X, Y - 0.11, size, size)
|
||||
|
||||
fs("style_type[list;size=%f]", BTN_SIZE)
|
||||
fs"listcolors[#bababa50;#bababa99]"
|
||||
fs("list[detached:i3_output_%s_%s;main;%f,%f;1,1;]", rcp_usg, data.player_name, X + 0.11, Y)
|
||||
button(X + 0.11, Y, BTN_SIZE, BTN_SIZE, _name, "")
|
||||
count = get_true_count(data, count, is_recipe, is_usage)
|
||||
item:set_count(count)
|
||||
|
||||
local inv = get_detached_inv(fmt("output_%s", rcp_usg), data.player_name)
|
||||
inv:set_stack("main", 1, item)
|
||||
pos = {x = X + 0.11, y = Y}
|
||||
else
|
||||
local size = BTN_SIZE * 1.2
|
||||
slot(X, Y - 0.11, size, size)
|
||||
|
||||
count = get_true_count(data, count, is_recipe, is_usage)
|
||||
item_image_button(X + 0.11, Y, BTN_SIZE, BTN_SIZE, fmt("%s %u %u", name, count, wear), _name, "")
|
||||
end
|
||||
local itemstr = ESC(item:to_string())
|
||||
item_image_button(X + 0.11, Y, BTN_SIZE, BTN_SIZE, itemstr, _name, "")
|
||||
|
||||
local def = reg_items[name]
|
||||
local unknown = not def or nil
|
||||
@ -983,7 +967,7 @@ local function get_output_fs(fs, data, rcp, is_recipe, is_usage, shapeless, righ
|
||||
}
|
||||
|
||||
if next(infos) then
|
||||
fs(get_tooltip(_name, infos, pos, data.lang_code))
|
||||
fs(get_tooltip(_name, infos, data.lang_code))
|
||||
end
|
||||
end
|
||||
|
||||
@ -1100,7 +1084,10 @@ local function get_grid_fs(fs, data, rcp, is_recipe, is_usage)
|
||||
label(X + 0.8, Y + 0.9, count)
|
||||
end
|
||||
else
|
||||
item_image_button(X, Y, btn_size, btn_size, fmt("%s %u", name, count), btn_name, label)
|
||||
item:set_name(name)
|
||||
item:set_count(count)
|
||||
local itemstr = ESC(item:to_string())
|
||||
item_image_button(X, Y, btn_size, btn_size, itemstr, btn_name, label)
|
||||
end
|
||||
|
||||
local def = reg_items[name]
|
||||
@ -1125,7 +1112,7 @@ local function get_grid_fs(fs, data, rcp, is_recipe, is_usage)
|
||||
}
|
||||
|
||||
if next(infos) then
|
||||
fs(get_tooltip(btn_name, infos, nil, data.lang_code))
|
||||
fs(get_tooltip(btn_name, infos, data.lang_code))
|
||||
end
|
||||
end
|
||||
|
||||
@ -1140,9 +1127,13 @@ local function get_rcp_lbl(fs, data, panel, rn, is_recipe, is_usage)
|
||||
local rcp = is_recipe and panel.rcp[data.rnum] or panel.rcp[data.unum]
|
||||
|
||||
if rcp.custom then
|
||||
local desc = i3.craft_types[rcp.type].description
|
||||
hypertext(data.inv_width + 4.8, data.yoffset + 0.12, 3, 1, "custom_rcp",
|
||||
fmt("<right><i><global size=16>%s\n<global size=15>%s</i></right>", ES"Custom recipe", desc))
|
||||
local craft_type = i3.craft_types[rcp.type]
|
||||
if craft_type then
|
||||
local desc = craft_type.description
|
||||
hypertext(data.inv_width + 4.8, data.yoffset + 0.12, 3, 1, "custom_rcp",
|
||||
fmt("<right><i><global size=16>%s\n<global size=15>%s</i></right>",
|
||||
ES"Custom recipe", ESC(desc)))
|
||||
end
|
||||
end
|
||||
|
||||
local lbl = ES("Usage @1 of @2", data.unum, rn)
|
||||
@ -1365,7 +1356,7 @@ local function hide_items(player, data)
|
||||
data.items = new
|
||||
end
|
||||
|
||||
if not core.is_creative_enabled(data.player_name) and not next(i3.recipe_filters) then
|
||||
if not core.is_creative_enabled(data.player_name) and not recipe_filter_set() then
|
||||
local new = {}
|
||||
|
||||
for i = 1, #data.items do
|
||||
@ -1499,7 +1490,7 @@ local function get_items_fs(fs, data, player, full_height)
|
||||
local lbl = ES"No item to show"
|
||||
local icon, width, offset = PNG.no_result, 4, 2
|
||||
|
||||
if next(i3.recipe_filters) and #i3.init_items > 0 and data.filter == "" then
|
||||
if recipe_filter_set() and #i3.init_items > 0 and data.filter == "" then
|
||||
lbl = ES"Collect items to reveal more recipes" -- Progressive mode, etc.
|
||||
icon, width, offset = PNG.find_more, 2.5, 2.75
|
||||
end
|
||||
@ -1524,7 +1515,7 @@ local function get_items_fs(fs, data, player, full_height)
|
||||
|
||||
local item_btn = fmt("item_image_button", X, Y, size, size, name, item, "")
|
||||
|
||||
if next(i3.recipe_filters) then
|
||||
if recipe_filter_set() then
|
||||
if data.items_progress[item] then
|
||||
insert(fs, item_btn)
|
||||
else
|
||||
@ -1705,7 +1696,7 @@ local function make_fs(player, data)
|
||||
|
||||
local tab = i3.tabs[data.tab]
|
||||
|
||||
if tab then
|
||||
if tab and tab.formspec then
|
||||
tab.formspec(player, data, fs)
|
||||
end
|
||||
|
||||
|
@ -44,7 +44,7 @@ local PNG = {
|
||||
nonvisible = "i3_non_visible.png",
|
||||
exit = "i3_exit.png",
|
||||
home = "i3_home.png",
|
||||
flag = "i3_flag.png",
|
||||
flag = "i3_flag_anim.png",
|
||||
edit = "i3_edit.png",
|
||||
no_result = "i3_no_result.png",
|
||||
find_more = "i3_find_more.png",
|
||||
|
@ -3,7 +3,8 @@ i3.new_tab("test1", {
|
||||
image = "i3_heart.png",
|
||||
|
||||
formspec = function(player, data, fs)
|
||||
fs("label[3,1;Test 1]")
|
||||
fs("label", 3, 1, "Just a test")
|
||||
fs"label[3,2;Lorem Ipsum]"
|
||||
end,
|
||||
})
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 745 B |
BIN
textures/i3_flag_anim.png
Normal file
BIN
textures/i3_flag_anim.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 227 B |
Reference in New Issue
Block a user