diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/20210321/UnhardcodeBaseBuilderBotModule.cs b/OpenRA.Mods.Common/UpdateRules/Rules/20210321/UnhardcodeBaseBuilderBotModule.cs index 7c970752c1..8541ae4acf 100644 --- a/OpenRA.Mods.Common/UpdateRules/Rules/20210321/UnhardcodeBaseBuilderBotModule.cs +++ b/OpenRA.Mods.Common/UpdateRules/Rules/20210321/UnhardcodeBaseBuilderBotModule.cs @@ -14,7 +14,7 @@ using System.Linq; namespace OpenRA.Mods.Common.UpdateRules.Rules { - public class UnhardcodeBaseBuilderBotModule : UpdateRule + public class UnhardcodeBaseBuilderBotModule : UpdateRule, IBeforeUpdateActors { MiniYamlNode defences; @@ -28,7 +28,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules public override string Description => "DefenseTypes were added."; - public override IEnumerable BeforeUpdateActors(ModData modData, List resolvedActors) + public IEnumerable BeforeUpdateActors(ModData modData, List resolvedActors) { var defences = new List(); diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/20210321/UnhardcodeSquadManager.cs b/OpenRA.Mods.Common/UpdateRules/Rules/20210321/UnhardcodeSquadManager.cs index 61b2b7d44a..05ee909279 100644 --- a/OpenRA.Mods.Common/UpdateRules/Rules/20210321/UnhardcodeSquadManager.cs +++ b/OpenRA.Mods.Common/UpdateRules/Rules/20210321/UnhardcodeSquadManager.cs @@ -14,7 +14,7 @@ using System.Linq; namespace OpenRA.Mods.Common.UpdateRules.Rules { - public class UnhardcodeSquadManager : UpdateRule + public class UnhardcodeSquadManager : UpdateRule, IBeforeUpdateActors { readonly List addNodes = new(); @@ -28,7 +28,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules public override string Description => "AirUnitsTypes and ProtectionTypes were added."; - public override IEnumerable BeforeUpdateActors(ModData modData, List resolvedActors) + public IEnumerable BeforeUpdateActors(ModData modData, List resolvedActors) { var aircraft = new List(); var vips = new List(); diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/20230225/ExplicitSequenceFilenames.cs b/OpenRA.Mods.Common/UpdateRules/Rules/20230225/ExplicitSequenceFilenames.cs index 0622646a9a..f7d17f17bf 100644 --- a/OpenRA.Mods.Common/UpdateRules/Rules/20230225/ExplicitSequenceFilenames.cs +++ b/OpenRA.Mods.Common/UpdateRules/Rules/20230225/ExplicitSequenceFilenames.cs @@ -15,7 +15,7 @@ using System.Reflection; namespace OpenRA.Mods.Common.UpdateRules.Rules { - public class ExplicitSequenceFilenames : UpdateRule + public class ExplicitSequenceFilenames : UpdateRule, IBeforeUpdateSequences { public override string Name => "Sequence filenames must be specified explicitly."; @@ -33,7 +33,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules bool reportModYamlChanges; bool disabled; - public override IEnumerable BeforeUpdateSequences(ModData modData, List resolvedImagesNodes) + public IEnumerable BeforeUpdateSequences(ModData modData, List resolvedImagesNodes) { // Keep a resolved copy of the sequences so we can account for values imported through inheritance or Defaults. // This will be modified during processing, so take a deep copy to avoid side-effects on other update rules. diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/20230225/RemoveNegativeSequenceLength.cs b/OpenRA.Mods.Common/UpdateRules/Rules/20230225/RemoveNegativeSequenceLength.cs index 8f7df1905d..1b73548c58 100644 --- a/OpenRA.Mods.Common/UpdateRules/Rules/20230225/RemoveNegativeSequenceLength.cs +++ b/OpenRA.Mods.Common/UpdateRules/Rules/20230225/RemoveNegativeSequenceLength.cs @@ -15,7 +15,7 @@ using System.Linq; namespace OpenRA.Mods.Common.UpdateRules.Rules { - public class RemoveNegativeSequenceLength : UpdateRule + public class RemoveNegativeSequenceLength : UpdateRule, IBeforeUpdateSequences { public override string Name => "Negative sequence length is no longer allowed."; @@ -23,7 +23,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules List resolvedImagesNodes; - public override IEnumerable BeforeUpdateSequences(ModData modData, List resolvedImagesNodes) + public IEnumerable BeforeUpdateSequences(ModData modData, List resolvedImagesNodes) { this.resolvedImagesNodes = resolvedImagesNodes; yield break; diff --git a/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs b/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs index dbe9a808a3..fd9ef0a10e 100644 --- a/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs +++ b/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs @@ -72,34 +72,38 @@ namespace OpenRA.Mods.Common.UpdateRules new RemoveSmokeTrailWhenDamaged(), new ReplaceCrateSecondsWithTicks(), new UseMillisecondsForSounds(), - new UnhardcodeSquadManager(), new RenameSupportPowerDescription(), new AttackBomberFacingTolerance(), new AttackFrontalFacingTolerance(), new RenameCloakTypes(), new SplitNukePowerMissileImage(), new ReplaceSequenceEmbeddedPalette(), - new UnhardcodeBaseBuilderBotModule(), new UnhardcodeVeteranProductionIconOverlay(), new RenameContrailProperties(), new RemoveDomainIndex(), new AddControlGroups(), + + // Execute these rules last to avoid premature yaml merge crashes. + new UnhardcodeSquadManager(), + new UnhardcodeBaseBuilderBotModule(), }), new UpdatePath("release-20230225", new UpdateRule[] { // bleed only changes here new TextNotificationsDisplayWidgetRemoveTime(), - new ExplicitSequenceFilenames(), new RenameEngineerRepair(), new ProductionTabsWidgetAddTabButtonCollection(), new RemoveTSRefinery(), new RenameMcvCrateAction(), - new RemoveSequenceHasEmbeddedPalette(), new RenameContrailWidth(), - new RemoveNegativeSequenceLength(), new RemoveExperienceFromInfiltrates(), new AddColorPickerValueRange(), + + // Execute these rules last to avoid premature yaml merge crashes. + new ExplicitSequenceFilenames(), + new RemoveSequenceHasEmbeddedPalette(), + new RemoveNegativeSequenceLength(), }) }; diff --git a/OpenRA.Mods.Common/UpdateRules/UpdateRule.cs b/OpenRA.Mods.Common/UpdateRules/UpdateRule.cs index 5589de3c96..d56d86c294 100644 --- a/OpenRA.Mods.Common/UpdateRules/UpdateRule.cs +++ b/OpenRA.Mods.Common/UpdateRules/UpdateRule.cs @@ -36,9 +36,21 @@ namespace OpenRA.Mods.Common.UpdateRules public virtual IEnumerable BeforeUpdate(ModData modData) { yield break; } public virtual IEnumerable AfterUpdate(ModData modData) { yield break; } + } - public virtual IEnumerable BeforeUpdateActors(ModData modData, List resolvedActors) { yield break; } - public virtual IEnumerable BeforeUpdateWeapons(ModData modData, List resolvedWeapons) { yield break; } - public virtual IEnumerable BeforeUpdateSequences(ModData modData, List resolvedImages) { yield break; } + // These aren't part of the UpdateRule class as to avoid premature yaml merge crashes when updating maps. + public interface IBeforeUpdateActors + { + IEnumerable BeforeUpdateActors(ModData modData, List resolvedActors) { yield break; } + } + + public interface IBeforeUpdateWeapons + { + IEnumerable BeforeUpdateWeapons(ModData modData, List resolvedWeapons) { yield break; } + } + + public interface IBeforeUpdateSequences + { + IEnumerable BeforeUpdateSequences(ModData modData, List resolvedImages) { yield break; } } } diff --git a/OpenRA.Mods.Common/UpdateRules/UpdateUtils.cs b/OpenRA.Mods.Common/UpdateRules/UpdateUtils.cs index 3b2172df88..ea921abcb8 100644 --- a/OpenRA.Mods.Common/UpdateRules/UpdateUtils.cs +++ b/OpenRA.Mods.Common/UpdateRules/UpdateUtils.cs @@ -114,8 +114,11 @@ namespace OpenRA.Mods.Common.UpdateRules var mapRulesNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Rules"); if (mapRulesNode != null) { - var resolvedActors = LoadMapYaml(modData.DefaultFileSystem, mapPackage, modData.Manifest.Rules, mapRulesNode.Value); - manualSteps.AddRange(rule.BeforeUpdateActors(modData, resolvedActors)); + if (rule is IBeforeUpdateActors before) + { + var resolvedActors = LoadMapYaml(modData.DefaultFileSystem, mapPackage, modData.Manifest.Rules, mapRulesNode.Value); + manualSteps.AddRange(before.BeforeUpdateActors(modData, resolvedActors)); + } var mapRules = LoadInternalMapYaml(modData, mapPackage, mapRulesNode.Value, externalFilenames); manualSteps.AddRange(ApplyTopLevelTransform(modData, mapRules, rule.UpdateActorNode)); @@ -125,8 +128,11 @@ namespace OpenRA.Mods.Common.UpdateRules var mapWeaponsNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Weapons"); if (mapWeaponsNode != null) { - var resolvedWeapons = LoadMapYaml(modData.DefaultFileSystem, mapPackage, modData.Manifest.Weapons, mapWeaponsNode.Value); - manualSteps.AddRange(rule.BeforeUpdateWeapons(modData, resolvedWeapons)); + if (rule is IBeforeUpdateWeapons before) + { + var resolvedWeapons = LoadMapYaml(modData.DefaultFileSystem, mapPackage, modData.Manifest.Weapons, mapWeaponsNode.Value); + manualSteps.AddRange(before.BeforeUpdateWeapons(modData, resolvedWeapons)); + } var mapWeapons = LoadInternalMapYaml(modData, mapPackage, mapWeaponsNode.Value, externalFilenames); manualSteps.AddRange(ApplyTopLevelTransform(modData, mapWeapons, rule.UpdateWeaponNode)); @@ -136,8 +142,11 @@ namespace OpenRA.Mods.Common.UpdateRules var mapSequencesNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Sequences"); if (mapSequencesNode != null) { - var resolvedImages = LoadMapYaml(modData.DefaultFileSystem, mapPackage, modData.Manifest.Sequences, mapSequencesNode.Value); - manualSteps.AddRange(rule.BeforeUpdateSequences(modData, resolvedImages)); + if (rule is IBeforeUpdateSequences before) + { + var resolvedImages = LoadMapYaml(modData.DefaultFileSystem, mapPackage, modData.Manifest.Sequences, mapSequencesNode.Value); + manualSteps.AddRange(before.BeforeUpdateSequences(modData, resolvedImages)); + } var mapSequences = LoadInternalMapYaml(modData, mapPackage, mapSequencesNode.Value, externalFilenames); manualSteps.AddRange(ApplyTopLevelTransform(modData, mapSequences, rule.UpdateSequenceNode)); @@ -229,16 +238,28 @@ namespace OpenRA.Mods.Common.UpdateRules manualSteps.AddRange(rule.BeforeUpdate(modData)); - var resolvedActors = MiniYaml.Load(modData.DefaultFileSystem, modData.Manifest.Rules, null); - manualSteps.AddRange(rule.BeforeUpdateActors(modData, resolvedActors)); + if (rule is IBeforeUpdateActors beforeActors) + { + var resolvedActors = MiniYaml.Load(modData.DefaultFileSystem, modData.Manifest.Rules, null); + manualSteps.AddRange(beforeActors.BeforeUpdateActors(modData, resolvedActors)); + } + manualSteps.AddRange(ApplyTopLevelTransform(modData, modRules, rule.UpdateActorNode)); - var resolvedWeapons = MiniYaml.Load(modData.DefaultFileSystem, modData.Manifest.Weapons, null); - manualSteps.AddRange(rule.BeforeUpdateWeapons(modData, resolvedWeapons)); + if (rule is IBeforeUpdateWeapons beforeWeapons) + { + var resolvedWeapons = MiniYaml.Load(modData.DefaultFileSystem, modData.Manifest.Weapons, null); + manualSteps.AddRange(beforeWeapons.BeforeUpdateWeapons(modData, resolvedWeapons)); + } + manualSteps.AddRange(ApplyTopLevelTransform(modData, modWeapons, rule.UpdateWeaponNode)); - var resolvedSequences = MiniYaml.Load(modData.DefaultFileSystem, modData.Manifest.Sequences, null); - manualSteps.AddRange(rule.BeforeUpdateSequences(modData, resolvedSequences)); + if (rule is IBeforeUpdateSequences beforeSequences) + { + var resolvedImages = MiniYaml.Load(modData.DefaultFileSystem, modData.Manifest.Sequences, null); + manualSteps.AddRange(beforeSequences.BeforeUpdateSequences(modData, resolvedImages)); + } + manualSteps.AddRange(ApplyTopLevelTransform(modData, modSequences, rule.UpdateSequenceNode)); manualSteps.AddRange(ApplyTopLevelTransform(modData, modTilesets, rule.UpdateTilesetNode));