Compare commits

..

31 Commits
1.5.5 ... 1.7

Author SHA1 Message Date
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
e1c0f106cc Fix Luacheck warnings on Ubuntu 22.04 2022-04-26 01:50:25 +02:00
46f1136bb7 Empty slots don't make click sound 2022-04-25 19:24:24 +02:00
e88921fe72 Fix crash 2022-04-25 16:00:49 +02:00
7e0feefc89 API doc: minor correction 2022-03-23 03:52:08 +01:00
44a6256589 Fix tab access on priv revoking 2022-03-21 03:55:22 +01:00
1dd742e887 HUD: minor tweak 2022-03-12 04:30:20 +01:00
518ed971ca Hide pagenum when only one page of skins 2022-03-01 12:15:28 +01:00
e9b8085fde Tweak quick crafting 2022-02-27 19:13:27 +01:00
6dc12390db Tweak sorting 2022-02-27 18:53:26 +01:00
44610b879e Skin selection UI overhaul 2022-02-26 02:09:53 +01:00
b0c9bcf3b9 Update screenshot 2022-02-21 01:02:57 +01:00
de70846d6c Smoother scrolling in skins category 2022-02-20 20:38:51 +01:00
8b6f50b387 Fix potential crash with skinssb 2022-02-20 18:57:52 +01:00
16 changed files with 832 additions and 687 deletions

4
API.md
View File

@ -17,9 +17,7 @@ i3.new_tab("stuff", {
-- Determine if the tab is visible by a player, `false` or `nil` hide the tab -- Determine if the tab is visible by a player, `false` or `nil` hide the tab
access = function(player, data) access = function(player, data)
local name = player:get_player_name() local name = player:get_player_name()
if name == "singleplayer" then return name == "singleplayer"
return false
end
end, end,
formspec = function(player, data, fs) formspec = function(player, data, fs)

View File

@ -53,4 +53,4 @@ Report bugs on the [**Bug Tracker**](https://github.com/minetest-mods/i3/issues)
**Video review on YouTube:** https://www.youtube.com/watch?v=Xd14BCdEZ3o **Video review on YouTube:** https://www.youtube.com/watch?v=Xd14BCdEZ3o
![Preview](https://user-images.githubusercontent.com/7883281/144105848-535b5e4f-a6fc-44d6-add1-e62a45d36f63.png) ![Preview](https://content.minetest.net/uploads/3abf3755de.png)

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

@ -167,6 +167,13 @@ function i3.set_fs(player)
sort_inventory(player, data) sort_inventory(player, data)
end end
for i, tab in ipairs(i3.tabs) do
if data.tab == i and tab.access and not tab.access(player, data) then
data.tab = 1
break
end
end
local fs = make_fs(player, data) local fs = make_fs(player, data)
player:set_inventory_formspec(fs) player:set_inventory_formspec(fs)
end end
@ -221,8 +228,8 @@ function i3.set_tab(player, tabname)
return return
end end
for i, def in ipairs(i3.tabs) do for i, tab in ipairs(i3.tabs) do
if def.name == tabname then if tab.name == tabname then
data.tab = i data.tab = i
return return
end end

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,55 @@ 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 c, px, lim = 0, 256, 10
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 is_cube(def.drawtype) then
texture = get_cube(tiles)
elseif texture then
texture = texture:gsub("%^", "\\^"):gsub(":", "\\:") .. "\\^[resize\\:150x150"
end
if texture then
sprite = sprite .. fmt(":0,%u=%s", c * px, texture)
c++
if c == lim then break end
end
end
sprite = sprite:gsub("WxH", px .. "x" .. px * c)
i3.groups[group].sprite = sprite
i3.groups[group].count = c
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 +225,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
@ -242,7 +286,7 @@ local function resolve_aliases(hash)
end end
end end
if newname ~= "" and i3.recipes_cache[oldname] and not hash[newname] then if newname ~= "" and i3.recipes_cache[oldname] and reg_items[newname] and not hash[newname] then
insert(i3.init_items, newname) insert(i3.init_items, newname)
end end
end end
@ -284,40 +328,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

@ -5,7 +5,7 @@ local init_detached = i3.files.detached()
local init_hud = i3.files.hud() local init_hud = i3.files.hud()
local set_fs = i3.set_fs local set_fs = i3.set_fs
IMPORT("slz", "min", "copy", "ItemStack") IMPORT("slz", "min", "insert", "copy", "ItemStack")
IMPORT("spawn_item", "reset_data", "get_detached_inv") IMPORT("spawn_item", "reset_data", "get_detached_inv")
core.register_on_player_hpchange(function(player, hpchange) core.register_on_player_hpchange(function(player, hpchange)
@ -134,6 +134,7 @@ local function init_data(player, info)
data.player_name = name data.player_name = name
data.filter = "" data.filter = ""
data.pagenum = 1 data.pagenum = 1
data.skin_pagenum = 1
data.items = i3.init_items data.items = i3.init_items
data.items_raw = i3.init_items data.items_raw = i3.init_items
data.favs = {} data.favs = {}
@ -175,7 +176,7 @@ local function save_data(player_name)
storage:set_string("data", slz(_data)) storage:set_string("data", slz(_data))
end end
core.register_on_joinplayer(function(player) insert(core.registered_on_joinplayers, 1, function(player)
local name = player:get_player_name() local name = player:get_player_name()
local info = core.get_player_information and core.get_player_information(name) local info = core.get_player_information and core.get_player_information(name)

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)
@ -101,7 +109,7 @@ local function search(data)
for i = 1, #data.items_raw do for i = 1, #data.items_raw do
local item = data.items_raw[i] local item = data.items_raw[i]
local def = reg_items[item] local def = reg_items[item]
local desc = lower(translate(data.lang_code, def and def.description)) or "" local desc = lower(translate(data.lang_code, def.description)) or ""
local search_in = fmt("%s %s", item, desc) local search_in = fmt("%s %s", item, desc)
local temp, j, to_add = {}, 1 local temp, j, to_add = {}, 1
@ -228,9 +236,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 +253,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 +409,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
@ -514,14 +547,17 @@ local function compress_items(list, start_i)
return new_inv return new_inv
end end
local function drop_items(player, inv, list, start_i, rej) local function drop_items(player, inv, list, start_i, rej, remove)
for i = start_i, #list do for i = start_i, #list do
local stack = list[i] local stack = list[i]
local name = stack:get_name() local name = stack:get_name()
for _, it in ipairs(rej) do for _, it in ipairs(rej) do
if name == it then if name == it then
spawn_item(player, stack) if not remove then
spawn_item(player, stack)
end
inv:set_stack("main", i, ItemStack("")) inv:set_stack("main", i, ItemStack(""))
end end
end end
@ -537,7 +573,7 @@ local function sort_inventory(player, data)
local start_i = data.ignore_hotbar and (i3.settings.hotbar_len + 1) or 1 local start_i = data.ignore_hotbar and (i3.settings.hotbar_len + 1) or 1
if true_table(data.drop_items) then if true_table(data.drop_items) then
list = drop_items(player, inv, list, start_i, data.drop_items) list = drop_items(player, inv, list, start_i, data.drop_items, true)
end end
if data.inv_compress then if data.inv_compress then
@ -589,7 +625,7 @@ local function add_hud_waypoint(player, name, pos, color)
return player:hud_add { return player:hud_add {
hud_elem_type = "waypoint", hud_elem_type = "waypoint",
name = name, name = name,
text = " m", text = "m",
world_pos = pos, world_pos = pos,
number = color, number = color,
z_index = -300, z_index = -300,
@ -630,6 +666,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,
@ -657,6 +694,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,

View File

@ -1,446 +1,456 @@
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 fields.skins then if sb_inv and sub(sb_inv, 1, 3) == "CHG" then
local id = tonumber(fields.skins) data.scrbar_inv = tonumber(match(sb_inv, "%d+"))
local _skins = skins.get_skinlist_for_player(name) return
skins.set_player_skin(player, _skins[id]) 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 find(field, "waypoint_%d+") then local id = tonumber(field:match("%d+"))
local id, action = match(field, "_(%d+)_(%w+)$") local _skins = skins.get_skinlist_for_player(name)
id = tonumber(id) skins.set_player_skin(player, _skins[id])
local waypoint = data.waypoints[id]
if not waypoint then return end elseif find(field, "waypoint_%d+") then
local id, action = match(field, "_(%d+)_(%w+)$")
if action == "see" then id = tonumber(id)
if data.waypoint_see and data.waypoint_see == id then local waypoint = data.waypoints[id]
data.waypoint_see = nil if not waypoint then return end
else
data.waypoint_see = id if action == "see" then
end if data.waypoint_see and data.waypoint_see == id then
data.waypoint_see = nil
elseif action == "delete" then else
player:hud_remove(waypoint.id) data.waypoint_see = id
remove(data.waypoints, id) end
elseif action == "teleport" then elseif action == "delete" then
local pos = str_to_pos(waypoint.pos) player:hud_remove(waypoint.id)
safe_teleport(player, pos) remove(data.waypoints, id)
msg(name, S("Teleported to: @1", waypoint.name))
elseif action == "teleport" then
elseif action == "refresh" then local pos = str_to_pos(waypoint.pos)
local color = random(0xffffff) safe_teleport(player, pos)
waypoint.color = color msg(name, S("Teleported to: @1", waypoint.name))
player:hud_change(waypoint.id, "number", color)
elseif action == "refresh" then
elseif action == "hide" then local color = random(0xffffff)
if waypoint.hide then waypoint.color = color
local new_id = add_hud_waypoint( player:hud_change(waypoint.id, "number", color)
player, waypoint.name, str_to_pos(waypoint.pos), waypoint.color)
elseif action == "hide" then
waypoint.id = new_id if waypoint.hide then
waypoint.hide = nil local new_id = add_hud_waypoint(
else player, waypoint.name, str_to_pos(waypoint.pos), waypoint.color)
player:hud_remove(waypoint.id)
waypoint.hide = true waypoint.id = new_id
end waypoint.hide = nil
end else
player:hud_remove(waypoint.id)
break waypoint.hide = true
end end
end end
if fields.quit then break
data.confirm_trash = nil end
data.show_settings = nil end
data.waypoint_see = nil
data.bag_rename = nil if fields.quit then
data.confirm_trash = nil
elseif fields.trash then data.show_settings = nil
data.show_settings = nil data.waypoint_see = nil
data.confirm_trash = true data.bag_rename = nil
elseif fields.settings then elseif fields.trash then
if not data.show_settings then data.show_settings = nil
data.confirm_trash = nil data.confirm_trash = true
data.show_settings = true
else elseif fields.settings then
data.show_settings = nil if not data.show_settings then
end data.confirm_trash = nil
data.show_settings = true
elseif fields.confirm_trash_yes or fields.confirm_trash_no then else
if fields.confirm_trash_yes then data.show_settings = nil
inv:set_list("main", {}) end
inv:set_list("craft", {})
end elseif fields.confirm_trash_yes or fields.confirm_trash_no then
if fields.confirm_trash_yes then
data.confirm_trash = nil inv:set_list("main", {})
inv:set_list("craft", {})
elseif fields.close_settings then end
data.show_settings = nil
data.confirm_trash = nil
elseif fields.close_preview then
data.waypoint_see = nil elseif fields.close_settings then
data.show_settings = nil
elseif fields.sort then
sort_inventory(player, data) elseif fields.close_preview then
data.waypoint_see = nil
elseif fields.prev_sort or fields.next_sort then
local idx = get_sorting_idx(data.sort) elseif fields.sort then
local tot = #i3.sorting_methods sort_inventory(player, data)
idx -= (fields.prev_sort and 1 or -1) elseif fields.prev_sort or fields.next_sort then
local idx = get_sorting_idx(data.sort)
if idx > tot then local tot = #i3.sorting_methods
idx = 1
elseif idx == 0 then idx -= (fields.prev_sort and 1 or -1)
idx = tot
end if idx > tot then
idx = 1
data.sort = i3.sorting_methods[idx].name elseif idx == 0 then
idx = tot
elseif fields.home then end
if not data.home then
return msg(name, "No home set") data.sort = i3.sorting_methods[idx].name
elseif not check_privs(name, {home = true}) then
return msg(name, "'home' privilege missing") elseif fields.home then
end if not data.home then
return msg(name, "No home set")
safe_teleport(player, str_to_pos(data.home)) elseif not check_privs(name, {home = true}) then
msg(name, S"Welcome back home!") return msg(name, "'home' privilege missing")
end
elseif fields.set_home then
data.home = pos_to_str(player:get_pos(), 1) safe_teleport(player, str_to_pos(data.home))
msg(name, S"Welcome back home!")
elseif fields.bag_rename then
data.bag_rename = true elseif fields.set_home then
data.home = pos_to_str(player:get_pos(), 1)
elseif fields.confirm_rename then
local bag = get_detached_inv("bag", name) elseif fields.bag_rename then
local bagstack = bag:get_stack("main", 1) data.bag_rename = true
local meta = bagstack:get_meta()
local desc = translate(data.lang_code, bagstack:get_description()) elseif fields.confirm_rename then
local fill = split(desc, "(")[2] local bag = get_detached_inv("bag", name)
local newname = fields.bag_newname:gsub("([%(%)])", "") local bagstack = bag:get_stack("main", 1)
newname = toupper(newname:trim()) local meta = bagstack:get_meta()
local desc = translate(data.lang_code, bagstack:get_description())
if fill then local fill = split(desc, "(")[2]
newname = fmt("%s (%s", newname, fill) local newname = fields.bag_newname:gsub("([%(%)])", "")
end newname = toupper(newname:trim())
meta:set_string("description", newname) if fill then
bag:set_stack("main", 1, bagstack) newname = fmt("%s (%s", newname, fill)
end
data.bag = bagstack:to_string()
data.bag_rename = nil meta:set_string("description", newname)
bag:set_stack("main", 1, bagstack)
elseif sb_inv and sub(sb_inv, 1, 3) == "CHG" then
data.scrbar_inv = tonumber(match(sb_inv, "%d+")) data.bag = bagstack:to_string()
return 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, _f) local function select_item(player, data, fields)
local item local item
for field in pairs(_f) 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.cancel then
reset_data(data) reset_data(data)
elseif fields.exit then elseif fields.exit then
data.query_item = nil data.query_item = nil
elseif fields.key_enter_field == "filter" or fields.search then elseif fields.key_enter_field == "filter" or fields.search then
if fields.filter == "" then if fields.filter == "" then
reset_data(data) reset_data(data)
return set_fs(player) return set_fs(player)
end end
local str = lower(fields.filter) local str = lower(fields.filter)
if data.filter == str then return end if data.filter == str then return end
data.filter = str data.filter = str
data.pagenum = 1 data.pagenum = 1
search(data) search(data)
if data.itab > 1 then if data.itab > 1 then
sort_by_category(data) sort_by_category(data)
end end
elseif fields.prev_page or fields.next_page then elseif fields.prev_page or fields.next_page then
if data.pagemax == 1 then return end if data.pagemax == 1 then return end
data.pagenum -= (fields.prev_page and 1 or -1) data.pagenum -= (fields.prev_page and 1 or -1)
if data.pagenum > data.pagemax then if data.pagenum > data.pagemax then
data.pagenum = 1 data.pagenum = 1
elseif data.pagenum == 0 then elseif data.pagenum == 0 then
data.pagenum = data.pagemax data.pagenum = data.pagemax
end end
elseif fields.prev_recipe or fields.next_recipe then elseif fields.prev_skin or fields.next_skin then
local num = data.rnum + (fields.prev_recipe and -1 or 1) if data.skin_pagemax == 1 then return end
data.rnum = data.recipes[num] and num or (fields.prev_recipe and #data.recipes or 1) data.skin_pagenum -= (fields.prev_skin and 1 or -1)
data.export_rcp = nil
data.scrbar_rcp = 1 if data.skin_pagenum > data.skin_pagemax then
data.skin_pagenum = 1
elseif fields.prev_usage or fields.next_usage then elseif data.skin_pagenum == 0 then
local num = data.unum + (fields.prev_usage and -1 or 1) data.skin_pagenum = data.skin_pagemax
data.unum = data.usages[num] and num or (fields.prev_usage and #data.usages or 1) end
data.export_usg = nil
data.scrbar_usg = 1 elseif fields.prev_recipe or fields.next_recipe then
local num = data.rnum + (fields.prev_recipe and -1 or 1)
elseif fields.fav then data.rnum = data.recipes[num] and num or (fields.prev_recipe and #data.recipes or 1)
local fav = is_fav(data) data.export_rcp = nil
data.scrbar_rcp = 1
if #data.favs < i3.settings.max_favs and not fav then
insert(data.favs, data.query_item) elseif fields.prev_usage or fields.next_usage then
elseif fav then local num = data.unum + (fields.prev_usage and -1 or 1)
remove(data.favs, fav) data.unum = data.usages[num] and num or (fields.prev_usage and #data.usages or 1)
end data.export_usg = nil
data.scrbar_usg = 1
elseif fields.export_rcp or fields.export_usg then
if fields.export_rcp then elseif fields.fav then
data.export_rcp = not data.export_rcp local fav = is_fav(data)
if not data.export_rcp then if #data.favs < i3.settings.max_favs and not fav then
data.scrbar_rcp = 1 insert(data.favs, data.query_item)
end elseif fav then
else remove(data.favs, fav)
data.export_usg = not data.export_usg end
if not data.export_usg then elseif fields.export_rcp or fields.export_usg then
data.scrbar_usg = 1 if fields.export_rcp then
end data.export_rcp = not data.export_rcp
end
if not data.export_rcp then
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+")) end
data.scrbar_usg = sb_usg and tonumber(match(sb_usg, "%d+")) else
data.export_usg = not data.export_usg
elseif fields.craft_rcp or fields.craft_usg then
craft_stack(player, data, fields.craft_rcp) if not data.export_usg then
data.scrbar_usg = 1
if fields.craft_rcp then end
data.export_rcp = nil end
data.scrbar_rcp = 1
else elseif (sb_rcp and sub(sb_rcp, 1, 3) == "CHG") or (sb_usg and sub(sb_usg, 1, 3) == "CHG") then
data.export_usg = nil data.scrbar_rcp = sb_rcp and tonumber(match(sb_rcp, "%d+"))
data.scrbar_usg = 1 data.scrbar_usg = sb_usg and tonumber(match(sb_usg, "%d+"))
end
else elseif fields.craft_rcp or fields.craft_usg then
select_item(player, data, fields) craft_stack(player, data, fields.craft_rcp)
end
end if fields.craft_rcp then
data.export_rcp = nil
core.register_on_player_receive_fields(function(player, formname, fields) data.scrbar_rcp = 1
local name = player:get_player_name() else
data.export_usg = nil
if formname == "i3_outdated" then data.scrbar_usg = 1
return false, core.kick_player(name, end
S"Come back when your Minetest client is up-to-date (www.minetest.net).") else
elseif formname ~= "" then select_item(player, data, fields)
return false end
end end
-- No-op buttons core.register_on_player_receive_fields(function(player, formname, fields)
if fields.player_name or fields.awards or fields.home_pos or fields.pagenum or local name = player:get_player_name()
fields.no_item or fields.no_rcp or fields.select_sorting or fields.sort_method or
fields.bg_content then if formname == "i3_outdated" then
return false return false, core.kick_player(name,
end S"Come back when your Minetest client is up-to-date (www.minetest.net).")
elseif formname ~= "" then
--print(dump(fields)) return false
local data = i3.data[name] end
if not data then return end
-- No-op buttons
for f in pairs(fields) do if fields.player_name or fields.awards or fields.home_pos or fields.pagenum or
if sub(f, 1, 4) == "tab_" then fields.no_item or fields.no_rcp or fields.select_sorting or fields.sort_method or
local tabname = sub(f, 5) fields.bg_content then
i3.set_tab(player, tabname) return false
break end
elseif sub(f, 1, 5) == "itab_" then
data.pagenum = 1 --print(dump(fields))
data.itab = tonumber(f:sub(-1)) local data = i3.data[name]
sort_by_category(data) if not data then return end
break
end for f in pairs(fields) do
end if sub(f, 1, 4) == "tab_" then
local tabname = sub(f, 5)
rcp_fields(player, data, fields) i3.set_tab(player, tabname)
break
local tab = i3.tabs[data.tab] elseif sub(f, 1, 5) == "itab_" then
data.pagenum = 1
if tab and tab.fields then data.itab = tonumber(f:sub(-1))
return true, tab.fields(player, data, fields) sort_by_category(data)
end break
end
return true, set_fs(player) end
end)
rcp_fields(player, data, fields)
return inv_fields
local tab = i3.tabs[data.tab]
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("S", "ES", "translate", "ItemStack", "toupper")
IMPORT("groups_to_items", "compression_active", "compressible") IMPORT("get_sorting_idx", "compression_active", "compressible")
IMPORT("true_str", "is_fav", "is_num", "get_group", "str_to_pos") IMPORT("get_bag_description", "get_detached_inv", "get_recipes")
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
@ -494,19 +495,44 @@ local function get_container(fs, data, player, yoffset, ctn_len, award_list, awa
local _skins = skins.get_skinlist_for_player(name) local _skins = skins.get_skinlist_for_player(name)
local skin_name = skins.get_player_skin(player).name local skin_name = skins.get_player_skin(player).name
local sks, id = {}, 1 local spp, add_y = 24, 0
for i, skin in ipairs(_skins) do if #_skins > spp then
if skin.name == skin_name then local btn_y = yextra + 0.75
id = i add_y += 0.6
end
insert(sks, skin.name) data.skin_pagemax = max(1, ceil(#_skins / spp))
image_button(1.5, btn_y, 0.35, 0.35, "", "prev_skin", "")
image_button(3.85, btn_y, 0.35, 0.35, "", "next_skin", "")
fs"style[skin_page;font=bold;font_size=18]"
button(1.85, btn_y - 0.23, 2, 0.8, "skin_page",
fmt("%s / %u", clr(colors.yellow, data.skin_pagenum), data.skin_pagemax))
end end
sks = concat(sks, ","):gsub(";", "") local first = (data.skin_pagenum - 1) * spp
fs("label", 0, yextra + 0.85, fmt("%s:", ES"Select a skin")) local last = first + spp - 1
fs(fmt("dropdown[0,%f;4,0.6;skins;%s;%u;true]", yextra + 1.1, sks, id))
for i = first, last do
local skin = _skins[i + 1]
if not skin then break end
local btn_name = fmt("skin_btn_%u", i + 1)
fs(fmt([[ style[%s;padding=10;
fgimg=%s;bgimg=%s;bgimg_hovered=i3_btn9_hovered.png;
bgimg_pressed=i3_btn9_pressed.png;bgimg_middle=4,6] ]],
btn_name, skin:get_preview(),
skin.name == skin_name and "i3_btn9_hovered.png" or "i3_btn9.png"))
local X = (i % 3) * 1.93
local Y = ceil((i % spp - X) / 3 + 1)
Y += (Y * 2.45) + yextra - 2.75 + add_y
image_button(X, Y, 1.86, 3.4, "", btn_name, "")
fs(fmt("tooltip[%s;%s]", btn_name, ESC(skin.name)))
end
elseif data.subcat == 4 then elseif data.subcat == 4 then
if not i3.modules.awards then if not i3.modules.awards then
@ -526,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"
@ -557,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"
@ -573,20 +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(fmt("style[prev_sort;fgimg=%s;fgimg_hovered=%s]", PNG.prev, PNG.prev_hover), image_button(2.2, 10.6, 0.35, 0.35, "", "prev_sort", "")
fmt("style[next_sort;fgimg=%s;fgimg_hovered=%s]", PNG.next, PNG.next_hover)) image_button(7.65, 10.6, 0.35, 0.35, "", "next_sort", "")
fs("image_button", 2.2, 10.6, 0.35, 0.35, "", "prev_sort", "")
fs("image_button", 7.65, 10.6, 0.35, 0.35, "", "next_sort", "")
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
@ -596,17 +619,17 @@ 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]",
fmt("field[5.4,10.68;2.4,0.45;drop_items;Drop items:;%s]", fmt("field[5.4,10.68;2.4,0.45;drop_items;Remove items:;%s]",
ESC(concat(data.drop_items or {}, ","))), ESC(concat(data.drop_items or {}, ","))),
"field_close_on_enter[drop_items;false]") "field_close_on_enter[drop_items;false]")
@ -619,7 +642,7 @@ local function show_popup(fs, data)
fmt("tooltip[cb_auto_sorting;%s;#707070;#fff]", fmt("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"),
fmt("tooltip[drop_items;%s;#707070;#fff]", fmt("tooltip[drop_items;%s;#707070;#fff]",
"Add a comma-separated list of items to drop on inventory sorting.\n" .. "Add a comma-separated list of items to remove on inventory sorting.\n" ..
"Format: " .. ("mod:item,mod:item, ..."):gsub("(%a+:%a+)", clr("#bddeff", "%1")))) "Format: " .. ("mod:item,mod:item, ..."):gsub("(%a+:%a+)", clr("#bddeff", "%1"))))
end end
end end
@ -645,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
@ -667,6 +690,14 @@ local function get_inventory_fs(player, data, fs)
max_val += 10 max_val += 10
elseif i3.modules.skins and data.subcat == 3 then
local spp = 24
local _skins = skins.get_skinlist_for_player(data.player_name)
local nb = #_skins
local num = max(1, min(spp, nb - ((data.skin_pagenum - 1) * spp)))
max_val += ceil(num / 3) * (nb > spp and 34 or 31)
elseif i3.modules.awards and data.subcat == 4 then elseif i3.modules.awards and data.subcat == 4 then
award_list = awards.get_award_states(data.player_name) award_list = awards.get_award_states(data.player_name)
award_list_nb = #award_list award_list_nb = #award_list
@ -712,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
@ -799,7 +830,7 @@ local function get_tooltip(item, info, pos)
return fmt("tooltip[%s;%s]", item, ESC(tooltip)) return fmt("tooltip[%s;%s]", item, ESC(tooltip))
end end
local function get_output_fs(fs, data, rcp, is_recipe, shapeless, right, btn_size, _btn_size) local function get_output_fs(fs, data, rcp, is_recipe, shapeless, right, btn_size, btn_size2)
local custom_recipe = i3.craft_types[rcp.type] local custom_recipe = i3.craft_types[rcp.type]
local cooking = rcp.type == "cooking" local cooking = rcp.type == "cooking"
local fuel = rcp.type == "fuel" local fuel = rcp.type == "fuel"
@ -808,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
@ -817,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
@ -831,19 +862,19 @@ 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
local BTN_SIZE = i3.settings.item_btn_size local BTN_SIZE = i3.settings.item_btn_size
local arrow_X = right + 0.2 + (_btn_size or BTN_SIZE) local arrow_X = right + 0.2 + (btn_size2 or BTN_SIZE)
local X = arrow_X + 1.2 local 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
@ -862,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, "")
@ -962,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 ""
@ -993,14 +1026,25 @@ 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)
item_image_button(X, Y, btn_size, btn_size, "", btn_name, "")
animated_image(X + 0.01, Y + 0.01, 1.89, 1.89, sprite, group_cache.count, 1000)
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
@ -1039,7 +1083,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
@ -1052,7 +1096,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
@ -1061,8 +1105,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)
@ -1109,7 +1153,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
@ -1124,16 +1168,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
@ -1145,19 +1189,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]
@ -1166,7 +1210,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
@ -1176,7 +1220,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
@ -1196,9 +1240,10 @@ local function get_export_fs(fs, data, is_recipe, is_usage, max_stacks_rcp, max_
fs(fmt("style[scrbar_%s;noclip=true]", name), fs(fmt("style[scrbar_%s;noclip=true]", name),
fmt("scrollbaroptions[min=1;max=%u;smallstep=1]", craft_max)) fmt("scrollbaroptions[min=1;max=%u;smallstep=1]", craft_max))
fs("scrollbar", data.inv_width + 8.1, data.yoffset, 3, 0.35, "horizontal", fmt("scrbar_%s", name), stack_fs)
fs("button", data.inv_width + 8.1, data.yoffset + 0.4, 3, 0.7, local x = data.inv_width + 8.1
fmt("craft_%s", name), ES("Craft (×@1)", stack_fs)) scrollbar(x, data.yoffset, 2.5, 0.35, "horizontal", fmt("scrbar_%s", name), 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)
@ -1234,7 +1279,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[]"
@ -1278,21 +1323,21 @@ 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), fs(fmt("box[%f,0.2;4.05,0.6;#bababa25]", data.inv_width + 0.3),
"set_focus[filter]", "set_focus[filter]",
fmt("field[%f,0.2;2.95,0.6;filter;;%s]", data.inv_width + 0.35, ESC(data.filter)), fmt("field[%f,0.2;2.95,0.6;filter;;%s]", data.inv_width + 0.35, ESC(data.filter)),
"field_close_on_enter[filter;false]") "field_close_on_enter[filter;false]")
fs("image_button", data.inv_width + 3.35, 0.35, 0.3, 0.3, "", "cancel", "") image_button(data.inv_width + 3.35, 0.35, 0.3, 0.3, "", "cancel", "")
fs("image_button", data.inv_width + 3.85, 0.32, 0.35, 0.35, "", "search", "") image_button(data.inv_width + 3.85, 0.32, 0.35, 0.35, "", "search", "")
fs("image_button", data.inv_width + 5.27, 0.3, 0.35, 0.35, "", "prev_page", "") image_button(data.inv_width + 5.27, 0.3, 0.35, 0.35, "", "prev_page", "")
fs("image_button", data.inv_width + 7.45, 0.3, 0.35, 0.35, "", "next_page", "") image_button(data.inv_width + 7.45, 0.3, 0.35, 0.35, "", "next_page", "")
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
@ -1302,7 +1347,7 @@ local function get_items_fs(fs, data, player, full_height)
lbl = ES"Collect items to reveal more recipes" lbl = ES"Collect items to reveal more recipes"
end end
fs("button", data.inv_width + 0.1, 3, 8, 1, "no_item", lbl) button(data.inv_width + 0.1, 3, 8, 1, "no_item", lbl)
else else
local first_item = (data.pagenum - 1) * ipp local first_item = (data.pagenum - 1) * ipp
@ -1326,7 +1371,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
@ -1343,25 +1388,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
@ -1378,7 +1423,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)
@ -1420,13 +1465,12 @@ 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)
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 * 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++
@ -1435,28 +1479,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
@ -1482,9 +1526,10 @@ 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]
if tab then if tab then
tab.formspec(player, data, fs) tab.formspec(player, data, fs)
end end
@ -1495,7 +1540,15 @@ local function make_fs(player, data)
get_items_fs(fs, data, player, full_height) get_items_fs(fs, data, player, full_height)
end end
if #i3.tabs > 1 then local visible_tabs = 1
for _, def in ipairs(i3.tabs) do
if visible_tabs < 2 and def.access and def.access(player, data) then
visible_tabs++
end
end
if visible_tabs > 1 then
get_tabs_fs(fs, player, data, full_height) get_tabs_fs(fs, player, data, full_height)
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

@ -74,17 +74,14 @@ local styles = string.format([[
style_type[image_button,item_image_button,checkbox,dropdown;border=false;sound=i3_click] style_type[image_button,item_image_button,checkbox,dropdown;border=false;sound=i3_click]
style_type[item_image_button;bgimg_hovered=%s] style_type[item_image_button;bgimg_hovered=%s]
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[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[search;fgimg=%s;fgimg_hovered=%s;content_offset=0]
style[prev_page;fgimg=%s;fgimg_hovered=%s] style[prev_page,prev_recipe,prev_usage,prev_sort,prev_skin;fgimg=%s;fgimg_hovered=%s]
style[next_page;fgimg=%s;fgimg_hovered=%s] style[next_page,next_recipe,next_usage,next_sort,next_skin;fgimg=%s;fgimg_hovered=%s]
style[prev_recipe;fgimg=%s;fgimg_hovered=%s]
style[next_recipe;fgimg=%s;fgimg_hovered=%s]
style[prev_usage;fgimg=%s;fgimg_hovered=%s]
style[next_usage;fgimg=%s;fgimg_hovered=%s]
style[waypoint_add;fgimg=%s;fgimg_hovered=%s;content_offset=0] style[waypoint_add;fgimg=%s;fgimg_hovered=%s;content_offset=0]
style[bag_rename;fgimg=%s;fgimg_hovered=%s;content_offset=0] style[bag_rename;fgimg=%s;fgimg_hovered=%s;content_offset=0]
style[btn_bag,btn_armor,btn_skins;font=bold;font_size=18;content_offset=0;sound=i3_click] style[btn_bag,btn_armor,btn_skins;font=bold;font_size=18;content_offset=0;sound=i3_click]
@ -102,10 +99,6 @@ PNG.cancel, PNG.cancel_hover,
PNG.search, PNG.search_hover, PNG.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.prev, PNG.prev_hover,
PNG.next, PNG.next_hover,
PNG.prev, PNG.prev_hover,
PNG.next, PNG.next_hover,
PNG.add, PNG.add_hover, PNG.add, PNG.add_hover,
PNG.edit, PNG.edit_hover) PNG.edit, PNG.edit_hover)

View File

@ -16,30 +16,18 @@ i3.new_tab("test2", {
end, end,
}) })
i3.new_tab("test3", { i3.new_tab("test_creative", {
description = "Test 3", description = "Test creative",
access = function(player, data) access = function(player, data)
local name = player:get_player_name() local name = player:get_player_name()
if name == "singleplayer" then return core.is_creative_enabled(name)
return true
end
end, end,
formspec = function(player, data, fs) formspec = function(player, data, fs)
fs("label[3,1;Test 3]") fs("label[3,1;Creative enabled]")
end, end,
fields = function(player, data, fields) fields = i3.set_fs,
i3.set_fs(player, "label[3,2;Test extra_fs]")
end,
}) })
i3.override_tab("test2", {
description = "Test override",
image = "i3_mesepick.png",
formspec = function(player, data, fs)
fs("label[3,1;Override!]")
end,
})

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"