Allow each caller on MergeOrDefault to discard nodes.
Use filtering ActorInfo's to drop template actors.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>();
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>())
|
||||
{
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user