1481 lines
48 KiB
Lua

-------------------------------------------------------------------------------
---Description of the module.
---@class Player
local Player = {
---single-line comment
classname = "HMPlayer"
}
local Lua_player = nil
-------------------------------------------------------------------------------
---Print message
function Player.print(...)
if Lua_player ~= nil then
Lua_player.print(table.concat({...}," "))
end
end
-------------------------------------------------------------------------------
---Load factorio player
---@param event LuaEvent
---@return Player
function Player.load(event)
Lua_player = game.players[event.player_index]
return Player
end
-------------------------------------------------------------------------------
---Load factorio player by name or first
---@param player_name string
---@return Player
function Player.try_load_by_name(player_name)
for _, player in pairs(game.players) do
if Lua_player == nil then
Lua_player = player
end
if player.name == player_name then
Lua_player = player
break
end
end
return Player
end
-------------------------------------------------------------------------------
---Set factorio player
---@param player LuaPlayer
---@return Player
function Player.set(player)
Lua_player = player
return Player
end
-------------------------------------------------------------------------------
---Get game day
---@return number, number, number, number
function Player.getGameDay()
local surface = game.surfaces[1]
local day = surface.ticks_per_day
local dusk = surface.evening-surface.dusk
local night = surface.morning-surface.evening
local dawn = surface.dawn-surface.morning
return day, day*dusk, day*night, day*dawn
end
------------------------------------------------------------------------------
---Get display sizes
---@return number, number, number
function Player.getDisplaySizes()
if Lua_player == nil or not Lua_player.valid then return 800,600,1 end
local display_resolution = Lua_player.display_resolution
local display_scale = Lua_player.display_scale
return display_resolution.width, display_resolution.height, display_scale
end
-------------------------------------------------------------------------------
---Set pipette
---@param entity any
---@return any
function Player.setPipette(entity)
if Lua_player == nil then return nil end
return Lua_player.pipette_entity(entity)
end
-------------------------------------------------------------------------------
---Get character crafting speed
---@return number
function Player.getCraftingSpeed()
if Lua_player == nil then return 0 end
return 1 + Lua_player.character_crafting_speed_modifier
end
-------------------------------------------------------------------------------
---Get main inventory
---@return any
function Player.getMainInventory()
if Lua_player == nil then return nil end
return Lua_player.get_main_inventory()
end
-------------------------------------------------------------------------------
---Begin Crafting
---@param item string
---@param count number
function Player.beginCrafting(item, count)
if Lua_player == nil then return nil end
local filters = {{filter = "has-product-item", elem_filters = {{filter = "name", name = item}}}}
local recipes = game.get_filtered_recipe_prototypes(filters)
if recipes ~= nil and table.size(recipes) > 0 then
local first_recipe = Model.firstRecipe(recipes)
local craft = {count=math.ceil(count),recipe=first_recipe.name,silent=false}
Lua_player.begin_crafting(craft)
else
Player.print("No recipe found for this craft!")
end
end
-------------------------------------------------------------------------------
---Get smart tool
---@return LuaItemStack
function Player.getSmartTool(entities)
if Lua_player == nil then
return nil
end
local script_inventory = game.create_inventory(1)
local tool_stack = script_inventory[1]
tool_stack.set_stack({name="blueprint"})
tool_stack.set_blueprint_entities(entities)
tool_stack.label = "Helmod Smart Tool"
Lua_player.add_to_clipboard(tool_stack)
Lua_player.activate_paste()
script_inventory.destroy()
return tool_stack
end
-------------------------------------------------------------------------------
---Set smart tool
---@param recipe table
---@param type string
---@param index number
---@return any
function Player.setSmartTool(recipe, type, index)
if Lua_player == nil or recipe == nil then
return nil
end
local factory = recipe[type]
if index ~= nil then
factory = factory[index]
end
local modules = {}
for name,value in pairs(factory.modules or {}) do
modules[name] = value
end
local entity = {
entity_number = 1,
name = factory.name,
position = {0, 0},
items = modules
}
if type == "factory" then
entity.recipe = recipe.name
end
Player.getSmartTool({entity})
end
-------------------------------------------------------------------------------
---Is valid sprite path
---@param sprite_path string
---@return boolean
function Player.is_valid_sprite_path(sprite_path)
if Lua_player == nil then return false end
return Lua_player.gui.is_valid_sprite_path(sprite_path)
end
-------------------------------------------------------------------------------
---Return factorio player
---@return LuaPlayer
function Player.native()
return Lua_player
end
-------------------------------------------------------------------------------
---Return admin player
---@return boolean
function Player.isAdmin()
return Lua_player.admin
end
-------------------------------------------------------------------------------
---Get gui
---@param location string
---@return LuaGuiElement
function Player.getGui(location)
return Lua_player.gui[location]
end
-------------------------------------------------------------------------------
---Return force's player
---@return LuaForce
function Player.getForce()
return Lua_player.force
end
-------------------------------------------------------------------------------
---Sets the toggle state of the shotcut tool/icon
---@param state boolean
function Player.setShortcutState(state)
if Lua_player ~= nil then
Lua_player.set_shortcut_toggled("helmod-shortcut", state)
end
end
-------------------------------------------------------------------------------
---Return item type
---@param element LuaPrototype
---@return string
function Player.getItemIconType(element)
local item = Player.getItemPrototype(element.name)
if item ~= nil then
return "item"
end
local fluid = Player.getFluidPrototype(element.name)
if fluid ~= nil then
return "fluid"
else
return "item"
end
end
-------------------------------------------------------------------------------
---Return localised name
---@param element LuaPrototype
---@return string|table
function Player.getLocalisedName(element)
local localisedName = element.name
if element.type ~= nil then
if element.type == "recipe" or element.type == "recipe-burnt" then
local recipe = Player.getPlayerRecipe(element.name)
if recipe ~= nil then
localisedName = recipe.localised_name
end
elseif element.type == "technology" then
local technology = Player.getPlayerTechnology(element.name)
if technology ~= nil then
localisedName = technology.localised_name
end
elseif element.type == "entity" or element.type == "resource" then
local item = Player.getEntityPrototype(element.name)
if item ~= nil then
localisedName = item.localised_name
end
elseif element.type == 0 or element.type == "item" then
local item = Player.getItemPrototype(element.name)
if item ~= nil then
localisedName = item.localised_name
end
elseif element.type == 1 or element.type == "fluid" then
local item = Player.getFluidPrototype(element.name)
if item ~= nil then
if element.temperature then
localisedName = {"helmod_common.fluid-temperature", item.localised_name, element.temperature}
elseif (element.minimum_temperature and (element.minimum_temperature >= -1e300)) and (element.maximum_temperature and (element.maximum_temperature <= 1e300)) then
localisedName = {"helmod_common.fluid-temperature-range", item.localised_name, element.minimum_temperature, element.maximum_temperature}
elseif (element.minimum_temperature and (element.minimum_temperature >= -1e300)) then
localisedName = {"helmod_common.fluid-temperature-min", item.localised_name, element.minimum_temperature}
elseif (element.maximum_temperature and (element.maximum_temperature <= 1e300)) then
localisedName = {"helmod_common.fluid-temperature-max", item.localised_name, element.maximum_temperature}
else
localisedName = item.localised_name
end
end
elseif element.type == "energy" then
localisedName = {string.format("helmod_common.%s", element.name)}
end
end
return localisedName
end
-------------------------------------------------------------------------------
---Return localised name
---@param prototype LuaPrototype
---@return string|table
function Player.getRecipeLocalisedName(prototype)
local element = Player.getPlayerRecipe(prototype.name)
if element ~= nil then
return element.localised_name
end
return prototype.name
end
-------------------------------------------------------------------------------
---Return localised name
---@param prototype LuaPrototype
---@return string|table
function Player.getTechnologyLocalisedName(prototype)
local element = Player.getPlayerTechnology(prototype.name)
if element ~= nil then
return element.localised_name
end
return element.name
end
-------------------------------------------------------------------------------
---Return recipes
---@return table
function Player.getPlayerRecipes()
if Lua_player ~= nil then
return Player.getForce().recipes
end
return {}
end
-------------------------------------------------------------------------------
---Return recipe prototypes
---@return table
function Player.getRecipes()
return game.recipe_prototypes
end
-------------------------------------------------------------------------------
---Return technologie prototypes
---@param filters table
---@return table
function Player.getTechnologies(filters)
if filters ~= nil then
return game.get_filtered_technology_prototypes(filters)
end
return game.technology_prototypes
end
-------------------------------------------------------------------------------
---Return technology prototype
---@param name string
---@return LuaTechnologyPrototype
function Player.getTechnology(name)
return game.technology_prototypes[name]
end
-------------------------------------------------------------------------------
---Return technologies
---@return table
function Player.getPlayerTechnologies()
if Lua_player ~= nil then
local technologies = {}
for _,technology in pairs(Player.getForce().technologies) do
technologies[technology.name] = technology
end
return technologies
end
return {}
end
-------------------------------------------------------------------------------
---Return technology
---@param name string
---@return LuaTechnology
function Player.getPlayerTechnology(name)
if Lua_player ~= nil then
local technology = Player.getForce().technologies[name]
return technology
end
return nil
end
-------------------------------------------------------------------------------
---Return rule
---@param rule_name string
---@return table, table --rules_included, rules_excluded
function Player.getRules(rule_name)
local rules_included = {}
local rules_excluded = {}
for rule_id, rule in spairs(Model.getRules(), function(t,a,b) return t[b].index > t[a].index end) do
if game.active_mods[rule.mod] and rule.name == rule_name then
if rule.excluded then
if rules_excluded[rule.category] == nil then rules_excluded[rule.category] = {} end
if rules_excluded[rule.category][rule.type] == nil then rules_excluded[rule.category][rule.type] = {} end
rules_excluded[rule.category][rule.type][rule.value] = true
else
if rules_included[rule.category] == nil then rules_included[rule.category] = {} end
if rules_included[rule.category][rule.type] == nil then rules_included[rule.category][rule.type] = {} end
rules_included[rule.category][rule.type][rule.value] = true
end
end
end
return rules_included, rules_excluded
end
-------------------------------------------------------------------------------
---Return rule
---@param check boolean
---@param rules table
---@param category string
---@param lua_entity table
---@param included boolean
---@return boolean
function Player.checkRules(check, rules, category, lua_entity, included)
if rules[category] then
if rules[category]["entity-name"] and (rules[category]["entity-name"]["all"] or rules[category]["entity-name"][lua_entity.name]) then
check = included
elseif rules[category]["entity-type"] and (rules[category]["entity-type"]["all"] or rules[category]["entity-type"][lua_entity.type]) then
check = included
elseif rules[category]["entity-group"] and (rules[category]["entity-group"]["all"] or rules[category]["entity-group"][lua_entity.group.name]) then
check = included
elseif rules[category]["entity-subgroup"] and (rules[category]["entity-subgroup"]["all"] or rules[category]["entity-subgroup"][lua_entity.subgroup.name]) then
check = included
end
end
return check
end
-------------------------------------------------------------------------------
---Check factory limitation module
---@param module table
---@param lua_recipe RecipeData
---@return boolean
function Player.checkFactoryLimitationModule(module, lua_recipe)
local factory = lua_recipe.factory
if factory.module_slots == 0 then
return false
end
local rules_included, rules_excluded = Player.getRules("module-limitation")
local model_filter_factory_module = User.getModGlobalSetting("model_filter_factory_module")
local allowed = true
local check_not_bypass = true
local prototype = RecipePrototype(lua_recipe)
local category = prototype:getCategory()
if prototype:getType() == "rocket" then
local rocket_part_recipe = Player.getRocketPartRecipe(lua_recipe.factory)
if rocket_part_recipe and category == rocket_part_recipe.category and lua_recipe.name ~= rocket_part_recipe.name then
local rocket_recipe = RecipePrototype(rocket_part_recipe.name)
if rocket_recipe.lua_prototype ~= nil then
rocket_recipe.name = rocket_part_recipe.name
rocket_recipe.factory = lua_recipe.factory
allowed = Player.checkFactoryLimitationModule(module, rocket_recipe)
return allowed
end
return true
end
end
if rules_excluded[category] == nil then
category = "standard"
end
check_not_bypass = Player.checkRules(check_not_bypass, rules_excluded, category, EntityPrototype(factory.name):native(), false)
if table.size(module.limitations) > 0 and check_not_bypass and model_filter_factory_module == true then
allowed = false
for _, recipe_name in pairs(module.limitations) do
if lua_recipe.name == recipe_name then
allowed = true
end
end
end
local allowed_effects = EntityPrototype(factory):getAllowedEffects()
if allowed_effects ~= nil and model_filter_factory_module == true then
for _, effect in pairs({"speed", "productivity", "consumption", "pollution"}) do
if (Player.getModuleBonus(module.name, effect) ~= 0) and (not allowed_effects[effect]) then
allowed = false
end
end
end
return allowed
end
-------------------------------------------------------------------------------
---Check beacon limitation module
---@param beacon FactoryData
---@param recipe RecipeData
---@param module LuaItemPrototype
---@return boolean
function Player.checkBeaconLimitationModule(beacon, recipe, module)
local allowed = true
local model_filter_beacon_module = User.getModGlobalSetting("model_filter_beacon_module")
if table.size(module.limitations) > 0 and model_filter_beacon_module == true and recipe.type ~= "resource" then
allowed = false
for _, module_recipe_name in pairs(module.limitations) do
if module_recipe_name == recipe.name then
allowed = true
end
end
end
local allowed_effects = EntityPrototype(beacon):getAllowedEffects()
if allowed_effects ~= nil and model_filter_beacon_module == true then
for _, effect in pairs({"speed", "productivity", "consumption", "pollution"}) do
if (Player.getModuleBonus(module.name, effect) ~= 0) and (not allowed_effects[effect]) then
allowed = false
end
end
end
if beacon.module_slots == 0 then
allowed = false
end
return allowed
end
-------------------------------------------------------------------------------
---Return list of productions
---@param category string
---@param lua_recipe table
---@return table
function Player.getProductionsCrafting(category, lua_recipe)
local productions = {}
local rules_included, rules_excluded = Player.getRules("production-crafting")
if category == "crafting-handonly" then
productions["character"] = game.entity_prototypes["character"]
elseif lua_recipe.name ~= nil and category == "fluid" then
for key, lua_entity in pairs(Player.getOffshorePumps(lua_recipe.name)) do
productions[lua_entity.name] = lua_entity
end
else
for key, lua_entity in pairs(Player.getProductionMachines()) do
local check = false
if category ~= nil then
if not(rules_included[category]) then
---standard recipe
if lua_entity.crafting_categories ~= nil and lua_entity.crafting_categories[category] then
local recipe_ingredient_count = RecipePrototype(lua_recipe, "recipe"):getIngredientCount()
local factory_ingredient_count = EntityPrototype(lua_entity):getIngredientCount()
--- check ingredient limitation
if factory_ingredient_count >= recipe_ingredient_count then
check = true
end
---resolve rule excluded
check = Player.checkRules(check, rules_excluded, "standard", lua_entity, false)
end
else
---resolve rule included
check = Player.checkRules(check, rules_included, category, lua_entity, true)
---resolve rule excluded
check = Player.checkRules(check, rules_excluded, category, lua_entity, false)
end
else
--- take all production if category is nil
if lua_entity.group ~= nil and lua_entity.group.name == "production" then
check = true
end
end
---resource filter
if check then
if lua_recipe.name ~= nil then
local lua_entity_filter = Player.getEntityPrototype(lua_recipe.name)
if lua_entity_filter ~= nil then
if lua_entity.resource_categories ~= nil and not(lua_entity.resource_categories[lua_entity_filter.resource_category]) then
check = false
elseif lua_entity_filter.mineable_properties and lua_entity_filter.mineable_properties.required_fluid then
local fluidboxes = EntityPrototype(lua_entity):getFluidboxPrototypes()
if #fluidboxes == 0 then
check = false
end
end
end
end
end
---ok to add entity
if check then
productions[lua_entity.name] = lua_entity
end
end
end
return productions
end
-------------------------------------------------------------------------------
---Excludes entities that are placed only by a hidden item
---@param entities table
---@return table
function Player.ExcludePlacedByHidden(entities)
local results = {}
for entity_name, entity in pairs(entities) do
local item_filters = {}
for _, item in pairs(entity.items_to_place_this or {}) do
if type(item) == "string" then
table.insert(item_filters, {filter="name", name=item, mode="or"})
elseif item.name then
table.insert(item_filters, {filter="name", name=item.name, mode="or"})
end
end
local show = false
if #item_filters == 0 then
-- Has no items to place it. Probably placed by script.
-- e.g. Numal reef from Py
show = true
else
local items = game.get_filtered_item_prototypes(item_filters)
for _, item in pairs(items) do
if not item.has_flag("hidden") then
show = true
break
end
end
end
if show == true then
results[entity_name] = entity
end
end
return results
end
-------------------------------------------------------------------------------
---Return list of modules
---@return table
function Player.getModules()
local items = {}
local filters = {}
table.insert(filters,{filter="type",type="module",mode="or"})
table.insert(filters,{filter="flag",flag="hidden",mode="and", invert=true})
for _,item in pairs(game.get_filtered_item_prototypes(filters)) do
table.insert(items,item)
end
return items
end
-------------------------------------------------------------------------------
---Return list of production machines
---@return table
function Player.getProductionMachines()
local cache_machines = Cache.getData(Player.classname, "list_machines")
if cache_machines ~= nil then
return cache_machines
end
local filters = {}
table.insert(filters, {filter="crafting-machine", mode="or"})
table.insert(filters, {filter="hidden", mode="and", invert=true})
table.insert(filters, {filter="type", type="lab", mode="or"})
table.insert(filters, {filter="hidden", mode="and", invert=true})
table.insert(filters, {filter="type", type="mining-drill", mode="or"})
table.insert(filters, {filter="hidden", mode="and", invert=true})
table.insert(filters, {filter="type", type="rocket-silo", mode="or"})
table.insert(filters, {filter="hidden", mode="and", invert=true})
local prototypes = game.get_filtered_entity_prototypes(filters)
prototypes = Player.ExcludePlacedByHidden(prototypes)
local list_machines = {}
for prototype_name, lua_prototype in pairs(prototypes) do
local machine = {name=lua_prototype.name, group=(lua_prototype.group or {}).name, subgroup=(lua_prototype.subgroup or {}).name, type=lua_prototype.type, order=lua_prototype.order, crafting_categories=lua_prototype.crafting_categories, resource_categories=lua_prototype.resource_categories}
table.insert(list_machines, machine)
end
Cache.setData(Player.classname, "list_machines", list_machines)
return list_machines
end
-------------------------------------------------------------------------------
---Return list of energy machines
---@return table
function Player.getEnergyMachines()
local machines = {}
local filters = {}
for _, type in pairs({"generator", "solar-panel", "accumulator", "reactor", "burner-generator", "electric-energy-interface"}) do
table.insert(filters, {filter="type", mode="or", invert=false, type=type})
table.insert(filters, {filter="hidden", mode="and", invert=true})
table.insert(filters, {filter="type", mode="or", invert=false, type=type})
table.insert(filters, {filter="flag", flag="player-creation", mode="and"})
end
for entity_name, entity in pairs(game.get_filtered_entity_prototypes(filters)) do
machines[entity_name] = entity
end
machines = Player.ExcludePlacedByHidden(machines)
return machines
end
-------------------------------------------------------------------------------
---Return list of boilers
---@param fluid_name string
---@return table
function Player.getBoilers(fluid_name)
local filters = {}
table.insert(filters, {filter="type", type="boiler", mode="or"})
table.insert(filters, {filter="hidden", mode="and", invert=true})
table.insert(filters, {filter="type", type="boiler", mode="or"})
table.insert(filters, {filter="flag", flag="player-creation", mode="and"})
local prototypes = game.get_filtered_entity_prototypes(filters)
prototypes = Player.ExcludePlacedByHidden(prototypes)
if fluid_name == nil then
return prototypes
else
local boilers = {}
for boiler_name, boiler in pairs(prototypes) do
for _, fluidbox in pairs(boiler.fluidbox_prototypes) do
if (fluidbox.production_type == "output") and fluidbox.filter and (fluidbox.filter.name == fluid_name) then
boilers[boiler_name] = boiler
break
end
end
end
return boilers
end
end
-------------------------------------------------------------------------------
---Return table of boiler recipes
---@return table
function Player.getBoilersForRecipe(recipe_prototype)
local boilers = {}
for boiler_name, boiler in pairs(Player.getBoilers()) do
---Check temperature
if boiler.target_temperature ~= recipe_prototype.output_fluid_temperature then
goto continue
end
---Check input fluid
local input_fluid
local fluidbox = boiler.fluidbox_prototypes[1]
if fluidbox.filter then
input_fluid = fluidbox.filter.name
end
if input_fluid ~= recipe_prototype.input_fluid_name then
goto continue
end
---Check output fluid
local output_fluid
for _, fluidbox in pairs(boiler.fluidbox_prototypes) do
if fluidbox.filter and fluidbox.production_type == "output" then
output_fluid = fluidbox.filter.name
end
end
if output_fluid ~= recipe_prototype.output_fluid_name then
goto continue
end
boilers[boiler_name] = boiler
::continue::
end
return boilers
end
-------------------------------------------------------------------------------
---Return list of Offshore-Pump
---@param fluid_name string
---@return table
function Player.getOffshorePumps(fluid_name)
local filters = {}
table.insert(filters, {filter="type", type="offshore-pump", mode="or"})
local entities = game.get_filtered_entity_prototypes(filters)
local offshore_pump = {}
for key, entity in pairs(entities) do
if entity.fluid.name == fluid_name then
for _, fluidbox in pairs(entity.fluidbox_prototypes) do
if #fluidbox.pipe_connections > 0 then
offshore_pump[key] = entity
break
end
end
end
end
return offshore_pump
end
-------------------------------------------------------------------------------
---Return module bonus (default return: bonus = 0 )
---@param module string
---@param effect string
---@return number
function Player.getModuleBonus(module, effect)
if module == nil then return 0 end
local bonus = 0
---search module
local module = Player.getItemPrototype(module)
if module ~= nil and module.module_effects ~= nil and module.module_effects[effect] ~= nil then
bonus = module.module_effects[effect].bonus
end
return bonus
end
-------------------------------------------------------------------------------
---Return recipe prototype
---@param name string
---@return LuaRecipe
function Player.getRecipe(name)
if name == nil then return nil end
return game.recipe_prototypes[name]
end
-------------------------------------------------------------------------------
---Return recipe
---@param name string
---@return LuaRecipe
function Player.getPlayerRecipe(name)
if Lua_player ~= nil then
return Player.getForce().recipes[name]
end
return nil
end
function Player.buildResourceRecipe(entity_prototype)
local prototype = entity_prototype:native()
if prototype == nil then return nil end
local ingredients = {}
if entity_prototype:getMineableMiningFluidRequired() then
local fluid_ingredient = {name=entity_prototype:getMineableMiningFluidRequired(), type="fluid", amount=entity_prototype:getMineableMiningFluidAmount()}
table.insert(ingredients, fluid_ingredient)
end
local recipe = {}
recipe.category = "extraction-machine"
recipe.enabled = true
recipe.energy = 1
recipe.force = {}
recipe.group = {name="helmod", order="zzzz"}
recipe.subgroup = {name="helmod-resource", order="aaaa"}
recipe.hidden = false
if prototype then
if prototype.flags ~= nil then
recipe.hidden = prototype.flags["hidden"] or false
end
recipe.localised_description = prototype.localised_description
recipe.localised_name = prototype.localised_name
recipe.name = prototype.name
end
recipe.ingredients = ingredients
recipe.products = entity_prototype:getMineableMiningProducts()
recipe.prototype = {}
recipe.valid = true
return recipe
end
-------------------------------------------------------------------------------
---Return resource recipes
---@return table
function Player.getResourceRecipes()
local recipes = {}
for key, prototype in pairs(game.entity_prototypes) do
if prototype.name ~= nil and prototype.resource_category ~= nil then
local recipe = Player.buildResourceRecipe(EntityPrototype(prototype))
if recipe ~= nil then
recipes[recipe.name] = recipe
end
end
end
return recipes
end
-------------------------------------------------------------------------------
---Return resource recipe
---@param name string
---@return table
function Player.getResourceRecipe(name)
local entity_prototype = EntityPrototype(name)
local recipe = Player.buildResourceRecipe(entity_prototype)
return recipe
end
-------------------------------------------------------------------------------
---Return energy recipe
---@param name string
---@return table
function Player.getEnergyRecipe(name)
local entity_prototype = EntityPrototype(name)
local prototype = entity_prototype:native()
local recipe = {}
recipe.category = "energy"
recipe.enabled = true
recipe.energy = 1
recipe.force = {}
recipe.group = {name="helmod", order="zzzz"}
recipe.subgroup = {name="helmod-energy", order="dddd"}
recipe.hidden = false
if prototype ~= nil and prototype.flags ~= nil then
recipe.hidden = prototype.flags["hidden"] or false
end
recipe.ingredients = {}
recipe.products = {}
recipe.localised_description = prototype.localised_description
recipe.localised_name = prototype.localised_name
recipe.name = prototype.name
recipe.prototype = {}
recipe.valid = true
return recipe
end
-------------------------------------------------------------------------------
---Return table of fluid recipes
---@return table
function Player.getFluidRecipes()
local recipes = {}
---Offshore pumps
local filters = {}
table.insert(filters, {filter="type", type="offshore-pump", mode="or"})
local entities = game.get_filtered_entity_prototypes(filters)
for key, entity in pairs(entities) do
for _, fluidbox in pairs(entity.fluidbox_prototypes) do
if #fluidbox.pipe_connections > 0 then
local recipe = Player.buildFluidRecipe(entity.fluid.name, {}, nil)
recipe.subgroup = {name="helmod-fluid", order="bbbb"}
if not recipes[entity.fluid.name] then
recipes[entity.fluid.name] = recipe
end
if entity.has_flag("hidden") then
recipes[entity.fluid.name].hidden = true
end
end
end
end
return recipes
end
-------------------------------------------------------------------------------
---Return recipe
---@param name string
---@return table
function Player.getFluidRecipe(name)
local recipes = Player.getFluidRecipes()
return recipes[name]
end
-------------------------------------------------------------------------------
---Return table of boiler recipes
---@return table
function Player.getBoilerRecipes()
local recipes = {}
---Boilers
local boilers = Player.getBoilers()
for boiler_name, boiler in pairs(boilers) do
local input_fluid
local output_fluid
local fluidbox = boiler.fluidbox_prototypes[1]
if fluidbox.filter then
input_fluid = fluidbox.filter.name
end
for _, fluidbox in pairs(boiler.fluidbox_prototypes) do
if fluidbox.filter and fluidbox.production_type == "output" then
output_fluid = fluidbox.filter.name
end
end
if input_fluid ~= nil and output_fluid ~= nil then
local ingredients = {{name=input_fluid, type="fluid", amount=1}}
local fluid_prototype = FluidPrototype(output_fluid)
local recipe = Player.buildFluidRecipe(fluid_prototype, ingredients, boiler.target_temperature)
recipe.subgroup = {name="helmod-boiler", order="cccc"}
recipe.input_fluid_name = input_fluid
recipe.output_fluid_name = output_fluid
recipe.output_fluid_temperature = boiler.target_temperature
if not recipes[recipe.name] then
recipes[recipe.name] = recipe
end
if boiler.has_flag("hidden") then
recipes[recipe.name].hidden = true
end
end
end
return recipes
end
-------------------------------------------------------------------------------
---Return recipe
---@param name string
---@return table
function Player.getBoilerRecipe(name)
local recipes = Player.getBoilerRecipes()
return recipes[name]
end
-------------------------------------------------------------------------------
---Return recipe
---@param ingredients table
---@param fluid string|table
---@param temperature number
---@return table
function Player.buildFluidRecipe(fluid, ingredients, temperature)
local fluid_prototype
if type(fluid) == "string" then
fluid_prototype = FluidPrototype(fluid)
else
fluid_prototype = fluid
end
local prototype = fluid_prototype:native()
local products = {{name=prototype.name, type="fluid", amount=1, temperature=temperature}}
local recipe = {}
recipe.enabled = true
recipe.energy = 1
recipe.force = {}
recipe.group = {name="helmod", order="zzzz"}
recipe.subgroup = {}
recipe.hidden = false
recipe.ingredients = ingredients
recipe.products = products
recipe.localised_description = prototype.localised_description
recipe.localised_name = prototype.localised_name
if temperature ~= nil then
recipe.name = string.format("%s#%s", prototype.name, temperature)
else
recipe.name = prototype.name
end
if #ingredients > 0 then
recipe.name = string.format("%s->%s", ingredients[1].name, recipe.name)
end
recipe.category = recipe.name
recipe.prototype = {}
recipe.valid = true
return recipe
end
function Player.getRocketPartRecipe(factory)
-- Get rocket silos
local silos = {}
if factory and factory.name then
silos = {game.entity_prototypes[factory.name]}
else
local entity_filters = {
{filter = "type", invert = false, mode = "and", type = "rocket-silo"},
{filter = "hidden", invert = true, mode = "and"},
}
silos = game.get_filtered_entity_prototypes(entity_filters)
end
-- Get rocket silo fixed recipes
local rocket_part_recipes = {}
for _, silo_prototype in pairs(silos) do
if silo_prototype.fixed_recipe then
table.insert(rocket_part_recipes, game.recipe_prototypes[silo_prototype.fixed_recipe])
end
end
if #rocket_part_recipes == 0 then
return nil
else
return rocket_part_recipes[1]
end
end
function Player.buildRocketRecipe(prototype)
if prototype == nil then return nil end
local products = prototype.rocket_launch_products
local ingredients = {}
local item_prototype = ItemPrototype(prototype.name)
local stack_size = item_prototype:stackSize()
table.insert(ingredients, {name=prototype.name, type="item", amount=1, constant=true})
local recipe = {}
recipe.category = Player.getRocketPartRecipe().category
recipe.enabled = true
recipe.energy = 1
recipe.force = {}
recipe.group = {name="helmod", order="zzzz"}
recipe.subgroup = {name="helmod-rocket", order="eeee"}
recipe.hidden = false
recipe.ingredients = ingredients
for key, product in pairs(products) do
local product_prototype = ItemPrototype(product.name)
local i=0
end
recipe.products = products
recipe.localised_description = prototype.localised_description
recipe.localised_name = prototype.localised_name
recipe.name = prototype.name
recipe.prototype = {}
recipe.valid = true
return recipe
end
-------------------------------------------------------------------------------
---Return table of recipe
---@return table
function Player.getRocketRecipes()
local recipes = {}
if Player.getRocketPartRecipe() ~= nil then
for key, item_prototype in pairs(Player.getItemPrototypes()) do
if item_prototype.rocket_launch_products ~= nil and table.size(item_prototype.rocket_launch_products) > 0 then
local recipe = Player.buildRocketRecipe(item_prototype)
recipes[recipe.name] = recipe
end
end
end
return recipes
end
-------------------------------------------------------------------------------
---Return recipe
---@param name string
---@return table
function Player.getRocketRecipe(name)
local item_prototype = ItemPrototype(name)
local prototype = item_prototype:native()
local recipe = Player.buildRocketRecipe(prototype)
return recipe
end
-------------------------------------------------------------------------------
---Return recipe
---@param name string
---@return table
function Player.getBurntRecipe(name)
local recipe_prototype = Player.getRecipe(name)
local recipe = {}
recipe.category = recipe_prototype.category
recipe.enabled = true
recipe.energy = recipe_prototype.energy
recipe.force = {}
recipe.group = {name="helmod", order="zzzz"}
recipe.subgroup = {name="helmod-recipe-burnt", order="ffff"}
recipe.hidden = false
recipe.ingredients = recipe_prototype.ingredients
recipe.products = recipe_prototype.products
recipe.localised_description = recipe_prototype.localised_description
recipe.localised_name = recipe_prototype.localised_name
recipe.name = recipe_prototype.name
recipe.prototype = {}
recipe.valid = true
recipe.hidden_from_player_crafting = recipe_prototype.hidden_from_player_crafting
return recipe
end
-------------------------------------------------------------------------------
---Return list of recipes
---@param element_name string
---@param by_ingredient boolean
---@return table
function Player.searchRecipe(element_name, by_ingredient)
local recipes = {}
---recherche dans les produits des recipes
for key, recipe in pairs(Player.getPlayerRecipes()) do
local elements = recipe.products or {}
if by_ingredient == true then
elements = recipe.ingredients or {}
end
for k, element in pairs(elements) do
if element.name == element_name then
table.insert(recipes,{name=recipe.name, type="recipe"})
break
end
end
end
---recherche dans les resource
for key, resource in pairs(Player.getResources()) do
local elements = EntityPrototype(resource):getMineableMiningProducts()
for key, element in pairs(elements) do
if element.name == element_name then
table.insert(recipes,{name=resource.name, type="resource"})
break
end
end
end
---recherche dans les fluids
for key, recipe in pairs(Player.getFluidRecipes()) do
if recipe.name == element_name then
table.insert(recipes, {name=recipe.name, type="fluid"})
end
end
for key, recipe in pairs(Player.getBoilerRecipes()) do
if recipe.name == element_name then
table.insert(recipes, {name=recipe.name, type="boiler"})
end
end
return recipes
end
-------------------------------------------------------------------------------
---Return entity prototypes
---@param filters table --{{filter="type", mode="or", invert=false type="transport-belt"}}
---@return table
function Player.getEntityPrototypes(filters)
if filters ~= nil then
return game.get_filtered_entity_prototypes(filters)
end
return game.entity_prototypes
end
-------------------------------------------------------------------------------
---Return entity prototype types
---@return table
function Player.getEntityPrototypeTypes()
local types = {}
for _,entity in pairs(game.entity_prototypes) do
local type = entity.type
types[type] = true
end
return types
end
-------------------------------------------------------------------------------
---Return entity prototype
---@param name string
---@return LuaEntityPrototype
function Player.getEntityPrototype(name)
if name == nil then return nil end
return game.entity_prototypes[name]
end
-------------------------------------------------------------------------------
---Return beacon production
---@return table
function Player.getProductionsBeacon()
local items = {}
local filters = {}
table.insert(filters,{filter="type",type="beacon",mode="or"})
table.insert(filters,{filter="hidden",invert=true,mode="and"})
for _,item in pairs(game.get_filtered_entity_prototypes(filters)) do
table.insert(items,item)
end
return items
end
-------------------------------------------------------------------------------
---Return resources list
---@return table
function Player.getResources()
local cache_resources = Cache.getData(Player.classname, "resources")
if cache_resources ~= nil then return cache_resources end
local items = {}
for _,item in pairs(game.entity_prototypes) do
if item.name ~= nil and item.resource_category ~= nil then
table.insert(items,item)
end
end
Cache.setData(Player.classname, "resources", items)
return items
end
-------------------------------------------------------------------------------
---Return item prototypes
---@param filters table --{{filter="fuel-category", mode="or", invert=false,["fuel-category"]="chemical"}}
---@return table
function Player.getItemPrototypes(filters)
if filters ~= nil then
return game.get_filtered_item_prototypes(filters)
end
return game.item_prototypes
end
-------------------------------------------------------------------------------
---Return item prototype types
---@return table
function Player.getItemPrototypeTypes()
local types = {}
for _,entity in pairs(game.item_prototypes) do
local type = entity.type
types[type] = true
end
return types
end
-------------------------------------------------------------------------------
---Return item prototype
---@param name string
---@return LuaItemPrototype
function Player.getItemPrototype(name)
if name == nil then return nil end
return game.item_prototypes[name]
end
-------------------------------------------------------------------------------
---Return fluid prototypes
---@param filters table --{{filter="type", mode="or", invert=false type="transport-belt"}}
---@return table
function Player.getFluidPrototypes(filters)
if filters ~= nil then
return game.get_filtered_fluid_prototypes(filters)
end
return game.fluid_prototypes
end
-------------------------------------------------------------------------------
---Return fluid prototype types
---@return table
function Player.getFluidPrototypeTypes()
local types = {}
for _,entity in pairs(game.fluid_prototypes) do
local type = entity.type
types[type] = true
end
return types
end
-------------------------------------------------------------------------------
---Return fluid prototype subgroups
---@return table
function Player.getFluidPrototypeSubgroups()
local types = {}
for _,entity in pairs(game.fluid_prototypes) do
local type = entity.subgroup.name
types[type] = true
end
return types
end
-------------------------------------------------------------------------------
---Return fluid prototype
---@param name string
---@return LuaFluidPrototype
function Player.getFluidPrototype(name)
if name == nil then return nil end
return game.fluid_prototypes[name]
end
-------------------------------------------------------------------------------
---Return fluid fuel prototype
---@return table
function Player.getFluidFuelPrototypes()
local filters = {}
table.insert(filters, {filter = "hidden", invert = true, mode = "and"})
table.insert(filters, {filter = "fuel-value", mode= "and", invert = false, comparison = ">", value = 0})
local items = {}
for _, fluid in spairs(Player.getFluidPrototypes(filters), function(t,a,b) return t[b].fuel_value > t[a].fuel_value end) do
table.insert(items, FluidPrototype(fluid))
end
return items
end
-------------------------------------------------------------------------------
---Return items logistic
---@param type string --belt, container or transport
---@return table
function Player.getItemsLogistic(type)
local filters = {}
if type == "inserter" then
filters = {{filter="type", mode="or", invert=false, type="inserter"}}
elseif type == "belt" then
filters = {{filter="type", mode="or", invert=false, type="transport-belt"}}
elseif type == "container" then
filters = {{filter="type", mode="or", invert=false, type="container"}, {filter="minable", mode="and", invert=false}, {filter="type", mode="or", invert=false, type="logistic-container"}, {filter="minable", mode="and", invert=false}}
elseif type == "transport" then
filters = {{filter="type", mode="or", invert=false, type="cargo-wagon"}, {filter="type", mode="or", invert=false, type="logistic-robot"}, {filter="type", mode="or", invert=false, type="car"}}
end
return Player.getEntityPrototypes(filters)
end
-------------------------------------------------------------------------------
---Return default item logistic
---@param type string --belt, container or transport
---@return table
function Player.getDefaultItemLogistic(type)
local default = User.getParameter(string.format("items_logistic_%s", type))
if default == nil then
local logistics = Player.getItemsLogistic(type)
if logistics ~= nil then
default = first(logistics).name
User.setParameter(string.format("items_logistic_%s", type), default)
end
end
return default
end
-------------------------------------------------------------------------------
---Return fluids logistic
---@param type string --pipe, container or transport
---@return table
function Player.getFluidsLogistic(type)
local filters = {}
if type == "pipe" then
filters = {{filter="type", mode="or", invert=false, type="pipe"}}
elseif type == "container" then
filters = {{filter="type", mode="or", invert=false, type="storage-tank"}, {filter="minable", mode="and", invert=false}}
elseif type == "transport" then
filters = {{filter="type", mode="or", invert=false, type="fluid-wagon"}}
end
return Player.getEntityPrototypes(filters)
end
-------------------------------------------------------------------------------
---Return default fluid logistic
---@param type string --pipe, container or transport
---@return table
function Player.getDefaultFluidLogistic(type)
local default = User.getParameter(string.format("fluids_logistic_%s", type))
if default == nil then
local logistics = Player.getFluidsLogistic(type)
if logistics ~= nil then
default = first(logistics).name
User.setParameter(string.format("fluids_logistic_%s", type), default)
end
end
return default
end
-------------------------------------------------------------------------------
---Return number
---@param number string
---@return number
function Player.parseNumber(number)
if number == nil then return 0 end
local value = string.match(number,"[0-9.]*",1)
local power = string.match(number,"[0-9.]*([a-zA-Z]*)",1)
if power == nil then
return tonumber(value)
elseif string.lower(power) == "kw" then
return tonumber(value)*1000
elseif string.lower(power) == "mw" then
return tonumber(value)*1000*1000
elseif string.lower(power) == "gw" then
return tonumber(value)*1000*1000*1000
elseif string.lower(power) == "kj" then
return tonumber(value)*1000
elseif string.lower(power) == "mj" then
return tonumber(value)*1000*1000
elseif string.lower(power) == "gj" then
return tonumber(value)*1000*1000*1000
end
end
-------------------------------------------------------------------------------
---Return fluid prototypes with temperature
---@param fluid LuaFluidPrototype
---@return table
function Player.getFluidTemperaturePrototypes(fluid)
-- Find all ways of making this fluid
local temperatures = {}
-- Recipes
local filters = {}
---Hidden fluids do need to be included unfortunately. Only real alternative would be to add a setting.
---table.insert(filters, {filter = "hidden", invert = true, mode = "and"})
table.insert(filters, {filter = "has-product-fluid", elem_filters = {{filter = "name", name = fluid.name}}, mode = "and"})
local prototypes = game.get_filtered_recipe_prototypes(filters)
for recipe_name, recipe in pairs(prototypes) do
for product_name, product in pairs(recipe.products) do
if product.name == fluid.name and product.temperature then
temperatures[product.temperature] = true
end
end
end
-- Boilers
local boilers = Player.getBoilers()
for boiler_name, boiler in pairs(boilers) do
for _, fluidbox in pairs(boiler.fluidbox_prototypes) do
if (fluidbox.production_type == "output") and fluidbox.filter and (fluidbox.filter.name == fluid.name) then
temperatures[boiler.target_temperature] = true
end
end
end
-- Build result table of FluidPrototype
local items = {}
local item
for temperature, _ in spairs(temperatures, function(t,a,b) return b > a end) do
item = FluidPrototype(fluid)
item:setTemperature(temperature)
table.insert(items, item)
end
return items
end
return Player