Allow each caller on MergeOrDefault to discard nodes.

Use filtering ActorInfo's to drop template actors.
This commit is contained in:
Peter Antal
2018-02-25 22:29:49 -08:00
committed by abcdefg30
parent 40d7b41e84
commit d2ff5b49fd
9 changed files with 24 additions and 26 deletions

View File

@@ -22,6 +22,8 @@ namespace OpenRA
/// </summary>
public class ActorInfo
{
public const string AbstractActorPrefix = "^";
/// <summary>
/// The actor name can be anything, but the sprites used in the Render*: traits default to this one.
/// If you add an ^ in front of the name, the engine will recognize this as a collection of traits
@@ -38,7 +40,6 @@ namespace OpenRA
{
Name = name;
var abstractActorType = name.StartsWith("^");
foreach (var t in node.Nodes)
{
try
@@ -47,8 +48,7 @@ namespace OpenRA
}
catch (FieldLoader.MissingFieldsException e)
{
if (!abstractActorType)
throw new YamlException(e.Message);
throw new YamlException(e.Message);
}
}

View File

@@ -87,16 +87,24 @@ namespace OpenRA
public IEnumerable<KeyValuePair<string, MusicInfo>> InstalledMusic { get { return Music.Where(m => m.Value.Exists); } }
static IReadOnlyDictionary<string, T> MergeOrDefault<T>(string name, IReadOnlyFileSystem fileSystem, IEnumerable<string> files, MiniYaml additional,
IReadOnlyDictionary<string, T> defaults, Func<MiniYamlNode, T> makeObject)
static IReadOnlyDictionary<string, T> MergeOrDefault<T>(string name,
IReadOnlyFileSystem fileSystem,
IEnumerable<string> files,
MiniYaml additional,
IReadOnlyDictionary<string, T> defaults,
Func<MiniYamlNode, T> makeObject,
Func<MiniYamlNode, bool> filterNode = null)
{
if (additional == null && defaults != null)
return defaults;
var result = MiniYaml.Load(fileSystem, files, additional)
.ToDictionaryWithConflictLog(k => k.Key.ToLowerInvariant(), makeObject, "LoadFromManifest<" + name + ">");
IEnumerable<MiniYamlNode> yamlNodes = MiniYaml.Load(fileSystem, files, additional);
return new ReadOnlyDictionary<string, T>(result);
// Optionally, the caller can filter out elements from the loaded set of nodes. Default behavior is unfiltered.
if (filterNode != null)
yamlNodes = yamlNodes.Where(k => !filterNode(k));
return new ReadOnlyDictionary<string, T>(yamlNodes.ToDictionaryWithConflictLog(k => k.Key.ToLowerInvariant(), makeObject, "LoadFromManifest<" + name + ">"));
}
public static Ruleset LoadDefaults(ModData modData)
@@ -108,7 +116,8 @@ namespace OpenRA
Action f = () =>
{
var actors = MergeOrDefault("Manifest,Rules", fs, m.Rules, null, null,
k => new ActorInfo(modData.ObjectCreator, k.Key.ToLowerInvariant(), k.Value));
k => new ActorInfo(modData.ObjectCreator, k.Key.ToLowerInvariant(), k.Value),
filterNode: n => n.Key.StartsWith(ActorInfo.AbstractActorPrefix, StringComparison.Ordinal));
var weapons = MergeOrDefault("Manifest,Weapons", fs, m.Weapons, null, null,
k => new WeaponInfo(k.Key.ToLowerInvariant(), k.Value));
@@ -166,7 +175,8 @@ namespace OpenRA
Action f = () =>
{
var actors = MergeOrDefault("Rules", fileSystem, m.Rules, mapRules, dr.Actors,
k => new ActorInfo(modData.ObjectCreator, k.Key.ToLowerInvariant(), k.Value));
k => new ActorInfo(modData.ObjectCreator, k.Key.ToLowerInvariant(), k.Value),
filterNode: n => n.Key.StartsWith(ActorInfo.AbstractActorPrefix, StringComparison.Ordinal));
var weapons = MergeOrDefault("Weapons", fileSystem, m.Weapons, mapWeapons, dr.Weapons,
k => new WeaponInfo(k.Key.ToLowerInvariant(), k.Value));
@@ -244,7 +254,7 @@ namespace OpenRA
MiniYaml mapRules, MiniYaml mapWeapons, MiniYaml mapVoices, MiniYaml mapNotifications, MiniYaml mapSequences)
{
// Maps that define any weapon, voice, notification, or sequence overrides are always flagged
if (AnyCustomYaml(mapWeapons) || AnyCustomYaml(mapVoices) || AnyCustomYaml(mapNotifications) || AnyCustomYaml(mapSequences))
if (AnyCustomYaml(mapWeapons) || AnyCustomYaml(mapVoices) || AnyCustomYaml(mapNotifications) || AnyCustomYaml(mapSequences))
return true;
// Any trait overrides that aren't explicitly whitelisted are flagged

View File

@@ -23,9 +23,6 @@ namespace OpenRA.Mods.Common.Lint
{
foreach (var actorInfo in rules.Actors)
{
if (actorInfo.Key.StartsWith("^", StringComparison.Ordinal))
continue;
var granted = new HashSet<string>();
var consumed = new HashSet<string>();

View File

@@ -22,9 +22,6 @@ namespace OpenRA.Mods.Common.Lint
{
foreach (var actorInfo in rules.Actors)
{
if (actorInfo.Key.StartsWith("^"))
continue;
var count = actorInfo.Value.TraitInfos<IDefaultVisibilityInfo>().Count();
if (count == 0)

View File

@@ -22,9 +22,6 @@ namespace OpenRA.Mods.Common.Lint
{
foreach (var actorInfo in rules.Actors)
{
if (actorInfo.Key.StartsWith("^", StringComparison.Ordinal))
continue;
var health = actorInfo.Value.TraitInfoOrDefault<HealthInfo>();
if (health == null)
continue;

View File

@@ -22,9 +22,6 @@ namespace OpenRA.Mods.Common.Lint
{
foreach (var actorInfo in rules.Actors)
{
if (actorInfo.Key.StartsWith("^", StringComparison.Ordinal))
continue;
var ios = actorInfo.Value.TraitInfoOrDefault<IOccupySpaceInfo>();
foreach (var rsi in actorInfo.Value.TraitInfos<RevealsShroudInfo>())
{

View File

@@ -48,7 +48,7 @@ namespace OpenRA.Mods.Common.Lint
foreach (var sequenceProvider in sequenceProviders)
{
var image = renderInfo.GetImage(actorInfo.Value, sequenceProvider, faction);
if (sequenceDefinitions.All(s => s.Key != image.ToLowerInvariant()) && !actorInfo.Value.Name.Contains("^"))
if (sequenceDefinitions.All(s => s.Key != image.ToLowerInvariant()))
emitError("Sprite image {0} from actor {1} using faction {2} has no sequence definition."
.F(image, actorInfo.Value.Name, faction));
}

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.Lint
{
public void Run(Action<string> emitError, Action<string> emitWarning, Ruleset rules)
{
foreach (var actorInfo in rules.Actors.Where(a => !a.Key.StartsWith("^")))
foreach (var actorInfo in rules.Actors)
{
try
{

View File

@@ -39,7 +39,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
Console.WriteLine("Tileset: " + ts.Name);
var sc = new SpriteCache(modData.DefaultFileSystem, modData.SpriteLoaders, new SheetBuilder(SheetType.Indexed));
var nodes = MiniYaml.Merge(modData.Manifest.Sequences.Select(s => MiniYaml.FromStream(modData.DefaultFileSystem.Open(s), s)));
foreach (var n in nodes.Where(node => !node.Key.StartsWith("^")))
foreach (var n in nodes.Where(node => !node.Key.StartsWith(ActorInfo.AbstractActorPrefix, StringComparison.Ordinal)))
modData.SpriteSequenceLoader.ParseSequences(modData, ts, sc, n);
}