A bunch of improvements

*Updated UI to match latest minetest-game
*An extra row of items, so less pages
*Option to filter items, so no more scrolling through 100 pages
*Option to show item strings ("default:glass") as tooltips
*Option to show all items, not just craftable items
*Show number of items output by craft (with itemstrings only for now)
*Probably some other things I forgot
This commit is contained in:
Ciaran Gultnieks 2014-11-19 20:59:09 +00:00
parent 6b9c00c838
commit ec79a38dab

View File

@ -6,106 +6,121 @@ zcg = {}
zcg.users = {} zcg.users = {}
zcg.crafts = {} zcg.crafts = {}
zcg.itemlist = {}
-- List of all items that can be crafted
zcg.craftableitems = {}
-- List of all items
zcg.allitems = {}
zcg.items_in_group = function(group) zcg.items_in_group = function(group)
local items = {} local items = {}
local ok = true local ok = true
for name, item in pairs(minetest.registered_items) do for name, item in pairs(minetest.registered_items) do
-- the node should be in all groups -- the node should be in all groups
ok = true ok = true
for _, g in ipairs(group:split(',')) do for _, g in ipairs(group:split(',')) do
if not item.groups[g] then if not item.groups[g] then
ok = false ok = false
end end
end end
if ok then table.insert(items,name) end if ok then table.insert(items,name) end
end end
return items return items
end end
local table_copy = function(table) local table_copy = function(table)
out = {} out = {}
for k,v in pairs(table) do for k,v in pairs(table) do
out[k] = v out[k] = v
end end
return out return out
end end
zcg.add_craft = function(input, output, groups) zcg.add_craft = function(input, output, groups)
if minetest.get_item_group(output, "not_in_craft_guide") > 0 then if minetest.get_item_group(output, "not_in_craft_guide") > 0 then
return return
end end
if not groups then groups = {} end if not input.items then return end
local c = {} if not groups then groups = {} end
c.width = input.width local c = {}
c.type = input.type c.width = input.width
c.items = input.items if c.width == 0 then c.width=3 end
if c.items == nil then return end c.type = input.type
for i, item in pairs(c.items) do c.items = input.items
if item:sub(0,6) == "group:" then c.makes, _ = input.output:match("%S+ (%d+)") or 1
local groupname = item:sub(7)
if groups[groupname] ~= nil then for i, item in pairs(c.items) do
c.items[i] = groups[groupname] if item:sub(1,6) == "group:" then
else local groupname = item:sub(7)
for _, gi in ipairs(zcg.items_in_group(groupname)) do if groups[groupname] then
local g2 = groups c.items[i] = groups[groupname]
g2[groupname] = gi else
zcg.add_craft({ for _, gi in ipairs(zcg.items_in_group(groupname)) do
width = c.width, local g2 = table_copy(groups)
type = c.type, g2[groupname] = gi
items = table_copy(c.items) zcg.add_craft({
}, output, g2) -- it is needed to copy the table, else groups won't work right width = c.width,
end type = c.type,
return items = table_copy(c.items),
end output = input.output
end }, output, g2)
end end
if c.width == 0 then c.width = 3 end return
table.insert(zcg.crafts[output],c) end
end
end
table.insert(zcg.crafts[output], c)
end end
zcg.load_crafts = function(name) zcg.load_crafts = function(name)
zcg.crafts[name] = {} zcg.crafts[name] = {}
local _recipes = minetest.get_all_craft_recipes(name) local recipes = minetest.get_all_craft_recipes(name)
if _recipes then if recipes then
for i, recipe in ipairs(_recipes) do for i, recipe in ipairs(recipes) do
if (recipe and recipe.items and recipe.type) then if (recipe and recipe.items and recipe.type) then
zcg.add_craft(recipe, name) zcg.add_craft(recipe, name)
end end
end end
end end
if zcg.crafts[name] == nil or #zcg.crafts[name] == 0 then if #zcg.crafts[name] == 0 then
zcg.crafts[name] = nil zcg.crafts[name] = nil
else else
table.insert(zcg.itemlist,name) table.insert(zcg.craftableitems,name)
end end
end end
zcg.need_load_all = true zcg.need_load_all = true
zcg.load_all = function() zcg.load_all = function()
print("Loading all crafts, this may take some time...") print("Loading all crafts, this may take some time...")
local i = 0 for name, item in pairs(minetest.registered_items) do
for name, item in pairs(minetest.registered_items) do if name and name ~= "" and
if (name and name ~= "") then name ~= "unknown" and
zcg.load_crafts(name) name ~= "air" and
end name ~= "ignore" then
i = i+1 table.insert(zcg.allitems, name)
end zcg.load_crafts(name)
table.sort(zcg.itemlist) end
zcg.need_load_all = false end
print("All crafts loaded !") table.sort(zcg.craftableitems)
table.sort(zcg.allitems)
zcg.need_load_all = false
minetest.log("info", "ZCG:items - "..minetest.write_json(zcg.allitems))
minetest.log("info", "ZCG:crafts - "..minetest.write_json(zcg.crafts))
print("All crafts loaded !")
end end
minetest.register_chatcommand("search_items", { minetest.register_chatcommand("search_items", {
params = "<text>", params = "<text>",
description = "search all craft items", description = "search all items",
privs = {}, privs = {},
func = function(name, param) func = function(name, param)
if zcg.need_load_all then zcg.load_all() end if zcg.need_load_all then zcg.load_all() end
local found = false local found = false
for _, itemname in ipairs(zcg.itemlist) do for _, itemname in ipairs(zcg.allitems) do
if itemname:find(param, 1, true) then if itemname:find(param, 1, true) then
minetest.chat_send_player(name, itemname) minetest.chat_send_player(name, itemname)
found = true found = true
@ -118,111 +133,195 @@ minetest.register_chatcommand("search_items", {
}) })
zcg.formspec = function(pn) zcg.formspec = function(pn)
if zcg.need_load_all then zcg.load_all() end
page = zcg.users[pn].page if zcg.need_load_all then zcg.load_all() end
alt = zcg.users[pn].alt
current_item = zcg.users[pn].current_item -- Read a few things for easier access...
local formspec = "size[8,7.5]" local page = zcg.users[pn].page
.. "button[0,0;2,.5;main;Back]" local alt = zcg.users[pn].alt
if zcg.users[pn].history.index > 1 then local current_item = zcg.users[pn].current_item
formspec = formspec .. "image_button[0,1;1,1;zcg_previous.png;zcg_previous;;false;false;zcg_previous_press.png]" local filter = zcg.users[pn].filter
else local itemstrings = zcg.users[pn].itemstrings
formspec = formspec .. "image[0,1;1,1;zcg_previous_inactive.png]"
end local formspec = "size[8,8.5]"
if zcg.users[pn].history.index < #zcg.users[pn].history.list then .. "bgcolor[#080808BB;true]"
formspec = formspec .. "image_button[1,1;1,1;zcg_next.png;zcg_next;;false;false;zcg_next_press.png]" .. "background[5,5;1,1;gui_formbg.png;true]"
else .. "listcolors[#00000069;#5A5A5A;#141318;#30434C;#FFF]"
formspec = formspec .. "image[1,1;1,1;zcg_next_inactive.png]" .. "button[0,0;2,.5;main;Back]"
end
-- Show craft recipe if zcg.users[pn].settings then
if current_item ~= "" then formspec = formspec .. "field[0.5,1.5;4,1;filter;Filter;"..filter.."]"
if zcg.crafts[current_item] then local sel = "false"
if alt > #zcg.crafts[current_item] then sel = zcg.users[pn].allitems and "true" or "false"
alt = #zcg.crafts[current_item] formspec = formspec .. "checkbox[0,2.5;zcg_allitems;All items;"..sel.."]"
end sel = zcg.users[pn].itemstrings and "true" or "false"
if alt > 1 then formspec = formspec .. "checkbox[0,3.5;zcg_itemstrings;Item strings;"..sel.."]"
formspec = formspec .. "button[7,0;1,1;zcg_alt:"..(alt-1)..";^]" formspec = formspec .. "button[6,7.85;2,1;zcg_update_settings;Update]"
end return formspec
if alt < #zcg.crafts[current_item] then end
formspec = formspec .. "button[7,2;1,1;zcg_alt:"..(alt+1)..";v]"
end -- Get the filtered and correct list of items...
local c = zcg.crafts[current_item][alt] local items
if c then local list = zcg.users[pn].allitems and zcg.allitems or zcg.craftableitems
local x = 3 if filter == "" then
local y = 0 items = list
for i, item in pairs(c.items) do else
formspec = formspec .. "item_image_button["..((i-1)%c.width+x)..","..(math.floor((i-1)/c.width+y))..";1,1;"..item..";zcg:"..item..";]" items = {}
end for _, item in ipairs(list) do
if c.type == "normal" or c.type == "cooking" then if item:find(filter, 1, true) then
formspec = formspec .. "image[6,2;1,1;zcg_method_"..c.type..".png]" table.insert(items, item)
else -- we don't have an image for other types of crafting end
formspec = formspec .. "label[0,2;Method: "..c.type.."]" end
end end
formspec = formspec .. "image[6,1;1,1;zcg_craft_arrow.png]"
formspec = formspec .. "item_image_button[7,1;1,1;"..zcg.users[pn].current_item..";;]" if zcg.users[pn].history.index > 1 then
end formspec = formspec .. "image_button[0,1;1,1;zcg_previous.png;zcg_previous;;false;false;zcg_previous_press.png]"
end else
end formspec = formspec .. "image[0,1;1,1;zcg_previous_inactive.png]"
end
-- Node list if zcg.users[pn].history.index < #zcg.users[pn].history.list then
local npp = 8*3 -- nodes per page formspec = formspec .. "image_button[1,1;1,1;zcg_next.png;zcg_next;;false;false;zcg_next_press.png]"
local i = 0 -- for positionning buttons else
local s = 0 -- for skipping pages formspec = formspec .. "image[1,1;1,1;zcg_next_inactive.png]"
for _, name in ipairs(zcg.itemlist) do end
if s < page*npp then s = s+1 else -- Show craft recipe
if i >= npp then break end if current_item ~= "" then
formspec = formspec .. "item_image_button["..(i%8)..","..(math.floor(i/8)+3.5)..";1,1;"..name..";zcg:"..name..";]" if zcg.crafts[current_item] then
i = i+1 if alt > #zcg.crafts[current_item] then
end alt = #zcg.crafts[current_item]
end end
if page > 0 then if alt > 1 then
formspec = formspec .. "button[0,7;1,.5;zcg_page:"..(page-1)..";<<]" formspec = formspec .. "button[7,0;1,1;zcg_alt:"..(alt-1)..";^]"
end end
if i >= npp then if alt < #zcg.crafts[current_item] then
formspec = formspec .. "button[1,7;1,.5;zcg_page:"..(page+1)..";>>]" formspec = formspec .. "button[7,2;1,1;zcg_alt:"..(alt+1)..";v]"
end end
formspec = formspec .. "label[2,6.85;Page "..(page+1).."/"..(math.floor(#zcg.itemlist/npp+1)).."]" -- The Y is approximatively the good one to have it centered vertically... local c = zcg.crafts[current_item][alt]
return formspec if c then
local x = 3
local y = 0
for i, item in pairs(c.items) do
formspec = formspec .. "item_image_button["..((i-1)%c.width+x)..","..(math.floor((i-1)/c.width+y))..";1,1;"..item..";zcg:"..item..";]"
if itemstrings then
formspec = formspec .. "tooltip[zcg:"..item..";"..item.."]"
end
end
if c.type == "normal" or c.type == "cooking" then
formspec = formspec .. "image[6,2;1,1;zcg_method_"..c.type..".png]"
else -- we don't have an image for other types of crafting
formspec = formspec .. "label[0,2;Method: "..c.type.."]"
end
formspec = formspec .. "image[6,1;1,1;zcg_craft_arrow.png]"
local itemstr = zcg.users[pn].current_item.." "..c.makes
formspec = formspec .. "item_image_button[7,1;1,1;"..
itemstr..";output:"..itemstr..";]"
if itemstrings then
formspec = formspec .. "tooltip[output:"..itemstr..
";"..itemstr.."]"
end
-- if c.makes ~= 1 then
-- formspec = formspec .. "label[7,2;"..c.makes.."]"
-- end
end
end
end
-- Node list
local npp = 8*4 -- nodes per page
local i = 0 -- for positioning buttons
local s = 0 -- for skipping pages
for _, name in ipairs(items) do
if s < page*npp then s = s+1 else
if i >= npp then break end
formspec = formspec .. "item_image_button["..(i%8)..","..(math.floor(i/8)+3.5)..";1,1;"..name..";zcg:"..name..";]"
if itemstrings then
formspec = formspec .. "tooltip[zcg:"..name..";"..name.."]"
end
i = i+1
end
end
if page > 0 then
formspec = formspec .. "button[0,8;1,.5;zcg_page:"..(page-1)..";<<]"
end
if i >= npp then
formspec = formspec .. "button[1,8;1,.5;zcg_page:"..(page+1)..";>>]"
end
local label = (page+1).."/"..(math.floor(#items/npp+1))
if filter ~= "" then
label = label .. " (filter='"..filter.."')"
end
formspec = formspec .. "label[2,7.85;Page "..label.."]"
formspec = formspec .. "button[6,7.85;2,1;zcg_settings;Settings]"
return formspec
end end
minetest.register_on_joinplayer(function(player) minetest.register_on_joinplayer(function(player)
inventory_plus.register_button(player,"zcg","Craft guide") inventory_plus.register_button(player,"zcg","Craft guide")
end) end)
minetest.register_on_player_receive_fields(function(player,formname,fields) minetest.register_on_player_receive_fields(function(player,formname,fields)
pn = player:get_player_name(); minetest.log("info", "ZCG:"..dump(fields))
if zcg.users[pn] == nil then zcg.users[pn] = {current_item = "", alt = 1, page = 0, history={index=0,list={}}} end pn = player:get_player_name();
if fields.zcg then
inventory_plus.set_inventory_formspec(player, zcg.formspec(pn)) -- Initialise all settings for a player when they're first seen...
return if not zcg.users[pn] then
elseif fields.zcg_previous then zcg.users[pn] = {current_item = "",
if zcg.users[pn].history.index > 1 then alt = 1,
zcg.users[pn].history.index = zcg.users[pn].history.index - 1 page = 0,
zcg.users[pn].current_item = zcg.users[pn].history.list[zcg.users[pn].history.index] history={index=0,list={}},
inventory_plus.set_inventory_formspec(player,zcg.formspec(pn)) filter="",
end settings=false,
elseif fields.zcg_next then allitems=false,
if zcg.users[pn].history.index < #zcg.users[pn].history.list then itemstrings=false}
zcg.users[pn].history.index = zcg.users[pn].history.index + 1 end
zcg.users[pn].current_item = zcg.users[pn].history.list[zcg.users[pn].history.index]
inventory_plus.set_inventory_formspec(player,zcg.formspec(pn)) if fields.zcg then
end inventory_plus.set_inventory_formspec(player, zcg.formspec(pn))
end return
for k, v in pairs(fields) do elseif fields.zcg_settings then
if (k:sub(0,4)=="zcg:") then zcg.users[pn].settings = true
local ni = k:sub(5) inventory_plus.set_inventory_formspec(player, zcg.formspec(pn))
if zcg.crafts[ni] then elseif fields.zcg_update_settings then
zcg.users[pn].current_item = ni zcg.users[pn].settings = false
table.insert(zcg.users[pn].history.list, ni) zcg.users[pn].filter = fields.filter
zcg.users[pn].history.index = #zcg.users[pn].history.list zcg.users[pn].current_item = ""
inventory_plus.set_inventory_formspec(player,zcg.formspec(pn)) zcg.users[pn].page = 0
end inventory_plus.set_inventory_formspec(player, zcg.formspec(pn))
elseif (k:sub(0,9)=="zcg_page:") then elseif fields.zcg_allitems then
zcg.users[pn].page = tonumber(k:sub(10)) zcg.users[pn].allitems = fields.zcg_allitems == "true"
inventory_plus.set_inventory_formspec(player,zcg.formspec(pn)) zcg.users[pn].current_item = ""
elseif (k:sub(0,8)=="zcg_alt:") then zcg.users[pn].page = 0
zcg.users[pn].alt = tonumber(k:sub(9)) elseif fields.zcg_itemstrings then
inventory_plus.set_inventory_formspec(player,zcg.formspec(pn)) zcg.users[pn].itemstrings = fields.zcg_itemstrings == "true"
end elseif fields.zcg_previous then
end if zcg.users[pn].history.index > 1 then
zcg.users[pn].history.index = zcg.users[pn].history.index - 1
zcg.users[pn].current_item = zcg.users[pn].history.list[zcg.users[pn].history.index]
inventory_plus.set_inventory_formspec(player,zcg.formspec(pn))
end
elseif fields.zcg_next then
if zcg.users[pn].history.index < #zcg.users[pn].history.list then
zcg.users[pn].history.index = zcg.users[pn].history.index + 1
zcg.users[pn].current_item = zcg.users[pn].history.list[zcg.users[pn].history.index]
inventory_plus.set_inventory_formspec(player,zcg.formspec(pn))
end
end
for k, v in pairs(fields) do
if (k:sub(0,4)=="zcg:") then
local ni = k:sub(5)
zcg.users[pn].current_item = ni
table.insert(zcg.users[pn].history.list, ni)
zcg.users[pn].history.index = #zcg.users[pn].history.list
inventory_plus.set_inventory_formspec(player,zcg.formspec(pn))
elseif (k:sub(0,9)=="zcg_page:") then
zcg.users[pn].page = tonumber(k:sub(10))
inventory_plus.set_inventory_formspec(player,zcg.formspec(pn))
elseif (k:sub(0,8)=="zcg_alt:") then
zcg.users[pn].alt = tonumber(k:sub(9))
inventory_plus.set_inventory_formspec(player,zcg.formspec(pn))
end
end
end) end)