diff --git a/ContentPatcher/Framework/Migrations/BaseMigration.cs b/ContentPatcher/Framework/Migrations/BaseMigration.cs
index 1d94ce870..d7953d79f 100644
--- a/ContentPatcher/Framework/Migrations/BaseMigration.cs
+++ b/ContentPatcher/Framework/Migrations/BaseMigration.cs
@@ -13,10 +13,10 @@ namespace ContentPatcher.Framework.Migrations
internal abstract class BaseMigration : IMigration
{
/*********
- ** Private methods
+ ** Fields
*********/
/// The tokens added in this format version.
- protected InvariantSet? AddedTokens { get; set; }
+ protected InvariantSet? AddedTokens;
/*********
diff --git a/ContentPatcher/Framework/Migrations/BaseRuntimeMigration.cs b/ContentPatcher/Framework/Migrations/BaseRuntimeMigration.cs
index a19710a41..87d61a401 100644
--- a/ContentPatcher/Framework/Migrations/BaseRuntimeMigration.cs
+++ b/ContentPatcher/Framework/Migrations/BaseRuntimeMigration.cs
@@ -1,4 +1,7 @@
+using System;
using System.Diagnostics.CodeAnalysis;
+using ContentPatcher.Framework.Conditions;
+using ContentPatcher.Framework.Migrations.Internal;
using ContentPatcher.Framework.Patches;
using StardewModdingAPI;
@@ -7,12 +10,30 @@ namespace ContentPatcher.Framework.Migrations
/// The base implementation for a format version migrator which overrides patches at runtime.
internal abstract class BaseRuntimeMigration : BaseMigration, IRuntimeMigration
{
+ /*********
+ ** Fields
+ *********/
+ /// The migrators that convert older patches to a newer asset or format.
+ /// For each edit, the first migrator which applies or returns errors is used.
+ protected IEditAssetMigrator[] RuntimeEditDataMigrators = Array.Empty();
+
+
/*********
** Public methods
*********/
///
public virtual IAssetName? RedirectTarget(IAssetName assetName, IPatch patch)
{
+ foreach (IEditAssetMigrator migrator in this.RuntimeEditDataMigrators)
+ {
+ if (migrator.AppliesTo(assetName))
+ {
+ IAssetName? newName = migrator.RedirectTarget(assetName, patch);
+ if (newName != null)
+ return newName;
+ }
+ }
+
return null;
}
@@ -20,6 +41,18 @@ internal abstract class BaseRuntimeMigration : BaseMigration, IRuntimeMigration
public virtual bool TryApplyLoadPatch(LoadPatch patch, IAssetName assetName, [NotNullWhen(true)] ref T? asset, out string? error)
where T : notnull
{
+ foreach (IEditAssetMigrator migrator in this.RuntimeEditDataMigrators)
+ {
+ if (migrator.AppliesTo(patch.TargetAssetBeforeRedirection ?? assetName))
+ {
+ if (migrator.TryApplyLoadPatch(patch, assetName, ref asset, out error))
+ return true;
+
+ if (error != null)
+ return false;
+ }
+ }
+
error = null;
return false;
}
@@ -28,6 +61,21 @@ public virtual bool TryApplyLoadPatch(LoadPatch patch, IAssetName assetName,
public virtual bool TryApplyEditPatch(IPatch patch, IAssetData asset, out string? error)
where T : notnull
{
+ if (patch is EditDataPatch editPatch)
+ {
+ foreach (IEditAssetMigrator migrator in this.RuntimeEditDataMigrators)
+ {
+ if (migrator.AppliesTo(patch.TargetAssetBeforeRedirection ?? asset.Name))
+ {
+ if (migrator.TryApplyEditPatch(editPatch, asset, out error))
+ return true;
+
+ if (error != null)
+ return false;
+ }
+ }
+ }
+
error = null;
return false;
}
diff --git a/ContentPatcher/Framework/Migrations/Internal/IEditAssetMigrator.cs b/ContentPatcher/Framework/Migrations/Internal/IEditAssetMigrator.cs
new file mode 100644
index 000000000..dfc3b715b
--- /dev/null
+++ b/ContentPatcher/Framework/Migrations/Internal/IEditAssetMigrator.cs
@@ -0,0 +1,24 @@
+using System.Diagnostics.CodeAnalysis;
+using ContentPatcher.Framework.Conditions;
+using ContentPatcher.Framework.Patches;
+using StardewModdingAPI;
+
+namespace ContentPatcher.Framework.Migrations.Internal
+{
+ /// A migrator which applies older patches to a newer asset or format.
+ internal interface IEditAssetMigrator
+ {
+ /// Get whether this migration applies to a patch.
+ /// The asset name to check. If the asset was redirected, this is the asset name before redirection.
+ bool AppliesTo(IAssetName assetName);
+
+ ///
+ IAssetName? RedirectTarget(IAssetName assetName, IPatch patch);
+
+ ///
+ bool TryApplyLoadPatch(LoadPatch patch, IAssetName assetName, [NotNullWhen(true)] ref T? asset, out string? error);
+
+ ///
+ bool TryApplyEditPatch(EditDataPatch patch, IAssetData asset, out string? error);
+ }
+}
diff --git a/ContentPatcher/Framework/Migrations/Internal/RuntimeMigrationHelper.cs b/ContentPatcher/Framework/Migrations/Internal/RuntimeMigrationHelper.cs
index 5d182a422..4980cec4e 100644
--- a/ContentPatcher/Framework/Migrations/Internal/RuntimeMigrationHelper.cs
+++ b/ContentPatcher/Framework/Migrations/Internal/RuntimeMigrationHelper.cs
@@ -14,6 +14,9 @@ internal static class RuntimeMigrationHelper
private static readonly Dictionary ParseObjectIdCache = new();
+ /*********
+ ** Public methods
+ *********/
/// Get the unqualified object ID, if it's a valid object ID.
/// The raw item ID, which may be an item query or non-object ID.
/// Returns the unqualified object ID, or null if it's not a valid object ID.
diff --git a/ContentPatcher/Framework/Migrations/Migration_2_0.cs b/ContentPatcher/Framework/Migrations/Migration_2_0.cs
index dd3711ea6..4545a5bc4 100644
--- a/ContentPatcher/Framework/Migrations/Migration_2_0.cs
+++ b/ContentPatcher/Framework/Migrations/Migration_2_0.cs
@@ -1,7 +1,6 @@
using System.Diagnostics.CodeAnalysis;
using ContentPatcher.Framework.Conditions;
using ContentPatcher.Framework.ConfigModels;
-using ContentPatcher.Framework.Patches;
using Pathoschild.Stardew.Common.Utilities;
using StardewModdingAPI;
@@ -11,14 +10,6 @@ namespace ContentPatcher.Framework.Migrations
[SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Named for clarity.")]
internal partial class Migration_2_0 : BaseRuntimeMigration
{
- /*********
- ** Fields
- *********/
- /// The migrators that convert pre-1.6 edit patches to a newer asset or format.
- /// For each edit, the first migrator which applies or returns errors is used.
- private readonly IEditAssetMigrator[] Migrators;
-
-
/*********
** Public methods
*********/
@@ -29,12 +20,8 @@ public Migration_2_0()
this.AddedTokens = new InvariantSet(
nameof(ConditionType.ModId)
);
- this.MigrationWarnings = [
- "Some content packs haven't been updated for Stardew Valley 1.6.0. Content Patcher will try to auto-migrate them, but compatibility isn't guaranteed."
- ];
-
- this.Migrators = new IEditAssetMigrator[]
- {
+ this.MigrationWarnings = ["Some content packs haven't been updated for Stardew Valley 1.6.0. Content Patcher will try to auto-migrate them, but compatibility isn't guaranteed."];
+ this.RuntimeEditDataMigrators = [
new BigCraftableInformationMigrator(),
new BlueprintsMigrator(),
new BootsMigrator(),
@@ -42,7 +29,7 @@ public Migration_2_0()
new LocationsMigrator(),
new NpcDispositionsMigrator(),
new ObjectInformationMigrator()
- };
+ ];
}
///
@@ -63,82 +50,5 @@ public override bool TryMigrate(ref PatchConfig[] patches, [NotNullWhen(false)]
return true;
}
-
- ///
- public override IAssetName? RedirectTarget(IAssetName assetName, IPatch patch)
- {
- foreach (IEditAssetMigrator migrator in this.Migrators)
- {
- if (migrator.AppliesTo(assetName))
- {
- IAssetName? newName = migrator.RedirectTarget(assetName, patch);
- if (newName != null)
- return newName;
- }
- }
-
- return base.RedirectTarget(assetName, patch);
- }
-
- ///
- public override bool TryApplyLoadPatch(LoadPatch patch, IAssetName assetName, [NotNullWhen(true)] ref T? asset, out string? error)
- where T : default
- {
- foreach (IEditAssetMigrator migrator in this.Migrators)
- {
- if (migrator.AppliesTo(patch.TargetAssetBeforeRedirection ?? assetName))
- {
- if (migrator.TryApplyLoadPatch(patch, assetName, ref asset, out error))
- return true;
-
- if (error != null)
- return false;
- }
- }
-
- return base.TryApplyLoadPatch(patch, assetName, ref asset, out error);
- }
-
- ///
- public override bool TryApplyEditPatch(IPatch patch, IAssetData asset, out string? error)
- {
- if (patch is EditDataPatch editPatch)
- {
- foreach (IEditAssetMigrator migrator in this.Migrators)
- {
- if (migrator.AppliesTo(patch.TargetAssetBeforeRedirection ?? asset.Name))
- {
- if (migrator.TryApplyEditPatch(editPatch, asset, out error))
- return true;
-
- if (error != null)
- return false;
- }
- }
- }
-
- return base.TryApplyEditPatch(patch, asset, out error);
- }
-
-
- /*********
- ** Private methods
- *********/
- /// The migration logic to apply pre-1.6 edit patches to a new asset or format.
- private interface IEditAssetMigrator
- {
- /// Get whether this migration applies to a patch.
- /// The asset name to check. If the asset was redirected, this is the asset name before redirection.
- bool AppliesTo(IAssetName assetName);
-
- ///
- IAssetName? RedirectTarget(IAssetName assetName, IPatch patch);
-
- ///
- bool TryApplyLoadPatch(LoadPatch patch, IAssetName assetName, [NotNullWhen(true)] ref T? asset, out string? error);
-
- ///
- bool TryApplyEditPatch(EditDataPatch patch, IAssetData asset, out string? error);
- }
}
}