From 51a2ca8253d092b4c9420ab5cca6c85c4b9a45af Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Thu, 21 Jun 2018 22:56:37 +0000 Subject: [PATCH] Add CheckUnknownWeaponFields lint check. --- .../Lint/CheckUnknownWeaponFields.cs | 98 +++++++++++++++++++ OpenRA.Mods.Common/OpenRA.Mods.Common.csproj | 1 + 2 files changed, 99 insertions(+) create mode 100644 OpenRA.Mods.Common/Lint/CheckUnknownWeaponFields.cs diff --git a/OpenRA.Mods.Common/Lint/CheckUnknownWeaponFields.cs b/OpenRA.Mods.Common/Lint/CheckUnknownWeaponFields.cs new file mode 100644 index 0000000000..ed9089c45d --- /dev/null +++ b/OpenRA.Mods.Common/Lint/CheckUnknownWeaponFields.cs @@ -0,0 +1,98 @@ +#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; +using OpenRA.GameRules; + +namespace OpenRA.Mods.Common.Lint +{ + class CheckUnknownWeaponFields : ILintPass, ILintMapPass + { + string NormalizeName(string key) + { + var name = key.Split('@')[0]; + if (name.StartsWith("-", StringComparison.Ordinal)) + return name.Substring(1); + + return name; + } + + void CheckWeapons(IEnumerable weapons, Action emitError, Action emitWarning, ModData modData) + { + var weaponInfo = typeof(WeaponInfo); + foreach (var weapon in weapons) + { + foreach (var field in weapon.Value.Nodes) + { + // Removals can never define children + if (field.Key.StartsWith("-", StringComparison.Ordinal) && field.Value.Nodes.Any()) + { + emitError("{0} has child nodes, which is not valid for removals.".F(field.Key)); + continue; + } + + var fieldName = NormalizeName(field.Key); + if (fieldName == "Projectile" && !string.IsNullOrEmpty(field.Value.Value)) + { + var projectileName = NormalizeName(field.Value.Value); + var projectileInfo = modData.ObjectCreator.FindType(projectileName + "Info"); + foreach (var projectileField in field.Value.Nodes) + { + var projectileFieldName = NormalizeName(projectileField.Key); + if (projectileInfo.GetField(projectileFieldName) == null) + emitError("{0} refers to a projectile field `{1}` that does not exist on `{2}`.".F(projectileField.Location, projectileFieldName, projectileName)); + } + } + else if (fieldName == "Warhead") + { + if (string.IsNullOrEmpty(field.Value.Value)) + { + emitWarning("{0} does not define a warhead type. Skipping unknown field check.".F(field.Location)); + continue; + } + + var warheadName = NormalizeName(field.Value.Value); + var warheadInfo = modData.ObjectCreator.FindType(warheadName + "Warhead"); + foreach (var warheadField in field.Value.Nodes) + { + var warheadFieldName = NormalizeName(warheadField.Key); + if (warheadInfo.GetField(warheadFieldName) == null) + emitError("{0} refers to a warhead field `{1}` that does not exist on `{2}`.".F(warheadField.Location, warheadFieldName, warheadName)); + } + } + else if (fieldName != "Inherits" && weaponInfo.GetField(fieldName) == null) + emitError("{0} refers to a weapon field `{1}` that does not exist.".F(field.Location, fieldName)); + } + } + } + + void ILintPass.Run(Action emitError, Action emitWarning, ModData modData) + { + foreach (var f in modData.Manifest.Weapons) + CheckWeapons(MiniYaml.FromStream(modData.DefaultFileSystem.Open(f), f), emitError, emitWarning, modData); + } + + void ILintMapPass.Run(Action emitError, Action emitWarning, ModData modData, Map map) + { + if (map.WeaponDefinitions != null && map.WeaponDefinitions.Value != null) + { + var mapFiles = FieldLoader.GetValue("value", map.WeaponDefinitions.Value); + foreach (var f in mapFiles) + CheckWeapons(MiniYaml.FromStream(map.Open(f), f), emitError, emitWarning, modData); + + if (map.WeaponDefinitions.Nodes.Any()) + CheckWeapons(map.WeaponDefinitions.Nodes, emitError, emitWarning, modData); + } + } + } +} diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index 2ad65d8c90..c5496d1d7f 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -885,6 +885,7 @@ +