Totally rework how bags work + other cool stuff
This commit is contained in:
parent
9cc8464111
commit
2e7dcd714d
9
API.md
9
API.md
|
@ -7,8 +7,7 @@
|
|||
Custom tabs can be added to the `i3` inventory as follow (example):
|
||||
|
||||
```Lua
|
||||
i3.new_tab {
|
||||
name = "stuff",
|
||||
i3.new_tab("stuff", {
|
||||
description = "Stuff",
|
||||
image = "image.png", -- Optional, adds an image next to the tab description
|
||||
|
||||
|
@ -28,16 +27,16 @@ i3.new_tab {
|
|||
fields = function(player, data, fields)
|
||||
|
||||
end,
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
- `player` is an `ObjectRef` to the user.
|
||||
- `data` are the user data.
|
||||
- `fs` is the formspec table which is callable with a metamethod. Each call adds a new entry.
|
||||
|
||||
#### `i3.set_fs(player[, extra_formspec])`
|
||||
#### `i3.set_fs(player)`
|
||||
|
||||
Updates the current formspec. `extra_formspec` adds an additional formspec string.
|
||||
Updates the current formspec.
|
||||
|
||||
#### `i3.remove_tab(tabname)`
|
||||
|
||||
|
|
18
README.md
18
README.md
|
@ -10,20 +10,20 @@ This mod features a modern, powerful inventory menu with a good user experience.
|
|||
This mod requires **Minetest 5.4+**
|
||||
|
||||
#### List of features:
|
||||
- Crafting Guide (only in survival mode)
|
||||
- Crafting Guide (survival mode only)
|
||||
- Progressive Mode¹
|
||||
- Quick Crafting
|
||||
- Backpacks
|
||||
- 3D Player Model Preview
|
||||
- Inventory Sorting (with optional compression)
|
||||
- 3D Player Model Real-Time Preview
|
||||
- Inventory Sorting (+ options: compression, reverse mode, automation, etc.)
|
||||
- Item List Compression (**`moreblocks`** is supported)
|
||||
- Item Bookmarks
|
||||
- Waypoints
|
||||
- Item List Compression (**`moreblocks`** is supported)
|
||||
- Bags
|
||||
- Home
|
||||
|
||||
**¹** *This mode is a Terraria-like system that shows recipes you can craft from items you ever had in your inventory.
|
||||
To enable it: `i3_progressive_mode = true` in `minetest.conf`.*
|
||||
|
||||
|
||||
#### This mod officially supports the following mods:
|
||||
- [**`3d_armor`**](https://content.minetest.net/packages/stu/3d_armor/)
|
||||
- [**`skinsdb`**](https://content.minetest.net/packages/bell07/skinsdb/)
|
||||
|
@ -46,12 +46,10 @@ value of the setting `display_density_factor` in your `minetest.conf`. Note that
|
|||
|
||||
`i3` uses a larger inventory than the usual inventories in Minetest games.
|
||||
Thus, most chests will be unadapted to this inventory size.
|
||||
The `i3` inventory is 9 slots wide by default (without backpack), such as Minecraft.
|
||||
The `i3` inventory is 9 slots wide by default, such as Minecraft.
|
||||
|
||||
Report any bug on the [**Bug Tracker**](https://github.com/minetest-mods/i3/issues).
|
||||
Report bugs on the [**Bug Tracker**](https://github.com/minetest-mods/i3/issues).
|
||||
|
||||
Love this mod? Donations are appreciated: https://www.paypal.me/jpg84240
|
||||
|
||||
Demo video (outdated): https://www.youtube.com/watch?v=25nCAaqeacU
|
||||
|
||||
![Preview](https://user-images.githubusercontent.com/7883281/140816791-693a5c8a-a7d1-47d4-a45d-883cc008ae8a.png)
|
||||
|
|
30
init.lua
30
init.lua
|
@ -15,13 +15,6 @@ i3 = {
|
|||
MIN_FORMSPEC_VERSION = 4,
|
||||
SAVE_INTERVAL = 600, -- Player data save interval (in seconds)
|
||||
|
||||
BAG_SIZES = {
|
||||
4*9 + 3,
|
||||
4*9 + 6,
|
||||
4*9 + 9,
|
||||
4*9 + 25,
|
||||
},
|
||||
|
||||
SUBCAT = {
|
||||
"bag",
|
||||
"armor",
|
||||
|
@ -36,7 +29,7 @@ i3 = {
|
|||
bag_size = true,
|
||||
waypoints = true,
|
||||
inv_items = true,
|
||||
reject_items = true,
|
||||
drop_items = true,
|
||||
known_recipes = true,
|
||||
},
|
||||
|
||||
|
@ -56,18 +49,19 @@ i3 = {
|
|||
files = {
|
||||
api = lf("/src/api.lua"),
|
||||
bags = lf("/src/bags.lua"),
|
||||
callbacks = lf("/src/callbacks.lua"),
|
||||
common = lf("/src/common.lua"),
|
||||
compress = lf("/src/compress.lua"),
|
||||
detached = lf("/src/detached_inv.lua"),
|
||||
groups = lf("/src/groups.lua"),
|
||||
gui = lf("/src/gui.lua"),
|
||||
inventory = lf("/src/inventory.lua"),
|
||||
model_alias = lf("/src/model_aliases.lua"),
|
||||
progressive = lf("/src/progressive.lua"),
|
||||
recipes = lf("/src/recipes.lua"),
|
||||
styles = lf("/src/styles.lua"),
|
||||
},
|
||||
|
||||
progressive_mode = core.settings:get_bool "i3_progressive_mode",
|
||||
progressive_mode = core.settings:get_bool"i3_progressive_mode",
|
||||
item_compression = core.settings:get_bool("i3_item_compression", true),
|
||||
}
|
||||
|
||||
|
@ -75,14 +69,16 @@ i3.files.common()
|
|||
i3.files.api()
|
||||
i3.files.compress()
|
||||
i3.files.groups()
|
||||
i3.files.inventory()
|
||||
i3.files.callbacks()
|
||||
|
||||
local storage = core.get_mod_storage()
|
||||
local slz, dslz, str_to_pos, add_hud_waypoint = i3.get("slz", "dslz", "str_to_pos", "add_hud_waypoint")
|
||||
local slz, dslz, ESC, str_to_pos, add_hud_waypoint =
|
||||
i3.get("slz", "dslz", "ESC", "str_to_pos", "add_hud_waypoint")
|
||||
|
||||
i3.data = dslz(storage:get_string "data") or {}
|
||||
|
||||
local init_backpack = i3.files.bags()
|
||||
local init_bags = i3.files.bags()
|
||||
local init_inventories = i3.files.detached()
|
||||
local init_recipes = i3.files.recipes()
|
||||
|
||||
local function get_lang_code(info)
|
||||
|
@ -146,6 +142,7 @@ local function init_data(player, info)
|
|||
i3.data[name] = i3.data[name] or {}
|
||||
local data = i3.data[name]
|
||||
|
||||
data.player_name = ESC(name)
|
||||
data.filter = ""
|
||||
data.pagenum = 1
|
||||
data.items = i3.init_items
|
||||
|
@ -165,6 +162,9 @@ local function init_data(player, info)
|
|||
data.lang_code = get_lang_code(info)
|
||||
data.fs_version = info.formspec_version
|
||||
|
||||
local inv = player:get_inventory()
|
||||
inv:set_size("main", i3.INV_SIZE)
|
||||
|
||||
core.after(0, i3.set_fs, player)
|
||||
end
|
||||
|
||||
|
@ -216,12 +216,12 @@ core.register_on_joinplayer(function(player)
|
|||
local info = core.get_player_information and core.get_player_information(name)
|
||||
|
||||
if not info or get_formspec_version(info) < i3.MIN_FORMSPEC_VERSION then
|
||||
i3.data[name] = nil
|
||||
return outdated(name)
|
||||
end
|
||||
|
||||
init_data(player, info)
|
||||
init_backpack(player)
|
||||
init_bags(player)
|
||||
init_inventories(player)
|
||||
init_waypoints(player)
|
||||
init_hudbar(player)
|
||||
end)
|
||||
|
|
Binary file not shown.
45
src/api.lua
45
src/api.lua
|
@ -161,7 +161,7 @@ function i3.get_recipes(item)
|
|||
}
|
||||
end
|
||||
|
||||
function i3.set_fs(player, _fs)
|
||||
function i3.set_fs(player)
|
||||
if not player or player.is_fake_player then return end
|
||||
local name = player:get_player_name()
|
||||
local data = i3.data[name]
|
||||
|
@ -171,32 +171,34 @@ function i3.set_fs(player, _fs)
|
|||
sort_inventory(player, data)
|
||||
end
|
||||
|
||||
local fs = fmt("%s%s", make_fs(player, data), _fs or "")
|
||||
local fs = make_fs(player, data)
|
||||
player:set_inventory_formspec(fs)
|
||||
end
|
||||
|
||||
function i3.new_tab(def)
|
||||
if not true_table(def) then
|
||||
return err "i3.new_tab: tab definition missing"
|
||||
elseif not true_str(def.name) then
|
||||
function i3.new_tab(name, def)
|
||||
if not true_str(name) then
|
||||
return err "i3.new_tab: tab name missing"
|
||||
elseif not true_table(def) then
|
||||
return err "i3.new_tab: tab definition missing"
|
||||
elseif not true_str(def.description) then
|
||||
return err "i3.new_tab: description missing"
|
||||
elseif #i3.tabs == 6 then
|
||||
return err(fmt("i3.new_tab: cannot add '%s' tab. Limit reached (6).", def.name))
|
||||
end
|
||||
|
||||
i3.tabs[#i3.tabs + 1] = def
|
||||
def.name = name
|
||||
insert(i3.tabs, def)
|
||||
end
|
||||
|
||||
function i3.remove_tab(tabname)
|
||||
if not true_str(tabname) then
|
||||
function i3.remove_tab(name)
|
||||
if not true_str(name) then
|
||||
return err "i3.remove_tab: tab name missing"
|
||||
end
|
||||
|
||||
for i, def in ipairs(i3.tabs) do
|
||||
if tabname == def.name then
|
||||
if name == def.name then
|
||||
remove(i3.tabs, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -217,32 +219,31 @@ function i3.set_tab(player, tabname)
|
|||
return
|
||||
end
|
||||
|
||||
local found
|
||||
|
||||
for i, def in ipairs(i3.tabs) do
|
||||
if not found and def.name == tabname then
|
||||
if def.name == tabname then
|
||||
data.tab = i
|
||||
found = true
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if not found then
|
||||
return err(fmt("i3.set_tab: tab name '%s' does not exist", tabname))
|
||||
end
|
||||
err(fmt("i3.set_tab: tab name '%s' does not exist", tabname))
|
||||
end
|
||||
|
||||
function i3.override_tab(tabname, newdef)
|
||||
if not true_table(newdef) then
|
||||
return err "i3.override_tab: tab definition missing"
|
||||
elseif not true_str(newdef.name) then
|
||||
function i3.override_tab(name, newdef)
|
||||
if not true_str(name) then
|
||||
return err "i3.override_tab: tab name missing"
|
||||
elseif not true_table(newdef) then
|
||||
return err "i3.override_tab: tab definition missing"
|
||||
elseif not true_str(newdef.description) then
|
||||
return err "i3.override_tab: description missing"
|
||||
end
|
||||
|
||||
newdef.name = name
|
||||
|
||||
for i, def in ipairs(i3.tabs) do
|
||||
if def.name == tabname then
|
||||
if def.name == name then
|
||||
i3.tabs[i] = newdef
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
176
src/bags.lua
176
src/bags.lua
|
@ -1,55 +1,161 @@
|
|||
local S, fmt, msg, spawn_item = i3.get("S", "fmt", "msg", "spawn_item")
|
||||
local S, ES, fmt, clr, msg, slz, dslz, play_sound, create_inventory =
|
||||
i3.get("S", "ES", "fmt", "clr", "msg", "slz", "dslz", "play_sound", "create_inventory")
|
||||
|
||||
local function init_backpack(player)
|
||||
local function get_content_inv(name)
|
||||
return core.get_inventory {
|
||||
type = "detached",
|
||||
name = fmt("i3_bag_content_%s", name)
|
||||
}
|
||||
end
|
||||
|
||||
local function get_content(content)
|
||||
local t = {}
|
||||
|
||||
for i, v in pairs(content) do
|
||||
local stack = ItemStack(v.name)
|
||||
local meta, wear = v.meta, v.wear
|
||||
|
||||
if meta then
|
||||
local m = stack:get_meta()
|
||||
m:from_table(meta)
|
||||
end
|
||||
|
||||
if wear then
|
||||
stack:set_wear(wear)
|
||||
end
|
||||
|
||||
t[i] = stack
|
||||
end
|
||||
|
||||
return t
|
||||
end
|
||||
|
||||
local function safe_format(stack)
|
||||
local meta = stack:get_meta():to_table()
|
||||
local wear = stack:get_wear()
|
||||
local has_meta = next(meta.fields)
|
||||
|
||||
local info = {}
|
||||
info.name = fmt("%s %u", stack:get_name(), stack:get_count())
|
||||
|
||||
if has_meta then
|
||||
info.meta = meta
|
||||
end
|
||||
|
||||
if wear > 0 then
|
||||
info.wear = wear
|
||||
end
|
||||
|
||||
return info
|
||||
end
|
||||
|
||||
local function init_bags(player)
|
||||
local name = player:get_player_name()
|
||||
local data = i3.data[name]
|
||||
local inv = player:get_inventory()
|
||||
|
||||
inv:set_size("main", data.bag_size and i3.BAG_SIZES[data.bag_size] or i3.INV_SIZE)
|
||||
local bag = create_inventory(fmt("i3_bag_%s", name), {
|
||||
allow_put = function(inv, _, _, stack)
|
||||
local empty = inv:is_empty"main"
|
||||
local item_group = core.get_item_group(stack:get_name(), "bag")
|
||||
|
||||
data.bag = core.create_detached_inventory(fmt("%s_backpack", name), {
|
||||
allow_put = function(_inv, listname, _, stack)
|
||||
local empty = _inv:get_stack(listname, 1):is_empty()
|
||||
local item_group = minetest.get_item_group(stack:get_name(), "bag")
|
||||
|
||||
if empty and item_group > 0 and item_group <= #i3.BAG_SIZES then
|
||||
if empty and item_group > 0 and item_group <= 4 then
|
||||
return 1
|
||||
end
|
||||
|
||||
msg(name, S"This is not a backpack")
|
||||
return 0
|
||||
if not empty then
|
||||
msg(name, S"There is already a bag")
|
||||
else
|
||||
msg(name, S"This is not a bag")
|
||||
end
|
||||
|
||||
return 0, play_sound(name, "i3_cannot", 0.8)
|
||||
end,
|
||||
|
||||
on_put = function(_, _, _, stack)
|
||||
local stackname = stack:get_name()
|
||||
data.bag_item = stackname
|
||||
data.bag_size = minetest.get_item_group(stackname, "bag")
|
||||
data.bag_item = safe_format(stack)
|
||||
data.bag_size = core.get_item_group(stack:get_name(), "bag")
|
||||
|
||||
local meta = stack:get_meta()
|
||||
local content = dslz(meta:get_string"content")
|
||||
|
||||
if content then
|
||||
local inv = get_content_inv(name)
|
||||
inv:set_list("main", get_content(content))
|
||||
end
|
||||
|
||||
inv:set_size("main", i3.BAG_SIZES[data.bag_size])
|
||||
i3.set_fs(player)
|
||||
end,
|
||||
|
||||
on_take = function()
|
||||
for i = i3.INV_SIZE + 1, i3.BAG_SIZES[data.bag_size] do
|
||||
local stack = inv:get_stack("main", i)
|
||||
|
||||
if not stack:is_empty() then
|
||||
spawn_item(player, stack)
|
||||
end
|
||||
end
|
||||
|
||||
data.bag_item = nil
|
||||
data.bag_size = nil
|
||||
|
||||
inv:set_size("main", i3.INV_SIZE)
|
||||
local content = get_content_inv(name)
|
||||
content:set_list("main", {})
|
||||
|
||||
i3.set_fs(player)
|
||||
end,
|
||||
})
|
||||
}, name)
|
||||
|
||||
data.bag:set_size("main", 1)
|
||||
bag:set_size("main", 1)
|
||||
|
||||
if data.bag_item then
|
||||
data.bag:set_stack("main", 1, data.bag_item)
|
||||
bag:set_list("main", get_content{data.bag_item})
|
||||
end
|
||||
|
||||
local function save_content(inv)
|
||||
local bagstack = bag:get_stack("main", 1)
|
||||
local meta = bagstack:get_meta()
|
||||
|
||||
if inv:is_empty("main") then
|
||||
meta:set_string("description", "")
|
||||
meta:set_string("content", "")
|
||||
else
|
||||
local list = inv:get_list"main"
|
||||
local t = {}
|
||||
|
||||
for i = 1, #list do
|
||||
local stack = list[i]
|
||||
|
||||
if not stack:is_empty() then
|
||||
t[i] = safe_format(stack)
|
||||
end
|
||||
end
|
||||
|
||||
local function count_items()
|
||||
local c = 0
|
||||
|
||||
for _ in pairs(t) do
|
||||
c = c + 1
|
||||
end
|
||||
|
||||
return c
|
||||
end
|
||||
|
||||
meta:set_string("description", "")
|
||||
meta:set_string("description", ES("@1 (contains @2 / @3 stacks)",
|
||||
bagstack:get_short_description(), clr("#ff0", count_items()), data.bag_size * 4))
|
||||
meta:set_string("content", slz(t))
|
||||
end
|
||||
|
||||
bag:set_stack("main", 1, bagstack)
|
||||
data.bag_item = safe_format(bagstack)
|
||||
|
||||
i3.set_fs(player)
|
||||
end
|
||||
|
||||
local bag_content = create_inventory(fmt("i3_bag_content_%s", name), {
|
||||
on_move = save_content,
|
||||
on_put = save_content,
|
||||
on_take = save_content,
|
||||
}, name)
|
||||
|
||||
bag_content:set_size("main", 4*4)
|
||||
|
||||
if data.bag_item then
|
||||
local meta = bag:get_stack("main", 1):get_meta()
|
||||
local content = dslz(meta:get_string"content") or {}
|
||||
bag_content:set_list("main", get_content(content))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -60,21 +166,21 @@ local bag_recipes = {
|
|||
{"group:wool", "group:wool", "group:wool"},
|
||||
{"group:wool", "group:wool", "group:wool"},
|
||||
},
|
||||
size = 1,
|
||||
size = 2,
|
||||
},
|
||||
medium = {
|
||||
rcp = {
|
||||
{"farming:string", "i3:bag_small", "farming:string"},
|
||||
{"farming:string", "i3:bag_small", "farming:string"},
|
||||
},
|
||||
size = 2,
|
||||
size = 3,
|
||||
},
|
||||
large = {
|
||||
rcp = {
|
||||
{"farming:string", "i3:bag_medium", "farming:string"},
|
||||
{"farming:string", "i3:bag_medium", "farming:string"},
|
||||
},
|
||||
size = 3,
|
||||
size = 4,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -84,12 +190,12 @@ for size, item in pairs(bag_recipes) do
|
|||
core.register_craftitem(bagname, {
|
||||
description = fmt("%s Backpack", size:gsub("^%l", string.upper)),
|
||||
inventory_image = fmt("i3_bag_%s.png", size),
|
||||
groups = {bag = item.size},
|
||||
stack_max = 1,
|
||||
groups = {bag = item.size}
|
||||
})
|
||||
|
||||
core.register_craft {output = bagname, recipe = item.rcp}
|
||||
core.register_craft {type = "fuel", recipe = bagname, burntime = 3}
|
||||
core.register_craft{output = bagname, recipe = item.rcp}
|
||||
core.register_craft{type = "fuel", recipe = bagname, burntime = 3}
|
||||
end
|
||||
|
||||
return init_backpack
|
||||
return init_bags
|
||||
|
|
|
@ -1,20 +1,18 @@
|
|||
local _, get_inventory_fs = i3.files.gui()
|
||||
|
||||
local S, clr = i3.get("S", "clr")
|
||||
local min, ceil, random = i3.get("min", "ceil", "random")
|
||||
local min, random = i3.get("min", "random")
|
||||
local reg_items, reg_aliases = i3.get("reg_items", "reg_aliases")
|
||||
local fmt, find, match, sub, lower, split = i3.get("fmt", "find", "match", "sub", "lower", "split")
|
||||
local vec_new, vec_eq, vec_round = i3.get("vec_new", "vec_eq", "vec_round")
|
||||
local sort, copy, insert, remove, indexof = i3.get("sort", "copy", "insert", "remove", "indexof")
|
||||
|
||||
local is_group, extract_groups, groups_to_items =
|
||||
i3.get("is_group", "extract_groups", "groups_to_items")
|
||||
local msg, is_fav, pos_to_str, str_to_pos, add_hud_waypoint =
|
||||
i3.get("msg", "is_fav", "pos_to_str", "str_to_pos", "add_hud_waypoint")
|
||||
local msg, is_fav, pos_to_str, str_to_pos, add_hud_waypoint, play_sound =
|
||||
i3.get("msg", "is_fav", "pos_to_str", "str_to_pos", "add_hud_waypoint", "play_sound")
|
||||
local search, get_sorting_idx, sort_inventory, sort_by_category, get_recipes =
|
||||
i3.get("search", "get_sorting_idx", "sort_inventory", "sort_by_category", "get_recipes")
|
||||
local show_item, get_stack, clean_name, compressible, check_privs, safe_teleport =
|
||||
i3.get("show_item", "get_stack", "clean_name", "compressible", "check_privs", "safe_teleport")
|
||||
local show_item, get_stack, craft_stack, clean_name, compressible, check_privs, safe_teleport =
|
||||
i3.get("show_item", "get_stack", "craft_stack", "clean_name", "compressible", "check_privs", "safe_teleport")
|
||||
|
||||
local function reset_data(data)
|
||||
data.filter = ""
|
||||
|
@ -40,13 +38,12 @@ local function reset_data(data)
|
|||
end
|
||||
end
|
||||
|
||||
i3.new_tab {
|
||||
name = "inventory",
|
||||
i3.new_tab("inventory", {
|
||||
description = S"Inventory",
|
||||
formspec = get_inventory_fs,
|
||||
|
||||
fields = function(player, data, fields)
|
||||
local name = player:get_player_name()
|
||||
local name = data.player_name
|
||||
local inv = player:get_inventory()
|
||||
local sb_inv = fields.scrbar_inv
|
||||
|
||||
|
@ -56,9 +53,9 @@ i3.new_tab {
|
|||
skins.set_player_skin(player, _skins[id])
|
||||
end
|
||||
|
||||
if fields.reject_items then
|
||||
local items = split(fields.reject_items, ",")
|
||||
data.reject_items = items
|
||||
if fields.drop_items then
|
||||
local items = split(fields.drop_items, ",")
|
||||
data.drop_items = items
|
||||
end
|
||||
|
||||
for field in pairs(fields) do
|
||||
|
@ -176,6 +173,7 @@ i3.new_tab {
|
|||
|
||||
for _, v in ipairs(data.waypoints) do
|
||||
if vec_eq(vec_round(pos), vec_round(str_to_pos(v.pos))) then
|
||||
play_sound(name, "i3_cannot", 0.8)
|
||||
return msg(name, "You already set a waypoint at this position")
|
||||
end
|
||||
end
|
||||
|
@ -201,9 +199,9 @@ i3.new_tab {
|
|||
|
||||
return i3.set_fs(player)
|
||||
end,
|
||||
}
|
||||
})
|
||||
|
||||
local function select_item(player, name, data, _f)
|
||||
local function select_item(player, data, _f)
|
||||
local item
|
||||
|
||||
for field in pairs(_f) do
|
||||
|
@ -271,7 +269,7 @@ local function select_item(player, name, data, _f)
|
|||
item = reg_aliases[item] or item
|
||||
if not reg_items[item] then return end
|
||||
|
||||
if core.is_creative_enabled(name) then
|
||||
if core.is_creative_enabled(data.player_name) then
|
||||
local stack = ItemStack(item)
|
||||
local stackmax = stack:get_stack_max()
|
||||
stack = fmt("%s %s", item, stackmax)
|
||||
|
@ -294,55 +292,7 @@ local function select_item(player, name, data, _f)
|
|||
end
|
||||
end
|
||||
|
||||
local function craft_stack(player, data, craft_rcp)
|
||||
local inv = player:get_inventory()
|
||||
local rcp_usg = craft_rcp and "recipe" or "usage"
|
||||
local output = craft_rcp and data.recipes[data.rnum].output or data.usages[data.unum].output
|
||||
output = ItemStack(output)
|
||||
local stackname, stackcount, stackmax = output:get_name(), output:get_count(), output:get_stack_max()
|
||||
local scrbar_val = data[fmt("scrbar_%s", craft_rcp and "rcp" or "usg")] or 1
|
||||
|
||||
for name, count in pairs(data.export_counts[rcp_usg].rcp) do
|
||||
local items = {[name] = count}
|
||||
|
||||
if is_group(name) then
|
||||
items = {}
|
||||
local groups = extract_groups(name)
|
||||
local item_groups = groups_to_items(groups, true)
|
||||
local remaining = count
|
||||
|
||||
for _, item in ipairs(item_groups) do
|
||||
for _name, _count in pairs(data.export_counts[rcp_usg].inv) do
|
||||
if item == _name and remaining > 0 then
|
||||
local c = min(remaining, _count)
|
||||
items[item] = c
|
||||
remaining = remaining - c
|
||||
end
|
||||
|
||||
if remaining == 0 then break end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for k, v in pairs(items) do
|
||||
inv:remove_item("main", fmt("%s %s", k, v * scrbar_val))
|
||||
end
|
||||
end
|
||||
|
||||
local count = stackcount * scrbar_val
|
||||
local iter = ceil(count / stackmax)
|
||||
local leftover = count
|
||||
|
||||
for _ = 1, iter do
|
||||
local c = min(stackmax, leftover)
|
||||
local stack = ItemStack(fmt("%s %s", stackname, c))
|
||||
get_stack(player, stack)
|
||||
leftover = leftover - stackmax
|
||||
end
|
||||
end
|
||||
|
||||
local function rcp_fields(player, data, fields)
|
||||
local name = player:get_player_name()
|
||||
local sb_rcp, sb_usg = fields.scrbar_rcp, fields.scrbar_usg
|
||||
|
||||
if fields.cancel then
|
||||
|
@ -431,7 +381,7 @@ local function rcp_fields(player, data, fields)
|
|||
data.scrbar_usg = 1
|
||||
end
|
||||
else
|
||||
select_item(player, name, data, fields)
|
||||
select_item(player, data, fields)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -439,11 +389,12 @@ core.register_on_player_receive_fields(function(player, formname, fields)
|
|||
local name = player:get_player_name()
|
||||
|
||||
if formname == "i3_outdated" then
|
||||
return false, core.kick_player(name, "Come back when your client is up-to-date.")
|
||||
return false, core.kick_player(name, S"Come back when your client is up-to-date.")
|
||||
elseif formname ~= "" then
|
||||
return false
|
||||
end
|
||||
|
||||
--print(dump(fields))
|
||||
local data = i3.data[name]
|
||||
if not data then return end
|
||||
|
||||
|
@ -456,6 +407,7 @@ core.register_on_player_receive_fields(function(player, formname, fields)
|
|||
data.pagenum = 1
|
||||
data.itab = tonumber(f:sub(-1))
|
||||
sort_by_category(data)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -486,15 +438,6 @@ core.register_on_dieplayer(function(player)
|
|||
local data = i3.data[name]
|
||||
if not data then return end
|
||||
|
||||
if data.bag_size then
|
||||
data.bag_item = nil
|
||||
data.bag_size = nil
|
||||
data.bag:set_list("main", {})
|
||||
|
||||
local inv = player:get_inventory()
|
||||
inv:set_size("main", i3.INV_SIZE)
|
||||
end
|
||||
|
||||
i3.set_fs(player)
|
||||
end)
|
||||
|
||||
|
@ -524,27 +467,3 @@ core.register_on_player_inventory_action(function(player, _, _, info)
|
|||
i3.set_fs(player)
|
||||
end
|
||||
end)
|
||||
|
||||
local trash = core.create_detached_inventory("i3_trash", {
|
||||
allow_put = function(_, _, _, stack)
|
||||
return stack:get_count()
|
||||
end,
|
||||
on_put = function(inv, listname, _, _, player)
|
||||
inv:set_list(listname, {})
|
||||
|
||||
local name = player:get_player_name()
|
||||
core.sound_play("i3_trash", {to_player = name, gain = 1.0}, true)
|
||||
|
||||
if not core.is_creative_enabled(name) then
|
||||
i3.set_fs(player)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
trash:set_size("main", 1)
|
||||
|
||||
local output_rcp = core.create_detached_inventory("i3_output_rcp", {})
|
||||
output_rcp:set_size("main", 1)
|
||||
|
||||
local output_usg = core.create_detached_inventory("i3_output_usg", {})
|
||||
output_usg:set_size("main", 1)
|
|
@ -349,9 +349,60 @@ local function get_stack(player, stack)
|
|||
end
|
||||
end
|
||||
|
||||
local function craft_stack(player, data, craft_rcp)
|
||||
local inv = player:get_inventory()
|
||||
local rcp_usg = craft_rcp and "recipe" or "usage"
|
||||
local output = craft_rcp and data.recipes[data.rnum].output or data.usages[data.unum].output
|
||||
output = ItemStack(output)
|
||||
local stackname, stackcount, stackmax = output:get_name(), output:get_count(), output:get_stack_max()
|
||||
local scrbar_val = data[fmt("scrbar_%s", craft_rcp and "rcp" or "usg")] or 1
|
||||
|
||||
for name, count in pairs(data.export_counts[rcp_usg].rcp) do
|
||||
local items = {[name] = count}
|
||||
|
||||
if is_group(name) then
|
||||
items = {}
|
||||
local groups = extract_groups(name)
|
||||
local item_groups = groups_to_items(groups, true)
|
||||
local remaining = count
|
||||
|
||||
for _, item in ipairs(item_groups) do
|
||||
for _name, _count in pairs(data.export_counts[rcp_usg].inv) do
|
||||
if item == _name and remaining > 0 then
|
||||
local c = math.min(remaining, _count)
|
||||
items[item] = c
|
||||
remaining = remaining - c
|
||||
end
|
||||
|
||||
if remaining == 0 then break end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for k, v in pairs(items) do
|
||||
inv:remove_item("main", fmt("%s %s", k, v * scrbar_val))
|
||||
end
|
||||
end
|
||||
|
||||
local count = stackcount * scrbar_val
|
||||
local iter = math.ceil(count / stackmax)
|
||||
local leftover = count
|
||||
|
||||
for _ = 1, iter do
|
||||
local c = math.min(stackmax, leftover)
|
||||
local stack = ItemStack(fmt("%s %s", stackname, c))
|
||||
get_stack(player, stack)
|
||||
leftover = leftover - stackmax
|
||||
end
|
||||
end
|
||||
|
||||
local function play_sound(name, sound, volume)
|
||||
core.sound_play(sound, {to_player = name, gain = volume}, true)
|
||||
end
|
||||
|
||||
local function safe_teleport(player, pos)
|
||||
local name = player:get_player_name()
|
||||
core.sound_play("i3_teleport", {to_player = name, gain = 1.0}, true)
|
||||
play_sound(name, "i3_teleport", 1.0)
|
||||
|
||||
pos.y = pos.y + 0.5
|
||||
local vel = player:get_velocity()
|
||||
|
@ -446,7 +497,7 @@ local function compress_items(list, start_i)
|
|||
return new_inv
|
||||
end
|
||||
|
||||
local function reject_items(player, inv, list, start_i, rej)
|
||||
local function drop_items(player, inv, list, start_i, rej)
|
||||
for i = start_i, #list do
|
||||
local stack = list[i]
|
||||
local name = stack:get_name()
|
||||
|
@ -459,17 +510,17 @@ local function reject_items(player, inv, list, start_i, rej)
|
|||
end
|
||||
end
|
||||
|
||||
return inv:get_list("main")
|
||||
return inv:get_list"main"
|
||||
end
|
||||
|
||||
local function sort_inventory(player, data)
|
||||
local inv = player:get_inventory()
|
||||
local list = inv:get_list("main")
|
||||
local size = inv:get_size("main")
|
||||
local list = inv:get_list"main"
|
||||
local size = inv:get_size"main"
|
||||
local start_i = data.ignore_hotbar and 10 or 1
|
||||
|
||||
if true_table(data.reject_items) then
|
||||
list = reject_items(player, inv, list, start_i, data.reject_items)
|
||||
if true_table(data.drop_items) then
|
||||
list = drop_items(player, inv, list, start_i, data.drop_items)
|
||||
end
|
||||
|
||||
if data.inv_compress then
|
||||
|
@ -540,9 +591,11 @@ local _ = {
|
|||
|
||||
-- Misc. functions
|
||||
get_stack = get_stack,
|
||||
craft_stack = craft_stack,
|
||||
show_item = show_item,
|
||||
spawn_item = spawn_item,
|
||||
clean_name = clean_name,
|
||||
play_sound = play_sound,
|
||||
safe_teleport = safe_teleport,
|
||||
add_hud_waypoint = add_hud_waypoint,
|
||||
|
||||
|
@ -554,6 +607,7 @@ local _ = {
|
|||
pos_to_str = core.pos_to_string,
|
||||
str_to_pos = core.string_to_pos,
|
||||
check_privs = core.check_player_privs,
|
||||
create_inventory = core.create_detached_inventory,
|
||||
|
||||
-- Registered items
|
||||
reg_items = core.registered_items,
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
local fmt, play_sound, create_inventory = i3.get("fmt", "play_sound", "create_inventory")
|
||||
|
||||
local trash = create_inventory("i3_trash", {
|
||||
allow_put = function(_, _, _, stack)
|
||||
return stack:get_count()
|
||||
end,
|
||||
|
||||
on_put = function(inv, listname, _, _, player)
|
||||
inv:set_list(listname, {})
|
||||
|
||||
local name = player:get_player_name()
|
||||
play_sound(name, "i3_trash", 1.0)
|
||||
|
||||
if not core.is_creative_enabled(name) then
|
||||
i3.set_fs(player)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
trash:set_size("main", 1)
|
||||
|
||||
local function init_inventories(player)
|
||||
local name = player:get_player_name()
|
||||
|
||||
local output_rcp = create_inventory(fmt("i3_output_rcp_%s", name), {}, name)
|
||||
output_rcp:set_size("main", 1)
|
||||
|
||||
local output_usg = create_inventory(fmt("i3_output_usg_%s", name), {}, name)
|
||||
output_usg:set_size("main", 1)
|
||||
end
|
||||
|
||||
return init_inventories
|
91
src/gui.lua
91
src/gui.lua
|
@ -124,10 +124,8 @@ local function get_stack_max(inv, data, is_recipe, rcp)
|
|||
return max_stacks
|
||||
end
|
||||
|
||||
local function get_inv_slots(data, fs)
|
||||
local inv_x, inv_y = 0.22, 6.9
|
||||
local width, size, spacing = i3.HOTBAR_LEN, 1, 0.1
|
||||
local bag = data.bag_size
|
||||
local function get_inv_slots(fs)
|
||||
local inv_x, inv_y, size, spacing = 0.22, 6.9, 1, 0.1
|
||||
|
||||
fs("style_type[box;colors=#77777710,#77777710,#777,#777]")
|
||||
|
||||
|
@ -138,14 +136,9 @@ local function get_inv_slots(data, fs)
|
|||
fs(fmt("style_type[list;size=%f;spacing=%f]", size, spacing),
|
||||
fmt("list[current_player;main;%f,%f;%u,1;]", inv_x, inv_y, i3.HOTBAR_LEN))
|
||||
|
||||
if bag then
|
||||
local params = {{10, 0.892}, {11, 0.8}, {12, 0.726}, {13, 0.663}}
|
||||
width, size = unpack(params[bag])
|
||||
end
|
||||
|
||||
fs(fmt("style_type[list;size=%f;spacing=%f]", size, spacing),
|
||||
fmt("list[current_player;main;%f,%f;%u,%u;%u]", inv_x, inv_y + 1.15,
|
||||
width, (bag and i3.BAG_SIZES[data.bag_size] or i3.INV_SIZE) / width, i3.HOTBAR_LEN),
|
||||
i3.HOTBAR_LEN, i3.INV_SIZE / i3.HOTBAR_LEN, i3.HOTBAR_LEN),
|
||||
"style_type[list;size=1;spacing=0.15]")
|
||||
|
||||
fs("listring[current_player;craft]listring[current_player;main]")
|
||||
|
@ -294,8 +287,8 @@ local function get_waypoint_fs(fs, data, player, yextra, ctn_len)
|
|||
end
|
||||
|
||||
local function get_container(fs, data, player, yoffset, ctn_len, award_list, awards_unlocked, award_list_nb)
|
||||
local name = player:get_player_name()
|
||||
add_subtitle(fs, "player_name", 0, ctn_len, 22, true, ESC(name))
|
||||
local name = data.player_name
|
||||
add_subtitle(fs, "player_name", 0, ctn_len, 22, true, name)
|
||||
|
||||
if damage_enabled then
|
||||
local hp = data.hp or player:get_hp() or 20
|
||||
|
@ -342,20 +335,39 @@ local function get_container(fs, data, player, yoffset, ctn_len, award_list, awa
|
|||
|
||||
local function not_installed(modname)
|
||||
fs("hypertext", 0, yextra + 0.9, ctn_len, 0.6, "not_installed",
|
||||
fmt("<center><style color=#7bf font=mono>%s</style> not installed</center>", modname))
|
||||
fmt("<global size=16><center><style color=#7bf font=mono>%s</style> not installed</center>",
|
||||
modname))
|
||||
end
|
||||
|
||||
if data.subcat == 1 then
|
||||
fs(fmt("list[detached:%s_backpack;main;0,%f;1,1;]", ESC(name), yextra + 0.7))
|
||||
fs(fmt("list[detached:i3_bag_%s;main;0,%f;1,1;]", name, yextra + 0.7))
|
||||
|
||||
if not data.bag:get_stack("main", 1):is_empty() then
|
||||
fs("hypertext", 1.2, yextra + 0.89, ctn_len - 1.9, 0.8, "bpk",
|
||||
ES("The inventory is extended by @1 slots", i3.BAG_SIZES[data.bag_size] - i3.INV_SIZE))
|
||||
local inv = core.get_inventory {
|
||||
type = "detached",
|
||||
name = fmt("i3_bag_%s", data.player_name)
|
||||
}
|
||||
|
||||
if not inv:is_empty"main" then
|
||||
fs("image", 0.5, yextra + 1.85, 0.6, 0.6, PNG.arrow_content)
|
||||
fs(fmt("style[content;bgimg=%s;fgimg=i3_blank.png;bgimg_middle=10,10;sound=]", PNG.bg_content))
|
||||
fs("image_button", 1.1, yextra + 0.5, 4.75, 4.75, "", "content", "")
|
||||
fs("hypertext", 1.3, yextra + 0.8, 4.3, 0.6, "content",
|
||||
fmt("<global size=16><center><b>%s</b></center>", ES"Content"))
|
||||
|
||||
local x, size, spacing = 1.45, 0.9, 0.12
|
||||
|
||||
if data.bag_size == 4 then
|
||||
x, size, spacing = 1.7, 0.8, 0.1
|
||||
end
|
||||
|
||||
fs(fmt("style_type[list;size=%f;spacing=%f]", size, spacing))
|
||||
fs(fmt("list[detached:i3_bag_content_%s;main;%f,%f;4,%u;]", name, x, yextra + 1.3, data.bag_size))
|
||||
fs("style_type[list;size=1;spacing=0.15]")
|
||||
end
|
||||
|
||||
elseif data.subcat == 2 then
|
||||
if i3.modules.armor then
|
||||
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;]", name, yextra + 0.7))
|
||||
|
||||
local armor_def = armor.def[name]
|
||||
|
||||
|
@ -438,13 +450,18 @@ local function show_popup(fs, data)
|
|||
fs("button", 5.8, 9.25, 1.8, 0.55, "setting_misc", "Misc.")
|
||||
|
||||
if show_home then
|
||||
local home_pos = data.home or ""
|
||||
home_pos = home_pos:gsub(",", ", "):sub(2,-2):gsub("%.%d", ""):gsub(
|
||||
"(%-?%d+)", clr("#dbeeff", "%1"))
|
||||
local home_str = fmt("Home position: %s", home_pos)
|
||||
home_str = data.home and home_str or ES"No home set"
|
||||
local coords, c, str = {"X", "Y", "Z"}, 0, ES"No home set"
|
||||
|
||||
fs("button", 2.1, 9.7, 6, 0.8, "", home_str)
|
||||
if data.home then
|
||||
str = data.home:gsub(",", " "):sub(2,-2):gsub("%.%d", ""):gsub(
|
||||
"(%-?%d+)", function(a)
|
||||
c = c + 1
|
||||
return fmt("<b>%s:</b> <style color=#dbeeff font=mono>%s</style>",
|
||||
coords[c], a)
|
||||
end)
|
||||
end
|
||||
|
||||
fs("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")
|
||||
|
||||
elseif show_sorting then
|
||||
|
@ -476,11 +493,11 @@ local function show_popup(fs, data)
|
|||
fs("box", 5.4, 10.68, 2.4, 0.45, "#707070")
|
||||
end
|
||||
|
||||
fs("style[reject_items;font_size=15;font=mono;textcolor=#dbeeff]")
|
||||
fs(fmt("field[5.4,10.68;2.4,0.45;reject_items;Reject items:;%s]",
|
||||
ESC(concat(data.reject_items or {}, ","))))
|
||||
fs("field_close_on_enter[reject_items;false]")
|
||||
fs(fmt("tooltip[reject_items;%s;#707070;#fff]",
|
||||
fs("style[drop_items;font_size=15;font=mono;textcolor=#dbeeff]")
|
||||
fs(fmt("field[5.4,10.68;2.4,0.45;drop_items;Drop items:;%s]",
|
||||
ESC(concat(data.drop_items or {}, ","))))
|
||||
fs("field_close_on_enter[drop_items;false]")
|
||||
fs(fmt("tooltip[drop_items;%s;#707070;#fff]",
|
||||
ES"Format:" .. "\n" ..
|
||||
("mod:item,mod:item, ..."):gsub("(%a+:%a+)", clr("#bddeff", "%1"))))
|
||||
end
|
||||
|
@ -490,11 +507,9 @@ end
|
|||
local function get_inventory_fs(player, data, fs)
|
||||
fs("listcolors[#bababa50;#bababa99]")
|
||||
|
||||
get_inv_slots(data, fs)
|
||||
get_inv_slots(fs)
|
||||
|
||||
local props = player:get_properties()
|
||||
local name = player:get_player_name()
|
||||
|
||||
local ctn_len, ctn_hgt = 5.7, 6.3
|
||||
local yoffset = 0
|
||||
|
||||
|
@ -522,7 +537,10 @@ local function get_inventory_fs(player, data, fs)
|
|||
local awards_unlocked = 0
|
||||
local max_val = damage_enabled and 12 or 7
|
||||
|
||||
if i3.modules.armor and data.subcat == 2 then
|
||||
if data.subcat == 1 and data.bag_size then
|
||||
max_val = max_val + 32
|
||||
|
||||
elseif i3.modules.armor and data.subcat == 2 then
|
||||
if data.scrbar_inv >= max_val then
|
||||
data.scrbar_inv = data.scrbar_inv + 10
|
||||
end
|
||||
|
@ -530,7 +548,7 @@ local function get_inventory_fs(player, data, fs)
|
|||
max_val = max_val + 10
|
||||
|
||||
elseif i3.modules.awards and data.subcat == 4 then
|
||||
award_list = awards.get_award_states(name)
|
||||
award_list = awards.get_award_states(data.player_name)
|
||||
award_list_nb = #award_list
|
||||
|
||||
for i = 1, award_list_nb do
|
||||
|
@ -710,19 +728,18 @@ local function get_output_fs(fs, data, rcp, is_recipe, shapeless, right, btn_siz
|
|||
|
||||
fs(fmt("style_type[list;size=%f]", i3.ITEM_BTN_SIZE))
|
||||
fs("listcolors[#bababa50;#bababa99]")
|
||||
fs(fmt("list[detached:i3_output_%s;main;%f,%f;1,1;]", rcp_usg, 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, i3.ITEM_BTN_SIZE, i3.ITEM_BTN_SIZE, _name, "")
|
||||
|
||||
local inv = core.get_inventory {
|
||||
type = "detached",
|
||||
name = fmt("i3_output_%s", rcp_usg)
|
||||
name = fmt("i3_output_%s_%s", rcp_usg, data.player_name)
|
||||
}
|
||||
|
||||
inv:set_stack("main", 1, item)
|
||||
pos = {x = X + 0.11, y = Y}
|
||||
else
|
||||
fs("image", X, Y - 0.11, bt_s, bt_s, PNG.slot)
|
||||
|
||||
fs("item_image_button",
|
||||
X + 0.11, Y, i3.ITEM_BTN_SIZE, i3.ITEM_BTN_SIZE,
|
||||
fmt("%s %u", name, count * (is_recipe and data.scrbar_rcp or data.scrbar_usg or 1)),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
local PNG = {
|
||||
bg = "i3_bg.png",
|
||||
bg_full = "i3_bg_full.png",
|
||||
bg_content = "i3_bg_content.png",
|
||||
bar = "i3_bar.png",
|
||||
hotbar = "i3_hotbar.png",
|
||||
search = "i3_search.png",
|
||||
|
@ -10,6 +11,7 @@ local PNG = {
|
|||
prev = "i3_next.png^\\[transformFX",
|
||||
next = "i3_next.png",
|
||||
arrow = "i3_arrow.png",
|
||||
arrow_content = "i3_arrow_content.png",
|
||||
trash = "i3_trash.png",
|
||||
sort = "i3_sort.png",
|
||||
settings = "i3_settings.png",
|
||||
|
@ -66,9 +68,10 @@ local styles = string.format([[
|
|||
style_type[field;border=false;bgcolor=transparent]
|
||||
style_type[label,field;font_size=16]
|
||||
style_type[button;border=false;content_offset=0]
|
||||
style_type[image_button,item_image_button,checkbox;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[nofav;sound=i3_cannot]
|
||||
style[pagenum,no_item,no_rcp;font=bold;font_size=18]
|
||||
style[exit;fgimg=%s;fgimg_hovered=%s;content_offset=0]
|
||||
style[cancel;fgimg=%s;fgimg_hovered=%s;content_offset=0]
|
||||
|
|
|
@ -1,25 +1,22 @@
|
|||
i3.new_tab {
|
||||
name = "test1",
|
||||
i3.new_tab("test1", {
|
||||
description = "Test 1 Test 1",
|
||||
image = "i3_heart.png",
|
||||
|
||||
formspec = function(player, data, fs)
|
||||
fs("label[3,1;Test 1]")
|
||||
end,
|
||||
}
|
||||
})
|
||||
|
||||
i3.new_tab {
|
||||
name = "test2",
|
||||
i3.new_tab("test2", {
|
||||
description = "Test 2",
|
||||
image = "i3_mesepick.png",
|
||||
|
||||
formspec = function(player, data, fs)
|
||||
fs("label[3,1;Test 2]")
|
||||
end,
|
||||
}
|
||||
})
|
||||
|
||||
i3.new_tab {
|
||||
name = "test3",
|
||||
i3.new_tab("test3", {
|
||||
description = "Test 3",
|
||||
|
||||
access = function(player, data)
|
||||
|
@ -36,10 +33,9 @@ i3.new_tab {
|
|||
fields = function(player, data, fields)
|
||||
i3.set_fs(player, "label[3,2;Test extra_fs]")
|
||||
end,
|
||||
}
|
||||
})
|
||||
|
||||
i3.override_tab("test2", {
|
||||
name = "test2",
|
||||
description = "Test override",
|
||||
image = "i3_mesepick.png",
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 7.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
Binary file not shown.
After Width: | Height: | Size: 527 B |
Ŝarĝante…
Reference in New Issue