minetest-craft_guide/api_craft_guide.lua
2012-09-12 11:30:55 +09:30

359 lines
9.8 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: GPLv3
CRAFT GUIDE API
]]--
-- expose object to other modules
craft_guide = {}
-- define api variables
craft_guide.crafts = {}
craft_guide.craft_guide_size = 0
-- 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())
craft_guide.crafts[itemstack:get_name()] = options
end
-- set_craft_guide_formspec
craft_guide.set_craft_guide_formspec = function(meta, start_i, pagenum)
pagenum = math.floor(pagenum)
local pagemax = math.floor((craft_guide.craft_guide_size-1) / (5*14) + 1)
meta:set_string("formspec",
"size[14,10;]"..
"label[0,0;--== Learn to Craft ==--]"..
"label[0,0.4;Drag an item to the Output box]"..
"label[9,0.2;page "..tostring(pagenum).." of "..tostring(pagemax).."]"..
"button[11,0;1.5,1;craft_guide_prev;<<]"..
"button[12.5,0;1.5,1;craft_guide_next;>>]"..
"list[detached:craft_guide;main;0,1;14,5;"..tostring(start_i).."]"..
"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;]")
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)
end
-- on_receive_fields
craft_guide.on_receive_fields = function(pos, formname, fields, player)
-- Figure out current page from formspec
local current_page = 0
local meta = minetest.env:get_meta(pos);
local formspec = meta:get_string("formspec")
local start_i = string.match(formspec, "list%[detached:craft_guide;main;[%d.]+,[%d.]+;[%d.]+,[%d.]+;(%d+)%]")
start_i = tonumber(start_i) or 0
if fields.craft_guide_prev then
start_i = start_i - 5*14
end
if fields.craft_guide_next then
start_i = start_i + 5*14
end
if start_i < 0 then
start_i = start_i + 5*14
end
if start_i >= craft_guide.craft_guide_size then
start_i = start_i - 5*14
end
if start_i < 0 or start_i >= craft_guide.craft_guide_size then
start_i = 0
end
craft_guide.set_craft_guide_formspec(meta, start_i, start_i / (5*14) + 1)
end
-- update_recipe
craft_guide.update_recipe = function(meta, player, stack)
craft_guide.log(player:get_player_name().." requests recipe for "..stack:get_name())
local inv = meta:get_inventory()
local craft = craft_guide.crafts[stack:get_name()];
for var=0,inv:get_size("build"),1 do
inv:set_stack("build", var, nil)
end
inv:set_stack("cook", 1, nil)
inv:set_stack("fuel", 1, nil)
inv:set_stack("output", 1, stack:get_name())
if craft_guide.crafts[stack:get_name()] == nil then
minetest.chat_send_player(player:get_player_name(), "no recipe available for "..stack:get_name())
return
end
-- show me the unknown items
craft_guide.log(dump(craft))
minetest.chat_send_player(player:get_player_name(), "recipe for "..stack:get_name()..": "..dump(craft))
local itemstack = ItemStack(craft.output)
inv:set_stack("output", 1, itemstack)
-- cook
if craft.type == "cooking" then
inv:set_stack("cook", 1, craft.recipe)
return
end
-- fuel
if craft.type == "fuel" then
inv:set_stack("fuel", 1, craft.recipe)
return
end
-- build (shaped or shapeless)
if craft.recipe[1] then
if (type(craft.recipe[1]) == "string") then
inv:set_stack("build", 1, craft.recipe[1])
else
if craft.recipe[1][1] then
inv:set_stack("build", 1, craft.recipe[1][1])
end
if craft.recipe[1][2] then
inv:set_stack("build", 2, craft.recipe[1][2])
end
if craft.recipe[1][3] then
inv:set_stack("build", 3, craft.recipe[1][3])
end
end
end
if craft.recipe[2] then
if (type(craft.recipe[2]) == "string") then
inv:set_stack("build", 2, craft.recipe[2])
else
if craft.recipe[2][1] then
inv:set_stack("build", 4, craft.recipe[2][1])
end
if craft.recipe[2][2] then
inv:set_stack("build", 5, craft.recipe[2][2])
end
if craft.recipe[2][3] then
inv:set_stack("build", 6, craft.recipe[2][3])
end
end
end
if craft.recipe[3] then
if (type(craft.recipe[3]) == "string") then
inv:set_stack("build", 3, craft.recipe[3])
else
if craft.recipe[3][1] then
inv:set_stack("build", 7, craft.recipe[3][1])
end
if craft.recipe[3][2] then
inv:set_stack("build", 8, craft.recipe[3][2])
end
if craft.recipe[3][3] then
inv:set_stack("build", 9, craft.recipe[3][3])
end
end
end
if craft.recipe[4] then
if (type(craft.recipe[4]) == "string") then
inv:set_stack("build", 4, craft.recipe[4])
end
end
if craft.recipe[5] then
if (type(craft.recipe[5]) == "string") then
inv:set_stack("build", 5, craft.recipe[5])
end
end
if craft.recipe[6] then
if (type(craft.recipe[6]) == "string") then
inv:set_stack("build", 6, craft.recipe[6])
end
end
if craft.recipe[7] then
if (type(craft.recipe[7]) == "string") then
inv:set_stack("build", 7, craft.recipe[7])
end
end
if craft.recipe[8] then
if (type(craft.recipe[8]) == "string") then
inv:set_stack("build", 8, craft.recipe[8])
end
end
if craft.recipe[9] then
if (type(craft.recipe[9]) == "string") then
inv:set_stack("build", 9, craft.recipe[9])
end
end
end
-- update_recipe_minetest (using minetest builtin craft registry)
craft_guide.update_recipe_minetest = function(meta, player, stack)
craft_guide.log(player:get_player_name().." requests recipe for "..stack:get_name())
-- clear out build items
local inv = meta:get_inventory()
for var=0,inv:get_size("build"),1 do
inv:set_stack("build", var, nil)
end
inv:set_stack("cook", 1, nil)
inv:set_stack("fuel", 1, nil)
-- ensure we have a recipe
local craft_recipe = minetest.get_craft_recipe(stack:get_name());
if craft_recipe.items == nil then
minetest.chat_send_player(player:get_player_name(), "no recipe available for "..stack:get_name())
return
end
-- show me the unknown items
craft_guide.log(dump(craft_recipe.items))
minetest.chat_send_player(player:get_player_name(), "recipe for "..stack:get_name()..": "..dump(craft_recipe.items))
-- output with quantity
local craft_result = minetest.get_craft_result(craft_recipe);
local itemstack = ItemStack(craft_result.item)
if itemstack:get_count() > 0 then
inv:set_stack("output", 1, itemstack)
else
inv:set_stack("output", 1, stack)
end
-- cook
if craft_recipe.type == "cooking" then
inv:set_stack("cook", 1, craft_recipe.items['0'])
return
end
-- fuel
if craft_recipe.type == "fuel" then
inv:set_stack("fuel", 1, craft_recipe.items['0'])
return
end
-- build (shaped or shapeless)
if craft_recipe.items['0'] then
inv:set_stack("build", 1, craft_recipe.items['0'])
end
if craft_recipe.items['1'] then
if craft_recipe.width == 1 then
inv:set_stack("build", 4, craft_recipe.items['1'])
else
inv:set_stack("build", 2, craft_recipe.items['1'])
end
end
if craft_recipe.items['2'] then
if craft_recipe.width == 1 then
inv:set_stack("build", 7, craft_recipe.items['2'])
elseif craft_recipe.width == 2 then
inv:set_stack("build", 4, craft_recipe.items['2'])
else
inv:set_stack("build", 3, craft_recipe.items['2'])
end
end
if craft_recipe.items['3'] then
if craft_recipe.width == 2 then
inv:set_stack("build", 5, craft_recipe.items['3'])
else
inv:set_stack("build", 4, craft_recipe.items['3'])
end
end
if craft_recipe.items['4'] then
if craft_recipe.width == 2 then
inv:set_stack("build", 7, craft_recipe.items['4'])
else
inv:set_stack("build", 5, craft_recipe.items['4'])
end
end
if craft_recipe.items['5'] then
if craft_recipe.width == 2 then
inv:set_stack("build", 8, craft_recipe.items['5'])
else
inv:set_stack("build", 6, craft_recipe.items['5'])
end
end
if craft_recipe.items['6'] then
inv:set_stack("build", 7, craft_recipe.items['6'])
end
if craft_recipe.items['7'] then
inv:set_stack("build", 8, craft_recipe.items['7'])
end
if craft_recipe.items['8'] then
inv:set_stack("build", 9, craft_recipe.items['8'])
end
end
-- create_detached_inventory
craft_guide.create_detached_inventory = function()
local inv = minetest.create_detached_inventory("craft_guide", {
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
return 0
end,
allow_put = function(inv, listname, index, stack, player)
return -1
end,
allow_take = function(inv, listname, index, stack, player)
return 0
end,
on_move = function(inv, from_list, from_index, to_list, to_index, count, player)
end,
on_put = function(inv, listname, index, stack, player)
end,
on_take = function(inv, listname, index, stack, player)
end,
})
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
table.insert(craft_guide_list, name)
end
end
end
table.sort(craft_guide_list)
inv:set_size("main", #craft_guide_list)
for _,itemstring in ipairs(craft_guide_list) do
inv:add_item("main", ItemStack(itemstring))
end
craft_guide.craft_guide_size = #craft_guide_list
craft_guide.log("craft_guide_size: "..dump(craft_guide.craft_guide_size))
end