229 lines
5.3 KiB
Lua
229 lines
5.3 KiB
Lua
--[[
|
|
|
|
TechAge
|
|
=======
|
|
|
|
Copyright (C) 2019-2020 Joachim Stolberg
|
|
|
|
AGPL v3
|
|
See LICENSE.txt for more information
|
|
|
|
Cooking routines for furnace
|
|
|
|
]]--
|
|
|
|
-- for lazy programmers
|
|
local P = minetest.string_to_pos
|
|
local M = minetest.get_meta
|
|
local S = techage.S
|
|
|
|
local range = techage.in_range
|
|
|
|
local Recipes = {} -- registered recipes {output = {recipe, ...},}
|
|
local Ingredients = {} -- {{input = output},
|
|
local KeyList = {} -- index to Recipes key translation
|
|
|
|
techage.furnace = {}
|
|
|
|
|
|
local function all_ingredients_available(output, ingr)
|
|
if Recipes[output] then
|
|
for idx,recipe in ipairs(Recipes[output]) do
|
|
local not_in_list = false
|
|
for _,item in ipairs(recipe.input) do
|
|
if not techage.in_list(ingr, item) then
|
|
not_in_list = true
|
|
end
|
|
end
|
|
if not_in_list == false then
|
|
return idx -- list number of the recipe
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Return a list with all outputs of the given list of ingredients
|
|
local function get_recipes(ingr)
|
|
if #ingr > 0 then
|
|
local tbl = {}
|
|
for _,item in ipairs(ingr) do
|
|
if Ingredients[item] then
|
|
for _,output in ipairs(Ingredients[item]) do
|
|
if all_ingredients_available(output, ingr) then
|
|
techage.add_to_set(tbl, output)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return tbl
|
|
else
|
|
return KeyList
|
|
end
|
|
end
|
|
|
|
function techage.furnace.get_ingredients(pos)
|
|
local inv = M(pos):get_inventory()
|
|
local tbl = {}
|
|
for _,stack in ipairs(inv:get_list('src')) do
|
|
if stack:get_name() ~= "" then
|
|
tbl[#tbl+1] = stack:get_name()
|
|
end
|
|
end
|
|
return tbl
|
|
end
|
|
|
|
local function remove_item_from_list(list, item)
|
|
for _,stack in ipairs(list) do
|
|
if stack:get_name() == item then
|
|
stack:set_count(stack:get_count() - 1)
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
-- move recipe src items to output inventory
|
|
local function process(inv, recipe, output)
|
|
-- check dst inv
|
|
local stack = ItemStack(output)
|
|
stack:set_count(recipe.number)
|
|
if not inv:room_for_item("dst", stack) then
|
|
return techage.BLOCKED
|
|
end
|
|
-- handle waste
|
|
if recipe.waste then
|
|
if not inv:room_for_item("dst", ItemStack(recipe.waste)) then
|
|
return techage.BLOCKED
|
|
end
|
|
end
|
|
-- remove items
|
|
local list = inv:get_list("src")
|
|
for _,item in ipairs(recipe.input) do
|
|
if not remove_item_from_list(list, item) then
|
|
return techage.STANDBY
|
|
end
|
|
end
|
|
-- store changes on scr
|
|
inv:set_list("src", list)
|
|
-- add output to dst
|
|
inv:add_item("dst", stack)
|
|
-- add waste to dst
|
|
if recipe.waste then
|
|
local leftover = inv:add_item("dst", ItemStack(recipe.waste))
|
|
if leftover:get_count() > 0 then
|
|
inv:add_item("src", leftover)
|
|
return techage.BLOCKED
|
|
end
|
|
end
|
|
return techage.RUNNING
|
|
end
|
|
|
|
function techage.furnace.check_if_worth_to_wakeup(pos, nvm)
|
|
local inv = M(pos):get_inventory()
|
|
if not nvm.output or not nvm.num_recipe then
|
|
return false
|
|
end
|
|
local recipe = Recipes[nvm.output] and Recipes[nvm.output][nvm.num_recipe]
|
|
if not recipe then
|
|
return false
|
|
end
|
|
-- check dst inv
|
|
local stack = ItemStack(nvm.output)
|
|
stack:set_count(recipe.number)
|
|
if not inv:room_for_item("dst", stack) then
|
|
return false
|
|
end
|
|
-- check src inv
|
|
local list = inv:get_list("src")
|
|
for _,item in ipairs(recipe.input) do
|
|
if not remove_item_from_list(list, item) then
|
|
return false
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
function techage.furnace.smelting(pos, nvm, elapsed)
|
|
local inv = M(pos):get_inventory()
|
|
local state = techage.RUNNING
|
|
if inv and not inv:is_empty("src") then
|
|
if not nvm.output or not nvm.num_recipe then
|
|
return techage.FAULT, "recipe error"
|
|
end
|
|
local recipe = Recipes[nvm.output] and Recipes[nvm.output][nvm.num_recipe]
|
|
if not recipe then
|
|
return techage.FAULT, "recipe error"
|
|
end
|
|
|
|
elapsed = elapsed + (nvm.leftover or 0)
|
|
while elapsed >= recipe.time do
|
|
state = process(inv, recipe, nvm.output)
|
|
if state ~= techage.RUNNING then
|
|
return state
|
|
end
|
|
elapsed = elapsed - recipe.time
|
|
end
|
|
nvm.leftover = elapsed
|
|
if recipe.time >= 10 then
|
|
nvm.item_percent = math.min(math.floor((nvm.leftover * 100.0) / recipe.time), 100)
|
|
else
|
|
nvm.item_percent = 100
|
|
end
|
|
return state
|
|
end
|
|
return techage.STANDBY
|
|
end
|
|
|
|
function techage.furnace.get_output(nvm, ingr, idx)
|
|
local tbl = get_recipes(ingr)
|
|
idx = range(idx, 1, #tbl)
|
|
nvm.output = tbl[idx] or tbl[1]
|
|
nvm.num_recipe = all_ingredients_available(nvm.output, ingr)
|
|
return nvm.output
|
|
end
|
|
|
|
function techage.furnace.get_num_recipes(ingr)
|
|
return #get_recipes(ingr)
|
|
end
|
|
|
|
function techage.furnace.reset_cooking(nvm)
|
|
nvm.leftover = 0
|
|
nvm.item_percent = 0
|
|
end
|
|
|
|
|
|
techage.recipes.register_craft_type("ta3_melting", {
|
|
description = S("TA3 Melting"),
|
|
icon = "techage_concrete.png^techage_appl_furnace.png^techage_frame_ta3.png",
|
|
width = 2,
|
|
height = 2,
|
|
})
|
|
|
|
function techage.furnace.register_recipe(recipe)
|
|
local words = string.split(recipe.output, " ")
|
|
local output = words[1]
|
|
local number = tonumber(words[2] or 1)
|
|
table.insert(KeyList, output)
|
|
--print(recipe.output, dump(recipe.recipe))
|
|
if not Recipes[output] then
|
|
Recipes[output] = {}
|
|
end
|
|
table.insert(Recipes[output], {
|
|
input = recipe.recipe,
|
|
waste = recipe.waste,
|
|
number = number,
|
|
time = math.max((recipe.time or 3) * number, 2),
|
|
})
|
|
for _,item in ipairs(recipe.recipe) do
|
|
if Ingredients[item] then
|
|
techage.add_to_set(Ingredients[item], output)
|
|
else
|
|
Ingredients[item] = {output}
|
|
end
|
|
end
|
|
|
|
recipe.items = recipe.recipe
|
|
recipe.type = "ta3_melting"
|
|
techage.recipes.register_craft(recipe)
|
|
end
|