123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378 |
- local log_removals = minetest.settings:get_bool("simplecrafting_lib_log_invalid_recipe_removal")
- local register_heat = function()
- if minetest.registered_craftitems["simplecrafting_lib:heat"] == nil then
- minetest.register_craftitem(":simplecrafting_lib:heat", {
- description = "Heat",
- groups = {simplecrafting_lib_intermediate=1, not_in_creative_inventory=1,},
- inventory_image = "simplecrafting_lib_heat.png",
- stack_max = 9999,
- })
- end
- end
- local function create_recipe(legacy)
- local items = legacy.items
- local has_items = false
- for _, item in pairs(items) do
- has_items = true
- break
- end
- if not has_items then return end
- local recipe = {}
- recipe.output = ItemStack(legacy.output)
- recipe.input = {}
- recipe.returns = legacy.returns
- for _, item in pairs(items) do
- if item ~= "" then
- recipe.input[item] = (recipe.input[item] or 0) + 1
- end
- end
- return recipe
- end
- local function get_item_and_quantity(item_string)
- local string_split_list = {}
- for v in string.gmatch(item_string, "%S+") do
- table.insert(string_split_list, v)
- end
- if #string_split_list == 1 then
- return item_string, 1
- else
- return string_split_list[1], tonumber(string_split_list[#string_split_list])
- end
- end
- local function get_replacement_group_haver(item_name, item_counts, recipe)
- if item_counts[item_name] == nil then
-
- if string.sub(item_name, 1, 6) == "group:" then
- local groupname = string.sub(item_name, 7)
- for k, v in pairs(item_counts) do
- if minetest.get_item_group(k, groupname) > 0 then
- return k
- end
- end
- return false, "[simplecrafting_lib] recipe has a group replacement " .. item_name
- .. " but an input belonging to that group can't be found."
- end
-
-
- for input, _ in pairs(item_counts) do
- if string.sub(input, 1, 6) == "group:" and
- minetest.get_item_group(item_name, string.sub(input, 7)) > 0 then
- return input
- end
- end
- return false, "[simplecrafting_lib] recipe has a replacement target " .. item_name ..
- " but an input matching it can't be found."
- end
-
- return item_name
- end
- local function process_replacements(recipe, count, legacy_returns)
- for _,pair in pairs(recipe.replacements) do
- local item_name, item_quantity = get_item_and_quantity(pair[2])
- local replace_input, err = get_replacement_group_haver(pair[1], count, recipe)
- if replace_input == false then
- return false, err
- end
- local input_count = count[replace_input]
- if input_count == nil then
- return false, "Replacement input not found: " .. replace_input
- end
- legacy_returns[item_name] = input_count * item_quantity
- end
- return true
- end
- local function process_shaped_recipe(recipe)
- local legacy = {items={},output=recipe.output}
- local count = {}
- for _,row in pairs(recipe.recipe) do
- for _, item in pairs(row) do
- legacy.items[#legacy.items+1] = item
- count[item] = (count[item] or 0) + 1
- end
- end
- if recipe.replacements then
- legacy.returns = {}
- local success, err = process_replacements(recipe, count, legacy.returns)
- if success == false then
- return false, err
- end
- end
- return create_recipe(legacy)
- end
- local function process_shapeless_recipe(recipe)
- local legacy = {items={},output=recipe.output}
- if recipe.replacements then
- legacy.returns = {}
- local count = {}
- for _, item in pairs(recipe.recipe) do
- count[item] = (count[item] or 0) + 1
- end
- local success, err = process_replacements(recipe, count, legacy.returns)
- if success == false then
- return false, err
- end
- end
- legacy.items = recipe.recipe
- return create_recipe(legacy)
- end
- local function process_cooking_recipe(recipe)
- local legacy = {input={}}
- legacy.output = recipe.output
- legacy.input[recipe.recipe] = 1
- legacy.input["simplecrafting_lib:heat"] = recipe.cooktime or 3
-
- if recipe.replacements then
- legacy.returns = {}
- local count = {}
- count[recipe.recipe] = 1
- local success, err = process_replacements(recipe, count, legacy.returns)
- if success == false then
- return false, err
- end
- end
- return legacy
- end
- local function process_fuel_recipe(recipe)
- local legacy = {input={}}
- legacy.input[recipe.recipe] = 1
- legacy.output = ItemStack({name="simplecrafting_lib:heat", count=recipe.burntime})
- if recipe.replacements then
- legacy.returns = {}
- for _,pair in pairs(recipe.replacements) do
- local item_name, item_quantity = get_item_and_quantity(pair[2])
- legacy.returns[item_name] = item_quantity
- end
- end
- return legacy
- end
- local already_cleared_processed = {}
- minetest.after(10, function()
- already_cleared_processed = nil
- end)
- local function safe_clear_craft(recipe_to_clear)
- local parameter_recipe = {}
- if recipe_to_clear.method == nil or recipe_to_clear.method == "normal" then
- if recipe_to_clear.width == 0 then
- parameter_recipe.type="shapeless"
- parameter_recipe.recipe = recipe_to_clear.items
- elseif recipe_to_clear.width == 1 then
- parameter_recipe.width = 1
- parameter_recipe.recipe = {
- {recipe_to_clear.items[1] or ""},
- {recipe_to_clear.items[2] or ""},
- {recipe_to_clear.items[3] or ""},
- }
- elseif recipe_to_clear.width == 2 then
- parameter_recipe.width = 2
- parameter_recipe.recipe = {
- {recipe_to_clear.items[1] or "", recipe_to_clear.items[2] or ""},
- {recipe_to_clear.items[3] or "", recipe_to_clear.items[4] or ""},
- {recipe_to_clear.items[5] or "", recipe_to_clear.items[6] or ""},
- }
- elseif recipe_to_clear.width == 3 then
- parameter_recipe.width = 3
- parameter_recipe.recipe = {
- {recipe_to_clear.items[1] or "", recipe_to_clear.items[2] or "", recipe_to_clear.items[3] or ""},
- {recipe_to_clear.items[4] or "", recipe_to_clear.items[5] or "", recipe_to_clear.items[6] or ""},
- {recipe_to_clear.items[7] or "", recipe_to_clear.items[8] or "", recipe_to_clear.items[9] or ""},
- }
- end
- elseif recipe_to_clear.type == "cooking" then
- parameter_recipe.type = "cooking"
- parameter_recipe.recipe = recipe_to_clear.items[1]
- else
- minetest.log("error", "[simplecrafting_lib] safe_clear_craft was unable to parse recipe "..dump(recipe_to_clear))
- return false
- end
-
- local success, err = pcall(function()
- if not minetest.clear_craft(parameter_recipe) then
- minetest.log("warning", "[simplecrafting_lib] failed to clear recipe " .. dump(recipe_to_clear) .. "\nas parameter\n" .. dump(parameter_recipe))
- end
- end)
- if not success and err ~= "No crafting specified for input" then
- minetest.log("error", "[simplecrafting_lib] minetest.clear_craft failed with error \"" ..err.. "\" while attempting to clear craft " ..dump(recipe_to_clear))
- return false
- elseif success == true and err == false then
- minetest.log("warning", "[simplecrafting_lib] minetest.clear_craft wasn't able to find inputs for " .. dump(recipe_to_clear))
- return false
- end
- return true
- end
- local function register_legacy_recipe(legacy_recipe)
- local clear_recipe = false
- for _, filter in ipairs(simplecrafting_lib.import_filters) do
- local working_recipe = simplecrafting_lib.deep_copy(legacy_recipe)
- local craft_type, clear_this = filter(working_recipe)
- if craft_type then
- if (working_recipe.input["simplecrafting_lib:heat"]) or
- (working_recipe.output and ItemStack(working_recipe.output):get_name() == "simplecrafting_lib:heat") then
- register_heat()
- end
- simplecrafting_lib.register(craft_type, working_recipe)
- end
- clear_recipe = clear_this or clear_recipe
- end
- return clear_recipe
- end
- simplecrafting_lib.minetest_register_craft = minetest.register_craft
- local function log_failure(err, recipe)
- if log_removals then
- if err ~= nil then
- minetest.log("error", err .. "\n" .. dump(recipe))
- else
- minetest.log("error", "[simplecrafting_lib] Shapeless recipe could not be processed, likely due to nonexistent replacement items:\n" .. dump(recipe))
- end
- end
- end
- minetest.register_craft = function(recipe)
- local clear = false
- local new_recipe
- if not recipe.type then
- local err
- new_recipe, err = process_shaped_recipe(recipe)
- if new_recipe == false then
- log_failure(err, recipe)
- return
- end
- clear = register_legacy_recipe(new_recipe)
- elseif recipe.type == "shapeless" then
- local err
- new_recipe, err = process_shapeless_recipe(recipe)
- if new_recipe == false then
- log_failure(err, recipe)
- return
- end
- clear = register_legacy_recipe(new_recipe)
- elseif recipe.type == "cooking" then
- new_recipe = process_cooking_recipe(recipe)
- clear = register_legacy_recipe(new_recipe)
- elseif recipe.type == "fuel" then
- new_recipe = process_fuel_recipe(recipe)
- clear = register_legacy_recipe(new_recipe)
- end
- if not clear then
- return simplecrafting_lib.minetest_register_craft(recipe)
- else
- table.insert(already_cleared_processed, new_recipe)
- end
- end
- local function import_legacy_recipes()
-
- for _, recipe in pairs(already_cleared_processed) do
- register_legacy_recipe(recipe)
- end
-
-
- for item,_ in pairs(minetest.registered_items) do
- local crafts = minetest.get_all_craft_recipes(item)
- if crafts and item ~= "" then
- for _,legacy_recipe in pairs(crafts) do
- if legacy_recipe.method == nil or legacy_recipe.method == "normal" then
-
-
- local output, decremented_input = minetest.get_craft_result(legacy_recipe)
-
-
-
-
-
-
-
-
-
- if output.item:get_count() > 0 then
- for _, returned_item in pairs(decremented_input.items) do
- if returned_item:get_count() > 0 then
- legacy_recipe.returns = legacy_recipe.returns or {}
- legacy_recipe.returns[returned_item:get_name()] = (legacy_recipe.returns[returned_item:get_name()] or 0) + returned_item:get_count()
- end
- end
- end
- local new_recipe = create_recipe(legacy_recipe)
- if register_legacy_recipe(new_recipe) then
- if not safe_clear_craft(legacy_recipe) then
- minetest.log("warning", "[simplecrafting_lib] minetest.clear_craft wasn't able to find inputs for " .. dump(legacy_recipe) .. " for output " .. item)
- end
- table.insert(already_cleared_processed, new_recipe)
- end
- elseif legacy_recipe.method == "cooking" then
- local new_recipe = {input={}}
- new_recipe.output = legacy_recipe.output
- new_recipe.input[legacy_recipe.items[1]] = 1
- local cooked = minetest.get_craft_result({method = "cooking", width = 1, items = {legacy_recipe.items[1]}})
- new_recipe.input["simplecrafting_lib:heat"] = cooked.time
- if register_legacy_recipe(new_recipe) then
- if not safe_clear_craft(legacy_recipe) then
- minetest.log("warning", "[simplecrafting_lib] minetest.clear_craft wasn't able to find inputs for " .. dump(legacy_recipe) .. " for cooking output " .. item)
- end
- table.insert(already_cleared_processed, new_recipe)
- end
- else
- minetest.log("error", "[simplecrafting_lib] Unrecognized crafting method for legacy recipe " .. dump(legacy_recipe))
- end
- end
- end
-
-
- local fuel, afterfuel = minetest.get_craft_result({method="fuel",width=1,items={item}})
- if fuel.time ~= 0 then
- local new_recipe = {}
- new_recipe.input = {}
- new_recipe.input[item] = 1
- new_recipe.output = ItemStack({name="simplecrafting_lib:heat", count = fuel.time})
- for _, afteritem in pairs(afterfuel.items) do
- if afteritem:get_count() > 0 then
- new_recipe.returns = new_recipe.returns or {}
- new_recipe.returns[afteritem:get_name()] = (new_recipe.returns[afteritem:get_name()] or 0) + afteritem:get_count()
- end
- end
- if register_legacy_recipe(new_recipe) then
- minetest.clear_craft({type="fuel", recipe=item})
- table.insert(already_cleared_processed, new_recipe)
- end
- end
- end
- end
- simplecrafting_lib.import_filters = {}
- simplecrafting_lib.register_recipe_import_filter = function(filter_function)
- table.insert(simplecrafting_lib.import_filters, filter_function)
- import_legacy_recipes()
- end
|