1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
local craftguide, datas = {}, {}
function craftguide:get_recipe(item)
if item:sub(1,6) == "group:" then
if item:sub(-4) == "wool" or item:sub(-3) == "dye" then
item = item:sub(7)..":white"
elseif minetest.registered_items["default:"..item:sub(7)] then
item = item:gsub("group:", "default:")
else for node, def in pairs(minetest.registered_items) do
if def.groups[item:match("[^,:]+$")] then item = node end
end
end
end
return item
end
function craftguide:get_formspec(stack, pagenum, item, recipe_num, filter, player_name)
local inv_size = datas[player_name].size
local npp, i, s = 8*3, 0, 0
local pagemax = math.floor((inv_size - 1) / npp + 1)
if pagenum > pagemax then pagenum = 1
elseif pagenum == 0 then pagenum = pagemax end
local formspec = [[ size[8,6.6;]
tablecolumns[color;text;color;text]
tableoptions[background=#00000000;highlight=#00000000;border=false]
button[5.4,0;0.8,0.95;prev;<]
button[7.2,0;0.8,0.95;next;>]
button[2.5,0.2;0.8,0.5;search;?]
button[3.2,0.2;0.8,0.5;clear;X]
tooltip[search;Search]
tooltip[clear;Reset] ]]
.."table[6,0.18;1.1,0.5;pagenum;#FFFF00,"..tostring(pagenum)..
",#FFFFFF,/ "..tostring(pagemax).."]"..
"field[0.3,0.32;2.6,1;filter;;"..filter.."]"..
default.gui_bg..default.gui_bg_img
for _, name in pairs(self:get_items(filter, player_name)) do
if s < (pagenum - 1) * npp then
s = s + 1
else if i >= npp then break end
formspec = formspec.."item_image_button["..(i%8)..","..
(math.floor(i/8)+1)..";1,1;"..name..";"..name..";]"
i = i + 1
end
end
if item and minetest.registered_items[item] then
--print(dump(minetest.get_all_craft_recipes(item)))
local items_num = #minetest.get_all_craft_recipes(item)
if recipe_num > items_num then recipe_num = 1 end
if items_num > 1 then formspec = formspec..
"button[0,6;1.6,1;alternate;Alternate]"..
"label[0,5.5;Recipe "..recipe_num.." of "..items_num.."]"
end
local type = minetest.get_all_craft_recipes(item)[recipe_num].type
if type == "cooking" then formspec = formspec..
"image[3.75,4.6;0.5,0.5;default_furnace_fire_fg.png]"
end
local items = minetest.get_all_craft_recipes(item)[recipe_num].items
local width = minetest.get_all_craft_recipes(item)[recipe_num].width
if width == 0 then width = math.min(3, #items) end
-- Lua 5.3 removed `table.maxn`, use `xdecor.maxn` in case of breakage.
local rows = math.ceil(table.maxn(items) / width)
local function is_group(item)
if item:sub(1,6) == "group:" then return "\nG" end
return ""
end
for i, v in pairs(items) do formspec = formspec..
"item_image_button["..((i-1) % width + 4.5)..","..
(math.floor((i-1) / width + (6 - math.min(2, rows))))..";1,1;"..
self:get_recipe(v)..";"..self:get_recipe(v)..";"..is_group(v).."]"
end
local output = minetest.get_all_craft_recipes(item)[recipe_num].output
formspec = formspec.."item_image_button[2.5,5;1,1;"..output..";"..item..";]"..
"image[3.5,5;1,1;gui_furnace_arrow_bg.png^[transformR90]"
end
stack:set_metadata(formspec)
datas[player_name].formspec = stack:get_metadata()
minetest.show_formspec(player_name, "xdecor:crafting_guide", formspec)
end
function craftguide:get_items(filter, player_name)
local items_list = {}
for name, def in pairs(minetest.registered_items) do
if not (def.groups.not_in_creative_inventory == 1) and
minetest.get_craft_recipe(name).items and
def.description and def.description ~= "" and
(not filter or def.name:find(filter, 1, true) or
def.description:lower():find(filter, 1, true)) then
items_list[#items_list+1] = name
end
end
datas[player_name].size = #items_list
table.sort(items_list)
return items_list
end
minetest.register_on_player_receive_fields(function(player, listname, fields)
if listname ~= "xdecor:crafting_guide" then return end
local player_name = player:get_player_name()
local stack = player:get_wielded_item()
local formspec = datas[player_name].formspec
local filter = formspec:match("filter;;([%w_:]+)") or ""
local pagenum = tonumber(formspec:match("#FFFF00,(%d+)")) or 1
if fields.clear then
craftguide:get_items(nil, player_name)
craftguide:get_formspec(stack, 1, nil, 1, "", player_name)
elseif fields.alternate then
local item = formspec:match("item_image_button%[.*;([%w_:]+);.*%]") or 1
local recipe_num = tonumber(formspec:match("Recipe%s(%d+)")) or 1
recipe_num = recipe_num + 1
craftguide:get_formspec(stack, pagenum, item, recipe_num, filter, player_name)
elseif fields.search then
craftguide:get_items(fields.filter:lower(), player_name)
craftguide:get_formspec(stack, 1, nil, 1, fields.filter:lower(), player_name)
elseif fields.prev or fields.next then
if fields.prev then pagenum = pagenum - 1
else pagenum = pagenum + 1 end
craftguide:get_formspec(stack, pagenum, nil, 1, filter, player_name)
else for item in pairs(fields) do
if minetest.get_craft_recipe(item).items then
craftguide:get_formspec(stack, pagenum, item, 1, filter, player_name)
end
end
end
end)
minetest.register_craftitem(":xdecor:crafting_guide", {
description = "Crafting Guide",
inventory_image = "crafting_guide.png",
wield_image = "crafting_guide.png",
stack_max = 1,
on_use = function(itemstack, user)
local player_name = user:get_player_name()
datas[player_name] = {}
craftguide:get_items(nil, player_name)
craftguide:get_formspec(itemstack, 1, nil, 1, "", player_name)
end
})
minetest.register_craft({
output = "xdecor:crafting_guide",
type = "shapeless",
recipe = {"default:book", "dye:blue"}
})
|