diff --git a/.gitignore b/.gitignore index 3bdebd86..eb984bd0 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,8 @@ node_modules Factorio* /factorio !/test/file/factorio +!/test/lib/factorio +!/packages/lib/src/factorio /instances /mods /database diff --git a/packages/lib/src/factorio/exchange_string.ts b/packages/lib/src/factorio/exchange_string.ts index 3ca83522..e5c2e7b1 100644 --- a/packages/lib/src/factorio/exchange_string.ts +++ b/packages/lib/src/factorio/exchange_string.ts @@ -3,6 +3,8 @@ import zlib from "zlib"; class MapReaderState { pos = 0; last_position = { x: 0, y: 0 }; + /** True when a version greater than 2.0.0 is detected */ + v2 = false; constructor( public buf: Buffer ) { } @@ -159,18 +161,49 @@ function readBoundingBox(state: MapReaderState) { } function readCliffSettings(state: MapReaderState) { - return { + return state.v2 ? { name: readString(state), - elevation_0: readFloat(state), - elevation_interval: readFloat(state), + control: readString(state), // v2 + cliff_elevation_0: readFloat(state), + cliff_elevation_interval: readFloat(state), + richness: readFloat(state), + cliff_smoothing: readFloat(state), // v2 + } : { + name: readString(state), + cliff_elevation_0: readFloat(state), + cliff_elevation_interval: readFloat(state), richness: readFloat(state), }; } -function readMapGenSettings(state: MapReaderState) { +function readTerritorySettings(state: MapReaderState) { return { - terrain_segmentation: readFloat(state), - water: readFloat(state), + units: readArray(state, readString), + territory_index_expression: readString(state), + territory_variation_expression: readString(state), + minimum_territory_size: readUInt32(state), + }; +} + +function readMapGenSettings(state: MapReaderState) { + return state.v2 ? { + autoplace_controls: Object.fromEntries(readDict(state, readString, readFrequencySizeRichness)), + autoplace_settings: Object.fromEntries(readDict(state, readString, readAutoplaceSetting)), + default_enable_all_autoplace_controls: readBool(state), + seed: readUInt32(state), + width: readUInt32(state), + height: readUInt32(state), + area_to_generate_at_start: readBoundingBox(state), + starting_area: readFloat(state), + peaceful_mode: readBool(state), + no_enemies_mode: readBool(state), // v2 + starting_points: readArray(state, readMapPosition), + property_expression_names: Object.fromEntries(readDict(state, readString, readString)), + cliff_settings: readCliffSettings(state), + territory_settings: readOptional(state, readTerritorySettings), // v2 + } : { + terrain_segmentation: readFloat(state), // v1 + water: readFloat(state), // v1 autoplace_controls: Object.fromEntries(readDict(state, readString, readFrequencySizeRichness)), autoplace_settings: Object.fromEntries(readDict(state, readString, readAutoplaceSetting)), default_enable_all_autoplace_controls: readBool(state), @@ -303,16 +336,36 @@ function readPathFinder(state: MapReaderState) { } function readDifficultySettings(state: MapReaderState) { - return { - recipe_difficulty: readUInt8(state), - technology_difficulty: readUInt8(state), + return state.v2 ? { technology_price_multiplier: readDouble(state), - research_queue_setting: ["always", "after-victory", "never"][readUInt8(state)], + spoil_time_modifier: readDouble(state), // v2 + } : { + recipe_difficulty: readUInt8(state), // v1 + technology_difficulty: readUInt8(state), // v1 + technology_price_multiplier: readDouble(state), + research_queue_setting: ["always", "after-victory", "never"][readUInt8(state)], // v1 + }; +} + +function readAsteroids(state: MapReaderState) { + return { + spawning_rate: readOptional(state, readDouble) ?? 1, + max_ray_portals_expanded_per_tick: readOptional(state, readUInt32) ?? 100, }; } function readMapSettings(state: MapReaderState) { - return { + return state.v2 ? { + pollution: readPollution(state), + steering: readSteering(state), + enemy_evolution: readEnemyEvolution(state), + enemy_expansion: readEnemyExpansion(state), + unit_group: readUnitGroup(state), + path_finder: readPathFinder(state), + max_failed_behavior_count: readUInt32(state), + difficulty_settings: readDifficultySettings(state), + asteroids: readAsteroids(state), // v2 + } : { pollution: readPollution(state), steering: readSteering(state), enemy_evolution: readEnemyEvolution(state), @@ -372,8 +425,10 @@ export function readMapExchangeString(exchangeString: string) { let data: MapExchangeData; try { + const version = readVersion(state); + state.v2 = version[0] >= 2; data = { - version: readVersion(state), + version: version, unknown: readUInt8(state), map_gen_settings: readMapGenSettings(state), map_settings: readMapSettings(state), diff --git a/test/integration/clusterio.js b/test/integration/clusterio.js index ef1ecebe..e4e4132d 100644 --- a/test/integration/clusterio.js +++ b/test/integration/clusterio.js @@ -911,17 +911,28 @@ describe("Integration of Clusterio", function() { await execCtl("instance config set 44 statistics_exporter.load_plugin false"); await execCtl("instance config set 44 subspace_storage.load_plugin false"); - let exchangeString = testStrings.modified.replace(/[\n\r]+/g, ""); - let args = `base/freeplay --seed 1234 --map-exchange-string "${exchangeString}"`; + await execCtl("instance start 44"); + const instance = (await getInstances()).get(44); + const isV2 = lib.integerFactorioVersion(instance.factorioVersion) > lib.integerFactorioVersion("2.0.0"); + const exchangeString = (isV2 ? testStrings.modified_v2 : testStrings.modified).replace(/[\n\r]+/g, ""); + const args = `base/freeplay --seed 1234 --map-exchange-string "${exchangeString}"`; + await execCtl("instance stop 44"); + await execCtl(`instance load-scenario test ${args}`); await checkInstanceStatus(44, "running"); await sendRcon(44, '/c game.print("disable achievements")'); await sendRcon(44, '/c game.print("disable achievements")'); assert.equal(await sendRcon(44, "/c rcon.print(game.default_map_gen_settings.seed)"), "1234\n"); assert.equal(await sendRcon(44, "/c rcon.print(game.map_settings.pollution.ageing)"), "1.5\n"); - assert.equal( - await sendRcon(44, "/c rcon.print(game.difficulty_settings.research_queue_setting)"), "never\n" - ); + if (isV2) { + assert.equal( + await sendRcon(44, "/c rcon.print(game.difficulty_settings.spoil_time_modifier)"), "1\n" + ); + } else { + assert.equal( + await sendRcon(44, "/c rcon.print(game.difficulty_settings.research_queue_setting)"), "never\n" + ); + } }); }); diff --git a/test/lib/factorio/exchange_string.js b/test/lib/factorio/exchange_string.js index 9a660205..08f92187 100644 --- a/test/lib/factorio/exchange_string.js +++ b/test/lib/factorio/exchange_string.js @@ -5,6 +5,7 @@ const zlib = require("zlib"); const lib = require("@clusterio/lib"); const testStrings = require("./test_strings"); +const testSettings = require("./test_settings"); // Simple linear congruential random number generator @@ -22,12 +23,40 @@ class Random { describe("lib/factorio/exchange_string", function() { describe("readMapExchangeString", function() { - it("should parse a valid string", function() { - let result = lib.readMapExchangeString(testStrings.default); - assert.equal(result.map_gen_settings.seed, 1234567890); + it("should parse post v0.16 strings", function() { + assert.deepEqual(lib.readMapExchangeString(testStrings.default), { + version: [1, 1, 33, 0], + unknown: 0, + map_gen_settings: testSettings.default_map_gen_settings, + map_settings: testSettings.default_map_settings, + checksum: 3169422966, + }); - result = lib.readMapExchangeString(testStrings.modified); - assert.equal(result.checksum, 4092204126); + assert.deepEqual(lib.readMapExchangeString(testStrings.modified), { + version: [1, 1, 33, 0], + unknown: 0, + map_gen_settings: testSettings.modified_map_gen_settings, + map_settings: testSettings.modified_map_settings, + checksum: 4092204126, + }); + }); + + it("should parse post v2.0 strings", function() { + assert.deepEqual(lib.readMapExchangeString(testStrings.modified_v2), { + version: [2, 0, 47, 0], + unknown: 0, + map_gen_settings: testSettings.modified_v2_map_gen_settings, + map_settings: testSettings.modified_v2_map_settings, + checksum: 979461261, + }); + + assert.deepEqual(lib.readMapExchangeString(testStrings.modified_space_age), { + version: [2, 0, 47, 0], + unknown: 0, + map_gen_settings: testSettings.modified_space_age_map_gen_settings, + map_settings: testSettings.modified_v2_map_settings, + checksum: 1746300027, + }); }); it("should handle malformed strings", function() { diff --git a/test/lib/factorio/test_settings.js b/test/lib/factorio/test_settings.js new file mode 100644 index 00000000..6795b99f --- /dev/null +++ b/test/lib/factorio/test_settings.js @@ -0,0 +1,557 @@ +"use strict"; + +const default_map_gen_settings = { + autoplace_controls: { + "coal": { frequency: 1, size: 1, richness: 1 }, + "copper-ore": { frequency: 1, size: 1, richness: 1 }, + "crude-oil": { frequency: 1, size: 1, richness: 1 }, + "enemy-base": { frequency: 1, size: 1, richness: 1 }, + "iron-ore": { frequency: 1, size: 1, richness: 1 }, + "stone": { frequency: 1, size: 1, richness: 1 }, + "trees": { frequency: 1, size: 1, richness: 1 }, + "uranium-ore": { frequency: 1, size: 1, richness: 1 }, + }, + autoplace_settings: {}, + default_enable_all_autoplace_controls: true, + seed: 1234567890, + width: 2000000, + height: 2000000, + area_to_generate_at_start: { + left_top: { x: -224, y: -224 }, + right_bottom: { x: 224, y: 224 }, + orientation: { x: 0, y: -32767 }, + }, + starting_area: 1, + peaceful_mode: false, + starting_points: [ + { x: 0, y: 0 }, + ], + property_expression_names: {}, + cliff_settings: { + name: "cliff", + cliff_elevation_0: 10, + cliff_elevation_interval: 40, + richness: 1, + }, + terrain_segmentation: 1, + water: 1, +}; + +const default_map_settings = { + pollution: { + enabled: true, + diffusion_ratio: 0.02, + min_to_diffuse: 15, + ageing: 1, + expected_max_per_chunk: 150, + min_to_show_per_chunk: 50, + min_pollution_to_damage_trees: 60, + pollution_with_max_forest_damage: 150, + pollution_per_tree_damage: 50, + pollution_restored_per_tree_damage: 10, + max_pollution_to_restore_trees: 20, + enemy_attack_pollution_consumption_modifier: 1, + }, + steering: { + default: { + radius: 1.2, separation_factor: 1.2, separation_force: 0.005, force_unit_fuzzy_goto_behavior: false, + }, + moving: { + radius: 3, separation_factor: 3, separation_force: 0.01, force_unit_fuzzy_goto_behavior: false, + }, + }, + enemy_evolution: { + enabled: true, + time_factor: 0.000004, + destroy_factor: 0.002, + pollution_factor: 9e-7, + }, + enemy_expansion: { + enabled: true, + max_expansion_distance: 7, + friendly_base_influence_radius: 2, + enemy_building_influence_radius: 2, + building_coefficient: 0.1, + other_base_coefficient: 2, + neighbouring_chunk_coefficient: 0.5, + neighbouring_base_chunk_coefficient: 0.4, + max_colliding_tiles_coefficient: 0.9, + settler_group_min_size: 5, + settler_group_max_size: 20, + min_expansion_cooldown: 14400, + max_expansion_cooldown: 216000, + }, + unit_group: { + min_group_gathering_time: 3600, + max_group_gathering_time: 36000, + max_wait_time_for_late_members: 7200, + max_group_radius: 30, + min_group_radius: 5, + max_member_speedup_when_behind: 1.4, + max_member_slowdown_when_ahead: 0.6, + max_group_slowdown_factor: 0.3, + max_group_member_fallback_factor: 3, + member_disown_distance: 10, + tick_tolerance_when_member_arrives: 60, + max_gathering_unit_groups: 30, + max_unit_group_size: 200, + }, + path_finder: { + fwd2bwd_ratio: 5, + goal_pressure_ratio: 2, + use_path_cache: true, + max_steps_worked_per_tick: 1000, + max_work_done_per_tick: 8000, + short_cache_size: 5, + long_cache_size: 25, + short_cache_min_cacheable_distance: 10, + short_cache_min_algo_steps_to_cache: 50, + long_cache_min_cacheable_distance: 30, + cache_max_connect_to_cache_steps_multiplier: 100, + cache_accept_path_start_distance_ratio: 0.2, + cache_accept_path_end_distance_ratio: 0.15, + negative_cache_accept_path_start_distance_ratio: 0.3, + negative_cache_accept_path_end_distance_ratio: 0.3, + cache_path_start_distance_rating_multiplier: 10, + cache_path_end_distance_rating_multiplier: 20, + stale_enemy_with_same_destination_collision_penalty: 30, + ignore_moving_enemy_collision_distance: 5, + enemy_with_different_destination_collision_penalty: 30, + general_entity_collision_penalty: 10, + general_entity_subsequent_collision_penalty: 3, + extended_collision_penalty: 3, + max_clients_to_accept_any_new_request: 10, + max_clients_to_accept_short_new_request: 100, + direct_distance_to_consider_short_request: 100, + short_request_max_steps: 1000, + short_request_ratio: 0.5, + min_steps_to_check_path_find_termination: 2000, + start_to_goal_cost_multiplier_to_terminate_path_find: 2000, + overload_levels: [0, 100, 500], + overload_multipliers: [2, 3, 4], + negative_path_cache_delay_interval: 20, + }, + max_failed_behavior_count: 3, + difficulty_settings: { + recipe_difficulty: 0, + technology_difficulty: 0, + technology_price_multiplier: 1, + research_queue_setting: "after-victory", + }, +}; + +const modified_map_gen_settings = { + autoplace_controls: { + "coal": { frequency: 1, size: 1, richness: 1 }, + "copper-ore": { frequency: 0.5, size: 1, richness: 1 }, + "crude-oil": { frequency: 0.5, size: 1, richness: 4 }, + "enemy-base": { frequency: 2, size: 1.5, richness: 1 }, + "iron-ore": { frequency: 1.5, size: 1, richness: 1 }, + "stone": { frequency: 2, size: 1, richness: 1 }, + "trees": { frequency: 1.3333333730697632, size: 0.3333333432674408, richness: 1 }, + "uranium-ore": { frequency: 1, size: 1.3333333730697632, richness: 1 }, + }, + autoplace_settings: { + entity: { + treat_missing_as_default: true, + settings: { + "rock-huge": { frequency: 10, size: 20, richness: 2.4000000953674316 }, + }, + }, + tile: { + treat_missing_as_default: false, + settings: { + "grass-1": { frequency: 4, size: 1, richness: 1 }, + "water": { frequency: 1, size: 1, richness: 1}, + }, + }, + }, + default_enable_all_autoplace_controls: true, + seed: 3378377395, + width: 2000000, + height: 2000000, + area_to_generate_at_start: { + left_top: { x: -224, y: -224 }, + right_bottom: { x: 224, y: 224 }, + orientation: { x: 0, y: -32767 }, + }, + starting_area: 0.3333333432674408, + peaceful_mode: false, + starting_points: [ + { x: 0, y: 0 }, + ], + property_expression_names: { + "control-setting:aux:bias": "-0.200000", + "control-setting:aux:frequency:multiplier": "2.000000", + "control-setting:moisture:bias": "-0.200000", + "control-setting:moisture:frequency:multiplier": "0.333333", + }, + cliff_settings: { + name: "cliff", + cliff_elevation_0: 10, + cliff_elevation_interval: 40, + richness: 0.3333333432674408, + }, + terrain_segmentation: 0.5, + water: 0.3333333432674408, +}; + +const modified_map_settings = { + pollution: { + enabled: true, + diffusion_ratio: 0.02, + min_to_diffuse: 15, + ageing: 1.5, + expected_max_per_chunk: 150, + min_to_show_per_chunk: 50, + min_pollution_to_damage_trees: 3785, + pollution_with_max_forest_damage: 150, + pollution_per_tree_damage: 50, + pollution_restored_per_tree_damage: 3714, + max_pollution_to_restore_trees: 20, + enemy_attack_pollution_consumption_modifier: 1, + }, + steering: { + default: { + radius: 1.2, separation_factor: 1.2, separation_force: 0.005, force_unit_fuzzy_goto_behavior: false, + }, + moving: { + radius: 3, separation_factor: 3, separation_force: 0.01, force_unit_fuzzy_goto_behavior: false, + }, + }, + enemy_evolution: { + enabled: true, + time_factor: 0.00002, + destroy_factor: 0.002, + pollution_factor: 0.000012, + }, + enemy_expansion: { + enabled: true, + max_expansion_distance: 13, + friendly_base_influence_radius: 2, + enemy_building_influence_radius: 2, + building_coefficient: 0.1, + other_base_coefficient: 2, + neighbouring_chunk_coefficient: 0.5, + neighbouring_base_chunk_coefficient: 0.4, + max_colliding_tiles_coefficient: 0.9, + settler_group_min_size: 3, + settler_group_max_size: 35, + min_expansion_cooldown: 169200, + max_expansion_cooldown: 414000, + }, + unit_group: { + min_group_gathering_time: 3600, + max_group_gathering_time: 36000, + max_wait_time_for_late_members: 7200, + max_group_radius: 30, + min_group_radius: 5, + max_member_speedup_when_behind: 1.4, + max_member_slowdown_when_ahead: 0.6, + max_group_slowdown_factor: 0.3, + max_group_member_fallback_factor: 3, + member_disown_distance: 10, + tick_tolerance_when_member_arrives: 60, + max_gathering_unit_groups: 30, + max_unit_group_size: 200, + }, + path_finder: { + fwd2bwd_ratio: 5, + goal_pressure_ratio: 2, + use_path_cache: true, + max_steps_worked_per_tick: 1000, + max_work_done_per_tick: 8000, + short_cache_size: 5, + long_cache_size: 25, + short_cache_min_cacheable_distance: 10, + short_cache_min_algo_steps_to_cache: 50, + long_cache_min_cacheable_distance: 30, + cache_max_connect_to_cache_steps_multiplier: 100, + cache_accept_path_start_distance_ratio: 0.2, + cache_accept_path_end_distance_ratio: 0.15, + negative_cache_accept_path_start_distance_ratio: 0.3, + negative_cache_accept_path_end_distance_ratio: 0.3, + cache_path_start_distance_rating_multiplier: 10, + cache_path_end_distance_rating_multiplier: 20, + stale_enemy_with_same_destination_collision_penalty: 30, + ignore_moving_enemy_collision_distance: 5, + enemy_with_different_destination_collision_penalty: 30, + general_entity_collision_penalty: 10, + general_entity_subsequent_collision_penalty: 3, + extended_collision_penalty: 3, + max_clients_to_accept_any_new_request: 10, + max_clients_to_accept_short_new_request: 100, + direct_distance_to_consider_short_request: 100, + short_request_max_steps: 1000, + short_request_ratio: 0.5, + min_steps_to_check_path_find_termination: 2000, + start_to_goal_cost_multiplier_to_terminate_path_find: 2000, + overload_levels: [0, 100, 500], + overload_multipliers: [2, 3, 4], + negative_path_cache_delay_interval: 20, + }, + max_failed_behavior_count: 3, + difficulty_settings: { + recipe_difficulty: 1, + technology_difficulty: 1, + technology_price_multiplier: 12, + research_queue_setting: "never", + }, +}; + +const modified_v2_map_gen_settings = { + autoplace_controls: { + "coal": { frequency: 1, size: 1, richness: 1 }, + "copper-ore": { frequency: 0.5, size: 1, richness: 1 }, + "crude-oil": { frequency: 0.5, size: 1, richness: 4 }, + "enemy-base": { frequency: 2, size: 1.5, richness: 1 }, + "iron-ore": { frequency: 1.5, size: 1, richness: 1 }, + "nauvis_cliff": { frequency: 1, size: 1, richness: 1 }, + "rocks": { frequency: 1, size: 1, richness: 1 }, + "starting_area_moisture": { frequency: 1, size: 1, richness: 1 }, + "stone": { frequency: 2, size: 1, richness: 1 }, + "trees": { frequency: 1.3333333730697632, size: 0.3333333432674408, richness: 1 }, + "uranium-ore": { frequency: 1, size: 1.3333333730697632, richness: 1 }, + "water": { frequency: 0.5, size: 0.3333333432674408, richness: 1 }, + }, + autoplace_settings: { + entity: { + treat_missing_as_default: true, + settings: { + "rock-huge": { frequency: 10, size: 20, richness: 2.4000000953674316 }, + }, + }, + tile: { + treat_missing_as_default: false, + settings: { + "grass-1": { frequency: 4, size: 1, richness: 1 }, + "water": { frequency: 1, size: 1, richness: 1 }, + }, + }, + }, + default_enable_all_autoplace_controls: true, + seed: 3378377395, + width: 2000000, + height: 2000000, + area_to_generate_at_start: { + left_top: { x: -224, y: -224 }, + right_bottom: { x: 224, y: 224 }, + orientation: { x: 0, y: -32767 }, + }, + starting_area: 0.3333333432674408, + peaceful_mode: false, + starting_points: [ + { x: 0, y: 0 }, + ], + property_expression_names: { + "control:aux:bias": "-0.200000", + "control:aux:frequency": "2.000000", + "control:moisture:bias": "-0.200000", + "control:moisture:frequency": "0.333333", + "elevation": "elevation_lakes", + }, + cliff_settings: { + name: "cliff", + control: "", + cliff_elevation_0: 10, + cliff_elevation_interval: 40, + richness: 1, + cliff_smoothing: 1, + }, + no_enemies_mode: false, + territory_settings: null, +}; + +const modified_v2_map_settings = { + pollution: { + enabled: true, + diffusion_ratio: 0.02, + min_to_diffuse: 15, + ageing: 1.5, + expected_max_per_chunk: 150, + min_to_show_per_chunk: 50, + min_pollution_to_damage_trees: 3785, + pollution_with_max_forest_damage: 150, + pollution_per_tree_damage: 50, + pollution_restored_per_tree_damage: 3714, + max_pollution_to_restore_trees: 20, + enemy_attack_pollution_consumption_modifier: 1, + }, + steering: { + default: { + radius: 1.2, separation_factor: 1.2, separation_force: 0.005, force_unit_fuzzy_goto_behavior: false, + }, + moving: { + radius: 3, separation_factor: 3, separation_force: 0.01, force_unit_fuzzy_goto_behavior: false, + }, + }, + enemy_evolution: { + enabled: true, + time_factor: 0.00002, + destroy_factor: 0.002, + pollution_factor: 0.000012, + }, + enemy_expansion: { + enabled: true, + max_expansion_distance: 13, + friendly_base_influence_radius: 2, + enemy_building_influence_radius: 2, + building_coefficient: 0.1, + other_base_coefficient: 2, + neighbouring_chunk_coefficient: 0.5, + neighbouring_base_chunk_coefficient: 0.4, + max_colliding_tiles_coefficient: 0.9, + settler_group_min_size: 3, + settler_group_max_size: 35, + min_expansion_cooldown: 169200, + max_expansion_cooldown: 414000, + }, + unit_group: { + min_group_gathering_time: 3600, + max_group_gathering_time: 36000, + max_wait_time_for_late_members: 7200, + max_group_radius: 30, + min_group_radius: 5, + max_member_speedup_when_behind: 1.4, + max_member_slowdown_when_ahead: 0.6, + max_group_slowdown_factor: 0.3, + max_group_member_fallback_factor: 3, + member_disown_distance: 10, + tick_tolerance_when_member_arrives: 60, + max_gathering_unit_groups: 30, + max_unit_group_size: 200, + }, + path_finder: { + fwd2bwd_ratio: 5, + goal_pressure_ratio: 2, + use_path_cache: true, + max_steps_worked_per_tick: 1000, + max_work_done_per_tick: 8000, + short_cache_size: 5, + long_cache_size: 25, + short_cache_min_cacheable_distance: 10, + short_cache_min_algo_steps_to_cache: 50, + long_cache_min_cacheable_distance: 30, + cache_max_connect_to_cache_steps_multiplier: 100, + cache_accept_path_start_distance_ratio: 0.2, + cache_accept_path_end_distance_ratio: 0.15, + negative_cache_accept_path_start_distance_ratio: 0.3, + negative_cache_accept_path_end_distance_ratio: 0.3, + cache_path_start_distance_rating_multiplier: 10, + cache_path_end_distance_rating_multiplier: 20, + stale_enemy_with_same_destination_collision_penalty: 30, + ignore_moving_enemy_collision_distance: 5, + enemy_with_different_destination_collision_penalty: 30, + general_entity_collision_penalty: 10, + general_entity_subsequent_collision_penalty: 3, + extended_collision_penalty: 3, + max_clients_to_accept_any_new_request: 10, + max_clients_to_accept_short_new_request: 100, + direct_distance_to_consider_short_request: 100, + short_request_max_steps: 1000, + short_request_ratio: 0.5, + min_steps_to_check_path_find_termination: 2000, + start_to_goal_cost_multiplier_to_terminate_path_find: 2000, + overload_levels: [0, 100, 500], + overload_multipliers: [2, 3, 4], + negative_path_cache_delay_interval: 20, + }, + max_failed_behavior_count: 3, + difficulty_settings: { + technology_price_multiplier: 12, + spoil_time_modifier: 1, + }, + asteroids: { + spawning_rate: 1, + max_ray_portals_expanded_per_tick: 100, + }, +}; + +const modified_space_age_map_gen_settings = { + autoplace_controls: { + "aquilo_crude_oil": { frequency: 1, size: 1, richness: 1 }, + "calcite": { frequency: 1, size: 1, richness: 1 }, + "coal": { frequency: 1, size: 1, richness: 1 }, + "copper-ore": { frequency: 0.5, size: 1, richness: 1 }, + "crude-oil": { frequency: 0.5, size: 1, richness: 4 }, + "enemy-base": { frequency: 2, size: 1.5, richness: 1 }, + "fluorine_vent": { frequency: 1, size: 1, richness: 1 }, + "fulgora_cliff": { frequency: 1, size: 1, richness: 1 }, + "fulgora_islands": { frequency: 1, size: 1, richness: 1 }, + "gleba_cliff": { frequency: 1, size: 1, richness: 1 }, + "gleba_enemy_base": { frequency: 1, size: 1, richness: 1 }, + "gleba_plants": { frequency: 1, size: 1, richness: 1 }, + "gleba_stone": { frequency: 1, size: 1, richness: 1 }, + "gleba_water": { frequency: 1, size: 1, richness: 1 }, + "iron-ore": { frequency: 1.5, size: 1, richness: 1 }, + "lithium_brine": { frequency: 1, size: 1, richness: 1 }, + "nauvis_cliff": { frequency: 1, size: 1, richness: 1 }, + "rocks": { frequency: 1, size: 1, richness: 1 }, + "scrap": { frequency: 1, size: 1, richness: 1 }, + "starting_area_moisture": { frequency: 1, size: 1, richness: 1 }, + "stone": { frequency: 2, size: 1, richness: 1 }, + "sulfuric_acid_geyser": { frequency: 1, size: 1, richness: 1 }, + "trees": { frequency: 1.3333333730697632, size: 0.3333333432674408, richness: 1 }, + "tungsten_ore": { frequency: 1, size: 1, richness: 1 }, + "uranium-ore": { frequency: 1, size: 1.3333333730697632, richness: 1 }, + "vulcanus_coal": { frequency: 1, size: 1, richness: 1 }, + "vulcanus_volcanism": { frequency: 1, size: 1, richness: 1 }, + "water": { frequency: 0.5, size: 0.3333333432674408, richness: 1 }, + }, + autoplace_settings: { + entity: { + treat_missing_as_default: true, + settings: { + "rock-huge": { frequency: 10, size: 20, richness: 2.4000000953674316 }, + }, + }, + tile: { + treat_missing_as_default: false, + settings: { + "grass-1": { frequency: 4, size: 1, richness: 1 }, + "water": { frequency: 1, size: 1, richness: 1 }, + }, + }, + }, + default_enable_all_autoplace_controls: true, + seed: 3378377395, + width: 2000000, + height: 2000000, + area_to_generate_at_start: { + left_top: { x: -224, y: -224 }, + right_bottom: { x: 224, y: 224 }, + orientation: { x: 0, y: -32767 }, + }, + starting_area: 0.3333333432674408, + peaceful_mode: false, + starting_points: [ + { x: 0, y: 0 }, + ], + property_expression_names: { + "control:aux:bias": "-0.200000", + "control:aux:frequency": "2.000000", + "control:moisture:bias": "-0.200000", + "control:moisture:frequency": "0.333333", + "elevation": "elevation_lakes", + }, + cliff_settings: { + name: "cliff", + control: "", + cliff_elevation_0: 10, + cliff_elevation_interval: 40, + richness: 1, + cliff_smoothing: 1, + }, + no_enemies_mode: false, + territory_settings: null, +}; + +module.exports = { + default_map_gen_settings, + default_map_settings, + modified_map_gen_settings, + modified_map_settings, + modified_v2_map_gen_settings, + modified_v2_map_settings, + modified_space_age_map_gen_settings, +}; diff --git a/test/lib/factorio/test_strings.js b/test/lib/factorio/test_strings.js index 243d4a01..6c724629 100644 --- a/test/lib/factorio/test_strings.js +++ b/test/lib/factorio/test_strings.js @@ -1,7 +1,7 @@ "use strict"; // Exchange strings for testing with -let default_ = ` +const default_ = ` >>>eNpjZGBkUGQAgwZ7EOZgSc5PzIHxQJgrOb+gILVIN78oFVmYM 7moNCVVNz8TVXFqXmpupW5SYjGKYo7Movw8dBNYi0vy81BFSopSU 4uRRbhLixLzMktz0fUyMF5imubZ0CLHAML/6xkU/v8HYSDrAdAvI @@ -12,10 +12,9 @@ zLBiVkzQWAnzCsMMDMf2EOlbtoznj0DAm/sGVlBOkRAhIMFkDjgz czAKMAHZC3oARIKMgwwp9nBjBFxYEwDg28wnzyGMS7bo/sDGBA2I MPlQMQJEAG2EO4yRgjTod+B0UEeJiuJUALUb8SA7IYUhA9Pwqw9j GQ/mkMwIwLZH2giKg5YooELZGEKnHjBDHcNMDwvsMN4DvMdGJlBD -JCqL0AxCA8kAzMKQgs4gIObmQEBgGmjrO/lHgDxa6G4<<< -`; +JCqL0AxCA8kAzMKQgs4gIObmQEBgGmjrO/lHgDxa6G4<<<`; -let modified = ` +const modified = ` >>>eNp1UzFs00AUvZ8mbRIEypCBSlCCyFAhOQqBKULxlQUxMCCxgnCc S2rh2On5LAgMZOjAgISEurQLXSmCBTGwRWKhEkgIJraiMgBiaGmFOiC FO5/PsUz6pfv+9/6/99+/kwEBOo2k6c83NhrZtOkaNkIDXa286fZ6hG @@ -32,7 +31,48 @@ jnh3gmXQRElVwYyxI8x4FMqOzsu4edrKK6hNZ5wU7V9G+ufEFL+7yHi cySQMp7wDHnRsBW571ORGn6fH2fUDj/FwV0iUbXPMbmTP7akkt8ChiL /BPceEs3j1M3iz71/ObT9tA==<<<`; +const modified_v2 = ` +>>>eNp1Uz9oU0EY/y5N2iRWzRCFitSAGURIjNEpSN7VRRwcBFeJl5dL ++ujLe+3de9XoYIYODoogXdrFrlZ0EQe3gIsFBdHJrVIHBYdWi3QQ4l3 +u3csz1Q++7333+31/75IYAJwRCpNx0yU2QNfQmjbd+XnKCi6jgg/hlM +n8Bi24lh1BcZo6tN0p1AmXwRigN6CSFnMdVaEXVph0iL9o8ZppW81mt +GOCueYcjyJHuUeYZzmtGmGU1NquxT1fVoskcc91gqYB4jFK+dP1dUNo +VSIHfEYcy2+rSboSV5E3iUeZ3ENHxsap41leB6GUHKYw67dERm4GYG1 +mdWUKxz3LphCbaDHCeeGsXD1sGxQbjoZe/Li+0V2aBqn9u5Dr96UKb1 +P0lAqoqzojAQaSyJiu4zHXrhD/VqVuEZ4qlIrlkpQjUarJ6IJPHbOTL +BdLf9P6okbSj+3jhzVKxXMDSVGbLhLPcp3DoVezyRzlieDBBteRuxhu +ihC6k31+6fPtZQOpFYo4cPYCpFfXyOXAefQM/4+KawrOa2fbQGq6nxF +HNfVEiyAqiYeOIpckidDO7Na9l3u7VfT7yc6HK/UbBrr2JbPAT3+rCv +KgfIZYaFZXpLzSq4CuuWkE1CcDvXsr5buBxmTGSWm2l2OASlfHAWUOi +ePafWFyx0GPVtVlshg1B/JLb7KlnY/G6B55jC7I4tPSvJEmAWFJMRlS +Ln6IET6h2alhiMgvQ3SGxnDDDd32daT/yCD5fQ8R3WMEyeN/PENaNmy +E5utYOI24z/cT+oQf48FdgozaFZg6qX+1KqW+GYyy4qNZgFNY/0IAHj +RI5Q/27QvL<<<`; + +const modified_space_age = ` +>>>eNp1VEFoE0EUnUkb27TWBomFSqkBexAhMVZPRbJbL+LBg+BV1slm +kgzd7LYzs9HYgz304EEQpJf2Yq9W9CIevBW8WFAQPXmr1IOCh1aL9CD +UmZ2dzW4aB2by972Z9//7MyQFALggJpjIogWfOJ5lU7+KLY84ACwZeg +7YyLEJx3Gs3/ZQYtOQ7c3PY1rwqNgHIjgTKBYCxQg1h7CLm+1CBTG52 +QRgM6BGao7vUeJiq4VdHlcfqflO3aPIsh1Sq8WZUc0Q5iC3yuLccN3B +lR5nsgoPirBUER3yuCLnhRrvpca45+Ie+F3EMY3jg4R6rurHZseIQ3i +D+E2rIn0m8rrIbxF2tNo09ey5RCVpZlM0H0fGGEeUE7duIYqR1fQI4z +7FyUOqcNluheSY79R8SmwL2aRq1XGbJR2kOcWYPd/YMMQsB0Vy360zj +l3LS6oP+xS5wlchxOWhwG/Ld2zk+sJX14M5GTEtTwaENRO5w36CKHfq +mHgUhLchzMiOFBp+XaTKzwKwPru2Om72c+JgkBqoU8RY4aJ8Z91iHXn +46tftraXlSSDn4QOQPzyUU0TbIqecAC6pzFCA4Uhnbc/l1HNmkH9vpk +IQyxRKxemSHKfiVI3iBR+7dntwulhK0vpuuo6fPsJ3NErFS8HIYAe3E +CeeOxpFloPmMEuHryZoR/5q5BRCuJh7ee3r/RUDKgtFMwwOQmSzopHr +YfDkhfk/ql9T4LIOdg2oqvsdC1RSLlKEuwbNTqDIZUlCuNfYefj6YL8 +M/z7b+3SjcseAt75lF9j5H2VBjshrSEXL2qocb7QVoDW3jZD6YsAP7+ +X4acA+eeKsXHZXUgCWbh4DMHtCfK4/Ekt+AujSylomZ8JaMP5oJzs6+ +Gx0+5gy4RUpPimXd3JJg0hSVAZVaD42oXlGs+OdLeL8NIjXUO043NJp +38bydxUydeQi4j66kCmzxzUMyYTVaPneF1Uj+vlxQH+ZT82gl0Du2he +Y+lJ/JEpK/WZNmBM/mgXgnKlfCACLzljjH+s/hYo=<<<`; + module.exports = { default: default_, modified, + modified_v2, + modified_space_age, };