Compare commits

...

30 Commits
1.5.6 ... 1.7.1

Author SHA1 Message Date
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
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
15 changed files with 831 additions and 685 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

@ -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,57 @@ 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 def.drawtype and 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
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 +227,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 +288,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 +330,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

@ -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 = {}

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,447 +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 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.skins then if fields.drop_items then
local id = tonumber(fields.skins) local items = split(fields.drop_items, ",")
local _skins = skins.get_skinlist_for_player(name) data.drop_items = items
skins.set_player_skin(player, _skins[id]) end
end
for field in pairs(fields) do
if fields.drop_items then if sub(field, 1, 4) == "btn_" then
local items = split(fields.drop_items, ",") data.subcat = indexof(i3.categories, sub(field, 5))
data.drop_items = items break
end
elseif sub(field, 1, 3) == "cb_" then
for field in pairs(fields) do local str = sub(field, 4)
if sub(field, 1, 4) == "btn_" then data[str] = false
data.subcat = indexof(i3.categories, sub(field, 5))
break if fields[field] == "true" then
data[str] = true
elseif sub(field, 1, 3) == "cb_" then end
local str = sub(field, 4)
data[str] = false elseif sub(field, 1, 8) == "setting_" then
data.show_setting = match(field, "_(%w+)$")
if fields[field] == "true" then
data[str] = true elseif sub(field, 1, 9) == "skin_btn_" then
end local id = tonumber(field:match("%d+"))
local _skins = skins.get_skinlist_for_player(name)
elseif sub(field, 1, 8) == "setting_" then skins.set_player_skin(player, _skins[id])
data.show_setting = match(field, "_(%w+)$")
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, _f) local item
local item
for field in pairs(fields) do
for field in pairs(_f) 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_skin or fields.next_skin then
elseif fields.prev_recipe or fields.next_recipe then if data.skin_pagemax == 1 then return end
local num = data.rnum + (fields.prev_recipe and -1 or 1) data.skin_pagenum -= (fields.prev_skin and 1 or -1)
data.rnum = data.recipes[num] and num or (fields.prev_recipe and #data.recipes or 1)
data.export_rcp = nil if data.skin_pagenum > data.skin_pagemax then
data.scrbar_rcp = 1 data.skin_pagenum = 1
elseif data.skin_pagenum == 0 then
elseif fields.prev_usage or fields.next_usage then data.skin_pagenum = data.skin_pagemax
local num = data.unum + (fields.prev_usage and -1 or 1) end
data.unum = data.usages[num] and num or (fields.prev_usage and #data.usages or 1)
data.export_usg = nil elseif fields.prev_recipe or fields.next_recipe then
data.scrbar_usg = 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)
elseif fields.fav then data.export_rcp = nil
local fav = is_fav(data) data.scrbar_rcp = 1
if #data.favs < i3.settings.max_favs and not fav then elseif fields.prev_usage or fields.next_usage then
insert(data.favs, data.query_item) local num = data.unum + (fields.prev_usage and -1 or 1)
elseif fav then data.unum = data.usages[num] and num or (fields.prev_usage and #data.usages or 1)
remove(data.favs, fav) data.export_usg = nil
end data.scrbar_usg = 1
elseif fields.export_rcp or fields.export_usg then elseif fields.fav then
if fields.export_rcp then local fav = is_fav(data)
data.export_rcp = not data.export_rcp
if #data.favs < i3.settings.max_favs and not fav then
if not data.export_rcp then insert(data.favs, data.query_item)
data.scrbar_rcp = 1 elseif fav then
end remove(data.favs, fav)
else end
data.export_usg = not data.export_usg
elseif fields.export_rcp or fields.export_usg then
if not data.export_usg then if fields.export_rcp then
data.scrbar_usg = 1 data.export_rcp = not data.export_rcp
end
end if not data.export_rcp then
data.scrbar_rcp = 1
elseif (sb_rcp and sub(sb_rcp, 1, 3) == "CHG") or (sb_usg and sub(sb_usg, 1, 3) == "CHG") then end
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 = not data.export_usg
elseif fields.craft_rcp or fields.craft_usg then if not data.export_usg then
craft_stack(player, data, fields.craft_rcp) data.scrbar_usg = 1
end
if fields.craft_rcp then end
data.export_rcp = nil
data.scrbar_rcp = 1 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 = nil data.scrbar_usg = sb_usg and tonumber(match(sb_usg, "%d+"))
data.scrbar_usg = 1
end elseif fields.craft_rcp or fields.craft_usg then
else craft_stack(player, data, fields.craft_rcp)
select_item(player, data, fields)
end if fields.craft_rcp then
end data.export_rcp = nil
data.scrbar_rcp = 1
core.register_on_player_receive_fields(function(player, formname, fields) else
local name = player:get_player_name() data.export_usg = nil
data.scrbar_usg = 1
if formname == "i3_outdated" then end
return false, core.kick_player(name, else
S"Come back when your Minetest client is up-to-date (www.minetest.net).") select_item(player, data, fields)
elseif formname ~= "" then end
return false end
end
core.register_on_player_receive_fields(function(player, formname, fields)
-- No-op buttons local name = player:get_player_name()
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 if formname == "i3_outdated" then
fields.bg_content then return false, core.kick_player(name,
return false S"Come back when your Minetest client is up-to-date (www.minetest.net).")
end elseif formname ~= "" then
return false
--print(dump(fields)) end
local data = i3.data[name]
if not data then return end -- No-op buttons
if fields.player_name or fields.awards or fields.home_pos or fields.pagenum or
for f in pairs(fields) do fields.no_item or fields.no_rcp or fields.select_sorting or fields.sort_method or
if sub(f, 1, 4) == "tab_" then fields.bg_content then
local tabname = sub(f, 5) return false
i3.set_tab(player, tabname) end
break
elseif sub(f, 1, 5) == "itab_" then --print(dump(fields))
data.pagenum = 1 local data = i3.data[name]
data.itab = tonumber(f:sub(-1)) if not data then return end
sort_by_category(data)
break for f in pairs(fields) do
end if sub(f, 1, 4) == "tab_" then
end local tabname = sub(f, 5)
i3.set_tab(player, tabname)
rcp_fields(player, data, fields) break
elseif sub(f, 1, 5) == "itab_" then
local tab = i3.tabs[data.tab] data.pagenum = 1
data.itab = tonumber(f:sub(-1))
if tab and tab.fields then sort_by_category(data)
return true, tab.fields(player, data, fields) break
end end
end
return true, set_fs(player)
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"