mirror of https://github.com/minetest-mods/i3.git
Progresive mod conflict resolved
This commit is contained in:
commit
a40fef7666
21
API.md
21
API.md
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
598
init.lua
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 5.6 KiB |
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
Loading…
Reference in New Issue