removed FieldLoader.LoadFields

This commit is contained in:
Bob
2010-08-27 18:12:56 +12:00
committed by Chris Forbes
parent a751b8c49d
commit 29a77f7c5c
6 changed files with 69 additions and 59 deletions

View File

@@ -22,7 +22,7 @@ namespace OpenRA.FileFormats
{
throw new InvalidOperationException("FieldLoader: Cannot parse `{0}` into `{1}.{2}` ".F(s,f,t) );
};
public static Action<string,Type> 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<string,MiniYaml> my, IEnumerable<string> 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<FieldInfo, Func<string, Type, MiniYaml, object>>();
var fieldsToLoad = new List<FieldInfo>();
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<MiniYaml, object> Loader;
Func<MiniYaml, object> loaderFuncCache;
public readonly string Loader;
public LoadUsingAttribute( Func<MiniYaml, object> loader )
public LoadUsingAttribute( string loader )
{
Loader = loader;
}
internal Func<MiniYaml, object> LoaderFunc( FieldInfo field )
{
const BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
if( loaderFuncCache == null )
loaderFuncCache = (Func<MiniYaml, object>)Delegate.CreateDelegate( typeof( Func<MiniYaml, object> ), 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<object>().Select(a => a.ToString()).ToArray())
: v.ToString();

View File

@@ -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<string, int2> Waypoints = new Dictionary<string, int2>();
public IEnumerable<int2> 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<string> Fields = new List<string>() {
"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<string, int2>();
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;
}
}
}

View File

@@ -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<byte, string> Tiles = new Dictionary<byte, string>();
static List<string> fields = new List<string>() {"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<MiniYamlNode>();
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;

View File

@@ -12,7 +12,7 @@ using OpenRA.FileFormats;
namespace OpenRA.GameRules
{
[FieldLoader.CustomLoad()]
[FieldLoader.Foo()]
public class MusicInfo
{
public readonly string Filename = null;

View File

@@ -15,6 +15,7 @@ using System;
namespace OpenRA.GameRules
{
[FieldLoader.Foo( "DisableVariants" )]
public class VoiceInfo
{
public readonly Dictionary<string,string[]> 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");

View File

@@ -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<int2> 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<string> SimpleFields = new List<string>() {
"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<Format2ActorReference>(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<MiniYamlNode>();
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;