mirror of
https://github.com/minetest-mods/i3.git
synced 2025-07-03 00:50:22 +02:00
Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
e1c0f106cc | |||
46f1136bb7 | |||
e88921fe72 | |||
7e0feefc89 | |||
44a6256589 | |||
1dd742e887 | |||
518ed971ca | |||
e9b8085fde | |||
6dc12390db | |||
44610b879e | |||
b0c9bcf3b9 | |||
de70846d6c | |||
8b6f50b387 |
4
API.md
4
API.md
@ -17,9 +17,7 @@ i3.new_tab("stuff", {
|
||||
-- Determine if the tab is visible by a player, `false` or `nil` hide the tab
|
||||
access = function(player, data)
|
||||
local name = player:get_player_name()
|
||||
if name == "singleplayer" then
|
||||
return false
|
||||
end
|
||||
return name == "singleplayer"
|
||||
end,
|
||||
|
||||
formspec = function(player, data, fs)
|
||||
|
@ -53,4 +53,4 @@ Report bugs on the [**Bug Tracker**](https://github.com/minetest-mods/i3/issues)
|
||||
|
||||
**Video review on YouTube:** https://www.youtube.com/watch?v=Xd14BCdEZ3o
|
||||
|
||||

|
||||

|
||||
|
11
src/api.lua
11
src/api.lua
@ -167,6 +167,13 @@ function i3.set_fs(player)
|
||||
sort_inventory(player, data)
|
||||
end
|
||||
|
||||
for i, tab in ipairs(i3.tabs) do
|
||||
if data.tab == i and tab.access and not tab.access(player, data) then
|
||||
data.tab = 1
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
local fs = make_fs(player, data)
|
||||
player:set_inventory_formspec(fs)
|
||||
end
|
||||
@ -221,8 +228,8 @@ function i3.set_tab(player, tabname)
|
||||
return
|
||||
end
|
||||
|
||||
for i, def in ipairs(i3.tabs) do
|
||||
if def.name == tabname then
|
||||
for i, tab in ipairs(i3.tabs) do
|
||||
if tab.name == tabname then
|
||||
data.tab = i
|
||||
return
|
||||
end
|
||||
|
@ -242,7 +242,7 @@ local function resolve_aliases(hash)
|
||||
end
|
||||
end
|
||||
|
||||
if newname ~= "" and i3.recipes_cache[oldname] and not hash[newname] then
|
||||
if newname ~= "" and i3.recipes_cache[oldname] and reg_items[newname] and not hash[newname] then
|
||||
insert(i3.init_items, newname)
|
||||
end
|
||||
end
|
||||
|
@ -5,7 +5,7 @@ local init_detached = i3.files.detached()
|
||||
local init_hud = i3.files.hud()
|
||||
local set_fs = i3.set_fs
|
||||
|
||||
IMPORT("slz", "min", "copy", "ItemStack")
|
||||
IMPORT("slz", "min", "insert", "copy", "ItemStack")
|
||||
IMPORT("spawn_item", "reset_data", "get_detached_inv")
|
||||
|
||||
core.register_on_player_hpchange(function(player, hpchange)
|
||||
@ -134,6 +134,7 @@ local function init_data(player, info)
|
||||
data.player_name = name
|
||||
data.filter = ""
|
||||
data.pagenum = 1
|
||||
data.skin_pagenum = 1
|
||||
data.items = i3.init_items
|
||||
data.items_raw = i3.init_items
|
||||
data.favs = {}
|
||||
@ -175,7 +176,7 @@ local function save_data(player_name)
|
||||
storage:set_string("data", slz(_data))
|
||||
end
|
||||
|
||||
core.register_on_joinplayer(function(player)
|
||||
insert(core.registered_on_joinplayers, 1, function(player)
|
||||
local name = player:get_player_name()
|
||||
local info = core.get_player_information and core.get_player_information(name)
|
||||
|
||||
|
@ -101,7 +101,7 @@ local function search(data)
|
||||
for i = 1, #data.items_raw do
|
||||
local item = data.items_raw[i]
|
||||
local def = reg_items[item]
|
||||
local desc = lower(translate(data.lang_code, def and def.description)) or ""
|
||||
local desc = lower(translate(data.lang_code, def.description)) or ""
|
||||
local search_in = fmt("%s %s", item, desc)
|
||||
local temp, j, to_add = {}, 1
|
||||
|
||||
@ -514,14 +514,17 @@ local function compress_items(list, start_i)
|
||||
return new_inv
|
||||
end
|
||||
|
||||
local function drop_items(player, inv, list, start_i, rej)
|
||||
local function drop_items(player, inv, list, start_i, rej, remove)
|
||||
for i = start_i, #list do
|
||||
local stack = list[i]
|
||||
local name = stack:get_name()
|
||||
|
||||
for _, it in ipairs(rej) do
|
||||
if name == it then
|
||||
spawn_item(player, stack)
|
||||
if not remove then
|
||||
spawn_item(player, stack)
|
||||
end
|
||||
|
||||
inv:set_stack("main", i, ItemStack(""))
|
||||
end
|
||||
end
|
||||
@ -537,7 +540,7 @@ local function sort_inventory(player, data)
|
||||
local start_i = data.ignore_hotbar and (i3.settings.hotbar_len + 1) or 1
|
||||
|
||||
if true_table(data.drop_items) then
|
||||
list = drop_items(player, inv, list, start_i, data.drop_items)
|
||||
list = drop_items(player, inv, list, start_i, data.drop_items, true)
|
||||
end
|
||||
|
||||
if data.inv_compress then
|
||||
@ -589,7 +592,7 @@ local function add_hud_waypoint(player, name, pos, color)
|
||||
return player:hud_add {
|
||||
hud_elem_type = "waypoint",
|
||||
name = name,
|
||||
text = " m",
|
||||
text = "m",
|
||||
world_pos = pos,
|
||||
number = color,
|
||||
z_index = -300,
|
||||
|
@ -14,10 +14,9 @@ local function inv_fields(player, data, fields)
|
||||
local inv = player:get_inventory()
|
||||
local sb_inv = fields.scrbar_inv
|
||||
|
||||
if fields.skins then
|
||||
local id = tonumber(fields.skins)
|
||||
local _skins = skins.get_skinlist_for_player(name)
|
||||
skins.set_player_skin(player, _skins[id])
|
||||
if sb_inv and sub(sb_inv, 1, 3) == "CHG" then
|
||||
data.scrbar_inv = tonumber(match(sb_inv, "%d+"))
|
||||
return
|
||||
end
|
||||
|
||||
if fields.drop_items then
|
||||
@ -41,6 +40,11 @@ local function inv_fields(player, data, fields)
|
||||
elseif sub(field, 1, 8) == "setting_" then
|
||||
data.show_setting = match(field, "_(%w+)$")
|
||||
|
||||
elseif sub(field, 1, 9) == "skin_btn_" then
|
||||
local id = tonumber(field:match("%d+"))
|
||||
local _skins = skins.get_skinlist_for_player(name)
|
||||
skins.set_player_skin(player, _skins[id])
|
||||
|
||||
elseif find(field, "waypoint_%d+") then
|
||||
local id, action = match(field, "_(%d+)_(%w+)$")
|
||||
id = tonumber(id)
|
||||
@ -169,10 +173,6 @@ local function inv_fields(player, data, fields)
|
||||
data.bag = bagstack:to_string()
|
||||
data.bag_rename = nil
|
||||
|
||||
elseif sb_inv and sub(sb_inv, 1, 3) == "CHG" then
|
||||
data.scrbar_inv = tonumber(match(sb_inv, "%d+"))
|
||||
return
|
||||
|
||||
elseif fields.waypoint_add then
|
||||
local max_waypoints = i3.settings.max_waypoints
|
||||
|
||||
@ -215,10 +215,10 @@ local function inv_fields(player, data, fields)
|
||||
return set_fs(player)
|
||||
end
|
||||
|
||||
local function select_item(player, data, _f)
|
||||
local function select_item(player, data, fields)
|
||||
local item
|
||||
|
||||
for field in pairs(_f) do
|
||||
for field in pairs(fields) do
|
||||
if find(field, ":") then
|
||||
item = field
|
||||
break
|
||||
@ -343,6 +343,16 @@ local function rcp_fields(player, data, fields)
|
||||
data.pagenum = data.pagemax
|
||||
end
|
||||
|
||||
elseif fields.prev_skin or fields.next_skin then
|
||||
if data.skin_pagemax == 1 then return end
|
||||
data.skin_pagenum -= (fields.prev_skin and 1 or -1)
|
||||
|
||||
if data.skin_pagenum > data.skin_pagemax then
|
||||
data.skin_pagenum = 1
|
||||
elseif data.skin_pagenum == 0 then
|
||||
data.skin_pagenum = data.skin_pagemax
|
||||
end
|
||||
|
||||
elseif fields.prev_recipe or fields.next_recipe then
|
||||
local num = data.rnum + (fields.prev_recipe and -1 or 1)
|
||||
data.rnum = data.recipes[num] and num or (fields.prev_recipe and #data.recipes or 1)
|
||||
|
80
src/gui.lua
80
src/gui.lua
@ -494,19 +494,44 @@ local function get_container(fs, data, player, yoffset, ctn_len, award_list, awa
|
||||
|
||||
local _skins = skins.get_skinlist_for_player(name)
|
||||
local skin_name = skins.get_player_skin(player).name
|
||||
local sks, id = {}, 1
|
||||
local spp, add_y = 24, 0
|
||||
|
||||
for i, skin in ipairs(_skins) do
|
||||
if skin.name == skin_name then
|
||||
id = i
|
||||
end
|
||||
if #_skins > spp then
|
||||
local btn_y = yextra + 0.75
|
||||
add_y += 0.6
|
||||
|
||||
insert(sks, skin.name)
|
||||
data.skin_pagemax = max(1, ceil(#_skins / spp))
|
||||
|
||||
fs("image_button", 1.5, btn_y, 0.35, 0.35, "", "prev_skin", "")
|
||||
fs("image_button", 3.85, btn_y, 0.35, 0.35, "", "next_skin", "")
|
||||
|
||||
fs"style[skin_page;font=bold;font_size=18]"
|
||||
fs("button", 1.85, btn_y - 0.23, 2, 0.8, "skin_page",
|
||||
fmt("%s / %u", clr(colors.yellow, data.skin_pagenum), data.skin_pagemax))
|
||||
end
|
||||
|
||||
sks = concat(sks, ","):gsub(";", "")
|
||||
fs("label", 0, yextra + 0.85, fmt("%s:", ES"Select a skin"))
|
||||
fs(fmt("dropdown[0,%f;4,0.6;skins;%s;%u;true]", yextra + 1.1, sks, id))
|
||||
local first = (data.skin_pagenum - 1) * spp
|
||||
local last = first + spp - 1
|
||||
|
||||
for i = first, last do
|
||||
local skin = _skins[i + 1]
|
||||
if not skin then break end
|
||||
local btn_name = fmt("skin_btn_%u", i + 1)
|
||||
|
||||
fs(fmt([[ style[%s;padding=10;
|
||||
fgimg=%s;bgimg=%s;bgimg_hovered=i3_btn9_hovered.png;
|
||||
bgimg_pressed=i3_btn9_pressed.png;bgimg_middle=4,6] ]],
|
||||
btn_name, skin:get_preview(),
|
||||
skin.name == skin_name and "i3_btn9_hovered.png" or "i3_btn9.png"))
|
||||
|
||||
local X = (i % 3) * 1.93
|
||||
|
||||
local Y = ceil((i % spp - X) / 3 + 1)
|
||||
Y += (Y * 2.45) + yextra - 2.75 + add_y
|
||||
|
||||
fs("image_button", X, Y, 1.86, 3.4, "", btn_name, "")
|
||||
fs(fmt("tooltip[%s;%s]", btn_name, ESC(skin.name)))
|
||||
end
|
||||
|
||||
elseif data.subcat == 4 then
|
||||
if not i3.modules.awards then
|
||||
@ -579,9 +604,6 @@ local function show_popup(fs, data)
|
||||
elseif show_sorting then
|
||||
fs("button", 2.1, 9.7, 6, 0.8, "select_sorting", ES"Select the inventory sorting method:")
|
||||
|
||||
fs(fmt("style[prev_sort;fgimg=%s;fgimg_hovered=%s]", PNG.prev, PNG.prev_hover),
|
||||
fmt("style[next_sort;fgimg=%s;fgimg_hovered=%s]", PNG.next, PNG.next_hover))
|
||||
|
||||
fs("image_button", 2.2, 10.6, 0.35, 0.35, "", "prev_sort", "")
|
||||
fs("image_button", 7.65, 10.6, 0.35, 0.35, "", "next_sort", "")
|
||||
|
||||
@ -606,7 +628,7 @@ local function show_popup(fs, data)
|
||||
end
|
||||
|
||||
fs("style[drop_items;font_size=15;font=mono;textcolor=#dbeeff]",
|
||||
fmt("field[5.4,10.68;2.4,0.45;drop_items;Drop items:;%s]",
|
||||
fmt("field[5.4,10.68;2.4,0.45;drop_items;Remove items:;%s]",
|
||||
ESC(concat(data.drop_items or {}, ","))),
|
||||
"field_close_on_enter[drop_items;false]")
|
||||
|
||||
@ -619,7 +641,7 @@ local function show_popup(fs, data)
|
||||
fmt("tooltip[cb_auto_sorting;%s;#707070;#fff]",
|
||||
ES"Enable this option to sort your inventory automatically"),
|
||||
fmt("tooltip[drop_items;%s;#707070;#fff]",
|
||||
"Add a comma-separated list of items to drop on inventory sorting.\n" ..
|
||||
"Add a comma-separated list of items to remove on inventory sorting.\n" ..
|
||||
"Format: " .. ("mod:item,mod:item, ..."):gsub("(%a+:%a+)", clr("#bddeff", "%1"))))
|
||||
end
|
||||
end
|
||||
@ -667,6 +689,14 @@ local function get_inventory_fs(player, data, fs)
|
||||
|
||||
max_val += 10
|
||||
|
||||
elseif i3.modules.skins and data.subcat == 3 then
|
||||
local spp = 24
|
||||
local _skins = skins.get_skinlist_for_player(data.player_name)
|
||||
local nb = #_skins
|
||||
local num = max(1, min(spp, nb - ((data.skin_pagenum - 1) * spp)))
|
||||
|
||||
max_val += ceil(num / 3) * (nb > spp and 34 or 31)
|
||||
|
||||
elseif i3.modules.awards and data.subcat == 4 then
|
||||
award_list = awards.get_award_states(data.player_name)
|
||||
award_list_nb = #award_list
|
||||
@ -799,7 +829,7 @@ local function get_tooltip(item, info, pos)
|
||||
return fmt("tooltip[%s;%s]", item, ESC(tooltip))
|
||||
end
|
||||
|
||||
local function get_output_fs(fs, data, rcp, is_recipe, shapeless, right, btn_size, _btn_size)
|
||||
local function get_output_fs(fs, data, rcp, is_recipe, shapeless, right, btn_size, btn_size2)
|
||||
local custom_recipe = i3.craft_types[rcp.type]
|
||||
local cooking = rcp.type == "cooking"
|
||||
local fuel = rcp.type == "fuel"
|
||||
@ -836,7 +866,7 @@ local function get_output_fs(fs, data, rcp, is_recipe, shapeless, right, btn_siz
|
||||
end
|
||||
|
||||
local BTN_SIZE = i3.settings.item_btn_size
|
||||
local arrow_X = right + 0.2 + (_btn_size or BTN_SIZE)
|
||||
local arrow_X = right + 0.2 + (btn_size2 or BTN_SIZE)
|
||||
local X = arrow_X + 1.2
|
||||
local Y = data.yoffset + 1.4
|
||||
|
||||
@ -1196,9 +1226,10 @@ local function get_export_fs(fs, data, is_recipe, is_usage, max_stacks_rcp, max_
|
||||
|
||||
fs(fmt("style[scrbar_%s;noclip=true]", name),
|
||||
fmt("scrollbaroptions[min=1;max=%u;smallstep=1]", craft_max))
|
||||
fs("scrollbar", data.inv_width + 8.1, data.yoffset, 3, 0.35, "horizontal", fmt("scrbar_%s", name), stack_fs)
|
||||
fs("button", data.inv_width + 8.1, data.yoffset + 0.4, 3, 0.7,
|
||||
fmt("craft_%s", name), ES("Craft (×@1)", stack_fs))
|
||||
|
||||
local x = data.inv_width + 8.1
|
||||
fs("scrollbar", x, data.yoffset, 2.5, 0.35, "horizontal", fmt("scrbar_%s", name), stack_fs)
|
||||
fs("button", x, data.yoffset + 0.4, 2.5, 0.7, fmt("craft_%s", name), ES("Craft (×@1)", stack_fs))
|
||||
end
|
||||
|
||||
local function get_rcp_extra(fs, data, player, panel, is_recipe, is_usage)
|
||||
@ -1485,6 +1516,7 @@ local function make_fs(player, data)
|
||||
fs("bg9", 0, 0, data.inv_width, full_height, PNG.bg_full, 10)
|
||||
|
||||
local tab = i3.tabs[data.tab]
|
||||
|
||||
if tab then
|
||||
tab.formspec(player, data, fs)
|
||||
end
|
||||
@ -1495,7 +1527,15 @@ local function make_fs(player, data)
|
||||
get_items_fs(fs, data, player, full_height)
|
||||
end
|
||||
|
||||
if #i3.tabs > 1 then
|
||||
local visible_tabs = 1
|
||||
|
||||
for _, def in ipairs(i3.tabs) do
|
||||
if visible_tabs < 2 and def.access and def.access(player, data) then
|
||||
visible_tabs++
|
||||
end
|
||||
end
|
||||
|
||||
if visible_tabs > 1 then
|
||||
get_tabs_fs(fs, player, data, full_height)
|
||||
end
|
||||
|
||||
|
@ -74,17 +74,14 @@ local styles = string.format([[
|
||||
style_type[image_button,item_image_button,checkbox,dropdown;border=false;sound=i3_click]
|
||||
style_type[item_image_button;bgimg_hovered=%s]
|
||||
|
||||
style[;sound=]
|
||||
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]
|
||||
style[search;fgimg=%s;fgimg_hovered=%s;content_offset=0]
|
||||
style[prev_page;fgimg=%s;fgimg_hovered=%s]
|
||||
style[next_page;fgimg=%s;fgimg_hovered=%s]
|
||||
style[prev_recipe;fgimg=%s;fgimg_hovered=%s]
|
||||
style[next_recipe;fgimg=%s;fgimg_hovered=%s]
|
||||
style[prev_usage;fgimg=%s;fgimg_hovered=%s]
|
||||
style[next_usage;fgimg=%s;fgimg_hovered=%s]
|
||||
style[prev_page,prev_recipe,prev_usage,prev_sort,prev_skin;fgimg=%s;fgimg_hovered=%s]
|
||||
style[next_page,next_recipe,next_usage,next_sort,next_skin;fgimg=%s;fgimg_hovered=%s]
|
||||
style[waypoint_add;fgimg=%s;fgimg_hovered=%s;content_offset=0]
|
||||
style[bag_rename;fgimg=%s;fgimg_hovered=%s;content_offset=0]
|
||||
style[btn_bag,btn_armor,btn_skins;font=bold;font_size=18;content_offset=0;sound=i3_click]
|
||||
@ -102,10 +99,6 @@ PNG.cancel, PNG.cancel_hover,
|
||||
PNG.search, PNG.search_hover,
|
||||
PNG.prev, PNG.prev_hover,
|
||||
PNG.next, PNG.next_hover,
|
||||
PNG.prev, PNG.prev_hover,
|
||||
PNG.next, PNG.next_hover,
|
||||
PNG.prev, PNG.prev_hover,
|
||||
PNG.next, PNG.next_hover,
|
||||
PNG.add, PNG.add_hover,
|
||||
PNG.edit, PNG.edit_hover)
|
||||
|
||||
|
@ -16,30 +16,18 @@ i3.new_tab("test2", {
|
||||
end,
|
||||
})
|
||||
|
||||
i3.new_tab("test3", {
|
||||
description = "Test 3",
|
||||
i3.new_tab("test_creative", {
|
||||
description = "Test creative",
|
||||
|
||||
access = function(player, data)
|
||||
local name = player:get_player_name()
|
||||
if name == "singleplayer" then
|
||||
return true
|
||||
end
|
||||
return core.is_creative_enabled(name)
|
||||
end,
|
||||
|
||||
formspec = function(player, data, fs)
|
||||
fs("label[3,1;Test 3]")
|
||||
fs("label[3,1;Creative enabled]")
|
||||
end,
|
||||
|
||||
fields = function(player, data, fields)
|
||||
i3.set_fs(player, "label[3,2;Test extra_fs]")
|
||||
end,
|
||||
fields = i3.set_fs,
|
||||
})
|
||||
|
||||
i3.override_tab("test2", {
|
||||
description = "Test override",
|
||||
image = "i3_mesepick.png",
|
||||
|
||||
formspec = function(player, data, fs)
|
||||
fs("label[3,1;Override!]")
|
||||
end,
|
||||
})
|
||||
|
Reference in New Issue
Block a user