Compare commits

...

30 Commits
1.6.2 ... 1.7.2

Author SHA1 Message Date
3f2d983091 Minor tweak 2022-07-01 03:46:25 +02:00
6dd95a6a87 Remove the bullshit and fix the sprite once and for all 2022-07-01 03:36:16 +02:00
32779ab56f Add comments 2022-07-01 03:10:37 +02:00
4ccff6621b Minor tweak 2022-07-01 02:43:05 +02:00
7d0f25e8b2 Minor tweak 2022-07-01 00:47:43 +02:00
652c486249 Tweak textures 2022-06-30 16:31:43 +02:00
9ab47fc0f0 Improve UTF-8 string length counting 2022-06-30 15:18:32 +02:00
c635343c9b Add a 404 image when no item found 2022-06-30 03:10:24 +02:00
662c938afb Minor UI improvement 2022-06-30 02:32:03 +02:00
b2c8447971 Some UI improvements + fix bug with custom tabs 2022-06-30 01:15:35 +02:00
c91f787cb2 Correct condition 2022-06-28 01:24:36 +02:00
dcc4068e46 Fix potential crash during sprite creation 2022-06-28 01:03:41 +02:00
c421c49916 Fix bug with group stereotype 2022-06-23 18:23:03 +02:00
3dfcd95c6f Tweak preprocessor to add -- decrement 2022-06-23 15:04:39 +02:00
72d4a5d4b8 Minor cleaning 2022-06-23 14:14:54 +02:00
f2b4c960ad Fix bug with favs 2022-06-23 02:30:54 +02:00
5d6ce3be18 Improve preprocessor a bit 2022-06-23 01:14:45 +02:00
5f413a150b Minor improvement 2022-06-19 15:23:50 +02:00
563dc719d0 Put a upper limit for sprite creation 2022-06-19 14:47:52 +02:00
56cb236025 Fix again 2022-06-19 03:33:21 +02:00
8525633d4c Improve groups caching 2022-06-19 02:54:11 +02:00
cb1dce66f9 Some last fix 2022-06-19 00:36:57 +02:00
2db1e885fc Minor cleanup 2022-06-18 23:40:22 +02:00
354561d54c Finish animation for group buttons (yay) 2022-06-18 23:20:57 +02:00
8e45f303d3 Some fix to previous commit 2022-06-18 22:32:51 +02:00
a6605263f4 Animated image buttons for groups (needs polish) 2022-06-18 21:52:08 +02:00
e17e1080d3 Remove some unessecerary [resize 2022-06-18 19:59:34 +02:00
f0f94017da Cache groups (testing needed) 2022-06-18 19:53:47 +02:00
cf5f18e1c1 Register creative priv in case MTG is not installed 2022-06-17 03:12:55 +02:00
4736b551a8 Fix crash in progressive mode 2022-06-09 12:33:56 +02:00
13 changed files with 801 additions and 654 deletions

View File

@ -13,7 +13,7 @@ print[[
local modpath = core.get_modpath"i3" local modpath = core.get_modpath"i3"
local http = core.request_http_api() local http = core.request_http_api()
local storage = core.get_mod_storage() local storage = core.get_mod_storage()
local _loadfile = dofile(modpath .. "/src/operators.lua") local _loadfile = dofile(modpath .. "/src/preprocessor.lua")
local function lf(path) local function lf(path)
return assert(_loadfile(modpath .. path)) return assert(_loadfile(modpath .. path))
@ -63,7 +63,7 @@ i3 = {
caches = lf"/src/caches.lua", caches = lf"/src/caches.lua",
callbacks = lf"/src/callbacks.lua", callbacks = lf"/src/callbacks.lua",
common = lf"/src/common.lua", common = lf"/src/common.lua",
compress = lf"/src/compress.lua", compress = lf"/src/compression.lua",
detached = lf"/src/detached_inv.lua", detached = lf"/src/detached_inv.lua",
fields = lf"/src/fields.lua", fields = lf"/src/fields.lua",
groups = lf"/src/groups.lua", groups = lf"/src/groups.lua",
@ -82,6 +82,7 @@ i3 = {
tabs = {}, tabs = {},
cubes = {}, cubes = {},
groups = {},
plants = {}, plants = {},
modules = {}, modules = {},
craft_types = {}, craft_types = {},

View File

@ -1,11 +1,10 @@
local PNG = i3.files.styles()
local replacements = {fuel = {}} local replacements = {fuel = {}}
local http = ... local http = ...
IMPORT("maxn", "copy", "insert", "sort", "match", "sub") IMPORT("maxn", "copy", "insert", "sort", "match", "sub")
IMPORT("is_group", "extract_groups", "item_has_groups", "groups_to_items") IMPORT("true_str", "is_table", "valid_item", "table_merge", "table_replace", "rcp_eq")
IMPORT("fmt", "reg_items", "reg_aliases", "reg_nodes", "draw_cube", "ItemStack") IMPORT("fmt", "reg_items", "reg_aliases", "reg_nodes", "is_cube", "get_cube", "ItemStack")
IMPORT("true_str", "true_table", "is_table", "valid_item", "table_merge", "table_replace", "rcp_eq") IMPORT("is_group", "extract_groups", "item_has_groups", "groups_to_items", "get_group_stereotype")
local function get_burntime(item) local function get_burntime(item)
return core.get_craft_result{method = "fuel", items = {item}}.time return core.get_craft_result{method = "fuel", items = {item}}.time
@ -23,10 +22,56 @@ local function cache_fuel(item)
end end
end end
local function get_item_usages(item, recipe, added) local function cache_groups(group, groups)
local groups = extract_groups(item) i3.groups[group] = {}
i3.groups[group].groups = groups
i3.groups[group].items = groups_to_items(groups)
if #groups == 1 then
i3.groups[group].stereotype = get_group_stereotype(groups[1])
end
local items = i3.groups[group].items
if #items <= 1 then return end
local px, lim, c = 64, 10, 0
local sprite = "[combine:WxH"
for _, item in ipairs(items) do
local def = reg_items[item]
local tiles = def.tiles or def.tile_images
local texture = true_str(def.inventory_image) and def.inventory_image --or tiles[1]
if def.drawtype and is_cube(def.drawtype) then
texture = get_cube(tiles)
end
if texture then
texture = texture:gsub("%^", "\\^"):gsub(":", "\\:") .. fmt("\\^[resize\\:%ux%u", px, px)
sprite = sprite .. fmt(":0,%u=%s", c * px, texture)
c++
if c == lim then break end
end
end
if c > 1 then
sprite = sprite:gsub("WxH", px .. "x" .. px * c)
i3.groups[group].sprite = sprite
i3.groups[group].count = c
end
end
local function get_item_usages(item, recipe, added)
if is_group(item) then
local group = item:sub(7)
local group_cache = i3.groups[group]
local groups = group_cache and group_cache.groups or extract_groups(item)
if not group_cache then
cache_groups(group, groups)
end
if groups then
for name, def in pairs(reg_items) do for name, def in pairs(reg_items) do
if not added[name] and valid_item(def) and item_has_groups(def.groups, groups) then if not added[name] and valid_item(def) and item_has_groups(def.groups, groups) then
local usage = copy(recipe) local usage = copy(recipe)
@ -181,7 +226,7 @@ core.register_craft = function(def)
if is_group(output[1]) then if is_group(output[1]) then
groups = extract_groups(output[1]) groups = extract_groups(output[1])
output = groups_to_items(groups, true) output = groups_to_items(groups)
end end
for i = 1, #output do for i = 1, #output do
@ -284,40 +329,20 @@ local function init_recipes()
end end
end end
local function get_cube(tiles)
if not true_table(tiles) then
return PNG.blank
end
local top = tiles[1] or PNG.blank
if is_table(top) then
top = top.name or top.image
end
local left = tiles[3] or top or PNG.blank
if is_table(left) then
left = left.name or left.image
end
local right = tiles[5] or left or PNG.blank
if is_table(right) then
right = right.name or right.image
end
return draw_cube(top, left, right)
end
local function init_cubes() local function init_cubes()
for name, def in pairs(reg_nodes) do for name, def in pairs(reg_nodes) do
if def then if def then
local id = core.get_content_id(name) local id = core.get_content_id(name)
local tiles = def.tiles or def.tile_images
if def.drawtype == "normal" or def.drawtype == "liquid" or if is_cube(def.drawtype) then
sub(def.drawtype, 1, 9) == "glasslike" or i3.cubes[id] = get_cube(tiles)
sub(def.drawtype, 1, 8) == "allfaces" then
i3.cubes[id] = get_cube(def.tiles)
elseif sub(def.drawtype, 1, 9) == "plantlike" or sub(def.drawtype, 1, 8) == "firelike" then elseif sub(def.drawtype, 1, 9) == "plantlike" or sub(def.drawtype, 1, 8) == "firelike" then
i3.plants[id] = def.inventory_image .. "^\\[resize:16x16" local texture = true_str(def.inventory_image) and def.inventory_image or tiles[1]
if texture then
i3.plants[id] = texture
end
end end
end end
end end

View File

@ -9,6 +9,14 @@ local fmt, find, match, gmatch, sub, split, lower, upper =
string.format, string.find, string.match, string.gmatch, string.format, string.find, string.match, string.gmatch,
string.sub, string.split, string.lower, string.upper string.sub, string.split, string.lower, string.upper
if not core.registered_privileges.creative then
core.register_privilege("creative", {
description = "Allow player to use creative inventory",
give_to_singleplayer = false,
give_to_admin = false,
})
end
local old_is_creative_enabled = core.is_creative_enabled local old_is_creative_enabled = core.is_creative_enabled
function core.is_creative_enabled(name) function core.is_creative_enabled(name)
@ -69,6 +77,16 @@ local function toupper(str)
return str:gsub("%f[%w]%l", upper):gsub("_", " ") return str:gsub("%f[%w]%l", upper):gsub("_", " ")
end end
local function utf8_len(str)
local c = 0
for _ in str:gmatch"([%z\1-\127\194-\244][\128-\191]*)" do -- Arguably working duct-tape code
c++
end
return c
end
local function get_bag_description(data, stack) local function get_bag_description(data, stack)
local desc = translate(data.lang_code, stack:get_description()) local desc = translate(data.lang_code, stack:get_description())
desc = split(desc, "(")[1] or desc desc = split(desc, "(")[1] or desc
@ -228,9 +246,7 @@ local function is_group(item)
end end
local function extract_groups(str) local function extract_groups(str)
if sub(str, 1, 6) == "group:" then return split(sub(str, 7), ",")
return split(sub(str, 7), ",")
end
end end
local function item_has_groups(item_groups, groups) local function item_has_groups(item_groups, groups)
@ -247,30 +263,56 @@ local function valid_item(def)
def.description and def.description ~= "" def.description and def.description ~= ""
end end
local function groups_to_items(groups, get_all) local function get_group_stereotype(group)
if not get_all and #groups == 1 then local stereotype = i3.group_stereotypes[group]
local group = groups[1] local def = reg_items[stereotype]
local stereotype = i3.group_stereotypes[group]
local def = reg_items[stereotype]
if valid_item(def) then if valid_item(def) then
return stereotype return stereotype
end
end end
end
local function groups_to_items(groups)
local names = {} local names = {}
for name, def in pairs(reg_items) do for name, def in pairs(reg_items) do
if valid_item(def) and item_has_groups(def.groups, groups) then if valid_item(def) and item_has_groups(def.groups, groups) then
if get_all then insert(names, name)
insert(names, name)
else
return name
end
end end
end end
return get_all and names or "" sort(names)
return names
end
local function is_cube(drawtype)
return drawtype == "normal" or drawtype == "liquid" or
sub(drawtype, 1, 9) == "glasslike" or
sub(drawtype, 1, 8) == "allfaces"
end
local function get_cube(tiles)
if not true_table(tiles) then
return "i3_blank.png"
end
local top = tiles[1] or "i3_blank.png"
if is_table(top) then
top = top.name or top.image
end
local left = tiles[3] or top or "i3_blank.png"
if is_table(left) then
left = left.name or left.image
end
local right = tiles[5] or left or "i3_blank.png"
if is_table(right) then
right = right.name or right.image
end
return core.inventorycube(top, left, right)
end end
local function apply_recipe_filters(recipes, player) local function apply_recipe_filters(recipes, player)
@ -377,7 +419,8 @@ local function craft_stack(player, data, craft_rcp)
if is_group(name) then if is_group(name) then
items = {} items = {}
local groups = extract_groups(name) local groups = extract_groups(name)
local item_groups = groups_to_items(groups, true) local groupname = name:sub(7)
local item_groups = i3.groups[groupname].items or groups_to_items(groups)
local remaining = count local remaining = count
for _, item in ipairs(item_groups) do for _, item in ipairs(item_groups) do
@ -573,6 +616,7 @@ local function reset_data(data)
data.scrbar_rcp = 1 data.scrbar_rcp = 1
data.scrbar_usg = 1 data.scrbar_usg = 1
data.query_item = nil data.query_item = nil
data.enable_search = nil
data.recipes = nil data.recipes = nil
data.usages = nil data.usages = nil
data.export_rcp = nil data.export_rcp = nil
@ -633,6 +677,7 @@ local _ = {
extract_groups = extract_groups, extract_groups = extract_groups,
item_has_groups = item_has_groups, item_has_groups = item_has_groups,
groups_to_items = groups_to_items, groups_to_items = groups_to_items,
get_group_stereotype = get_group_stereotype,
-- Compression -- Compression
compressible = compressible, compressible = compressible,
@ -660,6 +705,8 @@ local _ = {
msg = msg, msg = msg,
-- Misc. functions -- Misc. functions
is_cube = is_cube,
get_cube = get_cube,
ItemStack = ItemStack, ItemStack = ItemStack,
valid_item = valid_item, valid_item = valid_item,
spawn_item = spawn_item, spawn_item = spawn_item,
@ -712,6 +759,7 @@ local _ = {
match = string.match, match = string.match,
gmatch = string.gmatch, gmatch = string.gmatch,
toupper = toupper, toupper = toupper,
utf8_len = utf8_len,
-- Table -- Table
maxn = table.maxn, maxn = table.maxn,

View File

@ -1,456 +1,464 @@
local set_fs = i3.set_fs local set_fs = i3.set_fs
IMPORT("vec_eq", "vec_round") IMPORT("vec_eq", "vec_round")
IMPORT("reg_items", "reg_aliases") IMPORT("reg_items", "reg_aliases")
IMPORT("S", "random", "translate", "ItemStack") IMPORT("S", "random", "translate", "ItemStack")
IMPORT("sort", "copy", "insert", "remove", "indexof") IMPORT("sort", "copy", "insert", "remove", "indexof")
IMPORT("fmt", "find", "match", "sub", "lower", "split", "toupper") IMPORT("fmt", "find", "match", "sub", "lower", "split", "toupper")
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", "get_sorting_idx", "sort_inventory", "sort_by_category", "get_recipes", "get_detached_inv") IMPORT("search", "get_sorting_idx", "sort_inventory", "sort_by_category", "get_recipes", "get_detached_inv")
IMPORT("valid_item", "get_stack", "craft_stack", "clean_name", "compressible", "check_privs", "safe_teleport") 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
local inv = player:get_inventory() local inv = player:get_inventory()
local sb_inv = fields.scrbar_inv local sb_inv = fields.scrbar_inv
if sb_inv and sub(sb_inv, 1, 3) == "CHG" then if sb_inv and sub(sb_inv, 1, 3) == "CHG" then
data.scrbar_inv = tonumber(match(sb_inv, "%d+")) data.scrbar_inv = tonumber(match(sb_inv, "%d+"))
return return
end end
if fields.drop_items then if fields.drop_items then
local items = split(fields.drop_items, ",") local items = split(fields.drop_items, ",")
data.drop_items = items data.drop_items = items
end 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))
break break
elseif sub(field, 1, 3) == "cb_" then elseif sub(field, 1, 3) == "cb_" then
local str = sub(field, 4) local str = sub(field, 4)
data[str] = false data[str] = false
if fields[field] == "true" then if fields[field] == "true" then
data[str] = true data[str] = true
end end
elseif sub(field, 1, 8) == "setting_" then elseif sub(field, 1, 8) == "setting_" then
data.show_setting = match(field, "_(%w+)$") data.show_setting = match(field, "_(%w+)$")
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)
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
local id, action = match(field, "_(%d+)_(%w+)$") local id, action = match(field, "_(%d+)_(%w+)$")
id = tonumber(id) id = tonumber(id)
local waypoint = data.waypoints[id] local waypoint = data.waypoints[id]
if not waypoint then return end if not waypoint then return end
if action == "see" then if action == "see" then
if data.waypoint_see and data.waypoint_see == id then if data.waypoint_see and data.waypoint_see == id then
data.waypoint_see = nil data.waypoint_see = nil
else else
data.waypoint_see = id data.waypoint_see = id
end end
elseif action == "delete" then elseif action == "delete" then
player:hud_remove(waypoint.id) player:hud_remove(waypoint.id)
remove(data.waypoints, id) remove(data.waypoints, id)
elseif action == "teleport" then elseif action == "teleport" then
local pos = str_to_pos(waypoint.pos) local pos = str_to_pos(waypoint.pos)
safe_teleport(player, pos) safe_teleport(player, pos)
msg(name, S("Teleported to: @1", waypoint.name)) msg(name, S("Teleported to: @1", waypoint.name))
elseif action == "refresh" then elseif action == "refresh" then
local color = random(0xffffff) local color = random(0xffffff)
waypoint.color = color waypoint.color = color
player:hud_change(waypoint.id, "number", color) player:hud_change(waypoint.id, "number", color)
elseif action == "hide" then elseif action == "hide" then
if waypoint.hide then if waypoint.hide then
local new_id = add_hud_waypoint( local new_id = add_hud_waypoint(
player, waypoint.name, str_to_pos(waypoint.pos), waypoint.color) player, waypoint.name, str_to_pos(waypoint.pos), waypoint.color)
waypoint.id = new_id waypoint.id = new_id
waypoint.hide = nil waypoint.hide = nil
else else
player:hud_remove(waypoint.id) player:hud_remove(waypoint.id)
waypoint.hide = true waypoint.hide = true
end end
end end
break break
end end
end end
if fields.quit then if fields.quit then
data.confirm_trash = nil data.confirm_trash = nil
data.show_settings = nil data.show_settings = nil
data.waypoint_see = nil data.waypoint_see = nil
data.bag_rename = nil data.bag_rename = nil
elseif fields.trash then elseif fields.trash then
data.show_settings = nil data.show_settings = nil
data.confirm_trash = true data.confirm_trash = true
elseif fields.settings then elseif fields.settings then
if not data.show_settings then if not data.show_settings then
data.confirm_trash = nil data.confirm_trash = nil
data.show_settings = true data.show_settings = true
else else
data.show_settings = nil data.show_settings = nil
end end
elseif fields.confirm_trash_yes or fields.confirm_trash_no then elseif fields.confirm_trash_yes or fields.confirm_trash_no then
if fields.confirm_trash_yes then if fields.confirm_trash_yes then
inv:set_list("main", {}) inv:set_list("main", {})
inv:set_list("craft", {}) inv:set_list("craft", {})
end end
data.confirm_trash = nil data.confirm_trash = nil
elseif fields.close_settings then elseif fields.close_settings then
data.show_settings = nil data.show_settings = nil
elseif fields.close_preview then elseif fields.close_preview then
data.waypoint_see = nil data.waypoint_see = nil
elseif fields.sort then elseif fields.sort then
sort_inventory(player, data) sort_inventory(player, data)
elseif fields.prev_sort or fields.next_sort then elseif fields.prev_sort or fields.next_sort then
local idx = get_sorting_idx(data.sort) local idx = get_sorting_idx(data.sort)
local tot = #i3.sorting_methods local tot = #i3.sorting_methods
idx -= (fields.prev_sort and 1 or -1) idx -= (fields.prev_sort and 1 or -1)
if idx > tot then if idx > tot then
idx = 1 idx = 1
elseif idx == 0 then elseif idx == 0 then
idx = tot idx = tot
end end
data.sort = i3.sorting_methods[idx].name data.sort = i3.sorting_methods[idx].name
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")
elseif not check_privs(name, {home = true}) then elseif not check_privs(name, {home = true}) then
return msg(name, "'home' privilege missing") return msg(name, "'home' privilege missing")
end end
safe_teleport(player, str_to_pos(data.home)) safe_teleport(player, str_to_pos(data.home))
msg(name, S"Welcome back home!") msg(name, S"Welcome back home!")
elseif fields.set_home then elseif fields.set_home then
data.home = pos_to_str(player:get_pos(), 1) data.home = pos_to_str(player:get_pos(), 1)
elseif fields.bag_rename then elseif fields.bag_rename then
data.bag_rename = true data.bag_rename = true
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)
local meta = bagstack:get_meta() local meta = bagstack:get_meta()
local desc = translate(data.lang_code, bagstack:get_description()) local desc = translate(data.lang_code, bagstack:get_description())
local fill = split(desc, "(")[2] local fill = split(desc, "(")[2]
local newname = fields.bag_newname:gsub("([%(%)])", "") local newname = fields.bag_newname:gsub("([%(%)])", "")
newname = toupper(newname:trim()) newname = toupper(newname:trim())
if fill then if fill then
newname = fmt("%s (%s", newname, fill) newname = fmt("%s (%s", newname, fill)
end end
meta:set_string("description", newname) meta:set_string("description", newname)
bag:set_stack("main", 1, bagstack) bag:set_stack("main", 1, bagstack)
data.bag = bagstack:to_string() data.bag = bagstack:to_string()
data.bag_rename = nil data.bag_rename = nil
elseif fields.waypoint_add then elseif fields.waypoint_add then
local max_waypoints = i3.settings.max_waypoints local max_waypoints = i3.settings.max_waypoints
if #data.waypoints >= max_waypoints then if #data.waypoints >= max_waypoints then
play_sound(name, "i3_cannot", 0.8) play_sound(name, "i3_cannot", 0.8)
return msg(name, fmt("Waypoints limit reached (%u)", max_waypoints)) return msg(name, fmt("Waypoints limit reached (%u)", max_waypoints))
end end
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_eq(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 set a waypoint at this position") return msg(name, S"You already set a waypoint at this position")
end end
end end
local waypoint = fields.waypoint_name local waypoint = fields.waypoint_name
if fields.waypoint_name == "" then if fields.waypoint_name == "" then
waypoint = "Waypoint" waypoint = "Waypoint"
end end
local color = random(0xffffff) local color = random(0xffffff)
local id = add_hud_waypoint(player, waypoint, pos, color) local id = add_hud_waypoint(player, waypoint, pos, color)
insert(data.waypoints, { insert(data.waypoints, {
name = waypoint, name = waypoint,
pos = pos_to_str(pos, 1), pos = pos_to_str(pos, 1),
color = color, color = color,
id = id, id = id,
}) })
data.scrbar_inv += 1000 data.scrbar_inv += 1000
elseif fields.hide_debug_grid then elseif fields.hide_debug_grid then
data.hide_debug_grid = not data.hide_debug_grid data.hide_debug_grid = not data.hide_debug_grid
end end
return set_fs(player) return set_fs(player)
end end
local function select_item(player, data, fields) local function select_item(player, data, fields)
local item local item
for field in pairs(fields) do for field in pairs(fields) do
if find(field, ":") then if find(field, ":") then
item = field item = field
break break
end end
end end
if not item then return end if not item then return end
if compressible(item, data) then if compressible(item, data) then
local idx local idx
for i = 1, #data.items do for i = 1, #data.items do
local it = data.items[i] local it = data.items[i]
if it == item then if it == item then
idx = i idx = i
break break
end end
end end
if data.expand ~= "" then if data.expand ~= "" then
data.alt_items = nil data.alt_items = nil
if item == data.expand then if item == data.expand then
data.expand = nil data.expand = nil
return return
end end
end end
if idx and item ~= data.expand then if idx and item ~= data.expand then
data.alt_items = copy(data.items) data.alt_items = copy(data.items)
data.expand = item data.expand = item
if i3.compress_groups[item] then if i3.compress_groups[item] then
local items = copy(i3.compress_groups[item]) local items = copy(i3.compress_groups[item])
insert(items, fmt("_%s", item)) insert(items, fmt("_%s", item))
sort(items, function(a, b) sort(items, function(a, b)
if a:sub(1, 1) == "_" then if a:sub(1, 1) == "_" then
a = a:sub(2) a = a:sub(2)
end end
return a < b return a < b
end) end)
local i = 1 local i = 1
for _, v in ipairs(items) do for _, v in ipairs(items) do
if valid_item(reg_items[clean_name(v)]) then if valid_item(reg_items[clean_name(v)]) then
insert(data.alt_items, idx + i, v) insert(data.alt_items, idx + i, v)
i++ i++
end end
end end
end end
end end
else else
if sub(item, 1, 1) == "_" then if sub(item, 1, 1) == "_" then
item = sub(item, 2) item = sub(item, 2)
elseif sub(item, 1, 6) == "group!" then elseif sub(item, 1, 6) == "group!" then
item = match(item, "([%w:_]+)$") item = match(item, "([%w:_]+)$")
end end
item = reg_aliases[item] or item item = reg_aliases[item] or item
if not reg_items[item] then return end if not reg_items[item] then return end
if core.is_creative_enabled(data.player_name) then if core.is_creative_enabled(data.player_name) then
local stack = ItemStack(item) local stack = ItemStack(item)
local stackmax = stack:get_stack_max() local stackmax = stack:get_stack_max()
stack = fmt("%s %s", item, stackmax) stack = fmt("%s %s", item, stackmax)
return get_stack(player, stack) return get_stack(player, stack)
end end
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.export_rcp = nil data.export_rcp = nil
data.export_usg = nil data.export_usg = nil
end end
end end
local function rcp_fields(player, data, fields) local function rcp_fields(player, data, fields)
local sb_rcp, sb_usg = fields.scrbar_rcp, fields.scrbar_usg local sb_rcp, sb_usg = fields.scrbar_rcp, fields.scrbar_usg
if fields.cancel then if fields.filter and fields.filter == "" then
reset_data(data) data.enable_search = nil
end
elseif fields.exit then
data.query_item = nil if fields.cancel then
reset_data(data)
elseif fields.key_enter_field == "filter" or fields.search then
if fields.filter == "" then elseif fields.exit then
reset_data(data) data.query_item = nil
return set_fs(player)
end elseif fields.enable_search then
data.enable_search = true
local str = lower(fields.filter) return set_fs(player)
if data.filter == str then return end
elseif fields.filter and (fields.key_enter_field == "filter" or fields.search) then
data.filter = str if fields.filter == "" then
data.pagenum = 1 reset_data(data)
return set_fs(player)
search(data) end
if data.itab > 1 then local str = lower(fields.filter)
sort_by_category(data) if data.filter == str then return end
end
data.filter = str
elseif fields.prev_page or fields.next_page then data.pagenum = 1
if data.pagemax == 1 then return end
data.pagenum -= (fields.prev_page and 1 or -1) search(data)
if data.pagenum > data.pagemax then if data.itab > 1 then
data.pagenum = 1 sort_by_category(data)
elseif data.pagenum == 0 then end
data.pagenum = data.pagemax
end elseif fields.prev_page or fields.next_page then
if data.pagemax == 1 then return end
elseif fields.prev_skin or fields.next_skin then data.pagenum -= (fields.prev_page and 1 or -1)
if data.skin_pagemax == 1 then return end
data.skin_pagenum -= (fields.prev_skin and 1 or -1) if data.pagenum > data.pagemax then
data.pagenum = 1
if data.skin_pagenum > data.skin_pagemax then elseif data.pagenum == 0 then
data.skin_pagenum = 1 data.pagenum = data.pagemax
elseif data.skin_pagenum == 0 then end
data.skin_pagenum = data.skin_pagemax
end elseif fields.prev_skin or fields.next_skin then
if data.skin_pagemax == 1 then return end
elseif fields.prev_recipe or fields.next_recipe then data.skin_pagenum -= (fields.prev_skin and 1 or -1)
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) if data.skin_pagenum > data.skin_pagemax then
data.export_rcp = nil data.skin_pagenum = 1
data.scrbar_rcp = 1 elseif data.skin_pagenum == 0 then
data.skin_pagenum = data.skin_pagemax
elseif fields.prev_usage or fields.next_usage then end
local num = data.unum + (fields.prev_usage and -1 or 1)
data.unum = data.usages[num] and num or (fields.prev_usage and #data.usages or 1) elseif fields.prev_recipe or fields.next_recipe then
data.export_usg = nil local num = data.rnum + (fields.prev_recipe and -1 or 1)
data.scrbar_usg = 1 data.rnum = data.recipes[num] and num or (fields.prev_recipe and #data.recipes or 1)
data.export_rcp = nil
elseif fields.fav then data.scrbar_rcp = 1
local fav = is_fav(data)
elseif fields.prev_usage or fields.next_usage then
if #data.favs < i3.settings.max_favs and not fav then local num = data.unum + (fields.prev_usage and -1 or 1)
insert(data.favs, data.query_item) data.unum = data.usages[num] and num or (fields.prev_usage and #data.usages or 1)
elseif fav then data.export_usg = nil
remove(data.favs, fav) data.scrbar_usg = 1
end
elseif fields.fav then
elseif fields.export_rcp or fields.export_usg then local fav = is_fav(data)
if fields.export_rcp then
data.export_rcp = not data.export_rcp if #data.favs < i3.settings.max_favs and not fav then
insert(data.favs, data.query_item)
if not data.export_rcp then elseif fav then
data.scrbar_rcp = 1 remove(data.favs, fav)
end end
else
data.export_usg = not data.export_usg elseif fields.export_rcp or fields.export_usg then
if fields.export_rcp then
if not data.export_usg then data.export_rcp = not data.export_rcp
data.scrbar_usg = 1
end if not data.export_rcp then
end data.scrbar_rcp = 1
end
elseif (sb_rcp and sub(sb_rcp, 1, 3) == "CHG") or (sb_usg and sub(sb_usg, 1, 3) == "CHG") then else
data.scrbar_rcp = sb_rcp and tonumber(match(sb_rcp, "%d+")) data.export_usg = not data.export_usg
data.scrbar_usg = sb_usg and tonumber(match(sb_usg, "%d+"))
if not data.export_usg then
elseif fields.craft_rcp or fields.craft_usg then data.scrbar_usg = 1
craft_stack(player, data, fields.craft_rcp) end
end
if fields.craft_rcp then
data.export_rcp = nil elseif (sb_rcp and sub(sb_rcp, 1, 3) == "CHG") or (sb_usg and sub(sb_usg, 1, 3) == "CHG") then
data.scrbar_rcp = 1 data.scrbar_rcp = sb_rcp and tonumber(match(sb_rcp, "%d+"))
else data.scrbar_usg = sb_usg and tonumber(match(sb_usg, "%d+"))
data.export_usg = nil
data.scrbar_usg = 1 elseif fields.craft_rcp or fields.craft_usg then
end craft_stack(player, data, fields.craft_rcp)
else
select_item(player, data, fields) if fields.craft_rcp then
end data.export_rcp = nil
end data.scrbar_rcp = 1
else
core.register_on_player_receive_fields(function(player, formname, fields) data.export_usg = nil
local name = player:get_player_name() data.scrbar_usg = 1
end
if formname == "i3_outdated" then else
return false, core.kick_player(name, select_item(player, data, fields)
S"Come back when your Minetest client is up-to-date (www.minetest.net).") end
elseif formname ~= "" then end
return false
end core.register_on_player_receive_fields(function(player, formname, fields)
local name = player:get_player_name()
-- No-op buttons
if fields.player_name or fields.awards or fields.home_pos or fields.pagenum or if formname == "i3_outdated" then
fields.no_item or fields.no_rcp or fields.select_sorting or fields.sort_method or return false, core.kick_player(name,
fields.bg_content then S"Come back when your Minetest client is up-to-date (www.minetest.net).")
return false elseif formname ~= "" then
end return false
end
--print(dump(fields))
local data = i3.data[name] -- No-op buttons
if not data then return end if fields.player_name or fields.awards or fields.home_pos or fields.pagenum or
fields.no_item or fields.no_rcp or fields.select_sorting or fields.sort_method or
for f in pairs(fields) do fields.bg_content then
if sub(f, 1, 4) == "tab_" then return false
local tabname = sub(f, 5) end
i3.set_tab(player, tabname)
break --print(dump(fields))
elseif sub(f, 1, 5) == "itab_" then local data = i3.data[name]
data.pagenum = 1 if not data then return end
data.itab = tonumber(f:sub(-1))
sort_by_category(data) for f in pairs(fields) do
break if sub(f, 1, 4) == "tab_" then
end local tabname = sub(f, 5)
end i3.set_tab(player, tabname)
break
rcp_fields(player, data, fields) elseif sub(f, 1, 5) == "itab_" then
data.pagenum = 1
local tab = i3.tabs[data.tab] data.itab = tonumber(f:sub(-1))
sort_by_category(data)
if tab and tab.fields then break
return true, tab.fields(player, data, fields) end
end end
return true, set_fs(player) rcp_fields(player, data, fields)
end)
local tab = i3.tabs[data.tab]
return inv_fields
if tab and tab.fields then
return true, tab.fields(player, data, fields)
end
return true, set_fs(player)
end)
return inv_fields

View File

@ -11,6 +11,7 @@ i3.group_stereotypes = {
stone = "default:stone", stone = "default:stone",
leaves = "default:leaves", leaves = "default:leaves",
coal = "default:coal_lump", coal = "default:coal_lump",
fence = "default:fence_wood",
vessel = "vessels:glass_bottle", vessel = "vessels:glass_bottle",
flower = "flowers:dandelion_yellow", flower = "flowers:dandelion_yellow",
water_bucket = "bucket:bucket_water", water_bucket = "bucket:bucket_water",
@ -26,6 +27,7 @@ i3.group_names = {
glass = S"Any glass", glass = S"Any glass",
stick = S"Any stick", stick = S"Any stick",
stone = S"Any stone", stone = S"Any stone",
fence = S"Any fence",
carpet = S"Any carpet", carpet = S"Any carpet",
flower = S"Any flower", flower = S"Any flower",
leaves = S"Any leaves", leaves = S"Any leaves",

View File

@ -13,12 +13,12 @@ IMPORT("vec_new", "vec_sub", "vec_round")
IMPORT("clr", "ESC", "msg", "check_privs") IMPORT("clr", "ESC", "msg", "check_privs")
IMPORT("min", "max", "floor", "ceil", "round") IMPORT("min", "max", "floor", "ceil", "round")
IMPORT("reg_items", "reg_tools", "reg_entities") IMPORT("reg_items", "reg_tools", "reg_entities")
IMPORT("get_bag_description", "get_detached_inv") IMPORT("true_str", "is_fav", "is_num", "str_to_pos")
IMPORT("S", "ES", "translate", "ItemStack", "toupper") IMPORT("get_sorting_idx", "compression_active", "compressible")
IMPORT("groups_to_items", "compression_active", "compressible") IMPORT("get_bag_description", "get_detached_inv", "get_recipes")
IMPORT("true_str", "is_fav", "is_num", "get_group", "str_to_pos") IMPORT("S", "ES", "translate", "ItemStack", "toupper", "utf8_len")
IMPORT("maxn", "sort", "concat", "copy", "insert", "remove", "unpack") IMPORT("maxn", "sort", "concat", "copy", "insert", "remove", "unpack")
IMPORT("get_sorting_idx", "is_group", "extract_groups", "item_has_groups", "get_recipes") IMPORT("extract_groups", "groups_to_items", "is_group", "item_has_groups", "get_group")
local function fmt(elem, ...) local function fmt(elem, ...)
if not fs_elements[elem] then if not fs_elements[elem] then
@ -93,7 +93,8 @@ local function get_stack_max(inv, data, is_recipe, rcp)
local def = reg_items[item] local def = reg_items[item]
if def then if def then
local groups = extract_groups(name) local group_cache = i3.groups[name:sub(7)]
local groups = group_cache and group_cache.groups or extract_groups(name)
if item_has_groups(def.groups, groups) then if item_has_groups(def.groups, groups) then
counts_inv[name] = (counts_inv[name] or 0) + count counts_inv[name] = (counts_inv[name] or 0) + count
@ -131,7 +132,7 @@ local function get_inv_slots(fs)
fs"style_type[box;colors=#77777710,#77777710,#777,#777]" fs"style_type[box;colors=#77777710,#77777710,#777,#777]"
for i = 0, hotbar_len - 1 do for i = 0, hotbar_len - 1 do
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(fmt("style_type[list;size=%f;spacing=%f]", size, spacing),
@ -147,10 +148,10 @@ 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(fmt("style[%s;font=bold;font_size=%u]", name, font_size))
fs("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
fs("image", 0, y + 0.55, ctn_len, 0.035, PNG.bar) image(0, y + 0.55, ctn_len, 0.035, PNG.bar)
end end
end end
@ -295,14 +296,14 @@ local function get_isometric_view(fs, pos, X, Y, t, cubes, depth, high)
end end
shift += (base_depth and 0.45 or 0.95) shift += (base_depth and 0.45 or 0.95)
fs("image", 2.7, Y + shift, 0.3, 0.3, PNG.flag) image(2.7, Y + shift, 0.3, 0.3, PNG.flag)
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(fmt("box[0,%f;4.9,0.6;#bababa25]", yextra + 1.1))
fs("label", 0, yextra + 0.85, ES"Waypoint name:") label(0, yextra + 0.85, ES"Waypoint name:")
fs(fmt("field[0.1,%f;4.8,0.6;waypoint_name;;]", yextra + 1.1)) fs(fmt("field[0.1,%f;4.8,0.6;waypoint_name;;]", yextra + 1.1))
fs("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(fmt("tooltip[waypoint_add;%s]", ES"Add waypoint"))
if #data.waypoints == 0 then return end if #data.waypoints == 0 then return end
@ -313,7 +314,7 @@ local function get_waypoint_fs(fs, data, player, yextra, ctn_len)
local icon_size, yi = 0.35, y + 0.12 local icon_size, yi = 0.35, y + 0.12
fs"style_type[box;colors=#bababa30,#bababa30,#bababa05,#bababa05]" fs"style_type[box;colors=#bababa30,#bababa30,#bababa05,#bababa05]"
fs("box", 0, y, ctn_len, 0.6, "") box(0, y, ctn_len, 0.6, "")
local waypoint_name, lim = v.name, 18 local waypoint_name, lim = v.name, 18
@ -330,7 +331,7 @@ local function get_waypoint_fs(fs, data, player, yextra, ctn_len)
local teleport_priv = check_privs(player, {teleport = true}) local teleport_priv = check_privs(player, {teleport = true})
local waypoint_preview = data.waypoint_see and data.waypoint_see == i local waypoint_preview = data.waypoint_see and data.waypoint_see == i
fs("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")))
@ -339,38 +340,38 @@ local function get_waypoint_fs(fs, data, player, yextra, ctn_len)
tooltip = fmt("%s\n%s", tooltip, clr("#ff0", ES"[Click to teleport]")) tooltip = fmt("%s\n%s", tooltip, clr("#ff0", ES"[Click to teleport]"))
end end
fs("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(fmt("style[%s;fgimg=%s;fgimg_hovered=%s;content_offset=0]", del, PNG.trash, PNG.trash_hover))
fs("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(fmt("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(fmt("style[%s;fgimg=%s;fgimg_hovered=%s;content_offset=0]", rfs, PNG.refresh, PNG.refresh_hover))
fs("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(fmt("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(fmt("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))
fs("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(fmt("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(fmt("style[%s;fgimg=%s;content_offset=0]", vsb, v.hide and PNG.nonvisible or PNG.visible))
fs("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(fmt("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)
fs("button", 0, y, ctn_len - 2.1, 0.6, tp, "") button(0, y, ctn_len - 2.1, 0.6, tp, "")
end end
if waypoint_preview then if waypoint_preview then
fs("image", 0.25, y - 3.5, 5, 4, PNG.bg_content) image(0.25, y - 3.5, 5, 4, PNG.bg_content)
fs("button", 0.25, y - 3.35, 5, 0.55, "area_preview", v.name) button(0.25, y - 3.35, 5, 0.55, "area_preview", v.name)
fs("image_button", 4.65, y - 3.25, 0.25, 0.25, image_button(4.65, y - 3.25, 0.25, 0.25,
PNG.cancel_hover .. "^\\[brighten", "close_preview", "") PNG.cancel_hover .. "^\\[brighten", "close_preview", "")
local pos = str_to_pos(data.waypoints[i].pos) local pos = str_to_pos(data.waypoints[i].pos)
@ -392,20 +393,20 @@ local function get_bag_fs(fs, data, name, esc_name, bag_size, yextra)
local bagstack = bag:get_stack("main", 1) local bagstack = bag:get_stack("main", 1)
local desc = ESC(get_bag_description(data, bagstack)) local desc = ESC(get_bag_description(data, bagstack))
fs("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(fmt("style[bg_content;bgimg=%s;fgimg=i3_blank.png;bgimg_middle=10,%u;sound=]", PNG.bg_content, m))
fs("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
fs("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))
fs("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(fmt("tooltip[%s;%s]", "bag_rename", ES"Rename the bag"))
else else
fs("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(fmt("field[1.8,%f;2.5,0.4;bag_newname;;%s]", yextra + 0.82, desc),
"field_close_on_enter[bag_newname;false]") "field_close_on_enter[bag_newname;false]")
fs("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))
end end
@ -435,12 +436,12 @@ local function get_container(fs, data, player, yoffset, ctn_len, award_list, awa
local heart_x, heart_h = 0.65, yoffset + 0.75 local heart_x, heart_h = 0.65, yoffset + 0.75
for i = 1, 10 do for i = 1, 10 do
fs("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_grey)
end end
for i = 1, hearts do for i = 1, hearts do
fs("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, heart_size, heart_size,
(half == 1 and i == floor(hearts)) and PNG.heart_half or PNG.heart) (half == 1 and i == floor(hearts)) and PNG.heart_half or PNG.heart)
end end
@ -449,10 +450,10 @@ local function get_container(fs, data, player, yoffset, ctn_len, award_list, awa
end end
fs(fmt("list[current_player;craft;%f,%f;3,3;]", 0, yoffset + 1.45)) fs(fmt("list[current_player;craft;%f,%f;3,3;]", 0, yoffset + 1.45))
fs("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(fmt("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)) fmt("list[detached:i3_trash;main;%f,%f;1,1;]", 4.45, yoffset + 3.75))
fs("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
@ -461,15 +462,15 @@ local function get_container(fs, data, player, yoffset, ctn_len, award_list, awa
fs(fmt("style[btn_%s;fgimg=%s;fgimg_hovered=%s;content_offset=0]", title, fs(fmt("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)]))
fs("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(fmt("tooltip[%s;%s]", btn_name, title:gsub("^%l", upper)))
end end
fs("box", 0, yextra + 0.45, ctn_len, 0.045, "#bababa50") box(0, yextra + 0.45, ctn_len, 0.045, "#bababa50")
fs("box", (data.subcat - 1) * 1.18, yextra + 0.45, 1, 0.045, "#f9826c") box((data.subcat - 1) * 1.18, yextra + 0.45, 1, 0.045, "#f9826c")
local function not_installed(modname) local function not_installed(modname)
fs("hypertext", 0, yextra + 0.9, ctn_len, 0.6, "not_installed", hypertext(0, yextra + 0.9, ctn_len, 0.6, "not_installed",
fmt("<global size=16><center><style color=%s font=mono>%s</style> not installed</center>", fmt("<global size=16><center><style color=%s font=mono>%s</style> not installed</center>",
colors.blue, modname)) colors.blue, modname))
end end
@ -484,8 +485,8 @@ 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]
fs(fmt("list[detached:%s_armor;armor;0,%f;3,2;]", esc_name, yextra + 0.7)) fs(fmt("list[detached:%s_armor;armor;0,%f;3,2;]", esc_name, yextra + 0.7))
fs("label", 3.65, yextra + 1.55, fmt("%s: %s", ES"Level", armor_def.level)) label(3.65, yextra + 1.55, fmt("%s: %s", ES"Level", armor_def.level))
fs("label", 3.65, yextra + 2.05, fmt("%s: %s", ES"Heal", armor_def.heal)) label(3.65, yextra + 2.05, fmt("%s: %s", ES"Heal", armor_def.heal))
elseif data.subcat == 3 then elseif data.subcat == 3 then
if not i3.modules.skins then if not i3.modules.skins then
@ -502,11 +503,11 @@ local function get_container(fs, data, player, yoffset, ctn_len, award_list, awa
data.skin_pagemax = max(1, ceil(#_skins / spp)) data.skin_pagemax = max(1, ceil(#_skins / spp))
fs("image_button", 1.5, btn_y, 0.35, 0.35, "", "prev_skin", "") 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", "") image_button(3.85, btn_y, 0.35, 0.35, "", "next_skin", "")
fs"style[skin_page;font=bold;font_size=18]" fs"style[skin_page;font=bold;font_size=18]"
fs("button", 1.85, btn_y - 0.23, 2, 0.8, "skin_page", button(1.85, btn_y - 0.23, 2, 0.8, "skin_page",
fmt("%s / %u", clr(colors.yellow, data.skin_pagenum), data.skin_pagemax)) fmt("%s / %u", clr(colors.yellow, data.skin_pagenum), data.skin_pagemax))
end end
@ -529,7 +530,7 @@ local function get_container(fs, data, player, yoffset, ctn_len, award_list, awa
local Y = ceil((i % spp - X) / 3 + 1) local Y = ceil((i % spp - X) / 3 + 1)
Y += (Y * 2.45) + yextra - 2.75 + add_y Y += (Y * 2.45) + yextra - 2.75 + add_y
fs("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(fmt("tooltip[%s;%s]", btn_name, ESC(skin.name)))
end end
@ -551,25 +552,25 @@ local function show_popup(fs, data)
fs"style_type[box;colors=#999,#999,#808080,#808080]" fs"style_type[box;colors=#999,#999,#808080,#808080]"
for _ = 1, 3 do for _ = 1, 3 do
fs("box", 2.97, 10.75, 4.3, 0.5, "") box(2.97, 10.75, 4.3, 0.5, "")
end end
fs("label", 3.12, 11, "Confirm trash?") label(3.12, 11, "Confirm trash?")
fs("image_button", 5.17, 10.75, 1, 0.5, "", "confirm_trash_yes", "Yes") image_button(5.17, 10.75, 1, 0.5, "", "confirm_trash_yes", "Yes")
fs("image_button", 6.27, 10.75, 1, 0.5, "", "confirm_trash_no", "No") image_button(6.27, 10.75, 1, 0.5, "", "confirm_trash_no", "No")
elseif data.show_settings then elseif data.show_settings then
fs"style_type[box;colors=#999,#999,#808080,#808080]" fs"style_type[box;colors=#999,#999,#808080,#808080]"
for _ = 1, 3 do for _ = 1, 3 do
fs("box", 2.1, 9.25, 6, 2, "") box(2.1, 9.25, 6, 2, "")
end end
for _ = 1, 3 do for _ = 1, 3 do
fs("box", 2.1, 9.25, 6, 0.5, "#707070") box(2.1, 9.25, 6, 0.5, "#707070")
end end
fs("image_button", 7.75, 9.35, 0.25, 0.25, PNG.cancel_hover .. "^\\[brighten", "close_settings", "") image_button(7.75, 9.35, 0.25, 0.25, PNG.cancel_hover .. "^\\[brighten", "close_settings", "")
local show_home = data.show_setting == "home" local show_home = data.show_setting == "home"
local show_sorting = data.show_setting == "sorting" local show_sorting = data.show_setting == "sorting"
@ -582,9 +583,9 @@ local function show_popup(fs, data)
fmt("style[setting_misc;textcolor=%s;font=bold;sound=i3_click]", fmt("style[setting_misc;textcolor=%s;font=bold;sound=i3_click]",
show_misc and colors.yellow or "#fff")) show_misc and colors.yellow or "#fff"))
fs("button", 2.2, 9.25, 1.8, 0.55, "setting_home", "Home") button(2.2, 9.25, 1.8, 0.55, "setting_home", "Home")
fs("button", 4, 9.25, 1.8, 0.55, "setting_sorting", "Sorting") button(4, 9.25, 1.8, 0.55, "setting_sorting", "Sorting")
fs("button", 5.8, 9.25, 1.8, 0.55, "setting_misc", "Misc.") button(5.8, 9.25, 1.8, 0.55, "setting_misc", "Misc.")
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"
@ -598,17 +599,17 @@ local function show_popup(fs, data)
end) end)
end end
fs("hypertext", 2.1, 9.9, 6, 0.6, "home_pos", fmt("<global size=16><center>%s</center>", str)) hypertext(2.1, 9.9, 6, 0.6, "home_pos", fmt("<global size=16><center>%s</center>", str))
fs("image_button", 4.2, 10.4, 1.8, 0.7, "", "set_home", "Set home") image_button(4.2, 10.4, 1.8, 0.7, "", "set_home", "Set home")
elseif show_sorting then elseif show_sorting then
fs("button", 2.1, 9.7, 6, 0.8, "select_sorting", ES"Select the inventory sorting method:") button(2.1, 9.7, 6, 0.8, "select_sorting", ES"Select the inventory sorting method:")
fs("image_button", 2.2, 10.6, 0.35, 0.35, "", "prev_sort", "") 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", "") image_button(7.65, 10.6, 0.35, 0.35, "", "next_sort", "")
fs"style[sort_method;font=bold;font_size=20]" fs"style[sort_method;font=bold;font_size=20]"
fs("button", 2.55, 10.36, 5.1, 0.8, "sort_method", toupper(data.sort)) button(2.55, 10.36, 5.1, 0.8, "sort_method", toupper(data.sort))
local idx = get_sorting_idx(data.sort) local idx = get_sorting_idx(data.sort)
local desc = i3.sorting_methods[idx].description local desc = i3.sorting_methods[idx].description
@ -618,13 +619,13 @@ local function show_popup(fs, data)
end end
elseif show_misc then elseif show_misc then
fs("checkbox", 2.4, 10.05, "cb_inv_compress", "Compression", tostring(data.inv_compress)) checkbox(2.4, 10.05, "cb_inv_compress", "Compression", tostring(data.inv_compress))
fs("checkbox", 2.4, 10.5, "cb_reverse_sorting", "Reverse mode", tostring(data.reverse_sorting)) checkbox(2.4, 10.5, "cb_reverse_sorting", "Reverse mode", tostring(data.reverse_sorting))
fs("checkbox", 2.4, 10.95, "cb_ignore_hotbar", "Ignore hotbar", tostring(data.ignore_hotbar)) checkbox(2.4, 10.95, "cb_ignore_hotbar", "Ignore hotbar", tostring(data.ignore_hotbar))
fs("checkbox", 5.4, 10.05, "cb_auto_sorting", "Automation", tostring(data.auto_sorting)) checkbox(5.4, 10.05, "cb_auto_sorting", "Automation", tostring(data.auto_sorting))
for _ = 1, 3 do for _ = 1, 3 do
fs("box", 5.4, 10.68, 2.4, 0.45, "#707070") box(5.4, 10.68, 2.4, 0.45, "#707070")
end end
fs("style[drop_items;font_size=15;font=mono;textcolor=#dbeeff]", fs("style[drop_items;font_size=15;font=mono;textcolor=#dbeeff]",
@ -667,12 +668,12 @@ local function get_inventory_fs(player, data, fs)
local textures = concat(t, ","):gsub("!", ",") local textures = concat(t, ","):gsub("!", ",")
--fs("style[player_model;bgcolor=black]") --fs("style[player_model;bgcolor=black]")
fs("model", 0.2, 0.2, armor_skin and 4 or 3.4, ctn_hgt, model(0.2, 0.2, armor_skin and 4 or 3.4, ctn_hgt,
"player_model", props.mesh, textures, "0,-150", "false", "false", "player_model", props.mesh, textures, "0,-150", "false", "false",
fmt("%u,%u%s", anim.x, anim.y, data.fs_version >= 5 and ";30" or "")) fmt("%u,%u%s", anim.x, anim.y, data.fs_version >= 5 and ";30" or ""))
else else
local size = 2.5 local size = 2.5
fs("image", 0.7, 0.2, size, size * props.visual_size.y, props.textures[1]) image(0.7, 0.2, size, size * props.visual_size.y, props.textures[1])
end end
local awards_unlocked, award_list, award_list_nb = 0 local awards_unlocked, award_list, award_list_nb = 0
@ -742,7 +743,7 @@ local function get_inventory_fs(player, data, fs)
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(fmt("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)]))
fs("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(fmt("tooltip[%s;%s]", btn_name, tooltip))
end end
@ -838,7 +839,7 @@ local function get_output_fs(fs, data, rcp, is_recipe, shapeless, right, btn_siz
local icon, tooltip = PNG.blank local icon, tooltip = PNG.blank
if custom_recipe and true_str(custom_recipe.icon) then if custom_recipe and true_str(custom_recipe.icon) then
icon = fmt("%s^\\[resize:16x16", custom_recipe.icon) icon = custom_recipe.icon
elseif shapeless then elseif shapeless then
icon = PNG.shapeless icon = PNG.shapeless
end end
@ -847,9 +848,9 @@ local function get_output_fs(fs, data, rcp, is_recipe, shapeless, right, btn_siz
local pos_y = data.yoffset + 0.9 local pos_y = data.yoffset + 0.9
if cooking then if cooking then
fs("animated_image", pos_x, pos_y, 0.5, 0.5, PNG.furnace_anim, 8, 180) animated_image(pos_x, pos_y, 0.5, 0.5, PNG.furnace_anim, 8, 180)
else else
fs("image", pos_x, pos_y, 0.5, 0.5, icon) image(pos_x, pos_y, 0.5, 0.5, icon)
end end
if custom_recipe and true_str(custom_recipe.description) then if custom_recipe and true_str(custom_recipe.description) then
@ -861,7 +862,7 @@ local function get_output_fs(fs, data, rcp, is_recipe, shapeless, right, btn_siz
end end
if tooltip then if tooltip then
fs("tooltip", pos_x, pos_y, 0.5, 0.5, ESC(tooltip)) tooltip(pos_x, pos_y, 0.5, 0.5, ESC(tooltip))
end end
end end
@ -870,10 +871,10 @@ local function get_output_fs(fs, data, rcp, is_recipe, shapeless, right, btn_siz
local X = arrow_X + 1.2 local X = arrow_X + 1.2
local Y = data.yoffset + 1.4 local Y = data.yoffset + 1.4
fs("image", arrow_X, Y + 0.06, 1, 1, PNG.arrow) image(arrow_X, Y + 0.06, 1, 1, PNG.arrow)
if fuel then if fuel then
fs("animated_image", X + 0.05, Y, BTN_SIZE, BTN_SIZE, PNG.fire_anim, 8, 180) animated_image(X + 0.05, Y, BTN_SIZE, BTN_SIZE, PNG.fire_anim, 8, 180)
return return
end end
@ -892,14 +893,14 @@ local function get_output_fs(fs, data, rcp, is_recipe, shapeless, right, btn_siz
fs(fmt("style_type[list;size=%f]", BTN_SIZE)) fs(fmt("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(fmt("list[detached:i3_output_%s_%s;main;%f,%f;1,1;]", rcp_usg, data.player_name, X + 0.11, Y))
fs("button", X + 0.11, Y, 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)
inv:set_stack("main", 1, item) inv:set_stack("main", 1, item)
pos = {x = X + 0.11, y = Y} pos = {x = X + 0.11, y = Y}
else else
fs("image", X, Y - 0.11, bt_s, bt_s, PNG.slot) image(X, Y - 0.11, bt_s, bt_s, PNG.slot)
fs("item_image_button", item_image_button(
X + 0.11, Y, BTN_SIZE, BTN_SIZE, X + 0.11, Y, BTN_SIZE, BTN_SIZE,
fmt("%s %u %u", name, count * (is_recipe and data.scrbar_rcp or data.scrbar_usg or 1), wear), fmt("%s %u %u", name, count * (is_recipe and data.scrbar_rcp or data.scrbar_usg or 1), wear),
_name, "") _name, "")
@ -992,10 +993,12 @@ local function get_grid_fs(fs, data, rcp, is_recipe)
end end
local groups local groups
local group_cache = i3.groups[name:sub(7)]
if is_group(name) then if is_group(name) then
groups = extract_groups(name) groups = group_cache and group_cache.groups or extract_groups(name)
name = groups_to_items(groups) name = group_cache and (group_cache.stereotype or group_cache.items[1]) or
groups_to_items(groups)[1]
end end
local label = groups and "\nG" or "" local label = groups and "\nG" or ""
@ -1023,14 +1026,26 @@ local function get_grid_fs(fs, data, rcp, is_recipe)
end end
if not large_recipe then if not large_recipe then
fs("image", X, Y, btn_size, btn_size, PNG.slot) image(X, Y, btn_size, btn_size, PNG.slot)
end end
local btn_name = groups and fmt("group!%s!%s", groups[1], name) or name local btn_name = groups and fmt("group!%s!%s", groups[1], name) or name
local _count = count * (is_recipe and data.scrbar_rcp or data.scrbar_usg or 1)
fs("item_image_button", X, Y, btn_size, btn_size, if group_cache and group_cache.sprite and not large_recipe then
fmt("%s %u", name, count * (is_recipe and data.scrbar_rcp or data.scrbar_usg or 1)), local sprite = ESC(group_cache.sprite)
btn_name, label) local size = btn_size - 0.02
item_image_button(X, Y, btn_size, btn_size, "", btn_name, "")
animated_image(X + 0.01, Y + 0.025, size, size, sprite, group_cache.count, 1500)
label(X + 0.45, Y + 0.18, label)
if _count > 1 then
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)
end
local def = reg_items[name] local def = reg_items[name]
local unknown = not def or nil local unknown = not def or nil
@ -1069,7 +1084,7 @@ local function get_rcp_lbl(fs, data, panel, rn, is_recipe)
local rcp = is_recipe and panel.rcp[data.rnum] or panel.rcp[data.unum] local rcp = is_recipe and panel.rcp[data.rnum] or panel.rcp[data.unum]
if rcp.custom then if rcp.custom then
fs("hypertext", data.inv_width + 4.8, data.yoffset + 0.12, 3, 0.6, "custom_rcp", hypertext(data.inv_width + 4.8, data.yoffset + 0.12, 3, 0.6, "custom_rcp",
fmt("<global size=16><right><i>%s</i></right>", ES"Custom recipe")) fmt("<global size=16><right><i>%s</i></right>", ES"Custom recipe"))
end end
@ -1082,7 +1097,7 @@ local function get_rcp_lbl(fs, data, panel, rn, is_recipe)
local one = rn == 1 local one = rn == 1
local y = data.yoffset + 3.3 local y = data.yoffset + 3.3
fs("hypertext", data.inv_width + (one and 4.7 or 3.95), y, 3, 0.6, "rcp_num", hypertext(data.inv_width + (one and 4.7 or 3.95), y, 3, 0.6, "rcp_num",
fmt("<global size=16><right>%s</right>", lbl)) fmt("<global size=16><right>%s</right>", lbl))
if not one then if not one then
@ -1091,8 +1106,8 @@ local function get_rcp_lbl(fs, data, panel, rn, is_recipe)
local next_name = fmt("next_%s", btn_suffix) local next_name = fmt("next_%s", btn_suffix)
local size = 0.3 local size = 0.3
fs("image_button", data.inv_width + 7.05, y, size, size, "", prev_name, "") image_button(data.inv_width + 7.05, y, size, size, "", prev_name, "")
fs("image_button", data.inv_width + 7.5, y, size, size, "", next_name, "") image_button(data.inv_width + 7.5, y, size, size, "", next_name, "")
end end
get_grid_fs(fs, data, rcp, is_recipe) get_grid_fs(fs, data, rcp, is_recipe)
@ -1139,7 +1154,7 @@ local function get_model_fs(fs, data, def, model_alias)
insert(t, t[#t]) insert(t, t[#t])
end end
fs("model", data.inv_width + 6.6, data.yoffset + 0.05, 1.3, 1.3, "preview", model(data.inv_width + 6.6, data.yoffset + 0.05, 1.3, 1.3, "preview",
def.mesh, concat(t, ","), "0,0", "true", "true", def.mesh, concat(t, ","), "0,0", "true", "true",
model_alias and model_alias.frames or "") model_alias and model_alias.frames or "")
end end
@ -1154,16 +1169,16 @@ local function get_header(fs, data)
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(fmt("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))
fs("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(fmt("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(fmt("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))
fs("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(fmt("tooltip[nofav;%s]", ES"Cannot mark this item. Bookmark limit reached."))
end end
fs("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(fmt("tooltip[exit;%s]", ES"Back to item list"))
local desc_lim, name_lim = 34, 35 local desc_lim, name_lim = 34, 35
@ -1175,19 +1190,19 @@ local function get_header(fs, data)
local Y2 = Y1 + 0.5 local Y2 = Y1 + 0.5
if #desc > desc_lim then if #desc > desc_lim then
fs("tooltip", X, Y1 - 0.1, 5.7, 0.24, desc) tooltip(X, Y1 - 0.1, 5.7, 0.24, desc)
desc = snip(desc, desc_lim) desc = snip(desc, desc_lim)
end end
if #tech_name > name_lim then if #tech_name > name_lim then
fs("tooltip", X, Y2 - 0.1, 5.7, 0.24, tech_name) tooltip(X, Y2 - 0.1, 5.7, 0.24, tech_name)
tech_name = snip(tech_name, name_lim) tech_name = snip(tech_name, name_lim)
end end
fs"style_type[label;font=bold;font_size=20]" fs"style_type[label;font=bold;font_size=20]"
fs("label", X, Y1, desc) label(X, Y1, desc)
fs"style_type[label;font=mono;font_size=16]" fs"style_type[label;font=mono;font_size=16]"
fs("label", X, Y2, clr(colors.blue, tech_name)) label(X, Y2, clr(colors.blue, tech_name))
fs"style_type[label;font=normal;font_size=16]" fs"style_type[label;font=normal;font_size=16]"
local def = reg_items[data.query_item] local def = reg_items[data.query_item]
@ -1196,7 +1211,7 @@ local function get_header(fs, data)
if def.drawtype == "mesh" or model_alias then if def.drawtype == "mesh" or model_alias then
get_model_fs(fs, data, def, model_alias) get_model_fs(fs, data, def, model_alias)
else else
fs("item_image", data.inv_width + 6.8, data.yoffset + 0.17, 1.1, 1.1, data.query_item) item_image(data.inv_width + 6.8, data.yoffset + 0.17, 1.1, 1.1, data.query_item)
end end
end end
@ -1206,7 +1221,7 @@ local function get_export_fs(fs, data, is_recipe, is_usage, max_stacks_rcp, max_
fs(fmt("style[export_%s;fgimg=%s;fgimg_hovered=%s]", fs(fmt("style[export_%s;fgimg=%s;fgimg_hovered=%s]",
name, fmt("%s", show_export and PNG.export_hover or PNG.export), PNG.export_hover)) name, fmt("%s", show_export and PNG.export_hover or PNG.export), PNG.export_hover))
fs("image_button", data.inv_width + 7.35, data.yoffset + 0.2, 0.45, 0.45, "", fmt("export_%s", name), "") image_button(data.inv_width + 7.35, data.yoffset + 0.2, 0.45, 0.45, "", fmt("export_%s", name), "")
fs(fmt("tooltip[export_%s;%s]", name, ES"Quick crafting")) fs(fmt("tooltip[export_%s;%s]", name, ES"Quick crafting"))
if not show_export then return end if not show_export then return end
@ -1228,8 +1243,8 @@ local function get_export_fs(fs, data, is_recipe, is_usage, max_stacks_rcp, max_
fmt("scrollbaroptions[min=1;max=%u;smallstep=1]", craft_max)) fmt("scrollbaroptions[min=1;max=%u;smallstep=1]", craft_max))
local x = data.inv_width + 8.1 local x = data.inv_width + 8.1
fs("scrollbar", x, data.yoffset, 2.5, 0.35, "horizontal", fmt("scrbar_%s", name), stack_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)) button(x, data.yoffset + 0.4, 2.5, 0.7, fmt("craft_%s", name), ES("Craft (×@1)", stack_fs))
end end
local function get_rcp_extra(fs, data, player, panel, is_recipe, is_usage) local function get_rcp_extra(fs, data, player, panel, is_recipe, is_usage)
@ -1265,7 +1280,7 @@ local function get_rcp_extra(fs, data, player, panel, is_recipe, is_usage)
get_rcp_lbl(fs, data, panel, rn, is_recipe) get_rcp_lbl(fs, data, panel, rn, is_recipe)
else else
local lbl = is_recipe and ES"No recipes" or ES"No usages" local lbl = is_recipe and ES"No recipes" or ES"No usages"
fs("button", data.inv_width + 0.1, data.yoffset + (panel.height / 2) - 0.5, 7.8, 1, "no_rcp", lbl) button(data.inv_width + 0.1, data.yoffset + (panel.height / 2) - 0.5, 7.8, 1, "no_rcp", lbl)
end end
fs"container_end[]" fs"container_end[]"
@ -1309,31 +1324,47 @@ local function get_items_fs(fs, data, player, full_height)
local ipp = rows * lines local ipp = rows * lines
local size = 0.85 local size = 0.85
fs("bg9", data.inv_width + 0.1, 0, 7.9, full_height, PNG.bg_full, 10) bg9(data.inv_width + 0.1, 0, 7.9, full_height, PNG.bg_full, 10)
fs(fmt("box[%f,0.2;4.05,0.6;#bababa25]", data.inv_width + 0.3), if data.enable_search then
"set_focus[filter]", fs("set_focus[filter]",
fmt("field[%f,0.2;2.95,0.6;filter;;%s]", data.inv_width + 0.35, ESC(data.filter)), "style[filter;font_size=18;textcolor=#ccc]",
"field_close_on_enter[filter;false]") fmt("field[%f,0.2;3.35,0.6;filter;;%s]", data.inv_width + 0.85, ESC(data.filter)),
"field_close_on_enter[filter;false]")
else
fs"style_type[label;font=italic;font_size=18]"
label(data.inv_width + 0.9, 0.49, clr("#aaa", ES"Search..."))
button(data.inv_width + 0.8, 0.1, 4, 0.8, "enable_search", "")
end
fs("image_button", data.inv_width + 3.35, 0.35, 0.3, 0.3, "", "cancel", "") image_button(data.inv_width + 0.35, 0.32, 0.35, 0.35, "", "search", "")
fs("image_button", data.inv_width + 3.85, 0.32, 0.35, 0.35, "", "search", "") image_button(data.inv_width + 5.27, 0.3, 0.35, 0.35, "", "prev_page", "")
fs("image_button", data.inv_width + 5.27, 0.3, 0.35, 0.35, "", "prev_page", "") image_button(data.inv_width + 7.45, 0.3, 0.35, 0.35, "", "next_page", "")
fs("image_button", data.inv_width + 7.45, 0.3, 0.35, 0.35, "", "next_page", "")
fs(fmt("tooltip[search;%s]", ES"Search"))
if true_str(data.filter) then
image_button(data.inv_width + 4.3, 0.4, 0.2, 0.2, "", "cancel", "")
fs(fmt("tooltip[cancel;%s]", ES"Clear"))
box(data.inv_width + 0.85, 0.75, 3.74, 0.01, "#f9826c")
end
data.pagemax = max(1, ceil(#items / ipp)) data.pagemax = max(1, ceil(#items / ipp))
fs("button", data.inv_width + 5.6, 0.14, 1.88, 0.7, "pagenum", button(data.inv_width + 5.6, 0.14, 1.88, 0.7, "pagenum",
fmt("%s / %u", clr(colors.yellow, data.pagenum), data.pagemax)) fmt("%s / %u", clr(colors.yellow, data.pagenum), data.pagemax))
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
if next(i3.recipe_filters) and #i3.init_items > 0 and data.filter == "" then if next(i3.recipe_filters) and #i3.init_items > 0 and data.filter == "" then
lbl = ES"Collect items to reveal more recipes" lbl = ES"Collect items to reveal more recipes" -- Progressive mode, etc.
icon, width, offset = PNG.find_more, 2.5, 2.75
end end
fs("button", data.inv_width + 0.1, 3, 8, 1, "no_item", lbl) image(data.inv_width + offset, 3.5, width, width, icon)
button(data.inv_width + 0.1, 7, 8, 1, "no_item", lbl)
else else
local first_item = (data.pagenum - 1) * ipp local first_item = (data.pagenum - 1) * ipp
@ -1348,7 +1379,7 @@ local function get_items_fs(fs, data, player, full_height)
X -= (X * 0.045) + data.inv_width + 0.28 X -= (X * 0.045) + data.inv_width + 0.28
local Y = round((i % ipp - X) / rows + 1, 0) local Y = round((i % ipp - X) / rows + 1, 0)
Y -= (Y * 0.085) + 0.95 Y -= (Y * 0.085) + 0.92
insert(fs, fmt("item_image_button", X, Y, size, size, name, item, "")) insert(fs, fmt("item_image_button", X, Y, size, size, name, item, ""))
@ -1357,7 +1388,7 @@ local function get_items_fs(fs, data, player, full_height)
fs(fmt("tooltip[%s;%s]", item, expand and ES"Click to hide" or ES"Click to expand")) fs(fmt("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]"
fs("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]"
end end
end end
@ -1374,25 +1405,25 @@ local function get_items_fs(fs, data, player, full_height)
PNG.tab_small_hover, selected and "#fff" or "#ddd")) PNG.tab_small_hover, selected and "#fff" or "#ddd"))
fs"style_type[image_button:hovered;textcolor=#fff]" fs"style_type[image_button:hovered;textcolor=#fff]"
fs("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)
end end
end end
local function get_favs(fs, data) local function get_favs(fs, data)
local btn_size = i3.settings.item_btn_size local btn_size = i3.settings.item_btn_size
fs("label", data.inv_width + 0.4, data.yoffset + 0.4, ES"Bookmarks") label(data.inv_width + 0.4, data.yoffset + 0.4, ES"Bookmarks")
for i = 1, #data.favs do for i, item in ipairs(data.favs) do
local item = data.favs[i] local name = fmt("_%s", item)
local X = data.inv_width - 0.7 + (i * 1.2) local X = data.inv_width - 0.7 + (i * 1.2)
local Y = data.yoffset + 0.8 local Y = data.yoffset + 0.8
if data.query_item == item then if data.query_item == item then
fs("image", X, Y, btn_size, btn_size, PNG.slot) image(X, Y, btn_size, btn_size, PNG.slot)
end end
fs("item_image_button", X, Y, btn_size, btn_size, item, item, "") item_image_button(X, Y, btn_size, btn_size, item, name, "")
end end
end end
@ -1409,7 +1440,7 @@ local function get_panels(fs, data, player)
data.yoffset += panels[i - 1].height + 0.1 data.yoffset += panels[i - 1].height + 0.1
end end
fs("bg9", data.inv_width + 0.1, data.yoffset, 7.9, panel.height, PNG.bg_full, 10) bg9(data.inv_width + 0.1, data.yoffset, 7.9, panel.height, PNG.bg_full, 10)
local is_recipe, is_usage = panel.name == "recipes", panel.name == "usages" local is_recipe, is_usage = panel.name == "recipes", panel.name == "usages"
panel.func(fs, data, player, panel, is_recipe, is_usage) panel.func(fs, data, player, panel, is_recipe, is_usage)
@ -1451,13 +1482,14 @@ local function get_tabs_fs(fs, player, data, full_height)
local Y = btm and full_height or -tab_hgh local Y = btm and full_height or -tab_hgh
fs"style_type[image_button:hovered;textcolor=#fff]" fs"style_type[image_button:hovered;textcolor=#fff]"
fs("image_button", X, Y, tab_len, tab_hgh, "", fmt("tab_%s", def.name), ESC(def.description)) image_button(X, Y, tab_len, tab_hgh, "", fmt("tab_%s", def.name), ESC(def.description))
if true_str(def.image) then if true_str(def.image) then
local desc = translate(data.lang_code, def.description) local desc = translate(data.lang_code, def.description)
local desc_len = utf8_len(desc)
fs("style_type[image;noclip=true]") fs("style_type[image;noclip=true]")
fs("image", X + (tab_len / 2) - ((#desc * 0.1) / 2) - 0.55, image(X + (tab_len / 2) - ((desc_len * 0.1) / 2) - 0.55, Y + 0.05, 0.35, 0.35, def.image)
Y + 0.05, 0.35, 0.35, fmt("%s^\\[resize:16x16", def.image))
end end
c++ c++
@ -1466,28 +1498,28 @@ end
local function get_debug_grid(data, fs, full_height) local function get_debug_grid(data, fs, full_height)
fs"style[hide_debug_grid;noclip=true]" fs"style[hide_debug_grid;noclip=true]"
fs("button", -2, full_height - 1, 2, 1, "hide_debug_grid", "Toggle grid") button(-2, full_height - 1, 2, 1, "hide_debug_grid", "Toggle grid")
if data.hide_debug_grid then return end if data.hide_debug_grid then return end
fs("style_type[label;font_size=8;noclip=true]") fs("style_type[label;font_size=8;noclip=true]")
local spacing, i = 0.2, 1 local spacing, i = 0.2, 1
for x = 0, data.inv_width + 8, spacing do for x = 0, data.inv_width + 8, spacing do
fs("box", x, 0, 0.01, full_height, "#ff0") box(x, 0, 0.01, full_height, "#ff0")
fs("label", x, full_height + 0.1, tostring(i)) label(x, full_height + 0.1, tostring(i))
i++ i++
end end
i = 61 i = 61
for y = 0, full_height, spacing do for y = 0, full_height, spacing do
fs("box", 0, y, data.inv_width + 8, 0.01, "#ff0") box(0, y, data.inv_width + 8, 0.01, "#ff0")
fs("label", -0.15, y, tostring(i)) label(-0.15, y, tostring(i))
i -= 1 i -= 1
end end
fs("box", data.inv_width / 2, 0, 0.01, full_height, "#f00") box(data.inv_width / 2, 0, 0.01, full_height, "#f00")
fs("box", 0, full_height / 2, data.inv_width, 0.01, "#f00") box(0, full_height / 2, data.inv_width, 0.01, "#f00")
fs"style_type[label;font_size=16]" fs"style_type[label;font_size=16]"
end end
@ -1513,7 +1545,7 @@ local function make_fs(player, data)
fs(fmt("formspec_version[%u]size[%f,%f]no_prepend[]bgcolor[#0000]", fs(fmt("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), styles)
fs("bg9", 0, 0, data.inv_width, full_height, PNG.bg_full, 10) bg9(0, 0, data.inv_width, full_height, PNG.bg_full, 10)
local tab = i3.tabs[data.tab] local tab = i3.tabs[data.tab]
@ -1527,11 +1559,11 @@ local function make_fs(player, data)
get_items_fs(fs, data, player, full_height) get_items_fs(fs, data, player, full_height)
end end
local visible_tabs = 1 local visible_tabs = #i3.tabs
for _, def in ipairs(i3.tabs) do for _, def in ipairs(i3.tabs) do
if visible_tabs < 2 and def.access and def.access(player, data) then if def.access and not def.access(player, data) then
visible_tabs++ visible_tabs -= 1
end end
end end

View File

@ -3,6 +3,8 @@
local fmt, split = string.format, string.split local fmt, split = string.format, string.split
local var = "[%w%.%[%]\"\'_]" local var = "[%w%.%[%]\"\'_]"
local modpath = core.get_modpath"i3"
local _,_, fs_elements = dofile(modpath .. "/src/styles.lua")
local operators = { local operators = {
["([%+%-%*%^/&|])="] = function(a, b, c) ["([%+%-%*%^/&|])="] = function(a, b, c)
@ -43,6 +45,16 @@ local function compile(data)
return "local " .. a:gsub("\"", "") .. " = i3.get(" .. a .. ")" return "local " .. a:gsub("\"", "") .. " = i3.get(" .. a .. ")"
end) end)
data = data:gsub("([%w_]+)%(", function(a)
if fs_elements[a] then
return fmt("fs('%s',", a)
end
end)
data = data:gsub("([%w_]+)-%-\n", function(a)
return fmt("%s = %s - 1", a, a)
end)
for op, func in pairs(operators) do for op, func in pairs(operators) do
data = data:gsub("(" .. var .. "+)%s?" .. op .. "%s?(" .. var .. "*)", func) data = data:gsub("(" .. var .. "+)%s?" .. op .. "%s?(" .. var .. "*)", func)
end end

View File

@ -32,7 +32,9 @@ local function item_in_inv(item, inv_items)
local inv_items_size = #inv_items local inv_items_size = #inv_items
if is_group(item) then if is_group(item) then
local groups = extract_groups(item) local groupname = item:sub(7)
local group_cache = i3.groups[groupname]
local groups = group_cache and group_cache.groups or extract_groups(item)
for i = 1, inv_items_size do for i = 1, inv_items_size do
local def = core.registered_items[inv_items[i]] local def = core.registered_items[inv_items[i]]
@ -89,6 +91,10 @@ local item_lists = {"main", "craft", "craftpreview"}
local function get_inv_items(player) local function get_inv_items(player)
local inv = player:get_inventory() local inv = player:get_inventory()
if not inv then
return {}
end
local stacks = {} local stacks = {}
for i = 1, #item_lists do for i = 1, #item_lists do

View File

@ -42,6 +42,8 @@ local PNG = {
home = "i3_home.png", home = "i3_home.png",
flag = "i3_flag.png", flag = "i3_flag.png",
edit = "i3_edit.png", edit = "i3_edit.png",
no_result = "i3_no_result.png",
find_more = "i3_find_more.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",
@ -77,9 +79,9 @@ local styles = string.format([[
style[;sound=] style[;sound=]
style[nofav;sound=i3_cannot] style[nofav;sound=i3_cannot]
style[pagenum,no_item,no_rcp;font=bold;font_size=18] style[pagenum,no_item,no_rcp;font=bold;font_size=18]
style[search;fgimg=%s;content_offset=0]
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[search;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]
style[next_page,next_recipe,next_usage,next_sort,next_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[waypoint_add;fgimg=%s;fgimg_hovered=%s;content_offset=0]
@ -94,9 +96,9 @@ local styles = string.format([[
style[confirm_trash_yes;sound=i3_trash] style[confirm_trash_yes;sound=i3_trash]
]], ]],
PNG.slot, PNG.slot,
PNG.search_hover,
PNG.exit, PNG.exit_hover, PNG.exit, PNG.exit_hover,
PNG.cancel, PNG.cancel_hover, PNG.cancel, PNG.cancel_hover,
PNG.search, PNG.search_hover,
PNG.prev, PNG.prev_hover, PNG.prev, PNG.prev_hover,
PNG.next, PNG.next_hover, PNG.next, PNG.next_hover,
PNG.add, PNG.add_hover, PNG.add, PNG.add_hover,

BIN
textures/i3_find_more.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
textures/i3_no_result.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -1,6 +1,7 @@
local exec = os.execute local exec = os.execute
local fmt, find, sub = string.format, string.find, string.sub local fmt, find, sub = string.format, string.find, string.sub
local var = "[%w%.%[%]\"\'_]" local var = "[%w%.%[%]\"\'_]"
local _,_, fs_elements = dofile("../src/styles.lua")
exec "clear" exec "clear"
@ -34,7 +35,7 @@ local files = {
"caches", "caches",
"callbacks", "callbacks",
"common", "common",
"compress", "compression",
"detached_inv", "detached_inv",
"fields", "fields",
"groups", "groups",
@ -84,6 +85,16 @@ local function compile(data)
return "local " .. a:gsub("\"", "") .. " = i3.get(" .. a .. ")" return "local " .. a:gsub("\"", "") .. " = i3.get(" .. a .. ")"
end) end)
data = data:gsub("([%w_]+)%(", function(a)
if fs_elements[a] then
return fmt("fs('%s',", a)
end
end)
data = data:gsub("([%w_]+)-%-\n", function(a)
return fmt("%s = %s - 1", a, a)
end)
for op, func in pairs(operators) do for op, func in pairs(operators) do
data = data:gsub("(" .. var .. "+)%s?" .. op .. "%s?(" .. var .. "*)", func) data = data:gsub("(" .. var .. "+)%s?" .. op .. "%s?(" .. var .. "*)", func)
end end
@ -116,7 +127,7 @@ for _, p in ipairs(files) do
end end
end end
local _file = io.open(path:match("(.*)%.") .. ".l", "w") local _file = io.open(path:match("(.*)%.") .. ".lc", "w")
_file:write(data) _file:write(data)
_file:close() _file:close()
end end
@ -125,6 +136,6 @@ for _, p in ipairs(files) do
end end
exec "luacheck ../init.lua" exec "luacheck ../init.lua"
exec "luacheck ../src/operators.lua" exec "luacheck ../src/preprocessor.lua"
exec "luacheck ../src/*.l" exec "luacheck ../src/*.lc"
exec "rm ../src/*.l" exec "rm ../src/*.lc"