Module:Crafting

From Space Station 14 Wiki
Revision as of 07:08, 9 July 2025 by Aliser (talk | contribs) (support querying a config by station display name also; hardcoded station names mapped from station IDs;)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Module documentation
View or edit this documentation (about module documentation)
Uses JSON data

Contains various methods related to crafting. Currently, this only covers item recipes using lathes.

JSON files

JSON files that are updated automatically, syncing with the upstream:


local p = {}

local crafting_stations_configs_json = mw.loadJsonData("Module:Crafting/data/auto/crafting_stations_configs.json")

-- maps IDs of crafting stations to their display names.
p.map_of_crafting_station_id_to_name = {
    ["Autolathe"] = "Autolathe",
    ["AutolatheHyperConvection"] = "Hyper Convection Autolathe",
    ["Protolathe"] = "Protolathe",
    ["ProtolatheHyperConvection"] = "Hyper Convection Protolathe",
    ["CircuitImprinter"] = "Circuit Imprinter",
    ["CircuitImprinterHyperConvection"] = "Hyper Convection Circuit Imprinter",
    ["ExosuitFabricator"] = "Exosuit Fabricator",
    ["Biofabricator"] = "Biocube Fabricator",
    ["SecurityTechFab"] = "Security TechFab",
    ["AmmoTechFab"] = "Ammo TechFab",
    ["MedicalTechFab"] = "Medical TechFab",
    ["UniformPrinter"] = "Uniform Printer",
    ["Biogenerator"] = "Biogenerator",
    ["OreProcessor"] = "Ore Processor",
    ["OreProcessorIndustrial"] = "Industrial Ore Processor",
    ["Sheetifier"] = "Sheet-Meister 2000",
    ["CutterMachine"] = "Cutter Machine",
}

-- an array of property names containing recipes in station configs.
p.availability_prop_names = {
    "staticRecipes",
    "dynamicRecipes",
    "emagStaticRecipes",
    "emagDynamicRecipes",
}

-- maps availability property names to availability.
p.map_of_availability_prop_name_to_availability = {
    ["staticRecipes"] = "static",
    ["dynamicRecipes"] = "dynamic",
    ["emagStaticRecipes"] = "emag static",
    ["emagDynamicRecipes"] = "emag dynamic",
}

-- ===========================================

local function assert_value_not_nil(value, error_message)
    if value == nil then
        if error_message == nil then
            error("value is nil")
        else
            error(error_message)
        end
    end
end

local function find_first_table_item_matching_condition(table, condition)
    for key, value in pairs(table) do
        if condition(key, value, table) then
            return value
        end
    end
end

local function find_first_table_item_key_matching_condition(table, condition)
    for key, value in pairs(table) do
        if condition(key, value, table) then
            return key
        end
    end
end

-- ===========================================

-- Searches for a crafting station config with given ID or by a station name.
-- Any casing is supported.
-- 
-- Returns found config or `nil`.
function p.find_crafting_station_config(query)
    assert_value_not_nil(query)

    local crafting_station_query_lc = string.lower(query)

    local station_id = find_first_table_item_key_matching_condition(
        p.map_of_crafting_station_id_to_name,
        function (k, v)
            return string.lower(k) == crafting_station_query_lc
                or string.lower(v) == crafting_station_query_lc
        end
    )
    if station_id == nil then
        return nil
    end

	for _, config in ipairs(crafting_stations_configs_json) do
        if config.id == station_id then
            return config
        end
    end
end

-- Returns all existing configs on crafting stations.
function p.get_all_crafting_stations_configs()
    return crafting_stations_configs_json
end

-- Searches for station configs that have given recipe ID in their recipes.
-- Optionally takes in a crafting method to narrow down the results.
-- 
-- Returns an array of results, each containing:
-- * `station_type` - crafting station type.
-- * `station_id` - crafting station ID.
-- * `availability` - recipe availability, one of: `static`, `dynamic`, `emag static` or `emag dynamic`.
-- * `recipe_id` - recipe ID.
-- 
-- **Note: This is an expensive function.**
function p.search_recipe_id(recipe_id_query, crafting_method_query)
    assert_value_not_nil(recipe_id_query)

    local res = {}

    local config_pool = crafting_method_query
        and { p.find_crafting_station_config(crafting_method_query) }
        or crafting_stations_configs_json

    for _, cfg in ipairs(config_pool) do
        for _, availabilityPropName in ipairs(p.availability_prop_names) do
            local availability = p.map_of_availability_prop_name_to_availability[availabilityPropName]
            local recipe_ids = cfg[availabilityPropName]
            if recipe_ids ~= nil then 
                for _, recipe_id in ipairs(recipe_ids) do
                    if recipe_id == recipe_id_query then
                        table.insert(res, {
                            station_type = cfg.stationType,
                            station_id = cfg.id,
                            availability = availability,
                            recipe_id = recipe_id
                        })
                    end
                end
            end
        end
    end

    return res
end

return p