#region Copyright & License Information /* * Copyright (c) The OpenRA Developers and Contributors * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. For more * information, see COPYING. */ #endregion using System.Collections.Generic; using System.Linq; using OpenRA.Mods.Common.UpdateRules.Rules; namespace OpenRA.Mods.Common.UpdateRules { public sealed class UpdatePath { // Define known update paths from stable tags to the current bleed tip // // This file should be maintained separately on prep branches vs bleed. // The bleed version of this file should ignore the presence of the prep branch // and list rules from the playtest that forked the prep branch and current bleed. // The prep branch should maintain its own list of rules along the prep branch // until the eventual final release. // // When a final release has been tagged the update paths from the prep branch // can be merged back into bleed by replacing the forking-playtest-to-bleed path // with the prep playtest-to-playtest-to-release paths and finally a new/modified // release-to-bleed path. static readonly UpdatePath[] Paths = [ new("release-20230225", "release-20231010", [ new TextNotificationsDisplayWidgetRemoveTime(), new RenameEngineerRepair(), new ProductionTabsWidgetAddTabButtonCollection(), new RemoveTSRefinery(), new RenameMcvCrateAction(), new RenameContrailWidth(), new RemoveExperienceFromInfiltrates(), new AddColorPickerValueRange(), // Execute these rules last to avoid premature yaml merge crashes. new ExplicitSequenceFilenames(), new RemoveSequenceHasEmbeddedPalette(), new RemoveNegativeSequenceLength(), ]), new("release-20231010", "release-20250303", [ new RemoveValidRelationsFromCapturable(), new ExtractResourceStorageFromHarvester(), new ReplacePaletteModifiers(), new RemoveConyardChronoReturnAnimation(), new RemoveEditorSelectionLayerProperties(), new AddMarkerLayerOverlay(), new AddSupportPowerBlockedCursor(), new MovePreviewFacing(), new RenameOnDeath(), new RemoveParentTopParentLeftSubstitutions(), new RenameWidgetSubstitutions(), // Execute these rules last to avoid premature yaml merge crashes. new ReplaceCloakPalette(), new AbstractDocking(), ]), new("release-20250303", "release-20250330", []), new("release-20250330", [ // bleed only changes here. new ReplaceBaseAttackNotifier(), new RemoveBuildingInfoAllowPlacementOnResources(), new EditorMarkerTileLabels(), new RemoveBarracksTypesAndVehiclesTypesInBaseBuilderBotModule(), new RemoveAlwaysVisible(), // Execute these rules last to avoid premature yaml merge crashes. new WithDamageOverlayPropertyRename(), ]), ]; public static IReadOnlyCollection FromSource(ObjectCreator objectCreator, string source, bool chain = true) { // Use reflection to identify types var namedType = objectCreator.FindType(source); if (namedType != null && namedType.IsSubclassOf(typeof(UpdateRule))) return [(UpdateRule)objectCreator.CreateBasic(namedType)]; return Paths.FirstOrDefault(p => p.source == source)?.Rules(chain); } public static IEnumerable KnownPaths { get { return Paths.Select(p => p.source); } } public static IEnumerable KnownRules(ObjectCreator objectCreator) { return objectCreator.GetTypesImplementing().Select(t => t.Name); } readonly string source; readonly string chainToSource; readonly UpdateRule[] rules; UpdatePath(string source, UpdateRule[] rules) : this(source, null, rules) { } UpdatePath(string source, string chainToSource, UpdateRule[] rules) { this.source = source; this.rules = rules; this.chainToSource = chainToSource; } IReadOnlyCollection Rules(bool chain = true) { if (chainToSource != null && chain) { var child = Paths.First(p => p.source == chainToSource); return rules.Concat(child.Rules(chain)).ToList(); } return rules; } } }