mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-13 07:04:53 +09:00
New exchange string format for enemy expansion settings
This commit is contained in:
8 files changed
+255
-17
No files matched your search
@@ -9,3 +9,23 @@ debugCommands.add(new lib.Command({
|
||||
control.keepOpen = true;
|
||||
},
|
||||
}));
|
||||
|
||||
debugCommands.add(new lib.Command({
|
||||
definition: [
|
||||
"parse-exchange-string <exchange-string>",
|
||||
"Parse and print the contents of an exchange string",
|
||||
(yargs) => {
|
||||
yargs.positional("exchange-string", { describe: "String to parse", type: "string" });
|
||||
yargs.option("pretty", { alias: "p", type: "boolean", description: "Pretty output" });
|
||||
}],
|
||||
handler: async function(args: { exchangeString: string, pretty: boolean }, control: Control) {
|
||||
const result = lib.readMapExchangeString(args.exchangeString);
|
||||
if (args.pretty) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(JSON.stringify(result, null, 2));
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(JSON.stringify(result));
|
||||
}
|
||||
},
|
||||
}));
|
||||
@@ -662,7 +662,7 @@ export default class Host extends lib.Link {
|
||||
async fetchMods(mods: Iterable<lib.ModRecord>) {
|
||||
// This is better than the previous hard coded names
|
||||
// But it really shouldn't be a hard coded version either
|
||||
const builtinModNames = lib.ModPack.getBuiltinModNames("2.0");
|
||||
const builtinModNames = lib.ModPack.getBuiltinModNames("2.1");
|
||||
const modInfos: Promise<lib.ModInfo>[] = [];
|
||||
for (const mod of mods) {
|
||||
if (builtinModNames.includes(mod.name)) {
|
||||
|
||||
@@ -5,6 +5,8 @@ class MapReaderState {
|
||||
last_position = { x: 0, y: 0 };
|
||||
/** True when a version greater than 2.0.0 is detected */
|
||||
v2 = false;
|
||||
/** True when a version greater than 2.1.0 is detected */
|
||||
v2_1 = false;
|
||||
constructor(
|
||||
public buf: Buffer
|
||||
) { }
|
||||
@@ -262,7 +264,23 @@ function readEnemyEvolution(state: MapReaderState) {
|
||||
}
|
||||
|
||||
function readEnemyExpansion(state: MapReaderState) {
|
||||
return {
|
||||
return state.v2_1 ? {
|
||||
enabled: readOptional(state, readBool),
|
||||
max_expansion_distance: readOptional(state, readUInt32),
|
||||
min_expansion_distance: readOptional(state, readUInt32), // v2.1
|
||||
friendly_base_influence_radius: readOptional(state, readUInt32),
|
||||
enemy_building_influence_radius: readOptional(state, readUInt32),
|
||||
building_coefficient: readOptional(state, readDouble),
|
||||
other_base_coefficient: readOptional(state, readDouble),
|
||||
neighbouring_chunk_coefficient: readOptional(state, readDouble),
|
||||
neighbouring_base_chunk_coefficient: readOptional(state, readDouble),
|
||||
max_colliding_tiles_coefficient: readOptional(state, readDouble),
|
||||
settler_group_min_size: readOptional(state, readUInt32),
|
||||
settler_group_max_size: readOptional(state, readUInt32),
|
||||
evolution_group_size_factor: readOptional(state, readDouble), // v2.1
|
||||
min_expansion_cooldown: readOptional(state, readUInt32),
|
||||
max_expansion_cooldown: readOptional(state, readUInt32),
|
||||
} : {
|
||||
enabled: readOptional(state, readBool),
|
||||
max_expansion_distance: readOptional(state, readUInt32),
|
||||
friendly_base_influence_radius: readOptional(state, readUInt32),
|
||||
@@ -355,17 +373,32 @@ function readAsteroids(state: MapReaderState) {
|
||||
}
|
||||
|
||||
function readMapSettings(state: MapReaderState) {
|
||||
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
|
||||
} : {
|
||||
if (state.v2_1) {
|
||||
return {
|
||||
pollution: readPollution(state),
|
||||
// steering removed v2.1
|
||||
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
|
||||
};
|
||||
} else if (state.v2) {
|
||||
return {
|
||||
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
|
||||
};
|
||||
}
|
||||
return {
|
||||
pollution: readPollution(state),
|
||||
steering: readSteering(state),
|
||||
enemy_evolution: readEnemyEvolution(state),
|
||||
@@ -427,6 +460,7 @@ export function readMapExchangeString(exchangeString: string) {
|
||||
try {
|
||||
const version = readVersion(state);
|
||||
state.v2 = version[0] >= 2;
|
||||
state.v2_1 = version[0] >= 2 && version[1] >= 1;
|
||||
data = {
|
||||
version: version,
|
||||
unknown: readUInt8(state),
|
||||
|
||||
@@ -1150,8 +1150,15 @@ describe("Integration of Clusterio", function() {
|
||||
await execCtl("instance start 44");
|
||||
const instance = (await getInstances()).get(44);
|
||||
const isV2 = lib.integerPartialVersion(instance.factorioVersion) > lib.integerPartialVersion("2.0");
|
||||
const exchangeString = (isV2 ? testStrings.modified_v2 : testStrings.modified).replace(/[\n\r]+/g, "");
|
||||
const args = `base/freeplay --seed 1234 --map-exchange-string "${exchangeString}"`;
|
||||
const isV2_1 = lib.integerPartialVersion(instance.factorioVersion) > lib.integerPartialVersion("2.1");
|
||||
let exchangeString = testStrings.modified;
|
||||
if (isV2_1) {
|
||||
exchangeString = testStrings.modified_v2_1;
|
||||
} else if (isV2) {
|
||||
exchangeString = testStrings.modified_v2;
|
||||
}
|
||||
// eslint-disable-next-line max-len
|
||||
const args = `base/freeplay --seed 1234 --map-exchange-string "${exchangeString.replace(/[\n\r]+/g, "")}"`;
|
||||
await execCtl("instance stop 44");
|
||||
|
||||
await execCtl(`instance load-scenario test ${args}`);
|
||||
|
||||
@@ -382,8 +382,8 @@ before(async function() {
|
||||
const testPack = lib.ModPack.fromJSON({});
|
||||
testPack.id = 12;
|
||||
testPack.name = "subspace_storage-pack";
|
||||
testPack.factorioVersion = "2.0.0";
|
||||
testPack.mods.set("clusterio_lib", { name: "clusterio_lib", enabled: true, version: "2.0.20" });
|
||||
testPack.factorioVersion = "2.1";
|
||||
testPack.mods.set("clusterio_lib", { name: "clusterio_lib", enabled: true, version: "2.0.21" });
|
||||
await control.sendTo("controller", new lib.ModPackCreateRequest(testPack));
|
||||
await control.sendTo(
|
||||
"controller",
|
||||
|
||||
@@ -59,6 +59,16 @@ describe("lib/factorio/exchange_string", function() {
|
||||
});
|
||||
});
|
||||
|
||||
it("should parse post v2.1 strings", function() {
|
||||
assert.deepEqual(lib.readMapExchangeString(testStrings.modified_v2_1), {
|
||||
version: [2, 1, 9, 3],
|
||||
unknown: 0,
|
||||
map_gen_settings: testSettings.modified_v2_1_map_gen_settings,
|
||||
map_settings: testSettings.modified_v2_1_map_settings,
|
||||
checksum: 3180296799,
|
||||
});
|
||||
});
|
||||
|
||||
it("should handle malformed strings", function() {
|
||||
assert.throws(
|
||||
() => lib.readMapExchangeString("<<blah>>"),
|
||||
|
||||
@@ -467,6 +467,154 @@ const modified_v2_map_settings = {
|
||||
},
|
||||
};
|
||||
|
||||
const modified_v2_1_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": {},
|
||||
"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,
|
||||
"no_enemies_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,
|
||||
},
|
||||
"territory_settings": null,
|
||||
};
|
||||
|
||||
const modified_v2_1_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,
|
||||
},
|
||||
"enemy_evolution": {
|
||||
"enabled": true,
|
||||
"time_factor": 0.00002,
|
||||
"destroy_factor": 0.002,
|
||||
"pollution_factor": 0.000012,
|
||||
},
|
||||
"enemy_expansion": {
|
||||
"enabled": true,
|
||||
"max_expansion_distance": 13,
|
||||
"min_expansion_distance": 3,
|
||||
"friendly_base_influence_radius": 6,
|
||||
"enemy_building_influence_radius": 3,
|
||||
"building_coefficient": 0.5,
|
||||
"other_base_coefficient": 3,
|
||||
"neighbouring_chunk_coefficient": 0.5,
|
||||
"neighbouring_base_chunk_coefficient": 0.5,
|
||||
"max_colliding_tiles_coefficient": 0.8,
|
||||
"settler_group_min_size": 5,
|
||||
"settler_group_max_size": 20,
|
||||
"evolution_group_size_factor": 4,
|
||||
"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 },
|
||||
@@ -553,5 +701,7 @@ module.exports = {
|
||||
modified_map_settings,
|
||||
modified_v2_map_gen_settings,
|
||||
modified_v2_map_settings,
|
||||
modified_v2_1_map_gen_settings,
|
||||
modified_v2_1_map_settings,
|
||||
modified_space_age_map_gen_settings,
|
||||
};
|
||||
@@ -49,6 +49,22 @@ Ln6IET6h2alhiMgvQ3SGxnDDDd32daT/yCD5fQ8R3WMEyeN/PENaNmy
|
||||
E5utYOI24z/cT+oQf48FdgozaFZg6qX+1KqW+GYyy4qNZgFNY/0IAHj
|
||||
RI5Q/27QvL<<<`;
|
||||
|
||||
const modified_v2_1 = `
|
||||
>>>eNp1U89rE0EUftM0NYlVc4iCIjWHHkRICNFTkezoRTx4ELxKnGwm
|
||||
unSz087uVlsP5uDBg1CQXvSiVyt6EY9CwIu9if4DlXqwt1aK9CDEeZm
|
||||
dyZrgg/f49nu/37BTQCAPGYDZaVcwH6DnGC24YmmJy4qQHAAsnXdl3O
|
||||
YV4fkplhZ4wLurlRYLMZgC9IeunCdFoCv0bYXZgMUrXth0fa/TSXfMS
|
||||
uEuhmnmVBgxGXnB3SaTnDW7wgujGKulksJIBEnThIkk5+GbzU1HaQOZ
|
||||
o7FkgRd39SQ95HXkfRZxiXuYSCDvf93e6j2eA9TBIygPBqgKbas4VCA
|
||||
9HU0UmUi26IogksJfYPGDhZbHwnylVq3XUE6mXR3Jl2MeuKu5erX2r9
|
||||
ssN5Z+ZsI/qlGrXhxKnvt8hUWeCE5Y1PTZIg+zyZGhfEXpVXs4QsjD0
|
||||
rtr39c2HKJXqNIEHCZMv2WY6wl49pb+zzVtXHDJgD1HNdm/t/Pkw+FB
|
||||
g/x5vf/1RuuOQ279KC6HF3YbynkMj5lBM2ORzt02U+XoOKPAi+couw7
|
||||
JYkZplFakZG9jCkjt5gyQ4nHFv3qqTPmsjWiYeiVKOkP57RB9xB0Dvk
|
||||
00n6fkMnaZQ/MZTXbUFKhaRYN1Sug54z09ClH5dUjP0MYvvcaWafsp1
|
||||
X9skPmJ46b3GGNscC4FCtiwbc3PTPrUX46YL/qSDp8BMOqAJI8C+u/S
|
||||
peyl8e7GC3Ce2le3AIs019Y//gU3lOV1<<<`;
|
||||
|
||||
const modified_space_age = `
|
||||
>>>eNp1VEFoE0EUnUkb27TWBomFSqkBexAhMVZPRbJbL+LBg+BV1slm
|
||||
kgzd7LYzs9HYgz304EEQpJf2Yq9W9CIevBW8WFAQPXmr1IOCh1aL9CD
|
||||
@@ -74,5 +90,6 @@ module.exports = {
|
||||
default: default_,
|
||||
modified,
|
||||
modified_v2,
|
||||
modified_v2_1,
|
||||
modified_space_age,
|
||||
};
|
||||
Reference in new issue
Block a user