From fb22c9a1e5bcf5c744788fbbcbc38eb0535b779c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Mail=C3=A4nder?= Date: Tue, 4 Aug 2015 14:04:48 +0200 Subject: [PATCH] test unchanged miniyaml rules only once --- .../Lint/CheckActorReferences.cs | 18 ++++++--- OpenRA.Mods.Common/Lint/CheckActors.cs | 3 ++ OpenRA.Mods.Common/Lint/CheckDeathTypes.cs | 9 ++++- .../Lint/CheckDefaultVisibility.cs | 7 +++- OpenRA.Mods.Common/Lint/CheckMapCordon.cs | 3 ++ OpenRA.Mods.Common/Lint/CheckPlayers.cs | 3 ++ .../Lint/CheckRevealFootprint.cs | 7 +++- OpenRA.Mods.Common/Lint/CheckSequences.cs | 30 +++++++++----- .../Lint/CheckSyncAnnotations.cs | 3 ++ .../Lint/CheckTraitPrerequisites.cs | 7 +++- OpenRA.Mods.Common/Lint/CheckUpgrades.cs | 39 +++++++++++-------- .../Lint/CheckVoiceReferences.cs | 13 +++++-- .../Lint/LintBuildablePrerequisites.cs | 11 ++++-- .../UtilityCommands/CheckYaml.cs | 20 +++++++--- 14 files changed, 123 insertions(+), 50 deletions(-) diff --git a/OpenRA.Mods.Common/Lint/CheckActorReferences.cs b/OpenRA.Mods.Common/Lint/CheckActorReferences.cs index a253fa8b11..d38b518975 100644 --- a/OpenRA.Mods.Common/Lint/CheckActorReferences.cs +++ b/OpenRA.Mods.Common/Lint/CheckActorReferences.cs @@ -9,6 +9,7 @@ #endregion using System; +using System.Linq; using System.Reflection; using OpenRA.Traits; @@ -20,24 +21,29 @@ namespace OpenRA.Mods.Common.Lint public void Run(Action emitError, Action emitWarning, Map map) { + if (map != null && !map.RuleDefinitions.Any()) + return; + + var rules = map == null ? Game.ModData.DefaultRules : map.Rules; + this.emitError = emitError; - foreach (var actorInfo in map.Rules.Actors) + foreach (var actorInfo in rules.Actors) foreach (var traitInfo in actorInfo.Value.Traits.WithInterface()) - CheckTrait(actorInfo.Value, traitInfo, map); + CheckTrait(actorInfo.Value, traitInfo, rules); } - void CheckTrait(ActorInfo actorInfo, ITraitInfo traitInfo, Map map) + void CheckTrait(ActorInfo actorInfo, ITraitInfo traitInfo, Ruleset rules) { var actualType = traitInfo.GetType(); foreach (var field in actualType.GetFields()) { if (field.HasAttribute()) - CheckReference(actorInfo, traitInfo, field, map.Rules.Actors, "actor"); + CheckReference(actorInfo, traitInfo, field, rules.Actors, "actor"); if (field.HasAttribute()) - CheckReference(actorInfo, traitInfo, field, map.Rules.Weapons, "weapon"); + CheckReference(actorInfo, traitInfo, field, rules.Weapons, "weapon"); if (field.HasAttribute()) - CheckReference(actorInfo, traitInfo, field, map.Rules.Voices, "voice"); + CheckReference(actorInfo, traitInfo, field, rules.Voices, "voice"); } } diff --git a/OpenRA.Mods.Common/Lint/CheckActors.cs b/OpenRA.Mods.Common/Lint/CheckActors.cs index 3018a857d8..3db292eb11 100644 --- a/OpenRA.Mods.Common/Lint/CheckActors.cs +++ b/OpenRA.Mods.Common/Lint/CheckActors.cs @@ -18,6 +18,9 @@ namespace OpenRA.Mods.Common.Lint { public void Run(Action emitError, Action emitWarning, Map map) { + if (map == null) + return; + var actorTypes = map.ActorDefinitions.Select(a => a.Value.Value); foreach (var actor in actorTypes) if (!map.Rules.Actors.Keys.Contains(actor.ToLowerInvariant())) diff --git a/OpenRA.Mods.Common/Lint/CheckDeathTypes.cs b/OpenRA.Mods.Common/Lint/CheckDeathTypes.cs index d4f4276563..8e6efc7b82 100644 --- a/OpenRA.Mods.Common/Lint/CheckDeathTypes.cs +++ b/OpenRA.Mods.Common/Lint/CheckDeathTypes.cs @@ -20,7 +20,12 @@ namespace OpenRA.Mods.Common.Lint { public void Run(Action emitError, Action emitWarning, Map map) { - foreach (var actorInfo in map.Rules.Actors) + if (map != null && !map.RuleDefinitions.Any()) + return; + + var rules = map == null ? Game.ModData.DefaultRules : map.Rules; + + foreach (var actorInfo in rules.Actors) { var animations = actorInfo.Value.Traits.WithInterface().ToList(); if (!animations.Any()) @@ -34,7 +39,7 @@ namespace OpenRA.Mods.Common.Lint if (!targetable.Any()) continue; - foreach (var weaponInfo in map.Rules.Weapons) + foreach (var weaponInfo in rules.Weapons) { var warheads = weaponInfo.Value.Warheads.OfType().Where(dw => dw.Damage > 0); diff --git a/OpenRA.Mods.Common/Lint/CheckDefaultVisibility.cs b/OpenRA.Mods.Common/Lint/CheckDefaultVisibility.cs index d43033e181..696b2b1cf8 100644 --- a/OpenRA.Mods.Common/Lint/CheckDefaultVisibility.cs +++ b/OpenRA.Mods.Common/Lint/CheckDefaultVisibility.cs @@ -20,7 +20,12 @@ namespace OpenRA.Mods.Common.Lint { public void Run(Action emitError, Action emitWarning, Map map) { - foreach (var actorInfo in map.Rules.Actors) + if (map != null && !map.RuleDefinitions.Any()) + return; + + var rules = map == null ? Game.ModData.DefaultRules : map.Rules; + + foreach (var actorInfo in rules.Actors) { if (actorInfo.Key.StartsWith("^")) continue; diff --git a/OpenRA.Mods.Common/Lint/CheckMapCordon.cs b/OpenRA.Mods.Common/Lint/CheckMapCordon.cs index c5e1aed3cd..242431b9b4 100644 --- a/OpenRA.Mods.Common/Lint/CheckMapCordon.cs +++ b/OpenRA.Mods.Common/Lint/CheckMapCordon.cs @@ -18,6 +18,9 @@ namespace OpenRA.Mods.Common.Lint { public void Run(Action emitError, Action emitWarning, Map map) { + if (map == null) + return; + if (map.Bounds.Left == 0 || map.Bounds.Top == 0 || map.Bounds.Right == map.MapSize.X || map.Bounds.Bottom == map.MapSize.Y) emitError("This map does not define a valid cordon.\n" diff --git a/OpenRA.Mods.Common/Lint/CheckPlayers.cs b/OpenRA.Mods.Common/Lint/CheckPlayers.cs index a88a7dd64b..615facb123 100644 --- a/OpenRA.Mods.Common/Lint/CheckPlayers.cs +++ b/OpenRA.Mods.Common/Lint/CheckPlayers.cs @@ -19,6 +19,9 @@ namespace OpenRA.Mods.Common.Lint { public void Run(Action emitError, Action emitWarning, Map map) { + if (map == null) + return; + var players = new MapPlayers(map.PlayerDefinitions).Players; var playerNames = players.Values.Select(p => p.Name).ToHashSet(); diff --git a/OpenRA.Mods.Common/Lint/CheckRevealFootprint.cs b/OpenRA.Mods.Common/Lint/CheckRevealFootprint.cs index 5564f83f4a..2973a16cf5 100644 --- a/OpenRA.Mods.Common/Lint/CheckRevealFootprint.cs +++ b/OpenRA.Mods.Common/Lint/CheckRevealFootprint.cs @@ -20,7 +20,12 @@ namespace OpenRA.Mods.Common.Lint { public void Run(Action emitError, Action emitWarning, Map map) { - foreach (var actorInfo in map.Rules.Actors) + if (map != null && !map.RuleDefinitions.Any()) + return; + + var rules = map == null ? Game.ModData.DefaultRules : map.Rules; + + foreach (var actorInfo in rules.Actors) { if (actorInfo.Key.StartsWith("^")) continue; diff --git a/OpenRA.Mods.Common/Lint/CheckSequences.cs b/OpenRA.Mods.Common/Lint/CheckSequences.cs index 284959f624..259f412713 100644 --- a/OpenRA.Mods.Common/Lint/CheckSequences.cs +++ b/OpenRA.Mods.Common/Lint/CheckSequences.cs @@ -26,23 +26,32 @@ namespace OpenRA.Mods.Common.Lint public void Run(Action emitError, Action emitWarning, Map map) { + if (map != null && !map.SequenceDefinitions.Any()) + return; + this.emitWarning = emitWarning; - sequenceDefinitions = MiniYaml.MergeLiberal(map.SequenceDefinitions, + var sequenceSource = map != null ? map.SequenceDefinitions : new List(); + sequenceDefinitions = MiniYaml.MergeLiberal(sequenceSource, Game.ModData.Manifest.Sequences.Select(MiniYaml.FromFile).Aggregate(MiniYaml.MergeLiberal)); - var races = map.Rules.Actors["world"].Traits.WithInterface().Select(f => f.InternalName).ToArray(); + var rules = map == null ? Game.ModData.DefaultRules : map.Rules; + var races = rules.Actors["world"].Traits.WithInterface().Select(f => f.InternalName).ToArray(); + var sequenceProviders = map == null ? rules.Sequences.Values : new[] { rules.Sequences[map.Tileset] }; - foreach (var actorInfo in map.Rules.Actors) + foreach (var actorInfo in rules.Actors) { foreach (var renderInfo in actorInfo.Value.Traits.WithInterface()) { foreach (var race in races) { - var image = renderInfo.GetImage(actorInfo.Value, map.Rules.Sequences[map.Tileset], race); - if (sequenceDefinitions.All(s => s.Key != image.ToLowerInvariant()) && !actorInfo.Value.Name.Contains("^")) - emitWarning("Sprite image {0} from actor {1} on tileset {2} using race {3} has no sequence definition." + foreach (var sequenceProvider in sequenceProviders) + { + var image = renderInfo.GetImage(actorInfo.Value, sequenceProvider, race); + if (sequenceDefinitions.All(s => s.Key != image.ToLowerInvariant()) && !actorInfo.Value.Name.Contains("^")) + emitWarning("Sprite image {0} from actor {1} on tileset {2} using race {3} has no sequence definition." .F(image, actorInfo.Value.Name, map.Tileset, race)); + } } } @@ -82,8 +91,11 @@ namespace OpenRA.Mods.Common.Lint } else { - var image = renderInfo.GetImage(actorInfo.Value, map.SequenceProvider, race); - CheckDefintions(image, sequenceReference, actorInfo, sequence, race, field, traitInfo); + foreach (var sequenceProvider in sequenceProviders) + { + var image = renderInfo.GetImage(actorInfo.Value, sequenceProvider, race); + CheckDefintions(image, sequenceReference, actorInfo, sequence, race, field, traitInfo); + } } } } @@ -91,7 +103,7 @@ namespace OpenRA.Mods.Common.Lint } } - foreach (var weaponInfo in map.Rules.Weapons) + foreach (var weaponInfo in rules.Weapons) { var projectileInfo = weaponInfo.Value.Projectile; if (projectileInfo == null) diff --git a/OpenRA.Mods.Common/Lint/CheckSyncAnnotations.cs b/OpenRA.Mods.Common/Lint/CheckSyncAnnotations.cs index ce4f7e7965..9802106bb1 100644 --- a/OpenRA.Mods.Common/Lint/CheckSyncAnnotations.cs +++ b/OpenRA.Mods.Common/Lint/CheckSyncAnnotations.cs @@ -19,6 +19,9 @@ namespace OpenRA.Mods.Common.Lint { public void Run(Action emitError, Action emitWarning, Map map) { + if (map != null) + return; + /* first, check all the types implementing ISync */ foreach (var t in Game.ModData.ObjectCreator.GetTypesImplementing()) if (!HasAnySyncFields(t)) diff --git a/OpenRA.Mods.Common/Lint/CheckTraitPrerequisites.cs b/OpenRA.Mods.Common/Lint/CheckTraitPrerequisites.cs index 28203d9414..2a7c9db1f0 100644 --- a/OpenRA.Mods.Common/Lint/CheckTraitPrerequisites.cs +++ b/OpenRA.Mods.Common/Lint/CheckTraitPrerequisites.cs @@ -18,7 +18,12 @@ namespace OpenRA.Mods.Common.Lint { public void Run(Action emitError, Action emitWarning, Map map) { - foreach (var actorInfo in map.Rules.Actors.Where(a => !a.Key.StartsWith("^"))) + if (map != null && !map.RuleDefinitions.Any()) + return; + + var rules = map == null ? Game.ModData.DefaultRules : map.Rules; + + foreach (var actorInfo in rules.Actors.Where(a => !a.Key.StartsWith("^"))) try { var hasTraits = actorInfo.Value.TraitsInConstructOrder().Any(); diff --git a/OpenRA.Mods.Common/Lint/CheckUpgrades.cs b/OpenRA.Mods.Common/Lint/CheckUpgrades.cs index aedf046b69..f01c365f99 100644 --- a/OpenRA.Mods.Common/Lint/CheckUpgrades.cs +++ b/OpenRA.Mods.Common/Lint/CheckUpgrades.cs @@ -20,15 +20,20 @@ namespace OpenRA.Mods.Common.Lint { public void Run(Action emitError, Action emitWarning, Map map) { - CheckUpgradesValidity(emitError, map); - CheckUpgradesUsage(emitError, emitWarning, map); + if (map != null && !map.RuleDefinitions.Any()) + return; + + var rules = map == null ? Game.ModData.DefaultRules : map.Rules; + + CheckUpgradesValidity(emitError, rules); + CheckUpgradesUsage(emitError, emitWarning, rules); } - private static void CheckUpgradesValidity(Action emitError, Map map) + static void CheckUpgradesValidity(Action emitError, Ruleset rules) { - var upgradesGranted = GetAllGrantedUpgrades(emitError, map).ToHashSet(); + var upgradesGranted = GetAllGrantedUpgrades(emitError, rules).ToHashSet(); - foreach (var actorInfo in map.Rules.Actors) + foreach (var actorInfo in rules.Actors) { foreach (var trait in actorInfo.Value.Traits) { @@ -43,12 +48,12 @@ namespace OpenRA.Mods.Common.Lint } } - private static void CheckUpgradesUsage(Action emitError, Action emitWarning, Map map) + static void CheckUpgradesUsage(Action emitError, Action emitWarning, Ruleset rules) { - var upgradesUsed = GetAllUsedUpgrades(emitError, map).ToHashSet(); + var upgradesUsed = GetAllUsedUpgrades(emitError, rules).ToHashSet(); // Check all upgrades granted by traits. - foreach (var actorInfo in map.Rules.Actors) + foreach (var actorInfo in rules.Actors) { foreach (var trait in actorInfo.Value.Traits) { @@ -63,7 +68,7 @@ namespace OpenRA.Mods.Common.Lint } // Check all upgrades granted by warheads. - foreach (var weapon in map.Rules.Weapons) + foreach (var weapon in rules.Weapons) { foreach (var warhead in weapon.Value.Warheads) { @@ -78,10 +83,10 @@ namespace OpenRA.Mods.Common.Lint } } - static IEnumerable GetAllGrantedUpgrades(Action emitError, Map map) + static IEnumerable GetAllGrantedUpgrades(Action emitError, Ruleset rules) { // Get all upgrades granted by traits. - foreach (var actorInfo in map.Rules.Actors) + foreach (var actorInfo in rules.Actors) { foreach (var trait in actorInfo.Value.Traits) { @@ -96,7 +101,7 @@ namespace OpenRA.Mods.Common.Lint } // Get all upgrades granted by warheads. - foreach (var weapon in map.Rules.Weapons) + foreach (var weapon in rules.Weapons) { foreach (var warhead in weapon.Value.Warheads) { @@ -111,23 +116,23 @@ namespace OpenRA.Mods.Common.Lint } // TODO: HACK because GainsExperience grants upgrades differently to most other sources. - var gainsExperience = map.Rules.Actors.SelectMany(x => x.Value.Traits.WithInterface() + var gainsExperience = rules.Actors.SelectMany(x => x.Value.Traits.WithInterface() .SelectMany(y => y.Upgrades.SelectMany(z => z.Value))); foreach (var upgrade in gainsExperience) yield return upgrade; // TODO: HACK because Pluggable grants upgrades differently to most other sources. - var pluggable = map.Rules.Actors.SelectMany(x => x.Value.Traits.WithInterface() + var pluggable = rules.Actors.SelectMany(x => x.Value.Traits.WithInterface() .SelectMany(y => y.Upgrades.SelectMany(z => z.Value))); foreach (var upgrade in pluggable) yield return upgrade; } - static IEnumerable GetAllUsedUpgrades(Action emitError, Map map) + static IEnumerable GetAllUsedUpgrades(Action emitError, Ruleset rules) { - foreach (var actorInfo in map.Rules.Actors) + foreach (var actorInfo in rules.Actors) { foreach (var trait in actorInfo.Value.Traits) { @@ -143,7 +148,7 @@ namespace OpenRA.Mods.Common.Lint // TODO: HACK because GainsExperience and GainsStatUpgrades do not play by the rules... // We assume everything GainsExperience grants is used by GainsStatUpgrade - var gainsExperience = map.Rules.Actors.SelectMany(x => x.Value.Traits.WithInterface() + var gainsExperience = rules.Actors.SelectMany(x => x.Value.Traits.WithInterface() .SelectMany(y => y.Upgrades.SelectMany(z => z.Value))); foreach (var upgrade in gainsExperience) diff --git a/OpenRA.Mods.Common/Lint/CheckVoiceReferences.cs b/OpenRA.Mods.Common/Lint/CheckVoiceReferences.cs index 0acf1b77ce..6a40db2483 100644 --- a/OpenRA.Mods.Common/Lint/CheckVoiceReferences.cs +++ b/OpenRA.Mods.Common/Lint/CheckVoiceReferences.cs @@ -19,7 +19,12 @@ namespace OpenRA.Mods.Common.Lint { public void Run(Action emitError, Action emitWarning, Map map) { - foreach (var actorInfo in map.Rules.Actors) + if (map != null && !map.RuleDefinitions.Any() && !map.VoiceDefinitions.Any()) + return; + + var rules = map == null ? Game.ModData.DefaultRules : map.Rules; + + foreach (var actorInfo in rules.Actors) { foreach (var traitInfo in actorInfo.Value.Traits.WithInterface()) { @@ -32,16 +37,16 @@ namespace OpenRA.Mods.Common.Lint if (string.IsNullOrEmpty(voiceSet)) continue; - CheckVoices(actorInfo.Value, emitError, map, voiceSet); + CheckVoices(actorInfo.Value, emitError, rules, voiceSet); } } } } } - void CheckVoices(ActorInfo actorInfo, Action emitError, Map map, string voiceSet) + void CheckVoices(ActorInfo actorInfo, Action emitError, Ruleset rules, string voiceSet) { - var soundInfo = map.Rules.Voices[voiceSet.ToLowerInvariant()]; + var soundInfo = rules.Voices[voiceSet.ToLowerInvariant()]; foreach (var traitInfo in actorInfo.Traits.WithInterface()) { diff --git a/OpenRA.Mods.Common/Lint/LintBuildablePrerequisites.cs b/OpenRA.Mods.Common/Lint/LintBuildablePrerequisites.cs index adfe5bf24f..9f1a50db46 100644 --- a/OpenRA.Mods.Common/Lint/LintBuildablePrerequisites.cs +++ b/OpenRA.Mods.Common/Lint/LintBuildablePrerequisites.cs @@ -19,20 +19,25 @@ namespace OpenRA.Mods.Common.Lint { public void Run(Action emitError, Action emitWarning, Map map) { + if (map != null && !map.RuleDefinitions.Any()) + return; + + var rules = map == null ? Game.ModData.DefaultRules : map.Rules; + // ProvidesPrerequisite allows arbitrary prereq definitions - var customPrereqs = map.Rules.Actors.SelectMany(a => a.Value.Traits + var customPrereqs = rules.Actors.SelectMany(a => a.Value.Traits .WithInterface().Select(p => p.Prerequisite ?? a.Value.Name)); // ProvidesTechPrerequisite allows arbitrary prereq definitions // (but only one group at a time during gameplay) - var techPrereqs = map.Rules.Actors.SelectMany(a => a.Value.Traits + var techPrereqs = rules.Actors.SelectMany(a => a.Value.Traits .WithInterface()) .SelectMany(p => p.Prerequisites); var providedPrereqs = customPrereqs.Concat(techPrereqs); // TODO: this check is case insensitive while the real check in-game is not - foreach (var i in map.Rules.Actors) + foreach (var i in rules.Actors) { var bi = i.Value.Traits.GetOrDefault(); if (bi != null) diff --git a/OpenRA.Mods.Common/UtilityCommands/CheckYaml.cs b/OpenRA.Mods.Common/UtilityCommands/CheckYaml.cs index 30922a8537..34d7a4cb21 100644 --- a/OpenRA.Mods.Common/UtilityCommands/CheckYaml.cs +++ b/OpenRA.Mods.Common/UtilityCommands/CheckYaml.cs @@ -49,21 +49,29 @@ namespace OpenRA.Mods.Common.UtilityCommands ObjectCreator.MissingTypeAction = s => EmitError("Missing Type: {0}".F(s)); FieldLoader.UnknownFieldAction = (s, f) => EmitError("FieldLoader: Missing field `{0}` on `{1}`".F(s, f.Name)); - IEnumerable maps; + var maps = new List(); if (args.Length < 2) { + maps.Add(null); Game.ModData.MapCache.LoadMaps(); - maps = Game.ModData.MapCache + maps.AddRange(Game.ModData.MapCache .Where(m => m.Status == MapStatus.Available) - .Select(m => m.Map); + .Select(m => m.Map)); } else - maps = new[] { new Map(args[1]) }; + maps.Add(new Map(args[1])); foreach (var testMap in maps) { - Console.WriteLine("Testing map: {0}".F(testMap.Title)); - testMap.PreloadRules(); + if (testMap != null) + { + Console.WriteLine("Testing map: {0}".F(testMap.Title)); + testMap.PreloadRules(); + } + else + { + Console.WriteLine("Testing mod: {0}".F(Game.ModData.Manifest.Mod.Title)); + } foreach (var customPassType in Game.ModData.ObjectCreator .GetTypesImplementing())