diff --git a/CHANGELOG.md b/CHANGELOG.md index 95c8d2ee..1d7b0672 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,10 @@ Many thanks to the following for contributing to this release: ## Version 2.0.0-alpha.19 +### Major Features + +- Added support for 2.0 builtin mods during mod pack creation. [#684](https://github.com/clusterio/clusterio/pull/684). + ### Features - Added Datastore and Datastore Provider classes to the library to support savable Maps [#629](https://github.com/clusterio/clusterio/pull/629). diff --git a/packages/host/src/patch.ts b/packages/host/src/patch.ts index c0047667..1221224e 100644 --- a/packages/host/src/patch.ts +++ b/packages/host/src/patch.ts @@ -202,12 +202,6 @@ export class PatchInfo { } } - -const knownScenarios: Record = { - // First seen in 0.17.63 - "4e866186ebe297f1038fd325b09df1a1f5e2fdd1": new lib.ModuleInfo("freeplay", "0.17.63", ["freeplay", "silo-script"]), -}; - /** * Generates control.lua code for loading the Clusterio modules * @@ -349,6 +343,14 @@ function reorderDependencies(modules: SaveModule[]) { } } +const knownScenarios: Record = { + // First seen in 0.17.63 + "4e866186ebe297f1038fd325b09df1a1f5e2fdd1": new lib.ModuleInfo("freeplay", "0.17.63", [], ["scenario"]), + // First seen in 1.2.0 (aka 2.0) TODO Uncomment once clusterio lib supports 2.0 + // The rest of the code has already been updated to support the new control.lua file for 2.0 + // "bcbdde18ce4ec16ebfd93bd694cd9b12ef969c9a": new lib.ModuleInfo("freeplay", "1.2.0", [], ["scenario"]), +}; + /** * Patch a save with the given modules * @@ -387,6 +389,7 @@ export async function patch(savePath: string, modules: SaveModule[]) { if (controlHash in knownScenarios) { patchInfo = new PatchInfo(0, knownScenarios[controlHash], []); + root.file("scenario.lua", controlFile.nodeStream("nodebuffer")); } else { throw new Error(`Unable to patch save, unknown scenario (${controlHash})`); } diff --git a/packages/lib/src/data/ModPack.ts b/packages/lib/src/data/ModPack.ts index 4ad3e00e..094a9248 100644 --- a/packages/lib/src/data/ModPack.ts +++ b/packages/lib/src/data/ModPack.ts @@ -395,7 +395,7 @@ export default class ModPack { ]; const integerVersion = integerFactorioVersion(factorioVersion); - if (integerVersion > integerFactorioVersion("1.2")) { + if (integerVersion >= integerFactorioVersion("1.2")) { defaultMods = defaultMods.concat([ { name: "elevated-rails", enabled: false, version: factorioVersion }, { name: "quality", enabled: false, version: factorioVersion }, diff --git a/packages/web_ui/src/components/ModPackViewPage.tsx b/packages/web_ui/src/components/ModPackViewPage.tsx index 21108611..d16819af 100644 --- a/packages/web_ui/src/components/ModPackViewPage.tsx +++ b/packages/web_ui/src/components/ModPackViewPage.tsx @@ -679,7 +679,10 @@ function applyModPackChanges(modPack: lib.ModPack, changes: ModChange[]) { let modifiedModPack = modPack.shallowClone(); for (let change of changes) { // Only modify fields that change to reduce re-renders - if (["mods.set", "mods.delete"].includes(change.type) && modifiedModPack.mods === modPack.mods) { + if ( + ["mods.set", "mods.delete", "factorioVersion"].includes(change.type) + && modifiedModPack.mods === modPack.mods + ) { modifiedModPack.mods = new Map(modifiedModPack.mods); } if ( @@ -697,22 +700,30 @@ function applyModPackChanges(modPack: lib.ModPack, changes: ModChange[]) { modifiedModPack.name = change.value; } else if (change.type === "description") { modifiedModPack.description = change.value; - } else if (change.type === "factorioVersion") { - modifiedModPack.factorioVersion = change.value; } else if (change.type === "mods.set") { - if (change.name) { - modifiedModPack.mods.set(change.name, change.value as lib.ModRecord); - } + modifiedModPack.mods.set(change.name, change.value as lib.ModRecord); } else if (change.type === "mods.delete") { - modifiedModPack.mods.delete(change.name!); + modifiedModPack.mods.delete(change.name); } else if (change.type === "settings.set") { - if (change.name) { - modifiedModPack.settings[change.scope].set(change.name, change.value); - } + modifiedModPack.settings[change.scope].set(change.name, change.value); } else if (change.type === "settings.delete") { - if (change.name) { - modifiedModPack.settings[change.scope].delete(change.name); + modifiedModPack.settings[change.scope].delete(change.name); + } else if (change.type === "factorioVersion") { + const newBuiltinMods = lib.ModPack.getBuiltinMods(change.value); + for (const newBuiltinMod of newBuiltinMods) { + const builtinMod = modifiedModPack.mods.get(newBuiltinMod.name); + if (builtinMod) { newBuiltinMod.enabled = builtinMod.enabled; } + modifiedModPack.mods.set(newBuiltinMod.name, newBuiltinMod); } + + const oldBuiltinMods = lib.ModPack.getBuiltinMods(modifiedModPack.factorioVersion); + for (const oldBuiltinMod of oldBuiltinMods) { + if (!newBuiltinMods.some(builtinMod => builtinMod.name === oldBuiltinMod.name)) { + modifiedModPack.mods.delete(oldBuiltinMod.name); + } + } + + modifiedModPack.factorioVersion = change.value; } else { throw new Error(`Unknown change type ${change.type}`); } @@ -879,8 +890,9 @@ export default function ModPackViewPage() { name="factorioVersion" style={{ marginBottom: 0 }} rules={[{ - pattern: /^\d+\.\d+\.\d+?$/, - message: "Must be an a.b.c version number.", + required: true, + pattern: /^\d+\.\d+(\.\d+)?$/, + message: "Must be an a.b or a.b.c version number.", }]} > builtinMod.name) + lib.ModPack.getBuiltinMods(modifiedModPack.factorioVersion).map(builtinMod => builtinMod.name) } />