Compare commits

..

22 Commits
1.11 ... 1.12

Author SHA1 Message Date
7f437b21f4 Bump version 2022-09-25 17:22:38 +02:00
e8a811f72c Save more settings accross restarts 2022-09-25 17:22:36 +02:00
4c4911eb4f Fix 2022-09-25 16:55:41 +02:00
325d6f30be 🚀 Greatly improve Progressive Mode look 2022-09-25 16:23:11 +02:00
05995a22df Add sound for skins 2022-09-24 16:24:01 +02:00
32594e7552 Small fix 2022-09-24 14:30:45 +02:00
27ed1f02e6 More cleaning 2022-09-24 14:23:47 +02:00
916e80f2c3 Cleanup vectors 2022-09-24 13:46:50 +02:00
c42ea6c005 Minor tweak 2022-09-20 01:12:07 +02:00
da91223c4d Bump version 2022-09-18 14:24:45 +02:00
408267754c API.md: rewrite some parts 2022-09-15 12:28:23 +02:00
b4de48370a HUD: small tweak 2022-09-14 15:37:29 +02:00
477efe56d3 Bump version 2022-09-04 19:17:42 +02:00
8afb51dae8 Some cleaning 2022-09-04 19:12:57 +02:00
734b09b69f Minor cleaning 2022-08-29 11:29:09 +02:00
1560d59d4a Bump version 2022-08-28 16:36:30 +02:00
e4e175a775 Minor tweak 2022-08-28 16:36:08 +02:00
7a40f36611 Bump version 2022-08-28 15:36:44 +02:00
2467e8bb0b Fix sound play 2022-08-28 15:34:37 +02:00
9666834aed Minor tweak 2022-08-28 15:21:20 +02:00
7670356c8c Bump version (again) 2022-08-28 14:46:03 +02:00
646d16afd8 Hotfix HUD 2022-08-28 14:45:37 +02:00
20 changed files with 361 additions and 290 deletions

38
API.md
View File

@ -21,31 +21,33 @@ i3.new_tab("stuff", {
end, end,
formspec = function(player, data, fs) formspec = function(player, data, fs)
fs("label[3,1;This is just a test]") fs"label[3,1;This is just a test]"
end, end,
-- Events handling happens here -- Events handling happens here
fields = function(player, data, fields) fields = function(player, data, fields)
if fields.mybutton then
do_things()
end
end, end,
}) })
``` ```
- `player` is an `ObjectRef` to the user. - `player` is an `ObjectRef` to the user.
- `data` are the user data. - `data` are the user data.
- `fs` is the formspec table which is callable with a metamethod. Each call adds a new entry. - `fs` is the formspec table which is callable with a metamethod. Every call adds a new entry.
#### `i3.set_fs(player)` #### `i3.set_fs(player)`
Updates the current formspec. Update the current formspec.
#### `i3.remove_tab(tabname)` #### `i3.remove_tab(tabname)`
Deletes a tab by name. Delete a tab by name.
#### `i3.get_current_tab(player)` #### `i3.get_current_tab(player)`
Returns the current player tab. `player` is an `ObjectRef` to the user. Return the current player tab. `player` is an `ObjectRef` to the user.
#### `i3.set_tab(player[, tabname])` #### `i3.set_tab(player[, tabname])`
@ -54,7 +56,7 @@ Sets the current tab by name. `player` is an `ObjectRef` to the user.
#### `i3.override_tab(tabname, def)` #### `i3.override_tab(tabname, def)`
Overrides a tab by name. `def` is the tab definition like seen in `i3.set_tab`. Override a tab by name. `def` is the tab definition like seen in `i3.set_tab`
#### `i3.tabs` #### `i3.tabs`
@ -68,9 +70,11 @@ Custom recipes are nonconventional crafts outside the main crafting grid.
They can be registered in-game dynamically and have a size beyond 3x3 items. They can be registered in-game dynamically and have a size beyond 3x3 items.
**Note:** the registration format differs from the default registration format in everything. **Note:** the registration format differs from the default registration format in everything.
The width is automatically calculated depending where you place the commas. Look at the examples attentively. The width is automatically calculated depending where you place the commas.
#### Registering a custom crafting type (example) Examples:
#### Registering a custom crafting type
```Lua ```Lua
i3.register_craft_type("digging", { i3.register_craft_type("digging", {
@ -79,7 +83,7 @@ i3.register_craft_type("digging", {
}) })
``` ```
#### Registering a custom crafting recipe (examples) #### Registering a custom crafting recipe
```Lua ```Lua
i3.register_craft { i3.register_craft {
@ -159,7 +163,7 @@ mode is implemented as a recipe filter.
#### `i3.add_recipe_filter(name, function(recipes, player))` #### `i3.add_recipe_filter(name, function(recipes, player))`
Adds a recipe filter with the given `name`. The filter function returns the Add a recipe filter with the given `name`. The filter function returns the
recipes to be displayed, given the available recipes and an `ObjectRef` to the recipes to be displayed, given the available recipes and an `ObjectRef` to the
user. Each recipe is a table of the form returned by user. Each recipe is a table of the form returned by
`minetest.get_craft_recipe`. `minetest.get_craft_recipe`.
@ -181,7 +185,7 @@ end)
#### `i3.set_recipe_filter(name, function(recipe, player))` #### `i3.set_recipe_filter(name, function(recipe, player))`
Removes all recipe filters and adds a new one. Remove all recipe filters and add a new one.
#### `i3.recipe_filters` #### `i3.recipe_filters`
@ -207,7 +211,7 @@ Notes:
#### `i3.add_search_filter(name, function(item, values))` #### `i3.add_search_filter(name, function(item, values))`
Adds a search filter. Add a search filter.
The search function must return a boolean value (whether the given item should be listed or not). The search function must return a boolean value (whether the given item should be listed or not).
- `name` is the filter name. - `name` is the filter name.
@ -241,7 +245,7 @@ Sorting methods are used to filter the player's main inventory.
#### `i3.add_sorting_method(name, def)` #### `i3.add_sorting_method(name, def)`
Adds a player inventory sorting method. Add a player inventory sorting method.
- `name` is the method name. - `name` is the method name.
- `def` is the method definition. - `def` is the method definition.
@ -276,7 +280,7 @@ A table containing all sorting methods.
#### `i3.compress(item, def)` #### `i3.compress(item, def)`
Adds a new group of items to compress. Add a new group of items to compress.
- `item` is the item which represent the group of compressed items. - `item` is the item which represent the group of compressed items.
- `def` is a table specifying the substring replace patterns to be used. - `def` is a table specifying the substring replace patterns to be used.
@ -301,7 +305,7 @@ A map of all compressed item groups, indexed by stereotypes.
#### `i3.hud_notif(name, msg[, img])` #### `i3.hud_notif(name, msg[, img])`
Shows a Steam-like HUD notification on the bottom-right corner of the screen (experimental). Show a Steam-like HUD notification on the bottom-right corner of the screen (experimental).
- `name` is the player name. - `name` is the player name.
- `msg` is the HUD message to show. - `msg` is the HUD message to show.
@ -309,7 +313,7 @@ Shows a Steam-like HUD notification on the bottom-right corner of the screen (ex
#### `i3.get_recipes(item)` #### `i3.get_recipes(item)`
Returns a table of recipes and usages of `item`. Return a table of recipes and usages of `item`.
#### `i3.export_url` #### `i3.export_url`

View File

@ -20,7 +20,7 @@ local function lf(path)
end end
i3 = { i3 = {
version = 1110, version = 112,
data = core.deserialize(storage:get_string"data") or {}, data = core.deserialize(storage:get_string"data") or {},
settings = { settings = {
@ -36,9 +36,8 @@ i3 = {
hud_speed = 1, hud_speed = 1,
hud_timer_max = 1.5, hud_timer_max = 1.5,
damage_enabled = core.settings:get_bool"enable_damage", damage_enabled = core.settings:get_bool"enable_damage",
progressive_mode = core.settings:get_bool"i3_progressive_mode", progressive_mode = core.settings:get_bool"i3_progressive_mode",
item_compression = core.settings:get_bool("i3_item_compression", true),
}, },
categories = { categories = {
@ -52,15 +51,28 @@ i3 = {
saves = { -- Metadata to save saves = { -- Metadata to save
bag = true, bag = true,
home = true, home = true,
sort = true,
collapse = true,
font_size = true, font_size = true,
hide_tabs = true, hide_tabs = true,
waypoints = true, waypoints = true,
inv_items = true, inv_items = true,
auto_sorting = true,
inv_compress = true,
known_recipes = true, known_recipes = true,
wielditem_hud = true, wielditem_hud = true,
ignore_hotbar = true,
reverse_sorting = true,
legacy_inventory = true, legacy_inventory = true,
}, },
default_data = {
sort = 1,
font_size = 0,
collapse = true,
inv_compress = true,
},
files = { files = {
api = lf"/src/api.lua", api = lf"/src/api.lua",
bags = lf"/src/bags.lua", bags = lf"/src/bags.lua",

View File

@ -1,5 +1,2 @@
# The progressive mode shows recipes you can craft from items you ever had in your inventory. # The progressive mode shows recipes you can craft from items you ever had in your inventory.
i3_progressive_mode (Learn crafting recipes progressively) bool false i3_progressive_mode (Learn crafting recipes progressively) bool false
# Regroup the items of the same type in the item list.
i3_item_compression (Regroup items of the same type) bool true

BIN
sounds/i3_achievement.ogg Normal file

Binary file not shown.

BIN
sounds/i3_skin_change.ogg Normal file

Binary file not shown.

View File

@ -3,7 +3,7 @@ local make_fs, get_inventory_fs = i3.files.gui()
IMPORT("gmatch", "split") IMPORT("gmatch", "split")
IMPORT("S", "err", "fmt", "reg_items") IMPORT("S", "err", "fmt", "reg_items")
IMPORT("sorter", "sort_inventory") IMPORT("sorter", "sort_inventory", "play_sound")
IMPORT("sort", "concat", "copy", "insert", "remove") IMPORT("sort", "concat", "copy", "insert", "remove")
IMPORT("true_str", "true_table", "is_str", "is_func", "is_table", "clean_name") IMPORT("true_str", "true_table", "is_str", "is_func", "is_table", "clean_name")
@ -323,8 +323,10 @@ function i3.hud_notif(name, msg, img)
data.show_hud = true data.show_hud = true
data.hud_msg = msg data.hud_msg = msg
play_sound(name, "i3_achievement", 1.0)
if img then if img then
data.hud_img = fmt("%s^[resize:16x16", img) data.hud_img = fmt("%s^[resize:64x64", img)
end end
end end

View File

@ -2,7 +2,7 @@ local replacements = {fuel = {}}
local http = ... local http = ...
IMPORT("maxn", "copy", "insert", "sort", "match", "sub") IMPORT("maxn", "copy", "insert", "sort", "match", "sub")
IMPORT("true_str", "is_table", "valid_item", "table_merge", "table_replace", "rcp_eq") IMPORT("true_str", "is_table", "valid_item", "table_merge", "table_replace", "table_eq")
IMPORT("fmt", "reg_items", "reg_aliases", "reg_nodes", "is_cube", "get_cube", "ItemStack") IMPORT("fmt", "reg_items", "reg_aliases", "reg_nodes", "is_cube", "get_cube", "ItemStack")
IMPORT("is_group", "extract_groups", "item_has_groups", "groups_to_items", "get_group_stereotype") IMPORT("is_group", "extract_groups", "item_has_groups", "groups_to_items", "get_group_stereotype")
@ -248,11 +248,7 @@ local old_clear_craft = core.clear_craft
core.clear_craft = function(def) core.clear_craft = function(def)
old_clear_craft(def) old_clear_craft(def)
if true_str(def) then -- TODO: hide in crafting guide
return -- TODO
elseif is_table(def) then
return -- TODO
end
end end
local function resolve_aliases(hash) local function resolve_aliases(hash)
@ -274,7 +270,7 @@ local function resolve_aliases(hash)
local rcp_new = copy(i3.recipes_cache[newname][j]) local rcp_new = copy(i3.recipes_cache[newname][j])
rcp_new.output = oldname rcp_new.output = oldname
if rcp_eq(rcp_old, rcp_new) then if table_eq(rcp_old, rcp_new) then
similar = true similar = true
break break
end end

View File

@ -148,10 +148,6 @@ if core.global_exists"skins" then
i3.modules.skins = true i3.modules.skins = true
end end
if core.global_exists"hb" then
i3.modules.hudbars = true
end
if core.global_exists"awards" then if core.global_exists"awards" then
i3.modules.awards = true i3.modules.awards = true
@ -207,6 +203,17 @@ local function init_data(player, info)
local name = player:get_player_name() local name = player:get_player_name()
i3.data[name] = i3.data[name] or {} i3.data[name] = i3.data[name] or {}
local data = i3.data[name] 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
end
data[k] = default[k]
end
data.player_name = name data.player_name = name
data.filter = "" data.filter = ""
@ -216,17 +223,11 @@ local function init_data(player, info)
data.items_raw = i3.init_items data.items_raw = i3.init_items
data.favs = {} data.favs = {}
data.show_setting = "home" data.show_setting = "home"
data.ignore_hotbar = false
data.auto_sorting = false
data.reverse_sorting = false
data.inv_compress = true
data.crafting_counts = {} data.crafting_counts = {}
data.sort = 1
data.tab = 1 data.tab = 1
data.itab = 1 data.itab = 1
data.subcat = 1 data.subcat = 1
data.scrbar_inv = 0 data.scrbar_inv = 0
data.font_size = data.font_size or 0
data.lang_code = get_lang_code(info) data.lang_code = get_lang_code(info)
data.fs_version = info.formspec_version data.fs_version = info.formspec_version

View File

@ -1,8 +1,8 @@
local vec = vector.new
local ItemStack = ItemStack local ItemStack = ItemStack
local loadstring = loadstring local loadstring = loadstring
local reg_items = core.registered_items local reg_items = core.registered_items
local translate = core.get_translated_string local translate = core.get_translated_string
local vec_new, vec_add, vec_mul = vector.new, vector.add, vector.multiply
local sort, concat, insert = table.sort, table.concat, table.insert local sort, concat, insert = table.sort, table.concat, table.insert
local min, floor, ceil = math.min, math.floor, math.ceil local min, floor, ceil = math.min, math.floor, math.ceil
local fmt, find, match, gmatch, sub, split, lower, upper = local fmt, find, match, gmatch, sub, split, lower, upper =
@ -216,18 +216,22 @@ local function array_diff(t1, t2)
return diff return diff
end end
local function rcp_eq(rcp, rcp2) local function table_eq(t1, t2)
if rcp.type ~= rcp2.type then return end local ty1, ty2 = type(t1), type(t2)
if rcp.width ~= rcp2.width then return end if ty1 ~= ty2 then return end
if #rcp.items ~= #rcp2.items then return end
if rcp.output ~= rcp2.output then return end
for i, item in pairs(rcp.items) do if ty1 ~= "table" and ty2 ~= "table" then
if item ~= rcp2.items[i] then return end return t1 == t2
end end
for i, item in pairs(rcp2.items) do for k, v in pairs(t1) do
if item ~= rcp.items[i] then return end local v2 = t2[k]
if v2 == nil or not table_eq(v, v2) then return end
end
for k, v in pairs(t2) do
local v1 = t1[k]
if v1 == nil or not table_eq(v1, v) then return end
end end
return true return true
@ -324,7 +328,7 @@ local function apply_recipe_filters(recipes, player)
end end
local function compression_active(data) local function compression_active(data)
return i3.settings.item_compression and not next(i3.recipe_filters) and data.filter == "" return data.collapse and not next(i3.recipe_filters) and data.filter == ""
end end
local function compressible(item, data) local function compressible(item, data)
@ -372,7 +376,7 @@ local function spawn_item(player, stack)
local dir = player:get_look_dir() local dir = player:get_look_dir()
local ppos = player:get_pos() local ppos = player:get_pos()
ppos.y = ppos.y + player:get_properties().eye_height ppos.y = ppos.y + player:get_properties().eye_height
local look_at = vec_add(ppos, vec_mul(dir, 1)) local look_at = ppos + dir
core.add_item(look_at, stack) core.add_item(look_at, stack)
end end
@ -469,9 +473,9 @@ local function safe_teleport(player, pos)
play_sound(name, "i3_teleport", 0.8) play_sound(name, "i3_teleport", 0.8)
local vel = player:get_velocity() local vel = player:get_velocity()
player:add_velocity(vec_mul(vel, -1)) player:add_velocity(-vel)
local p = vec_new(pos) local p = vec(pos)
p.y += 0.25 p.y += 0.25
player:set_pos(p) player:set_pos(p)
@ -764,7 +768,7 @@ local _ = {
is_table = is_table, is_table = is_table,
table_merge = table_merge, table_merge = table_merge,
table_replace = table_replace, table_replace = table_replace,
rcp_eq = rcp_eq, table_eq = table_eq,
array_diff = array_diff, array_diff = array_diff,
-- Math -- Math
@ -776,12 +780,8 @@ local _ = {
random = math.random, random = math.random,
-- Vectors -- Vectors
vec_new = vector.new, vec = vector.new,
vec_add = vector.add,
vec_sub = vector.subtract,
vec_mul = vector.multiply,
vec_round = vector.round, vec_round = vector.round,
vec_eq = vector.equals,
} }
function i3.get(...) function i3.get(...)

View File

@ -10,6 +10,9 @@ local trash = create_inventory("i3_trash", {
inv:set_list(listname, {}) inv:set_list(listname, {})
local name = player:get_player_name() local name = player:get_player_name()
local data = i3.data[name]
data.armor_allow = nil
play_sound(name, "i3_trash", 1.0) play_sound(name, "i3_trash", 1.0)
if not core.is_creative_enabled(name) then if not core.is_creative_enabled(name) then

View File

@ -1,13 +1,13 @@
local set_fs = i3.set_fs local set_fs = i3.set_fs
IMPORT("min", "max", "vec_round")
IMPORT("reg_items", "reg_aliases") IMPORT("reg_items", "reg_aliases")
IMPORT("min", "max", "vec_eq", "vec_round")
IMPORT("S", "random", "translate", "ItemStack")
IMPORT("sort", "copy", "insert", "remove", "indexof") IMPORT("sort", "copy", "insert", "remove", "indexof")
IMPORT("S", "random", "translate", "compressible", "ItemStack")
IMPORT("fmt", "find", "match", "sub", "lower", "split", "toupper") IMPORT("fmt", "find", "match", "sub", "lower", "split", "toupper")
IMPORT("valid_item", "get_stack", "craft_stack", "clean_name", "check_privs", "safe_teleport")
IMPORT("msg", "is_fav", "pos_to_str", "str_to_pos", "add_hud_waypoint", "play_sound", "reset_data") IMPORT("msg", "is_fav", "pos_to_str", "str_to_pos", "add_hud_waypoint", "play_sound", "reset_data")
IMPORT("search", "sort_inventory", "sort_by_category", "get_recipes", "get_detached_inv", "update_inv_size") IMPORT("search", "sort_inventory", "sort_by_category", "get_recipes", "get_detached_inv", "update_inv_size")
IMPORT("valid_item", "get_stack", "craft_stack", "clean_name", "compressible", "check_privs", "safe_teleport")
local function inv_fields(player, data, fields) local function inv_fields(player, data, fields)
local name = data.player_name local name = data.player_name
@ -19,6 +19,12 @@ local function inv_fields(player, data, fields)
return return
end end
if fields.dd_sorting_method then
data.sort = tonumber(fields.dd_sorting_method)
elseif fields.sb_font_size then
data.font_size = tonumber(fields.sb_font_size:match"-?%d+$")
end
for field in pairs(fields) do for field in pairs(fields) do
if sub(field, 1, 4) == "btn_" then if sub(field, 1, 4) == "btn_" then
data.subcat = indexof(i3.categories, sub(field, 5)) data.subcat = indexof(i3.categories, sub(field, 5))
@ -34,6 +40,8 @@ local function inv_fields(player, data, fields)
if str == "legacy_inventory" then if str == "legacy_inventory" then
update_inv_size(player, data) update_inv_size(player, data)
elseif str == "collapse" then
search(data)
end end
elseif sub(field, 1, 8) == "setting_" then elseif sub(field, 1, 8) == "setting_" then
@ -42,6 +50,8 @@ local function inv_fields(player, data, fields)
elseif sub(field, 1, 9) == "skin_btn_" then elseif sub(field, 1, 9) == "skin_btn_" then
local id = tonumber(field:match("%d+")) local id = tonumber(field:match("%d+"))
local _skins = skins.get_skinlist_for_player(name) local _skins = skins.get_skinlist_for_player(name)
play_sound(name, "i3_skin_change", 0.6)
skins.set_player_skin(player, _skins[id]) skins.set_player_skin(player, _skins[id])
elseif find(field, "waypoint_%d+") then elseif find(field, "waypoint_%d+") then
@ -128,9 +138,6 @@ local function inv_fields(player, data, fields)
elseif fields.sort then elseif fields.sort then
sort_inventory(player, data) sort_inventory(player, data)
elseif fields.dd_sorting_method then
data.sort = tonumber(fields.dd_sorting_method)
elseif fields.home then elseif fields.home then
if not data.home then if not data.home then
return msg(name, "No home set") return msg(name, "No home set")
@ -147,9 +154,6 @@ local function inv_fields(player, data, fields)
elseif fields.bag_rename then elseif fields.bag_rename then
data.bag_rename = true data.bag_rename = true
elseif fields.sb_font_size then
data.font_size = tonumber(fields.sb_font_size:match"-?%d+$")
elseif fields.confirm_rename then elseif fields.confirm_rename then
local bag = get_detached_inv("bag", name) local bag = get_detached_inv("bag", name)
local bagstack = bag:get_stack("main", 1) local bagstack = bag:get_stack("main", 1)
@ -180,7 +184,7 @@ local function inv_fields(player, data, fields)
local pos = player:get_pos() local pos = player:get_pos()
for _, v in ipairs(data.waypoints) do for _, v in ipairs(data.waypoints) do
if vec_eq(vec_round(pos), vec_round(str_to_pos(v.pos))) then if vec_round(pos) == vec_round(str_to_pos(v.pos)) then
play_sound(name, "i3_cannot", 0.8) play_sound(name, "i3_cannot", 0.8)
return msg(name, S"You already have set a waypoint at this position") return msg(name, S"You already have set a waypoint at this position")
end end
@ -290,13 +294,13 @@ local function select_item(player, data, fields)
if item == data.query_item then return end if item == data.query_item then return end
local recipes, usages = get_recipes(player, item) local recipes, usages = get_recipes(player, item)
data.query_item = item data.query_item = item
data.recipes = recipes data.recipes = recipes
data.usages = usages data.usages = usages
data.rnum = 1 data.rnum = 1
data.unum = 1 data.unum = 1
data.scrbar_rcp = 1 data.scrbar_rcp = 1
data.scrbar_usg = 1 data.scrbar_usg = 1
data.crafting_rcp = nil data.crafting_rcp = nil
data.crafting_usg = nil data.crafting_usg = nil
end end
@ -428,7 +432,7 @@ core.register_on_player_receive_fields(function(player, formname, fields)
if formname == "i3_outdated" then if formname == "i3_outdated" then
return false, core.kick_player(name, return false, core.kick_player(name,
S"Come back when your Minetest client is up-to-date (www.minetest.net).") S"Your Minetest client needs updating (www.minetest.net)")
elseif formname ~= "" then elseif formname ~= "" then
return false return false
end end

View File

@ -7,13 +7,13 @@ local PNG, styles, fs_elements, colors = i3.files.styles()
local sprintf = string.format local sprintf = string.format
local VoxelArea, VoxelManip = VoxelArea, VoxelManip local VoxelArea, VoxelManip = VoxelArea, VoxelManip
IMPORT("vec", "vec_round")
IMPORT("find", "match", "sub", "upper") IMPORT("find", "match", "sub", "upper")
IMPORT("vec_new", "vec_sub", "vec_round")
IMPORT("clr", "ESC", "msg", "check_privs") IMPORT("clr", "ESC", "msg", "check_privs")
IMPORT("compression_active", "compressible") IMPORT("compression_active", "compressible")
IMPORT("min", "max", "floor", "ceil", "round") IMPORT("min", "max", "floor", "ceil", "round")
IMPORT("reg_items", "reg_tools", "reg_entities")
IMPORT("true_str", "is_fav", "is_num", "str_to_pos") 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("get_bag_description", "get_detached_inv", "get_recipes")
IMPORT("S", "ES", "translate", "ItemStack", "toupper", "utf8_len") IMPORT("S", "ES", "translate", "ItemStack", "toupper", "utf8_len")
IMPORT("maxn", "sort", "concat", "copy", "insert", "remove", "unpack") IMPORT("maxn", "sort", "concat", "copy", "insert", "remove", "unpack")
@ -131,7 +131,7 @@ local function get_inv_slots(data, fs)
local legacy_inventory = data.legacy_inventory local legacy_inventory = data.legacy_inventory
local hotbar_len = data.hotbar_len local hotbar_len = data.hotbar_len
local inv_x = legacy_inventory and 0.23 or 0.22 local inv_x = legacy_inventory and 0.23 or 0.22
local inv_y = legacy_inventory and 6.5 or 6.9 local inv_y = legacy_inventory and 6.7 or 6.9
local spacing = legacy_inventory and 0.25 or 0.1 local spacing = legacy_inventory and 0.25 or 0.1
local size = 1 local size = 1
@ -141,20 +141,20 @@ local function get_inv_slots(data, fs)
box(i * size + inv_x + (i * spacing), inv_y, size, size, "") box(i * size + inv_x + (i * spacing), inv_y, size, size, "")
end end
fs(fmt("style_type[list;size=%f;spacing=%f]", size, spacing), fs("style_type[list;size=%f;spacing=%f]", size, spacing)
fmt("list[current_player;main;%f,%f;%u,1;]", inv_x, inv_y, hotbar_len)) fs("list[current_player;main;%f,%f;%u,1;]", inv_x, inv_y, hotbar_len)
fs(fmt("style_type[list;size=%f;spacing=%f]", size, spacing)) fs("style_type[list;size=%f;spacing=%f,%f]", size, spacing, legacy_inventory and 0.15 or spacing)
fs(fmt("list[current_player;main;%f,%f;%u,%u;%u]", inv_x, inv_y + (legacy_inventory and 1.25 or 1.15), fs("list[current_player;main;%f,%f;%u,%u;%u]", inv_x, inv_y + (legacy_inventory and 1.25 or 1.15),
hotbar_len, data.inv_size / hotbar_len, hotbar_len)) hotbar_len, data.inv_size / hotbar_len, hotbar_len)
fs"style_type[list;size=1;spacing=0.15]" fs"style_type[list;size=1;spacing=0.15]"
fs"listring[current_player;craft]listring[current_player;main]" fs"listring[current_player;craft]listring[current_player;main]"
end end
local function add_subtitle(fs, name, y, ctn_len, font_size, sep, label) local function add_subtitle(fs, name, y, ctn_len, font_size, sep, label)
fs(fmt("style[%s;font=bold;font_size=%u]", name, font_size)) fs("style[%s;font=bold;font_size=%u]", name, font_size)
button(0, y, ctn_len, 0.5, name, ESC(label)) button(0, y, ctn_len, 0.5, name, ESC(label))
if sep then if sep then
@ -240,8 +240,8 @@ local function get_isometric_view(fs, pos, X, Y, t, cubes, depth, high)
local max_depth = -7 local max_depth = -7
local height = base_depth and (base_height - 1) or depth local height = base_depth and (base_height - 1) or depth
local pos1 = vec_new(pos.x - width, pos.y + depth, pos.z - width) local pos1 = vec(pos.x - width, pos.y + depth, pos.z - width)
local pos2 = vec_new(pos.x + width, pos.y + height, pos.z + width) local pos2 = vec(pos.x + width, pos.y + height, pos.z + width)
local vm = VoxelManip(pos1, pos2) local vm = VoxelManip(pos1, pos2)
local emin, emax = vm:get_emerged_area() local emin, emax = vm:get_emerged_area()
@ -255,7 +255,7 @@ local function get_isometric_view(fs, pos, X, Y, t, cubes, depth, high)
if img then if img then
local p = area:position(idx) local p = area:position(idx)
p = vec_sub(p, pos) p -= pos
local size = 0.25 local size = 0.25
local x = 2 + (size / 2 * (p.z - p.x)) local x = 2 + (size / 2 * (p.z - p.x))
@ -301,11 +301,11 @@ local function get_isometric_view(fs, pos, X, Y, t, cubes, depth, high)
end end
local function get_waypoint_fs(fs, data, player, yextra, ctn_len) local function get_waypoint_fs(fs, data, player, yextra, ctn_len)
fs(fmt("box[0,%f;4.9,0.6;#bababa25]", yextra + 1.1)) fs("box[0,%f;4.9,0.6;#bababa25]", yextra + 1.1)
label(0, yextra + 0.85, ES"New waypoint" .. ":") label(0, yextra + 0.85, ES"New waypoint" .. ":")
fs(fmt("field[0.1,%f;4.8,0.6;waypoint_name;;]", yextra + 1.1)) fs("field[0.1,%f;4.8,0.6;waypoint_name;;]", yextra + 1.1)
image_button(5.1, yextra + 1.15, 0.5, 0.5, "", "waypoint_add", "") image_button(5.1, yextra + 1.15, 0.5, 0.5, "", "waypoint_add", "")
fs(fmt("tooltip[waypoint_add;%s]", ES"Add waypoint")) fs("tooltip[waypoint_add;%s]", ES"Add waypoint")
if #data.waypoints == 0 then return end if #data.waypoints == 0 then return end
fs"style_type[label;font=bold;font_size=17]" fs"style_type[label;font=bold;font_size=17]"
@ -332,7 +332,7 @@ local function get_waypoint_fs(fs, data, player, yextra, ctn_len)
label(0.15, y + 0.33, clr(fmt("#%s", hex), waypoint_name)) label(0.15, y + 0.33, clr(fmt("#%s", hex), waypoint_name))
local tooltip = fmt("Name: %s\nPosition:%s", clr("#dbeeff", v.name), local tooltip = fmt("Name: %s\nPosition:%s", clr("#dbeeff", v.name),
v.pos:sub(2,-2):gsub("(%-*%d*%.?%d+)", clr("#dbeeff", " %1"))) v.pos:sub(2,-2):gsub("(%-*%d*%.?%d+)", clr("#dbeeff", " %1")))
if teleport_priv then if teleport_priv then
tooltip = fmt("%s\n%s", tooltip, clr("#ff0", ES"[Click to teleport]")) tooltip = fmt("%s\n%s", tooltip, clr("#ff0", ES"[Click to teleport]"))
@ -341,25 +341,25 @@ local function get_waypoint_fs(fs, data, player, yextra, ctn_len)
tooltip(0, y, ctn_len - 2.1, 0.65, tooltip) tooltip(0, y, ctn_len - 2.1, 0.65, tooltip)
local del = fmt("waypoint_%u_delete", i) local del = fmt("waypoint_%u_delete", i)
fs(fmt("style[%s;fgimg=%s;fgimg_hovered=%s;content_offset=0]", del, PNG.trash, PNG.trash_hover)) fs("style[%s;fgimg=%s;fgimg_hovered=%s;content_offset=0]", del, PNG.trash, PNG.trash_hover)
image_button(ctn_len - 0.5, yi, icon_size, icon_size, "", del, "") image_button(ctn_len - 0.5, yi, icon_size, icon_size, "", del, "")
fs(fmt("tooltip[%s;%s]", del, ES"Remove waypoint")) fs("tooltip[%s;%s]", del, ES"Remove waypoint")
local rfs = fmt("waypoint_%u_refresh", i) local rfs = fmt("waypoint_%u_refresh", i)
fs(fmt("style[%s;fgimg=%s;fgimg_hovered=%s;content_offset=0]", rfs, PNG.refresh, PNG.refresh_hover)) fs("style[%s;fgimg=%s;fgimg_hovered=%s;content_offset=0]", rfs, PNG.refresh, PNG.refresh_hover)
image_button(ctn_len - 1, yi, icon_size, icon_size, "", rfs, "") image_button(ctn_len - 1, yi, icon_size, icon_size, "", rfs, "")
fs(fmt("tooltip[%s;%s]", rfs, ES"Change color")) fs("tooltip[%s;%s]", rfs, ES"Change color")
local see = fmt("waypoint_%u_see", i) local see = fmt("waypoint_%u_see", i)
fs(fmt("style[%s;fgimg=%s;fgimg_hovered=%s;content_offset=0]", fs("style[%s;fgimg=%s;fgimg_hovered=%s;content_offset=0]",
see, waypoint_preview and PNG.search_hover or PNG.search, PNG.search, PNG.search_hover)) see, waypoint_preview and PNG.search_hover or PNG.search, PNG.search, PNG.search_hover)
image_button(ctn_len - 1.5, yi, icon_size, icon_size, "", see, "") image_button(ctn_len - 1.5, yi, icon_size, icon_size, "", see, "")
fs(fmt("tooltip[%s;%s]", see, ES"Preview the waypoint area")) fs("tooltip[%s;%s]", see, ES"Preview the waypoint area")
local vsb = fmt("waypoint_%u_hide", i) local vsb = fmt("waypoint_%u_hide", i)
fs(fmt("style[%s;fgimg=%s;content_offset=0]", vsb, v.hide and PNG.nonvisible or PNG.visible)) fs("style[%s;fgimg=%s;content_offset=0]", vsb, v.hide and PNG.nonvisible or PNG.visible)
image_button(ctn_len - 2, yi, icon_size, icon_size, "", vsb, "") image_button(ctn_len - 2, yi, icon_size, icon_size, "", vsb, "")
fs(fmt("tooltip[%s;%s]", vsb, v.hide and ES"Show waypoint" or ES"Hide waypoint")) fs("tooltip[%s;%s]", vsb, v.hide and ES"Show waypoint" or ES"Hide waypoint")
if teleport_priv then if teleport_priv then
local tp = fmt("waypoint_%u_teleport", i) local tp = fmt("waypoint_%u_teleport", i)
@ -381,7 +381,7 @@ local function get_waypoint_fs(fs, data, player, yextra, ctn_len)
end end
local function get_bag_fs(fs, data, name, esc_name, bag_size, yextra) local function get_bag_fs(fs, data, name, esc_name, bag_size, yextra)
fs(fmt("list[detached:i3_bag_%s;main;0,%f;1,1;]", esc_name, yextra + 0.7)) fs("list[detached:i3_bag_%s;main;0,%f;1,1;]", esc_name, yextra + 0.7)
local bag = get_detached_inv("bag", name) local bag = get_detached_inv("bag", name)
if bag:is_empty"main" then return end if bag:is_empty"main" then return end
@ -392,18 +392,18 @@ local function get_bag_fs(fs, data, name, esc_name, bag_size, yextra)
local desc = ESC(get_bag_description(data, bagstack)) local desc = ESC(get_bag_description(data, bagstack))
image(0.5, yextra + 1.85, 0.6, 0.6, PNG.arrow_content) image(0.5, yextra + 1.85, 0.6, 0.6, PNG.arrow_content)
fs(fmt("style[bg_content;bgimg=%s;fgimg=i3_blank.png;bgimg_middle=10,%u;sound=]", PNG.bg_content, m)) fs("style[bg_content;bgimg=%s;fgimg=i3_blank.png;bgimg_middle=10,%u;sound=]", PNG.bg_content, m)
image_button(1.1, yextra + 0.5 + (yy or 0), 4.75, h, "", "bg_content", "") image_button(1.1, yextra + 0.5 + (yy or 0), 4.75, h, "", "bg_content", "")
if not data.bag_rename then if not data.bag_rename then
hypertext(1.3, yextra + 0.8, 4.3, 0.6, "content", hypertext(1.3, yextra + 0.8, 4.3, 0.6, "content",
fmt("<global size=16><center><b>%s</b></center>", desc)) fmt("<global size=16><center><b>%s</b></center>", desc))
image_button(5.22, yextra + 0.835, 0.25, 0.25, "", "bag_rename", "") image_button(5.22, yextra + 0.835, 0.25, 0.25, "", "bag_rename", "")
fs(fmt("tooltip[%s;%s]", "bag_rename", ES"Rename the bag")) fs("tooltip[bag_rename;%s]", ES"Rename the bag")
else else
box(1.7, yextra + 0.82, 2.6, 0.4, "#707070") box(1.7, yextra + 0.82, 2.6, 0.4, "#707070")
fs(fmt("field[1.8,%f;2.5,0.4;bag_newname;;%s]", yextra + 0.82, desc), fs("field[1.8,%f;2.5,0.4;bag_newname;;%s]", yextra + 0.82, desc)
"field_close_on_enter[bag_newname;false]") fs"field_close_on_enter[bag_newname;false]"
hypertext(4.4, yextra + 0.88, 0.8, 0.6, "confirm_rename", hypertext(4.4, yextra + 0.88, 0.8, 0.6, "confirm_rename",
fmt("<global size=16><tag name=action color=#fff hovercolor=%s>" .. fmt("<global size=16><tag name=action color=#fff hovercolor=%s>" ..
"<center><b><action name=ok>OK</action></b></center>", colors.yellow)) "<center><b><action name=ok>OK</action></b></center>", colors.yellow))
@ -415,8 +415,8 @@ local function get_bag_fs(fs, data, name, esc_name, bag_size, yextra)
x, size, spacing = 1.7, 0.8, 0.1 x, size, spacing = 1.7, 0.8, 0.1
end end
fs(fmt("style_type[list;size=%f;spacing=%f]", size, spacing)) fs("style_type[list;size=%f;spacing=%f]", size, spacing)
fs(fmt("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;]", esc_name, x, yextra + 1.3, bag_size)
fs"style_type[list;size=1;spacing=0.15]" fs"style_type[list;size=1;spacing=0.15]"
end end
@ -435,7 +435,7 @@ local function get_container(fs, data, player, yoffset, ctn_len, award_list, awa
for i = 1, 10 do for i = 1, 10 do
image(heart_x + ((i - 1) * (heart_size + 0.1)), heart_h, image(heart_x + ((i - 1) * (heart_size + 0.1)), heart_h,
heart_size, heart_size, PNG.heart_grey) heart_size, heart_size, PNG.heart .. "^[colorize:#232428")
end end
for i = 1, hearts do for i = 1, hearts do
@ -447,21 +447,21 @@ local function get_container(fs, data, player, yoffset, ctn_len, award_list, awa
yoffset -= 0.5 yoffset -= 0.5
end end
fs(fmt("list[current_player;craft;%f,%f;3,3;]", 0, yoffset + 1.45)) fs("list[current_player;craft;%f,%f;3,3;]", 0, yoffset + 1.45)
image(3.47, yoffset + 2.69, 0.85, 0.85, PNG.arrow) image(3.47, yoffset + 2.69, 0.85, 0.85, PNG.arrow)
fs(fmt("list[current_player;craftpreview;%f,%f;1,1;]", 4.45, yoffset + 2.6), fs("list[current_player;craftpreview;%f,%f;1,1;]", 4.45, yoffset + 2.6)
fmt("list[detached:i3_trash;main;%f,%f;1,1;]", 4.45, yoffset + 3.75)) fs("list[detached:i3_trash;main;%f,%f;1,1;]", 4.45, yoffset + 3.75)
image(4.45, yoffset + 3.75, 1, 1, PNG.trash) image(4.45, yoffset + 3.75, 1, 1, PNG.trash)
local yextra = damage_enabled and 5.5 or 5 local yextra = damage_enabled and 5.5 or 5
for i, title in ipairs(i3.categories) do for i, title in ipairs(i3.categories) do
local btn_name = fmt("btn_%s", title) local btn_name = fmt("btn_%s", title)
fs(fmt("style[btn_%s;fgimg=%s;fgimg_hovered=%s;content_offset=0]", title, fs("style[btn_%s;fgimg=%s;fgimg_hovered=%s;content_offset=0]", title,
data.subcat == i and PNG[fmt("%s_hover", title)] or PNG[title], data.subcat == i and PNG[fmt("%s_hover", title)] or PNG[title],
PNG[fmt("%s_hover", title)])) PNG[fmt("%s_hover", title)])
image_button(0.25 + ((i - 1) * 1.18), yextra - 0.2, 0.5, 0.5, "", btn_name, "") image_button(0.25 + ((i - 1) * 1.18), yextra - 0.2, 0.5, 0.5, "", btn_name, "")
fs(fmt("tooltip[%s;%s]", btn_name, title:gsub("^%l", upper))) fs("tooltip[%s;%s]", btn_name, title:gsub("^%l", upper))
end end
box(0, yextra + 0.45, ctn_len, 0.045, "#bababa50") box(0, yextra + 0.45, ctn_len, 0.045, "#bababa50")
@ -484,7 +484,7 @@ local function get_container(fs, data, player, yoffset, ctn_len, award_list, awa
local armor_def = armor.def[name] local armor_def = armor.def[name]
local _, armor_inv = armor:get_valid_player(player, "3d_armor") local _, armor_inv = armor:get_valid_player(player, "3d_armor")
fs(fmt("list[detached:%s_armor;armor;0,%f;5,1;]", esc_name, yextra + 0.7)) fs("list[detached:%s_armor;armor;0,%f;5,1;]", esc_name, yextra + 0.7)
for i = 1, 5 do for i = 1, 5 do
local stack = armor_inv:get_stack("armor", i) local stack = armor_inv:get_stack("armor", i)
@ -548,11 +548,10 @@ local function get_container(fs, data, player, yoffset, ctn_len, award_list, awa
if not skin then break end if not skin then break end
local btn_name = fmt("skin_btn_%u", i + 1) local btn_name = fmt("skin_btn_%u", i + 1)
fs(fmt([[ style[%s;padding=10; fs([[ style[%s;padding=10;fgimg=%s;bgimg=%s;bgimg_hovered=i3_btn9_hovered.png;
fgimg=%s;bgimg=%s;bgimg_hovered=i3_btn9_hovered.png; bgimg_pressed=i3_btn9_pressed.png;bgimg_middle=4,6;sound=] ]],
bgimg_pressed=i3_btn9_pressed.png;bgimg_middle=4,6] ]],
btn_name, skin:get_preview(), btn_name, skin:get_preview(),
skin.name == skin_name and "i3_btn9_hovered.png" or "i3_btn9.png")) skin.name == skin_name and "i3_btn9_hovered.png" or "i3_btn9.png")
local X = (i % 3) * 1.93 local X = (i % 3) * 1.93
@ -560,7 +559,7 @@ local function get_container(fs, data, player, yoffset, ctn_len, award_list, awa
Y += (Y * 2.45) + yextra - 2.75 + add_y Y += (Y * 2.45) + yextra - 2.75 + add_y
image_button(X, Y, 1.86, 3.4, "", btn_name, "") image_button(X, Y, 1.86, 3.4, "", btn_name, "")
fs(fmt("tooltip[%s;%s]", btn_name, ESC(skin.name))) fs("tooltip[%s;%s]", btn_name, ESC(skin.name))
end end
elseif data.subcat == 4 then elseif data.subcat == 4 then
@ -584,32 +583,33 @@ local function show_settings(fs, data)
image_button(6.17, 10.75, 1, 0.5, "", "confirm_trash_no", "No") image_button(6.17, 10.75, 1, 0.5, "", "confirm_trash_no", "No")
elseif data.show_settings then elseif data.show_settings then
image(2.2, 9, 6, 2.35, PNG.bg_content) fs"container[-0.06,0]"
image(2.2, 9, 6.1, 2.35, PNG.bg_content)
local show_home = data.show_setting == "home" local show_home = data.show_setting == "home"
local show_style = data.show_setting == "style" local show_style = data.show_setting == "style"
local show_sorting = data.show_setting == "sorting" local show_sorting = data.show_setting == "sorting"
fs"style[setting_home,setting_style,setting_sorting;font=bold;font_size=16;sound=i3_click]" fs"style[setting_home,setting_style,setting_sorting;font=bold;font_size=16;sound=i3_click]"
fs(fmt("style[setting_home:hovered;textcolor=%s]", show_home and colors.yellow or "#fff")) fs("style[setting_home:hovered;textcolor=%s]", show_home and colors.yellow or "#fff")
fs(fmt("style[setting_style:hovered;textcolor=%s]", show_style and colors.yellow or "#fff")) fs("style[setting_style:hovered;textcolor=%s]", show_style and colors.yellow or "#fff")
fs(fmt("style[setting_sorting:hovered;textcolor=%s]", show_sorting and colors.yellow or "#fff")) fs("style[setting_sorting:hovered;textcolor=%s]", show_sorting and colors.yellow or "#fff")
fs(fmt("style[setting_home;bgimg=%s;bgimg_hovered=%s;bgimg_middle=9;padding=-9;textcolor=%s]", fs("style[setting_home;bgimg=%s;bgimg_hovered=%s;bgimg_middle=9;padding=-9;textcolor=%s]",
show_home and PNG.pagenum_hover or "", PNG.pagenum_hover, show_home and PNG.pagenum_hover or "", PNG.pagenum_hover,
show_home and colors.yellow or "#ddd"), show_home and colors.yellow or "#ddd")
fmt("style[setting_style;bgimg=%s;bgimg_hovered=%s;bgimg_middle=9;padding=-9;textcolor=%s]", fs("style[setting_style;bgimg=%s;bgimg_hovered=%s;bgimg_middle=9;padding=-9;textcolor=%s]",
show_style and PNG.pagenum_hover or "", PNG.pagenum_hover, show_style and PNG.pagenum_hover or "", PNG.pagenum_hover,
show_style and colors.yellow or "#ddd"), show_style and colors.yellow or "#ddd")
fmt("style[setting_sorting;bgimg=%s;bgimg_hovered=%s;bgimg_middle=9;padding=-9;textcolor=%s]", fs("style[setting_sorting;bgimg=%s;bgimg_hovered=%s;bgimg_middle=9;padding=-9;textcolor=%s]",
show_sorting and PNG.pagenum_hover or "", PNG.pagenum_hover, show_sorting and PNG.pagenum_hover or "", PNG.pagenum_hover,
show_sorting and colors.yellow or "#ddd")) show_sorting and colors.yellow or "#ddd")
local X = 2.5 local X = 2.5
button(X, 9.1, 1.6, 0.55, "setting_home", "Home") button(X, 9.1, 1.6, 0.55, "setting_home", "Home")
button(X + 1.6, 9.1, 1.6, 0.55, "setting_style", "Style") button(X + 1.7, 9.1, 1.6, 0.55, "setting_style", "Style")
button(X + 3.2, 9.1, 1.6, 0.55, "setting_sorting", "Sorting") button(X + 3.38, 9.1, 1.6, 0.55, "setting_sorting", "Sorting")
image_button(X + 5, 9.2, 0.25, 0.25, PNG.cancel_hover .. "^\\[brighten", "close_settings", "") image_button(X + 5.12, 9.2, 0.25, 0.25, PNG.cancel_hover .. "^\\[brighten", "close_settings", "")
if show_home then if show_home then
local coords, c, str = {"X", "Y", "Z"}, 0, ES"No home set" local coords, c, str = {"X", "Y", "Z"}, 0, ES"No home set"
@ -623,33 +623,39 @@ local function show_settings(fs, data)
end) end)
end end
hypertext(2.1, 9.9, 6, 0.6, "home_pos", fmt("<global size=16><center>%s</center>", str)) hypertext(2.2, 9.9, 6, 0.6, "home_pos", fmt("<global size=16><center>%s</center>", str))
image_button(4.2, 10.4, 1.8, 0.7, "", "set_home", "Set home") image_button(4.3, 10.4, 1.8, 0.7, "", "set_home", "Set home")
elseif show_style then elseif show_style then
checkbox(2.6, 9.95, "cb_hide_tabs", "Hide tabs", tostring(data.hide_tabs)) checkbox(2.6, 9.95, "cb_hide_tabs", "Hide tabs", tostring(data.hide_tabs))
checkbox(2.6, 10.4, "cb_legacy_inventory", "Legacy inventory", tostring(data.legacy_inventory)) 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)) 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))
end
local sign = (data.font_size > 0 and "+") or (data.font_size > 0 and "-") or "" local sign = (data.font_size > 0 and "+") or (data.font_size > 0 and "-") or ""
label(5.3, 9.95, ES"Font size" .. fmt(": %s", sign .. data.font_size)) label(5.3, 9.95, ES"Font size" .. fmt(": %s", sign .. data.font_size))
local range = 5 local range = 5
fs(fmt("scrollbaroptions[min=-%u;max=%u;smallstep=1;largestep=1;thumbsize=2]", range, range)) fs("scrollbaroptions[min=-%u;max=%u;smallstep=1;largestep=1;thumbsize=2]", range, range)
fs(fmt("scrollbar[5.3,10.25;2.45,0.3;horizontal;sb_font_size;%d]", data.font_size)) fs("scrollbar[5.3,10.2;2.45,0.3;horizontal;sb_font_size;%d]", data.font_size)
fs(fmt("tooltip[cb_hide_tabs;%s;#707070;#fff]", fs("tooltip[cb_hide_tabs;%s;#707070;#fff]",
ES"Enable this option to change the style of the right panel"), ES"Enable this option to change the style of the right panel")
fmt("tooltip[cb_legacy_inventory;%s;#707070;#fff]", fs("tooltip[cb_legacy_inventory;%s;#707070;#fff]",
ES"Enable this option to set the classic inventory size in Minetest"), ES"Enable this option to set the classic inventory size in Minetest")
fmt("tooltip[cb_wielditem_hud;%s;#707070;#fff]", fs("tooltip[cb_wielditem_hud;%s;#707070;#fff]",
ES"Enable this option to show the wielded item description in your HUD")) 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")
elseif show_sorting then elseif show_sorting then
checkbox(2.6, 9.95, "cb_inv_compress", "Compression", tostring(data.inv_compress)) checkbox(2.6, 9.95, "cb_inv_compress", "Compression", tostring(data.inv_compress))
checkbox(2.6, 10.4, "cb_reverse_sorting", "Reverse mode", tostring(data.reverse_sorting)) checkbox(2.6, 10.4, "cb_reverse_sorting", "Reverse mode", tostring(data.reverse_sorting))
checkbox(2.6, 10.85, "cb_ignore_hotbar", "Ignore hotbar", tostring(data.ignore_hotbar)) checkbox(2.6, 10.85, "cb_ignore_hotbar", "Ignore hotbar", tostring(data.ignore_hotbar))
checkbox(5.5, 9.95, "cb_auto_sorting", "Automation", tostring(data.auto_sorting)) checkbox(5.3, 9.95, "cb_auto_sorting", "Automation", tostring(data.auto_sorting))
local methods = {} local methods = {}
@ -658,24 +664,26 @@ local function show_settings(fs, data)
insert(methods, name) insert(methods, name)
end end
label(5.5, 10.4, ES"Sorting method:") label(5.3, 10.4, ES"Sorting method:")
fs(fmt("dropdown[%f,%f;2.3,0.5;dd_sorting_method;%s;%u;true]", fs("dropdown[%f,%f;2.6,0.5;dd_sorting_method;%s;%u;true]",
5.5, 10.6, concat(methods, ","), data.sort)) 5.3, 10.6, concat(methods, ","), data.sort)
local desc = i3.sorting_methods[data.sort].description local desc = i3.sorting_methods[data.sort].description
if desc then if desc then
tooltip(5.5, 10.6, 2.3, 0.5, ESC(desc)) tooltip(5.3, 10.6, 2.4, 0.5, ESC(desc))
end end
fs(fmt("tooltip[cb_inv_compress;%s;#707070;#fff]", fs("tooltip[cb_inv_compress;%s;#707070;#fff]",
ES"Enable this option to compress your inventory"), ES"Enable this option to compress your inventory")
fmt("tooltip[cb_reverse_sorting;%s;#707070;#fff]", fs("tooltip[cb_reverse_sorting;%s;#707070;#fff]",
ES"Enable this option to sort your inventory in reverse order"), ES"Enable this option to sort your inventory in reverse order")
fmt("tooltip[cb_ignore_hotbar;%s;#707070;#fff]", fs("tooltip[cb_ignore_hotbar;%s;#707070;#fff]",
ES"Enable this option to sort your inventory except the hotbar slots"), ES"Enable this option to sort your inventory except the hotbar slots")
fmt("tooltip[cb_auto_sorting;%s;#707070;#fff]", fs("tooltip[cb_auto_sorting;%s;#707070;#fff]",
ES"Enable this option to sort your inventory automatically")) ES"Enable this option to sort your inventory automatically")
end end
fs"container_end[]"
end end
end end
@ -755,14 +763,12 @@ local function get_inventory_fs(player, data, fs)
end end
end end
fs(fmt([[ fs([[ scrollbaroptions[arrows=hide;thumbsize=%d;max=%d]
scrollbaroptions[arrows=hide;thumbsize=%d;max=%d]
scrollbar[%f,0.2;0.2,%f;vertical;scrbar_inv;%u] scrollbar[%f,0.2;0.2,%f;vertical;scrbar_inv;%u]
scrollbaroptions[arrows=default;thumbsize=0;max=1000] scrollbaroptions[arrows=default;thumbsize=0;max=1000] ]],
]], (max_val * 4) / 12, max_val, 9.8, ctn_hgt, data.scrbar_inv)
(max_val * 4) / 12, max_val, 9.8, ctn_hgt, data.scrbar_inv))
fs(fmt("scroll_container[3.9,0.2;%f,%f;scrbar_inv;vertical]", ctn_len, ctn_hgt)) fs("scroll_container[3.9,0.2;%f,%f;scrbar_inv;vertical]", ctn_len, ctn_hgt)
get_container(fs, data, player, yoffset, ctn_len, award_list, awards_unlocked, award_list_nb, bag_size) get_container(fs, data, player, yoffset, ctn_len, award_list, awards_unlocked, award_list_nb, bag_size)
fs"scroll_container_end[]" fs"scroll_container_end[]"
@ -775,10 +781,10 @@ local function get_inventory_fs(player, data, fs)
for i, v in ipairs(btn) do for i, v in ipairs(btn) do
local btn_name, tooltip = unpack(v) local btn_name, tooltip = unpack(v)
fs(fmt("style[%s;fgimg=%s;fgimg_hovered=%s;content_offset=0]", fs("style[%s;fgimg=%s;fgimg_hovered=%s;content_offset=0]",
btn_name, PNG[btn_name], PNG[fmt("%s_hover", btn_name)])) btn_name, PNG[btn_name], PNG[fmt("%s_hover", btn_name)])
image_button(i + 3.43 - (i * 0.4), 11.43, 0.35, 0.35, "", btn_name, "") image_button(i + 3.43 - (i * 0.4), 11.43, 0.35, 0.35, "", btn_name, "")
fs(fmt("tooltip[%s;%s]", btn_name, tooltip)) fs("tooltip[%s;%s]", btn_name, tooltip)
end end
show_settings(fs, data) show_settings(fs, data)
@ -940,9 +946,9 @@ local function get_output_fs(fs, data, rcp, is_recipe, is_usage, shapeless, righ
if meta:get_string"color" ~= "" or meta:get_string"palette_index" ~= "" then if meta:get_string"color" ~= "" or meta:get_string"palette_index" ~= "" then
local rcp_usg = is_recipe and "rcp" or "usg" local rcp_usg = is_recipe and "rcp" or "usg"
fs(fmt("style_type[list;size=%f]", BTN_SIZE)) fs("style_type[list;size=%f]", BTN_SIZE)
fs"listcolors[#bababa50;#bababa99]" fs"listcolors[#bababa50;#bababa99]"
fs(fmt("list[detached:i3_output_%s_%s;main;%f,%f;1,1;]", rcp_usg, data.player_name, X + 0.11, Y)) 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, "") button(X + 0.11, Y, BTN_SIZE, BTN_SIZE, _name, "")
local inv = get_detached_inv(fmt("output_%s", rcp_usg), data.player_name) local inv = get_detached_inv(fmt("output_%s", rcp_usg), data.player_name)
@ -1218,19 +1224,19 @@ local function get_header(fs, data)
if nfavs < max_favs or (nfavs == max_favs and fav) then if nfavs < max_favs or (nfavs == max_favs and fav) then
local fav_marked = fmt("i3_fav%s.png", fav and "_off" or "") local fav_marked = fmt("i3_fav%s.png", fav and "_off" or "")
fs(fmt("style[fav;fgimg=%s;fgimg_hovered=%s;fgimg_pressed=%s]", fs("style[fav;fgimg=%s;fgimg_hovered=%s;fgimg_pressed=%s]",
fmt("i3_fav%s.png", fav and "" or "_off"), fav_marked, fav_marked)) fmt("i3_fav%s.png", fav and "" or "_off"), fav_marked, fav_marked)
image_button(star_x, star_y, size, size, "", "fav", "") image_button(star_x, star_y, size, size, "", "fav", "")
fs(fmt("tooltip[fav;%s]", fav and ES"Unmark this item" or ES"Mark this item")) fs("tooltip[fav;%s]", fav and ES"Unmark this item" or ES"Mark this item")
else else
fs(fmt("style[nofav;fgimg=%s;fgimg_hovered=%s;fgimg_pressed=%s]", fs("style[nofav;fgimg=%s;fgimg_hovered=%s;fgimg_pressed=%s]",
"i3_fav_off.png", PNG.cancel, PNG.cancel)) "i3_fav_off.png", PNG.cancel, PNG.cancel)
image_button(star_x, star_y, size, size, "", "nofav", "") image_button(star_x, star_y, size, size, "", "nofav", "")
fs(fmt("tooltip[nofav;%s]", ES"Cannot mark this item. Bookmark limit reached.")) fs("tooltip[nofav;%s]", ES"Cannot mark this item. Bookmark limit reached.")
end end
image_button(star_x + 0.05, star_y + 0.6, size, size, "", "exit", "") image_button(star_x + 0.05, star_y + 0.6, size, size, "", "exit", "")
fs(fmt("tooltip[exit;%s]", ES"Back to item list")) fs("tooltip[exit;%s]", ES"Back to item list")
local desc_lim, name_lim = 34, 35 local desc_lim, name_lim = 34, 35
local desc = get_desc(data.query_item, data.lang_code) local desc = get_desc(data.query_item, data.lang_code)
@ -1270,10 +1276,10 @@ local function get_crafting_fs(fs, data, is_recipe, is_usage, max_stacks_rcp, ma
local name = is_recipe and "rcp" or "usg" local name = is_recipe and "rcp" or "usg"
local show_crafting = (is_recipe and data.crafting_rcp) or (is_usage and data.crafting_usg) local show_crafting = (is_recipe and data.crafting_rcp) or (is_usage and data.crafting_usg)
fs(fmt("style[crafting_%s;fgimg=%s;fgimg_hovered=%s;content_offset=0]", fs("style[crafting_%s;fgimg=%s;fgimg_hovered=%s;content_offset=0]",
name, fmt("%s", show_crafting and PNG.crafting_hover or PNG.crafting), PNG.crafting_hover)) name, fmt("%s", show_crafting and PNG.crafting_hover or PNG.crafting), PNG.crafting_hover)
image_button(data.inv_width + 7.35, data.yoffset + 0.2, 0.45, 0.45, "", fmt("crafting_%s", name), "") image_button(data.inv_width + 7.35, data.yoffset + 0.2, 0.45, 0.45, "", fmt("crafting_%s", name), "")
fs(fmt("tooltip[crafting_%s;%s]", name, ES"Quick crafting")) fs("tooltip[crafting_%s;%s]", name, ES"Quick crafting")
if not show_crafting then return end if not show_crafting then return end
@ -1297,8 +1303,8 @@ local function get_crafting_fs(fs, data, is_recipe, is_usage, max_stacks_rcp, ma
fs"style[quick_crafting;font_size=16;textcolor=#ddd]" fs"style[quick_crafting;font_size=16;textcolor=#ddd]"
button(x, data.yoffset + 0.85, 3.05, 0.55, "quick_crafting", ES"Quick Crafting") button(x, data.yoffset + 0.85, 3.05, 0.55, "quick_crafting", ES"Quick Crafting")
fs(fmt("style[scrbar_%s;noclip=true]", name), fs("style[scrbar_%s;noclip=true]", name)
fmt("scrollbaroptions[min=1;max=%u;smallstep=1]", craft_max)) fs("scrollbaroptions[min=1;max=%u;smallstep=1]", craft_max)
scrollbar(x + 0.2, data.yoffset + 1.45, 2.5, 0.35, "horizontal", fmt("scrbar_%s", name), stack_fs) scrollbar(x + 0.2, data.yoffset + 1.45, 2.5, 0.35, "horizontal", fmt("scrbar_%s", name), stack_fs)
button(x + 0.2, data.yoffset + 1.85, 2.5, 0.7, fmt("craft_%s", name), ES("Craft (×@1)", stack_fs)) button(x + 0.2, data.yoffset + 1.85, 2.5, 0.7, fmt("craft_%s", name), ES("Craft (×@1)", stack_fs))
@ -1359,7 +1365,7 @@ local function hide_items(player, data)
data.items = new data.items = new
end end
if not core.is_creative_enabled(data.player_name) then if not core.is_creative_enabled(data.player_name) and not next(i3.recipe_filters) then
local new = {} local new = {}
for i = 1, #data.items do for i = 1, #data.items do
@ -1380,17 +1386,17 @@ local function get_header_items_fs(fs, data)
fs"set_focus[filter;true]" fs"set_focus[filter;true]"
if data.hide_tabs then if data.hide_tabs then
fs(fmt("style[enable_search;bgimg=%s;bgimg_hovered=%s;bgimg_pressed=%s]", fs("style[enable_search;bgimg=%s;bgimg_hovered=%s;bgimg_pressed=%s]",
data.enable_search and PNG.search_hover or PNG.search, PNG.search_hover, PNG.search_hover)) data.enable_search and PNG.search_hover or PNG.search, PNG.search_hover, PNG.search_hover)
image_button(X + 0.3, 0.2, 0.5, 0.5, "", "enable_search", "") image_button(X + 0.3, 0.2, 0.5, 0.5, "", "enable_search", "")
fs(fmt("tooltip[enable_search;%s]", ES"Search")) fs("tooltip[enable_search;%s]", ES"Search")
if data.enable_search then if data.enable_search then
image(X + 0.4, 0.75, 3.4, 0.8, PNG.bg_goto) image(X + 0.4, 0.75, 3.4, 0.8, PNG.bg_goto)
fs("style[filter;font_size=16]", fs"style[filter;font_size=16]"
fmt("field[%f,%f;3,0.45;filter;;%s]", X + 0.6, 0.95, data.filter), fs("field[%f,%f;3,0.45;filter;;%s]", X + 0.6, 0.95, data.filter)
"field_close_on_enter[filter;false]") fs"field_close_on_enter[filter;false]"
end end
box(X + 1, 0.2, 0.01, 0.5, "#bababa50") box(X + 1, 0.2, 0.01, 0.5, "#bababa50")
@ -1400,20 +1406,20 @@ local function get_header_items_fs(fs, data)
local name, desc = unpack(cat[i]) local name, desc = unpack(cat[i])
local active = PNG[name .. "_hover"] local active = PNG[name .. "_hover"]
fs(fmt("style[itab_%u;bgimg=%s;bgimg_hovered=%s;bgimg_pressed=%s;sound=i3_tab]", fs("style[itab_%u;bgimg=%s;bgimg_hovered=%s;bgimg_pressed=%s;sound=i3_tab]",
i, data.itab == i and active or PNG[name], active, active)) i, data.itab == i and active or PNG[name], active, active)
image_button(X + 1.25 + ((i - 1) * 0.7), 0.2, 0.5, 0.5, "", fmt("itab_%s", i), "") image_button(X + 1.25 + ((i - 1) * 0.7), 0.2, 0.5, 0.5, "", fmt("itab_%s", i), "")
fs(fmt("tooltip[itab_%u;Show %s]", i, desc)) fs("tooltip[itab_%u;Show %s]", i, desc)
end end
else else
fs(fmt("style[search;bgimg=%s]", PNG.search_hover)) fs("style[search;bgimg=%s]", PNG.search_hover)
image_button(X + 0.35, 0.32, 0.35, 0.35, "", "search", "") image_button(X + 0.35, 0.32, 0.35, 0.35, "", "search", "")
fs(fmt("tooltip[search;%s]", ES"Search")) fs("tooltip[search;%s]", ES"Search")
if data.enable_search then if data.enable_search then
fs("style[filter;font_size=18]", fs"style[filter;font_size=18]"
fmt("field[%f,0.2;3.35,0.6;filter;;%s]", X + 0.85, ESC(data.filter)), fs("field[%f,0.2;3.35,0.6;filter;;%s]", X + 0.85, ESC(data.filter))
"field_close_on_enter[filter;false]") fs"field_close_on_enter[filter;false]"
if not true_str(data.filter) then if not true_str(data.filter) then
image(X + 0.85, 0.75, 4, 0.01, PNG.search_outline_trim .. "^[opacity:100") image(X + 0.85, 0.75, 4, 0.01, PNG.search_outline_trim .. "^[opacity:100")
@ -1427,7 +1433,7 @@ local function get_header_items_fs(fs, data)
if true_str(data.filter) then if true_str(data.filter) then
image_button(X + 4.3, 0.4, 0.2, 0.2, "", "cancel", "") image_button(X + 4.3, 0.4, 0.2, 0.2, "", "cancel", "")
fs(fmt("tooltip[cancel;%s]", ES"Clear")) fs("tooltip[cancel;%s]", ES"Clear")
box(X + 0.85, 0.75, 3.74, 0.01, "#f9826c") box(X + 0.85, 0.75, 3.74, 0.01, "#f9826c")
end end
end end
@ -1435,8 +1441,8 @@ local function get_header_items_fs(fs, data)
image_button(X + 5.27, 0.3, 0.35, 0.35, "", "prev_page", "") image_button(X + 5.27, 0.3, 0.35, 0.35, "", "prev_page", "")
image_button(X + 7.45, 0.3, 0.35, 0.35, "", "next_page", "") image_button(X + 7.45, 0.3, 0.35, 0.35, "", "next_page", "")
fs(fmt("style[pagenum;bgimg=%s;bgimg_hovered=%s;bgimg_middle=9;padding=-9;sound=i3_click]", fs("style[pagenum;bgimg=%s;bgimg_hovered=%s;bgimg_middle=9;padding=-9;sound=i3_click]",
data.goto_page and PNG.pagenum_hover or "", PNG.pagenum_hover)) data.goto_page and PNG.pagenum_hover or "", PNG.pagenum_hover)
button(X + 5.8, 0.14, 1.48, 0.7, "pagenum", button(X + 5.8, 0.14, 1.48, 0.7, "pagenum",
fmt("%s / %u", clr(colors.yellow, data.pagenum), data.pagemax)) fmt("%s / %u", clr(colors.yellow, data.pagenum), data.pagemax))
@ -1447,9 +1453,9 @@ local function get_header_items_fs(fs, data)
label(X + 5, 1.25, ES"Go to page" .. ":") label(X + 5, 1.25, ES"Go to page" .. ":")
box(X + 6.5, 1, 1, 0.45, "#bababa10") box(X + 6.5, 1, 1, 0.45, "#bababa10")
fs(fmt("style[goto_page;font=mono,bold;font_size=16;textcolor=%s]", colors.yellow), fs("style[goto_page;font=mono,bold;font_size=16;textcolor=%s]", colors.yellow)
fmt("field[%f,%f;1,0.45;goto_page;;%s]", X + 6.55, 1.05, data.pagenum), fs("field[%f,%f;1,0.45;goto_page;;%s]", X + 6.55, 1.05, data.pagenum)
"field_close_on_enter[goto_page;false]") fs"field_close_on_enter[goto_page;false]"
fs"style_type[label;font_size=16;textcolor=#fff]" fs"style_type[label;font_size=16;textcolor=#fff]"
end end
@ -1463,11 +1469,11 @@ local function get_minitabs(fs, data, full_height)
local selected = i == data.itab local selected = i == data.itab
local hover_texture = selected and PNG.tab_small_hover or PNG.tab_small local hover_texture = selected and PNG.tab_small_hover or PNG.tab_small
fs(fmt([[style_type[image_button;bgimg=%s;bgimg_hovered=%s; fs([[ style_type[image_button;bgimg=%s;bgimg_hovered=%s;
bgimg_middle=14,0,-14,-14;padding=-14,0,14,14] ]], hover_texture, PNG.tab_small_hover)) bgimg_middle=14,0,-14,-14;padding=-14,0,14,14] ]], hover_texture, PNG.tab_small_hover)
fs(fmt([[style_type[image_button;noclip=true;font=bold;font_size=16; fs([[ style_type[image_button;noclip=true;font=bold;font_size=16;
textcolor=%s;content_offset=0;sound=i3_tab] ]], selected and "#fff" or "#bbb")) textcolor=%s;content_offset=0;sound=i3_tab] ]], selected and "#fff" or "#bbb")
fs"style_type[image_button:hovered;textcolor=#fff]" fs"style_type[image_button:hovered;textcolor=#fff]"
image_button((data.inv_width - 0.65) + (i * (tab_len + 0.1)), image_button((data.inv_width - 0.65) + (i * (tab_len + 0.1)),
full_height, tab_len, tab_hgh, "", fmt("itab_%u", i), title) full_height, tab_len, tab_hgh, "", fmt("itab_%u", i), title)
@ -1485,6 +1491,10 @@ local function get_items_fs(fs, data, player, full_height)
data.pagemax = max(1, ceil(#items / ipp)) data.pagemax = max(1, ceil(#items / ipp))
if data.pagenum > data.pagemax then
data.pagenum = data.pagemax
end
if #items == 0 then if #items == 0 then
local lbl = ES"No item to show" local lbl = ES"No item to show"
local icon, width, offset = PNG.no_result, 4, 2 local icon, width, offset = PNG.no_result, 4, 2
@ -1512,12 +1522,29 @@ local function get_items_fs(fs, data, player, full_height)
local Y = round((i % ipp - X) / rows + 1, 0) local Y = round((i % ipp - X) / rows + 1, 0)
Y -= (Y * 0.085) + 0.92 Y -= (Y * 0.085) + 0.92
insert(fs, fmt("item_image_button", X, Y, size, size, name, item, "")) local item_btn = fmt("item_image_button", X, Y, size, size, name, item, "")
if next(i3.recipe_filters) then
if data.items_progress[item] then
insert(fs, item_btn)
else
local col = "^\\[colorize:#232428^\\[opacity:245"
local img = reg_items[item].inventory_image .. col
if reg_nodes[item] then
img = PNG.cube .. col
end
insert(fs, fmt("image", X, Y, size, size, img))
end
else
insert(fs, item_btn)
end
if compressible(item, data) then if compressible(item, data) then
local expand = data.expand == name local expand = data.expand == name
fs(fmt("tooltip[%s;%s]", item, expand and ES"Click to hide" or ES"Click to expand")) fs("tooltip[%s;%s]", item, expand and ES"Click to hide" or ES"Click to expand")
fs"style_type[label;font=bold;font_size=20]" fs"style_type[label;font=bold;font_size=20]"
label(X + 0.65, Y + 0.7, expand and "-" or "+") label(X + 0.65, Y + 0.7, expand and "-" or "+")
fs"style_type[label;font=normal;font_size=16]" fs"style_type[label;font=normal;font_size=16]"
@ -1597,11 +1624,11 @@ local function get_tabs_fs(fs, player, data, full_height)
local middle = btm and "16,0,-16,-16" or "16,16,-16,-16" local middle = btm and "16,0,-16,-16" or "16,16,-16,-16"
local padding = btm and "-16,0,16,16" or "-16,-16,16,16" local padding = btm and "-16,0,16,16" or "-16,-16,16,16"
fs(fmt([[style_type[image_button;bgimg=%s;bgimg_hovered=%s;bgimg_middle=%s;padding=%s] ]], fs([[ style_type[image_button;bgimg=%s;bgimg_hovered=%s;bgimg_middle=%s;padding=%s] ]],
bgimg, bgimg_hover, middle, padding)) bgimg, bgimg_hover, middle, padding)
fs(fmt("style_type[image_button;noclip=true;font_size=16;textcolor=%s;content_offset=0;sound=i3_tab]", fs("style_type[image_button;noclip=true;font_size=16;textcolor=%s;content_offset=0;sound=i3_tab]",
selected and "#fff" or "#ddd")) selected and "#fff" or "#ddd")
local X = (data.inv_width / 2) + (c * (tab_len + 0.1)) - ((tab_len + 0.05) * (shift / 2)) local X = (data.inv_width / 2) + (c * (tab_len + 0.1)) - ((tab_len + 0.05) * (shift / 2))
local Y = btm and full_height or -tab_hgh local Y = btm and full_height or -tab_hgh
@ -1654,10 +1681,11 @@ local function make_fs(player, data)
local fs = setmetatable({}, { local fs = setmetatable({}, {
__call = function(t, ...) __call = function(t, ...)
local args = {...} local args = {...}
local elem = fs_elements[args[1]]
if elem then if #args > 1 then
insert(t, fmt(elem, select(2, ...))) local arg1 = args[1]
local elem = fs_elements[arg1]
insert(t, fmt(elem or arg1, select(2, ...)))
else else
insert(t, concat(args)) insert(t, concat(args))
end end
@ -1667,8 +1695,10 @@ local function make_fs(player, data)
data.inv_width = 10.23 data.inv_width = 10.23
local full_height = 12 local full_height = 12
fs(fmt("formspec_version[%u]size[%f,%f]no_prepend[]bgcolor[#0000]", fs("formspec_version[%u]size[%f,%f]no_prepend[]bgcolor[#0000]",
i3.settings.min_fs_version, data.inv_width + 8, full_height), styles) i3.settings.min_fs_version, data.inv_width + 8, full_height)
fs(styles)
bg9(0, 0, data.inv_width, full_height, PNG.bg_full) bg9(0, 0, data.inv_width, full_height, PNG.bg_full)

View File

@ -4,6 +4,14 @@ local function init_hud(player)
local name = player:get_player_name() local name = player:get_player_name()
local data = i3.data[name] local data = i3.data[name]
local wdesc_y = -90
if core.global_exists"hb" then
wdesc_y -= ceil(hb.hudbars_count / 2) * 5
elseif not i3.settings.damage_enabled then
wdesc_y += 15
end
data.hud = { data.hud = {
bg = player:hud_add { bg = player:hud_add {
hud_elem_type = "image", hud_elem_type = "image",
@ -18,7 +26,7 @@ local function init_hud(player)
hud_elem_type = "image", hud_elem_type = "image",
position = {x = 0.79, y = 1.02}, position = {x = 0.79, y = 1.02},
alignment = {x = 1, y = 1}, alignment = {x = 1, y = 1},
scale = {x = 4, y = 4}, scale = {x = 1, y = 1},
text = "", text = "",
z_index = 0xDEAD, z_index = 0xDEAD,
}, },
@ -36,7 +44,7 @@ local function init_hud(player)
wielditem = player:hud_add { wielditem = player:hud_add {
hud_elem_type = "text", hud_elem_type = "text",
position = {x = 0.5, y = 1}, position = {x = 0.5, y = 1},
offset = {x = 0, y = -65 - (i3.modules.hudbars and (ceil(hb.hudbars_count / 2) * 25) or 25)}, offset = {x = 0, y = wdesc_y},
alignment = {x = 0, y = -1}, alignment = {x = 0, y = -1},
number = 0xffffff, number = 0xffffff,
text = "", text = "",
@ -51,7 +59,7 @@ local function show_hud(player, data)
-- 2 calls for the notification's back and forth. -- 2 calls for the notification's back and forth.
local hud_info_bg = player:hud_get(data.hud.bg) local hud_info_bg = player:hud_get(data.hud.bg)
local dt = 0.016 local dt = 0.025
if hud_info_bg.position.y <= 0.9 then if hud_info_bg.position.y <= 0.9 then
data.show_hud = false data.show_hud = false
@ -105,36 +113,32 @@ core.register_globalstep(function(dt)
local data = i3.data[name] local data = i3.data[name]
if not data then return end if not data then return end
local function reset()
player:hud_change(data.hud.wielditem, "text", "")
data.timer = 0
end
if not data.wielditem_hud then if not data.wielditem_hud then
return reset() player:hud_change(data.hud.wielditem, "text", "")
return
end end
data.timer = (data.timer or 0) + dt data.timer = (data.timer or 0) + dt
local wieldidx = player:get_wield_index()
local wielditem = player:get_wielded_item() if wieldidx == data.old_wieldidx then
local wieldname = wielditem:get_name()
if wieldname == data.old_wielditem then
if data.timer >= i3.settings.wielditem_fade_after then if data.timer >= i3.settings.wielditem_fade_after then
return reset() player:hud_change(data.hud.wielditem, "text", "")
end end
return return
end end
data.old_wielditem = wieldname data.timer = 0
data.old_wieldidx = wieldidx
local wielditem = player:get_wielded_item()
local meta = wielditem:get_meta() local meta = wielditem:get_meta()
local meta_desc = meta:get_string"short_description" local meta_desc = meta:get_string"short_description"
meta_desc = meta_desc:gsub("\27", "") meta_desc = meta_desc:gsub("\27", "")
meta_desc = core.strip_colors(meta_desc) meta_desc = core.strip_colors(meta_desc)
local desc = meta_desc ~= "" and meta_desc or wielditem:get_short_description() local desc = meta_desc ~= "" and meta_desc or wielditem:get_short_description()
player:hud_change(data.hud.wielditem, "text", desc:trim()) player:hud_change(data.hud.wielditem, "text", desc:trim())
end end
end) end)

View File

@ -81,6 +81,10 @@ local function _load(path, line, data, t)
if not l then if not l then
local err_line = tonumber(err:match(":(%d+):")) local err_line = tonumber(err:match(":(%d+):"))
if t then
print("err_line", err_line, t[err_line])
end
if line ~= err_line then if line ~= err_line then
return _load(path, err_line, data, t) return _load(path, err_line, data, t)
end end

View File

@ -2,11 +2,12 @@ local set_fs = i3.set_fs
local hud_notif = i3.hud_notif local hud_notif = i3.hud_notif
local POLL_FREQ = 0.25 local POLL_FREQ = 0.25
IMPORT("reg_items", "reg_nodes")
IMPORT("fmt", "search", "table_merge", "array_diff") IMPORT("fmt", "search", "table_merge", "array_diff")
IMPORT("is_group", "extract_groups", "item_has_groups", "apply_recipe_filters") IMPORT("is_group", "extract_groups", "item_has_groups", "apply_recipe_filters")
local function get_filtered_items(player, data) local function get_filtered_items(player, data)
local items, known, c = {}, 0, 0 local items, known = {}, 0
for i = 1, #i3.init_items do for i = 1, #i3.init_items do
local item = i3.init_items[i] local item = i3.init_items[i]
@ -17,8 +18,7 @@ local function get_filtered_items(player, data)
usages = #apply_recipe_filters(usages or {}, player) usages = #apply_recipe_filters(usages or {}, player)
if recipes > 0 or usages > 0 then if recipes > 0 or usages > 0 then
c++ items[item] = true
items[c] = item
known += recipes + usages known += recipes + usages
end end
end end
@ -133,10 +133,18 @@ local function poll_new_items(player, data, join)
if data.discovered > 0 then if data.discovered > 0 then
local msg = fmt("%u new recipe%s unlocked!", data.discovered, data.discovered > 1 and "s" or "") local msg = fmt("%u new recipe%s unlocked!", data.discovered, data.discovered > 1 and "s" or "")
hud_notif(data.player_name, msg, "i3_book.png") local last_discovered = diff[1]
local img = reg_items[last_discovered].inventory_image
if reg_nodes[last_discovered] then
local id = core.get_content_id(last_discovered)
img = i3.cubes[id] or img
end
hud_notif(data.player_name, msg, img)
end end
data.items_raw = items data.items_progress = items
data.itab = 1 data.itab = 1
search(data) search(data)

View File

@ -12,7 +12,6 @@ local PNG = {
search = "i3_search.png", search = "i3_search.png",
heart = "i3_heart.png", heart = "i3_heart.png",
heart_half = "i3_heart_half.png", heart_half = "i3_heart_half.png",
heart_grey = "i3_heart_grey.png",
prev = "i3_next.png^\\[transformFX", prev = "i3_next.png^\\[transformFX",
next = "i3_next.png", next = "i3_next.png",
arrow = "i3_arrow.png", arrow = "i3_arrow.png",
@ -54,6 +53,7 @@ local PNG = {
all = "i3_all.png", all = "i3_all.png",
node = "i3_node.png", node = "i3_node.png",
item = "i3_item.png", item = "i3_item.png",
cube = "i3_cube.png",
cancel_hover = "i3_cancel.png^\\[brighten", cancel_hover = "i3_cancel.png^\\[brighten",
search_hover = "i3_search.png^\\[brighten", search_hover = "i3_search.png^\\[brighten",
@ -95,7 +95,6 @@ local styles = string.format([[
style[search;content_offset=0] style[search;content_offset=0]
style[pagenum,no_item,no_rcp;font=bold;font_size=18] style[pagenum,no_item,no_rcp;font=bold;font_size=18]
style[enable_search:hovered;bgimg=%s] style[enable_search:hovered;bgimg=%s]
style[enable_search:pressed;bgimg=%s^[opacity:178]
style[exit;fgimg=%s;fgimg_hovered=%s;content_offset=0] style[exit;fgimg=%s;fgimg_hovered=%s;content_offset=0]
style[cancel;fgimg=%s;fgimg_hovered=%s;content_offset=0] style[cancel;fgimg=%s;fgimg_hovered=%s;content_offset=0]
style[prev_page,prev_recipe,prev_usage,prev_sort,prev_skin;fgimg=%s;fgimg_hovered=%s] style[prev_page,prev_recipe,prev_usage,prev_sort,prev_skin;fgimg=%s;fgimg_hovered=%s]
@ -112,7 +111,7 @@ local styles = string.format([[
style[confirm_trash_yes;sound=i3_trash] style[confirm_trash_yes;sound=i3_trash]
]], ]],
PNG.slot, PNG.slot,
PNG.search_outline, PNG.search_outline, PNG.search_outline,
PNG.exit, PNG.exit_hover, PNG.exit, PNG.exit_hover,
PNG.cancel, PNG.cancel_hover, PNG.cancel, PNG.cancel_hover,
PNG.prev, PNG.prev_hover, PNG.prev, PNG.prev_hover,

View File

@ -11,32 +11,39 @@ mt3:get_meta():set_string("description", "Worn Pick")
mt3:get_meta():set_string("color", "yellow") mt3:get_meta():set_string("color", "yellow")
mt3:set_wear(10000) mt3:set_wear(10000)
minetest.register_craft({ minetest.register_craft {
output = mt:to_string(), output = mt:to_string(),
type = "shapeless", type = "shapeless",
recipe = { recipe = {
"default:wood", "default:wood",
mt2:to_string(), mt2:to_string(),
}, },
}) }
minetest.register_craft({ minetest.register_craft {
output = mt3:to_string(), output = mt3:to_string(),
type = "shapeless", type = "shapeless",
recipe = { recipe = {
"default:pick_mese", "default:pick_mese",
"default:diamond", "default:diamond",
}, },
}) }
minetest.clear_craft {
recipe = {
{"default:sand", "default:sand"},
{"default:sand", "default:sand"},
},
}
i3.register_craft { i3.register_craft {
url = "https://raw.githubusercontent.com/minetest-mods/i3/main/tests/test_online_recipe.json" url = "https://raw.githubusercontent.com/minetest-mods/i3/main/tests/test_online_recipe.json"
} }
i3.register_craft({ i3.register_craft {
result = "default:ladder_wood 2", result = "default:ladder_wood 2",
items = {"default:copper_ingot 7, default:tin_ingot, default:steel_ingot 2"}, items = {"default:copper_ingot 7, default:tin_ingot, default:steel_ingot 2"},
}) }
i3.register_craft { i3.register_craft {
result = "default:tree", result = "default:tree",
@ -56,7 +63,7 @@ i3.register_craft {
} }
} }
i3.register_craft({ i3.register_craft {
grid = { grid = {
"X", "X",
"#", "#",
@ -68,9 +75,9 @@ i3.register_craft({
['X'] = "default:glass 2", ['X'] = "default:glass 2",
}, },
result = "default:mese 3", result = "default:mese 3",
}) }
i3.register_craft({ i3.register_craft {
grid = { grid = {
"X", "X",
"#X", "#X",
@ -82,9 +89,9 @@ i3.register_craft({
['X'] = "default:glass 2", ['X'] = "default:glass 2",
}, },
result = "default:mese 3", result = "default:mese 3",
}) }
i3.register_craft({ i3.register_craft {
grid = { grid = {
"X", "X",
}, },
@ -93,10 +100,10 @@ i3.register_craft({
['X'] = "default:glass 2", ['X'] = "default:glass 2",
}, },
result = "default:mese 3", result = "default:mese 3",
}) }
i3.register_craft({ i3.register_craft {
grid = { grid = {
"X#", "X#",
}, },
@ -105,9 +112,9 @@ i3.register_craft({
['X'] = "default:glass 2", ['X'] = "default:glass 2",
}, },
result = "default:mese 3", result = "default:mese 3",
}) }
i3.register_craft({ i3.register_craft {
grid = { grid = {
"X#X", "X#X",
}, },
@ -116,9 +123,9 @@ i3.register_craft({
['X'] = "default:glass 2", ['X'] = "default:glass 2",
}, },
result = "default:mese 3", result = "default:mese 3",
}) }
i3.register_craft({ i3.register_craft {
grid = { grid = {
"X#XX", "X#XX",
}, },
@ -127,9 +134,9 @@ i3.register_craft({
['X'] = "default:glass 2", ['X'] = "default:glass 2",
}, },
result = "default:mese 3", result = "default:mese 3",
}) }
i3.register_craft({ i3.register_craft {
grid = { grid = {
"X#XX", "X#XX",
"X#X", "X#X",
@ -139,9 +146,9 @@ i3.register_craft({
['X'] = "default:glass 2", ['X'] = "default:glass 2",
}, },
result = "default:mese 3", result = "default:mese 3",
}) }
i3.register_craft({ i3.register_craft {
grid = { grid = {
"X#XX", "X#XX",
"X#X", "X#X",
@ -152,9 +159,9 @@ i3.register_craft({
['X'] = "default:glass 2", ['X'] = "default:glass 2",
}, },
result = "default:mese 3", result = "default:mese 3",
}) }
i3.register_craft({ i3.register_craft {
grid = { grid = {
"X##XX", "X##XX",
}, },
@ -163,9 +170,9 @@ i3.register_craft({
['X'] = "default:glass 2", ['X'] = "default:glass 2",
}, },
result = "default:mese 3", result = "default:mese 3",
}) }
i3.register_craft({ i3.register_craft {
grid = { grid = {
"X##X#X", "X##X#X",
}, },
@ -174,9 +181,9 @@ i3.register_craft({
['X'] = "default:glass 2", ['X'] = "default:glass 2",
}, },
result = "default:mese 3", result = "default:mese 3",
}) }
i3.register_craft({ i3.register_craft {
grid = { grid = {
"X##X#X", "X##X#X",
"", "",
@ -187,9 +194,9 @@ i3.register_craft({
['X'] = "default:glass 2", ['X'] = "default:glass 2",
}, },
result = "default:mese 3", result = "default:mese 3",
}) }
i3.register_craft({ i3.register_craft {
grid = { grid = {
"X #", "X #",
" ## ", " ## ",
@ -201,9 +208,9 @@ i3.register_craft({
['X'] = "default:glass 2", ['X'] = "default:glass 2",
}, },
result = "default:mese 3", result = "default:mese 3",
}) }
i3.register_craft({ i3.register_craft {
grid = { grid = {
"X #", "X #",
" ## ", " ## ",
@ -215,9 +222,9 @@ i3.register_craft({
['X'] = "default:glass", ['X'] = "default:glass",
}, },
result = "default:mese 3", result = "default:mese 3",
}) }
i3.register_craft({ i3.register_craft {
grid = { grid = {
"X #", "X #",
" ## ", " ## ",
@ -230,9 +237,9 @@ i3.register_craft({
['X'] = "default:glass", ['X'] = "default:glass",
}, },
result = "default:mese 3", result = "default:mese 3",
}) }
i3.register_craft({ i3.register_craft {
grid = { grid = {
"X #", "X #",
" ## ", " ## ",
@ -245,10 +252,10 @@ i3.register_craft({
['X'] = "default:glass", ['X'] = "default:glass",
}, },
result = "default:mese 3", result = "default:mese 3",
}) }
i3.register_craft({ i3.register_craft {
grid = { grid = {
"X #", "X #",
" ## ", " ## ",
@ -262,9 +269,9 @@ i3.register_craft({
['X'] = "default:glass", ['X'] = "default:glass",
}, },
result = "default:mese 3", result = "default:mese 3",
}) }
i3.register_craft({ i3.register_craft {
grid = { grid = {
"X #", "X #",
" ## ", " ## ",
@ -278,9 +285,9 @@ i3.register_craft({
['X'] = "default:glass", ['X'] = "default:glass",
}, },
result = "default:mese 3", result = "default:mese 3",
}) }
i3.register_craft({ i3.register_craft {
grid = { grid = {
"X #", "X #",
" ## ", " ## ",
@ -294,9 +301,9 @@ i3.register_craft({
['X'] = "default:glass", ['X'] = "default:glass",
}, },
result = "default:mese 3", result = "default:mese 3",
}) }
i3.register_craft({ i3.register_craft {
grid = { grid = {
"X #", "X #",
" ## ", " ## ",
@ -310,9 +317,9 @@ i3.register_craft({
['X'] = "default:glass", ['X'] = "default:glass",
}, },
result = "default:mese 3", result = "default:mese 3",
}) }
i3.register_craft({ i3.register_craft {
grid = { grid = {
"X #", "X #",
" ## ", " ## ",
@ -328,4 +335,4 @@ i3.register_craft({
['X'] = "default:glass", ['X'] = "default:glass",
}, },
result = "default:mese 3", result = "default:mese 3",
}) }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 B

BIN
textures/i3_cube.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 B