test unchanged miniyaml rules only once

This commit is contained in:
Matthias Mailänder
2015-08-04 14:04:48 +02:00
parent 6a1f7fd55a
commit fb22c9a1e5
14 changed files with 123 additions and 50 deletions

View File

@@ -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<string> emitError, Action<string> 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<ITraitInfo>())
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<ActorReferenceAttribute>())
CheckReference(actorInfo, traitInfo, field, map.Rules.Actors, "actor");
CheckReference(actorInfo, traitInfo, field, rules.Actors, "actor");
if (field.HasAttribute<WeaponReferenceAttribute>())
CheckReference(actorInfo, traitInfo, field, map.Rules.Weapons, "weapon");
CheckReference(actorInfo, traitInfo, field, rules.Weapons, "weapon");
if (field.HasAttribute<VoiceSetReferenceAttribute>())
CheckReference(actorInfo, traitInfo, field, map.Rules.Voices, "voice");
CheckReference(actorInfo, traitInfo, field, rules.Voices, "voice");
}
}

View File

@@ -18,6 +18,9 @@ namespace OpenRA.Mods.Common.Lint
{
public void Run(Action<string> emitError, Action<string> 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()))

View File

@@ -20,7 +20,12 @@ namespace OpenRA.Mods.Common.Lint
{
public void Run(Action<string> emitError, Action<string> 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<WithDeathAnimationInfo>().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<DamageWarhead>().Where(dw => dw.Damage > 0);

View File

@@ -20,7 +20,12 @@ namespace OpenRA.Mods.Common.Lint
{
public void Run(Action<string> emitError, Action<string> 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;

View File

@@ -18,6 +18,9 @@ namespace OpenRA.Mods.Common.Lint
{
public void Run(Action<string> emitError, Action<string> 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"

View File

@@ -19,6 +19,9 @@ namespace OpenRA.Mods.Common.Lint
{
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
{
if (map == null)
return;
var players = new MapPlayers(map.PlayerDefinitions).Players;
var playerNames = players.Values.Select(p => p.Name).ToHashSet();

View File

@@ -20,7 +20,12 @@ namespace OpenRA.Mods.Common.Lint
{
public void Run(Action<string> emitError, Action<string> 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;

View File

@@ -26,23 +26,32 @@ namespace OpenRA.Mods.Common.Lint
public void Run(Action<string> emitError, Action<string> 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<MiniYamlNode>();
sequenceDefinitions = MiniYaml.MergeLiberal(sequenceSource,
Game.ModData.Manifest.Sequences.Select(MiniYaml.FromFile).Aggregate(MiniYaml.MergeLiberal));
var races = map.Rules.Actors["world"].Traits.WithInterface<FactionInfo>().Select(f => f.InternalName).ToArray();
var rules = map == null ? Game.ModData.DefaultRules : map.Rules;
var races = rules.Actors["world"].Traits.WithInterface<FactionInfo>().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<RenderSpritesInfo>())
{
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)

View File

@@ -19,6 +19,9 @@ namespace OpenRA.Mods.Common.Lint
{
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
{
if (map != null)
return;
/* first, check all the types implementing ISync */
foreach (var t in Game.ModData.ObjectCreator.GetTypesImplementing<ISync>())
if (!HasAnySyncFields(t))

View File

@@ -18,7 +18,12 @@ namespace OpenRA.Mods.Common.Lint
{
public void Run(Action<string> emitError, Action<string> 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();

View File

@@ -20,15 +20,20 @@ namespace OpenRA.Mods.Common.Lint
{
public void Run(Action<string> emitError, Action<string> 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<string> emitError, Map map)
static void CheckUpgradesValidity(Action<string> 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<string> emitError, Action<string> emitWarning, Map map)
static void CheckUpgradesUsage(Action<string> emitError, Action<string> 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<string> GetAllGrantedUpgrades(Action<string> emitError, Map map)
static IEnumerable<string> GetAllGrantedUpgrades(Action<string> 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<GainsExperienceInfo>()
var gainsExperience = rules.Actors.SelectMany(x => x.Value.Traits.WithInterface<GainsExperienceInfo>()
.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<PluggableInfo>()
var pluggable = rules.Actors.SelectMany(x => x.Value.Traits.WithInterface<PluggableInfo>()
.SelectMany(y => y.Upgrades.SelectMany(z => z.Value)));
foreach (var upgrade in pluggable)
yield return upgrade;
}
static IEnumerable<string> GetAllUsedUpgrades(Action<string> emitError, Map map)
static IEnumerable<string> GetAllUsedUpgrades(Action<string> 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<GainsExperienceInfo>()
var gainsExperience = rules.Actors.SelectMany(x => x.Value.Traits.WithInterface<GainsExperienceInfo>()
.SelectMany(y => y.Upgrades.SelectMany(z => z.Value)));
foreach (var upgrade in gainsExperience)

View File

@@ -19,7 +19,12 @@ namespace OpenRA.Mods.Common.Lint
{
public void Run(Action<string> emitError, Action<string> 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<ITraitInfo>())
{
@@ -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<string> emitError, Map map, string voiceSet)
void CheckVoices(ActorInfo actorInfo, Action<string> 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<ITraitInfo>())
{

View File

@@ -19,20 +19,25 @@ namespace OpenRA.Mods.Common.Lint
{
public void Run(Action<string> emitError, Action<string> 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<ProvidesPrerequisiteInfo>().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<ProvidesTechPrerequisiteInfo>())
.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<BuildableInfo>();
if (bi != null)

View File

@@ -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<Map> maps;
var maps = new List<Map>();
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<ILintPass>())