From 29a77f7c5cd03917016a0c46c6f97486534cf5e0 Mon Sep 17 00:00:00 2001 From: Bob Date: Fri, 27 Aug 2010 18:12:56 +1200 Subject: [PATCH] removed FieldLoader.LoadFields --- OpenRA.FileFormats/FieldLoader.cs | 51 ++++++++++++++++-------------- OpenRA.FileFormats/Map/MapStub.cs | 29 +++++++++-------- OpenRA.FileFormats/Map/TileSet.cs | 16 ++++++---- OpenRA.Game/GameRules/MusicInfo.cs | 2 +- OpenRA.Game/GameRules/VoiceInfo.cs | 3 +- OpenRA.Game/Map.cs | 27 +++++++--------- 6 files changed, 69 insertions(+), 59 deletions(-) diff --git a/OpenRA.FileFormats/FieldLoader.cs b/OpenRA.FileFormats/FieldLoader.cs index 9209819674..be62449e18 100644 --- a/OpenRA.FileFormats/FieldLoader.cs +++ b/OpenRA.FileFormats/FieldLoader.cs @@ -22,7 +22,7 @@ namespace OpenRA.FileFormats { throw new InvalidOperationException("FieldLoader: Cannot parse `{0}` into `{1}.{2}` ".F(s,f,t) ); }; - + public static Action UnknownFieldAction = (s,f) => { throw new NotImplementedException( "FieldLoader: Missing field `{0}` on `{1}`".F( s, f.Name ) ); @@ -64,15 +64,6 @@ namespace OpenRA.FileFormats Load(t, y); return t; } - - public static void LoadFields( object self, Dictionary my, IEnumerable fields ) - { - foreach (var field in fields) - { - if (!my.ContainsKey(field)) continue; - LoadField(self,field,my[field].Value); - } - } public static void LoadField( object self, string key, string value ) { @@ -85,7 +76,7 @@ namespace OpenRA.FileFormats else field.SetValue( self, GetValue( field.Name, field.FieldType, value ) ); } - + public static object GetValue( string field, Type fieldType, string x ) { if (x != null) x = x.Trim(); @@ -96,7 +87,7 @@ namespace OpenRA.FileFormats return res; return InvalidValueAction(x,fieldType, field); } - + else if( fieldType == typeof( ushort ) ) { ushort res; @@ -115,7 +106,7 @@ namespace OpenRA.FileFormats else if (fieldType == typeof(string)) return x; - + else if (fieldType == typeof(Color)) { var parts = x.Split(','); @@ -125,14 +116,14 @@ namespace OpenRA.FileFormats return Color.FromArgb(int.Parse(parts[0]), int.Parse(parts[1]), int.Parse(parts[2]), int.Parse(parts[3])); return InvalidValueAction(x,fieldType, field); } - + else if (fieldType.IsEnum) { if (!Enum.GetNames(fieldType).Select(a => a.ToLower()).Contains(x.ToLower())) return InvalidValueAction(x,fieldType, field); return Enum.Parse(fieldType, x, true); } - + else if (fieldType == typeof(bool)) return ParseYesNo(x, fieldType, field); @@ -153,7 +144,7 @@ namespace OpenRA.FileFormats var parts = x.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); return new int2(int.Parse(parts[0]), int.Parse(parts[1])); } - + UnknownFieldAction("[Type] {0}".F(x),fieldType); return null; } @@ -175,7 +166,7 @@ namespace OpenRA.FileFormats var ret = new Dictionary>(); var fieldsToLoad = new List(); - var attr = (CustomLoadAttribute[])type.GetCustomAttributes( typeof( CustomLoadAttribute ), false ); + var attr = (FooAttribute[])type.GetCustomAttributes( typeof( FooAttribute ), false ); if( attr.Length == 0 ) { var defCtor = type.GetConstructor( new Type[ 0 ] ); @@ -195,7 +186,7 @@ namespace OpenRA.FileFormats { var use = (LoadUsingAttribute[])field.GetCustomAttributes( typeof( LoadUsingAttribute ), false ); if( use.Length != 0 ) - ret[ field ] = ( _1, _2, yaml ) => use[ 0 ].Loader( yaml ); + ret[ field ] = ( _1, fieldType, yaml ) => use[ 0 ].LoaderFunc( field )( yaml ); else { var attr2 = (FieldFromYamlKeyAttribute[])field.GetCustomAttributes( typeof( FieldFromYamlKeyAttribute ), false ); @@ -207,19 +198,33 @@ namespace OpenRA.FileFormats return ret; } - public class CustomLoadAttribute : Attribute + public class FooAttribute : Attribute { public string[] Fields; + + public FooAttribute( params string[] fields ) + { + Fields = fields; + } } public class LoadUsingAttribute : Attribute { - public readonly Func Loader; + Func loaderFuncCache; + public readonly string Loader; - public LoadUsingAttribute( Func loader ) + public LoadUsingAttribute( string loader ) { Loader = loader; } + + internal Func LoaderFunc( FieldInfo field ) + { + const BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static; + if( loaderFuncCache == null ) + loaderFuncCache = (Func)Delegate.CreateDelegate( typeof( Func ), field.DeclaringType.GetMethod( Loader, bf ) ); + return loaderFuncCache; + } } } @@ -240,7 +245,7 @@ namespace OpenRA.FileFormats return new MiniYaml( root, nodes ); } - + public static MiniYaml SaveDifferences(object o, object from) { if (o.GetType() != from.GetType()) @@ -266,7 +271,7 @@ namespace OpenRA.FileFormats var c = (Color)v; return "{0},{1},{2},{3}".F(c.A,c.R,c.G,c.B); } - + return f.FieldType.IsArray ? string.Join(",", ((Array)v).OfType().Select(a => a.ToString()).ToArray()) : v.ToString(); diff --git a/OpenRA.FileFormats/Map/MapStub.cs b/OpenRA.FileFormats/Map/MapStub.cs index 89fbb5a142..fed9e488d4 100644 --- a/OpenRA.FileFormats/Map/MapStub.cs +++ b/OpenRA.FileFormats/Map/MapStub.cs @@ -15,6 +15,7 @@ using System.Linq; namespace OpenRA.FileFormats { + [FieldLoader.Foo( "Selectable", "Title", "Description", "Author", "PlayerCount", "Tileset", "TopLeft", "BottomRight" )] public class MapStub { public readonly IFolder Package; @@ -28,6 +29,8 @@ namespace OpenRA.FileFormats public string Author; public int PlayerCount; public string Tileset; + + [FieldLoader.LoadUsing( "LoadWaypoints" )] public Dictionary Waypoints = new Dictionary(); public IEnumerable SpawnPoints { get { return Waypoints.Select(kv => kv.Value); } } @@ -36,24 +39,24 @@ namespace OpenRA.FileFormats public int Width { get { return BottomRight.X - TopLeft.X; } } public int Height { get { return BottomRight.Y - TopLeft.Y; } } - static List Fields = new List() { - "Selectable", "Title", "Description", "Author", "PlayerCount", "Tileset", "TopLeft", "BottomRight" - }; - public MapStub(IFolder package) { Package = package; - var yaml = MiniYaml.DictFromStream(Package.GetContent("map.yaml")); - FieldLoader.LoadFields(this, yaml, Fields); + var yaml = MiniYaml.FromStream(Package.GetContent("map.yaml")); + FieldLoader.Load( this, new MiniYaml( null, yaml ) ); - // Waypoints - foreach (var wp in yaml["Waypoints"].NodesDict) - { - string[] loc = wp.Value.Value.Split(','); - Waypoints.Add(wp.Key, new int2(int.Parse(loc[0]), int.Parse(loc[1]))); - } - Uid = Package.GetContent("map.uid").ReadAllText(); } + + static object LoadWaypoints( MiniYaml y ) + { + var ret = new Dictionary(); + foreach( var wp in y.NodesDict[ "Waypoints" ].NodesDict ) + { + string[] loc = wp.Value.Value.Split( ',' ); + ret.Add( wp.Key, new int2( int.Parse( loc[ 0 ] ), int.Parse( loc[ 1 ] ) ) ); + } + return ret; + } } } diff --git a/OpenRA.FileFormats/Map/TileSet.cs b/OpenRA.FileFormats/Map/TileSet.cs index dc7c7d5033..0b55934dfe 100644 --- a/OpenRA.FileFormats/Map/TileSet.cs +++ b/OpenRA.FileFormats/Map/TileSet.cs @@ -29,30 +29,34 @@ namespace OpenRA.FileFormats public MiniYaml Save() { return FieldSaver.Save(this); } } + [FieldLoader.Foo("Id", "Image", "Size", "PickAny")] public class TileTemplate { public ushort Id; public string Image; public int2 Size; public bool PickAny; + + [FieldLoader.LoadUsing( "LoadTiles" )] public Dictionary Tiles = new Dictionary(); - static List fields = new List() {"Id", "Image", "Size", "PickAny"}; - public TileTemplate() {} public TileTemplate(MiniYaml my) { - FieldLoader.LoadFields(this, my.NodesDict, fields); + FieldLoader.Load( this, my ); + } - Tiles = my.NodesDict["Tiles"].NodesDict.ToDictionary( + static object LoadTiles( MiniYaml y ) + { + return y.NodesDict["Tiles"].NodesDict.ToDictionary( t => byte.Parse(t.Key), - t => t.Value.Value); + t => t.Value.Value ); } public MiniYaml Save() { var root = new List(); - foreach (var field in fields) + foreach (var field in new string[] {"Id", "Image", "Size", "PickAny"}) { FieldInfo f = this.GetType().GetField(field); if (f.GetValue(this) == null) continue; diff --git a/OpenRA.Game/GameRules/MusicInfo.cs b/OpenRA.Game/GameRules/MusicInfo.cs index 3949b6c8fc..945efb600a 100644 --- a/OpenRA.Game/GameRules/MusicInfo.cs +++ b/OpenRA.Game/GameRules/MusicInfo.cs @@ -12,7 +12,7 @@ using OpenRA.FileFormats; namespace OpenRA.GameRules { - [FieldLoader.CustomLoad()] + [FieldLoader.Foo()] public class MusicInfo { public readonly string Filename = null; diff --git a/OpenRA.Game/GameRules/VoiceInfo.cs b/OpenRA.Game/GameRules/VoiceInfo.cs index ab432a6274..07bf8c3d76 100644 --- a/OpenRA.Game/GameRules/VoiceInfo.cs +++ b/OpenRA.Game/GameRules/VoiceInfo.cs @@ -15,6 +15,7 @@ using System; namespace OpenRA.GameRules { + [FieldLoader.Foo( "DisableVariants" )] public class VoiceInfo { public readonly Dictionary Variants; @@ -30,7 +31,7 @@ namespace OpenRA.GameRules public VoiceInfo( MiniYaml y ) { - FieldLoader.LoadFields(this, y.NodesDict, new string[] { "DisableVariants" }); + FieldLoader.Load( this, y ); Variants = Load(y, "Variants"); Voices = Load(y, "Voices"); diff --git a/OpenRA.Game/Map.cs b/OpenRA.Game/Map.cs index 721158f800..76a52c664f 100755 --- a/OpenRA.Game/Map.cs +++ b/OpenRA.Game/Map.cs @@ -19,6 +19,7 @@ using OpenRA.FileFormats; namespace OpenRA { + [FieldLoader.Foo( "Selectable", "MapFormat", "Title", "Description", "Author", "PlayerCount", "Tileset", "MapSize", "TopLeft", "BottomRight" )] public class Map { public IFolder Package; @@ -61,10 +62,6 @@ namespace OpenRA public IEnumerable SpawnPoints { get { return Waypoints.Select(kv => kv.Value); } } public Rectangle Bounds { get { return Rectangle.FromLTRB(TopLeft.X, TopLeft.Y, BottomRight.X, BottomRight.Y); } } - static List SimpleFields = new List() { - "Selectable", "MapFormat", "Title", "Description", "Author", "PlayerCount", "Tileset", "MapSize", "TopLeft", "BottomRight" - }; - public Map() { MapSize = new int2(1, 1); @@ -95,13 +92,13 @@ namespace OpenRA public Map(IFolder package) { Package = package; - var yaml = MiniYaml.DictFromStream(Package.GetContent("map.yaml")); + var yaml = new MiniYaml( null, MiniYaml.FromStream( Package.GetContent( "map.yaml" ) ) ); // 'Simple' metadata - FieldLoader.LoadFields(this, yaml, SimpleFields); + FieldLoader.Load( this, yaml ); // Waypoints - foreach (var wp in yaml["Waypoints"].NodesDict) + foreach (var wp in yaml.NodesDict["Waypoints"].NodesDict) { string[] loc = wp.Value.Value.Split(','); Waypoints.Add(wp.Key, new int2(int.Parse(loc[0]), int.Parse(loc[1]))); @@ -120,7 +117,7 @@ namespace OpenRA Players.Add("Neutral", new PlayerReference("Neutral", "allies", true, true)); int actors = 0; - foreach (var kv in yaml["Actors"].NodesDict) + foreach (var kv in yaml.NodesDict["Actors"].NodesDict) { string[] vals = kv.Value.Value.Split(' '); string[] loc = vals[2].Split(','); @@ -134,13 +131,13 @@ namespace OpenRA case 2: { - foreach (var kv in yaml["Players"].NodesDict) + foreach (var kv in yaml.NodesDict["Players"].NodesDict) { var player = new PlayerReference(kv.Value); Players.Add(player.Name, player); } - foreach (var kv in yaml["Actors"].NodesDict) + foreach (var kv in yaml.NodesDict["Actors"].NodesDict) { var oldActorReference = FieldLoader.Load(kv.Value); Actors.Add(oldActorReference.Id, new ActorReference(oldActorReference.Type) @@ -153,13 +150,13 @@ namespace OpenRA case 3: { - foreach (var kv in yaml["Players"].NodesDict) + foreach (var kv in yaml.NodesDict["Players"].NodesDict) { var player = new PlayerReference(kv.Value); Players.Add(player.Name, player); } - foreach (var kv in yaml["Actors"].NodesDict) + foreach (var kv in yaml.NodesDict["Actors"].NodesDict) Actors.Add(kv.Key, new ActorReference(kv.Value.Value, kv.Value.NodesDict)); } break; @@ -184,7 +181,7 @@ namespace OpenRA } // Smudges - foreach (var kv in yaml["Smudges"].NodesDict) + foreach (var kv in yaml.NodesDict["Smudges"].NodesDict) { string[] vals = kv.Key.Split(' '); string[] loc = vals[1].Split(','); @@ -192,7 +189,7 @@ namespace OpenRA } // Rules - Rules = yaml["Rules"].Nodes; + Rules = yaml.NodesDict["Rules"].Nodes; CustomTerrain = new string[MapSize.X, MapSize.Y]; LoadUid(); @@ -204,7 +201,7 @@ namespace OpenRA MapFormat = 3; var root = new List(); - foreach (var field in SimpleFields) + foreach (var field in new string[] {"Selectable", "MapFormat", "Title", "Description", "Author", "PlayerCount", "Tileset", "MapSize", "TopLeft", "BottomRight"}) { FieldInfo f = this.GetType().GetField(field); if (f.GetValue(this) == null) continue;