diff --git a/OpenRA.FileFormats/FieldLoader.cs b/OpenRA.FileFormats/FieldLoader.cs index 5525b3e26a..f0e0e0c205 100755 --- a/OpenRA.FileFormats/FieldLoader.cs +++ b/OpenRA.FileFormats/FieldLoader.cs @@ -351,4 +351,11 @@ namespace OpenRA.FileFormats } public class FieldFromYamlKeyAttribute : Attribute { } + + // mirrors DescriptionAttribute from System.ComponentModel but we dont want to have to use that everywhere. + public class DescAttribute : Attribute + { + public readonly string Description; + public DescAttribute(string description) { Description = description; } + } } diff --git a/OpenRA.Utility/Command.cs b/OpenRA.Utility/Command.cs index 725976ce01..96bf9a38ab 100644 --- a/OpenRA.Utility/Command.cs +++ b/OpenRA.Utility/Command.cs @@ -14,6 +14,7 @@ using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Linq; +using System.Reflection; using System.Runtime.InteropServices; using OpenRA.FileFormats; using OpenRA.FileFormats.Graphics; @@ -475,5 +476,43 @@ namespace OpenRA.Utility ShpWriter.Write(destStream, srcImage.Width, srcImage.Height, destFrames.Select(f => f.Image)); } + + static string NiceTypeName(Type t) + { + if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Dictionary<,>)) + return "Dictionary<{0},{1}>".F(t.GetGenericArguments().Select(a => NiceTypeName(a)).ToArray ()); + + return t.Name; + } + + public static void ExtractTraitDocs(string[] args) + { + Game.modData = new ModData(args[1]); + FileSystem.LoadFromManifest(Game.modData.Manifest); + Rules.LoadRules(Game.modData.Manifest, new Map()); + + foreach( var t in Game.modData.ObjectCreator.GetTypesImplementing() ) + { + if (t.ContainsGenericParameters || t.IsAbstract) + continue; // skip helpers like TraitInfo + + var traitName = t.Name.Replace("Info",""); + var traitDesc = t.GetCustomAttributes(false).Select(a => a.Description).FirstOrDefault(); + + Console.WriteLine("{0}:", traitName); + var liveTraitInfo = Game.modData.ObjectCreator.CreateBasic(t); + + foreach(var f in t.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy)) + { + var fieldDesc = f.GetCustomAttributes(true).Select(a => a.Description).FirstOrDefault(); + var fieldType = NiceTypeName(f.FieldType); + var defaultValue = FieldSaver.SaveField(liveTraitInfo, f.Name).Value.Value; + if (string.IsNullOrEmpty(defaultValue)) + defaultValue = "(none)"; + + Console.WriteLine("\t{0}: {2} # type: {1}", f.Name, fieldType, defaultValue); + } + } + } } } diff --git a/OpenRA.Utility/Program.cs b/OpenRA.Utility/Program.cs index b6cc18f8c0..f227ca8b97 100644 --- a/OpenRA.Utility/Program.cs +++ b/OpenRA.Utility/Program.cs @@ -29,6 +29,7 @@ namespace OpenRA.Utility { "--remap", Command.RemapShp }, { "--r8", Command.ConvertR8ToPng }, { "--transpose", Command.TransposeShp }, + { "--docs", Command.ExtractTraitDocs }, }; if (args.Length == 0) { PrintUsage(); return; }