minetest-craft_guide/craft_guide/api_craft_guide.lua
2014-12-14 17:04:22 +10:30

446 lines
13 KiB
Lua

--[[
Craft Guide for Minetest
Copyright (c) 2012 cornernote, Brett O'Donnell <cornernote@gmail.com>
Source Code: https://github.com/cornernote/minetest-craft_guide
License: BSD-3-Clause https://raw.github.com/cornernote/minetest-craft_guide/master/LICENSE
CRAFT GUIDE API
]]--
-- expose object to other modules
craft_guide = {}
-- define api variables
craft_guide.crafts = {}
craft_guide.groups = {}
craft_guide.group_messages = {}
-- log
craft_guide.log = function(message)
--if not craft_guide.DEBUG then return end
minetest.log("action", "[CraftGuide] "..message)
end
-- register_craft
craft_guide.register_craft = function(options)
if options.output == nil then
return
end
local itemstack = ItemStack(options.output)
if itemstack:is_empty() then
return
end
--craft_guide.log("registered craft for - "..itemstack:get_name())
if craft_guide.crafts[itemstack:get_name()]==nil then
craft_guide.crafts[itemstack:get_name()] = {}
end
table.insert(craft_guide.crafts[itemstack:get_name()],options)
end
-- get_craft_guide_formspec
craft_guide.get_craft_guide_formspec = function(meta, search, page, alternate)
if search == nil then
search = meta:get_string("search")
end
if page == nil then
page = craft_guide.get_current_page(meta)
end
if alternate == nil then
alternate = craft_guide.get_current_alternate(meta)
end
local inv = meta:get_inventory()
local size = inv:get_size("main")
local start = (page-1) * (5*14) + 1
local pages = math.floor((size-1) / (5*14) + 1)
local alternates = 0
local stack = inv:get_stack("output",1)
local crafts = craft_guide.crafts[stack:get_name()]
if crafts ~= nil then
alternates = #crafts
end
local formspec = "size[14,10;]"
.."list[current_name;main;0,0;14,5;"..tostring(start).."]"
.."label[0,5;--== Learn to Craft ==--]"
.."label[0,5.4;Drag any item to the Output box to see the]"
.."label[0,5.8;craft. Save your favorite items in Bookmarks.]"
.."field[6,5.4;2,1;craft_guide_search_box;;"..tostring(search).."]"
.."button[7.5,5.1;1.2,1;craft_guide_search_button;Search]"
.."label[9,5.2;page "..tostring(page).." of "..tostring(pages).."]"
.."button[11,5;1.5,1;craft_guide_prev;<<]"
.."button[12.5,5;1.5,1;craft_guide_next;>>]"
.."label[0,6.5;Output]"
.."list[current_name;output;0,7;1,1;]"
.."label[2,6.5;Inventory Craft]"
.."list[current_name;build;2,7;3,3;]"
.."label[6,6.5;Cook]"
.."list[current_name;cook;6,7;1,1;]"
.."label[6,8.5;Fuel]"
.."list[current_name;fuel;6,9;1,1;]"
.."label[8,6.5;Bookmarks]"
.."list[current_name;bookmark;8,7;6,3;]"
.."label[12,6.1;Bin ->]"
.."list[current_name;bin;13,6;1,1;]"
if alternates > 1 then
formspec = formspec
.."label[0,8.6;recipe "..tostring(alternate).." of "..tostring(alternates).."]"
.."button[0,9;2,1;alternate;Alternate]"
end
return formspec
end
-- on_construct
craft_guide.on_construct = function(pos)
local meta = minetest.env:get_meta(pos)
local inv = meta:get_inventory()
inv:set_size("output", 1)
inv:set_size("build", 3*3)
inv:set_size("cook", 1)
inv:set_size("fuel", 1)
inv:set_size("bookmark", 6*3)
inv:set_size("bin", 1)
craft_guide.create_inventory(inv)
meta:set_string("formspec",craft_guide.get_craft_guide_formspec(meta))
end
-- on_receive_fields
craft_guide.on_receive_fields = function(pos, formname, fields, player)
local meta = minetest.env:get_meta(pos);
local inv = meta:get_inventory()
local size = inv:get_size("main",1)
local stack = inv:get_stack("output",1)
local crafts = craft_guide.crafts[stack:get_name()]
local alternate = craft_guide.get_current_alternate(meta)
local alternates = 0
if crafts ~= nil then
alternates = #crafts
end
local page = craft_guide.get_current_page(meta)
local pages = math.floor((size-1) / (5*14) + 1)
local search
-- search
search = fields.craft_guide_search_box
meta:set_string("search", search)
if fields.craft_guide_search_button then
page = 1
end
-- change page
if fields.craft_guide_prev then
page = page - 1
end
if fields.craft_guide_next then
page = page + 1
end
if page < 1 then
page = 1
end
if page > pages then
page = pages
end
-- get an alternate recipe
if fields.alternate then
alternate = alternate+1
craft_guide.update_recipe(meta, player, stack, alternate)
end
if alternate > alternates then
alternate = 1
end
-- update the formspec
craft_guide.create_inventory(inv, search)
meta:set_string("formspec",craft_guide.get_craft_guide_formspec(meta, search, page, alternate))
end
-- get_current_page
craft_guide.get_current_page = function(meta)
local formspec = meta:get_string("formspec")
local page = string.match(formspec, "label%[[%d.]+,[%d.]+;page (%d+) of [%d.]+%]")
page = tonumber(page) or 1
return page
end
-- get_current_alternate
craft_guide.get_current_alternate = function(meta)
local formspec = meta:get_string("formspec")
local alternate = string.match(formspec, "label%[[%d.]+,[%d.]+;recipe (%d+) of [%d.]+%]")
alternate = tonumber(alternate) or 1
return alternate
end
-- update_recipe
craft_guide.update_recipe = function(meta, player, stack, alternate)
craft_guide.group_messages[player:get_player_name()] = {}
local inv = meta:get_inventory()
for i=0,inv:get_size("build"),1 do
inv:set_stack("build", i, nil)
end
inv:set_stack("cook", 1, nil)
inv:set_stack("fuel", 1, nil)
if stack==nil then return end
inv:set_stack("output", 1, stack:get_name())
local crafts = craft_guide.crafts[stack:get_name()]
if crafts == nil then
if stack:get_name() ~= '' then
minetest.chat_send_player(player:get_player_name(), "no recipe available for "..stack:get_name())
end
meta:set_string("formspec",craft_guide.get_craft_guide_formspec(meta))
return
end
alternate = tonumber(alternate) or 1
if alternate < 1 or alternate > #crafts then
alternate = 1
end
local craft = crafts[alternate]
local itemstack = ItemStack(craft.output)
inv:set_stack("output", 1, itemstack)
-- cook
if craft.type == "cooking" then
inv:set_stack("cook", 1, craft_guide.get_item_name(craft.recipe, player))
meta:set_string("formspec",craft_guide.get_craft_guide_formspec(meta))
return
end
-- fuel
if craft.type == "fuel" then
inv:set_stack("fuel", 1, craft_guide.get_item_name(craft.recipe, player))
meta:set_string("formspec",craft_guide.get_craft_guide_formspec(meta))
return
end
-- build (shaped or shapeless)
if craft.recipe[1] then
if (type(craft.recipe[1]) == "string") then
inv:set_stack("build", 1, craft_guide.get_item_name(craft.recipe[1], player))
else
if craft.recipe[1][1] then
inv:set_stack("build", 1, craft_guide.get_item_name(craft.recipe[1][1], player))
end
if craft.recipe[1][2] then
inv:set_stack("build", 2, craft_guide.get_item_name(craft.recipe[1][2], player))
end
if craft.recipe[1][3] then
inv:set_stack("build", 3, craft_guide.get_item_name(craft.recipe[1][3], player))
end
end
end
if craft.recipe[2] then
if (type(craft.recipe[2]) == "string") then
inv:set_stack("build", 2, craft_guide.get_item_name(craft.recipe[2], player))
else
if craft.recipe[2][1] then
inv:set_stack("build", 4, craft_guide.get_item_name(craft.recipe[2][1], player))
end
if craft.recipe[2][2] then
inv:set_stack("build", 5, craft_guide.get_item_name(craft.recipe[2][2], player))
end
if craft.recipe[2][3] then
inv:set_stack("build", 6, craft_guide.get_item_name(craft.recipe[2][3], player))
end
end
end
if craft.recipe[3] then
if (type(craft.recipe[3]) == "string") then
inv:set_stack("build", 3, craft_guide.get_item_name(craft.recipe[3], player))
else
if craft.recipe[3][1] then
inv:set_stack("build", 7, craft_guide.get_item_name(craft.recipe[3][1], player))
end
if craft.recipe[3][2] then
inv:set_stack("build", 8, craft_guide.get_item_name(craft.recipe[3][2], player))
end
if craft.recipe[3][3] then
inv:set_stack("build", 9, craft_guide.get_item_name(craft.recipe[3][3], player))
end
end
end
if craft.recipe[4] then
if (type(craft.recipe[4]) == "string") then
inv:set_stack("build", 4, craft_guide.get_item_name(craft.recipe[4], player))
end
end
if craft.recipe[5] then
if (type(craft.recipe[5]) == "string") then
inv:set_stack("build", 5, craft_guide.get_item_name(craft.recipe[5], player))
end
end
if craft.recipe[6] then
if (type(craft.recipe[6]) == "string") then
inv:set_stack("build", 6, craft_guide.get_item_name(craft.recipe[6], player))
end
end
if craft.recipe[7] then
if (type(craft.recipe[7]) == "string") then
inv:set_stack("build", 7, craft_guide.get_item_name(craft.recipe[7], player))
end
end
if craft.recipe[8] then
if (type(craft.recipe[8]) == "string") then
inv:set_stack("build", 8, craft_guide.get_item_name(craft.recipe[8], player))
end
end
if craft.recipe[9] then
if (type(craft.recipe[9]) == "string") then
inv:set_stack("build", 9, craft_guide.get_item_name(craft.recipe[9], player))
end
end
meta:set_string("formspec",craft_guide.get_craft_guide_formspec(meta))
end
-- create_inventory
craft_guide.create_inventory = function(inv, search)
local craft_guide_list = {}
for name,def in pairs(minetest.registered_items) do
-- local craft_recipe = minetest.get_craft_recipe(name);
-- if craft_recipe.items ~= nil then
local craft = craft_guide.crafts[name];
if craft ~= nil then
if (not def.groups.not_in_craft_guide or def.groups.not_in_craft_guide == 0)
--and (not def.groups.not_in_creative_inventory or def.groups.not_in_creative_inventory == 0)
and def.description and def.description ~= "" then
if search then
if string.find(def.name, search) or string.find(def.description, search) then
table.insert(craft_guide_list, name)
end
else
table.insert(craft_guide_list, name)
end
end
end
end
table.sort(craft_guide_list)
for i=0,inv:get_size("main"),1 do
inv:set_stack("main", i, nil)
end
inv:set_size("main", #craft_guide_list)
for _,itemstring in ipairs(craft_guide_list) do
inv:add_item("main", ItemStack(itemstring))
end
end
-- allow_metadata_inventory_move
craft_guide.allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
local meta = minetest.env:get_meta(pos)
local inv = meta:get_inventory()
if to_list == "bin" and from_list == "output" then
inv:set_stack(from_list,from_index,nil)
craft_guide.update_recipe(meta, player, inv:get_stack(from_list, from_index))
end
if to_list == "bin" and from_list == "bookmark" then
inv:set_stack(from_list,from_index,nil)
end
if to_list == "bookmark" then
inv:set_stack(to_list, to_index, inv:get_stack(from_list, from_index):get_name())
if from_list == "output" then
inv:set_stack(from_list,from_index,nil)
end
end
if to_list == "output" or from_list == "output" then
craft_guide.update_recipe(meta, player, inv:get_stack(from_list, from_index))
end
if from_list == "bookmarks" and to_list == "bookmarks" then
return count
end
return 0
end
-- allow_metadata_inventory_put
craft_guide.allow_metadata_inventory_put = function(pos, listname, index, stack, player)
return 0
end
-- allow_metadata_inventory_take
craft_guide.allow_metadata_inventory_take = function(pos, listname, index, stack, player)
return 0
end
-- get an item name, if it's a group then get an item in the group
craft_guide.get_item_name = function(item_name, player)
if string.find(item_name, "group:") then
local group_name = item_name
if craft_guide.table_count(craft_guide.groups) == 0 then
craft_guide.load_item_groups()
end
if craft_guide.table_count(craft_guide.groups) > 0 then
local other_items = {}
if craft_guide.groups[string.sub(group_name, 7)] ~= nil then
item_name = craft_guide.groups[string.sub(group_name, 7)].item_name
other_items = craft_guide.groups[string.sub(group_name, 7)].other_items
if #other_items > 0 then
if craft_guide.group_messages[player:get_player_name()][item_name] == nil then
minetest.chat_send_player(player:get_player_name(), "Item "..item_name.." used for "..group_name..". You can also use "..table.concat(other_items, ", ")..".")
end
craft_guide.group_messages[player:get_player_name()][item_name] = true
end
end
end
end
return item_name
end
-- load the item groups table
craft_guide.load_item_groups = function()
for name,def in pairs(minetest.registered_items) do
if name ~= nil and def ~= nil and dump(name) ~= "\"\"" and dump(def) ~= "\"\"" then
local i = 1
for group,_ in pairs(def.groups) do
if craft_guide.groups[group] == nil then
craft_guide.groups[group] = {}
craft_guide.groups[group].other_items = {}
craft_guide.groups[group].item_name = name
else
craft_guide.groups[group].other_items[i] = name
i = i+1
end
end
end
end
end
-- count items in a table
craft_guide.table_count = function(count_table)
local count = 0;
for k,v in pairs(count_table) do
count = count + 1
end
return count
end