Compare commits

...

108 Commits
1.5.6 ... 1.12

Author SHA1 Message Date
7f437b21f4 Bump version 2022-09-25 17:22:38 +02:00
e8a811f72c Save more settings accross restarts 2022-09-25 17:22:36 +02:00
4c4911eb4f Fix 2022-09-25 16:55:41 +02:00
325d6f30be 🚀 Greatly improve Progressive Mode look 2022-09-25 16:23:11 +02:00
05995a22df Add sound for skins 2022-09-24 16:24:01 +02:00
32594e7552 Small fix 2022-09-24 14:30:45 +02:00
27ed1f02e6 More cleaning 2022-09-24 14:23:47 +02:00
916e80f2c3 Cleanup vectors 2022-09-24 13:46:50 +02:00
c42ea6c005 Minor tweak 2022-09-20 01:12:07 +02:00
da91223c4d Bump version 2022-09-18 14:24:45 +02:00
408267754c API.md: rewrite some parts 2022-09-15 12:28:23 +02:00
b4de48370a HUD: small tweak 2022-09-14 15:37:29 +02:00
477efe56d3 Bump version 2022-09-04 19:17:42 +02:00
8afb51dae8 Some cleaning 2022-09-04 19:12:57 +02:00
734b09b69f Minor cleaning 2022-08-29 11:29:09 +02:00
1560d59d4a Bump version 2022-08-28 16:36:30 +02:00
e4e175a775 Minor tweak 2022-08-28 16:36:08 +02:00
7a40f36611 Bump version 2022-08-28 15:36:44 +02:00
2467e8bb0b Fix sound play 2022-08-28 15:34:37 +02:00
9666834aed Minor tweak 2022-08-28 15:21:20 +02:00
7670356c8c Bump version (again) 2022-08-28 14:46:03 +02:00
646d16afd8 Hotfix HUD 2022-08-28 14:45:37 +02:00
6b54dbc934 Bump version 2022-08-28 14:23:36 +02:00
911bed3911 Add option in Style settings to show wielditem descriptions in HUD 2022-08-28 14:18:05 +02:00
75fdd57f2a Integrate Legacy Inventory option per-player in Settings popup 2022-08-28 13:31:01 +02:00
c8d6312772 Minor cleaning 2022-08-21 23:47:15 +02:00
a4e8fac0e6 Update preview screenshot 2022-08-20 17:45:44 +02:00
eac4a18df2 HOTFIX 2022-08-20 16:59:26 +02:00
2ddaa4ddfb Bump version 2022-08-20 16:20:44 +02:00
56b5cb78f2 Minor fix 2022-08-16 16:44:31 +02:00
813d27d2cc Minor cleaning 2022-08-16 14:25:02 +02:00
52464d4486 Add checkbox to change the panel style (preview: https://i.imgur.com/gNPLf0B.png) 2022-08-16 14:18:26 +02:00
e300539dd3 Cleaning 2022-08-15 18:19:02 +02:00
2cdd03b127 Redesign settings 2022-08-15 17:51:38 +02:00
8db3fb4a41 Minor fixes 2022-08-15 15:25:23 +02:00
d3ad413876 Minor cleaning 2022-08-15 01:00:34 +02:00
6219c2f64e Fix bug with Quick Crafting 2022-08-14 21:57:45 +02:00
55d364acae Bump version 2022-08-14 20:37:07 +02:00
0a8ae9a3d7 Take replacements into consideration in Quick Crafting (fix #73) 2022-08-14 20:29:22 +02:00
0e2f233234 Improve Quick Crafting look a bit 2022-08-14 20:12:28 +02:00
aeeac6ac1b New highlight look 2022-08-14 19:37:44 +02:00
0c4b4e6c4f Add ability to goto pagenum from pagenum button 2022-08-14 19:21:01 +02:00
7b31c998de Specify custom recipe type in UI 2022-08-14 17:41:03 +02:00
7ee19e3dc5 Minor tweak 2022-08-09 15:19:01 +02:00
60e21627e1 Some tweaks 2022-08-08 22:09:39 +02:00
7e7422def7 🚀 Redesign the armor tab (preview: https://i.imgur.com/Ulkx6KB.png) 2022-08-08 02:50:12 +02:00
aa10460886 Bump version 2022-08-07 16:34:41 +02:00
cef11f5301 Update README 2022-08-07 16:34:19 +02:00
2297b47dc0 Minor Fix 2022-08-07 01:40:49 +02:00
a67ef8b08b Some adjusting 2022-08-07 01:23:36 +02:00
48ab26b4c6 Add a font size global change slider 2022-08-07 00:42:52 +02:00
1389027a22 Another UI tweak 2022-08-01 06:43:20 +02:00
629676a975 Bump version 2022-08-01 04:34:06 +02:00
20b8110375 Minor tweak 2022-08-01 04:21:17 +02:00
a3fea93a09 Remove all the legacy code (MT 5.6+ required) 2022-08-01 04:04:14 +02:00
326ee3e098 Improve search bar look 2022-08-01 03:54:35 +02:00
60bdfa34fb Cleaner bg + slot textures 2022-07-04 05:10:31 +02:00
9971b8c3e6 Improve get_desc() 2022-07-04 03:01:30 +02:00
5a14116b69 Improve alphabetical sorting 2022-07-03 19:40:23 +02:00
222e04d2c4 Minor cleaning 2022-07-03 19:21:13 +02:00
8f4c9f28f1 Also for slots 2022-07-03 18:55:13 +02:00
37e0c21ca3 Add support for bgimg_middle (better looking tabs) 2022-07-03 17:27:03 +02:00
057f0cf03f Fix again 2022-07-03 05:07:49 +02:00
dca93b7249 Minor cleaning 2022-07-02 02:21:14 +02:00
1e9c3ce55a Minor cleaning 2022-07-01 17:28:50 +02:00
1627172cce Check string limits correctly 2022-07-01 17:15:10 +02:00
bd356e4a40 Minor QoL 2022-07-01 15:50:04 +02:00
f26c6af9c4 Minor fix 2022-07-01 15:15:21 +02:00
3f2d983091 Minor tweak 2022-07-01 03:46:25 +02:00
6dd95a6a87 Remove the bullshit and fix the sprite once and for all 2022-07-01 03:36:16 +02:00
32779ab56f Add comments 2022-07-01 03:10:37 +02:00
4ccff6621b Minor tweak 2022-07-01 02:43:05 +02:00
7d0f25e8b2 Minor tweak 2022-07-01 00:47:43 +02:00
652c486249 Tweak textures 2022-06-30 16:31:43 +02:00
9ab47fc0f0 Improve UTF-8 string length counting 2022-06-30 15:18:32 +02:00
c635343c9b Add a 404 image when no item found 2022-06-30 03:10:24 +02:00
662c938afb Minor UI improvement 2022-06-30 02:32:03 +02:00
b2c8447971 Some UI improvements + fix bug with custom tabs 2022-06-30 01:15:35 +02:00
c91f787cb2 Correct condition 2022-06-28 01:24:36 +02:00
dcc4068e46 Fix potential crash during sprite creation 2022-06-28 01:03:41 +02:00
c421c49916 Fix bug with group stereotype 2022-06-23 18:23:03 +02:00
3dfcd95c6f Tweak preprocessor to add -- decrement 2022-06-23 15:04:39 +02:00
72d4a5d4b8 Minor cleaning 2022-06-23 14:14:54 +02:00
f2b4c960ad Fix bug with favs 2022-06-23 02:30:54 +02:00
5d6ce3be18 Improve preprocessor a bit 2022-06-23 01:14:45 +02:00
5f413a150b Minor improvement 2022-06-19 15:23:50 +02:00
563dc719d0 Put a upper limit for sprite creation 2022-06-19 14:47:52 +02:00
56cb236025 Fix again 2022-06-19 03:33:21 +02:00
8525633d4c Improve groups caching 2022-06-19 02:54:11 +02:00
cb1dce66f9 Some last fix 2022-06-19 00:36:57 +02:00
2db1e885fc Minor cleanup 2022-06-18 23:40:22 +02:00
354561d54c Finish animation for group buttons (yay) 2022-06-18 23:20:57 +02:00
8e45f303d3 Some fix to previous commit 2022-06-18 22:32:51 +02:00
a6605263f4 Animated image buttons for groups (needs polish) 2022-06-18 21:52:08 +02:00
e17e1080d3 Remove some unessecerary [resize 2022-06-18 19:59:34 +02:00
f0f94017da Cache groups (testing needed) 2022-06-18 19:53:47 +02:00
cf5f18e1c1 Register creative priv in case MTG is not installed 2022-06-17 03:12:55 +02:00
4736b551a8 Fix crash in progressive mode 2022-06-09 12:33:56 +02:00
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
58 changed files with 1624 additions and 1090 deletions

View File

@ -10,6 +10,7 @@ read_globals = {
"armor", "armor",
"skins", "skins",
"awards", "awards",
"hb",
"vector", "vector",
"string", "string",
"table", "table",

42
API.md
View File

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

View File

@ -7,7 +7,7 @@
This mod features a modern, powerful inventory menu with a good user experience. This mod features a modern, powerful inventory menu with a good user experience.
**`i3`** provides a rich [**API**](https://github.com/minetest-mods/i3/blob/master/API.md) for mod developers who want to extend it. **`i3`** provides a rich [**API**](https://github.com/minetest-mods/i3/blob/master/API.md) for mod developers who want to extend it.
This mod requires **Minetest 5.4+** This mod requires **Minetest 5.6+**
#### List of features: #### List of features:
- Crafting Guide (survival mode only) - Crafting Guide (survival mode only)
@ -43,6 +43,8 @@ To use this mod in the best conditions:
If the inventory's font size is too big on certain setups (namely Windows 10/11 or 144 DPI display), you should lower the If the inventory's font size is too big on certain setups (namely Windows 10/11 or 144 DPI display), you should lower the
value of the setting `display_density_factor` in your `minetest.conf`. Note that the change is applied after restart. value of the setting `display_density_factor` in your `minetest.conf`. Note that the change is applied after restart.
You can also use the font size slider in the inventory, settings window.
#### Notes #### Notes
`i3` uses a larger inventory than the usual inventories in Minetest games. `i3` uses a larger inventory than the usual inventories in Minetest games.
@ -53,4 +55,4 @@ Report bugs on the [**Bug Tracker**](https://github.com/minetest-mods/i3/issues)
**Video review on YouTube:** https://www.youtube.com/watch?v=Xd14BCdEZ3o **Video review on YouTube:** https://www.youtube.com/watch?v=Xd14BCdEZ3o
![Preview](https://content.minetest.net/uploads/3abf3755de.png) ![Preview](https://user-images.githubusercontent.com/7883281/185755315-23c2fffa-203d-4115-9dc3-576c92615733.png)

View File

@ -13,31 +13,31 @@ 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))
end end
i3 = { i3 = {
version = 112,
data = core.deserialize(storage:get_string"data") or {}, data = core.deserialize(storage:get_string"data") or {},
settings = { settings = {
debug_mode = false, debug_mode = false,
max_favs = 6, max_favs = 6,
max_waypoints = 30, max_waypoints = 30,
min_fs_version = 4, min_fs_version = 6,
item_btn_size = 1.1, item_btn_size = 1.1,
drop_bag_on_die = true, drop_bag_on_die = true,
wielditem_fade_after = 3,
save_interval = 600, -- Player data save interval (in seconds) save_interval = 600, -- Player data save interval (in seconds)
hud_speed = 1, hud_speed = 1,
hud_timer_max = 1.5, hud_timer_max = 1.5,
damage_enabled = core.settings:get_bool"enable_damage", damage_enabled = core.settings:get_bool"enable_damage",
progressive_mode = core.settings:get_bool"i3_progressive_mode", progressive_mode = core.settings:get_bool"i3_progressive_mode",
legacy_inventory = core.settings:get_bool"i3_legacy_inventory",
item_compression = core.settings:get_bool("i3_item_compression", true),
}, },
categories = { categories = {
@ -51,10 +51,26 @@ i3 = {
saves = { -- Metadata to save saves = { -- Metadata to save
bag = true, bag = true,
home = true, home = true,
sort = true,
collapse = true,
font_size = true,
hide_tabs = true,
waypoints = true, waypoints = true,
inv_items = true, inv_items = true,
drop_items = true, auto_sorting = true,
inv_compress = true,
known_recipes = true, known_recipes = true,
wielditem_hud = true,
ignore_hotbar = true,
reverse_sorting = true,
legacy_inventory = true,
},
default_data = {
sort = 1,
font_size = 0,
collapse = true,
inv_compress = true,
}, },
files = { files = {
@ -63,7 +79,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 +98,7 @@ i3 = {
tabs = {}, tabs = {},
cubes = {}, cubes = {},
groups = {},
plants = {}, plants = {},
modules = {}, modules = {},
craft_types = {}, craft_types = {},
@ -91,9 +108,6 @@ i3 = {
sorting_methods = {}, sorting_methods = {},
} }
i3.settings.hotbar_len = i3.settings.legacy_inventory and 8 or 9
i3.settings.inv_size = 4 * i3.settings.hotbar_len
i3.files.common() i3.files.common()
i3.files.api(http) i3.files.api(http)
i3.files.compress() i3.files.compress()

View File

@ -1,4 +1,4 @@
name = i3 name = i3
description = Next-generation inventory description = Next-generation inventory
optional_depends = 3d_armor, skinsdb, awards optional_depends = 3d_armor, skinsdb, awards
min_minetest_version = 5.4 min_minetest_version = 5.6

View File

@ -1,8 +1,2 @@
# The progressive mode shows recipes you can craft from items you ever had in your inventory. # The progressive mode shows recipes you can craft from items you ever had in your inventory.
i3_progressive_mode (Learn crafting recipes progressively) bool false i3_progressive_mode (Learn crafting recipes progressively) bool false
# Regroup the items of the same type in the item list.
i3_item_compression (Regroup items of the same type) bool true
# Set the inventory size to common chests size (8*4).
i3_legacy_inventory (Legacy inventory size) bool false

BIN
sounds/i3_achievement.ogg Normal file

Binary file not shown.

BIN
sounds/i3_heavy_armor.ogg Normal file

Binary file not shown.

BIN
sounds/i3_heavy_boots.ogg Normal file

Binary file not shown.

BIN
sounds/i3_heavy_helmet.ogg Normal file

Binary file not shown.

Binary file not shown.

BIN
sounds/i3_heavy_shield.ogg Normal file

Binary file not shown.

BIN
sounds/i3_light_armor.ogg Normal file

Binary file not shown.

BIN
sounds/i3_light_boots.ogg Normal file

Binary file not shown.

BIN
sounds/i3_light_helmet.ogg Normal file

Binary file not shown.

Binary file not shown.

BIN
sounds/i3_light_shield.ogg Normal file

Binary file not shown.

BIN
sounds/i3_skin_change.ogg Normal file

Binary file not shown.

View File

@ -3,7 +3,7 @@ local make_fs, get_inventory_fs = i3.files.gui()
IMPORT("gmatch", "split") IMPORT("gmatch", "split")
IMPORT("S", "err", "fmt", "reg_items") IMPORT("S", "err", "fmt", "reg_items")
IMPORT("sorter", "sort_inventory") IMPORT("sorter", "sort_inventory", "play_sound")
IMPORT("sort", "concat", "copy", "insert", "remove") IMPORT("sort", "concat", "copy", "insert", "remove")
IMPORT("true_str", "true_table", "is_str", "is_func", "is_table", "clean_name") IMPORT("true_str", "true_table", "is_str", "is_func", "is_table", "clean_name")
@ -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
@ -316,8 +323,10 @@ function i3.hud_notif(name, msg, img)
data.show_hud = true data.show_hud = true
data.hud_msg = msg data.hud_msg = msg
play_sound(name, "i3_achievement", 1.0)
if img then if img then
data.hud_img = fmt("%s^[resize:16x16", img) data.hud_img = fmt("%s^[resize:64x64", img)
end end
end end
@ -337,7 +346,7 @@ end
i3.add_sorting_method("alphabetical", { i3.add_sorting_method("alphabetical", {
description = S"Sort items by name (A-Z)", description = S"Sort items by name (A-Z)",
func = function(list, data) func = function(list, data)
sorter(list, data.reverse_sorting, 1) sorter(list, data, 1)
return list return list
end end
}) })
@ -345,7 +354,7 @@ i3.add_sorting_method("alphabetical", {
i3.add_sorting_method("numerical", { i3.add_sorting_method("numerical", {
description = S"Sort items by number of items per stack", description = S"Sort items by number of items per stack",
func = function(list, data) func = function(list, data)
sorter(list, data.reverse_sorting, 2) sorter(list, data, 2)
return list return list
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", "table_eq")
IMPORT("fmt", "reg_items", "reg_aliases", "reg_nodes", "draw_cube", "ItemStack") IMPORT("fmt", "reg_items", "reg_aliases", "reg_nodes", "is_cube", "get_cube", "ItemStack")
IMPORT("true_str", "true_table", "is_table", "valid_item", "table_merge", "table_replace", "rcp_eq") IMPORT("is_group", "extract_groups", "item_has_groups", "groups_to_items", "get_group_stereotype")
local function get_burntime(item) local function get_burntime(item)
return core.get_craft_result{method = "fuel", items = {item}}.time return core.get_craft_result{method = "fuel", items = {item}}.time
@ -23,10 +22,55 @@ local function cache_fuel(item)
end end
end end
local function get_item_usages(item, recipe, added) local function cache_groups(group, groups)
local groups = extract_groups(item) i3.groups[group] = {}
i3.groups[group].groups = groups
i3.groups[group].items = groups_to_items(groups)
if #groups == 1 then
i3.groups[group].stereotype = get_group_stereotype(groups[1])
end
local items = i3.groups[group].items
if #items <= 1 then return end
local px, lim, c = 64, 10, 0
local sprite = "[combine:WxH"
for _, item in ipairs(items) do
local def = reg_items[item]
local tiles = def.tiles or def.tile_images
local texture = true_str(def.inventory_image) and def.inventory_image --or tiles[1]
if def.drawtype and is_cube(def.drawtype) then
texture = get_cube(tiles)
end
if texture then
texture = texture:gsub("%^", "\\^"):gsub(":", "\\:") .. fmt("\\^[resize\\:%ux%u", px, px)
sprite = sprite .. fmt(":0,%u=%s", c * px, texture)
c++
if c == lim then break end
end
end
if c > 1 then
sprite = sprite:gsub("WxH", px .. "x" .. px * c)
i3.groups[group].sprite = sprite
i3.groups[group].count = c
end
end
local function get_item_usages(item, recipe, added)
if is_group(item) then
local group = item:sub(7)
local group_cache = i3.groups[group]
local groups = group_cache and group_cache.groups or extract_groups(item)
if not group_cache then
cache_groups(group, groups)
end
if groups then
for name, def in pairs(reg_items) do for name, def in pairs(reg_items) do
if not added[name] and valid_item(def) and item_has_groups(def.groups, groups) then if not added[name] and valid_item(def) and item_has_groups(def.groups, groups) then
local usage = copy(recipe) local usage = copy(recipe)
@ -181,7 +225,7 @@ core.register_craft = function(def)
if is_group(output[1]) then if is_group(output[1]) then
groups = extract_groups(output[1]) groups = extract_groups(output[1])
output = groups_to_items(groups, true) output = groups_to_items(groups)
end end
for i = 1, #output do for i = 1, #output do
@ -204,11 +248,7 @@ local old_clear_craft = core.clear_craft
core.clear_craft = function(def) core.clear_craft = function(def)
old_clear_craft(def) old_clear_craft(def)
if true_str(def) then -- TODO: hide in crafting guide
return -- TODO
elseif is_table(def) then
return -- TODO
end
end end
local function resolve_aliases(hash) local function resolve_aliases(hash)
@ -230,7 +270,7 @@ local function resolve_aliases(hash)
local rcp_new = copy(i3.recipes_cache[newname][j]) local rcp_new = copy(i3.recipes_cache[newname][j])
rcp_new.output = oldname rcp_new.output = oldname
if rcp_eq(rcp_old, rcp_new) then if table_eq(rcp_old, rcp_new) then
similar = true similar = true
break break
end end
@ -242,7 +282,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 +324,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

@ -6,7 +6,7 @@ local init_hud = i3.files.hud()
local set_fs = i3.set_fs local set_fs = i3.set_fs
IMPORT("slz", "min", "insert", "copy", "ItemStack") IMPORT("slz", "min", "insert", "copy", "ItemStack")
IMPORT("spawn_item", "reset_data", "get_detached_inv") IMPORT("spawn_item", "reset_data", "get_detached_inv", "play_sound", "update_inv_size")
core.register_on_player_hpchange(function(player, hpchange) core.register_on_player_hpchange(function(player, hpchange)
local name = player:get_player_name() local name = player:get_player_name()
@ -66,16 +66,89 @@ core.register_on_player_inventory_action(function(player, _, _, info)
end end
end) end)
if core.global_exists("armor") then if core.global_exists"armor" then
i3.modules.armor = true i3.modules.armor = true
armor:register_on_update(set_fs)
local group_indexes = {
{"armor_head", "i3_heavy_helmet"},
{"armor_torso", "i3_heavy_armor"},
{"armor_legs", "i3_heavy_leggings"},
{"armor_feet", "i3_heavy_boots"},
{"armor_shield", "i3_heavy_shield"},
}
local function check_group(def, group)
return def.groups[group] and def.groups[group] > 0
end
armor:register_on_equip(function(player, idx, stack)
local _, armor_inv = armor:get_valid_player(player, "3d_armor")
local def = stack:get_definition()
local name = player:get_player_name()
local data = i3.data[name]
for i, v in ipairs(group_indexes) do
local group, sound = unpack(v)
local stackname = stack:get_name()
if stackname:find"wood" or stackname:find"stone" or stackname:find"cactus" then
sound = sound:gsub("heavy", "light")
end
if i == idx and check_group(def, group) then
data.armor_allow = sound
return armor:register_on_update(set_fs)
end
end
data.armor_disallow = true
armor_inv:remove_item("armor", stack)
end)
armor:register_on_update(function(player)
local _, armor_inv = armor:get_valid_player(player, "3d_armor")
if not armor_inv then return end
for i = 1, 5 do
local stack = armor_inv:get_stack("armor", i)
local def = stack:get_definition()
for j, v in ipairs(group_indexes) do
local group = v[1]
if check_group(def, group) and i ~= j then
armor_inv:set_stack("armor", i, armor_inv:get_stack("armor", j))
armor_inv:set_stack("armor", j, stack)
return play_sound(player:get_player_name(), "i3_cannot", 0.8)
end
end
end
end)
core.register_on_player_inventory_action(function(player, action, _, info)
if action ~= "take" then return end
local name = player:get_player_name()
local data = i3.data[name]
if data.armor_disallow then
local inv = player:get_inventory()
inv:set_stack("main", info.index, info.stack)
data.armor_disallow = nil
play_sound(name, "i3_cannot", 0.8)
elseif data.armor_allow then
play_sound(name, data.armor_allow, 0.8)
data.armor_allow = nil
end
end)
end end
if core.global_exists("skins") then if core.global_exists"skins" then
i3.modules.skins = true i3.modules.skins = true
end end
if core.global_exists("awards") then if core.global_exists"awards" then
i3.modules.awards = true i3.modules.awards = true
core.register_on_craft(function(_, player) core.register_on_craft(function(_, player)
@ -130,20 +203,27 @@ local function init_data(player, info)
local name = player:get_player_name() local name = player:get_player_name()
i3.data[name] = i3.data[name] or {} i3.data[name] = i3.data[name] or {}
local data = i3.data[name] local data = i3.data[name]
local default = {}
for k, v in pairs(i3.default_data) do
default[k] = data[k]
if data[k] == nil then
default[k] = v
end
data[k] = default[k]
end
data.player_name = name data.player_name = name
data.filter = "" data.filter = ""
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 = {}
data.sort = "alphabetical"
data.show_setting = "home" data.show_setting = "home"
data.ignore_hotbar = false data.crafting_counts = {}
data.auto_sorting = false
data.reverse_sorting = false
data.inv_compress = true
data.export_counts = {}
data.tab = 1 data.tab = 1
data.itab = 1 data.itab = 1
data.subcat = 1 data.subcat = 1
@ -151,8 +231,7 @@ local function init_data(player, info)
data.lang_code = get_lang_code(info) data.lang_code = get_lang_code(info)
data.fs_version = info.formspec_version data.fs_version = info.formspec_version
local inv = player:get_inventory() update_inv_size(player, data)
inv:set_size("main", i3.settings.inv_size)
core.after(0, set_fs, player) core.after(0, set_fs, player)
end end

View File

@ -1,14 +1,22 @@
local vec = vector.new
local ItemStack = ItemStack local ItemStack = ItemStack
local loadstring = loadstring local loadstring = loadstring
local reg_items = core.registered_items local reg_items = core.registered_items
local translate = core.get_translated_string local translate = core.get_translated_string
local vec_new, vec_add, vec_mul = vector.new, vector.add, vector.multiply
local sort, concat, insert = table.sort, table.concat, table.insert local sort, concat, insert = table.sort, table.concat, table.insert
local min, floor, ceil = math.min, math.floor, math.ceil local min, floor, ceil = math.min, math.floor, math.ceil
local fmt, find, match, gmatch, sub, split, lower, upper = local fmt, find, match, gmatch, sub, split, lower, upper =
string.format, string.find, string.match, string.gmatch, string.format, string.find, string.match, string.gmatch,
string.sub, string.split, string.lower, string.upper string.sub, string.split, string.lower, string.upper
if not core.registered_privileges.creative then
core.register_privilege("creative", {
description = "Allow player to use creative inventory",
give_to_singleplayer = false,
give_to_admin = false,
})
end
local old_is_creative_enabled = core.is_creative_enabled local old_is_creative_enabled = core.is_creative_enabled
function core.is_creative_enabled(name) function core.is_creative_enabled(name)
@ -69,6 +77,16 @@ local function toupper(str)
return str:gsub("%f[%w]%l", upper):gsub("_", " ") return str:gsub("%f[%w]%l", upper):gsub("_", " ")
end end
local function utf8_len(str)
local c = 0
for _ in str:gmatch"[%z\1-\127\194-\244][\128-\191]*" do -- Arguably working duct-tape code
c++
end
return c
end
local function get_bag_description(data, stack) local function get_bag_description(data, stack)
local desc = translate(data.lang_code, stack:get_description()) local desc = translate(data.lang_code, stack:get_description())
desc = split(desc, "(")[1] or desc desc = split(desc, "(")[1] or desc
@ -101,7 +119,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
@ -198,18 +216,22 @@ local function array_diff(t1, t2)
return diff return diff
end end
local function rcp_eq(rcp, rcp2) local function table_eq(t1, t2)
if rcp.type ~= rcp2.type then return end local ty1, ty2 = type(t1), type(t2)
if rcp.width ~= rcp2.width then return end if ty1 ~= ty2 then return end
if #rcp.items ~= #rcp2.items then return end
if rcp.output ~= rcp2.output then return end
for i, item in pairs(rcp.items) do if ty1 ~= "table" and ty2 ~= "table" then
if item ~= rcp2.items[i] then return end return t1 == t2
end end
for i, item in pairs(rcp2.items) do for k, v in pairs(t1) do
if item ~= rcp.items[i] then return end local v2 = t2[k]
if v2 == nil or not table_eq(v, v2) then return end
end
for k, v in pairs(t2) do
local v1 = t1[k]
if v1 == nil or not table_eq(v1, v) then return end
end end
return true return true
@ -228,9 +250,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 +267,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)
@ -282,7 +328,7 @@ local function apply_recipe_filters(recipes, player)
end end
local function compression_active(data) local function compression_active(data)
return i3.settings.item_compression and not next(i3.recipe_filters) and data.filter == "" return data.collapse and not next(i3.recipe_filters) and data.filter == ""
end end
local function compressible(item, data) local function compressible(item, data)
@ -330,7 +376,7 @@ local function spawn_item(player, stack)
local dir = player:get_look_dir() local dir = player:get_look_dir()
local ppos = player:get_pos() local ppos = player:get_pos()
ppos.y = ppos.y + player:get_properties().eye_height ppos.y = ppos.y + player:get_properties().eye_height
local look_at = vec_add(ppos, vec_mul(dir, 1)) local look_at = ppos + dir
core.add_item(look_at, stack) core.add_item(look_at, stack)
end end
@ -366,22 +412,24 @@ end
local function craft_stack(player, data, craft_rcp) local function craft_stack(player, data, craft_rcp)
local inv = player:get_inventory() local inv = player:get_inventory()
local rcp_usg = craft_rcp and "recipe" or "usage" local rcp_usg = craft_rcp and "recipe" or "usage"
local rcp_def = rcp_usg == "recipe" and data.recipes[data.rnum] or data.usages[data.unum]
local output = craft_rcp and data.recipes[data.rnum].output or data.usages[data.unum].output local output = craft_rcp and data.recipes[data.rnum].output or data.usages[data.unum].output
output = ItemStack(output) output = ItemStack(output)
local stackname, stackcount, stackmax = output:get_name(), output:get_count(), output:get_stack_max() 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 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 for name, count in pairs(data.crafting_counts[rcp_usg].rcp) do
local items = {[name] = count} local items = {[name] = count}
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
for _name, _count in pairs(data.export_counts[rcp_usg].inv) do for _name, _count in pairs(data.crafting_counts[rcp_usg].inv) do
if item == _name and remaining > 0 then if item == _name and remaining > 0 then
local c = min(remaining, _count) local c = min(remaining, _count)
items[item] = c items[item] = c
@ -398,6 +446,12 @@ local function craft_stack(player, data, craft_rcp)
end end
end end
if rcp_def.replacements then
for _, pair in ipairs(rcp_def.replacements) do
get_stack(player, ItemStack(pair[2]))
end
end
local count = stackcount * scrbar_val local count = stackcount * scrbar_val
local iter = ceil(count / stackmax) local iter = ceil(count / stackmax)
local leftover = count local leftover = count
@ -419,35 +473,24 @@ local function safe_teleport(player, pos)
play_sound(name, "i3_teleport", 0.8) play_sound(name, "i3_teleport", 0.8)
local vel = player:get_velocity() local vel = player:get_velocity()
player:add_velocity(vec_mul(vel, -1)) player:add_velocity(-vel)
local p = vec_new(pos) local p = vec(pos)
p.y += 0.25 p.y += 0.25
player:set_pos(p) player:set_pos(p)
end end
local function get_sorting_idx(name) local function sorter(inv, data, mode)
local idx = 1
for i, def in ipairs(i3.sorting_methods) do
if name == def.name then
idx = i
end
end
return idx
end
local function sorter(inv, reverse, mode)
sort(inv, function(a, b) sort(inv, function(a, b)
if mode == 1 then if mode == 1 then
a, b = a:get_name(), b:get_name() a = translate(data.lang_code, a:get_short_description())
b = translate(data.lang_code, b:get_short_description())
else else
a, b = a:get_count(), b:get_count() a, b = a:get_count(), b:get_count()
end end
if reverse then if data.reverse_sorting then
return a > b return a > b
end end
@ -514,31 +557,11 @@ 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)
for i = start_i, #list do
local stack = list[i]
local name = stack:get_name()
for _, it in ipairs(rej) do
if name == it then
spawn_item(player, stack)
inv:set_stack("main", i, ItemStack(""))
end
end
end
return inv:get_list"main"
end
local function sort_inventory(player, data) local function sort_inventory(player, data)
local inv = player:get_inventory() local inv = player:get_inventory()
local list = inv:get_list"main" local list = inv:get_list"main"
local size = inv:get_size"main" local size = inv:get_size"main"
local start_i = data.ignore_hotbar and (i3.settings.hotbar_len + 1) or 1 local start_i = data.ignore_hotbar and (data.hotbar_len + 1) or 1
if true_table(data.drop_items) then
list = drop_items(player, inv, list, start_i, data.drop_items)
end
if data.inv_compress then if data.inv_compress then
list = compress_items(list, start_i) list = compress_items(list, start_i)
@ -546,8 +569,7 @@ local function sort_inventory(player, data)
list = pre_sorting(list, start_i) list = pre_sorting(list, start_i)
end end
local idx = get_sorting_idx(data.sort) local new_inv = i3.sorting_methods[data.sort].func(list, data)
local new_inv = i3.sorting_methods[idx].func(list, data)
if not new_inv then return end if not new_inv then return end
if not data.ignore_hotbar then if not data.ignore_hotbar then
@ -570,10 +592,12 @@ local function reset_data(data)
data.scrbar_rcp = 1 data.scrbar_rcp = 1
data.scrbar_usg = 1 data.scrbar_usg = 1
data.query_item = nil data.query_item = nil
data.enable_search = nil
data.goto_page = nil
data.recipes = nil data.recipes = nil
data.usages = nil data.usages = nil
data.export_rcp = nil data.crafting_rcp = nil
data.export_usg = nil data.crafting_usg = nil
data.alt_items = nil data.alt_items = nil
data.confirm_trash = nil data.confirm_trash = nil
data.show_settings = nil data.show_settings = nil
@ -589,7 +613,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,
@ -603,6 +627,24 @@ local function get_detached_inv(name, player_name)
} }
end end
local function update_inv_size(player, data)
data.hotbar_len = data.legacy_inventory and 8 or 9
data.inv_size = 4 * data.hotbar_len
local inv = player:get_inventory()
inv:set_size("main", data.inv_size)
player:hud_set_hotbar_itemcount(data.hotbar_len)
core.after(0, function()
if data.legacy_inventory then
player:hud_set_hotbar_image"gui_hotbar.png"
else
player:hud_set_hotbar_image"i3_hotbar.png"
end
end)
end
-- Much faster implementation of `unpack` -- Much faster implementation of `unpack`
local function createunpack(n) local function createunpack(n)
local ret = {"local t = ... return "} local ret = {"local t = ... return "}
@ -630,6 +672,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,
@ -640,7 +683,6 @@ local _ = {
sorter = sorter, sorter = sorter,
get_recipes = get_recipes, get_recipes = get_recipes,
sort_inventory = sort_inventory, sort_inventory = sort_inventory,
get_sorting_idx = get_sorting_idx,
sort_by_category = sort_by_category, sort_by_category = sort_by_category,
apply_recipe_filters = apply_recipe_filters, apply_recipe_filters = apply_recipe_filters,
@ -657,6 +699,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,
@ -682,6 +726,7 @@ local _ = {
-- Inventory -- Inventory
get_stack = get_stack, get_stack = get_stack,
craft_stack = craft_stack, craft_stack = craft_stack,
update_inv_size = update_inv_size,
get_detached_inv = get_detached_inv, get_detached_inv = get_detached_inv,
get_bag_description = get_bag_description, get_bag_description = get_bag_description,
create_inventory = core.create_detached_inventory, create_inventory = core.create_detached_inventory,
@ -709,6 +754,7 @@ local _ = {
match = string.match, match = string.match,
gmatch = string.gmatch, gmatch = string.gmatch,
toupper = toupper, toupper = toupper,
utf8_len = utf8_len,
-- Table -- Table
maxn = table.maxn, maxn = table.maxn,
@ -722,7 +768,7 @@ local _ = {
is_table = is_table, is_table = is_table,
table_merge = table_merge, table_merge = table_merge,
table_replace = table_replace, table_replace = table_replace,
rcp_eq = rcp_eq, table_eq = table_eq,
array_diff = array_diff, array_diff = array_diff,
-- Math -- Math
@ -734,12 +780,8 @@ local _ = {
random = math.random, random = math.random,
-- Vectors -- Vectors
vec_new = vector.new, vec = vector.new,
vec_add = vector.add,
vec_sub = vector.subtract,
vec_mul = vector.multiply,
vec_round = vector.round, vec_round = vector.round,
vec_eq = vector.equals,
} }
function i3.get(...) function i3.get(...)

View File

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

View File

@ -1,447 +1,475 @@
local set_fs = i3.set_fs local set_fs = i3.set_fs
IMPORT("vec_eq", "vec_round") IMPORT("min", "max", "vec_round")
IMPORT("reg_items", "reg_aliases") IMPORT("reg_items", "reg_aliases")
IMPORT("S", "random", "translate", "ItemStack") IMPORT("sort", "copy", "insert", "remove", "indexof")
IMPORT("sort", "copy", "insert", "remove", "indexof") IMPORT("S", "random", "translate", "compressible", "ItemStack")
IMPORT("fmt", "find", "match", "sub", "lower", "split", "toupper") IMPORT("fmt", "find", "match", "sub", "lower", "split", "toupper")
IMPORT("msg", "is_fav", "pos_to_str", "str_to_pos", "add_hud_waypoint", "play_sound", "reset_data") IMPORT("valid_item", "get_stack", "craft_stack", "clean_name", "check_privs", "safe_teleport")
IMPORT("search", "get_sorting_idx", "sort_inventory", "sort_by_category", "get_recipes", "get_detached_inv") IMPORT("msg", "is_fav", "pos_to_str", "str_to_pos", "add_hud_waypoint", "play_sound", "reset_data")
IMPORT("valid_item", "get_stack", "craft_stack", "clean_name", "compressible", "check_privs", "safe_teleport") IMPORT("search", "sort_inventory", "sort_by_category", "get_recipes", "get_detached_inv", "update_inv_size")
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.dd_sorting_method then
local id = tonumber(fields.skins) data.sort = tonumber(fields.dd_sorting_method)
local _skins = skins.get_skinlist_for_player(name) elseif fields.sb_font_size then
skins.set_player_skin(player, _skins[id]) data.font_size = tonumber(fields.sb_font_size:match"-?%d+$")
end end
if fields.drop_items then for field in pairs(fields) do
local items = split(fields.drop_items, ",") if sub(field, 1, 4) == "btn_" then
data.drop_items = items data.subcat = indexof(i3.categories, sub(field, 5))
end break
for field in pairs(fields) do elseif sub(field, 1, 3) == "cb_" then
if sub(field, 1, 4) == "btn_" then local str = sub(field, 4)
data.subcat = indexof(i3.categories, sub(field, 5)) data[str] = false
break
if fields[field] == "true" then
elseif sub(field, 1, 3) == "cb_" then data[str] = true
local str = sub(field, 4) end
data[str] = false
if str == "legacy_inventory" then
if fields[field] == "true" then update_inv_size(player, data)
data[str] = true elseif str == "collapse" then
end search(data)
end
elseif sub(field, 1, 8) == "setting_" then
data.show_setting = match(field, "_(%w+)$") elseif sub(field, 1, 8) == "setting_" then
data.show_setting = match(field, "_(%w+)$")
elseif find(field, "waypoint_%d+") then
local id, action = match(field, "_(%d+)_(%w+)$") elseif sub(field, 1, 9) == "skin_btn_" then
id = tonumber(id) local id = tonumber(field:match("%d+"))
local waypoint = data.waypoints[id] local _skins = skins.get_skinlist_for_player(name)
if not waypoint then return end
play_sound(name, "i3_skin_change", 0.6)
if action == "see" then skins.set_player_skin(player, _skins[id])
if data.waypoint_see and data.waypoint_see == id then
data.waypoint_see = nil elseif find(field, "waypoint_%d+") then
else local id, action = match(field, "_(%d+)_(%w+)$")
data.waypoint_see = id id = tonumber(id)
end local waypoint = data.waypoints[id]
if not waypoint then return end
elseif action == "delete" then
player:hud_remove(waypoint.id) if action == "see" then
remove(data.waypoints, id) if data.waypoint_see and data.waypoint_see == id then
data.waypoint_see = nil
elseif action == "teleport" then else
local pos = str_to_pos(waypoint.pos) data.waypoint_see = id
safe_teleport(player, pos) end
msg(name, S("Teleported to: @1", waypoint.name))
elseif action == "delete" then
elseif action == "refresh" then player:hud_remove(waypoint.id)
local color = random(0xffffff) remove(data.waypoints, id)
waypoint.color = color
player:hud_change(waypoint.id, "number", color) elseif action == "teleport" then
local pos = str_to_pos(waypoint.pos)
elseif action == "hide" then safe_teleport(player, pos)
if waypoint.hide then msg(name, S("Teleported to: @1", waypoint.name))
local new_id = add_hud_waypoint(
player, waypoint.name, str_to_pos(waypoint.pos), waypoint.color) elseif action == "refresh" then
local color = random(0xffffff)
waypoint.id = new_id waypoint.color = color
waypoint.hide = nil player:hud_change(waypoint.id, "number", color)
else
player:hud_remove(waypoint.id) elseif action == "hide" then
waypoint.hide = true if waypoint.hide then
end local new_id = add_hud_waypoint(
end player, waypoint.name, str_to_pos(waypoint.pos), waypoint.color)
break waypoint.id = new_id
end waypoint.hide = nil
end else
player:hud_remove(waypoint.id)
if fields.quit then waypoint.hide = true
data.confirm_trash = nil end
data.show_settings = nil end
data.waypoint_see = nil
data.bag_rename = nil break
end
elseif fields.trash then end
data.show_settings = nil
data.confirm_trash = true if fields.quit then
data.confirm_trash = nil
elseif fields.settings then data.show_settings = nil
if not data.show_settings then data.waypoint_see = nil
data.confirm_trash = nil data.bag_rename = nil
data.show_settings = true data.goto_page = nil
else
data.show_settings = nil if data.filter == "" then
end data.enable_search = nil
end
elseif fields.confirm_trash_yes or fields.confirm_trash_no then
if fields.confirm_trash_yes then elseif fields.trash then
inv:set_list("main", {}) data.show_settings = nil
inv:set_list("craft", {}) data.confirm_trash = true
end
elseif fields.settings then
data.confirm_trash = nil if not data.show_settings then
data.confirm_trash = nil
elseif fields.close_settings then data.show_settings = true
data.show_settings = nil else
data.show_settings = nil
elseif fields.close_preview then end
data.waypoint_see = nil
elseif fields.confirm_trash_yes or fields.confirm_trash_no then
elseif fields.sort then if fields.confirm_trash_yes then
sort_inventory(player, data) inv:set_list("main", {})
inv:set_list("craft", {})
elseif fields.prev_sort or fields.next_sort then end
local idx = get_sorting_idx(data.sort)
local tot = #i3.sorting_methods data.confirm_trash = nil
idx -= (fields.prev_sort and 1 or -1) elseif fields.close_settings then
data.show_settings = nil
if idx > tot then
idx = 1 elseif fields.close_preview then
elseif idx == 0 then data.waypoint_see = nil
idx = tot
end elseif fields.sort then
sort_inventory(player, data)
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_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 have 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.crafting_rcp = nil
data.export_rcp = nil data.crafting_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 not data.hide_tabs and fields.filter and fields.filter == "" then
if fields.cancel then data.enable_search = nil
reset_data(data) end
elseif fields.exit then if fields.cancel then
data.query_item = nil reset_data(data)
elseif fields.key_enter_field == "filter" or fields.search then elseif fields.exit then
if fields.filter == "" then data.query_item = nil
reset_data(data)
return set_fs(player) elseif fields.enable_search then
end if data.hide_tabs then
data.enable_search = not data.enable_search
local str = lower(fields.filter) else
if data.filter == str then return end data.enable_search = true
end
data.filter = str
data.pagenum = 1 elseif fields.filter and (fields.key_enter_field == "filter" or fields.search) then
if fields.filter == "" then
search(data) reset_data(data)
return set_fs(player)
if data.itab > 1 then end
sort_by_category(data)
end local str = lower(fields.filter)
if data.filter == str then return end
elseif fields.prev_page or fields.next_page then
if data.pagemax == 1 then return end data.filter = str
data.pagenum -= (fields.prev_page and 1 or -1) data.pagenum = 1
if data.pagenum > data.pagemax then search(data)
data.pagenum = 1
elseif data.pagenum == 0 then if data.itab > 1 then
data.pagenum = data.pagemax sort_by_category(data)
end end
elseif fields.prev_recipe or fields.next_recipe then elseif fields.pagenum then
local num = data.rnum + (fields.prev_recipe and -1 or 1) data.goto_page = not data.goto_page
data.rnum = data.recipes[num] and num or (fields.prev_recipe and #data.recipes or 1)
data.export_rcp = nil elseif fields.goto_page then
data.scrbar_rcp = 1 local pagenum = tonumber(fields.goto_page)
data.pagenum = max(1, min(data.pagemax, pagenum or data.pagenum))
elseif fields.prev_usage or fields.next_usage then data.goto_page = nil
local num = data.unum + (fields.prev_usage and -1 or 1)
data.unum = data.usages[num] and num or (fields.prev_usage and #data.usages or 1) elseif fields.prev_page or fields.next_page then
data.export_usg = nil if data.pagemax == 1 then return end
data.scrbar_usg = 1 data.pagenum -= (fields.prev_page and 1 or -1)
elseif fields.fav then if data.pagenum > data.pagemax then
local fav = is_fav(data) data.pagenum = 1
elseif data.pagenum == 0 then
if #data.favs < i3.settings.max_favs and not fav then data.pagenum = data.pagemax
insert(data.favs, data.query_item) end
elseif fav then
remove(data.favs, fav) elseif fields.prev_skin or fields.next_skin then
end if data.skin_pagemax == 1 then return end
data.skin_pagenum -= (fields.prev_skin and 1 or -1)
elseif fields.export_rcp or fields.export_usg then
if fields.export_rcp then if data.skin_pagenum > data.skin_pagemax then
data.export_rcp = not data.export_rcp data.skin_pagenum = 1
elseif data.skin_pagenum == 0 then
if not data.export_rcp then data.skin_pagenum = data.skin_pagemax
data.scrbar_rcp = 1 end
end
else elseif fields.prev_recipe or fields.next_recipe then
data.export_usg = not data.export_usg local num = data.rnum + (fields.prev_recipe and -1 or 1)
data.rnum = data.recipes[num] and num or (fields.prev_recipe and #data.recipes or 1)
if not data.export_usg then data.crafting_rcp = nil
data.scrbar_usg = 1 data.scrbar_rcp = 1
end
end elseif fields.prev_usage or fields.next_usage then
local num = data.unum + (fields.prev_usage and -1 or 1)
elseif (sb_rcp and sub(sb_rcp, 1, 3) == "CHG") or (sb_usg and sub(sb_usg, 1, 3) == "CHG") then data.unum = data.usages[num] and num or (fields.prev_usage and #data.usages or 1)
data.scrbar_rcp = sb_rcp and tonumber(match(sb_rcp, "%d+")) data.crafting_usg = nil
data.scrbar_usg = sb_usg and tonumber(match(sb_usg, "%d+")) data.scrbar_usg = 1
elseif fields.craft_rcp or fields.craft_usg then elseif fields.fav then
craft_stack(player, data, fields.craft_rcp) local fav = is_fav(data)
if fields.craft_rcp then if #data.favs < i3.settings.max_favs and not fav then
data.export_rcp = nil insert(data.favs, data.query_item)
data.scrbar_rcp = 1 elseif fav then
else remove(data.favs, fav)
data.export_usg = nil end
data.scrbar_usg = 1
end elseif fields.crafting_rcp or fields.crafting_usg then
else if fields.crafting_rcp then
select_item(player, data, fields) data.crafting_rcp = not data.crafting_rcp
end
end if not data.crafting_rcp then
data.scrbar_rcp = 1
core.register_on_player_receive_fields(function(player, formname, fields) end
local name = player:get_player_name() else
data.crafting_usg = not data.crafting_usg
if formname == "i3_outdated" then
return false, core.kick_player(name, if not data.crafting_usg then
S"Come back when your Minetest client is up-to-date (www.minetest.net).") data.scrbar_usg = 1
elseif formname ~= "" then end
return false end
end
elseif (sb_rcp and sub(sb_rcp, 1, 3) == "CHG") or (sb_usg and sub(sb_usg, 1, 3) == "CHG") then
-- No-op buttons data.scrbar_rcp = sb_rcp and tonumber(match(sb_rcp, "%d+"))
if fields.player_name or fields.awards or fields.home_pos or fields.pagenum or data.scrbar_usg = sb_usg and tonumber(match(sb_usg, "%d+"))
fields.no_item or fields.no_rcp or fields.select_sorting or fields.sort_method or
fields.bg_content then elseif fields.craft_rcp or fields.craft_usg then
return false craft_stack(player, data, fields.craft_rcp)
end
if fields.craft_rcp then
--print(dump(fields)) data.crafting_rcp = nil
local data = i3.data[name] data.scrbar_rcp = 1
if not data then return end else
data.crafting_usg = nil
for f in pairs(fields) do data.scrbar_usg = 1
if sub(f, 1, 4) == "tab_" then end
local tabname = sub(f, 5) else
i3.set_tab(player, tabname) select_item(player, data, fields)
break end
elseif sub(f, 1, 5) == "itab_" then end
data.pagenum = 1
data.itab = tonumber(f:sub(-1)) core.register_on_player_receive_fields(function(player, formname, fields)
sort_by_category(data) local name = player:get_player_name()
break
end if formname == "i3_outdated" then
end return false, core.kick_player(name,
S"Your Minetest client needs updating (www.minetest.net)")
rcp_fields(player, data, fields) elseif formname ~= "" then
return false
local tab = i3.tabs[data.tab] end
if tab and tab.fields then -- No-op buttons
return true, tab.fields(player, data, fields) if fields.player_name or fields.awards or fields.home_pos or fields.no_item or
end fields.no_rcp or fields.select_sorting or fields.sort_method or fields.bg_content or
fields.quick_crafting then
return true, set_fs(player) return false
end) end
return inv_fields -- print(dump(fields))
local data = i3.data[name]
if not data then return end
for f in pairs(fields) do
if sub(f, 1, 4) == "tab_" then
local tabname = sub(f, 5)
i3.set_tab(player, tabname)
break
elseif sub(f, 1, 5) == "itab_" then
data.pagenum = 1
data.itab = tonumber(f:sub(-1))
sort_by_category(data)
break
end
end
rcp_fields(player, data, 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",

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,17 @@
IMPORT("get_connected_players", "str_to_pos", "add_hud_waypoint") IMPORT("ceil", "get_connected_players", "str_to_pos", "add_hud_waypoint")
local function init_hud(player) local function init_hud(player)
local name = player:get_player_name() local name = player:get_player_name()
local data = i3.data[name] local data = i3.data[name]
local wdesc_y = -90
if core.global_exists"hb" then
wdesc_y -= ceil(hb.hudbars_count / 2) * 5
elseif not i3.settings.damage_enabled then
wdesc_y += 15
end
data.hud = { data.hud = {
bg = player:hud_add { bg = player:hud_add {
hud_elem_type = "image", hud_elem_type = "image",
@ -18,7 +26,7 @@ local function init_hud(player)
hud_elem_type = "image", hud_elem_type = "image",
position = {x = 0.79, y = 1.02}, position = {x = 0.79, y = 1.02},
alignment = {x = 1, y = 1}, alignment = {x = 1, y = 1},
scale = {x = 4, y = 4}, scale = {x = 1, y = 1},
text = "", text = "",
z_index = 0xDEAD, z_index = 0xDEAD,
}, },
@ -32,14 +40,18 @@ local function init_hud(player)
z_index = 0xDEAD, z_index = 0xDEAD,
style = 1, style = 1,
}, },
}
if not i3.settings.legacy_inventory then wielditem = player:hud_add {
core.after(0, function() hud_elem_type = "text",
player:hud_set_hotbar_itemcount(i3.settings.hotbar_len) position = {x = 0.5, y = 1},
player:hud_set_hotbar_image"i3_hotbar.png" offset = {x = 0, y = wdesc_y},
end) alignment = {x = 0, y = -1},
end number = 0xffffff,
text = "",
z_index = 0xDEAD,
style = 1,
},
}
end end
local function show_hud(player, data) local function show_hud(player, data)
@ -47,7 +59,7 @@ local function show_hud(player, data)
-- 2 calls for the notification's back and forth. -- 2 calls for the notification's back and forth.
local hud_info_bg = player:hud_get(data.hud.bg) local hud_info_bg = player:hud_get(data.hud.bg)
local dt = 0.016 local dt = 0.025
if hud_info_bg.position.y <= 0.9 then if hud_info_bg.position.y <= 0.9 then
data.show_hud = false data.show_hud = false
@ -91,6 +103,46 @@ local function show_hud(player, data)
end end
end end
core.register_globalstep(function(dt)
local players = get_connected_players()
players[0] = #players
for i = 1, players[0] do
local player = players[i]
local name = player:get_player_name()
local data = i3.data[name]
if not data then return end
if not data.wielditem_hud then
player:hud_change(data.hud.wielditem, "text", "")
return
end
data.timer = (data.timer or 0) + dt
local wieldidx = player:get_wield_index()
if wieldidx == data.old_wieldidx then
if data.timer >= i3.settings.wielditem_fade_after then
player:hud_change(data.hud.wielditem, "text", "")
end
return
end
data.timer = 0
data.old_wieldidx = wieldidx
local wielditem = player:get_wielded_item()
local meta = wielditem:get_meta()
local meta_desc = meta:get_string"short_description"
meta_desc = meta_desc:gsub("\27", "")
meta_desc = core.strip_colors(meta_desc)
local desc = meta_desc ~= "" and meta_desc or wielditem:get_short_description()
player:hud_change(data.hud.wielditem, "text", desc:trim())
end
end)
core.register_globalstep(function() core.register_globalstep(function()
local players = get_connected_players() local players = get_connected_players()
players[0] = #players players[0] = #players

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

View File

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

View File

@ -1,14 +1,17 @@
local fmt = string.format
local PNG = { local PNG = {
blank = "i3_blank.png", blank = "i3_blank.png",
bg = "i3_bg.png", bg = "i3_bg.png",
bg_full = "i3_bg_full.png", bg_full = "i3_bg_full.png",
bg_goto = "i3_bg_goto.png",
bg_content = "i3_bg_content.png", bg_content = "i3_bg_content.png",
bar = "i3_bar.png", bar = "i3_bar.png",
hotbar = "i3_hotbar.png", hotbar = "i3_hotbar.png",
highlight = "i3_highlight.png",
search = "i3_search.png", search = "i3_search.png",
heart = "i3_heart.png", heart = "i3_heart.png",
heart_half = "i3_heart_half.png", heart_half = "i3_heart_half.png",
heart_grey = "i3_heart_grey.png",
prev = "i3_next.png^\\[transformFX", prev = "i3_next.png^\\[transformFX",
next = "i3_next.png", next = "i3_next.png",
arrow = "i3_arrow.png", arrow = "i3_arrow.png",
@ -22,8 +25,9 @@ local PNG = {
book = "i3_book.png", book = "i3_book.png",
sign = "i3_sign.png", sign = "i3_sign.png",
cancel = "i3_cancel.png", cancel = "i3_cancel.png",
export = "i3_export.png", crafting = "i3_crafting.png",
slot = "i3_slot.png", slot = "i3_slot.png^\\[resize:128x128",
pagenum_hover = "i3_slot.png^\\[resize:128x128^\\[opacity:130",
tab = "i3_tab.png", tab = "i3_tab.png",
tab_small = "i3_tab_small.png", tab_small = "i3_tab_small.png",
tab_top = "i3_tab.png^\\[transformFY", tab_top = "i3_tab.png^\\[transformFY",
@ -42,10 +46,18 @@ local PNG = {
home = "i3_home.png", home = "i3_home.png",
flag = "i3_flag.png", flag = "i3_flag.png",
edit = "i3_edit.png", edit = "i3_edit.png",
no_result = "i3_no_result.png",
find_more = "i3_find_more.png",
search_outline = "i3_search_outline.png",
search_outline_trim = "i3_search_outline_trim.png",
all = "i3_all.png",
node = "i3_node.png",
item = "i3_item.png",
cube = "i3_cube.png",
cancel_hover = "i3_cancel.png^\\[brighten", cancel_hover = "i3_cancel.png^\\[brighten",
search_hover = "i3_search.png^\\[brighten", search_hover = "i3_search.png^\\[brighten",
export_hover = "i3_export.png^\\[brighten", crafting_hover = "i3_crafting.png^\\[brighten",
trash_hover = "i3_trash.png^\\[brighten^\\[colorize:#f00:100", trash_hover = "i3_trash.png^\\[brighten^\\[colorize:#f00:100",
compress_hover = "i3_compress.png^\\[brighten", compress_hover = "i3_compress.png^\\[brighten",
sort_hover = "i3_sort.png^\\[brighten", sort_hover = "i3_sort.png^\\[brighten",
@ -65,6 +77,9 @@ local PNG = {
exit_hover = "i3_exit.png^\\[brighten", exit_hover = "i3_exit.png^\\[brighten",
home_hover = "i3_home.png^\\[brighten", home_hover = "i3_home.png^\\[brighten",
edit_hover = "i3_edit.png^\\[brighten", edit_hover = "i3_edit.png^\\[brighten",
all_hover = "i3_all_on.png^\\[brighten",
node_hover = "i3_node_on.png^\\[brighten",
item_hover = "i3_item_on.png^\\[brighten",
} }
local styles = string.format([[ local styles = string.format([[
@ -72,19 +87,18 @@ local styles = string.format([[
style_type[label,field;font_size=16] style_type[label,field;font_size=16]
style_type[button;border=false;content_offset=0] style_type[button;border=false;content_offset=0]
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_middle=9;padding=-9]
style_type[item_image_button:hovered;bgimg=%s]
style[;sound=]
style[nofav;sound=i3_cannot] style[nofav;sound=i3_cannot]
style[search;content_offset=0]
style[pagenum,no_item,no_rcp;font=bold;font_size=18] style[pagenum,no_item,no_rcp;font=bold;font_size=18]
style[enable_search:hovered;bgimg=%s]
style[exit;fgimg=%s;fgimg_hovered=%s;content_offset=0] style[exit;fgimg=%s;fgimg_hovered=%s;content_offset=0]
style[cancel;fgimg=%s;fgimg_hovered=%s;content_offset=0] style[cancel;fgimg=%s;fgimg_hovered=%s;content_offset=0]
style[search;fgimg=%s;fgimg_hovered=%s;content_offset=0] style[prev_page,prev_recipe,prev_usage,prev_sort,prev_skin;fgimg=%s;fgimg_hovered=%s]
style[prev_page;fgimg=%s;fgimg_hovered=%s] style[next_page,next_recipe,next_usage,next_sort,next_skin;fgimg=%s;fgimg_hovered=%s]
style[next_page;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]
@ -97,17 +111,13 @@ local styles = string.format([[
style[confirm_trash_yes;sound=i3_trash] style[confirm_trash_yes;sound=i3_trash]
]], ]],
PNG.slot, PNG.slot,
PNG.exit, PNG.exit_hover, PNG.search_outline,
PNG.cancel, PNG.cancel_hover, PNG.exit, PNG.exit_hover,
PNG.search, PNG.search_hover, PNG.cancel, PNG.cancel_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.add, PNG.add_hover,
PNG.next, PNG.next_hover, PNG.edit, PNG.edit_hover)
PNG.prev, PNG.prev_hover,
PNG.next, PNG.next_hover,
PNG.add, PNG.add_hover,
PNG.edit, PNG.edit_hover)
local fs_elements = { local fs_elements = {
label = "label[%f,%f;%s]", label = "label[%f,%f;%s]",
@ -116,9 +126,10 @@ local fs_elements = {
tooltip = "tooltip[%f,%f;%f,%f;%s]", tooltip = "tooltip[%f,%f;%f,%f;%s]",
button = "button[%f,%f;%f,%f;%s;%s]", button = "button[%f,%f;%f,%f;%s;%s]",
checkbox = "checkbox[%f,%f;%s;%s;%s]", checkbox = "checkbox[%f,%f;%s;%s;%s]",
slot = "image[%f,%f;%f,%f;" .. fmt("%s;9]", PNG.slot),
item_image = "item_image[%f,%f;%f,%f;%s]", item_image = "item_image[%f,%f;%f,%f;%s]",
hypertext = "hypertext[%f,%f;%f,%f;%s;%s]", hypertext = "hypertext[%f,%f;%f,%f;%s;%s]",
bg9 = "background9[%f,%f;%f,%f;%s;false;%u]", bg9 = "background9[%f,%f;%f,%f;%s;false;12]",
scrollbar = "scrollbar[%f,%f;%f,%f;%s;%s;%u]", scrollbar = "scrollbar[%f,%f;%f,%f;%s;%s;%u]",
model = "model[%f,%f;%f,%f;%s;%s;%s;%s;%s;%s;%s]", model = "model[%f,%f;%f,%f;%s;%s;%s;%s;%s;%s;%s]",
image_button = "image_button[%f,%f;%f,%f;%s;%s;%s]", image_button = "image_button[%f,%f;%f,%f;%s;%s;%s]",

View File

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

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,
})

BIN
textures/i3_all.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
textures/i3_all_on.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
textures/i3_armor_1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

BIN
textures/i3_armor_2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 B

BIN
textures/i3_armor_3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

BIN
textures/i3_armor_4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

BIN
textures/i3_armor_5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
textures/i3_bg_goto.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 B

BIN
textures/i3_crafting.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
textures/i3_cube.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

BIN
textures/i3_find_more.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 B

BIN
textures/i3_highlight.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 B

BIN
textures/i3_item.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
textures/i3_item_on.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
textures/i3_no_result.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
textures/i3_node.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
textures/i3_node_on.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 507 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

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