elepower/elepower_machines/craft.lua

248 lines
5.7 KiB
Lua

local have_ui = minetest.get_modpath("unified_inventory")
local have_cg = minetest.get_modpath("craftguide") and craftguide and craftguide.register_craft
elepm.craft = {}
elepm.craft.types = {}
local function item_string( ... )
-- body
end
function elepm.register_craft_type(name, def)
elepm.craft.types[name] = {
inputs = def.inputs or 2,
description = def.description or name,
overview = def.overview or name,
time = def.time or 0,
gui_name = def.gui_name,
}
elepm.craft[name] = {}
-- Don't register cooking or fuel types externally.
if name == "cooking" or name == "fuel" then return end
if have_ui and unified_inventory.register_craft_type then
unified_inventory.register_craft_type(name, {
description = def.description or name,
icon = def.icon or "elepower_machine_side.png",
width = def.inputs or 2,
height = 1,
})
end
if have_cg then
craftguide.register_craft_type(name, {
description = def.description,
icon = def.icon or "elepower_machine_side.png",
})
end
end
function elepm.register_craft(craftdef)
if not craftdef.type or not elepm.craft.types[craftdef.type] then
return nil
end
if craftdef.type == "cooking" or craftdef.type == "fuel" then
minetest.register_craft(craftdef)
return
end
local inputs = craftdef.recipe
local outputs = craftdef.output
local ctype = craftdef.type
local ctypedef = elepm.craft.types[ctype]
local time = (craftdef.time or craftdef.cooktime or 5) + (ctypedef.time or 0)
local craftrecipe = {}
-- Recipe inputs are stored as hybridization of standard furnace and regular crafting
-- Table is structured as example
-- input{{[default:tin_ingot]=1},{[default:tin_ingot]=1}}
-- to contrast "cooking" recipes are stored as
-- input{[default:iron_ore]=1}
-- to contrast normal craft recipes are stored as and always assume x1:
-- input:{
-- {item,item,item},
-- {item,item,item},
-- {item,item,item}
-- }
for _,input in ipairs(inputs) do
local stack = ItemStack(input)
if stack and not stack:is_empty() then
table.insert(craftrecipe,{[stack:get_name()] = stack:get_count()})
end
end
local craftresult = {}
if type(outputs) == "table" then
for _,output in ipairs(outputs) do
local stack = ItemStack(output)
if stack and not stack:is_empty() then
craftresult[#craftresult + 1] = stack:to_string()
end
end
else
craftresult = ItemStack(outputs)
end
local recipe = {
recipe = craftrecipe,
output = craftresult,
time = time
}
table.insert(elepm.craft[ctype], recipe)
if have_ui or have_cg then
local spec = {}
local items = {}
for _, def in pairs(recipe.recipe) do
for item,count in pairs(def) do
local stack = ItemStack(item)
stack:set_count(count)
spec[#spec+1] = stack
items[#items+1] = stack:to_string()
end
end
if type(recipe.output) == "table" then
for _,itm in pairs(recipe.output) do
local itmst = ItemStack(itm)
if have_ui then
unified_inventory.register_craft({
type = craftdef.type,
output = itmst,
items = spec,
width = ctypedef.inputs,
})
end
if have_cg then
craftguide.register_craft({
type = craftdef.type,
output = itmst:to_string(),
items = items,
width = ctypedef.inputs,
})
end
end
return
end
if have_ui then
unified_inventory.register_craft({
type = craftdef.type,
output = recipe.output,
items = spec,
width = ctypedef.inputs,
})
end
if have_cg then
craftguide.register_craft({
type = craftdef.type,
output = recipe.output:to_string(),
items = items,
width = ctypedef.inputs,
})
end
end
end
local no_recipe = {
time = 0,
new_input = {},
output = {}
}
function elepm.get_recipe(type, inputs)
if not elepm.craft[type] or not inputs then
return no_recipe
end
-- Minetest's cooking builtin type
if type == "cooking" then
local result, new_input = minetest.get_craft_result({
method = "cooking",
width = 1,
items = inputs
})
if not result or result.time == 0 then
return no_recipe
else
return {
time = result.time,
new_input = new_input.items,
output = result.item
}
end
end
-- Custom types
local result = no_recipe
local recipe_match = false
local new_input = {}
local sp_recipe
local count
for rec_num,recipe in pairs(elepm.craft[type]) do
sp_recipe = 0
count = 0
for item_num, items in pairs(recipe.recipe) do -- items = {value4 = 1}
for pos,input in pairs(inputs) do
local in_name = input:get_name()
if items[in_name] and -- is input_name in recipe
items[in_name] <= input:get_count() and -- do we have enough materials in input
pos == item_num then -- are we in correct pos/slot
sp_recipe = rec_num
count = count + 1
end
end
end
if count == #inputs then
recipe_match = true
break
end
end
if recipe_match == true then
for item_num,items in pairs(elepm.craft[type][sp_recipe]["recipe"]) do
for name,num in pairs(items) do
local istack = ItemStack(name)
istack:set_count(inputs[item_num]:get_count() - num)
new_input[#new_input + 1] = istack
end
end
result = elepm.craft[type][sp_recipe] -- includes recipe,time,output
result.new_input = new_input
else
--minetest.debug("no match") -- useful for debugging
end
return result
end
-- Cooking craft type built-in.
elepm.register_craft_type("cooking", {
description = "Cooking",
overview = "Cooking is more than just the prepartion of food "..
"it provides access to the prepartion of ores to metals "..
"and the creation of glass and glass objects.",
inputs = 1,
})