235 lines
6.9 KiB
Lua

-- ZCG mod for minetest
-- See README for more information
-- Released by Zeg9 under WTFPL
zcg = {}
zcg.users = {}
zcg.crafts = {}
zcg.itemlist = {}
zcg.items_in_group = function(group)
local items = {}
local ok = true
for name, item in pairs(minetest.registered_items) do
-- the node should be in all groups
ok = true
for _, g in ipairs(group:split(',')) do
if not item.groups[g] then
ok = false
end
end
if ok then table.insert(items,name) end
end
return items
end
local table_copy = function(table)
out = {}
for k,v in pairs(table) do
out[k] = v
end
return out
end
zcg.add_craft = function(input, output, groups)
if minetest.get_item_group(output, "not_in_craft_guide") > 0 then
return
end
if not groups then groups = {} end
local stack_num = ItemStack(nil)
if input.output == nil then
-- prevent a crash indexing nil
else
stack_num = ItemStack(input.output):get_count()
end
--print(stack_num:get_count(), input.output)
local c = {}
c.width = input.width
c.type = input.type
c.items = input.items
c.number = stack_num
if c.items == nil then return end
for i, item in pairs(c.items) do
if item:sub(0,6) == "group:" then
local groupname = item:sub(7)
if groups[groupname] ~= nil then
c.items[i] = groups[groupname]
else
for _, gi in ipairs(zcg.items_in_group(groupname)) do
local g2 = groups
g2[groupname] = gi
zcg.add_craft({
width = c.width,
type = c.type,
items = table_copy(c.items),
output = input.output
}, output, g2) -- it is needed to copy the table, else groups won't work right
end
return
end
end
end
if c.width == 0 then c.width = 3 end
table.insert(zcg.crafts[output],c)
end
zcg.load_crafts = function(name)
zcg.crafts[name] = {}
local _recipes = minetest.get_all_craft_recipes(name)
if _recipes then
for i, recipe in ipairs(_recipes) do
if (recipe and recipe.items and recipe.type) then
zcg.add_craft(recipe, name)
end
end
end
if zcg.crafts[name] == nil or #zcg.crafts[name] == 0 then
zcg.crafts[name] = nil
else
table.insert(zcg.itemlist,name)
end
end
zcg.need_load_all = true
zcg.load_all = function()
print("Loading all crafts, this may take some time...")
local i = 0
for name, item in pairs(minetest.registered_items) do
if (name and name ~= "") then
zcg.load_crafts(name)
end
i = i+1
end
table.sort(zcg.itemlist)
zcg.need_load_all = false
print("All crafts loaded !")
end
zcg.formspec = function(pn)
if zcg.need_load_all then zcg.load_all() end
page = zcg.users[pn].page
alt = zcg.users[pn].alt
current_item = zcg.users[pn].current_item
local formspec = "size[8,9]"
.. "button[0,0;3,1;main;Return to Inventory]"
.. "background[-0.45,-0.5;8.9,10;core_inv_plus_guide.png]"
.. "listcolors[#573b2e;#de9860;#ffffff;#3f2832;#ffffff]"
if zcg.users[pn].history.index > 1 then
formspec = formspec .. "button[0,3.1;2.25,1;zcg_previous;Last Recipe]"
else
end
if zcg.users[pn].history.index < #zcg.users[pn].history.list then
formspec = formspec .. "button[2.25,3.1;2.25,1;zcg_next;Next Recipe]"
else
end
-- Show craft recipe
if current_item ~= "" then
if zcg.crafts[current_item] then
if alt > #zcg.crafts[current_item] then
alt = #zcg.crafts[current_item]
end
if alt > 1 then
formspec = formspec .. "button[7,0;1,1;zcg_alt:"..(alt-1)..";^]"
end
if alt < #zcg.crafts[current_item] then
formspec = formspec .. "button[7,2;1,1;zcg_alt:"..(alt+1)..";v]"
end
local c = zcg.crafts[current_item][alt]
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..";]"
end
if c.type == "normal" then
formspec = formspec .. "image[6,2;1,1;zcg_method_"..c.type..".png]"
elseif c.type == "cooking" then -- we don't have an image for other types of crafting
formspec = formspec .. "image[6,2;1,1;"..minetest.inventorycube("core_furnace_top.png", "core_furnace_front_active.png", "core_furnace_top.png").."]"
else
formspec = formspec .. "label[0,2;Method: "..c.type.."]"
end
formspec = formspec .. "image[6,1;1,1;core_crafting_arrow.png]"
formspec = formspec .. "item_image_button[7,1;1,1;"..zcg.users[pn].current_item..";;]"
formspec = formspec .. "label[7.8,1.5;" .. tostring(c.number) .. "]"
--print (dump(zcg.crafts["stairs:slab_grass_wildlands"]))
end
end
end
-- Node list
local npp = 8*3 -- nodes per page
local i = 0 -- for positionning buttons
local s = 0 -- for skipping pages
for _, name in ipairs(zcg.itemlist) 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)+5)..";1,1;"..name..";zcg:"..name..";]"
i = i+1
end
end
if page > 0 then
formspec = formspec .. "button[0,8.1;2.25,1;zcg_page:"..(page-1)..";Previous Page]"
end
if i >= npp then
formspec = formspec .. "button[2.25,8.1;2.25,1;zcg_page:"..(page+1)..";Next Page]"
end
formspec = formspec .. "label[0,4.45;Crafting Page: "..(page+1).." of "..(math.floor(#zcg.itemlist/npp+1)).."]" -- The Y is approximatively the good one to have it centered vertically...
return formspec
end
minetest.register_on_joinplayer(function(player)
inventory_plus.register_button(player,"zcg","Crafting Guide")
end)
minetest.register_on_player_receive_fields(function(player,formname,fields)
pn = player:get_player_name();
if zcg.users[pn] == nil then zcg.users[pn] = {current_item = "", alt = 1, page = 0, history={index=0,list={}}} end
if fields.zcg then
inventory_plus.set_inventory_formspec(player, zcg.formspec(pn))
return
elseif fields.zcg_previous then
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)
if zcg.crafts[ni] then
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))
end
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)