From f342ecf18adf686f01f7ee1f979fecdc58d168ae Mon Sep 17 00:00:00 2001 From: Andre Mohren Date: Mon, 24 Sep 2018 19:33:53 +0000 Subject: [PATCH] Added UpdateRule. --- OpenRA.Mods.Common/OpenRA.Mods.Common.csproj | 1 + .../Rules/DefineNotificationDefaults.cs | 139 ++++++++++++++++++ OpenRA.Mods.Common/UpdateRules/UpdatePath.cs | 3 +- OpenRA.Mods.Common/UpdateRules/UpdateUtils.cs | 4 +- 4 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 OpenRA.Mods.Common/UpdateRules/Rules/DefineNotificationDefaults.cs diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index 81df62773f..589933bd1e 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -910,6 +910,7 @@ + diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/DefineNotificationDefaults.cs b/OpenRA.Mods.Common/UpdateRules/Rules/DefineNotificationDefaults.cs new file mode 100644 index 0000000000..4cd1cbe118 --- /dev/null +++ b/OpenRA.Mods.Common/UpdateRules/Rules/DefineNotificationDefaults.cs @@ -0,0 +1,139 @@ +#region Copyright & License Information +/* + * Copyright 2007-2018 The OpenRA Developers (see AUTHORS) + * 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; +using System.Collections.Generic; +using System.Linq; + +namespace OpenRA.Mods.Common.UpdateRules.Rules +{ + public class DefineNotificationDefaults : UpdateRule + { + public override string Name { get { return "Move mod-specific notifications to yaml"; } } + public override string Description + { + get + { + return "Mod-specific default notifications values have been removed from several traits and the Radar widget\n" + + "(" + traits.Select(f => f.Trait).JoinWith(", ") + ")\n" + + "The mod chrome is updated automatically and uses of these traits are listed for inspection so the values can be overriden in yaml."; + } + } + + class TraitWrapper + { + public readonly string Trait; + public readonly Dictionary Fields; + public List Uses = new List(); + + public TraitWrapper(string trait, Dictionary fields) + { + Trait = trait; + Fields = fields; + } + } + + TraitWrapper[] traits = + { + new TraitWrapper("PrimaryBuilding", new Dictionary { + { "SelectionNotification", "PrimaryBuildingSelected" } + }), + new TraitWrapper("RepairableBuilding", new Dictionary { + { "RepairingNotification", "Repairing" } + }), + new TraitWrapper("RepairsUnits", new Dictionary { + { "StartRepairingNotification", "Repairing" } + }), + new TraitWrapper("GainsExperience", new Dictionary { + { "LevelUpNotification", "LevelUp" } + }), + new TraitWrapper("MissionObjectives", new Dictionary { + { "WinNotification", "Win" }, + { "LoseNotification", "Lose" }, + { "LeaveNotification", "Leave" } + }), + new TraitWrapper("PlaceBuilding", new Dictionary { + { "NewOptionsNotification", "NewOptions" }, + { "CannotPlaceNotification", "BuildingCannotPlaceAudio" } + }), + new TraitWrapper("PlayerResources", new Dictionary { + { "CashTickUpNotification", "CashTickUp" }, + { "CashTickDownNotification", "CashTickDown" } + }), + new TraitWrapper("ProductionQueue", new Dictionary { + { "ReadyAudio", "UnitReady" }, + { "BlockedAudio", "NoBuild" }, + { "QueuedAudio", "Training" }, + { "OnHoldAudio", "OnHold" }, + { "CancelledAudio", "Cancelled" } + }), + new TraitWrapper("PowerManager", new Dictionary { + { "SpeechNotification", "LowPower" } + }) + }; + + string BuildMessage(TraitWrapper t) + { + return "Default notification values have been removed from {0}.\n".F(t.Trait) + + "You may wish to explicitly define the following overrides:\n " + t.Trait + ":\n" + + UpdateUtils.FormatMessageList(t.Fields.Select(kv => " " + kv.Key + ": " + kv.Value), separator: " ") + + "\non the following actors (if they have not already been inherited from a parent).\n" + + UpdateUtils.FormatMessageList(t.Uses); + } + + public override IEnumerable AfterUpdate(ModData modData) + { + foreach (var t in traits) + { + if (t.Uses.Any()) + yield return BuildMessage(t); + + t.Uses.Clear(); + } + } + + public override IEnumerable UpdateActorNode(ModData modData, MiniYamlNode actorNode) + { + foreach (var t in traits) + { + foreach (var traitNode in actorNode.ChildrenMatching(t.Trait)) + { + foreach (var f in t.Fields) + { + var node = traitNode.LastChildMatching(f.Key); + if (node == null) + { + var location = "{0} ({1})".F(actorNode.Key, traitNode.Location.Filename); + if (!t.Uses.Contains(location)) + t.Uses.Add(location); + } + } + } + } + + yield break; + } + + public override IEnumerable UpdateChromeNode(ModData modData, MiniYamlNode chromeNode) + { + foreach (var node in chromeNode.ChildrenMatching("Radar")) + { + if (!node.ChildrenMatching("SoundUp").Any()) + node.AddNode("SoundUp", "RadarUp"); + + if (!node.ChildrenMatching("SoundDown").Any()) + node.AddNode("SoundDown", "RadarDown"); + } + + yield break; + } + } +} diff --git a/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs b/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs index 7b849791a2..5e1042b75d 100644 --- a/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs +++ b/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs @@ -87,7 +87,8 @@ namespace OpenRA.Mods.Common.UpdateRules new UpdatePath("playtest-20180729", new UpdateRule[] { // Bleed only changes here - new RenameEditorTilesetFilter() + new RenameEditorTilesetFilter(), + new DefineNotificationDefaults(), }) }; diff --git a/OpenRA.Mods.Common/UpdateRules/UpdateUtils.cs b/OpenRA.Mods.Common/UpdateRules/UpdateUtils.cs index 23eda33dc5..6889e95614 100644 --- a/OpenRA.Mods.Common/UpdateRules/UpdateUtils.cs +++ b/OpenRA.Mods.Common/UpdateRules/UpdateUtils.cs @@ -221,10 +221,10 @@ namespace OpenRA.Mods.Common.UpdateRules yield return manualStep; } - public static string FormatMessageList(IEnumerable messages, int indent = 0) + public static string FormatMessageList(IEnumerable messages, int indent = 0, string separator = "*") { var prefix = string.Concat(Enumerable.Repeat(" ", indent)); - return string.Join("\n", messages.Select(m => prefix + " * {0}".F(m.Replace("\n", "\n " + prefix)))); + return string.Join("\n", messages.Select(m => prefix + " {0} {1}".F(separator, m.Replace("\n", "\n " + prefix)))); } }