Map exchange string format
This is a technical description of the map exchange string format, used to share map generating configurations with other users. This format is also used to store these settings inside save files for future chunk generation.
Factorio line wraps the entire map exchange string after 57 characters during export (55 code characters + '\r\n', which is fairly standard), but ignores all whitespace during import. The outer layer of the map exchange string format includes three angle brackets on either side: ">>>" and "<<<", which must be present for Factorio to accept the string. Between those two tokens is the map exchange data, encoded using base 64 as defined by RFC 4648 (or 3548, 2535, 2045, 1421, et al).
See the page on data types for an explanation of the different types of data used in this document.
Factorio 0.16 and Beyond
Beginning with Factorio 0.16.0, two important changes are made to the encoding of the map exchange string data:
- The map exchange data inside the Base 64 encoding is further encoded using the zlib compression algorithm. The best way to determine the encoding is to first attempt to parse the map exchange string using zlib, and if that fails, try again using the 0.14+ rules.
- All numeric data fields longer than 1 byte are encoding using a custom-built variable length integer format described by Factorio developer Rseding at Data_types#Space_Optimized. For appropriate Factorio versions, all such data types (int, short, dict, etc) used in this document represent values encoded using this approach, unless otherwise specifically noted.
After taking these considerations into your codec, proceed using the 0.14+ rules below.
Factorio 0.14 and Beyond
This is the base map exchange string format for all Factorio versions 0.14.x and greater.
|short||The version string of Factorio that generated this string, used to determine encoding format. This field is never space optimized.|
|byte[*]||Map Gen Settings. Variable length. See linked section for information on how to parse.|
|byte[*]||0.15.x Map Settings. If present, this chunk consists of the remainder of the data (minus the checksum).|
|uint||CRC32 checksum of all preceding data, as defined by ANSI X3.66 / FIPS 71 / ITU-T V.42 (the same one used by zlib, ethernet, etc.)|
Map Gen Settings
This format matches MapGenSettings.
The "From" column denotes the earliest Factorio version in which that field is present. Most of them are currently labeled as "≤0.14", which means the field was present from at least 0.14. If you have more specific information, please edit this page!
|dict<string, byte>||autoplace_controls||≤0.14||An dictionary of Autoplace Controls, with string keys, where the key represents the resource name. Factorio doesn’t care what order this dictionary is in, but it always alphabetizes during export. Vanilla has seven resources: coal, copper-ore, crude-oil, enemy-base, iron-ore, stone, and uranium-ore. Unknown ores are ignored and missing ores are set to their defaults.
Factorio 0.16.x adds addition terrain related autoplace features: desert, dirt, grass, sand, trees. With the exception of trees, these resources ignore their richness and as such are not configuration using the map gen GUI, and always have a richness value of 3 ("Regular").
|uint||seed||≤0.14||Map seed. This field is never space optimized.|
|none||shift||≤0.14||This field isn't present in the binary format! But it is part of the Lua structure - by default it's derived from the map seed. I'll slap the algorithm here soon(tm).|
|uint||width||≤0.14||Map width. This field is never space optimized.|
|uint||height||≤0.14||Map height. This field is never space optimized.|
|byte||starting_area||≤0.14||Starting area size.|
|boolean||peaceful_mode||≤0.14||Peaceful mode. Enabled if set to 1, disabled otherwise.|
0.15 Map Settings
All of the following data fields (until noted at the end) have a special encapsulation format. Preceding each value is a single byte that states whether or not the value is present. If the byte is equal to zero, then the field value is not present. Otherwise, then the field's value follows.
In the LUA structure, this information is stored in the "game.map_settings" table, which is created by the "MapSettings" prototype. Each section in the table below represents a nested sub-table in "map-settings", where the LUA key listed is the key of the table, and all subsequent fields are part of the sub-table. See data/base/prototypes/map-settings.lua for a description of all attributes (some of that information has now been copied to this page).
Fields marked with a check (✓) in the "GUI" column are configurable in the new game map generator GUI.
|double||✓||diffusion_ratio||The amount of pollution that is diffused into neighboring chunk per second.|
|double||min_to_diffuse||This many PUs must be on the chunk to start diffusing.|
|double||✓||ageing||[Modifier of] the pollution eaten by a chunks tiles.|
|double||expected_max_per_chunk||Anything bigger than this is visualised as this value.|
|double||min_to_show_per_chunk||Anything lower than this (but > 0) is visualised as this value.|
|double||✓||min_pollution_to_damage_trees||Any pollution above this amount starts to damage trees.|
|double||✓||pollution_restored_per_tree_damage||The amount of pollution absorbed by a tree when it is damaged by pollution.|
|double||✓||time_factor||Percent increase in the evolve factor for every second.|
|double||✓||destroy_factor||Percent increase in the evolve factor for every destroyed spawner.|
|double||✓||pollution_factor||Percent increase in the evolve factor for every 1000 PU [produced].|
|boolean||✓||enabled||Enemy expansion enabled.|
|int||✓||max_expansion_distance||Distance in chunks from the furthest base around.|
|double||building_coefficient||Expansion algorithm. See LUA file for details.|
|double||max_colliding_tiles_coefficient||A chunk has to have at most this much percent unbuildable tiles for it to be considered a candidate.|
|int||✓||settler_group_min_size||Size of the group that goes to build new base (in game this is multiplied by the evolution factor).|
|int||min_group_gathering_time||A pollution triggered group's waiting time is a random time between min and max gathering time.|
|int||max_wait_time_for_late_members||After the gathering is finished the group can still wait for late members, but it doesn't accept new ones anymore.|
|double||max_group_radius||Limits for group radius.|
|double||max_member_speedup_when_behind||When a member falls behind the group he can speedup up till this much of his regular speed.|
|double||max_member_slowdown_when_ahead||When a member gets ahead of its group, it will slow down to at most this factor of its speed.|
|double||max_group_slowdown_factor||When members of a group are behind, the entire group will slow down to at most this factor of its max speed.|
|double||max_group_member_fallback_factor||If a member falls behind more than this times the group radius, the group will slow down to max_group_slowdown_factor.|
|double||member_disown_distance||If a member falls behind more than this time the group radius, it will be removed from the group.|
|int||max_gathering_unit_groups||Maximum number of automatically created unit groups gathering for attack at any time.|
|int||max_unit_group_size||Maximum size of an attack unit group. This only affects automatically-created unit groups.|
|int||fwd2bwd_ratio||Defines whether we prefer forward (>1) or backward (<-1) or symmetrical (1) search.|
|double||goal_pressure_ratio||When comparing nodes in open which one to check next, heuristic value is multiplied by this ratio. The higher the number the more is the search directed directly towards the goal.|
|double||max_steps_worked_per_tick||When this is exhausted no more requests are allowed. At the moment the first path to exhaust this will be finished (even if it is hundreds of steps).|
|int||short_cache_size||Number of elements in the cache.|
|double||short_cache_min_cacheable_distance||Minimal distance to goal for path to be searched in short path cache.|
|int||short_cache_min_algo_steps_to_cache||Minimal number of algorithm steps for path to be inserted into the short path cache.|
|double||long_cache_min_cacheable_distance||Minimal distance to goal for path to be searched in long path cache.|
|int||cache_max_connect_to_cache_steps_multiplier||When searching for connection to path cache path, search at most for this number of steps times the initial estimate.|
|double||cache_accept_path_start_distance_ratio||When looking for path from cache make sure it doesn't start too far from requested start in relative distance terms.|
|double||cache_accept_path_end_distance_ratio||When looking for path from cache make sure it doesn't end too far from requested end. This is typically higher than accept value for the start because the end target can be moving.|
|double||negative_cache_accept_path_start_distance_ratio||Same as cache_accept_path_start_distance_ratio, but used for negative cache queries.|
|double||negative_cache_accept_path_end_distance_ratio||Same as cache_accept_path_end_distance_ratio, but used for negative cache queries.|
|double||cache_path_start_distance_rating_multiplier||When assigning rating to the best path this * start distances is considered.|
|double||cache_path_end_distance_rating_multiplier||When assigning rating to the best path this * end distances is considered. This is typically higher than value for the start to achieve better path end quality.|
|double||stale_enemy_with_same_destination_collision_penalty||Somewhere along the path is stuck enemy we need to avoid. This is mainly to handle situations when units have arrived and are attacking the target, then units further in the back will use this and run around the target.|
|double||ignore_moving_enemy_collision_distance||If there is a moving unit further than this we don't really care.|
|double||enemy_with_different_destination_collision_penalty||Enemy is not moving/or is too close and has different destination.|
|double||general_entity_collision_penalty||Simplification for now - collision with everything else is this.|
|double||general_entity_subsequent_collision_penalty||Collision penalty for successors of positions that require destroy to reach.|
|int||max_clients_to_accept_any_new_request||Uptil this amount any client will be served by the path finder (no estimate on the path length).|
|int||max_clients_to_accept_short_new_request||From max_clients_to_accept_any_new_request till this one only those that have a short estimate will be served.|
|int||direct_distance_to_consider_short_request||This is the "threshold" to decide what is short and what is not.|
|int||short_request_max_steps||If a short request takes more than this many steps, it will be rescheduled as a long request.|
|double||short_request_ratio||How many steps will be allocated to short requests each tick, as a ratio of all available steps per tick.|
|int||min_steps_to_check_path_find_termination||Absolute minimum of steps that will be performed for every path find request no matter what.|
|double||start_to_goal_cost_multiplier_to_terminate_path_find||If the amount of steps is higher than this times estimate of start to goal then path finding is terminated.|
|Note: The following fields do not use the special encapsulation method.|
|int||max_failed_behavior_count||If a behavior fails this many times, the enemy (or enemy group) is destroyed. This solves biters stuck within their own base.|
|byte||✓||recipe_difficulty||Recipe difficulty. 0 for Normal, 1 for Expensive.|
|byte||✓||technology_difficulty||Technology difficulty. 0 for Normal, 1 for Expensive.|
|double||✓||technology_price_multiplier||Technology price multiplier.|
Note: these values are typically defined using the constants at defines.difficulty_settings.
See the page on map generation for more information on frequency, size, and richness.
Map Gen Size
These are the values used for the frequencies, sizes, and richnesses of ores, water, and the starting area size. None is a valid value for all three options.
|0||None / None /None|
|1||Very Low / Small / Poor|
|2||Low / Small / Poor|
|3||Normal / Medium / Regular|
|4||High / Big / Good|
|5||Very High / Big / Good|
Each of the values in a triplet (such as "low", "small", and "poor") are synonymous.