From 106fd8daeb44cbcf9d860d16238ab3e23905fd8e Mon Sep 17 00:00:00 2001 From: Jean-Patrick Guerrero Date: Wed, 30 Dec 2020 23:21:05 +0100 Subject: [PATCH] Init commit --- .luacheckrc | 17 + API.md | 214 +++ LICENSE | 50 +- README.md | 26 +- init.lua | 2541 ++++++++++++++++++++++++++++++++++ license.txt | 59 + locale/i3.de.tr | 60 + locale/i3.fr.tr | 69 + locale/i3.it.tr | 60 + locale/i3.ru.tr | 19 + locale/i3.zh_CN.tr | 40 + locale/template | 69 + mod.conf | 2 + settingtypes.txt | 2 + sounds/i3_click.ogg | Bin 0 -> 6220 bytes sounds/i3_craft.ogg | Bin 0 -> 12926 bytes sounds/i3_delete.ogg | Bin 0 -> 8596 bytes sounds/i3_tab.ogg | Bin 0 -> 6421 bytes textures/i3_arrow.png | Bin 0 -> 469 bytes textures/i3_bg.png | Bin 0 -> 1297 bytes textures/i3_bg_full.png | Bin 0 -> 2701 bytes textures/i3_book.png | Bin 0 -> 2247 bytes textures/i3_btn9.png | Bin 0 -> 146 bytes textures/i3_btn9_hovered.png | Bin 0 -> 146 bytes textures/i3_btn9_pressed.png | Bin 0 -> 146 bytes textures/i3_cancel.png | Bin 0 -> 4307 bytes textures/i3_compress.png | Bin 0 -> 2825 bytes textures/i3_delete.png | Bin 0 -> 4539 bytes textures/i3_export.png | Bin 0 -> 6495 bytes textures/i3_fav.png | Bin 0 -> 7051 bytes textures/i3_fav_off.png | Bin 0 -> 5095 bytes textures/i3_fire_anim.png | Bin 0 -> 7434 bytes textures/i3_furnace_anim.png | Bin 0 -> 5268 bytes textures/i3_hb_bg.png | Bin 0 -> 509 bytes textures/i3_heart.png | Bin 0 -> 279 bytes textures/i3_heart_half.png | Bin 0 -> 5204 bytes textures/i3_mesepick.png | Bin 0 -> 2407 bytes textures/i3_next.png | Bin 0 -> 6209 bytes textures/i3_next_hover.png | Bin 0 -> 4011 bytes textures/i3_search.png | Bin 0 -> 7679 bytes textures/i3_shapeless.png | Bin 0 -> 3982 bytes textures/i3_slot.png | Bin 0 -> 567 bytes textures/i3_sort.png | Bin 0 -> 6278 bytes textures/i3_sort2.png | Bin 0 -> 7268 bytes textures/i3_steelpick.png | Bin 0 -> 2309 bytes textures/i3_tab.png | Bin 0 -> 950 bytes textures/i3_tab_hover.png | Bin 0 -> 16499 bytes textures/i3_trash.png | Bin 0 -> 1827 bytes 48 files changed, 3220 insertions(+), 8 deletions(-) create mode 100644 .luacheckrc create mode 100644 API.md create mode 100644 init.lua create mode 100644 license.txt create mode 100644 locale/i3.de.tr create mode 100644 locale/i3.fr.tr create mode 100644 locale/i3.it.tr create mode 100644 locale/i3.ru.tr create mode 100644 locale/i3.zh_CN.tr create mode 100644 locale/template create mode 100644 mod.conf create mode 100644 settingtypes.txt create mode 100755 sounds/i3_click.ogg create mode 100755 sounds/i3_craft.ogg create mode 100755 sounds/i3_delete.ogg create mode 100755 sounds/i3_tab.ogg create mode 100644 textures/i3_arrow.png create mode 100644 textures/i3_bg.png create mode 100644 textures/i3_bg_full.png create mode 100644 textures/i3_book.png create mode 100644 textures/i3_btn9.png create mode 100644 textures/i3_btn9_hovered.png create mode 100644 textures/i3_btn9_pressed.png create mode 100644 textures/i3_cancel.png create mode 100644 textures/i3_compress.png create mode 100644 textures/i3_delete.png create mode 100644 textures/i3_export.png create mode 100644 textures/i3_fav.png create mode 100644 textures/i3_fav_off.png create mode 100644 textures/i3_fire_anim.png create mode 100644 textures/i3_furnace_anim.png create mode 100644 textures/i3_hb_bg.png create mode 100644 textures/i3_heart.png create mode 100644 textures/i3_heart_half.png create mode 100644 textures/i3_mesepick.png create mode 100644 textures/i3_next.png create mode 100644 textures/i3_next_hover.png create mode 100644 textures/i3_search.png create mode 100644 textures/i3_shapeless.png create mode 100644 textures/i3_slot.png create mode 100644 textures/i3_sort.png create mode 100644 textures/i3_sort2.png create mode 100644 textures/i3_steelpick.png create mode 100644 textures/i3_tab.png create mode 100644 textures/i3_tab_hover.png create mode 100644 textures/i3_trash.png diff --git a/.luacheckrc b/.luacheckrc new file mode 100644 index 0000000..04cef09 --- /dev/null +++ b/.luacheckrc @@ -0,0 +1,17 @@ +unused_args = false +allow_defined_top = true + +read_globals = { + "minetest", + "default", + "armor", + "vector", + "string", + "table", + "ItemStack", +} + +globals = { + "craftguide", + "core", +} diff --git a/API.md b/API.md new file mode 100644 index 0000000..82c92f4 --- /dev/null +++ b/API.md @@ -0,0 +1,214 @@ +## API + +### Custom recipes + +Custom recipes are nonconventional crafts outside the main crafting grid. +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. +The width is automatically calculated depending where you place the commas. Look at the examples attentively. + +#### Registering a custom crafting type (example) + +```Lua +craftguide.register_craft_type("digging", { + description = "Digging", + icon = "default_tool_steelpick.png", +}) +``` + +#### Registering a custom crafting recipe (examples) + +```Lua +craftguide.register_craft({ + type = "digging", + result = "default:cobble 2", + items = {"default:stone"}, +}) +``` + +```Lua +craftguide.register_craft({ + result = "default:cobble 16", + items = { + "default:stone, default:stone, default:stone", + "default:stone, , default:stone", + "default:stone, default:stone, default:stone", + } +}) +``` + +Recipes can be registered in a Minecraft-like way: + +```Lua +craftguide.register_craft({ + grid = { + "X #", + " ## ", + "X#X#", + "X X", + }, + key = { + ['#'] = "default:wood", + ['X'] = "default:glass", + }, + result = "default:mese 3", +}) +``` + +Multiples recipes can also be registered: + +```Lua +craftguide.register_craft({ + { + result = "default:mese", + items = { + "default:mese_crystal, default:mese_crystal", + "default:mese_crystal, default:mese_crystal", + } + }, + + big = { + result = "default:mese 4", + items = { + "default:mese_crystal, default:mese_crystal", + "default:mese_crystal, default:mese_crystal", + "default:mese_crystal, default:mese_crystal", + "default:mese_crystal, default:mese_crystal", + } + }, +}) +``` + +Recipes can be registered from a given URL containing a JSON file (HTTP support is required¹): + +```Lua +craftguide.register_craft({ + url = "https://raw.githubusercontent.com/minetest-mods/craftguide/master/test.json" +}) +``` + +--- + +### Recipe filters + +Recipe filters can be used to filter the recipes shown to players. Progressive +mode is implemented as a recipe filter. + +#### `craftguide.add_recipe_filter(name, function(recipes, player))` + +Adds a recipe filter with the given name. The filter function should return 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 +`minetest.get_craft_recipe`. + +Example function to hide recipes for items from a mod called "secretstuff": + +```lua +craftguide.add_recipe_filter("Hide secretstuff", function(recipes) + local filtered = {} + for _, recipe in ipairs(recipes) do + if recipe.output:sub(1,12) ~= "secretstuff:" then + filtered[#filtered + 1] = recipe + end + end + + return filtered +end) +``` + +#### `craftguide.set_recipe_filter(name, function(recipe, player))` + +Removes all recipe filters and adds a new one. + +#### `craftguide.remove_recipe_filter(name)` + +Removes the recipe filter with the given name. + +#### `craftguide.get_recipe_filters()` + +Returns a map of recipe filters, indexed by name. + +--- + +### Search filters + +Search filters are used to perform specific searches inside the search field. +They can be used like so: `+=,,<...>` + +Examples: + +- `+groups=cracky,crumbly`: search for groups `cracky` and `crumbly` in all items. +- `sand+groups=falling_node`: search for group `falling_node` for items which contain `sand` in their names. + +Notes: +- If `optional name` is omitted, the search filter will apply to all items, without pre-filtering. +- Filters can be combined. +- The `groups` filter is currently implemented by default. + +#### `craftguide.add_search_filter(name, function(item, values))` + +Adds a search filter with the given name. +The search function should return a boolean value (whether the given item should be listed or not). + +Example function to show items which contain at least a recipe of given width(s): + +```lua +craftguide.add_search_filter("widths", function(item, widths) + local has_width + local recipes = recipes_cache[item] + + if recipes then + for i = 1, #recipes do + local recipe_width = recipes[i].width + for j = 1, #widths do + local width = tonumber(widths[j]) + if width == recipe_width then + has_width = true + break + end + end + end + end + + return has_width +end) +``` + +#### `craftguide.remove_search_filter(name)` + +Removes the search filter with the given name. + +#### `craftguide.get_search_filters()` + +Returns a map of search filters, indexed by name. + +--- + +### Miscellaneous + +#### `craftguide.show(player_name, item, show_usages)` + +Opens the Crafting Guide with the current filter applied. + + * `player_name`: string param. + * `item`: optional, string param. If set, this item is pre-selected. If the item does not exist or has no recipe, use the player's previous selection. By default, player's previous selection is used + * `show_usages`: optional, boolean param. If true, show item usages. + +#### `craftguide.group_stereotypes` + +This is the table indexing the item groups by stereotypes. +You can add a stereotype like so: + +```Lua +craftguide.group_stereotypes.radioactive = "mod:item" +``` + +#### `craftguide.export_url` + +If set, the mod will export all the cached recipes and usages in a JSON format +to the given URL (HTTP support is required¹). + +--- + +**¹** Add `craftguide` to the `secure.http_mods` or `secure.trusted_mods` setting in `minetest.conf`. diff --git a/LICENSE b/LICENSE index e6cb1e8..ed928e7 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,9 @@ -MIT License +License of source code +---------------------- -Copyright (c) 2020 Jean-Patrick Guerrero +The MIT License (MIT) + +Copyright (c) 2015-present Jean-Patrick Guerrero and contributors. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -9,13 +12,48 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +Licenses of media (textures) +---------------------------- + +paramat (CC BY-SA 3.0): + i3_arrow.png - derived from a texture by BlockMen (CC BY-SA 3.0) + +You are free to: +Share — copy and redistribute the material in any medium or format. +Adapt — remix, transform, and build upon the material for any purpose, even commercially. +The licensor cannot revoke these freedoms as long as you follow the license terms. + +Under the following terms: + +Attribution — You must give appropriate credit, provide a link to the license, and +indicate if changes were made. You may do so in any reasonable manner, but not in any way +that suggests the licensor endorses you or your use. + +ShareAlike — If you remix, transform, or build upon the material, you must distribute +your contributions under the same license as the original. + +No additional restrictions — You may not apply legal terms or technological measures that +legally restrict others from doing anything the license permits. + +Notices: + +You do not have to comply with the license for elements of the material in the public +domain or where your use is permitted by an applicable exception or limitation. +No warranties are given. The license may not give you all of the permissions necessary +for your intended use. For example, other rights such as publicity, privacy, or moral +rights may limit how you use the material. + +For more details: +http://creativecommons.org/licenses/by-sa/3.0/ diff --git a/README.md b/README.md index 2eb563b..9665ece 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,24 @@ -# i3 -Next-gen inventory for Minetest +# ![Preview1](http://i.imgur.com/fIPNYkb.png) Crafting Guide + +[![ContentDB](https://content.minetest.net/packages/jp/craftguide/shields/title/)](https://content.minetest.net/packages/jp/craftguide/) [![ContentDB](https://content.minetest.net/packages/jp/craftguide/shields/downloads/)](https://content.minetest.net/packages/jp/craftguide/) + +#### `craftguide` is the most comprehensive crafting guide on Minetest. +#### Consult the [Minetest Wiki](http://wiki.minetest.net/Crafting_guide) for more details. + +This crafting guide is a blue book named *"Crafting Guide"* or a wooden sign. + +This crafting guide features a **progressive mode**. +This mode is a Terraria-like system that shows recipes you can craft +from items you ever had in your inventory. To enable it: `craftguide_progressive_mode = true` in `minetest.conf`. + +`craftguide` is also integrated in `sfinv` (Minetest Game inventory). To enable it: +`craftguide_sfinv_only = true` in `minetest.conf`. + +Use the command `/craft` to show the recipe(s) of the pointed node. + +For developers, `craftguide` also has a [modding API](https://github.com/minetest-mods/craftguide/blob/master/API.md). + +Love this mod? Donations are appreciated: https://www.paypal.me/jpg84240 + + +![Preview2](https://user-images.githubusercontent.com/7883281/103141399-113b5e00-46f4-11eb-96cd-0167972ca1cf.png) diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..7265b1c --- /dev/null +++ b/init.lua @@ -0,0 +1,2541 @@ +i3 = {} + +-- Caches +local pdata = {} +local init_items = {} +local searches = {} +local recipes_cache = {} +local usages_cache = {} +local fuel_cache = {} +local replacements = {fuel = {}} +local toolrepair + +local progressive_mode = core.settings:get_bool "i3_progressive_mode" +local __3d_armor + +local http = core.request_http_api() +local singleplayer = core.is_singleplayer() + +local reg_items = core.registered_items +local reg_tools = core.registered_tools +local reg_entities = core.registered_entities +local reg_aliases = core.registered_aliases + +local log = core.log +local after = core.after +local clr = core.colorize +local parse_json = core.parse_json +local write_json = core.write_json +local chat_send = core.chat_send_player +local show_formspec = core.show_formspec +local globalstep = core.register_globalstep +local on_shutdown = core.register_on_shutdown +local get_players = core.get_connected_players +local get_craft_result = core.get_craft_result +local translate = minetest.get_translated_string +local on_joinplayer = core.register_on_joinplayer +local get_all_recipes = core.get_all_craft_recipes +local register_command = core.register_chatcommand +local get_player_by_name = core.get_player_by_name +local slz, dslz = core.serialize, core.deserialize +local on_mods_loaded = core.register_on_mods_loaded +local on_leaveplayer = core.register_on_leaveplayer +local get_player_info = core.get_player_information +local on_receive_fields = core.register_on_player_receive_fields + +local ESC = core.formspec_escape +local S = core.get_translator "i3" + +local ES = function(...) + return ESC(S(...)) +end + +local maxn, sort, concat, copy, insert, remove = + table.maxn, table.sort, table.concat, table.copy, + table.insert, table.remove + +local sprintf, find, gmatch, match, sub, split, upper, lower = + string.format, string.find, string.gmatch, string.match, + string.sub, string.split, string.upper, string.lower + +local min, max, floor, ceil, abs = math.min, math.max, math.floor, math.ceil, math.abs +local pairs, ipairs, next, type, setmetatable, tonum = + pairs, ipairs, next, type, setmetatable, tonumber + +local vec_add, vec_mul = vector.add, vector.multiply + +local ROWS = 9 +local LINES = 10 +local IPP = ROWS * LINES +local MAX_FAVS = 6 +local ITEM_BTN_SIZE = 1.1 + +-- Progressive mode +local POLL_FREQ = 0.25 +local HUD_TIMER_MAX = 1.5 + +local MIN_FORMSPEC_VERSION = 4 + +local PNG = { + bg = "i3_bg.png", + bg_full = "i3_bg_full.png", + search = "i3_search.png", + prev = "i3_next.png^\\[transformFX", + next = "i3_next.png", + arrow = "i3_arrow.png", + trash = "i3_trash.png", + sort_az = "i3_sort.png", + sort_za = "i3_sort2.png", + compress = "i3_compress.png", + fire = "i3_fire.png", + fire_anim = "i3_fire_anim.png", + book = "i3_book.png", + sign = "i3_sign.png", + cancel = "i3_cancel.png", + export = "i3_export.png", + slot = "i3_slot.png", + tab = "i3_tab.png", + furnace_anim = "i3_furnace_anim.png", + + cancel_hover = "i3_cancel.png^\\[brighten", + search_hover = "i3_search.png^\\[brighten", + export_hover = "i3_export.png^\\[brighten", + trash_hover = "i3_trash.png^\\[brighten", + compress_hover = "i3_compress.png^\\[brighten", + sort_az_hover = "i3_sort.png^\\[brighten", + sort_za_hover = "i3_sort2.png^\\[brighten", + prev_hover = "i3_next_hover.png^\\[transformFX", + next_hover = "i3_next_hover.png", + tab_hover = "i3_tab_hover.png", +} + +local fs_elements = { + box = "box[%f,%f;%f,%f;%s]", + label = "label[%f,%f;%s]", + image = "image[%f,%f;%f,%f;%s]", + button = "button[%f,%f;%f,%f;%s;%s]", + tooltip = "tooltip[%f,%f;%f,%f;%s]", + item_image = "item_image[%f,%f;%f,%f;%s]", + bg9 = "background9[%f,%f;%f,%f;%s;false;%u]", + model = "model[%f,%f;%f,%f;%s;%s;%s;%s;%s;true;%s]", + image_button = "image_button[%f,%f;%f,%f;%s;%s;%s]", + animated_image = "animated_image[%f,%f;%f,%f;;%s;%u;%u]", + scrollbar = "scrollbar[%f,%f;%f,%f;horizontal;%s;%u]", + item_image_button = "item_image_button[%f,%f;%f,%f;%s;%s;%s]", +} + +local styles = sprintf([[ + style_type[label,field;font_size=+0] + style_type[image_button;border=false;sound=i3_click] + style_type[item_image_button;border=false;bgimg_hovered=%s;sound=i3_click] + + style[filter;border=false] + style[cancel;fgimg=%s;fgimg_hovered=%s;content_offset=0] + style[search;fgimg=%s;fgimg_hovered=%s;content_offset=0] + style[trash;fgimg=%s;fgimg_hovered=%s;content_offset=0;sound=i3_delete] + style[sort_az;fgimg=%s;fgimg_hovered=%s;content_offset=0] + style[sort_za;fgimg=%s;fgimg_hovered=%s;content_offset=0] + style[compress;fgimg=%s;fgimg_hovered=%s;content_offset=0] + style[prev_page;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[guide_mode,inv_mode;fgimg_hovered=%s;noclip=true;content_offset=0;sound=i3_tab] + style[pagenum,no_item,no_rcp;border=false;font=bold;font_size=+2;content_offset=0] + style[craft_rcp,craft_usg;border=false;noclip=true;font_size=+0;sound=i3_craft; + bgimg=i3_btn9.png;bgimg_hovered=i3_btn9_hovered.png; + bgimg_pressed=i3_btn9_pressed.png;bgimg_middle=4,6] +]], +PNG.slot, +PNG.cancel, PNG.cancel_hover, +PNG.search, PNG.search_hover, +PNG.trash, PNG.trash_hover, +PNG.sort_az, PNG.sort_az_hover, +PNG.sort_za, PNG.sort_za_hover, +PNG.compress, PNG.compress_hover, +PNG.prev, PNG.prev_hover, +PNG.next, PNG.next_hover, +PNG.prev, PNG.prev_hover, +PNG.next, PNG.next_hover, +PNG.prev, PNG.prev_hover, +PNG.next, PNG.next_hover, +PNG.tab_hover) + +local function get_lang_code(info) + return info and info.lang_code +end + +local function get_formspec_version(info) + return info and info.formspec_version or 1 +end + +local function outdated(name) + local fs = sprintf([[ + size[7.1,1.3] + image[0,0;1,1;%s] + label[1,0;%s] + button_exit[3.1,0.8;1,1;;OK] + ]], + PNG.book, + "Your Minetest client is outdated.\n" .. + "Get the latest version on minetest.net to use the i3 inventory.") + + return show_formspec(name, "i3", fs) +end + +i3.group_stereotypes = { + dye = "dye:white", + wool = "wool:white", + wood = "default:wood", + tree = "default:tree", + sand = "default:sand", + glass = "default:glass", + stick = "default:stick", + stone = "default:stone", + leaves = "default:leaves", + coal = "default:coal_lump", + vessel = "vessels:glass_bottle", + flower = "flowers:dandelion_yellow", + water_bucket = "bucket:bucket_water", + mesecon_conductor_craftable = "mesecons:wire_00000000_off", +} + +local group_names = { + dye = S"Any dye", + coal = S"Any coal", + sand = S"Any sand", + tree = S"Any tree", + wool = S"Any wool", + glass = S"Any glass", + stick = S"Any stick", + stone = S"Any stone", + carpet = S"Any carpet", + flower = S"Any flower", + leaves = S"Any leaves", + vessel = S"Any vessel", + wood = S"Any wood planks", + mushroom = S"Any mushroom", + + ["color_red,flower"] = S"Any red flower", + ["color_blue,flower"] = S"Any blue flower", + ["color_black,flower"] = S"Any black flower", + ["color_white,flower"] = S"Any white flower", + ["color_green,flower"] = S"Any green flower", + ["color_orange,flower"] = S"Any orange flower", + ["color_yellow,flower"] = S"Any yellow flower", + ["color_violet,flower"] = S"Any violet flower", + + ["color_red,dye"] = S"Any red dye", + ["color_blue,dye"] = S"Any blue dye", + ["color_grey,dye"] = S"Any grey dye", + ["color_pink,dye"] = S"Any pink dye", + ["color_cyan,dye"] = S"Any cyan dye", + ["color_black,dye"] = S"Any black dye", + ["color_white,dye"] = S"Any white dye", + ["color_brown,dye"] = S"Any brown dye", + ["color_green,dye"] = S"Any green dye", + ["color_orange,dye"] = S"Any orange dye", + ["color_yellow,dye"] = S"Any yellow dye", + ["color_violet,dye"] = S"Any violet dye", + ["color_magenta,dye"] = S"Any magenta dye", + ["color_dark_grey,dye"] = S"Any dark grey dye", + ["color_dark_green,dye"] = S"Any dark green dye", +} + +i3.model_alias = { + ["boats:boat"] = {name = "boats:boat", drawtype = "entity"}, + ["carts:cart"] = {name = "carts:cart", drawtype = "entity", frames = "0,0"}, + ["default:chest"] = {name = "default:chest_open"}, + ["default:chest_locked"] = {name = "default:chest_locked_open"}, + ["doors:door_wood"] = {name = "doors:door_wood_a"}, + ["doors:door_glass"] = {name = "doors:door_glass_a"}, + ["doors:door_obsidian_glass"] = {name = "doors:door_obsidian_glass_a"}, + ["doors:door_steel"] = {name = "doors:door_steel_a"}, + ["xpanes:door_steel_bar"] = {name = "xpanes:door_steel_bar_a"}, +} + +local function err(str) + return log("error", str) +end + +local function msg(name, str) + return chat_send(name, sprintf("[i3] %s", str)) +end + +local function is_str(x) + return type(x) == "string" +end + +local function true_str(str) + return is_str(str) and str ~= "" +end + +local function is_table(x) + return type(x) == "table" +end + +local function is_func(x) + return type(x) == "function" +end + +local function is_group(item) + return sub(item, 1, 6) == "group:" +end + +local function fmt(elem, ...) + return sprintf(fs_elements[elem], ...) +end + +local function clean_name(item) + if sub(item, 1, 1) == ":" then + item = sub(item, 2) + end + + return item +end + +local function array_diff(t1, t2) + local hash = {} + + for i = 1, #t1 do + local v = t1[i] + hash[v] = true + end + + for i = 1, #t2 do + local v = t2[i] + hash[v] = nil + end + + local diff, c = {}, 0 + + for i = 1, #t1 do + local v = t1[i] + if hash[v] then + c = c + 1 + diff[c] = v + end + end + + return diff +end + +local function table_eq(T1, T2) + local avoid_loops = {} + + local function recurse(t1, t2) + if type(t1) ~= type(t2) then return end + + if not is_table(t1) then + return t1 == t2 + end + + if avoid_loops[t1] then + return avoid_loops[t1] == t2 + end + + avoid_loops[t1] = t2 + local t2k, t2kv = {}, {} + + for k in pairs(t2) do + if is_table(k) then + insert(t2kv, k) + end + + t2k[k] = true + end + + for k1, v1 in pairs(t1) do + local v2 = t2[k1] + if type(k1) == "table" then + local ok + for i = 1, #t2kv do + local tk = t2kv[i] + if table_eq(k1, tk) and recurse(v1, t2[tk]) then + remove(t2kv, i) + t2k[tk] = nil + ok = true + break + end + end + + if not ok then return end + else + if v2 == nil then return end + t2k[k1] = nil + if not recurse(v1, v2) then return end + end + end + + if next(t2k) then return end + return true + end + + return recurse(T1, T2) +end + +local function table_merge(t1, t2, hash) + t1 = t1 or {} + t2 = t2 or {} + + if hash then + for k, v in pairs(t2) do + t1[k] = v + end + else + local c = #t1 + + for i = 1, #t2 do + c = c + 1 + t1[c] = t2[i] + end + end + + return t1 +end + +local function table_replace(t, val, new) + for k, v in pairs(t) do + if v == val then + t[k] = new + end + end +end + +local craft_types = {} + +function i3.register_craft_type(name, def) + if not true_str(name) then + return err "i3.register_craft_type(): name missing" + end + + if not is_str(def.description) then + def.description = "" + end + + if not is_str(def.icon) then + def.icon = "" + end + + craft_types[name] = def +end + +function i3.register_craft(def) + local width, c = 0, 0 + + if true_str(def.url) then + if not http then + return err(sprintf([[i3.register_craft(): Unable to reach %s. + No HTTP support for this mod: add it to the `secure.http_mods` or + `secure.trusted_mods` setting.]], def.url)) + end + + http.fetch({url = def.url}, function(result) + if result.succeeded then + local t = parse_json(result.data) + if is_table(t) then + return i3.register_craft(t) + end + end + end) + + return + end + + if not is_table(def) or not next(def) then + return err "i3.register_craft(): craft definition missing" + end + + if #def > 1 then + for _, v in pairs(def) do + i3.register_craft(v) + end + return + end + + if def.result then + def.output = def.result -- Backward compatibility + def.result = nil + end + + if not true_str(def.output) then + return err "i3.register_craft(): output missing" + end + + if not is_table(def.items) then + def.items = {} + end + + if def.grid then + if not is_table(def.grid) then + def.grid = {} + end + + if not is_table(def.key) then + def.key = {} + end + + local cp = copy(def.grid) + sort(cp, function(a, b) + return #a > #b + end) + + width = #cp[1] + + for i = 1, #def.grid do + while #def.grid[i] < width do + def.grid[i] = def.grid[i] .. " " + end + end + + for symbol in gmatch(concat(def.grid), ".") do + c = c + 1 + def.items[c] = def.key[symbol] + end + else + local items, len = def.items, #def.items + def.items = {} + + for i = 1, len do + items[i] = items[i]:gsub(",", ", ") + local rlen = #split(items[i], ",") + + if rlen > width then + width = rlen + end + end + + for i = 1, len do + while #split(items[i], ",") < width do + items[i] = items[i] .. ", " + end + end + + for name in gmatch(concat(items, ","), "[%s%w_:]+") do + c = c + 1 + def.items[c] = match(name, "%S+") + end + end + + local item = match(def.output, "%S+") + recipes_cache[item] = recipes_cache[item] or {} + + def.custom = true + def.width = width + + insert(recipes_cache[item], def) +end + +local recipe_filters = {} + +function i3.add_recipe_filter(name, f) + if not true_str(name) then + return err "i3.add_recipe_filter(): name missing" + elseif not is_func(f) then + return err "i3.add_recipe_filter(): function missing" + end + + recipe_filters[name] = f +end + +function i3.set_recipe_filter(name, f) + if not is_str(name) then + return err "i3.set_recipe_filter(): name missing" + elseif not is_func(f) then + return err "i3.set_recipe_filter(): function missing" + end + + recipe_filters = {[name] = f} +end + +function i3.remove_recipe_filter(name) + recipe_filters[name] = nil +end + +function i3.get_recipe_filters() + return recipe_filters +end + +local function apply_recipe_filters(recipes, player) + for _, filter in pairs(recipe_filters) do + recipes = filter(recipes, player) + end + + return recipes +end + +local search_filters = {} + +function i3.add_search_filter(name, f) + if not true_str(name) then + return err "i3.add_search_filter(): name missing" + elseif not is_func(f) then + return err "i3.add_search_filter(): function missing" + end + + search_filters[name] = f +end + +function i3.remove_search_filter(name) + search_filters[name] = nil +end + +function i3.get_search_filters() + return search_filters +end + +local function weird_desc(str) + return not true_str(str) or find(str, "\n") or not find(str, "%u") +end + +local function toupper(str) + return str:gsub("%f[%w]%l", upper):gsub("_", " ") +end + +local function snip(str, limit) + return #str > limit and sprintf("%s...", sub(str, 1, limit - 3)) or str +end + +local function get_desc(item, lang_code) + if sub(item, 1, 1) == "_" then + item = sub(item, 2) + end + + local def = reg_items[item] + + if def then + local desc = def.description + desc = lang_code and translate(lang_code, desc) or desc + + if true_str(desc) then + desc = desc:trim():match("[^\n]*") + + if not find(desc, "%u") then + desc = toupper(desc) + end + + return desc + + elseif true_str(item) then + return toupper(match(item, ":(.*)")) + end + end + + return S("Unknown Item (@1)", item) +end + +local function item_has_groups(item_groups, groups) + for i = 1, #groups do + local group = groups[i] + if (item_groups[group] or 0) == 0 then return end + end + + return true +end + +local function extract_groups(str) + if sub(str, 1, 6) == "group:" then + return split(sub(str, 7), ",") + end +end + +local function get_filtered_items(player, data) + local items, known, c = {}, 0, 0 + + for i = 1, #init_items do + local item = init_items[i] + local recipes = recipes_cache[item] + local usages = usages_cache[item] + + recipes = #apply_recipe_filters(recipes or {}, player) + usages = #apply_recipe_filters(usages or {}, player) + + if recipes > 0 or usages > 0 then + c = c + 1 + items[c] = item + + if data then + known = known + recipes + usages + end + end + end + + if data then + data.known_recipes = known + end + + return items +end + +local function get_burntime(item) + return get_craft_result{method = "fuel", items = {item}}.time +end + +local function cache_fuel(item) + local burntime = get_burntime(item) + if burntime > 0 then + fuel_cache[item] = { + type = "fuel", + items = {item}, + burntime = burntime, + replacements = replacements.fuel[item], + } + end +end + +local function show_item(def) + return def and def.groups.not_in_creative_inventory ~= 1 and + def.description and def.description ~= "" +end + +local function get_usages(recipe) + local added = {} + + for _, item in pairs(recipe.items) do + item = reg_aliases[item] or item + if not added[item] then + local groups = extract_groups(item) + if groups then + for name, def in pairs(reg_items) do + if not added[name] and show_item(def) and + item_has_groups(def.groups, groups) then + local usage = copy(recipe) + table_replace(usage.items, item, name) + usages_cache[name] = usages_cache[name] or {} + insert(usages_cache[name], 1, usage) + added[name] = true + end + end + elseif show_item(reg_items[item]) then + usages_cache[item] = usages_cache[item] or {} + insert(usages_cache[item], 1, recipe) + end + + added[item] = true + end + end +end + +local function cache_usages(item) + local recipes = recipes_cache[item] or {} + + for i = 1, #recipes do + get_usages(recipes[i]) + end + + if fuel_cache[item] then + usages_cache[item] = table_merge(usages_cache[item] or {}, {fuel_cache[item]}) + end +end + +local function drop_table(name, drop) + local count_sure = 0 + local drop_items = drop.items or {} + local max_items = drop.max_items + + for i = 1, #drop_items do + local di = drop_items[i] + local valid_rarity = di.rarity and di.rarity > 1 + + if di.rarity or not max_items or + (max_items and not di.rarity and count_sure < max_items) then + for j = 1, #di.items do + local dstack = ItemStack(di.items[j]) + local dname = dstack:get_name() + local dcount = dstack:get_count() + local empty = dstack:is_empty() + + if not empty and (dname ~= name or + (dname == name and dcount > 1)) then + local rarity = valid_rarity and di.rarity + + i3.register_craft{ + type = rarity and "digging_chance" or "digging", + items = {name}, + output = sprintf("%s %u", dname, dcount), + rarity = rarity, + tools = di.tools, + } + end + end + end + + if not di.rarity then + count_sure = count_sure + 1 + end + end +end + +local function cache_drops(name, drop) + if true_str(drop) then + local dstack = ItemStack(drop) + local dname = dstack:get_name() + local empty = dstack:is_empty() + + if not empty and dname ~= name then + i3.register_craft{ + type = "digging", + items = {name}, + output = drop, + } + end + elseif is_table(drop) then + drop_table(name, drop) + end +end + +local function cache_recipes(item) + local recipes = get_all_recipes(item) + + if replacements[item] then + local _recipes = {} + + for k, v in ipairs(recipes or {}) do + _recipes[#recipes + 1 - k] = v + end + + local shift = 0 + local size_rpl = maxn(replacements[item]) + local size_rcp = #_recipes + + if size_rpl > size_rcp then + shift = size_rcp - size_rpl + end + + for k, v in pairs(replacements[item]) do + k = k + shift + + if _recipes[k] then + _recipes[k].replacements = v + end + end + + recipes = _recipes + end + + if recipes then + recipes_cache[item] = table_merge(recipes, recipes_cache[item] or {}) + end +end + +local function get_recipes(item, data, player) + local clean_item = reg_aliases[item] or item + local recipes = recipes_cache[clean_item] + local usages = usages_cache[clean_item] + + if recipes then + recipes = apply_recipe_filters(recipes, player) + end + + local no_recipes = not recipes or #recipes == 0 + if no_recipes and not usages then return end + usages = apply_recipe_filters(usages, player) + + local no_usages = not usages or #usages == 0 + + return not no_recipes and recipes or nil, + not no_usages and usages or nil +end + +local function groups_to_items(groups, get_all) + if not get_all and #groups == 1 then + local group = groups[1] + local stereotype = i3.group_stereotypes[group] + local def = reg_items[stereotype] + + if def and show_item(def) then + return stereotype + end + end + + local names = {} + for name, def in pairs(reg_items) do + if show_item(def) and item_has_groups(def.groups, groups) then + if get_all then + names[#names + 1] = name + else + return name + end + end + end + + return get_all and names or "" +end + +local function sort_itemlist(player, az) + local inv = player:get_inventory() + local list = inv:get_list("main") + local size = inv:get_size("main") + local new_inv, stack_meta = {}, {} + + for i = 1, size do + local stack = list[i] + local name = stack:get_name() + local count = stack:get_count() + local empty = stack:is_empty() + local meta = stack:get_meta():to_table() + + if not empty then + if next(meta.fields) then + stack_meta[#stack_meta + 1] = stack + else + new_inv[#new_inv + 1] = sprintf("%s %u", name, count) + end + end + end + + if az then + sort(new_inv) + else + sort(new_inv, function(a, b) return a > b end) + end + + inv:set_list("main", new_inv) + + for i = 1, #stack_meta do + inv:set_stack("main", #new_inv + i, stack_meta[i]) + end +end + +local function compress_items(player) + local inv = player:get_inventory() + local list = inv:get_list("main") + local size = inv:get_size("main") + local new_inv, _new_inv, stack_meta = {}, {}, {} + + for i = 1, size do + local stack = list[i] + local name = stack:get_name() + local count = stack:get_count() + local empty = stack:is_empty() + local meta = stack:get_meta():to_table() + + if not empty then + if next(meta.fields) then + stack_meta[#stack_meta + 1] = stack + else + new_inv[name] = new_inv[name] or 0 + new_inv[name] = new_inv[name] + count + end + end + end + + for name, count in pairs(new_inv) do + local stackmax = ItemStack(name):get_stack_max() + local iter = ceil(count / stackmax) + local leftover = count + + for _ = 1, iter do + _new_inv[#_new_inv + 1] = sprintf("%s %u", name, min(stackmax, leftover)) + leftover = leftover - stackmax + end + end + + sort(_new_inv) + inv:set_list("main", _new_inv) + + for i = 1, #stack_meta do + inv:set_stack("main", #_new_inv + i, stack_meta[i]) + end +end + +local function get_stack_max(inv, data, is_recipe, rcp) + local list = inv:get_list("main") + local size = inv:get_size("main") + local counts_inv, counts_rcp, counts = {}, {}, {} + local rcp_usg = is_recipe and "recipe" or "usage" + + for _, it in pairs(rcp.items) do + counts_rcp[it] = (counts_rcp[it] or 0) + 1 + end + + data.export_counts[rcp_usg] = {} + data.export_counts[rcp_usg].rcp = counts_rcp + + for i = 1, size do + local stack = list[i] + + if not stack:is_empty() then + local item = stack:get_name() + local count = stack:get_count() + + for name in pairs(counts_rcp) do + if is_group(name) then + local def = reg_items[item] + local groups = extract_groups(name) + + if item_has_groups(def.groups, groups) then + counts_inv[name] = (counts_inv[name] or 0) + count + end + end + end + + counts_inv[item] = (counts_inv[item] or 0) + count + end + end + + data.export_counts[rcp_usg].inv = counts_inv + + for name in pairs(counts_rcp) do + counts[name] = floor((counts_inv[name] or 0) / (counts_rcp[name] or 0)) + end + + local max_stacks = math.huge + + for _, count in pairs(counts) do + if count < max_stacks then + max_stacks = count + end + end + + return max_stacks +end + +local function get_stack(player, pname, stack, message) + local inv = player:get_inventory() + + if inv:room_for_item("main", stack) then + inv:add_item("main", stack) + msg(pname, sprintf("%s added in your inventory", message)) + else + local dir = player:get_look_dir() + local ppos = player:get_pos() + ppos.y = ppos.y + 1.625 + local look_at = vec_add(ppos, vec_mul(dir, 1)) + + core.add_item(look_at, stack) + msg(pname, sprintf("%s spawned", message)) + end +end + +local function craft_stack(player, pname, data, craft_rcp) + local inv = player:get_inventory() + local rcp_usg = craft_rcp and "recipe" or "usage" + local output = craft_rcp and data.recipes[data.rnum].output or data.usages[data.unum].output + output = ItemStack(output) + local stackname, stackcount, stackmax = output:get_name(), output:get_count(), output:get_stack_max() + local scrbar_val = data[sprintf("scrbar_%s", craft_rcp and "rcp" or "usg")] or 1 + + for name, count in pairs(data.export_counts[rcp_usg].rcp) do + local items = {[name] = count} + + if is_group(name) then + items = {} + local groups = extract_groups(name) + local item_groups = groups_to_items(groups, true) + local remaining = count + + for _, item in ipairs(item_groups) do + for _name, _count in pairs(data.export_counts[rcp_usg].inv) do + if item == _name and remaining > 0 then + local c = min(remaining, _count) + items[item] = c + remaining = remaining - c + end + + if remaining == 0 then break end + end + end + end + + for k, v in pairs(items) do + inv:remove_item("main", sprintf("%s %s", k, v * scrbar_val)) + end + end + + local count = stackcount * scrbar_val + local desc = get_desc(stackname) + local iter = ceil(count / stackmax) + local leftover = count + + for _ = 1, iter do + local c = min(stackmax, leftover) + local message + + if c > 1 then + message = clr("#ff0", sprintf("%s x %s", c, desc)) + else + message = clr("#ff0", sprintf("%s", desc)) + end + + local stack = ItemStack(sprintf("%s %s", stackname, c)) + get_stack(player, pname, stack, message) + leftover = leftover - stackmax + end +end + +local function select_item(player, name, data, _f) + local item + + for field in pairs(_f) do + if find(field, ":") then + item = field + break + end + end + + if not item then + return + elseif sub(item, -4) == "_inv" then + item = sub(item, 1, -5) + elseif sub(item, 1, 1) == "_" then + item = sub(item, 2) + elseif sub(item, 1, 6) == "group|" then + item = match(item, "([%w:_]+)$") + end + + item = reg_aliases[item] or item + + if item == data.query_item then + if data.creative then + local stack = ItemStack(item) + local stackmax = stack:get_stack_max() + stack = sprintf("%s %s", item, stackmax) + get_stack(player, name, stack, clr("#ff0", sprintf("%u x %s", stackmax, item))) + end + return + end + + local recipes, usages = get_recipes(item, data, player) + + data.query_item = item + data.recipes = recipes + data.usages = usages + data.rnum = 1 + data.unum = 1 + data.scrbar_rcp = 1 + data.scrbar_usg = 1 + data.export_rcp = nil + data.export_usg = nil +end + +local function repairable(tool) + local def = reg_tools[tool] + return toolrepair and def and def.groups and def.groups.disable_repair ~= 1 +end + +local function is_fav(favs, query_item) + local fav, i + for j = 1, #favs do + if favs[j] == query_item then + fav = true + i = j + break + end + end + + return fav, i +end + +local function get_tooltip(item, info) + local tooltip + + if info.groups then + sort(info.groups) + tooltip = group_names[concat(info.groups, ",")] + + if not tooltip then + local groupstr = {} + + for i = 1, #info.groups do + insert(groupstr, clr("#ff0", info.groups[i])) + end + + groupstr = concat(groupstr, ", ") + tooltip = S("Any item belonging to the group(s): @1", groupstr) + end + else + tooltip = get_desc(item) + end + + local function add(str) + return sprintf("%s\n%s", tooltip, str) + end + + if info.cooktime then + tooltip = add(S("Cooking time: @1", clr("#ff0", info.cooktime))) + end + + if info.burntime then + tooltip = add(S("Burning time: @1", clr("#ff0", info.burntime))) + end + + if info.replace then + for i = 1, #info.replace.items do + local rpl = match(info.replace.items[i], "%S+") + local desc = clr("#ff0", get_desc(rpl)) + + if info.replace.type == "cooking" then + tooltip = add(S("Replaced by @1 on smelting", desc)) + elseif info.replace.type == "fuel" then + tooltip = add(S("Replaced by @1 on burning", desc)) + else + tooltip = add(S("Replaced by @1 on crafting", desc)) + end + end + end + + if info.repair then + tooltip = add(S("Repairable by step of @1", clr("#ff0", toolrepair .. "%"))) + end + + if info.rarity then + local chance = (1 / max(1, info.rarity)) * 100 + tooltip = add(S("@1 of chance to drop", clr("#ff0", chance .. "%"))) + end + + if info.tools then + local several = #info.tools > 1 + local names = several and "\n" or "" + + if several then + for i = 1, #info.tools do + names = sprintf("%s\t\t- %s\n", + names, clr("#ff0", get_desc(info.tools[i]))) + end + + tooltip = add(S("Only drop if using one of these tools: @1", + sub(names, 1, -2))) + else + tooltip = add(S("Only drop if using this tool: @1", + clr("#ff0", get_desc(info.tools[1])))) + end + end + + return sprintf("tooltip[%s;%s]", item, ESC(tooltip)) +end + +local function get_output_fs(fs, data, rcp, is_recipe, shapeless, right, btn_size, _btn_size) + local custom_recipe = craft_types[rcp.type] + + if custom_recipe or shapeless or rcp.type == "cooking" then + local icon = custom_recipe and custom_recipe.icon or + shapeless and "shapeless" or "furnace" + + if not custom_recipe then + icon = sprintf("i3_%s.png^[resize:16x16", icon) + end + + local pos_x = right + btn_size + 0.42 + local pos_y = data.yoffset + 0.9 + + if sub(icon, 1, 10) == "i3_furnace" then + fs(fmt("animated_image", pos_x, pos_y, 0.5, 0.5, PNG.furnace_anim, 8, 180)) + else + fs(fmt("image", pos_x, pos_y, 0.5, 0.5, icon)) + end + + local tooltip = custom_recipe and custom_recipe.description or + shapeless and S"Shapeless" or S"Cooking" + + fs(fmt("tooltip", pos_x, pos_y, 0.5, 0.5, ESC(tooltip))) + end + + local arrow_X = right + 0.2 + (_btn_size or ITEM_BTN_SIZE) + local X = arrow_X + 1.2 + local Y = data.yoffset + 1.4 + + fs(fmt("image", arrow_X, Y + 0.06, 1, 1, PNG.arrow)) + + if rcp.type == "fuel" then + fs(fmt("animated_image", X + 0.05, Y, ITEM_BTN_SIZE, ITEM_BTN_SIZE, PNG.fire_anim, 8, 180)) + else + local item = rcp.output + item = ItemStack(clean_name(item)) + local name = item:get_name() + local count = item:get_count() + local bt_s = ITEM_BTN_SIZE * 1.2 + + fs(fmt("image", X, Y - 0.11, bt_s, bt_s, PNG.slot)) + + local _name = sprintf("_%s", name) + + fs(fmt("item_image_button", + X + 0.1, Y, ITEM_BTN_SIZE, ITEM_BTN_SIZE, + sprintf("%s %u", name, count * (is_recipe and data.scrbar_rcp or data.scrbar_usg or 1)), + _name, "")) + + local def = reg_items[name] + local unknown = not def or nil + local desc = def and def.description + local weird = name ~= "" and desc and weird_desc(desc) or nil + local burntime = fuel_cache[name] and fuel_cache[name].burntime + + local infos = { + unknown = unknown, + weird = weird, + burntime = burntime, + repair = repairable(name), + rarity = rcp.rarity, + tools = rcp.tools, + } + + if next(infos) then + fs(get_tooltip(_name, infos)) + end + end +end + +local function get_grid_fs(fs, data, rcp, is_recipe) + local width = rcp.width or 1 + local right, btn_size, _btn_size = 0, ITEM_BTN_SIZE + local cooktime, shapeless + + if rcp.type == "cooking" then + cooktime, width = width, 1 + elseif width == 0 and not rcp.custom then + shapeless = true + local n = #rcp.items + width = (n < 5 and n > 1) and 2 or min(3, max(1, n)) + end + + local rows = ceil(maxn(rcp.items) / width) + local large_recipe = width > 3 or rows > 3 + + if large_recipe then + fs("style_type[item_image_button;border=true]") + end + + for i = 1, width * rows do + local item = rcp.items[i] or "" + item = clean_name(item) + local name = match(item, "%S*") + + local X = ceil((i - 1) % width - width) + X = X + (X * 0.2) + data.xoffset + 3.9 + + local Y = ceil(i / width) - min(2, rows) + Y = Y + (Y * 0.15) + data.yoffset + 1.4 + + if large_recipe then + btn_size = (3 / width) * (3 / rows) + 0.3 + _btn_size = btn_size + + local xi = (i - 1) % width + local yi = floor((i - 1) / width) + + X = btn_size * xi + data.xoffset + 0.3 + (xi * 0.05) + Y = btn_size * yi + data.yoffset + 0.2 + (yi * 0.05) + end + + if X > right then + right = X + end + + local groups + + if is_group(name) then + groups = extract_groups(name) + item = groups_to_items(groups) + end + + local label = groups and "\nG" or "" + local replace + + for j = 1, #(rcp.replacements or {}) do + local replacement = rcp.replacements[j] + if replacement[1] == name then + replace = replace or {type = rcp.type, items = {}} + + local added + + for _, v in ipairs(replace.items) do + if replacement[2] == v then + added = true + break + end + end + + if not added then + label = sprintf("%s%s\nR", label ~= "" and "\n" or "", label) + replace.items[#replace.items + 1] = replacement[2] + end + end + end + + if not large_recipe then + fs(fmt("image", X, Y, btn_size, btn_size, PNG.slot)) + end + + local btn_name = groups and sprintf("group|%s|%s", groups[1], item) or item + + fs(fmt("item_image_button", X, Y, btn_size, btn_size, + sprintf("%s %u", item, is_recipe and data.scrbar_rcp or data.scrbar_usg or 1), + btn_name, label)) + + local def = reg_items[name] + local unknown = not def or nil + unknown = not groups and unknown or nil + local desc = def and def.description + local weird = name ~= "" and desc and weird_desc(desc) or nil + local burntime = fuel_cache[name] and fuel_cache[name].burntime + + local infos = { + unknown = unknown, + weird = weird, + groups = groups, + burntime = burntime, + cooktime = cooktime, + replace = replace, + } + + if next(infos) then + fs(get_tooltip(btn_name, infos)) + end + end + + if large_recipe then + fs("style_type[item_image_button;border=false]") + end + + get_output_fs(fs, data, rcp, is_recipe, shapeless, right, btn_size, _btn_size) +end + +local function get_rcp_lbl(fs, data, panel, rn, is_recipe) + local lbl = ES("Usage @1 of @2", data.unum, rn) + + if is_recipe then + lbl = ES("Recipe @1 of @2", data.rnum, rn) + end + + local _lbl = translate(data.lang_code, lbl) + local lbl_len = #_lbl:gsub("[\128-\191]", "") -- Count chars, not bytes in UTF-8 strings + local shift = min(0.9, abs(12 - max(12, lbl_len)) * 0.15) + + fs(fmt("label", data.xoffset + 5.65 - shift, data.yoffset + 3.37, lbl)) + + if rn > 1 then + local btn_suffix = is_recipe and "recipe" or "usage" + local prev_name = sprintf("prev_%s", btn_suffix) + local next_name = sprintf("next_%s", btn_suffix) + local x_arrow = data.xoffset + 5.09 + local y_arrow = data.yoffset + 3.2 + + fs(fmt("image_button", x_arrow - shift, y_arrow, 0.3, 0.3, "", prev_name, ""), + fmt("image_button", x_arrow + 2.3, y_arrow, 0.3, 0.3, "", next_name, "")) + end + + local rcp = is_recipe and panel.rcp[data.rnum] or panel.rcp[data.unum] + get_grid_fs(fs, data, rcp, is_recipe) +end + +local function get_model_fs(fs, data, def, model_alias) + if model_alias then + if model_alias.drawtype == "entity" then + def = reg_entities[model_alias.name] + local init_props = def.initial_properties + def.textures = init_props and init_props.textures or def.textures + def.mesh = init_props and init_props.mesh or def.mesh + else + def = reg_items[model_alias.name] + end + end + + local tiles = def.tiles or def.textures or {} + local t = {} + + for _, v in ipairs(tiles) do + local _name + + if v.color then + local hex = sprintf("%02x", v.color) + + while #hex < 8 do + hex = "0" .. hex + end + + _name = sprintf("%s^[multiply:%s", v.name, + sprintf("#%s%s", sub(hex, 3), sub(hex, 1, 2))) + + elseif v.animation then + _name = sprintf("%s^[verticalframe:%u:0", v.name, v.animation.aspect_h) + end + + t[#t + 1] = _name or v.name or v + end + + while #t < 6 do + t[#t + 1] = t[#t] + end + + fs(fmt("model", + data.xoffset + 6.6, data.yoffset + 0.05, 1.3, 1.3, "", + def.mesh, concat(t, ","), "0,0", "true", model_alias and model_alias.frames or "")) +end + +local function get_header(fs, data) + local fav = is_fav(data.favs, data.query_item) + local nfavs = #data.favs + local star_x, star_y, star_size = data.xoffset + 0.4, data.yoffset + 0.5, 0.4 + + if nfavs < MAX_FAVS or (nfavs == MAX_FAVS and fav) then + local fav_marked = sprintf("i3_fav%s.png", fav and "_off" or "") + + fs(sprintf("style[fav;fgimg=%s;fgimg_hovered=%s;fgimg_pressed=%s]", + sprintf("i3_fav%s.png", fav and "" or "_off"), fav_marked, fav_marked), + fmt("image_button", star_x, star_y, star_size, star_size, "", "fav", ""), + sprintf("tooltip[fav;%s]", fav and ES"Unmark this item" or ES"Mark this item")) + else + fs(sprintf("style[nofav;fgimg=%s;fgimg_hovered=%s;fgimg_pressed=%s]", + "i3_fav_off.png", PNG.cancel, PNG.cancel), + fmt("image_button", star_x, star_y, star_size, star_size, "", "nofav", ""), + sprintf("tooltip[nofav;%s]", ES"Cannot mark this item. Bookmark limit reached.")) + end + + local desc_lim, name_lim = 32, 34 + local desc = ESC(get_desc(data.query_item, data.lang_code)) + local tech_name = data.query_item + local X = data.xoffset + 1.05 + local Y1 = data.yoffset + 0.47 + local Y2 = Y1 + 0.5 + + if #desc > desc_lim then + fs(fmt("tooltip", X, Y1 - 0.1, 5.7, 0.24, desc)) + desc = snip(desc, desc_lim) + end + + if #tech_name > name_lim then + fs(fmt("tooltip", X, Y2 - 0.1, 5.7, 0.24, tech_name)) + tech_name = snip(tech_name, name_lim) + end + + fs("style_type[label;font=bold;font_size=+6]", + fmt("label", X, Y1, desc), "style_type[label;font=mono;font_size=+0]", + fmt("label", X, Y2, clr("#7bf", tech_name)), "style_type[label;font=normal;font_size=+0]") + + local def = reg_items[data.query_item] + local model_alias = i3.model_alias[data.query_item] + + if def.drawtype == "mesh" or model_alias then + get_model_fs(fs, data, def, model_alias) + else + fs(fmt("item_image", data.xoffset + 6.8, data.yoffset + 0.17, 1.1, 1.1, data.query_item)) + end +end + +local function get_export_fs(fs, data, panel, is_recipe, is_usage, max_stacks_rcp, max_stacks_usg) + local name = is_recipe and "rcp" or "usg" + local show_export = (is_recipe and data.export_rcp) or (is_usage and data.export_usg) + + fs(sprintf("style[export_%s;fgimg=%s;fgimg_hovered=%s]", + name, sprintf("%s", show_export and PNG.export_hover or PNG.export), PNG.export_hover), + fmt("image_button", + data.xoffset + 7.35, data.yoffset + 0.2, 0.45, 0.45, "", sprintf("export_%s", name), ""), + sprintf("tooltip[export_%s;%s]", name, ES"Quick crafting")) + + if not show_export then return end + + local craft_max = is_recipe and max_stacks_rcp or max_stacks_usg + local stack_fs = (is_recipe and data.scrbar_rcp) or (is_usage and data.scrbar_usg) or 1 + + if stack_fs > craft_max then + stack_fs = craft_max + + if is_recipe then + data.scrbar_rcp = craft_max + elseif is_usage then + data.scrbar_usg = craft_max + end + end + + fs(sprintf("style[scrbar_%s;noclip=true]", name), + sprintf("scrollbaroptions[min=1;max=%u;smallstep=1]", craft_max), + fmt("scrollbar", + data.xoffset + 8.1, data.yoffset, 3, 0.35, sprintf("scrbar_%s", name), stack_fs), + fmt("button", data.xoffset + 8.1, data.yoffset + 0.4, 3, 0.7, sprintf("craft_%s", name), + sprintf("%s", sprintf(stack_fs > 1 and ES"Craft %u items" or ES"Craft %u item", + stack_fs)))) +end + +local function get_rcp_extra(player, fs, data, panel, is_recipe, is_usage) + local rn = panel.rcp and #panel.rcp + + if rn then + local rcp_normal = is_recipe and panel.rcp[data.rnum].type == "normal" + local usg_normal = is_usage and panel.rcp[data.unum].type == "normal" + local max_stacks_rcp, max_stacks_usg = 0, 0 + local inv = player:get_inventory() + + if rcp_normal then + max_stacks_rcp = get_stack_max(inv, data, is_recipe, panel.rcp[data.rnum]) + end + + if usg_normal then + max_stacks_usg = get_stack_max(inv, data, is_recipe, panel.rcp[data.unum]) + end + + if is_recipe and max_stacks_rcp == 0 then + data.export_rcp = nil + data.scrbar_rcp = 1 + elseif is_usage and max_stacks_usg == 0 then + data.export_usg = nil + data.scrbar_usg = 1 + end + + if max_stacks_rcp > 0 or max_stacks_usg > 0 then + get_export_fs(fs, data, panel, is_recipe, is_usage, max_stacks_rcp, + max_stacks_usg) + end + + get_rcp_lbl(fs, data, panel, rn, is_recipe) + else + local lbl = is_recipe and ES"No recipes" or ES"No usages" + fs(fmt("button", + data.xoffset + 0.1, data.yoffset + (panel.height / 2) - 0.5, + 7.8, 1, "no_rcp", lbl)) + end +end + +local function get_favs(fs, data) + fs(fmt("label", data.xoffset + 0.4, data.yoffset + 0.4, ES"Bookmarks")) + + for i = 1, #data.favs do + local item = data.favs[i] + local X = data.xoffset - 0.7 + (i * 1.2) + local Y = data.yoffset + 0.8 + + if data.query_item == item then + fs(fmt("image", X, Y, ITEM_BTN_SIZE, ITEM_BTN_SIZE, PNG.slot)) + end + + fs(fmt("item_image_button", X, Y, ITEM_BTN_SIZE, ITEM_BTN_SIZE, item, item, "")) + end +end + +local function get_panels(player, fs, data) + local _title = {name = "title", height = 1.4} + local _favs = {name = "favs", height = 2.23} + local _recipes = {name = "recipes", rcp = data.recipes, height = 3.9} + local _usages = {name = "usages", rcp = data.usages, height = 3.9} + local panels = {_title, _recipes, _usages, _favs} + + for idx = 1, #panels do + local panel = panels[idx] + data.yoffset = 0 + + if idx > 1 then + for _idx = idx - 1, 1, -1 do + data.yoffset = data.yoffset + panels[_idx].height + 0.1 + end + end + + fs(fmt("bg9", data.xoffset + 0.1, data.yoffset, 7.9, panel.height, PNG.bg_full, 10)) + + local is_recipe, is_usage = panel.name == "recipes", panel.name == "usages" + + if is_recipe or is_usage then + get_rcp_extra(player, fs, data, panel, is_recipe, is_usage) + elseif panel.name == "title" then + get_header(fs, data) + elseif panel.name == "favs" then + get_favs(fs, data) + end + end +end + +local function get_item_list(fs, data, full_height) + fs(fmt("bg9", 0, 0, data.xoffset, full_height, PNG.bg_full, 10)) + + local filtered = data.filter ~= "" + + fs("box[0.2,0.2;4.55,0.6;#bababa25]", "set_focus[filter]") + fs(sprintf("field[0.3,0.2;%f,0.6;filter;;%s]", filtered and 3.45 or 3.9, ESC(data.filter))) + fs("field_close_on_enter[filter;false]") + + if filtered then + fs(fmt("image_button", 3.75, 0.35, 0.3, 0.3, "", "cancel", "")) + end + + fs(fmt("image_button", 4.25, 0.32, 0.35, 0.35, "", "search", "")) + + fs(fmt("image_button", data.xoffset - 2.73, 0.3, 0.35, 0.35, "", "prev_page", ""), + fmt("image_button", data.xoffset - 0.55, 0.3, 0.35, 0.35, "", "next_page", "")) + + data.pagemax = max(1, ceil(#data.items / IPP)) + + fs(fmt("button", + data.xoffset - 2.4, 0.14, 1.88, 0.7, "pagenum", + sprintf("%s / %u", clr("#ff0", data.pagenum), data.pagemax))) + + if #data.items == 0 then + local lbl = ES"No item to show" + + if next(recipe_filters) and #init_items > 0 and data.filter == "" then + lbl = ES"Collect items to reveal more recipes" + end + + fs(fmt("button", 0, 3, data.xoffset, 1, "no_item", lbl)) + end + + local first_item = (data.pagenum - 1) * IPP + + for i = first_item, first_item + IPP - 1 do + local item = data.items[i + 1] + if not item then break end + + local X = i % ROWS + X = X + (X * 0.1) + 0.2 + + local Y = floor((i % IPP - X) / ROWS + 1) + Y = Y + (Y * 0.06) + 1 + + if data.query_item == item then + fs(fmt("image", X, Y, 1, 1, PNG.slot)) + end + + fs(fmt("item_image_button", X, Y, 1, 1, item, sprintf("%s_inv", item), "")) + end +end + +local function get_inventory_mode(player, fs, data, full_height) + fs(fmt("bg9", 0, 0, data.xoffset, full_height, PNG.bg_full, 10)) + + local player_props = player:get_properties() + local name = player:get_player_name() + + fs(fmt("model", 0.2, 0.2, 4, 5.4, "player_model", + player_props.mesh, concat(player_props.textures, ","), "0,-150", "false", "0,0")) + + local xoffset = __3d_armor and 0 or 4.5 + + if __3d_armor then + fs(sprintf("scrollbaroptions[max=35]scrollbar[-1,0;0.3,3;vertical;scrbar_inv;%u]", + data.scrbar_inv or 0)) + fs("scroll_container[4.5,0;5.5,5.5;scrbar_inv;vertical]") + end + + fs("style_type[label;font=bold;font_size=+6]") + fs(fmt("label", xoffset, 0.4, ESC(name))) + fs("style_type[label;font=normal;font_size=+0]") + fs(fmt("box", xoffset, 0.7, 5.5, 0.05, "#666")) + + fs("listcolors[#bababa50;#bababa99]") + + local hp = data.hp or player:get_hp() + local half = ceil((hp / 2) % 1) + local hearts = (hp / 2) + half + + for i = 1, hearts do + fs(fmt("image", xoffset + ((i - 1) * 0.4), 0.9, 0.4, 0.4, + (half == 1 and i == floor(hearts)) and + "i3_heart_half.png" or "i3_heart.png")) + end + + fs(sprintf("list[current_player;craft;%f,1.75;3,3;]", xoffset)) + fs(fmt("image", xoffset + 3.64, 3.18, 0.7, 0.7, PNG.arrow)) + fs(sprintf("list[current_player;craftpreview;%f,3;1,1;]", xoffset + 4.45)) + fs("listring[detached:i3_trash;main]") + fs(sprintf("list[detached:i3_trash;main;%f,4.25;1,1;]", xoffset + 4.45)) + fs(fmt("image", xoffset + 4.45, 4.25, 1, 1, PNG.trash)) + + if __3d_armor then + fs("style_type[label;font=bold;font_size=+2]") + fs(fmt("label", 0, 5.8, ES"Armor")) + fs("style_type[label;font=normal;font_size=+0]") + fs(fmt("box", 0, 6.1, 5.5, 0.05, "#666")) + fs(sprintf("list[detached:%s_armor;armor;0,6.4;3,2;]", name)) + + fs(fmt("label", 3.75, 7.35, sprintf("%s: %s", ES"Level", armor.def[name].level))) + fs(fmt("label", 3.75, 7.75, sprintf("%s: %s", ES"Heal", armor.def[name].heal))) + + fs("scroll_container_end[]") + end + + for i = 0, 7 do + fs(fmt("image", i + 0.23 + (i * 0.25), 6.1, 1, 1, "i3_hb_bg.png")) + end + + fs("listring[current_player;main]") + fs("list[current_player;main;0.23,6.1;8,1;]") + fs("list[current_player;main;0.23,7.4;8,3;8]") + + local i = 0 + local btn = { + trash = ES"Trash all items", + sort_az = ES"Sort items (A-Z)", + sort_za = ES"Sort items (Z-A)", + compress = ES"Compress items", + } + + for btn_name, tooltip in pairs(btn) do + fs(fmt("image_button", i + 4 - (i * 0.4), + full_height - 0.6, 0.35, 0.35, "", btn_name, "")) + i = i + 1 + fs(sprintf("tooltip[%s;%s]", btn_name, tooltip)) + end +end + +local function make_fs(player, data) + local fs = setmetatable({}, { + __call = function(t, ...) + t[#t + 1] = concat({...}) + end + }) + + data.xoffset = ROWS + 1.2 + local full_height = LINES + 1.73 + local half_height = full_height / 2 + + fs(sprintf("formspec_version[%u]size[%f,%f]no_prepend[]bgcolor[#0000]", + MIN_FORMSPEC_VERSION, data.xoffset + (data.query_item and 8 or 0), full_height), styles) + + fs(sprintf("style[guide_mode;fgimg=%s]", data.inv_mode and PNG.tab or PNG.tab_hover)) + fs(sprintf("style[inv_mode;fgimg=%s]", data.inv_mode and PNG.tab_hover or PNG.tab)) + + fs(fmt("image_button", 2.05, full_height, 3, 0.5, "", "guide_mode", ES"Crafting Guide")) + fs(fmt("image_button", 5.15, full_height, 3, 0.5, "", "inv_mode", ES"Inventory")) + + if data.inv_mode then + get_inventory_mode(player, fs, data, full_height, half_height) + else + get_item_list(fs, data, full_height) + end + + if data.query_item then + get_panels(player, fs, data) + end + + return concat(fs) +end + +local function show_fs(player, name) + local data = pdata[name] + local fs = make_fs(player, data) + + player:set_inventory_formspec(fs) +end + +local trash = core.create_detached_inventory("i3_trash", { + allow_put = function(inv, listname, index, stack, player) + return stack:get_count() + end, + on_put = function(inv, listname) + inv:set_list(listname, {}) + end, +}) + +trash:set_size("main", 1) + +core.register_on_player_inventory_action(function(player) + after(0, function() + local name = player:get_player_name() + local data = pdata[name] + local fs = make_fs(player, data) + + player:set_inventory_formspec(fs) + end) +end) + +i3.register_craft_type("digging", { + description = ES"Digging", + icon = "i3_steelpick.png", +}) + +i3.register_craft_type("digging_chance", { + description = ES"Digging (by chance)", + icon = "i3_mesepick.png", +}) + +local function search(data) + local filter = data.filter + + if searches[filter] then + data.items = searches[filter] + return + end + + local opt = "^(.-)%+([%w_]+)=([%w_,]+)" + local search_filter = next(search_filters) and match(filter, opt) + local filters = {} + + if search_filter then + for filter_name, values in gmatch(filter, sub(opt, 6)) do + if search_filters[filter_name] then + values = split(values, ",") + filters[filter_name] = values + end + end + end + + local filtered_list, c = {}, 0 + + for i = 1, #data.items_raw do + local item = data.items_raw[i] + local def = reg_items[item] + local desc = lower(translate(data.lang_code, def and def.description)) or "" + local search_in = sprintf("%s %s", item, desc) + local to_add + + if search_filter then + for filter_name, values in pairs(filters) do + if values then + local func = search_filters[filter_name] + to_add = func(item, values) and (search_filter == "" or + find(search_in, search_filter, 1, true)) + end + end + else + to_add = find(search_in, filter, 1, true) + end + + if to_add then + c = c + 1 + filtered_list[c] = item + end + end + + if not next(recipe_filters) then + -- Cache the results only if searched 2 times + if searches[filter] == nil then + searches[filter] = false + else + searches[filter] = filtered_list + end + end + + data.items = filtered_list +end + +i3.add_search_filter("groups", function(item, groups) + local def = reg_items[item] + local has_groups = true + + for i = 1, #groups do + local group = groups[i] + if not def.groups[group] then + has_groups = nil + break + end + end + + return has_groups +end) + +--[[ As `core.get_craft_recipe` and `core.get_all_craft_recipes` do not + return the fuel, replacements and toolrepair recipes, we have to + override `core.register_craft` and do some reverse engineering. + See engine's issues #4901, #5745 and #8920. ]] + +local old_register_craft = core.register_craft +local rcp_num = {} + +core.register_craft = function(def) + old_register_craft(def) + + if def.type == "toolrepair" then + toolrepair = def.additional_wear * -100 + end + + local output = def.output or (true_str(def.recipe) and def.recipe) or nil + if not output then return end + output = {match(output, "%S+")} + + local groups + + if is_group(output[1]) then + groups = extract_groups(output[1]) + output = groups_to_items(groups, true) + end + + for i = 1, #output do + local item = output[i] + rcp_num[item] = (rcp_num[item] or 0) + 1 + + if def.replacements then + if def.type == "fuel" then + replacements.fuel[item] = def.replacements + else + replacements[item] = replacements[item] or {} + replacements[item][rcp_num[item]] = def.replacements + end + end + end +end + +local old_clear_craft = core.clear_craft + +core.clear_craft = function(def) + old_clear_craft(def) + + if true_str(def) then + return -- TODO + elseif is_table(def) then + return -- TODO + end +end + +local function resolve_aliases(hash) + for oldname, newname in pairs(reg_aliases) do + cache_recipes(oldname) + local recipes = recipes_cache[oldname] + + if recipes then + if not recipes_cache[newname] then + recipes_cache[newname] = {} + end + + local similar + + for i = 1, #recipes_cache[oldname] do + local rcp_old = recipes_cache[oldname][i] + + for j = 1, #recipes_cache[newname] do + local rcp_new = copy(recipes_cache[newname][j]) + rcp_new.output = oldname + + if table_eq(rcp_old, rcp_new) then + similar = true + break + end + end + + if not similar then + insert(recipes_cache[newname], rcp_old) + end + end + end + + if newname ~= "" and recipes_cache[oldname] and not hash[newname] then + init_items[#init_items + 1] = newname + end + end +end + +local function get_init_items() + local _select, _preselect = {}, {} + + for name, def in pairs(reg_items) do + if name ~= "" and show_item(def) then + cache_drops(name, def.drop) + cache_fuel(name) + cache_recipes(name) + + _preselect[name] = true + end + end + + for name in pairs(_preselect) do + cache_usages(name) + + init_items[#init_items + 1] = name + _select[name] = true + end + + resolve_aliases(_select) + sort(init_items) + + if http and true_str(i3.export_url) then + local post_data = { + recipes = recipes_cache, + usages = usages_cache, + } + + http.fetch_async{ + url = i3.export_url, + post_data = write_json(post_data), + } + end +end + +local function init_data(player, name) + local info = get_player_info(name) + + pdata[name] = { + filter = "", + pagenum = 1, + items = init_items, + items_raw = init_items, + favs = {}, + export_counts = {}, + inv_mode = true, + lang_code = get_lang_code(info), + fs_version = get_formspec_version(info), + creative = core.is_creative_enabled(name), + } + + local data = pdata[name] + local fs = make_fs(player, data) + + player:set_inventory_formspec(fs) +end + +local function reset_data(data) + data.filter = "" + data.pagenum = 1 + data.rnum = 1 + data.unum = 1 + data.scrbar_rcp = 1 + data.scrbar_usg = 1 + data.query_item = nil + data.recipes = nil + data.usages = nil + data.export_rcp = nil + data.export_usg = nil + data.items = data.items_raw +end + +on_mods_loaded(function() + get_init_items() + + local creative = rawget(_G, "creative") + if creative then + function creative.set_creative_formspec() return end + end + + local sfinv = rawget(_G, "sfinv") + if sfinv then + sfinv.enabled = false + end + + local unified_inventory = rawget(_G, "unified_inventory") + if unified_inventory then + function unified_inventory.set_inventory_formspec() return end + end + + if rawget(_G, "armor") then + __3d_armor = true + end +end) + +on_joinplayer(function(player) + after(0, function() + local name = player:get_player_name() + init_data(player, name) + local data = pdata[name] + + if data.fs_version < MIN_FORMSPEC_VERSION then + outdated(name) + end + end) +end) + +on_receive_fields(function(player, formname, _f) + if _f.quit or formname ~= "" then return false end + local name = player:get_player_name() + local data = pdata[name] + local sb_rcp, sb_usg = _f.scrbar_rcp, _f.scrbar_usg + + if _f.cancel then + reset_data(data) + + elseif _f.prev_recipe or _f.next_recipe then + local num = data.rnum + (_f.prev_recipe and -1 or 1) + data.rnum = data.recipes[num] and num or (_f.prev_recipe and #data.recipes or 1) + data.export_rcp = nil + data.scrbar_rcp = 1 + + elseif _f.prev_usage or _f.next_usage then + local num = data.unum + (_f.prev_usage and -1 or 1) + data.unum = data.usages[num] and num or (_f.prev_usage and #data.usages or 1) + data.export_usg = nil + data.scrbar_usg = 1 + + elseif _f.key_enter_field == "filter" or _f.search then + if _f.filter == "" then + reset_data(data) + return true, show_fs(player, name) + end + + local str = lower(_f.filter) + if data.filter == str then return end + + data.filter = str + data.pagenum = 1 + + search(data) + + elseif _f.prev_page or _f.next_page then + if data.pagemax == 1 then return end + data.pagenum = data.pagenum - (_f.prev_page and 1 or -1) + + if data.pagenum > data.pagemax then + data.pagenum = 1 + elseif data.pagenum == 0 then + data.pagenum = data.pagemax + end + + elseif _f.fav then + local fav, i = is_fav(data.favs, data.query_item) + local total = #data.favs + + if total < MAX_FAVS and not fav then + data.favs[total + 1] = data.query_item + elseif fav then + remove(data.favs, i) + end + + elseif _f.export_rcp or _f.export_usg then + if _f.export_rcp then + data.export_rcp = not data.export_rcp + + if not data.export_rcp then + data.scrbar_rcp = 1 + end + else + data.export_usg = not data.export_usg + + if not data.export_usg then + data.scrbar_usg = 1 + end + end + + elseif _f.guide_mode or _f.inv_mode then + if _f.guide_mode then + data.inv_mode = nil + else + data.inv_mode = true + end + + elseif _f.trash then + local inv = player:get_inventory() + if not inv:is_empty("main") then + inv:set_list("main", {}) + end + + elseif _f.compress then + compress_items(player) + + elseif _f.sort_az or _f.sort_za then + sort_itemlist(player, _f.sort_az) + + elseif _f.scrbar_inv then + data.scrbar_inv = tonumber(match(_f.scrbar_inv, "%d+")) + return true + + elseif (sb_rcp and sub(sb_rcp, 1, 3) == "CHG") or (sb_usg and sub(sb_usg, 1, 3) == "CHG") then + data.scrbar_rcp = sb_rcp and tonum(match(sb_rcp, "%d+")) + data.scrbar_usg = sb_usg and tonum(match(sb_usg, "%d+")) + + elseif _f.craft_rcp or _f.craft_usg then + craft_stack(player, name, data, _f.craft_rcp) + else + select_item(player, name, data, _f) + end + + return true, show_fs(player, name) +end) + +core.register_on_player_hpchange(function(player, hpchange) + local name = player:get_player_name() + local data = pdata[name] + local hp_max = player:get_properties().hp_max + + data.hp = min(hp_max, player:get_hp() + hpchange) + + local fs = make_fs(player, data) + player:set_inventory_formspec(fs) +end) + +if progressive_mode then + local function item_in_inv(item, inv_items) + local inv_items_size = #inv_items + + if is_group(item) then + local groups = extract_groups(item) + for i = 1, inv_items_size do + local def = reg_items[inv_items[i]] + + if def then + if item_has_groups(def.groups, groups) then + return true + end + end + end + else + for i = 1, inv_items_size do + if inv_items[i] == item then + return true + end + end + end + end + + local function recipe_in_inv(rcp, inv_items) + for _, item in pairs(rcp.items) do + if not item_in_inv(item, inv_items) then return end + end + + return true + end + + local function progressive_filter(recipes, player) + if not recipes then + return {} + end + + local name = player:get_player_name() + local data = pdata[name] + + if #data.inv_items == 0 then + return {} + end + + local filtered, c = {}, 0 + for i = 1, #recipes do + local recipe = recipes[i] + if recipe_in_inv(recipe, data.inv_items) then + c = c + 1 + filtered[c] = recipe + end + end + + return filtered + end + + local item_lists = {"main", "craft", "craftpreview"} + + local function get_inv_items(player) + local inv = player:get_inventory() + local stacks = {} + + for i = 1, #item_lists do + local list = inv:get_list(item_lists[i]) + table_merge(stacks, list) + end + + local inv_items, c = {}, 0 + + for i = 1, #stacks do + local stack = stacks[i] + if not stack:is_empty() then + local name = stack:get_name() + if reg_items[name] then + c = c + 1 + inv_items[c] = name + end + end + end + + return inv_items + end + + local function init_hud(player, data) + data.hud = { + bg = player:hud_add{ + hud_elem_type = "image", + position = {x = 0.78, y = 1}, + alignment = {x = 1, y = 1}, + scale = {x = 370, y = 112}, + text = PNG.bg, + z_index = 0xDEAD, + }, + + book = player:hud_add{ + hud_elem_type = "image", + position = {x = 0.79, y = 1.02}, + alignment = {x = 1, y = 1}, + scale = {x = 4, y = 4}, + text = PNG.book, + z_index = 0xDEAD, + }, + + text = player:hud_add{ + hud_elem_type = "text", + position = {x = 0.84, y = 1.04}, + alignment = {x = 1, y = 1}, + number = 0xffffff, + text = "", + z_index = 0xDEAD, + }, + } + end + + local function show_hud_success(player, data) + -- It'd better to have an engine function `hud_move` to only need + -- 2 calls for the notification's back and forth. + + local hud_info_bg = player:hud_get(data.hud.bg) + local dt = 0.016 + + if hud_info_bg.position.y <= 0.9 then + data.show_hud = false + data.hud_timer = (data.hud_timer or 0) + dt + end + + if data.show_hud then + for _, def in pairs(data.hud) do + local hud_info = player:hud_get(def) + + player:hud_change(def, "position", { + x = hud_info.position.x, + y = hud_info.position.y - (dt / 5) + }) + end + + player:hud_change(data.hud.text, "text", + S("@1 new recipe(s) discovered!", data.discovered)) + + elseif data.show_hud == false then + if data.hud_timer >= HUD_TIMER_MAX then + for _, def in pairs(data.hud) do + local hud_info = player:hud_get(def) + + player:hud_change(def, "position", { + x = hud_info.position.x, + y = hud_info.position.y + (dt / 5) + }) + end + + if hud_info_bg.position.y >= 1 then + data.show_hud = nil + data.hud_timer = nil + end + end + end + end + + -- Workaround. Need an engine call to detect when the contents of + -- the player inventory changed, instead. + local function poll_new_items() + local players = get_players() + for i = 1, #players do + local player = players[i] + local name = player:get_player_name() + local data = pdata[name] + + local inv_items = get_inv_items(player) + local diff = array_diff(inv_items, data.inv_items) + + if #diff > 0 then + data.inv_items = table_merge(diff, data.inv_items) + local oldknown = data.known_recipes or 0 + local items = get_filtered_items(player, data) + data.discovered = data.known_recipes - oldknown + + if data.show_hud == nil and data.discovered > 0 then + data.show_hud = true + end + + data.items_raw = items + search(data) + local fs = make_fs(player, data) + player:set_inventory_formspec(fs) + end + end + + after(POLL_FREQ, poll_new_items) + end + + poll_new_items() + + globalstep(function() + local players = get_players() + for i = 1, #players do + local player = players[i] + local name = player:get_player_name() + local data = pdata[name] + + if data.show_hud ~= nil and singleplayer then + show_hud_success(player, data) + end + end + end) + + i3.add_recipe_filter("Default progressive filter", progressive_filter) + + on_joinplayer(function(player) + local name = player:get_player_name() + local data = pdata[name] + + local meta = player:get_meta() + data.inv_items = dslz(meta:get_string "inv_items") or {} + data.known_recipes = dslz(meta:get_string "known_recipes") or 0 + + if singleplayer then + init_hud(player, data) + end + end) + + local to_save = {"inv_items", "known_recipes"} + + local function save_meta(player) + local meta = player:get_meta() + local name = player:get_player_name() + local data = pdata[name] + + for i = 1, #to_save do + local meta_name = to_save[i] + meta:set_string(meta_name, slz(data[meta_name])) + end + end + + on_leaveplayer(save_meta) + + on_shutdown(function() + local players = get_players() + for i = 1, #players do + local player = players[i] + save_meta(player) + end + end) +end + +on_leaveplayer(function(player) + local name = player:get_player_name() + pdata[name] = nil +end) + +function i3.show(name, item) + if not true_str(name) then + return err "i3.show(): player name missing" + end + + local data = pdata[name] + local player = get_player_by_name(name) + local query_item = data.query_item + + reset_data(data) + + item = reg_items[item] and item or query_item + local recipes, usages = get_recipes(item, data, player) + + if not recipes and not usages then + if not recipes_cache[item] and not usages_cache[item] then + return false, msg(name, sprintf("%s: %s", + S"No recipe or usage for this node", clr("#ff0", get_desc(item)))) + end + + return false, msg(name, sprintf("%s: %s", + S"You don't know a recipe or usage for this item", get_desc(item))) + end + + data.query_item = item + data.recipes = recipes + data.usages = usages + + show_fs(player, name) +end + +register_command("craft", { + description = S"Show recipe(s) of the pointed node", + func = function(name) + local player = get_player_by_name(name) + local dir = player:get_look_dir() + local ppos = player:get_pos() + ppos.y = ppos.y + 1.625 + + local node_name + + for i = 1, 10 do + local look_at = vec_add(ppos, vec_mul(dir, i)) + local node = core.get_node(look_at) + + if node.name ~= "air" then + local def = reg_items[node.name] + + if def then + node_name = node.name + break + end + end + end + + if not node_name then + return false, msg(name, S"No node pointed") + end + + return true, i3.show(name, node_name) + end, +}) diff --git a/license.txt b/license.txt new file mode 100644 index 0000000..91dc864 --- /dev/null +++ b/license.txt @@ -0,0 +1,59 @@ +License of source code +---------------------- + +The MIT License (MIT) + +Copyright (c) 2015-present Jean-Patrick Guerrero and contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +Licenses of media (textures) +---------------------------- + +paramat (CC BY-SA 3.0): + sfinv_crafting_arrow.png - derived from a texture by BlockMen (CC BY-SA 3.0) + +You are free to: +Share — copy and redistribute the material in any medium or format. +Adapt — remix, transform, and build upon the material for any purpose, even commercially. +The licensor cannot revoke these freedoms as long as you follow the license terms. + +Under the following terms: + +Attribution — You must give appropriate credit, provide a link to the license, and +indicate if changes were made. You may do so in any reasonable manner, but not in any way +that suggests the licensor endorses you or your use. + +ShareAlike — If you remix, transform, or build upon the material, you must distribute +your contributions under the same license as the original. + +No additional restrictions — You may not apply legal terms or technological measures that +legally restrict others from doing anything the license permits. + +Notices: + +You do not have to comply with the license for elements of the material in the public +domain or where your use is permitted by an applicable exception or limitation. +No warranties are given. The license may not give you all of the permissions necessary +for your intended use. For example, other rights such as publicity, privacy, or moral +rights may limit how you use the material. + +For more details: +http://creativecommons.org/licenses/by-sa/3.0/ diff --git a/locale/i3.de.tr b/locale/i3.de.tr new file mode 100644 index 0000000..8fb702d --- /dev/null +++ b/locale/i3.de.tr @@ -0,0 +1,60 @@ +# textdomain: i3 + +Craft Guide=Rezeptbuch +Crafting Guide=Rezeptbuch +Crafting Guide Sign=Rezepttafel +Bookmarks=Lesezeichen +Usage @1 of @2=Verwendung @1 von @2 +Recipe @1 of @2=Rezept @1 von @2 +No recipes=Keine Rezepte +No usages=Keine Verwendungen +Burning time: @1=Brennzeit: @1 +Cooking time: @1=Kochzeit: @1 +Replaced by @1 on smelting=Ersetzt durch @1 beim Schmelzen +Replaced by @1 on burning=Ersetzt durch @1 beim Brennen +Replaced by @1 on crafting=Ersetzt durch @1 beim Fertigen +Repairable by step of @1=Reparierbar um @1 +Any item belonging to the group(s): @1=Beliebiger Gegenstand aus Gruppe(n): @1 +Any black dye=Beliebiger schwarzer Farbstoff +Any black flower=Beliebige schwarze Blume +Any blue dye=Beliebiger blauer Farbstoff +Any blue flower=Beliebige blaue Blume +Any brown dye=Beliebiger brauner Farbstoff +Any coal=Beliebige Kohle +Any cyan dye=Beliebiger türkiser Farbstoff +Any dark green dye=Beliebiger dunkelgrüner Farbstoff +Any dark grey dye=Beliebiger dunkelgrauer Farbstoff +Any green dye=Beliebiger grüner Farbstoff +Any green flower=Beliebige grüne Blume +Any grey dye=Beliebiger grauer Farbstoff +Any kind of stone block=Beliebiger Steinblock +Any magenta dye=Beliebiger magenta Farbstoff +Any orange dye=Beliebiger orange Farbstoff +Any orange flower=Beliebige orange Blume +Any pink dye=Beliebiger rosa Farbstoff +Any red dye=Beliebiger roter Farbstoff +Any red flower=Beliebige rote Blume +Any sand=Beliebiger Sand +Any stick=Beliebiger Stock +Any tree=Beliebiger Baum +Any vessel=Beliebiger Behälter +Any violet dye=Beliebiger violetter Farbstoff +Any violet flower=Beliebige violette Blume +Any white dye=Beliebiger weißer Farbstoff +Any white flower=Beliebige weiße Blume +Any wood planks=Beliebige Holzplanken +Any wool=Beliebige Wolle +Any yellow dye=Beliebiger gelber Farbstoff +Any yellow flower=Beliebige gelbe Blume +Recipe's too big to be displayed (@1x@2)=Rezept ist zu groß für die Anzeige (@1×@2) +Shapeless=Formlos +Cooking=Kochen +No item to show=Nichts anzuzeigen +Collect items to reveal more recipes=Gegenstände aufsammeln, um mehr Rezepte aufzudecken +Show recipe(s) of the pointed node=Rezept(e) des gezeigten Blocks anzeigen +No node pointed=Auf keinem Block gezeigt +You don't know a recipe or usage for this item=Sie kennen kein Rezept und keine Verwendung für diesen Gegenstand +No recipe or usage for this item=Kein Rezept und keine Verwendung für diesen Gegenstand +Digging=Graben +Digging Chance=Grabechance +@1 of chance to drop=@1 Abwurfwahrscheinlichkeit diff --git a/locale/i3.fr.tr b/locale/i3.fr.tr new file mode 100644 index 0000000..7ef3829 --- /dev/null +++ b/locale/i3.fr.tr @@ -0,0 +1,69 @@ +# textdomain: i3 + +Craft Guide=Guide de recettes +Crafting Guide=Guide de recettes +Crafting Guide Sign=Guide de recettes +Bookmarks=Favoris +Usage @1 of @2=Usage @1 sur @2 +Recipe @1 of @2=Recette @1 sur @2 +No recipes=Pas de recettes +No usages=Pas d'usages +Burning time: @1=Temps de combustion : @1 +Cooking time: @1=Temps de cuisson : @1 +Replaced by @1 on smelting=Remplacé par @1 lors de la cuisson +Replaced by @1 on burning=Remplacé par @1 lors de la combustion +Replaced by @1 on crafting=Remplacé par @1 lors de la fabrication +Repairable by step of @1=Réparable par étape de @1 +Any item belonging to the group(s): @1=Tout item appartenant au(x) groupe(s) : @1 +Any black dye=Quelconque colorant noir +Any black flower=Quelconque fleur noire +Any blue dye=Quelconque colorant bleu +Any blue flower=Quelconque fleur bleue +Any brown dye=Quelconque colorant marron +Any coal=Quelconque charbon +Any cyan dye=Quelconque colorant bleu ciel +Any dark green dye=Quelconque colorant vert foncé +Any dark grey dye=Quelconque colorant gris foncé +Any green dye=Quelconque colorant vert +Any green flower=Quelconque fleur verte +Any grey dye=Quelconque colorant gris +Any kind of stone block=Quelconque roche +Any magenta dye=Quelconque colorant magenta +Any orange dye=Quelconque colorant orange +Any orange flower=Quelconque fleur orange +Any pink dye=Quelconque colorant rose +Any red dye=Quelconque colorant rouge +Any red flower=Quelconque fleur rouge +Any sand=Quelconque sable +Any stick=Quelconque bâton +Any tree=Quelconque tronc d'arbre +Any vessel=Quelconque couvert +Any violet dye=Quelconque colorant violet +Any violet flower=Quelconque fleur violette +Any white dye=Quelconque colorant blanc +Any white flower=Quelconque fleur blanche +Any wood planks=Quelconques planches de bois +Any wool=Quelconque laine +Any yellow dye=Quelconque colorant jaune +Any yellow flower=Quelconque fleur jaune +Shapeless=Sans forme +Cooking=Cuisson +No item to show=Aucun item à afficher +Collect items to reveal more recipes=Collecte des items pour révéler plus de recettes +Show recipe(s) of the pointed node=Affiche les recettes du bloc visé +No node pointed=Aucun bloc visé +You don't know a recipe or usage for this item=Vous ne connaissez aucune recette pour ce bloc +No recipe or usage for this node=Aucune recette pour ce bloc +Digging=Destruction +Digging (by chance)=Destruction (par chance) +@1 of chance to drop=@1 de chance de tomber +Mark this item=Mettre en favori. +Unmark this item=Enlever des favoris. +Cannot mark this item. Limit of bookmarks reached.=Impossible de mettre cet item en favori. Limite des favoris atteinte. +Only drop if using one of these tools: @1=Tombe seulement si détruit avec un de ces outils : @1 +Only drop if using this tool: @1=Tombe seulement si détruit avec cet outil : @1 +Craft @1 stack=Fabriquer @1 objet +Craft @1 stacks=Fabriquer @1 objets +@1 added in your inventory=@1 mis dans votre inventaire +@1 crafted=@1 fabriqué(s) +Quick crafting=Fabrication rapide diff --git a/locale/i3.it.tr b/locale/i3.it.tr new file mode 100644 index 0000000..2b2be2d --- /dev/null +++ b/locale/i3.it.tr @@ -0,0 +1,60 @@ +# textdomain: i3 + +Craft Guide=Guida di assemblaggio +Crafting Guide=Guida d'assemblaggio +Crafting Guide Sign=Cartello della guida di assemblaggio +Bookmarks=Segnalibri +Usage @1 of @2=Utilizzo @1 di @2 +Recipe @1 of @2=Ricetta @1 di @2 +No recipes=Nessuna ricetta +No usages=Nessun utilizzo +Burning time: @1=Tempo di combustione: @1 +Cooking time: @1=Tempo di cottura: @1 +Replaced by @1 on smelting=Sostituito da @1 alla fusione +Replaced by @1 on burning=Sostituito da @1 alla combustione +Replaced by @1 on crafting=Sostituito da @1 all'assemblaggio +Repairable by step of @1=Riparabile per passo di @1 +Any item belonging to the group(s): @1=Qualunque oggetto appartenente al/ai gruppo/i: @1 +Any black dye=Qualunque tintura nera +Any black flower=Qualunque fiore nero +Any blue dye=Qualunque tintura blu +Any blue flower=Qualunque fiore blu +Any brown dye=Qualunque tintura marrone +Any coal=Qualunque carbone +Any cyan dye=Qualunque tintura ciano +Any dark green dye=Qualunque tintura verde scura +Any dark grey dye=Qualunque tintura grigio scura +Any green dye=Qualunque tintura verde +Any green flower=Qualunque fiore verde +Any grey dye=Qualunque tintura grigia +Any kind of stone block=Qualunque tipo di blocco di pietra +Any magenta dye=Qualunque tintura magenta +Any orange dye=Qualunque tintura arancione +Any orange flower=Qualunque fiore arancione +Any pink dye=Qualunque tintura rosa +Any red dye=Qualunque tintura rossa +Any red flower=Qualunque fiore rosso +Any sand=Qualunque sabbia +Any stick=Qualunque bastone +Any tree=Qualunque albero +Any vessel=Qualunque contenitore +Any violet dye=Qualunque tintura viola +Any violet flower=Qualunque fiore viola +Any white dye=Qualunque tintura bianca +Any white flower=Qualunque fiore bianco +Any wood planks=Qualunque asse di legno +Any wool=Qualunque lana +Any yellow dye=Qualunque tintura gialla +Any yellow flower=Qualunque fiore giallo +Recipe's too big to be displayed (@1x@2)=La ricetta è troppo grande per essere mostrata (@1x@2) +Shapeless=Senza forma +Cooking=Cottura +No item to show=Nessun oggetto da mostrare +Collect items to reveal more recipes=Raccogli oggetti per svelare più ricette +Show recipe(s) of the pointed node=Mostra la/le ricetta/e del nodo puntato +No node pointed=Nessun nodo puntato +You don't know a recipe or usage for this item=Non conosci una ricetta o un utilizzo per questo oggetto +No recipe or usage for this item=Nessuna ricetta o utilizzo per questo oggetto +Digging=Scavando +Digging Chance=Probabilità di scavare +@1 of chance to drop=@1 di probabilità di rilascio diff --git a/locale/i3.ru.tr b/locale/i3.ru.tr new file mode 100644 index 0000000..aaf293b --- /dev/null +++ b/locale/i3.ru.tr @@ -0,0 +1,19 @@ +# textdomain: i3 + +Craft Guide=книга рецептов крафта +Crafting Guide=книга рецептов крафта +Crafting Guide Sign=Знак с книгой рецептов +Usage @1 of @2=использование @1 из @2 +Recipe @1 of @2=Рецепт @1 из @2 +Burning time: @1=Время горения: @1 +Cooking time: @1=Время преготовления: @1 +Any item belonging to the group(s): @1=Любой элемент из группы: @1 +Recipe's too big to be displayed (@1x@2)=Рецепт слишком большой для показа (@1x@2) +Shapeless=Бесформенный +Cooking=Приготовление +No item to show=Нет элемента для показа +Collect items to reveal more recipes=Собирайте предметы, чтобы раскрыть больше рецептов +Show recipe(s) of the pointed node=Показать рецепт(ы) выбранной ноды +No node pointed=Не указана нода +You don't know a recipe for this node=Вы не знаете рецепт для этой ноды +No recipe for this node=Нет рецептов для этой ноды diff --git a/locale/i3.zh_CN.tr b/locale/i3.zh_CN.tr new file mode 100644 index 0000000..89458d8 --- /dev/null +++ b/locale/i3.zh_CN.tr @@ -0,0 +1,40 @@ +# textdomain: i3 + +Any black dye=任何黑染料 +Any black flower=任何黑花 +Any blue dye=任何蓝染料 +Any blue flower=任何蓝花 +Any brown dye=任何棕染料 +Any coal=任何煤炭 +Any cyan dye=任何青染料 +Any dark green dye=任何暗绿染料 +Any dark grey dye=任何暗灰染料 +Any green dye=任何绿染料 +Any green flower=任何绿花 +Any grey dye=任何灰染料 +Any item belonging to the group(s): @1=任何属于以下组别的物品:@1 +Any kind of stone block=任何石方块 +Any magenta dye=任何品红染料 +Any orange dye=任何橙染料 +Any orange flower=任何橙花 +Any pink dye=任何粉红染料 +Any red dye=任何红染料 +Any red flower=任何红花 +Any sand=任何沙 +Any stick=任何棒 +Any vessel=任何容器 +Any violet dye=任何紫染料 +Any violet flower=任何紫花 +Any white dye=任何白染料 +Any white flower=任何白花 +Any wood planks=任何木板 +Any wool=任何羊毛 +Any yellow dye=任何黄染料 +Any yellow flower=任何黄花 +Cooking time: @1=熔炼时间为:@1 +No items to show=没有可显示的项目。 +Recipe @1 of @2=第@1个配方,共@2个 +Usage @1 of @2=第@1个用法,共@2个 +Recipe is too big to be displayed=配方太大,无法显示。 +Shapeless=无序配方 +Unknown Item=不明物品 diff --git a/locale/template b/locale/template new file mode 100644 index 0000000..8c7618a --- /dev/null +++ b/locale/template @@ -0,0 +1,69 @@ +# textdomain: i3 + +Craft Guide= +Crafting Guide= +Crafting Guide Sign= +Bookmarks= +Usage @1 of @2= +Recipe @1 of @2= +No recipes= +No usages= +Burning time: @1= +Cooking time: @1= +Replaced by @1 on smelting= +Replaced by @1 on burning= +Replaced by @1 on crafting= +Repairable by step of @1= +Any item belonging to the group(s): @1= +Any black dye= +Any black flower= +Any blue dye= +Any blue flower= +Any brown dye= +Any coal= +Any cyan dye= +Any dark green dye= +Any dark grey dye= +Any green dye= +Any green flower= +Any grey dye= +Any stone= +Any magenta dye= +Any orange dye= +Any orange flower= +Any pink dye= +Any red dye= +Any red flower= +Any sand= +Any stick= +Any tree= +Any vessel= +Any violet dye= +Any violet flower= +Any white dye= +Any white flower= +Any wood planks= +Any wool= +Any yellow dye= +Any yellow flower= +Shapeless= +Cooking= +No item to show= +Collect items to reveal more recipes= +Show recipe(s) of the pointed node= +No node pointed= +You don't know a recipe or usage for this item= +No recipe or usage for this node= +Digging= +Digging (by chance)= +@1 of chance to drop= +Mark this item= +Unmark this item= +Cannot mark this item. Limit of bookmarks reached.= +Only drop if using one of these tools: @1= +Only drop if using this tool: @1= +Craft @1 stack= +Craft @1 stacks= +@1 added in your inventory= +@1 crafted= +Quick crafting= diff --git a/mod.conf b/mod.conf new file mode 100644 index 0000000..fa10511 --- /dev/null +++ b/mod.conf @@ -0,0 +1,2 @@ +name = i3 +description = Next-Gen inventory for Minetest diff --git a/settingtypes.txt b/settingtypes.txt new file mode 100644 index 0000000..a97f54a --- /dev/null +++ b/settingtypes.txt @@ -0,0 +1,2 @@ +# 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 diff --git a/sounds/i3_click.ogg b/sounds/i3_click.ogg new file mode 100755 index 0000000000000000000000000000000000000000..2983f59845f5f52dd4651a903bc2e1122883c4c5 GIT binary patch literal 6220 zcmeG=dpOiv*Lw&jO6yC(Zt; zWlM@#Er1lxesMu&=0+wKMtEc6c@VGy{?YaX>=+TX5;icc6zgFKqmh7mjO!% zgd*kvhMp|5eAF?l%OY4+mq{Bq4#(8#t(sMZbUA}FCCPFot=J>ZCgT++x2_*QQ_fufLa(mJcD`ZV zU6M2Y{`P>HYtlZ4qPr}{3g-q{(K)d2TWqD(0u^o12>Ues$~-z`B|a7wFyJx4mTZjU z1x)(|_0C?cZEta|N@l&L_HOQE57=UTJmYBnak2ez3DmsQ9SsT8hSVJoQ+=jW{Zx<6 z^$!Vy(?}N`9g6}bt1LLf`eiGZmOZs7lT0}(kN|;*O0cr5mHMo5$I76vn$Uv!khArX z?X|e}T6qx(KtU3um4xP3{;wWH<^piPMs zTr-`pC7RF@Z3+99m`!)s&YizGFZ^Nz#OweN@#@V{>UW?vD29D>GtX$N{%CSPR0X1u z|J;&9{sIr8Sro(xW1vm5{6uPDK(?x-XghhaBuJ1}`V5=jlRwpIp^!gP!ow8w-AH#Y z&~4=96^JYt(WN#FZK>aOs=4G;PkwZlqkKMBJd0mkAXCk|3t?(wg$lRT{2*QE-Fz9| zBQLm@+LJ$erV#^Y>FfesVWYd4-<(_Ub`^Hru=oY;NPk=q-YDw>XCDI#Cp%>k*q_~p z2<_(gQ1y0EGB$xJ?T^u{)I6yXb3)-{3BFaoLgP4dGl_S^g`%d*jY$@r91B2-qR5NC z3?f$+dvOIT!=O#?VuwjP4jBZuy4Fvezolp=kB452GlO1yTsT@BU1Q-8&J{lJUd?4w zNcvoHL_wos1G8+T)kHyZG>_hRzHtfA7hHj=-9_}8V zago&A*q<(?`aFys>`xf%KkmEa=${?yYvceJG%2E(Wcz30TMCbCwUrec_)FwOVOp}) z?__H^)oPLN;yT|FwoMUwmF!&!WH)7>Ugg+66`I>xpFT5Mp9k%J9PLp(ZO5eqYW-Zm zh{I;EKlYo*K|*Au1#{SeHSgb%Q=-RwYR+8c$kL*+bmBR|>G`}<#pAp(xj#itNJdp& zMpatISQ=9=ofDd#&u=V?XsemH{I~sUc6tGg|dR zg~r$~`PKjcG-b&Ocn@!}{A4 z&5<)Q@Y+LzQZ=B^f>I|-syj)-$U~ZAA0T5;ok~awf~~2SKvc3KD%p#d|7?VU2(I&B zpJM|B^}3^a33IZblqOSqA^~QSf8PE=ma7?R+c&a^1TxW`{Ldx*m&1QG@V6R(E{;-w ze=4@6nyV!k<|uG%n8?C9z9ujNsIM&#EOk~I@=~!}m@m`!B|2b&eM>l?VY#qUHjA*Z zSf=|(=-2WRVB;a87!o@mh_M@A{2G49YiFfO+1`{e3Cq5e(3=E5{$GC_0{{j}1~7n9 z8}aKml{+j3z?>CGh4qC4i-rOW8nsvk02VD?oao>H?*uZ3g^_fDVqk1 zp!AglI9*gc7GEjbJq6FLmr)if0n-aqyA-1KwIL*&f=fs%31GEA(=XQ-53(5ZqCXg}k7KXR6&yxJnbc6$+ zUo#(4_7TXCvR|q!B)^i!hna*ZBD^2#vm_0H@nLq6K!`ki`g3TEP`K}M4NlTsyjCmW z^Iu%9S=|m`0re<{MwK2yR<$?)hMG_S+k{?!=S(en8M)y#z$~p@3DTf1WcrctT={^- zwsNI@&bAJkffR~?K3C4xKs$$G4C9R7KsQ;!Pf zfw!>Q3t;?s<6D_VFHjEht0ynI(aMUP9B8maswe<;YrGR2vdLs zM+_vXU{h?L7e>SSqX?3q08y;%jEJqqi`_-)Rt8N&h`EY&p}HMemGQ;8ux<@wRfr+^ zmfdsOk1w9nG2I7R15uQAJ7OaqpDzbjeNa)UNWIJFPu#3W^xq%r_YjD{bEy2mR)FqiB1B^mnnF(KCHQRSe{racSKoACx;=OaeCYSB~yS~!FSn39AL29FYsBQ-+Ug=W?8fFJWdx%lP>4L3tb91eY9Rp4>nZExr}vb4@!cn(5~Ohh9OnZc!a6eGA$5Cn=r zh#ieeVN&=h4Z)IIP%n@MkTbgZ`9 zymYjr;-RCArqIiYhP7#PBo!s2^`&{KnFidvlN{UjJc_*kYJ5y4ev8G3yKRdqyt0!4 zkX&S>k~KH~<*4q!>y%}MC2sC7h)@my8ej-s zUys1bm1U=fpTGV9WEZJv>f|M{x}ZEg!*Z?~r@h%6EBRyh^#s;~7{pPuUvQ4`zTToO*^gBYxlHA3p zUKvmVOuOp7_cg0gGk#EJD6eF9-{5z;XQlhw3zJ?JWP`rksvYmlvxQaOMoV+s4p4*f zNlp#9=z|S%SuW4FpO631yEyr&1n%Xhl{p6vQ<;Rv<1dLQ4QoFay#z*QUxO8Rei}@^ zxOnSPos*7r_WGE5e~&kl>(|h$F|NDVRd;Dg2C3VBSGjuPhvZ$#f`{4ms%%M5ce`l$ z-zLJ3%*6e41wHL3LvLbbo)|@!Oyz!=UVqFVia8Lfn%c0g!5~to3te64U?wx%>ih8zj=HQbn zgWB>pu@4434&5~I9qWJPdwrI?T?GW6ezIzd-}(2236)!Nf`9+xZ))VO+c_Qki(Cj{mh<>u&eIL`2&xUCWL z&yehWdp)<(qBtD*=<*00W(jni__%v61T4wQk)4 z=jMnfFXnBha;7@TyTc4JDk~?g)j?C^<;%%D9?$pisr*_Hu?IF44s*qIXEK@G?8Q0A z5D2cGn}O16an^lqLzf_;d6O&qpsNR`pnwaAC~5VNhg_tV$+e&MT}0!*CIm-vF4fn2 zSDsIalsL2BC$j1RFHFb}=CoN{*^WsNdRJe7S-w`VeLA7gM)Ay*9T_WW`;YV+%isE7 z6mYI4I%VVa!^a~B4S?mxIMZB(8xMNIyq;Z2MkmZOHXaBK^IssysHi#(_C0dCUb8N{ z?;-u(_w3D=xDQ;Ss-LIQgx(cs4|`Y224Pz6#r_HQi*|dCX4BbHNH_hYKxZ{V&EkWndUXqc)F~v7dyJiNBt>vM_Gd3`H|? zHYlIFv0-6i%Z}P5AAPTm7mV*~_dvZ#To*ibjo5K=h3~e{_n0{{+1wjz{M7PkKkvFW zDeazoOxcpA*8P3IkBtuBvk^-e{Lo|ndyn?~eak!F{L;%5Zd@8^Cp7X1g^o@9}S>YQ!S^@r6FGqHbu**!KUBw;=6vT|)n65O@?)F{nS96oC25rZ{N?AWC1YXDs}-?DcW_;;*W?;LOcz#!I8@BJdmG&la!@5uV-mHuD2-!+@?@5fROT_6mSq4Fk z?UiICeI9yI^lX_%z>^tf*nDFw$owQ23DVD)r1=1qUz3{0I@J8AO$H3@R@4CPQ#5mM zsjNVs`Z{t!;)?PCrhH1~nz1uNOSN}qrXC*iGvego{nDfpaZ@KCY@QBJu{Qt7_sKu^~7ryMoZf54-B;r-x3;h?;%D7l3&H= zS0(RzmuJ*%{m1M;x!(Nw4jIj|_dXwnx68S~(_UK*x|L-v$dQ?*M+TfFHR`AST@5iy!c8GUK3RL>&LzImgSd!n9*{f7L2sC z2=Ja4xl-;bnSytt!^5|3T);_M#ry6z$*Z09@$tb6_e(|Wq1SxABK_gR!-1cF4uqG- zqfT;{^4N>8`p#)duT(hY*-p+Oo!5LCLPyF@s2cZ$*>As`?vC5<8=B62tS zdw=iyz2ANA{hsGO-+y3 zT045(0+19cZ~uYG;}3BwMC-Qa-|4m|1Z+JbS63u@cJps35&6$hxFChPm9L$UC^x?t zHyf(byTPtt4 z6hALNFBh*67r!tm2=aDxgcFtlp)VxcJkMLm5D12FlR8~MWLe0}D8gG@5Q?zaY+w1(ZE4>P|Avmy`wD}N7Ky|~T4 zrw)Sv1&m^88*GIPl!c$f3Xwy@E0F-(TamyplNi{NUa2DNoT?qOn;j~eT}SIVN9%EZ zlK>Eqy=1>^%sh*vY{gps)hz9N%Z5 zmn|5BeN85_woBWfU@a;oo298u|Ic`TnMK)yobfke>tK(lkJ-*`nC4*Z(l+Pl9p)|U z-_1uB)SJ~j`9SV7SWrBgHIyDfpG@oh0x!9MZ-}jkHZERCt?aqBE(J@m_p{$KhXFt+ z!EY=6NAcT~|5$NRQZ)MrYr`1-DCcca**h-2U)xJ?7l#kDVoo8@isPEL^Sr9XRGf>O zKA3V8r|7D&760)lP^mE61UWQ{-%b*q;W@%q0(!;2D(-}7f{~=o=XMx|*c>EVhK1&-<*-1+C7-S&)VQyJ7w9IRNN1p}&1H#X6R6Fz30ZJmwz- z|HE@Upo59j!--7y>X|g&bH4j3sC6nhMXabJsG&zGj44P?|C(Rl}e&pG=)- zy!2z@s%%x{xS9ua>9gPwPrRHp$ADC8aS?H&ZCo+&|D zVkuc-#XrseSqU-{)IkCBU&DZmrt~3Gf`9P>x%3Dq$_j!z$^Sh4C%kloAX@*zOIA=r zR$t?P&gp+g_+JV9w-NwN9D)Zvr1CH6Igmm`Awa~2Y!XcML@>n0YJkWRp0tElmIo0LBFLtc#{?`4_TAgYi@OhzIBBse%qvL(jlGeZx3yC#sM&3sK(A z4KkYey+wh+okP~&U_lKixC(=-u{l}RcGT?%<>l4bAmy~621q%FTIi64C@Tkd64~E` zvp(izk+-mNaCbqvB{DFdONECxg8ka7Ig$1Mv?&V8%lF!=IYt36fLcg}o1m@Tw(2h zBBC!Q2g92(sLgGRlaj;-#>tv$!x%3}e=t(t`J&tn1OR;Q$*KaecRiNB=ppZAxHJgplYZ??(*loO9UcUdf`BwgOK30pj!ryQ20p;!kr)a(1zB#c0K+7Ef z*lVqPLX!*Ydcchi>2|*i<-=eDV=grMA_938wy=c%)BGVJV4o0zzfLH^u~vW8Jh1-t z)bh{s%m2^Xys2|llOaGp9)>Jy5*jB^$&^bHk48pWPXu6Kf?Ai0-*f{<0{=G@7mX6R02%22RD)44b|<#WaSinLOKt9@LsM z2(uATYXV{5RGc~0+CW%cKe=<9B5U^jTdZ@H5Zjj5y}DUbo64p;uVRyKVUc57F}Rg0Wt!I`O^ce+=k$(x3ssF-(}ft4Q&1? z{~(G%Mj-GH=#~-K{A;}5j8b&j|1`nn7x{MeV`S&*(-f$dL{f(GtIPiOS@48LfL_=5 z!L%aQb3|3O>aG&yc0tj+Dms0W@jW<9ZbVfr_ZbEoT3J{udvQi`n*3;nE{-(^pLZ;u zve=fs{2)2FWIqD{WI}#o45;kWr#OJ9tV#kBfQ5}i)2k>e%T52Pr@&oZlqFXf0OTUa z2%;kUVSFzsS=kZDA^oV~fxyt@yh=xF2sg6XWWPDOJcc~MGh=F52&Sm$dN|9+4#idZm%K$Kmzy<04lm6k&zDDqT-U$ zvhoT_Dr)MQ+TijA`Mnd$0uT(0KL^g+HU`G;`x2Cz;NSg$+xwE+ZSh@+POXB1p}m38 zO`x)ZqO!8G>V0)n1HBuw8?_tD8|xdF8~BaQjX791xp{EobYl#b@Ec7KV|rr&`Dfas zUPu$JGW&e4;yoKB$8S#ND8Q< zhpx|U8SUz1ldTY;503bbM2*C!w*o$0Ko~^GkS2JDy*Vbz0;rPKOY?fKZ|G{|5*m(T zpXf zS{KjK8kzKH=30c9k!Qe)R99AJCMhW`Q1y(Agd@ZYsWKy z81G4*_?huMvrI*OZ?8{(r1bNGl1_tdkl0rz?IIQn$^7HZlWG3RX#6H8$&GJRK+oP; zK-Y?}Qgfz*>4msKPmT(bVU{Wp&?C6rX3JFD&{FY2t5z%KZp`U=+*)&HYw+UoiV6Km zh8;q~%+Zu7Xxn8hgWuC_l&P-8wV8)KD;id=RPn0NsNb5R&bSPUsrsq8GAeefk^GLV zeq4EJG-_rAmczd5(5rzWPV0rD(zkz3a>Uk@=?4$^4v5hCed+73csiF z!kPp?wQQZ|+{sQ%T)*4q*7ao7w!?*HJ@8W9tyu)gJt(c-fg>%k0vT{sNaGxhHi1!< z2pASWA3+F=>kiiouDYprqzVWuEG%X!WtE1ekcK8&%^o&r#T#b+K3Jjg+>L$k*aHhV z@r~yq(NIhu_u+sqI4*hL?IUt97Lvj>FOMIG5iGh`*v7C z?Xh8m9iCbEYN0of0WozHAOJIifI@gc-T%3)D^A#b$m6OHYZZW+Y+0mxxd7gK1_oq) z6P$v#cadxf?@0&@^ip~=p5F~7i9wUt9BlYpd-kS7Xl^5jPVinV2z^JUe=X;$>27(d+FEsV`?@Ax{*rZensT5BcS!Z31 zLy_^wJjFXVtvJ`(7cV$i=*E+=5S9Qhp6m9G$tla5-hSQ~Lw$@B4xxM6XfLJ+<1qT| zI;07SDSBVF@ADO5Hl^~;Hk{%fM40y$;+n|>W5(boWa+R1_$|U1sUin22Xr7+-35A# z+O{4!)|kur^aoT$eVPZr?)?0clAU^g%`yW%5Q}<-onZSqQGa8GnbSCmtKml>s`35+ z`p`4&a#YI&VEkt1t@$+S=GLBC$lFFeKNFT%`nYmKyEj9+W4qcb*V&rQWkVw{7a;aJ z8n?8lYdzmah7M)m)8LnwtCpI%D8mx1j40mF9x<+Kg1t@KDeelmwBf#~&Zhgqg*-Iq ztKh|QzFst z*VR89iNobIu`;6k-hJp!)$wsMP}o&0aT9Sr zA5?{1Vx2$u^Sx+QN~#bBMT!!FXqo=j$kf|Ge{?%KPuilP`~?J6G~F^P-p+5{u7>micmX8 zA)$f`p}qN`DIrII8J01 zO7uBgv1F^h*t^_!_wi*TiD4({D&I|xrbfed`1Xk*rUBB`zB%hmonh?DfkUdu>F{#} zv(UP~{ZJH%3HhTC^>|%3pR!r-T>lzl!iSo5cg`z=Cnmuy7`{$fPsW2gJ_?a-1i=r_ zDPMaWZaC-1`kkKAP(*cp1M=e}P3*Yg$xWIWnWS38$iPW%PWTnxN@yn<%R%%mmihQS zqQ|Jc%~a!jWEEC*P2iu9HcZV_okQ5P)HtmH<(ZK~sX2K|$8(iZ^ZT4mv-O6X_nw-X zd}weOfpKE?!L1WfO_q>Q!`P@SJ>T6Wz}tfjM8C{F&3`Q@3MhUs&_`-WWc+yKGbW$}0kvp<1bkvbCfgQWQ{;ifJ z2Ae^1R@{pd8rGPQb=MpcejvoSQqp}qg3ve~r`{MDV-e_K|F|5}>cR=E2s8QTNGz+} z!OWBA&&PEw5IC&D!OF92t?QVUd9Ls<`;|ZcTYXEc@G^n}a&uA}AY}EZFk_iv%FbQV z?9;)!iXAQVi*P=*Ej9-m^XE3d=t#AkuO?St1hZY+H;k7o%=9v`RG|exn*eB)(B~QQ zrFGRf=J=jiV{*R8S2~T)pjfh>!)6Hj`QIKoOnw}v#MS5frd|4;*IH)|CoYq(z3*G8 zBC;(~(LN>e3=9%UndWDDkB2QvAFH6j-1w-{5iw^+YGeb&3SpB_#0-yDnqkIZWWyX6irx^DYItY~mA>?0j93X_S1jvas`a!A?L^1>z zMWW6?W2(ob1z;?|P&fNR(CFJSFbpd&C^CA?+l&$kPvvBkt>6WNP14b!MU(v8+}IVT zxC(U`BP*7)-OP}^8?AKe8_{;2S1_|5Cpr(_stD^;t{gP>OV3CMwr1JvDt+Q2Bmy)$ z%gtRis3_OpyYXhj02nmtedbqhk5jpCRFp5eG6L9?S3COnyE>RtE#E0Y9tNP{O{R2v;bNhNKQ#?I zBucHf99{p3TW|N(tf`Q)R8s6+=~qK$#Gw!FbU~JTPSbE(d;3>X-kyZix+Ogm%rgY> zk5#X)N0pyH2>P$s8;REgwU(I3$d)D_z71g^Bd5TXYLrGPYd`ci>NMKZLo|!LF^vbJ zUrBJt?OV4wBJ&>7qMZ;q{a{C0OJzQKNx>}2s|f%wQi}CE6@7{H6fccouBGS@z@!cf z7=kla;8fVgCRF)AZ~$^P%La1JHANK-g(ylq9_k^?$P^(WT%0X=%bt)d6yO*9o2}M{ zW#UJM1tNuOe(^4Eg?4?SGtR&hv<4DA;)ji<<`)Nn4mGXZWLn#%JWPPKxGQ`41{Q1~hP`dY9IDNS`8(TnC+4*m!+n$~u%bVBelc}j!0IqLcFjIYg8H$(x+ zC`Q@beu=Ky1X=jG+Mgo z;T=MnPMl09-Cky#l7=+VhV;$TKSe-{IV(fVD>xR5T{#1~x)BO|NkBh2C0eMD4id(R z6PMGQ%32k)B6&)3o((Qh09Xv!m@nc5V8}f_n8@VFPYe&zxP8;k=^G^w;+Uw`5x08YfZe;D*U*K@9~+hiElE`(a~5^Sovn`4;LKM?)J^~A5+qAzOHFZ z&`idkc($LELJ_BmQpj;gVAf^RGs$pTPQ&|`5-I_PWU{@aPpfj2CMTW z#Nz?Z?n?i4gRur_hoCh|Xs%L~K0{=3**DLy4Ht*(2T+arc+sfFm~e?q z2;w`j{6AClu~&-L=Lf1-Ydj~{iHSynz%jW-O%`;s6$NVBQB469-l2Angy(Ry>AL{8 zj?Qo$Rxx;xyOS{aeuJTpG6n&)(Sd{@0X^r&rioIO^Y^HR+d`1EjV$Y}Fz?rK(ql)O z--+^2Y-S=tL8Z$wfW06@su@b^K`LbjR^Z=8^z)6))GneJ-~;h<3Mkyg($oVfG_;Sj zazAR;$y75>jKeLPCl=P7O#~_Tif!A+m;gZG?we`yacDb9{}Bt!dr&KZ&a`Xc*{ zlqfUfj}BTy#fEpLOA?v|NhABzLEc!xl@MCXQ-P6-hO-Te zRa*Fk@>V#1GMm5!Qdiy)J@`)1{E2U6{G*W6WHKj*-lia|nbU}LmxCtqh%3yKa!g;q z%XH9gA)U5IlwaR=V6+0FQcjN5rqAl4vcd9W3Yi$-eF_%~L+df60!F8dpBHeAK=^CC zNk+Ca%3HDl%j^#Xn?&!efGN_dR(%)M&2zqxXUg`}ih|~pkTo+0?QrmxqQ{>F6JTOy zk)<}lP+_Se$P}a^fr{qAT^wlD?vFnI&VRJF$ggR=P#lr2xF;rJCnzGUX}m=hR!`fU zd0E*#Ro*1uoYh2QwXTHqWVlWKY@dG&)5UH<#cf;Jw~sQPG73@RPkl?c?sWtn(_sXC)hF8uTS}oHunLk2M3CBj>tK`oM3j~fgztd6 z9rc$SZY&O3&mO9EL@aS0J7rON@jmr0-X7e1sqaG(`={t8N*HOR4n1~!sB_x=5^-6Zk%|5BA0x;v*{=F%aeoqQ}wak9N$Vh3G;j= zUNBj-PF?(%o#pkG%6U>`fwm-eKN8yD{p$`h>9FVh@5k>~p$v1uerCK-17_Y?=ha$j z?{3RAT&G;R6OFk&7XQShX4{s#kce`EAZ99|O|Ra9cK#$oz9Z0=(ce1#Bk0)}^kSU-{&fPw>!66OKw#=dUW^DK7br)odKs z$eb=f9`^#@Fi%!yIMVpcEl*wQT*WKA4aC<`-J2J4-zjq&z3^YejwEgPIW0+3!E8_F zHgEp%mu|(#0xBxgDRW(T^5asRBWhogaoeH7)0vsdx&F=E$OjX@?3jn)J>7REMd(hQ zJ2NW)-qh4FuFe!yr459+rXXGbVEH+OZFbVR<>FUj%Yet4*(JvJwKw+#vWckmSiG_*c|th@r|F@|7W&cl^L(SCdFc}d0%?lTiXO~!*zsGh z0*pGQ@V%Kb<7z+18!%U?Mc!V1zR3^2iFp1z^hMWIU+Bifg7o9yJh$Tq87+sny{`G@ zzjj4rg0r?`go4%1wbHp7haaBiQMC`PZvBwyVY==pq>pjY1=a#S6$L-|I_P7cbe)-3 zT{NxnO^pgTf1UY)06BX}>-kOJJLO+4#rdoFmvZCjgPigB^DCwK&!+uvgf#f=r~6cX zL{dMo-)Y{wyCZz5o@aWeQiLU6(&%FHYGwf`F=&j>Ia@^Xo`9RfXF(J7#BU6&r=r8T z(+SoA8;>|^c#a_7&IOS((+xh8Hau8(LAlK<`+nsiQYuXc`bDkQms+YPc1xTsLvWsI z0Smg}UE!nVbnJ{5v z*`c;T4MY~`hA%zbxx(7mkkbgPzCW-L&|MQ&*ZKK*Zz9Fv%0#(aE(!TQ^?I+VKow>2 z8yoy89OT@1;{)N+PkbnN$f9xr#ucn@uZ$A7B|NArgf9Zz#2 zdD_K?4^HcTNgq5d5|;u5d^XqDPJ@qJbMl{11yBZf$lD4z>zKrhGJm`6Pwe6bQm?eT`wP5~RIn zyAlMh_-v;0CMvgQeioG{cDC6)!CDjZ-I+YHm3bxk;hpc{d2`E&Xx+z2Ts?QbwrwU= zN9G1D>t`XS=@E77nf~hd_ZNlnV%yMwQn>xA0UL~B)x2*uFR&VUd%M_*A#zL|*7QhY zRv7>m6DVlOnyah&*fTi`>TkMvr)gh0D=(@#&VLYic|20}SV7hnwV}JO>@3bdtDT&} zt_t4N(^*cf`?17)artSA543;3l+xNedkbj^JbV3X`gpZlkIL!ij`?D~A+;A_k`T@n z5}Kv_4c`d`q0i6#Aiuk*0IWPPpy4aq?vj)hQUTioiaQ)74}hfWF*WB|Hbj}VALlZ> z^ZMsc2jh`h$$s9k6Nh>%Je)Z<{Zq|}+EEidy@gFjg#RAbTzsVL1aYg3mHU9}yUybh zYeZruD=KuPKhtMl&(C~)a z=&bC0^d@emQ7Dih!7Xkp4y^nJq1Y^n;aFDSwx!2#`eCH^9nDj(mI7jdw{ zf7EjLcslm%O%gOy&KzGnjAKvbmyzksy1<$F8l3GuQt}D`>D@~gW7|0^DFT# zEBM)K((~vGGJh06J$)kJ;~D{v+u-6QZE$FF* zK~Ruo`6N;6yMC9;ua)!(?AcCOh-=&0cH3UF zWL+kpW)3a9J87^t^cMH(*p*hY`2I5&FUemd{(I&VX&ijySh>3vCKIwGN>xa$&UXw= z`TS3yA-tIPzdDFW6i$?9ang&5#O5&iwLQMm@M#x~nP%dw>4(gf6_zb=jYaL!*rmPj zn#N7G7gG#$>Bw$g%54Cnubu1N7-q;g!j7mbT+fqujhl9duVL4Wo2To2iSEY-!pS74 zNu@+v4(l;J+89k(YX;sWu?XPJQ%f-1T{>PoR-|~LxgX6rgyZ{>KQI08s*ugF3_F^l z^a?oo+Wm`oLV^#<88Oj0=MZXWFk8d~%6HRnsHJ23)5+;+Yj4c9$Loy^e7B|fqpGEn zSrmZar+46k9_x&Unv3_JMQl+G(r4^EO6%qh**ajcsKHIJJy4U8Qn}n18$6Pxtix63BTTQ{>^e1DgNW!PU2^eB}Att{mCV@0Ri8K;_X+-*I!f*j?51-JbIZTybaFpohP7{ zNHm!7kUt9Q%;S)7U8z(rvA=nAn&`*bEVg6txY9UUQQts~X-f8uYQ^#8L%1Yyt_yC1k1GZ?c*Wzp?Wc5oWpOZ_C+?jX z^ugMAa-8}+>AK2^f4OJ^TQw0-5KjNA`2bxc`vp=KdyPcry>F6y@j^b&rX%%*mtenCis z0vHKYj|-Rlr+eRp^i7_Ls0tjsxbB(P=pv0Pom2ID$`XO=PO9^<+BiL~>4lRgi>mM{ z>zm6V@@n-@(M0^mrSuiwUC<kA-)l-IIhQQ+Z?VKj&K{V<~Vy%s)o_BDjje#>-ja z!ootJqI$H1m1MlMqy@~8$=6Vk36Q4oe+0$rLA^zKW`GDsbkJZsEp{Gq$IeASV|rJ7 z5BXPk_Wdg2ALyIC#ScZ{%@!K?vAuh=b$a>JwC#;>x=qGI@CpytZWuhH0guG4#CM9x z9@?imdO3uKHPQg%DReu_k5MkKS4kIX`{<>g_8E zg%i8(_`*4%(^lAJnBaAKzVgkn*--wK(d(LP-PO^Juh%~>F5Nr5HZmKsA8PqdtmMMI zTzMK+_Vzl5m9&!h;lg8PDzprU(~UFFji`yccC)z)EMDF|X>n}G(=*&_Bhyme2rtA< zFX=8sYhqzW#%m%a8|&wf&RE<>Y{j1HNgE$xE+#CbrfH0~y^kc?(BEGhJ{@xNG&FoN zPMX837(_%#=X+?ru&HvKQ(k_7(_*plB;xqj{cIKh!9AYg3i~3#FQAx@0oL~Y8J zjQZFUIb>uFnnk7prN#Aa=^HlH!`YEl5qt{d!8^^;t_E;(Nt1iE78c>159W?1aqwS} z;;eB(f6kfFyha~zcxCcR2OAgL4h{URFZ~s5T#@g1$AZoA$`7}5bh4<`jgza_{F;#N zv3{`_cbfRx&bAjoo``AMg)K_*Lb>`!IYzQ=nSB{TMx7v*`Ajpl5 zSRSoDse+Rw zl)c?D`(rm$bki<@E}0Yq*YQ)l31^x~mTeGN4speh9@SIkNX6*vxPITK86}Mb-*-NX zXY};~3=}9KpydX-UDV+8J7pN+45fYXH(4#C3J`EhzoZ~|Df^|tYg*#)Nnavg(vRk< zurSbhL4!p?sc)zM-c@mFpL~irw|uiaf8o&e`SHOaT`Yj$ebv%}tehG9^UG0ceSOk<_slkzt=&VPYl+t)0RRv5%~e+Wc*lu!h?BSTY9f{FG_c!#wA@j0s@Yn@z~L+&!&$#qK7#al833+*Z-VFT z(-9>N0jrq6bh4uLvuwT5N|b{7Rr{fmZ&djwu@b;ri8<2IAj=EZ92 zw7TO^uVn8tJ|CrTh`H_7`2}0TP2{zW-bB+ZZV^T)@v#Rm{k6p`h)O7$3O?RH(|-Ux Ct2wR! literal 0 HcmV?d00001 diff --git a/sounds/i3_delete.ogg b/sounds/i3_delete.ogg new file mode 100755 index 0000000000000000000000000000000000000000..fea98b6f8c09077610e77ae2a87fd67a66fb1c1b GIT binary patch literal 8596 zcmeG>XH=8RwqK~BN(l%UFf=I!4}l>47)t1f1cDHx6FMkWQ9L5e5Q<2Xst5!j6afJX zf>;7bQ$(bwfYMYf2qIW{6Y!ktJ@2k}-&%LQe{a@gnAv;J>~D6PJ%f#}uN}k!{VW3_ zqi|+d6OLqqNx`BHhI#sjGXX5dHOxPtgl-aFh1oD?{#BSWVPG_Lb&H5l-1^_j8P?6E z_yC2KN0g6-)-E;eT^LnWHUQWTe&i6ZgWlvYeSq`=NDV9#i3;-f+?*%)7m2rXZe^b(XuZnM(1UlF?$Tvrt{ARh4mJJ zAT}sgkt@Ay&OBg1+gD5>J*-6Af3Ma>6erboN}KEU$_}rPil&OdkO3umIG+b$BfOV@d=*z~}VN2TeZ zg%xJl!KK0me97s8iVS1J9}#)D3LDvqsSvskt0#Zo$?Z$uO4^0n&>>5=(3vVA(r&B zt{tCTW!8r)`X-Q7RZ|^5)@aaj8bNqd4*3voqu7AUv*1x zZzH<5k#~axf&mg{De*6;_;1z6DVO~3E6%T58NvZsc7-ClLgnxTxvnrY=Z1v4A)r$n z0nG@*nucS$!u3EkjWE8KZPowLYRjKW*syH~he0wzk@tW!2r5Hi8vDcbN5ZW~fGC&} z`Jc;l|~casw!pj?vi~X1}@KPqV0UEgHC`{T$3l9xn{M#^nNfpS_FT^>Z;{ ze>Wc-(3{7oSZ8q@>UcVbCqlYHI!h|zG=EkJrdz38DlOf_qAGqLL0o|r5x22(6a*y* zY*_K1&4wv&T5)+MRk=s;a-Ui+n%UIc8PHj%zawD8ivd=Q)&N$V);xDEyiVIJkka`y!#2Y;#eKOk*|1U!DU2r%BlG$!yP5Ojl9-UPG=;1^?+e zp@^tCK@8YTxS@Em-Y+%KNffk7GpZ)!wa zFK_Nqe-H>X0>AZF1wc?o2CwBt9I+*+3==el2`WT;{r}lx0CpH_J%j~<&4D0s2%0Ic zcyyFs$TLGb*}xBOeiz9&p!2Gz>_FS1)j$&=0lJ*0@g3gJcB^#7{ua)^>M=Z&EbF6 z0!CO{Hc)>q0~ih3!v?WGc>yjR>UbO$oFxBw`4_xwHDETs@WNrOarV~#Ij8?$;r}J@ zZzTXs9L5iRqJ|fwce2E4!Jt#qxJ;D!A~x2`X;JTpgq84=qp04N0?wg7y#s=9OV}e) zdRr>EGO%0Dao&&j|0}t+7;(7!Q+#VSJ3 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 MUHx3vIVCg!0F!X3YybcN literal 0 HcmV?d00001 diff --git a/textures/i3_bg.png b/textures/i3_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..383d53298b72198c533ba1188e53d82b0a617e49 GIT binary patch literal 1297 zcmV+s1@8KZP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+U=KJmgFW3h2L34mVhLL#Bwk{=gbbW{9LeIUDeZ* z%uMo-hcd^21s3xC1l1kJpWkNq0~eLdA*p#TIY(Tnq{0;)kLOi(O)>2{UQc)XVh@i2 zMo-Yn`Dpc;Ut!me7w$Fac(n(=M%XV$x8uv9td$v^{v0IieA+2pj>Barj1xP8|N^GGuKA{x+;+@AzNUOw+` zV|*6qRs5?LKCA!eeG;GRWtUG{=9^mndVut6@wdcJ3(F%SejPBmU40?)>^|o>zpkbX zMe~(WG2H5G^=F6dN%m_Q#c(V7wo5_rSYre79$P$68WmztnSl~@sx)crwoyZfi3b~6 z=EkyZF2;qMEKX?^nru>}gCI-e5r8fUKVqT1ZrSTKa;)45Q<>n5@X8NM_`AVhDPhjG zB%Qlyha#{+^R7PKxkgvbPIf!3x9mdAEYV>>XzB@fi)hdi$m!nw`6k`%u}@I z7NTJNasY|2wjvl35Qv#XDN{6NBZ7_&KoyZQ_QnAMq{Dw1d!0Ym_?_Qc#&JoV&Qe3F@n^^CUjcFfG`bWo%CS$LGGux1@)ie z#{WbvEOh?`xd3$EbNhl?U%zv06FYa|(liQo-xROxq4JS%{;Ymoziz+VhJWke?da|3 z?da|3?da|3?dX5t2!A}_pU&_XplqH;D;UEX>4Tx0C=2z zkv&MmKpe$iKcq#f4t5Z6h)~7Bf~bh2R-p(LLaorMgUO{ILX(Ch#l=x@EjakGSaoo5 z*44pP5ClI!oE)7LU8KbSC509-9vt`M-Mz=%JHTHrGt~@^0jg#h>10C4=2nEzE5Zn( z8-o~;n5oZ-VhWz)>mEM7-o<&A_qjhumy$Ob;1h^vm~L3a>%>!=md<&fILbC;;fddta(rV z!bo0QUgA2<0VJ`2MTig}qlyibVIfYdMv93v?I%3^{f=KGmrSk=FmlYJ0u_?u2mgcL z-I|4oaW^TF06Jc5`(p?Q?E;OOZGRuzcH;yHJOfu+%U`Jj)1Rc*T3YM~=-CD?u3MVC z2VCv|eNVb%NRAYs=`R$3_cQvY9MF3UbgsI+HTQA)0A#4E)D3WO2n-h~d(GqB;r8DC zJ=5&(2VqEZprb|LkpKVy24YJ`L;wH)0002_L%V+f000SaNLh0L04^f{04^f|c%?sf z00007bV*G`2jmC@4kHaTl?ikJ000e1L_t&t*JCiVwEqME0{8);67yFI00000NkvXX Hu0mjfW0+Bv literal 0 HcmV?d00001 diff --git a/textures/i3_bg_full.png b/textures/i3_bg_full.png new file mode 100644 index 0000000000000000000000000000000000000000..9b299034e81a854aa6737162ae4d7c11ca86ebb4 GIT binary patch literal 2701 zcmeHHYg7_=7XOP6@RhMy`5L9tRw`eajpZ|yluD#z6>$)JmAY6cifE>o;;4-n)PyO9 zBbx8mw$@@+<|A8m(w!ntqN!+VK9-!8Fe6*q-PzNAn=hU-ANGIGJ@@|ZmwWE-cmFpZ zi}BUhG0_14=%f97P642H`Ln~cR2AlfgM$D--lpO3NvFb75Y)tTr(-G6h@@0%G$NW2 zdl~@7=rWJ^Tw<-4D+@vKn3g#`iS{0INzhx$`(zi=PZ?#gE;NVj4t;sBeKQI*ZqCZc zi1Gc&3hp6Gry;AkyuIJ!{!%fu($U|9yh)s}ZSSyKe=|?UXMKOGdm*;AtJ%U}j5fTo zV2~kiA!RkOUCJA-8yBwgEtTnO$Z_MsTbxT0S{+nyo2Z_$XT;4^#z^B67ikQ-W%e)XTDuRzl${PrS2WQ zef-D@K2rT>^H5i;$<_$$^{n3|*BywZNNRTU_GIf{6SYzVmlCFSUkW6!c9$ByMm+wB zk;B5Qa&(td2W~WTB4;s1{W;_u-wZ<6MDjXDn|9j@j>?Q-bub$LSlRlx(L@MxW_$hb zbf$>j^i|8Vt8^~5N7FmVg?+|S>>57wPlt3LA(uofYy1O<=gz@Kzg!KCh}|dq4GUl7 zl?&CesM+uCB``s4qA!>4Lp3*cX%?+~_c!x_{_8x`Gg~~Z=~uG+IXZYG@_CU}pGn=G z5}Z?gE!2i^Yv!uc93}OuL~#$dHrkQ4H;CveN~6;h(l#obpG8P)l~!FP9KxNz!RsT^ zS#y)#?4)^)fs4}GHy-b9;}kCnc^gDn9;=!zo)?8G!qUDn)WQ^Sa@nqwRcj%pp$+Ni zUzR%hkC4+Buyn|iL{8#$T_gHAp4aJSfm)}(%R7!x%^Go}b?YX+b^k7Yyt|i_Gdok2=LG>3{vEJTT zw72&!>#tgR{soSkU$>`OFUg}4Rkw-0IUx_*`|x5-o-pVK*jBH`;kxXz#`;T$G(lM@a!mo|RoPH` z1NEh};aYt|YQTDzUs!0E^ze^rmaR-w-e!cbK>up^4ov;gg8T!^zjsxBWRom;Cz|x_ z69|e~*GMin97g#N34<*|3QOWMEhO}54VbHXFkygHtNv6_IYJ;T z!RB9R**1libU?rPJGcYwRTsW83m z$n!r=k59dOx$gFKNd^t~ODq?nCON9Jq!n@8*GCmq@4ffkOjXdP`i0N{u-*09)fiPC zbX5_Wg!V^4XJ8tec5WHT(hLGXvjFXL1gAP#k{zc^!;P3zysh(Q2zLl8T#GfS;f%rN zd+i#wjtXEdYVS;g7(xWqw-F|H5I{qJgDH>9b{->*tD|Jh3Zjt!b(sSg0gu zbq2T8hSep@aq%AKU&ri5q=@~KDQrL*4VB}^W$s4wjOIFlxRC+u+a~F8-Ep>v`UT(Q zxG=EfTxQa`whu8u8&d1+c=fEnKutvZ8IXsrJRU#qxvg;fENCezjdM8Aw9sx3C6oHZ z^5NAoC@_;I#wh(ZgG~whqu%N;yKSJ3V3Gub0SJW21PBCBr5lX?-Q<^k8-R|2|BeEI zd^y-gpbaMLf92Q!vi_s_zvTFWHdVU8=>Ni~)cnlE1Be0stqz%T%D%7O=Nc{QEK+*9NQ|! znH@pFn4Msd@7i=TND05J$omFoAi_h*l!x8Vaz`dC%*x70gCAp05`%eSblU-6rd{~c j)xyd4gus*!FOEL|l8* zaB^>EX>4U6ba`-PAZ2)IW&i+q+U-|aw&f-a{AU$e0uqz79L969gDgMAVBe`(}$V*sJo=Ztf07lSAqD zYs$wyqdh!6xW=IJ+HU0ZupCEpJ6=CGN1pZe93?073M^OuG zy4=990CKlJi?|Z*fO=Y&;u4!}1?A0FTX0oUVz4p{d1{ntP+w)GiV!__PAHixyVWKx zv2t~jCqFM5oSeD_2H92aW>V+)j)m5^y2h&{7`YKlnc$4@$(NV;S?52w%oue-L{@IB z5EoBfBaF%1e8LKZ&^Ww>1@Ltp`t6f`AXP9J7R-VPW?Qz466m2Vw|I823n=#zB9q#2 z0EjSlKrrOMfQ{q=MY4%G5dlX5K^c)_A#ec$6aqH{$=xU#*3+Gmu}Y3YErsf z&`c*`at6lO6BtjE0SKBWXI992p3F_otTGlwU<4T^H>S~K3>5lK90uLoJ(&9?-b|2R z;*Gy!&P?k53+4={`{eBhthKq%)y3Feg%eZju=-$=SqyG#@%Y{He@DOR$knncxmNwo znQ?_zHA_sjL8pWhQx>Rt*5+B`l+@~~g;pW+w@w?(vFf93A9ZNg4<|k7>W3w6Adv|)bj?~v&OGk9RzPlM*celef`qXEZ z$C_7DCLFum3CkmaJi@|i+27aZvTeFwuoDk$T^4I2)b8IoVBNrCZCwoZ5+ANU12tbn zx;mZPeXTmFxol|2rxM#5rblfyw)KKt1RK#ZnFq^VMz`b1YLR_*y(`sz867`l5hipL zdCyohrgGf$NCm>&BSs1KCkoXiK=TUxY8+G9L-iwB7B9DH4xH{!p-Yq);2Gk3k7-JK?|8s>sGU$6K& zwj=DbJsj4HRA2OhDzkC1114$GA<^YN0Qls{K0bgF5zBT zpbOI0Y&LHR`Fvh+uCWinq{i0-C3&p)wx=k=Ub)ZAKdSApG=lB!yPeRrai$Box7*x2 zc2#@4Wz_4p?rOi#6U;)Jxw6<#ss5^bl7RVEX>4Tx0C=2zkv&MmKpe$iKcq#f4t5Z6h)~7Bf~bh2R-p(L zLaorMgUO{ILX(Ch#l=x@EjakGSaoo5*44pP5ClI!oE)7LU8KbSC509-9vt`M-Mz=% zJHTHrGt~@^0jg#h>10C4=2nEzE5Zn(8-o~;n5oZ-VhWz)>mEM7-o<&A_qjhumy$Ob z;1h^vm~L3a>%>!=md<&fILbC;;fddta(rV!bo0QUgA2<0VJ`2MTig}qlyibVIfYdMv93v z?I%3^{f=KGmrSk=FmlYJ0u_?u2mgcL-I|4oaW^TF06Jc5`(p?Q?E;OOZGRuzcH;yH zJOfu+%U`Jj)1Rc*T3YM~=-CD?u3MVC2VCv|eNVb%NRAYs=`R$3_cQvY9MF3UbgsI+ zHTQA)0A#4E)D3WO2n-h~d(GqB;r8DCJ=5&(2VqEZprb|LkpKVy24YJ`L;wH)0002_ zL%V+f000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2jmC@4k8#pQ{3JF00D1FL_t(I z%cYXPOF~f?hMy~eBxw*XE&T&dK|xNA7EV%A(qIq`aub4}@E4haAOz_YNfDBR2r41b z+R&XF8ZHr$V3P@kSWTzto-{8lzS}w9d7t+?e4iqOU>sQ(Q)2@r0Lr!ENMT`qNd!VU zd3L$il)-u-;`s%bNT|sMHoH?^JZcqT2C|qXUtYiS)$bAu`#8(217Nc|vDuwGY87F? z%m6}7Hu&myiK@%Y%}xVwmRTnj_DN9t?P;`w!DQ>CgKXiRt^E=JudNP8Ck+7FEuCyC zC;^HPf^w}W&4aQ|Iso|o`~aY-Yh+VF5}7&=cO^x3U}iRqhS^Boi(atk-ByOakdOOl z>Kg5qZaR{tt`XT?A(5%$Sv?q?LLihQ9S=|~9*%(8EuC~cKqPrJlsvRZF87*}K0Xz2 z!)-MWfPW)Fzt@p%|4kkO0Fv(YtHL%l!+Cy(=a;8{&8C}ZJl<4uqTlQMYnEdiM?cDa Vr@1EZ_R;_V002ovPDHLkV1lKZ9Z>)P literal 0 HcmV?d00001 diff --git a/textures/i3_btn9.png b/textures/i3_btn9.png new file mode 100644 index 0000000000000000000000000000000000000000..34433ac82a89114e0be99fd1f2a9bd1bfdfd0a2e GIT binary patch literal 146 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 BMzR0^ literal 0 HcmV?d00001 diff --git a/textures/i3_compress.png b/textures/i3_compress.png new file mode 100644 index 0000000000000000000000000000000000000000..754179cdf60d2fcb374bab92a1a959b5f9f8b53e GIT binary patch literal 2825 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 Z{{y};WUZm_drANR002ovPDHLkV1m#eZ7%=- literal 0 HcmV?d00001 diff --git a/textures/i3_export.png b/textures/i3_export.png new file mode 100644 index 0000000000000000000000000000000000000000..e179c0707db62c4a5dd9718a8d4551ced9e1391b GIT binary patch literal 6495 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 FV1hVuk4*po literal 0 HcmV?d00001 diff --git a/textures/i3_fav.png b/textures/i3_fav.png new file mode 100644 index 0000000000000000000000000000000000000000..b1ff1d57585df47355540f0c284d51b9e041fe15 GIT binary patch literal 7051 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 literal 0 HcmV?d00001 diff --git a/textures/i3_fav_off.png b/textures/i3_fav_off.png new file mode 100644 index 0000000000000000000000000000000000000000..61aa7de219238ede243e2aa2e30d083cd2996fd3 GIT binary patch literal 5095 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 JPDHLkV1m*Pmf8RS literal 0 HcmV?d00001 diff --git a/textures/i3_fire_anim.png b/textures/i3_fire_anim.png new file mode 100644 index 0000000000000000000000000000000000000000..22dc40a4749c809b0b04c34d2f6117163cad5ec0 GIT binary patch literal 7434 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 IM6N<$g4T068UO$Q literal 0 HcmV?d00001 diff --git a/textures/i3_furnace_anim.png b/textures/i3_furnace_anim.png new file mode 100644 index 0000000000000000000000000000000000000000..472c38271a259c483b87ab525a5f13f39be558ec GIT binary patch literal 5268 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 literal 0 HcmV?d00001 diff --git a/textures/i3_heart.png b/textures/i3_heart.png new file mode 100644 index 0000000000000000000000000000000000000000..4412cab587f2690e68731d7def7abda335dcd2a0 GIT binary patch literal 279 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$3?vg*uel1OasqrpTtQq0h9m}tOa_K528JdE zhE4{CE(V4P3=9()7^X8Y%wS-cBO$VYfngy7!$t;%O$-bN7#J=xFgy|Gc&Z}xMnUWo z1H*41Vr2Nu%kW#2;kSy^Z&m5vrh30^%zxWj{0{K>9T)vOF6MV_O{MGAQlNc|B|(0{ z3=Yq3qyagRo-U3d9I~tjIhh&*7+4QzMmyOrY(G)<-+C4!L&1$rS&h%CZf!rlu~D!8 z`p=@XJDiK_|JoH#;+y^OXRZIq4ac^n%$qbtYE_YUP*%c4^`&epeg!dZh+$y(z`i|% V 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 literal 0 HcmV?d00001 diff --git a/textures/i3_shapeless.png b/textures/i3_shapeless.png new file mode 100644 index 0000000000000000000000000000000000000000..75a4e03c3e51d5709db39868d0a675331da5a4b8 GIT binary patch literal 3982 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 literal 0 HcmV?d00001 diff --git a/textures/i3_slot.png b/textures/i3_slot.png new file mode 100644 index 0000000000000000000000000000000000000000..86e6111b81b986a8420db68b41ed5372dd70d487 GIT binary patch literal 567 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 literal 0 HcmV?d00001 diff --git a/textures/i3_sort2.png b/textures/i3_sort2.png new file mode 100644 index 0000000000000000000000000000000000000000..e39566994a5a8e41a3b2e7ddedb7228fa430827a GIT binary patch literal 7268 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 y581kZ5r?IRz|+Dy$0PCTjw-+VQR_zu;r{{Y{ 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 literal 0 HcmV?d00001 diff --git a/textures/i3_tab.png b/textures/i3_tab.png new file mode 100644 index 0000000000000000000000000000000000000000..4dea611a9ff9f22ba0a078320bb3597c834f9a87 GIT binary patch literal 950 zcmeAS@N?(olHy`uVBq!ia0y~yV4MJCyK%4q$w%uCc>x8QGo76SJe{2t3X1a6GILTH z7&Io>zVAK6q)67GIjc%LxmuA_YVXuV{%ZbXp-ARcf&F3->G&6-~XqrtE_U z`;V?_?%uqPZ(WnZ55`ANUMzW`r222Y=9Z3+4|d4Ee`ovd9;4IZLnXV@WiId@_fi)Q zGTW}z8Yk!|qI5_iXh!b2lSN$n9>11j+;{J2<+T4h?cMiJ+b$_Ep(A}}rsWaoBbR6Q zovfT6k)rCVY^N@_`9;%_{+Mvvy2mj&8xI(}YEPc0F4nm;Nqlwe8Lw%6Hm)+4OPW8m zt~oCCT=!hn(qp&2Khf`b(mOSE-Q^yoPFEerHWpFSDS?g67Hiow%`R=3|KTJ5_CH2D zLyD#zJh8Dst3*TB{)haZch~fM{3<*rvRwH6XqUXQLxy<9wb<{!Z{>T zOXdj+*9Dm$IH+h4wd76d{PORm-@m<|Sypc!T39rjS$k71FjhDVJR*x381$4un6YB1 zeHl=Yy~NYkmHi2itcZa6rBvI8z-T+>>EaktaqI0J!z__RhPH?1ixbp2%9OH_^Aib(b-MRF%@+;Bmy_2@Y^UX|V4Vb3aeH70hguaulo zUsm@0TRjUyw3H7+Lj!|?0s{vJ0}~Sv(Ub?a1a1QX-hV3vZexZGOOFQ3y~)_1JD2zB z6+VWXOskOPWef@4%biVEKHJ8S;QTquDCGIoPFsc>7d%V%{p$I?V%ANT2Gg`;W4&{Y zHEa3aFddL$Pd5H%vN?=3^#lE|;Ss?4`7EM<(G879Aa{?)~=*6A|l zwN!rHR~1^j@71!oclZAFl`Gp_6}flCyiosDzs=Zw=<7uN6ED2=>AlM2Y3VHMze?*& XFgU%ka;+6Gk{LW*{an^LB{Ts5aVm9l literal 0 HcmV?d00001 diff --git a/textures/i3_tab_hover.png b/textures/i3_tab_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..44c9adc039fd88ba2f703dc6d4634e1adb0f69fd GIT binary patch literal 16499 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 B7McJ6 literal 0 HcmV?d00001 diff --git a/textures/i3_trash.png b/textures/i3_trash.png new file mode 100644 index 0000000000000000000000000000000000000000..962eac7ad586b4a9e396fd37925101518f42e661 GIT binary patch literal 1827 zcmV+;2i*9HP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+U=HIlI$i7h2L34mVhLL#Bwk{RoOw7p98jgx@RWI zy>;(Ps@jwd7Fd$cC(|9qUw_W<2M#JZhNR}Xz1COQ_2Yp%1|6^V;MWZM<>;EY9m{G>*5|q(SS~cu1p}v%j?~J zjL!nShoo%g-%gNzFaDPJDX=^;;@1h|+tpW*=j=Y`INz?O z3`O%*QCsX=p|$XUjXogcUw%rPv#~K@u_t@fr)~FDJ$_$jKQ>95`_l+7-OgtE= zF>_ zNkq{fS|Kl9b&WI@xpl=V0HJwt(=G7bF8uMSepaa_EL$==Ua-dFba5zs)Rt_{f^~}i z{Ddf2zZ^g!#8xCj0s=9UC}l!Dun|E=2cU|~SrQ*0K&sr4Bqx!~!Pt4l#xq8HEh}eU zX6#J>p_0YGrbq>>loa)2$x%a9MU$##HT9rHYnGg{=A13BO|F_)GPP`GZpEsLCs)sI z?q0kWE`mK!ODfM;UdZ)~3ufb>?Z)XPNau?V|dn{RB0-sPQJX*4cv^tikMd zL2EnF#SFwa5s2F&fP&`5EIOsci`-%s3*)0uMv}VNgiebX5T-$_lOF6o$o&wvp#DSL z_`k@7h3$9@gfZwyY2EW?B9lagB9lagB9lagB z9sTbe3H~~i@HfA9oL02Ai`)PJ0fT8nLr_UWLm+T+Z)Rz1WdHzpoPCi!NW(xJ#a~mU zQYsE+5b2PiI$01Eanvdlp+cw?T6HkF^b49aBq=VAf@{ISkHxBki?gl{u7V)=0pjH7 zr060g{;w&ti1FaKAMfrx?%n}Hqr!B%XB^NC$4Vy?QZ~0Lgxm0qM!N{?IDs(6J>YT&7~)`a_jUL7@0oUgKUHyZoBz@8 z9{>OV32;bRa{vGV*Z=?l*a7-nrg8uP00(qQO+^Rf3>^UlGv()Q6951LJxN4CRCwC$ z+r4WPK^VvJPc9)ztD?b_Vr38!I~640OGqP1Y*f%rv9q(%%1RJB#pZ%G!B`85e}FG2 zsA#khu`opxVku(oEV2?k?so5z-Sh79Ja8~`{C0Sr@9r}*`!L&AE|(Q#{kVfE46bsF zpP0oNEEVBoNpUuTlWPcGa_uP`Day$r0c_53tSv=3IiP*^4)aZFN3o+FPPG%jHB2|D zJ&STXoGMx8w(bEmlLEVNC|TB8u{|~YNsP4N+CR30M|hnk>dV*%Y{Od&cj*oOkxZta zR+|EQyEu4>@B7v=2MqLjn#U>-00Kbl1JZ1|h3#uR0Rf;#QlNz0*wACKF5)GsSpa5n zyhm^NeVj;3flWOeJj?aTjcEWD@xF%v%q1~4Oo0jx;I#U6xJm5n@F3sdL7o2>aJQK` zU;)<~3_j8Y0AAqI|5^s;a1pm;*YUsOGOi@;tm4MaWb9m1G|$)FUpVOB%J2CU{W;uA z+8;2JqP>j^f2~rVwO*kr{0W$^3I17z{&|CTmi9~X>$sg@rKVra&{tEgl`&SO69L4# zKmZ5;0U!VbfB+Bx0zd!=00AHX1b_e#00KY&2mk>f00e*l5C8%|00;o<1HfQLKTSW> z;@Cr-2w>F8+5CRlhpna>wCmY1E9U|BV{2Yc=lwmvV?4xmjAdxAT0T$#;~ClsyuwEu z&eP$%0Sx143;OXEv|~*`jY%*76b#^77sT|nNB}qRRE}qKa