Merge branch 'minetest-mods-main' into main

This commit is contained in:
Daretmavi 2021-07-01 10:26:50 +02:00
commit 7c7266a227
13 changed files with 795 additions and 340 deletions

21
API.md
View File

@ -38,7 +38,7 @@ i3.new_tab {
Updates the current formspec. `extra_formspec` adds an additional formspec string.
#### `i3.delete_tab(tabname)`
#### `i3.remove_tab(tabname)`
Deletes a tab by name.
@ -141,7 +141,7 @@ Recipes can be registered from a given URL containing a JSON file (HTTP support
```Lua
i3.register_craft({
url = "https://raw.githubusercontent.com/minetest-mods/i3/main/test_online_recipe.json"
url = "https://raw.githubusercontent.com/minetest-mods/i3/main/tests/test_online_recipe.json"
})
```
@ -178,7 +178,7 @@ end)
Removes all recipe filters and adds a new one.
#### `i3.delete_recipe_filter(name)`
#### `i3.remove_recipe_filter(name)`
Removes the recipe filter with the given `name`.
@ -197,12 +197,12 @@ They can be used like so: `<optional_name> +<filter name>=<value1>,<value2>,<...
Example usages:
- `+groups=cracky,crumbly`: search for groups `cracky` and `crumbly` in all items.
- `wood +groups=flammable +types=node`: search for group `flammable` amongst items which contain
`wood` in their names AND have a `node` drawtype.
- `wood +groups=flammable`: search for group `flammable` amongst items which contain
`wood` in their names.
Notes:
- If `optional_name` is omitted, the search filter will apply to all items, without pre-filtering.
- The `+groups` and `+types` filters are currently implemented by default.
- The `+groups` filter is currently implemented by default.
#### `i3.add_search_filter(name, function(item, values))`
@ -237,15 +237,6 @@ Returns a map of search filters, indexed by name.
### Miscellaneous
#### `i3.group_stereotypes`
This is the table indexing the item groups by stereotypes.
You can add a stereotype like so:
```Lua
i3.group_stereotypes.radioactive = "mod:item"
```
#### `i3.export_url`
If set, the mod will export all the cached recipes and usages in a JSON format

View File

@ -18,6 +18,7 @@ This mod requires **Minetest 5.4+**
- Inventory Sorting (alphabetical + item stack compression)
- Item Bookmarks
- Waypoints
- Item List Compression (**`moreblocks`** supported)
**¹** *This mode is a Terraria-like system that shows recipes you can craft from items you ever had in your inventory.
To enable it: `i3_progressive_mode = true` in `minetest.conf`.*
@ -48,4 +49,4 @@ Love this mod? Donations are appreciated: https://www.paypal.me/jpg84240
Demo video (outdated): https://www.youtube.com/watch?v=25nCAaqeacU
![Preview](https://user-images.githubusercontent.com/7883281/116791813-0edf7b00-aabd-11eb-90b3-11c604af34dc.png)
![Preview](https://user-images.githubusercontent.com/7883281/123561657-10ba7780-d7aa-11eb-8bbe-dcec348bb28c.png)

319
etc/compress.lua Normal file
View File

@ -0,0 +1,319 @@
local fmt, insert = string.format, table.insert
local wood_types = {
"acacia_wood", "aspen_wood", "junglewood", "pine_wood",
}
local material_tools = {
"bronze", "diamond", "mese", "stone", "wood",
}
local material_stairs = {
"acacia_wood", "aspen_wood", "brick", "bronzeblock", "cobble", "copperblock",
"desert_cobble", "desert_sandstone", "desert_sandstone_block", "desert_sandstone_brick",
"desert_stone", "desert_stone_block", "desert_stonebrick",
"glass", "goldblock", "ice", "junglewood", "mossycobble", "obsidian",
"obsidian_block", "obsidian_glass", "obsidianbrick", "pine_wood",
"sandstone", "sandstone_block", "sandstonebrick",
"silver_sandstone", "silver_sandstone_block", "silver_sandstone_brick",
"snowblock", "steelblock", "stone", "stone_block", "stonebrick",
"straw", "tinblock",
}
local colors = {
"black", "blue", "brown", "cyan", "dark_green", "dark_grey", "green",
"grey", "magenta", "orange", "pink", "red", "violet", "yellow",
}
local to_compress = {
["default:wood"] = {
replace = "wood",
by = wood_types,
},
["default:fence_wood"] = {
replace = "wood",
by = wood_types,
},
["default:fence_rail_wood"] = {
replace = "wood",
by = wood_types,
},
["default:mese_post_light"] = {
replace = "mese_post_light",
by = {
"mese_post_light_acacia",
"mese_post_light_aspen_wood",
"mese_post_light_junglewood",
"mese_post_light_pine_wood",
}
},
["doors:gate_wood_closed"] = {
replace = "wood",
by = wood_types,
},
["wool:white"] = {
replace = "white",
by = colors
},
["dye:white"] = {
replace = "white",
by = colors
},
["default:axe_steel"] = {
replace = "steel",
by = material_tools
},
["default:pick_steel"] = {
replace = "steel",
by = material_tools
},
["default:shovel_steel"] = {
replace = "steel",
by = material_tools
},
["default:sword_steel"] = {
replace = "steel",
by = material_tools
},
["farming:hoe_steel"] = {
replace = "steel",
by = {"wood", "stone"}
},
["stairs:slab_wood"] = {
replace = "wood",
by = material_stairs
},
["stairs:stair_wood"] = {
replace = "wood",
by = material_stairs
},
["stairs:stair_inner_wood"] = {
replace = "wood",
by = material_stairs
},
["stairs:stair_outer_wood"] = {
replace = "wood",
by = material_stairs
},
["walls:cobble"] = {
replace = "cobble",
by = {"desertcobble", "mossycobble"}
},
}
local circular_saw_names = {
{"micro", "_1"},
{"panel", "_1"},
{"micro", "_2"},
{"panel", "_2"},
{"micro", "_4"},
{"panel", "_4"},
{"micro", ""},
{"panel", ""},
{"micro", "_12"},
{"panel", "_12"},
{"micro", "_14"},
{"panel", "_14"},
{"micro", "_15"},
{"panel", "_15"},
{"stair", "_outer"},
{"stair", ""},
{"stair", "_inner"},
{"slab", "_1"},
{"slab", "_2"},
{"slab", "_quarter"},
{"slab", ""},
{"slab", "_three_quarter"},
{"slab", "_14"},
{"slab", "_15"},
{"slab", "_two_sides"},
{"slab", "_three_sides"},
{"slab", "_three_sides_u"},
{"stair", "_half"},
{"stair", "_alt_1"},
{"stair", "_alt_2"},
{"stair", "_alt_4"},
{"stair", "_alt"},
{"stair", "_right_half"},
{"slope", ""},
{"slope", "_half"},
{"slope", "_half_raised"},
{"slope", "_inner"},
{"slope", "_inner_half"},
{"slope", "_inner_half_raised"},
{"slope", "_inner_cut"},
{"slope", "_inner_cut_half"},
{"slope", "_inner_cut_half_raised"},
{"slope", "_outer"},
{"slope", "_outer_half"},
{"slope", "_outer_half_raised"},
{"slope", "_outer_cut"},
{"slope", "_outer_cut_half"},
{"slope", "_outer_cut_half_raised"},
{"slope", "_cut"},
}
local moreblocks_nodes = {
"coal_stone",
"wood_tile",
"iron_checker",
"circle_stone_bricks",
"cobble_compressed",
"plankstone",
"clean_glass",
"split_stone_tile",
"all_faces_tree",
"dirt_compressed",
"coal_checker",
"clean_glow_glass",
"tar",
"clean_super_glow_glass",
"stone_tile",
"cactus_brick",
"super_glow_glass",
"desert_cobble_compressed",
"copperpatina",
"coal_stone_bricks",
"glow_glass",
"cactus_checker",
"all_faces_pine_tree",
"all_faces_aspen_tree",
"all_faces_acacia_tree",
"all_faces_jungle_tree",
"iron_stone",
"grey_bricks",
"wood_tile_left",
"wood_tile_down",
"wood_tile_center",
"wood_tile_right",
"wood_tile_full",
"checker_stone_tile",
"iron_glass",
"iron_stone_bricks",
"wood_tile_flipped",
"wood_tile_offset",
"coal_glass",
"straw",
"stone",
"stone_block",
"cobble",
"mossycobble",
"brick",
"sandstone",
"steelblock",
"goldblock",
"copperblock",
"bronzeblock",
"diamondblock",
"tinblock",
"desert_stone",
"desert_stone_block",
"desert_cobble",
"meselamp",
"glass",
"tree",
"wood",
"jungletree",
"junglewood",
"pine_tree",
"pine_wood",
"acacia_tree",
"acacia_wood",
"aspen_tree",
"aspen_wood",
"obsidian",
"obsidian_block",
"obsidianbrick",
"obsidian_glass",
"stonebrick",
"desert_stonebrick",
"sandstonebrick",
"silver_sandstone",
"silver_sandstone_brick",
"silver_sandstone_block",
"desert_sandstone",
"desert_sandstone_brick",
"desert_sandstone_block",
"sandstone_block",
"coral_skeleton",
"ice",
}
local colors_moreblocks = table.copy(colors)
insert(colors_moreblocks, "white")
local moreblocks_mods = {
wool = colors_moreblocks,
moreblocks = moreblocks_nodes,
}
local t = {}
for mod, v in pairs(moreblocks_mods) do
for _, nodename in ipairs(v) do
t[nodename] = {}
for _, shape in ipairs(circular_saw_names) do
local to_add = true
if shape[1] == "slope" and shape[2] == "" then
to_add = nil
end
if to_add then
insert(t[nodename], fmt("%s_%s%s", shape[1], nodename, shape[2]))
end
end
local slope_name = fmt("slope_%s", nodename)
to_compress[fmt("%s:%s", mod, slope_name)] = {
replace = slope_name,
by = t[nodename]
}
end
end
local compressed = {}
for k, v in pairs(to_compress) do
compressed[k] = compressed[k] or {}
for _, str in ipairs(v.by) do
local it = k:gsub(v.replace, str)
insert(compressed[k], it)
end
end
local _compressed = {}
for _, v in pairs(compressed) do
for _, v2 in ipairs(v) do
_compressed[v2] = true
end
end
return compressed, _compressed

62
etc/groups.lua Normal file
View File

@ -0,0 +1,62 @@
local S = core.get_translator "i3"
local 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",
}
return group_stereotypes, group_names

13
etc/model_aliases.lua Normal file
View File

@ -0,0 +1,13 @@
local 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"},
}
return model_alias

116
etc/styles.lua Normal file
View File

@ -0,0 +1,116 @@
local fmt = string.format
local PNG = {
bg = "i3_bg.png",
bg_full = "i3_bg_full.png",
bar = "i3_bar.png",
hotbar = "i3_hotbar.png",
search = "i3_search.png",
heart = "i3_heart.png",
heart_half = "i3_heart_half.png",
heart_grey = "i3_heart_grey.png",
prev = "i3_next.png^\\[transformFX",
next = "i3_next.png",
arrow = "i3_arrow.png",
trash = "i3_trash.png",
sort_az = "i3_sort_az.png",
sort_za = "i3_sort_za.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",
tab_small = "i3_tab_small.png",
tab_top = "i3_tab.png^\\[transformFY",
furnace_anim = "i3_furnace_anim.png",
bag = "i3_bag.png",
armor = "i3_armor.png",
awards = "i3_award.png",
skins = "i3_skin.png",
waypoints = "i3_waypoint.png",
teleport = "i3_teleport.png",
add = "i3_add.png",
refresh = "i3_refresh.png",
visible = "i3_visible.png^\\[brighten",
nonvisible = "i3_non_visible.png",
exit = "i3_exit.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^\\[colorize:#f00:100",
compress_hover = "i3_compress.png^\\[brighten",
sort_az_hover = "i3_sort_az.png^\\[brighten",
sort_za_hover = "i3_sort_za.png^\\[brighten",
prev_hover = "i3_next_hover.png^\\[transformFX",
next_hover = "i3_next_hover.png",
tab_hover = "i3_tab_hover.png",
tab_small_hover = "i3_tab_small_hover.png",
tab_hover_top = "i3_tab_hover.png^\\[transformFY",
bag_hover = "i3_bag_hover.png",
armor_hover = "i3_armor_hover.png",
awards_hover = "i3_award_hover.png",
skins_hover = "i3_skin_hover.png",
waypoints_hover = "i3_waypoint_hover.png",
teleport_hover = "i3_teleport.png^\\[brighten",
add_hover = "i3_add.png^\\[brighten",
refresh_hover = "i3_refresh.png^\\[brighten",
exit_hover = "i3_exit.png^\\[brighten",
}
local styles = fmt([[
style_type[field;border=false;bgcolor=transparent]
style_type[label,field;font_size=16]
style_type[button;border=false;content_offset=0]
style_type[image_button,item_image_button;border=false;sound=i3_click]
style_type[item_image_button;bgimg_hovered=%s]
style[pagenum,no_item,no_rcp;font=bold;font_size=18]
style[exit;fgimg=%s;fgimg_hovered=%s;content_offset=0]
style[cancel;fgimg=%s;fgimg_hovered=%s;content_offset=0]
style[search;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[waypoint_add;fgimg=%s;fgimg_hovered=%s;content_offset=0]
style[btn_bag,btn_armor,btn_skins;font=bold;font_size=18;content_offset=0;sound=i3_click]
style[craft_rcp,craft_usg;noclip=true;font_size=16;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.exit, PNG.exit_hover,
PNG.cancel, PNG.cancel_hover,
PNG.search, PNG.search_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.add, PNG.add_hover)
local fs_elements = {
label = "label[%f,%f;%s]",
box = "box[%f,%f;%f,%f;%s]",
image = "image[%f,%f;%f,%f;%s]",
tooltip = "tooltip[%f,%f;%f,%f;%s]",
button = "button[%f,%f;%f,%f;%s;%s]",
item_image = "item_image[%f,%f;%f,%f;%s]",
hypertext = "hypertext[%f,%f;%f,%f;%s;%s]",
bg9 = "background9[%f,%f;%f,%f;%s;false;%u]",
scrollbar = "scrollbar[%f,%f;%f,%f;%s;%s;%u]",
model = "model[%f,%f;%f,%f;%s;%s;%s;%s;%s;%s;%s]",
image_button = "image_button[%f,%f;%f,%f;%s;%s;%s]",
animated_image = "animated_image[%f,%f;%f,%f;;%s;%u;%u]",
item_image_button = "item_image_button[%f,%f;%f,%f;%s;%s;%s]",
}
return PNG, styles, fs_elements

598
init.lua
View File

@ -1,12 +1,12 @@
i3 = {}
local modpath = core.get_modpath "i3"
local storage = core.get_mod_storage()
local slz, dslz = core.serialize, core.deserialize
local pdata = dslz(storage:get_string "pdata") or {}
-- Caches
local init_items = {}
local searches = {}
local recipes_cache = {}
local usages_cache = {}
local fuel_cache = {}
@ -15,7 +15,13 @@ local toolrepair
local tabs = {}
local model_aliases = loadfile(modpath .. "/etc/model_aliases.lua")()
local PNG, styles, fs_elements = loadfile(modpath .. "/etc/styles.lua")()
local compress_groups, compressed = loadfile(modpath .. "/etc/compress.lua")()
local group_stereotypes, group_names = loadfile(modpath .. "/etc/groups.lua")()
local progressive_mode = core.settings:get_bool "i3_progressive_mode" and not(core.is_creative_enabled())
local item_compression = core.settings:get_bool "i3_item_compression"
local damage_enabled = core.settings:get_bool "enable_damage"
local __3darmor, __skinsdb, __awards
@ -25,6 +31,9 @@ local __unified_inventory, old_unified_inventory_fn
local http = core.request_http_api()
local singleplayer = core.is_singleplayer()
local after = core.after
local clr = core.colorize
local reg_items = core.registered_items
local reg_nodes = core.registered_nodes
local reg_craftitems = core.registered_craftitems
@ -32,29 +41,9 @@ 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 get_inv = core.get_inventory
local chat_send = core.chat_send_player
local show_formspec = core.show_formspec
local pos_to_string = core.pos_to_string
local check_privs = core.check_player_privs
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 on_leaveplayer = core.register_on_leaveplayer
local on_mods_loaded = core.register_on_mods_loaded
local get_player_info = core.get_player_information
local translate = core.get_translated_string
local create_inventory = core.create_detached_inventory
local on_receive_fields = core.register_on_player_receive_fields
local ESC = core.formspec_escape
local S = core.get_translator "i3"
@ -109,117 +98,6 @@ local SUBCAT = {
"waypoints",
}
local PNG = {
bg = "i3_bg.png",
bg_full = "i3_bg_full.png",
bar = "i3_bar.png",
hotbar = "i3_hotbar.png",
search = "i3_search.png",
heart = "i3_heart.png",
heart_half = "i3_heart_half.png",
heart_grey = "i3_heart_grey.png",
prev = "i3_next.png^\\[transformFX",
next = "i3_next.png",
arrow = "i3_arrow.png",
trash = "i3_trash.png",
sort_az = "i3_sort_az.png",
sort_za = "i3_sort_za.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",
tab_top = "i3_tab.png^\\[transformFY",
furnace_anim = "i3_furnace_anim.png",
bag = "i3_bag.png",
armor = "i3_armor.png",
awards = "i3_award.png",
skins = "i3_skin.png",
waypoints = "i3_waypoint.png",
teleport = "i3_teleport.png",
add = "i3_add.png",
refresh = "i3_refresh.png",
visible = "i3_visible.png^\\[brighten",
nonvisible = "i3_non_visible.png",
exit = "i3_exit.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^\\[colorize:#f00:100",
compress_hover = "i3_compress.png^\\[brighten",
sort_az_hover = "i3_sort_az.png^\\[brighten",
sort_za_hover = "i3_sort_za.png^\\[brighten",
prev_hover = "i3_next_hover.png^\\[transformFX",
next_hover = "i3_next_hover.png",
tab_hover = "i3_tab_hover.png",
tab_hover_top = "i3_tab_hover.png^\\[transformFY",
bag_hover = "i3_bag_hover.png",
armor_hover = "i3_armor_hover.png",
awards_hover = "i3_award_hover.png",
skins_hover = "i3_skin_hover.png",
waypoints_hover = "i3_waypoint_hover.png",
teleport_hover = "i3_teleport.png^\\[brighten",
add_hover = "i3_add.png^\\[brighten",
refresh_hover = "i3_refresh.png^\\[brighten",
exit_hover = "i3_exit.png^\\[brighten",
}
local fs_elements = {
label = "label[%f,%f;%s]",
box = "box[%f,%f;%f,%f;%s]",
image = "image[%f,%f;%f,%f;%s]",
tooltip = "tooltip[%f,%f;%f,%f;%s]",
button = "button[%f,%f;%f,%f;%s;%s]",
item_image = "item_image[%f,%f;%f,%f;%s]",
hypertext = "hypertext[%f,%f;%f,%f;%s;%s]",
bg9 = "background9[%f,%f;%f,%f;%s;false;%u]",
scrollbar = "scrollbar[%f,%f;%f,%f;%s;%s;%u]",
model = "model[%f,%f;%f,%f;%s;%s;%s;%s;%s;%s;%s]",
image_button = "image_button[%f,%f;%f,%f;%s;%s;%s]",
animated_image = "animated_image[%f,%f;%f,%f;;%s;%u;%u]",
item_image_button = "item_image_button[%f,%f;%f,%f;%s;%s;%s]",
}
local styles = sprintf([[
style_type[field;border=false;bgcolor=transparent]
style_type[label,field;font_size=16]
style_type[button;border=false;content_offset=0]
style_type[image_button,item_image_button;border=false;sound=i3_click]
style_type[item_image_button;bgimg_hovered=%s]
style[pagenum,no_item,no_rcp;font=bold;font_size=18]
style[exit;fgimg=%s;fgimg_hovered=%s;content_offset=0]
style[cancel;fgimg=%s;fgimg_hovered=%s;content_offset=0]
style[search;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[waypoint_add;fgimg=%s;fgimg_hovered=%s;content_offset=0]
style[btn_bag,btn_armor,btn_skins;font=bold;font_size=18;content_offset=0;sound=i3_click]
style[craft_rcp,craft_usg;noclip=true;font_size=16;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.exit, PNG.exit_hover,
PNG.cancel, PNG.cancel_hover,
PNG.search, PNG.search_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.add, PNG.add_hover)
local function get_lang_code(info)
return info and info.lang_code
end
@ -233,92 +111,25 @@ local function outdated(name)
PNG.book,
"Your Minetest client is outdated.\nGet the latest version on minetest.net to use i3")
show_formspec(name, "i3", fs)
core.show_formspec(name, "i3", fs)
end
local old_is_creative_enabled = core.is_creative_enabled
function core.is_creative_enabled(name)
if name == "" then
return old_is_creative_enabled(name)
end
return check_privs(name, {creative = true}) or old_is_creative_enabled(name)
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)
return core.log("error", str)
end
local function msg(name, str)
return chat_send(name, sprintf("[i3] %s", str))
return core.chat_send_player(name, sprintf("[i3] %s", str))
end
local function is_num(x)
@ -354,7 +165,7 @@ local function fmt(elem, ...)
end
local function clean_name(item)
if sub(item, 1, 1) == ":" or sub(item, 1, 1) == " " then
if sub(item, 1, 1) == ":" or sub(item, 1, 1) == " " or sub(item, 1, 1) == "_" then
item = sub(item, 2)
end
@ -500,7 +311,7 @@ function i3.register_craft(def)
http.fetch({url = def.url}, function(result)
if result.succeeded then
local t = parse_json(result.data)
local t = core.parse_json(result.data)
if is_table(t) then
return i3.register_craft(t)
end
@ -615,7 +426,7 @@ function i3.set_recipe_filter(name, f)
recipe_filters = {[name] = f}
end
function i3.delete_recipe_filter(name)
function i3.remove_recipe_filter(name)
recipe_filters[name] = nil
end
@ -651,6 +462,14 @@ function i3.get_search_filters()
return search_filters
end
local function compression_active(data)
return item_compression and not next(recipe_filters) and data.filter == ""
end
local function compressible(item, data)
return compression_active(data) and compress_groups[item]
end
local function weird_desc(str)
return not true_str(str) or find(str, "\n") or not find(str, "%u")
end
@ -734,7 +553,7 @@ local function get_filtered_items(player, data)
end
local function get_burntime(item)
return get_craft_result{method = "fuel", items = {item}}.time
return core.get_craft_result{method = "fuel", items = {item}}.time
end
local function cache_fuel(item)
@ -754,19 +573,22 @@ local function show_item(def)
def.description and def.description ~= ""
end
local function reset_compression(data)
data.alt_items = nil
data.expand = ""
end
local function search(data)
reset_compression(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
search_filter = search_filter:trim()
for filter_name, values in gmatch(filter, sub(opt, 6)) do
if search_filters[filter_name] then
values = split(values, ",")
@ -800,7 +622,18 @@ local function search(data)
end
end
else
to_add = find(search_in, filter, 1, true)
local ok = true
for keyword in gmatch(filter, "%S+") do
if not find(search_in, keyword, 1, true) then
ok = nil
break
end
end
if ok then
to_add = true
end
end
if to_add then
@ -809,16 +642,36 @@ local function search(data)
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
data.items = filtered_list
end
local function sort_by_category(data)
reset_compression(data)
local items = data.items_raw
if data.filter ~= "" then
search(data)
items = data.items
end
local new = {}
for i = 1, #items do
local item = items[i]
local to_add = true
if data.current_itab == 2 then
to_add = reg_nodes[item]
elseif data.current_itab == 3 then
to_add = reg_craftitems[item] or reg_tools[item]
end
if to_add then
new[#new + 1] = item
end
end
data.items = filtered_list
data.items = new
end
local function get_item_usages(item, recipe, added)
@ -923,7 +776,7 @@ local function cache_drops(name, drop)
end
local function cache_recipes(item)
local recipes = get_all_recipes(item)
local recipes = core.get_all_craft_recipes(item)
if replacements[item] then
local _recipes = {}
@ -978,15 +831,16 @@ 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 stereotype = group_stereotypes[group]
local def = reg_items[stereotype]
if def and show_item(def) then
if 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
@ -1241,36 +1095,84 @@ local function select_item(player, name, data, _f)
end
end
if not item then
return
elseif sub(item, 1, 1) == "_" then
item = sub(item, 2)
elseif sub(item, 1, 6) == "group|" then
item = match(item, "([%w:_]+)$")
if not item then return end
if compressible(item, data) then
local idx
for i = 1, #data.items do
local it = data.items[i]
if it == item then
idx = i
break
end
end
if data.expand ~= "" then
data.alt_items = nil
if item == data.expand then
data.expand = nil
return
end
end
if idx and item ~= data.expand then
data.alt_items = copy(data.items)
data.expand = item
if compress_groups[item] then
local items = copy(compress_groups[item])
insert(items, fmt("_%s", item))
sort(items, function(a, b)
if a:sub(1, 1) == "_" then
a = a:sub(2)
end
return a < b
end)
local i = 1
for _, v in ipairs(items) do
if show_item(reg_items[clean_name(v)]) then
insert(data.alt_items, idx + i, v)
i = i + 1
end
end
end
end
else
if 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 not reg_items[item] then return end
if core.is_creative_enabled(name) then
local stack = ItemStack(item)
local stackmax = stack:get_stack_max()
stack = fmt("%s %s", item, stackmax)
return get_stack(player, stack, clr("#ff0", fmt("%u x %s", stackmax, get_desc(item))))
end
if item == data.query_item then return end
local recipes, usages = get_recipes(player, item)
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
item = reg_aliases[item] or item
if not reg_items[item] then return end
if core.is_creative_enabled(name) then
local stack = ItemStack(item)
local stackmax = stack:get_stack_max()
stack = fmt("%s %s", item, stackmax)
return get_stack(player, stack, clr("#ff0", fmt("%u x %s", stackmax, get_desc(item))))
end
if item == data.query_item then return end
local recipes, usages = get_recipes(player, item)
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)
@ -1421,7 +1323,11 @@ local function get_output_fs(fs, data, rcp, is_recipe, shapeless, right, btn_siz
fs(fmt("list[detached:i3_output_%s;main;%f,%f;1,1;]", rcp_usg, X + 0.11, Y))
fs("button", X + 0.11, Y, ITEM_BTN_SIZE, ITEM_BTN_SIZE, _name, "")
local inv = get_inv {type = "detached", name = fmt("i3_output_%s", rcp_usg)}
local inv = core.get_inventory {
type = "detached",
name = fmt("i3_output_%s", rcp_usg)
}
inv:set_stack("main", 1, item)
pos = {x = X + 0.11, y = Y}
else
@ -1708,7 +1614,7 @@ local function get_header(fs, data)
fs("style_type[label;font=normal;font_size=16]")
local def = reg_items[data.query_item]
local model_alias = i3.model_alias[data.query_item]
local model_alias = model_aliases[data.query_item]
if def.drawtype == "mesh" or model_alias then
get_model_fs(fs, data, def, model_alias)
@ -1788,9 +1694,22 @@ local function get_rcp_extra(player, fs, data, panel, is_recipe, is_usage)
fs("container_end[]")
end
local function get_items_fs(fs, data, extend)
local rows = 8
local lines = extend and 12 or 9
local function get_items_fs(fs, data, full_height)
if compression_active(data) then
local new = {}
for i = 1, #data.items do
local item = data.items[i]
if not compressed[item] then
new[#new + 1] = item
end
end
data.items = new
end
local items = data.alt_items or data.items
local rows, lines = 8, 12
local ipp = rows * lines
local size = 0.85
@ -1799,17 +1718,17 @@ local function get_items_fs(fs, data, extend)
fmt("field[%f,0.2;2.95,0.6;filter;;%s]", data.inv_width + 0.35, ESC(data.filter)),
"field_close_on_enter[filter;false]")
fs("image_button", data.inv_width + 3.35, 0.35, 0.3, 0.3, "", "cancel", "")
fs("image_button", data.inv_width + 3.35, 0.35, 0.3, 0.3, "", "cancel", "")
fs("image_button", data.inv_width + 3.85, 0.32, 0.35, 0.35, "", "search", "")
fs("image_button", data.inv_width + 5.27, 0.3, 0.35, 0.35, "", "prev_page", "")
fs("image_button", data.inv_width + 7.45, 0.3, 0.35, 0.35, "", "next_page", "")
fs("image_button", data.inv_width + 5.27, 0.3, 0.35, 0.35, "", "prev_page", "")
fs("image_button", data.inv_width + 7.45, 0.3, 0.35, 0.35, "", "next_page", "")
data.pagemax = max(1, ceil(#data.items / ipp))
data.pagemax = max(1, ceil(#items / ipp))
fs("button", data.inv_width + 5.6, 0.14, 1.88, 0.7, "pagenum",
fmt("%s / %u", clr("#ff0", data.pagenum), data.pagemax))
if #data.items == 0 then
if #items == 0 then
local lbl = ES"No item to show"
if next(recipe_filters) and #init_items > 0 and data.filter == "" then
@ -1817,21 +1736,49 @@ local function get_items_fs(fs, data, extend)
end
fs("button", data.inv_width + 0.1, 3, 8, 1, "no_item", lbl)
else
local first_item = (data.pagenum - 1) * ipp
for i = first_item, first_item + ipp - 1 do
local item = items[i + 1]
if not item then break end
local _compressed = item:sub(1, 1) == "_"
local name = _compressed and item:sub(2) or item
local X = i % rows
X = X - (X * 0.045) + data.inv_width + 0.28
local Y = round((i % ipp - X) / rows + 1, 0)
Y = Y - (Y * 0.085) + 0.95
fs[#fs + 1] = fmt("item_image_button", X, Y, size, size, name, item, "")
if compressible(item, data) then
local expand = data.expand == name
fs(fmt("tooltip[%s;%s]", item, expand and ES"Click to hide" or ES"Click to expand"))
fs("style_type[label;font=bold;font_size=20]")
fs("label", X + 0.65, Y + 0.7, expand and "-" or "+")
fs("style_type[label;font=normal;font_size=16]")
end
end
end
local first_item = (data.pagenum - 1) * ipp
local _tabs = {"All", "Nodes", "Items"}
local tab_len, tab_hgh = 1.8, 0.5
for i = first_item, first_item + ipp - 1 do
local item = data.items[i + 1]
if not item then break end
for i, title in ipairs(_tabs) do
local selected = i == data.current_itab
local X = i % rows
X = X - (X * 0.045) + data.inv_width + 0.28
fs(fmt([[style_type[image_button;fgimg=%s;fgimg_hovered=%s;noclip=true;
font_size=16;textcolor=%s;content_offset=0;sound=i3_tab] ]],
selected and PNG.tab_small_hover or PNG.tab_small,
PNG.tab_small_hover, selected and "#fff" or "#ddd"))
local Y = round((i % ipp - X) / rows + 1, 0)
Y = Y - (Y * (extend and 0.085 or 0.035)) + 0.95
fs[#fs + 1] = fmt("item_image_button", X, Y, size, size, item, item, "")
fs("style_type[image_button:hovered;textcolor=#fff]")
fs("image_button", (data.inv_width - 0.65) + (i * (tab_len + 0.1)),
full_height, tab_len, tab_hgh, "", fmt("itab_%u", i), title)
end
end
@ -1854,21 +1801,15 @@ end
local function get_panels(player, data, fs, full_height)
local _title = {name = "title", height = 1.4}
local _favs = {name = "favs", height = 2.23}
local _items = {name = "items", height = 9.69}
local _items = {name = "items", height = full_height}
local _recipes = {name = "recipes", rcp = data.recipes, height = 4.045}
local _usages = {name = "usages", rcp = data.usages, height = 4.045}
local panels, extend
local panels
if data.query_item then
panels = {_title, _recipes, _usages, _favs}
else
panels = {_items, _favs}
if #data.favs == 0 then
extend = true
remove(panels, 2)
_items.height = full_height
end
panels = {_items}
end
for idx = 1, #panels do
@ -1888,7 +1829,7 @@ local function get_panels(player, data, fs, full_height)
if is_recipe or is_usage then
get_rcp_extra(player, fs, data, panel, is_recipe, is_usage)
elseif panel.name == "items" then
get_items_fs(fs, data, extend)
get_items_fs(fs, data, full_height)
elseif panel.name == "title" then
get_header(fs, data)
elseif panel.name == "favs" then
@ -2008,7 +1949,7 @@ local function get_waypoint_fs(fs, data, player, yextra, ctn_len)
fs("tooltip", 0, y, ctn_len - 2.5, 0.65,
fmt("Name: %s\nPosition:%s", clr("#ff0", v.name),
pos_to_string(v.pos, 0):sub(2,-2):gsub("(%-*%d+)", clr("#ff0", " %1"))))
core.pos_to_string(v.pos, 0):sub(2,-2):gsub("(%-*%d+)", clr("#ff0", " %1"))))
local del = fmt("waypoint_%u_delete", i)
fs(fmt("style[%s;fgimg=%s;fgimg_hovered=%s;content_offset=0]", del, PNG.trash, PNG.trash_hover))
@ -2287,9 +2228,9 @@ function i3.get_tabs()
return tabs
end
function i3.delete_tab(tabname)
function i3.remove_tab(tabname)
if not true_str(tabname) then
return err "i3.delete_tab: tab name missing"
return err "i3.remove_tab: tab name missing"
end
for i, def in ipairs(tabs) do
@ -2356,15 +2297,18 @@ local function init_data(player, info)
data.favs = {}
data.export_counts = {}
data.current_tab = 1
data.current_itab = 1
data.subcat = 1
data.scrbar_inv = 0
data.lang_code = get_lang_code(info)
data.fs_version = info.formspec_version
after(0, set_fs, player)
end
local function reset_data(data)
data.filter = ""
data.expand = ""
data.pagenum = 1
data.rnum = 1
data.unum = 1
@ -2375,7 +2319,12 @@ local function reset_data(data)
data.usages = nil
data.export_rcp = nil
data.export_usg = nil
data.alt_items = nil
data.items = data.items_raw
if data.current_itab > 1 then
sort_by_category(data)
end
end
local function rcp_fields(player, data, fields)
@ -2402,6 +2351,10 @@ local function rcp_fields(player, data, fields)
search(data)
if data.current_itab > 1 then
sort_by_category(data)
end
elseif fields.prev_page or fields.next_page then
if data.pagemax == 1 then return end
data.pagenum = data.pagenum - (fields.prev_page and 1 or -1)
@ -2515,9 +2468,9 @@ local function get_inventory_fs(player, data, fs)
local textures = concat(t, ","):gsub("!", ",")
--fs("style[player_model;bgcolor=black]")
fs("model", 0.2, 0.2, armor_skin and 4 or 3.4, armor_skin and ctn_hgt or 6.1,
fs("model", 0.2, 0.2, armor_skin and 4 or 3.4, ctn_hgt,
"player_model", props.mesh, textures, "0,-150", "false", "false",
fmt("%u,%u", anim.x, anim.y))
fmt("%u,%u%s", anim.x, anim.y, data.fs_version >= 5 and ";30" or ""))
else
local size = 2.5
fs("image", 0.7, 0.2, size, size * props.visual_size.y, props.textures[1])
@ -2565,9 +2518,7 @@ local function get_inventory_fs(player, data, fs)
(max_val * 4) / 12, max_val, 9.8, ctn_hgt, data.scrbar_inv))
fs(fmt("scroll_container[3.9,0.2;%f,%f;scrbar_inv;vertical]", ctn_len, ctn_hgt))
get_ctn_content(fs, data, player, yoffset, ctn_len, award_list, awards_unlocked, award_list_nb)
get_ctn_content(fs, data, player, yoffset, ctn_len, award_list, awards_unlocked, award_list_nb)
fs("scroll_container_end[]")
local btn = {
@ -2812,18 +2763,6 @@ i3.add_search_filter("groups", function(item, groups)
return has_groups
end)
i3.add_search_filter("types", function(item, drawtypes)
local t = {}
for i, dt in ipairs(drawtypes) do
t[i] = (dt == "node" and reg_nodes[item] and 1) or
(dt == "item" and reg_craftitems[item] and 1) or
(dt == "tool" and reg_tools[item] and 1) or nil
end
return #t > 0
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.
@ -2943,14 +2882,14 @@ local function get_init_items()
usages = usages_cache,
}
http.fetch_async{
http.fetch_async {
url = i3.export_url,
post_data = write_json(post_data),
post_data = core.write_json(post_data),
}
end
end
on_mods_loaded(function()
core.register_on_mods_loaded(function()
get_init_items()
__sfinv = rawget(_G, "sfinv")
@ -2974,7 +2913,7 @@ local function init_backpack(player)
local data = pdata[name]
local inv = player:get_inventory()
inv:set_size("main", INV_SIZE)
inv:set_size("main", data.bag_size and BAG_SIZES[data.bag_size] or INV_SIZE)
data.bag = create_inventory(fmt("%s_backpack", name), {
allow_put = function(_inv, listname, _, stack)
@ -3015,7 +2954,6 @@ local function init_backpack(player)
if data.bag_size then
data.bag:set_stack("main", 1, fmt("i3:bag_%s", data.bag_size))
inv:set_size("main", BAG_SIZES[data.bag_size])
end
end
@ -3040,11 +2978,11 @@ local function init_waypoints(player)
end
end
on_joinplayer(function(player)
core.register_on_joinplayer(function(player)
local name = player:get_player_name()
local info = get_player_info(name)
local info = core.get_player_information and core.get_player_information(name)
if get_formspec_version(info) < MIN_FORMSPEC_VERSION then
if not info or get_formspec_version(info) < MIN_FORMSPEC_VERSION then
if __sfinv then
sfinv.set_player_inventory_formspec = old_sfinv_fn
sfinv.enabled = true
@ -3058,6 +2996,8 @@ on_joinplayer(function(player)
end
end
pdata[name] = nil
return outdated(name)
end
@ -3111,12 +3051,12 @@ local function save_data(player_name)
storage:set_string("pdata", slz(_pdata))
end
on_leaveplayer(function(player)
core.register_on_leaveplayer(function(player)
local name = player:get_player_name()
save_data(name)
end)
on_shutdown(save_data)
core.register_on_shutdown(save_data)
local function routine()
save_data()
@ -3125,7 +3065,7 @@ end
after(SAVE_INTERVAL, routine)
on_receive_fields(function(player, formname, fields)
core.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "" then
return false
end
@ -3139,6 +3079,10 @@ on_receive_fields(function(player, formname, fields)
local tabname = sub(f, 5)
set_tab(player, tabname)
break
elseif sub(f, 1, 5) == "itab_" then
data.pagenum = 1
data.current_itab = tonum(f:sub(-1))
sort_by_category(data)
end
end
@ -3170,6 +3114,7 @@ if progressive_mode then
if is_group(item) then
local groups = extract_groups(item)
for i = 1, inv_items_size do
local def = reg_items[inv_items[i]]
@ -3236,6 +3181,7 @@ if progressive_mode then
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
@ -3326,7 +3272,8 @@ if progressive_mode then
-- 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()
local players = core.get_connected_players()
for i = 1, #players do
local player = players[i]
local name = player:get_player_name()
@ -3346,6 +3293,8 @@ if progressive_mode then
end
data.items_raw = items
data.current_itab = 1
search(data)
set_fs(player)
end
@ -3356,8 +3305,9 @@ if progressive_mode then
poll_new_items()
globalstep(function()
local players = get_players()
core.register_globalstep(function()
local players = core.get_connected_players()
for i = 1, #players do
local player = players[i]
local name = player:get_player_name()
@ -3371,7 +3321,7 @@ if progressive_mode then
i3.add_recipe_filter("Default progressive filter", progressive_filter)
on_joinplayer(function(player)
core.register_on_joinplayer(function(player)
local name = player:get_player_name()
local data = pdata[name]
@ -3417,5 +3367,5 @@ for size, rcp in pairs(bag_recipes) do
core.register_craft {type = "fuel", recipe = bagname, burntime = 3}
end
--dofile(core.get_modpath("i3") .. "/test_tabs.lua")
--dofile(core.get_modpath("i3") .. "/test_custom_recipes.lua")
--dofile(modpath .. "/tests/test_tabs.lua")
--dofile(modpath .. "/tests/test_custom_recipes.lua")

View File

@ -1,2 +1,5 @@
# 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
# Regroup the items of the same type in the item list.
i3_item_compression (Regroup items of the same type) bool true

BIN
textures/i3_tab_small.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB