In other languages:

Tutorial:Mod settings: Difference between revisions

From Official Factorio Wiki
Jump to navigation Jump to search
(WIP)
 
(Completed the tutorial)
Line 1: Line 1:
{{Languages}}
{{Languages}}
This tutorial aims to explain how to create and use mod settings and the gui that mods can create. It corresponds to factorio version 0.15.
This tutorial aims to explain how to create and use mod settings. This tutorial assumes basic knowledge of modding, so you should have at least completed [[Tutorial:Modding tutorial/Gangsir|Gangsir's modding tutorial]].


== Mod settings ==
== Overview ==
Each mod can specify settings that users can change outside or inside the game. These settings can be accessed from inside the data stage or the control stage depending on their [[#The setting_type|setting_type]] and allow to conditionally create or modify prototypes and to add configuration options to control scripts.
Each mod can specify settings that users can change. The values of these settings can be accessed from inside the data stage or the control stage depending on their [[#The setting_type|setting_type]] and allow to conditionally create or modify prototypes and to add configuration options to control scripts. They were added in version 0.15 to allow modders to easily create a graphical interface for their configuration options, instead of relying on text files that had to be edited manually by the users.


=== Where and when mod settings are defined ===
== Location ==


Mod settings are defined in the [http://lua-api.factorio.com/latest/Data-Lifecycle.html settings stage]. This stage is loaded before the prototype stage. There are three files in which settings can be defined:
Mod settings are defined in the [http://lua-api.factorio.com/latest/Data-Lifecycle.html settings stage]. This stage is loaded before the data stage. There are three files in which settings can be defined:
* settings.lua
* settings.lua
* settings-updates.lua
* settings-updates.lua
Line 14: Line 14:
First the settings.lua file is called for each mod, in the order of their dependencies and then in the [[:Wikipedia:natural sort order|natural sort order]]. Next, the settings-updates.lua file is called for each mod <sup>(in the same order)</sup> and finally the settings-final-fixes.lua file is called for each mod <sup>(in the same order)</sup>. The settings are all defined in the same stage and their user defined values are not available, therefore mods cannot conditionally create settings depending on the values of other mod settings. Since the settings stage gets loaded first, there is also no prototype data or [http://lua-api.factorio.com/latest/LuaRemote.html remote interface] available.
First the settings.lua file is called for each mod, in the order of their dependencies and then in the [[:Wikipedia:natural sort order|natural sort order]]. Next, the settings-updates.lua file is called for each mod <sup>(in the same order)</sup> and finally the settings-final-fixes.lua file is called for each mod <sup>(in the same order)</sup>. The settings are all defined in the same stage and their user defined values are not available, therefore mods cannot conditionally create settings depending on the values of other mod settings. Since the settings stage gets loaded first, there is also no prototype data or [http://lua-api.factorio.com/latest/LuaRemote.html remote interface] available.


=== How to define mod settings ===
The "mod-settings.json" file stored in the [[Application_directory#User_Data_directory|write-data folder]] for the game contains the local players settings between game sessions similar to the player-data.json file.
 
== Creation ==


Mod settings are defined and modified by using the data table. This works [[Tutorial:Modding_tutorial/Gangsir#Prototype_creation|the same way as other prototypes]]. An example would be:
Mod settings are defined and modified by using the data table. This works [[Tutorial:Modding_tutorial/Gangsir#Prototype_creation|the same way as other prototypes]]. An example would be:
 
<pre>
<pre style="background-color:#BA77BA!important; border-color: #333; color:black">
data:extend({
data:extend({
     {
     {
         type = "bool-setting",
         type = "bool-setting",
         name = "my-mod-first-setting",
         name = "my-mod-test-setting",
         setting_type = "runtime-global",
         setting_type = "runtime-global",
         default_value = true,
         default_value = true
        order = "a"
     }
     }
})
})
Line 41: Line 41:
* setting_type (string, required)
* setting_type (string, required)


==== The name property ====
=== The name property ===


The name of the settings prototype should be unique to avoid mod conflicts since all mods share the data table (the "prototype space"). Because of that it is recommened to prefix mod settings with your mod name, "my-mod" in this example.
The name of the settings prototype should be unique to avoid mod conflicts since the mod settings are global across all mods. Because of that it is recommened to prefix mod settings with your mod name, "my-mod" in this example.


==== The type property ====
=== The type property ===


There are four types of mod settings:
There are four types of mod settings:
Line 58: Line 58:
<div class="factorio-list">
<div class="factorio-list">
* '''bool-setting''':
* '''bool-setting''':
** default_value ([http://lua-api.factorio.com/latest/Builtin-Types.html#boolean bool], required) - defines the default value of the setting, in this case whether the checkbox is checked or not
** default_value ([http://lua-api.factorio.com/latest/Builtin-Types.html#boolean bool], required) - Defines the default value of the setting, in this case whether the checkbox is checked or not.


* '''int-setting''':
* '''int-setting''':
** default_value ([http://lua-api.factorio.com/latest/Builtin-Types.html#int int], required) - defines the default value of the setting
** default_value ([http://lua-api.factorio.com/latest/Builtin-Types.html#int int], required) - Defines the default value of the setting.
** minimum_value (int, optional) - defines the lowest possible number
** minimum_value (int, optional) - Defines the lowest possible number.
** maximum_value (int, optional) - defines the highest possible number
** maximum_value (int, optional) - Defines the highest possible number.
** allowed_values (array(int), optional) - makes it possible to force the player to choose between the defined numbers, creates a dropdown instead of a texfield
** allowed_values (array(int), optional) - Makes it possible to force the player to choose between the defined numbers, creates a dropdown instead of a texfield.


* '''double-setting''':
* '''double-setting''':
** default_value ([http://lua-api.factorio.com/latest/Builtin-Types.html#double double], required) - defines the default value of the setting
** default_value ([http://lua-api.factorio.com/latest/Builtin-Types.html#double double], required) - Defines the default value of the setting.
** minimum_value (double, optional) - defines the lowest possible number
** minimum_value (double, optional) - Defines the lowest possible number.
** maximum_value (double, optional) - defines the highest possible number
** maximum_value (double, optional) - Defines the highest possible number.
** allowed_values (array(double), optional) - makes it possible to force the player to choose between the defined numbers, creates a dropdown instead of a textfield
** allowed_values (array(double), optional) - Makes it possible to force the player to choose between the defined numbers, creates a dropdown instead of a textfield.


* '''string-setting''':
* '''string-setting''':
** default_value (string, required) - defines the default value of the setting
** default_value (string, required) - Defines the default value of the setting.
** allow_blank (boolean, optional) - defaults to false, defines whether it's possible for the user to set the textfield to empty and apply the setting
** allow_blank (boolean, optional) - Defaults to false, defines whether it's possible for the user to set the textfield to empty and apply the setting.
** allowed_values (array(string), optional) - makes it possible to force the player to choose between the defined strings, creates a dropdown instead of a textfield
** allowed_values (array(string), optional) - Makes it possible to force the player to choose between the defined strings, creates a dropdown instead of a textfield. The strings inside the array can not be localized (translated).
</div>
</div>


==== The setting_type property ====
=== The order property ===
 
The order property can be used to change how the mod settings are ordered in the settings gui. Mod settings are sorted
* first by mod
* then by the setting "order" string
* then finally by the setting name.
 
For more info on how to use the order string, see [[Types/Order]].
 
=== The setting_type property ===
[[File:Mod_settings_gui.png|right|300px|thumb|The mod settings gui. Can be reached from the main menu -> Settings -> Mods.]]
[[File:Mod_settings_gui.png|right|300px|thumb|The mod settings gui. Can be reached from the main menu -> Settings -> Mods.]]
There are the overall kinds of settings:
There are the overall kinds of settings:
Line 88: Line 97:
This "setting_type" also determines in which tab the setting is showed in the mod settings menu.
This "setting_type" also determines in which tab the setting is showed in the mod settings menu.


==== Localization ====
=== Locale ===
The locale for mod settings works like any other locale in the game. The names of the groups for the settings are "mod-setting-name" and "mod-setting-description". An example for mod setting localization that would be set within "locale/en/locale.cfg", is:
<pre>
[mod-setting-name]
my-mod-test-setting=Localized test setting name
 
[mod-setting-description]
my-mod-test-setting=Localized test setting description
</pre>
== Usage ==
 
When accessing any mod setting, you will have to specifically access the ''value'' of the setting. The data type of the value depends on the type of the setting. See also [http://lua-api.factorio.com/latest/Concepts.html#ModSetting ModSetting concept].
 
In the prototype stage you can access settings of the setting_type "startup" using the [http://lua-api.factorio.com/latest/LuaSettings.html settings table]. Example:
<pre>
--in settings.lua:
data:extend({
    {
        type = "int-setting",
        name = "my-mod-stone-wall-stack-size",
        setting_type = "startup",
        minimum_value = 1,
        default_value = 100
    }
})
 
--in data.lua:
data.raw.item["stone-wall"].stack_size = settings.startup["my-mod-stone-wall-stack-size"].value
</pre>
 
In the control stage, the settings of the setting_type "runtime-global" can be accessed using <code>settings.global["setting-name"]</code>. Settings of the setting_type "runtime-per-user" are accessed using <code>settings.get_player_settings(game.players[event.player_index])["setting-name"]</code>.
 
Example:
<pre>
--in settings.lua:
data:extend({
    {
        type = "bool-setting",
        name = "my-mod-always-difficult",
        setting_type = "runtime-global",
        default_value = true
    },
    {
        type = "bool-setting",
        name = "my-mod-kill-player-on-entity-built",
        setting_type = "runtime-per-user",
        default_value = false
    }
})
 
--in control.lua:
script.on_init(function()
    if settings.global["my-mod-always-difficult"].value then
        game.difficulty_settings.recipe_difficulty = 1
        game.difficulty_settings.technology_difficulty = 1
        game.difficulty_settings.technology_price_multiplier = 4
    end
end)
 
script.on_event(defines.events.on_built_entity, function(event)
    local setting_value = settings.get_player_settings(game.players[event.player_index])["my-mod-kill-player-on-entity-built"]
    if setting_value then
        game.players[event.player_index].die()
    end
end)
</pre>


=== Tips ===


=== Usage ===
* Do not conditionally 'require(...)' things: This breaks the CRC checks and people will get errors trying to use your mod in multiplayer. 'require(...)' everything and then conditionally add the values to data.raw using the settings.
* You should cache the settings table inside the event you use it in. Accessing it is relatively expensive, so when accessing it mutliple times you should set a local variable to it to improve performance.
* If you want to detect whether a certain mod is installed in the settings stage, you can use <code>if mods["another-mods-name"] then</code>, just like in the data stage.


== See also ==
== See also ==


* https://forums.factorio.com/viewtopic.php?p=207275
* [https://forums.factorio.com/viewtopic.php?p=207275 forum post documenting mod settings]
* [http://lua-api.factorio.com/latest/LuaSettings.html lua api doc on mod settings]

Revision as of 10:45, 21 August 2017

This tutorial aims to explain how to create and use mod settings. This tutorial assumes basic knowledge of modding, so you should have at least completed Gangsir's modding tutorial.

Overview

Each mod can specify settings that users can change. The values of these settings can be accessed from inside the data stage or the control stage depending on their setting_type and allow to conditionally create or modify prototypes and to add configuration options to control scripts. They were added in version 0.15 to allow modders to easily create a graphical interface for their configuration options, instead of relying on text files that had to be edited manually by the users.

Location

Mod settings are defined in the settings stage. This stage is loaded before the data stage. There are three files in which settings can be defined:

  • settings.lua
  • settings-updates.lua
  • settings-final-fixes.lua

First the settings.lua file is called for each mod, in the order of their dependencies and then in the natural sort order. Next, the settings-updates.lua file is called for each mod (in the same order) and finally the settings-final-fixes.lua file is called for each mod (in the same order). The settings are all defined in the same stage and their user defined values are not available, therefore mods cannot conditionally create settings depending on the values of other mod settings. Since the settings stage gets loaded first, there is also no prototype data or remote interface available.

The "mod-settings.json" file stored in the write-data folder for the game contains the local players settings between game sessions similar to the player-data.json file.

Creation

Mod settings are defined and modified by using the data table. This works the same way as other prototypes. An example would be:

data:extend({
    {
        type = "bool-setting",
        name = "my-mod-test-setting",
        setting_type = "runtime-global",
        default_value = true
    }
})

As you can see, the setting has multiple properties. Each setting supports the following standard protoype properties:

  • name (string, required)
  • type (string, required)
  • localised_name (localised string, optional)
  • localised_description (localised string, optional)
  • order (string, optional)

In addition to the standard properties, mod settings also contain:

  • setting_type (string, required)

The name property

The name of the settings prototype should be unique to avoid mod conflicts since the mod settings are global across all mods. Because of that it is recommened to prefix mod settings with your mod name, "my-mod" in this example.

The type property

There are four types of mod settings:

  • bool-setting - a true/false checkbox
  • int-setting - a signed 64 bit integer textfield (or selection dropdown)
  • double-setting - a double precision floating point textfield (or selection dropdown)
  • string-setting - a string textfield (or selection dropdown)

Depending on the type, the prototype also allows or requires additional properties:

  • bool-setting:
    • default_value (bool, required) - Defines the default value of the setting, in this case whether the checkbox is checked or not.
  • int-setting:
    • default_value (int, required) - Defines the default value of the setting.
    • minimum_value (int, optional) - Defines the lowest possible number.
    • maximum_value (int, optional) - Defines the highest possible number.
    • allowed_values (array(int), optional) - Makes it possible to force the player to choose between the defined numbers, creates a dropdown instead of a texfield.
  • double-setting:
    • default_value (double, required) - Defines the default value of the setting.
    • minimum_value (double, optional) - Defines the lowest possible number.
    • maximum_value (double, optional) - Defines the highest possible number.
    • allowed_values (array(double), optional) - Makes it possible to force the player to choose between the defined numbers, creates a dropdown instead of a textfield.
  • string-setting:
    • default_value (string, required) - Defines the default value of the setting.
    • allow_blank (boolean, optional) - Defaults to false, defines whether it's possible for the user to set the textfield to empty and apply the setting.
    • allowed_values (array(string), optional) - Makes it possible to force the player to choose between the defined strings, creates a dropdown instead of a textfield. The strings inside the array can not be localized (translated).

The order property

The order property can be used to change how the mod settings are ordered in the settings gui. Mod settings are sorted

  • first by mod
  • then by the setting "order" string
  • then finally by the setting name.

For more info on how to use the order string, see Types/Order.

The setting_type property

The mod settings gui. Can be reached from the main menu -> Settings -> Mods.

There are the overall kinds of settings:

  • startup: This kind of setting is available in the prototype stage, and can not be changed runtime. They have to be set to the same values for all players on a server.
  • runtime-global: This kind of setting is global to an entire save game and can be changed runtime. On servers, only admins can change these settings.
  • runtime-per-user: This kind of setting is only available runtime in the control.lua stage and each player has their own instance of this setting. When a player joins a server their local setting of "keep mod settings per save" determines if the local settings they have set are synced to the loaded save or if the save's settings are used.

This "setting_type" also determines in which tab the setting is showed in the mod settings menu.

Locale

The locale for mod settings works like any other locale in the game. The names of the groups for the settings are "mod-setting-name" and "mod-setting-description". An example for mod setting localization that would be set within "locale/en/locale.cfg", is:

[mod-setting-name]
my-mod-test-setting=Localized test setting name

[mod-setting-description]
my-mod-test-setting=Localized test setting description

Usage

When accessing any mod setting, you will have to specifically access the value of the setting. The data type of the value depends on the type of the setting. See also ModSetting concept.

In the prototype stage you can access settings of the setting_type "startup" using the settings table. Example:

--in settings.lua:
data:extend({
    {
        type = "int-setting",
        name = "my-mod-stone-wall-stack-size",
        setting_type = "startup",
        minimum_value = 1,
        default_value = 100
    }
})

--in data.lua:
data.raw.item["stone-wall"].stack_size = settings.startup["my-mod-stone-wall-stack-size"].value

In the control stage, the settings of the setting_type "runtime-global" can be accessed using settings.global["setting-name"]. Settings of the setting_type "runtime-per-user" are accessed using settings.get_player_settings(game.players[event.player_index])["setting-name"].

Example:

--in settings.lua:
data:extend({
    {
        type = "bool-setting",
        name = "my-mod-always-difficult",
        setting_type = "runtime-global",
        default_value = true
    },
    {
        type = "bool-setting",
        name = "my-mod-kill-player-on-entity-built",
        setting_type = "runtime-per-user",
        default_value = false
    }
})

--in control.lua:
script.on_init(function()
    if settings.global["my-mod-always-difficult"].value then
        game.difficulty_settings.recipe_difficulty = 1
        game.difficulty_settings.technology_difficulty = 1
        game.difficulty_settings.technology_price_multiplier = 4
    end
end)

script.on_event(defines.events.on_built_entity, function(event)
    local setting_value = settings.get_player_settings(game.players[event.player_index])["my-mod-kill-player-on-entity-built"]
    if setting_value then
        game.players[event.player_index].die()
    end
end)

Tips

  • Do not conditionally 'require(...)' things: This breaks the CRC checks and people will get errors trying to use your mod in multiplayer. 'require(...)' everything and then conditionally add the values to data.raw using the settings.
  • You should cache the settings table inside the event you use it in. Accessing it is relatively expensive, so when accessing it mutliple times you should set a local variable to it to improve performance.
  • If you want to detect whether a certain mod is installed in the settings stage, you can use if mods["another-mods-name"] then, just like in the data stage.

See also