diff --git a/OpenRA.Mods.Common/Lint/CheckChromeHotkeys.cs b/OpenRA.Mods.Common/Lint/CheckChromeHotkeys.cs index 212f27ddfb..df3f8490ce 100644 --- a/OpenRA.Mods.Common/Lint/CheckChromeHotkeys.cs +++ b/OpenRA.Mods.Common/Lint/CheckChromeHotkeys.cs @@ -20,6 +20,16 @@ using OpenRA.Widgets; namespace OpenRA.Mods.Common.Lint { + [AttributeUsage(AttributeTargets.Class)] + public sealed class ChromeLogicArgsHotkeys : Attribute + { + public string[] LogicArgKeys; + public ChromeLogicArgsHotkeys(params string[] logicArgKeys) + { + LogicArgKeys = logicArgKeys; + } + } + class CheckChromeHotkeys : ILintPass { public void Run(Action emitError, Action emitWarning, ModData modData) @@ -61,6 +71,27 @@ namespace OpenRA.Mods.Common.Lint } } + // Logic classes can declare the data key names that specify hotkeys + if (node.Key == "Logic" && node.Value.Nodes.Any()) + { + var typeNames = FieldLoader.GetValue(node.Key, node.Value.Value); + var checkArgKeys = new List(); + foreach (var typeName in typeNames) + { + var type = Game.ModData.ObjectCreator.FindType(typeName); + if (type == null) + continue; + + checkArgKeys.AddRange(type.GetCustomAttributes(true).SelectMany(x => x.LogicArgKeys)); + } + + Hotkey unused; + foreach (var n in node.Value.Nodes) + if (checkArgKeys.Contains(n.Key)) + if (!namedKeys.Contains(n.Value.Value) && !Hotkey.TryParse(n.Value.Value, out unused)) + emitError("{0} {1}:{2} refers to a Key named `{3}` that does not exist".F(filename, node.Value.Value, n.Key, n.Value.Value)); + } + if (node.Value.Nodes != null) CheckInner(modData, namedKeys, checkWidgetFields, node.Value.Nodes, filename, node, emitError); }