diff --git a/OpenRA.FileFormats/FieldLoader.cs b/OpenRA.FileFormats/FieldLoader.cs index 1d02b71b62..18ab4ecf3d 100644 --- a/OpenRA.FileFormats/FieldLoader.cs +++ b/OpenRA.FileFormats/FieldLoader.cs @@ -28,13 +28,15 @@ namespace OpenRA.FileFormats throw new NotImplementedException( "FieldLoader: Missing field `{0}` on `{1}`".F( s, f.Name ) ); }; - public static void Load(object self, MiniYaml my) { Load(self, my.Nodes); } - - public static void Load(object self, Dictionary my) + public static void Load( object self, MiniYaml my ) { - foreach (var x in my) + foreach( var x in my.Nodes ) if (!x.Key.StartsWith("-")) LoadField(self, x.Key, x.Value.Value); + + foreach( var field in self.GetType().GetFields()) + if( field.HasAttribute() ) + field.SetValue( self, GetValue( field.Name, field.FieldType, my.Value ) ); } public static T Load(MiniYaml y) where T : new() @@ -58,7 +60,9 @@ namespace OpenRA.FileFormats var field = self.GetType().GetField( key.Trim() ); if( field == null ) - UnknownFieldAction(key.Trim(), self.GetType()); + UnknownFieldAction( key.Trim(), self.GetType() ); + else if( field.HasAttribute() ) + return; else field.SetValue( self, GetValue( field.Name, field.FieldType, value ) ); } @@ -150,10 +154,18 @@ namespace OpenRA.FileFormats { public static MiniYaml Save(object o) { - return new MiniYaml(null, o.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance) - .ToDictionary( - f => f.Name, - f => new MiniYaml(FormatValue(o, f)))); + var dict = new Dictionary(); + string root = null; + + foreach( var f in o.GetType().GetFields( BindingFlags.Public | BindingFlags.Instance ) ) + { + if( f.HasAttribute() ) + root = FormatValue( o, f ); + else + dict.Add( f.Name, new MiniYaml( FormatValue( o, f ) ) ); + } + + return new MiniYaml( root, dict ); } public static MiniYaml SaveDifferences(object o, object from) @@ -187,4 +199,6 @@ namespace OpenRA.FileFormats : v.ToString(); } } + + public class FieldFromYamlKeyAttribute : Attribute { } } diff --git a/OpenRA.FileFormats/OpenRA.FileFormats.csproj b/OpenRA.FileFormats/OpenRA.FileFormats.csproj index 6024cedd55..a4f5f64aee 100644 --- a/OpenRA.FileFormats/OpenRA.FileFormats.csproj +++ b/OpenRA.FileFormats/OpenRA.FileFormats.csproj @@ -76,7 +76,6 @@ - diff --git a/OpenRA.Game/ActorInitializer.cs b/OpenRA.Game/ActorInitializer.cs index b42753b7b1..8653ec1bfc 100755 --- a/OpenRA.Game/ActorInitializer.cs +++ b/OpenRA.Game/ActorInitializer.cs @@ -49,8 +49,11 @@ namespace OpenRA public class LocationInit : IActorInit { + [FieldFromYamlKey] public readonly int2 value = int2.Zero; + public LocationInit() { } + public LocationInit( int2 init ) { value = init; @@ -64,9 +67,17 @@ namespace OpenRA public class OwnerInit : IActorInit { + [FieldFromYamlKey] public readonly string PlayerName = "Neutral"; Player player; + public OwnerInit() { } + + public OwnerInit( string playerName ) + { + this.PlayerName = playerName; + } + public OwnerInit( Player player ) { this.player = player; diff --git a/OpenRA.Game/ActorReference.cs b/OpenRA.Game/ActorReference.cs new file mode 100755 index 0000000000..63ba48f1e3 --- /dev/null +++ b/OpenRA.Game/ActorReference.cs @@ -0,0 +1,53 @@ +#region Copyright & License Information +/* + * Copyright 2007-2010 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see LICENSE. + */ +#endregion + +using System.Collections.Generic; +using System.Collections; + +namespace OpenRA.FileFormats +{ + public class ActorReference : IEnumerable + { + public readonly string Type; + public readonly TypeDictionary InitDict; + + public ActorReference( string type ) : this( type, new Dictionary() ) { } + + public ActorReference( string type, Dictionary inits ) + { + Type = type; + InitDict = new TypeDictionary(); + foreach( var i in inits ) + InitDict.Add( LoadInit( i.Key, i.Value ) ); + } + + static IActorInit LoadInit(string traitName, MiniYaml my) + { + var info = Game.CreateObject(traitName + "Init"); + FieldLoader.Load(info, my); + return info; + } + + public MiniYaml Save() + { + var ret = new MiniYaml( Type ); + foreach( var init in InitDict ) + { + var initName = init.GetType().Name; + ret.Nodes.Add( initName.Substring( 0, initName.Length - 4 ), FieldSaver.Save( init ) ); + } + return ret; + } + + // for initialization syntax + public void Add( object o ) { InitDict.Add( o ); } + public IEnumerator GetEnumerator() { return InitDict.GetEnumerator(); } + } +} diff --git a/OpenRA.Game/GameRules/ActorInfo.cs b/OpenRA.Game/GameRules/ActorInfo.cs index ca6a349ef4..e8e0d9d74b 100644 --- a/OpenRA.Game/GameRules/ActorInfo.cs +++ b/OpenRA.Game/GameRules/ActorInfo.cs @@ -14,7 +14,7 @@ using System.Linq; using OpenRA.FileFormats; using OpenRA.Traits; -namespace OpenRA.GameRules +namespace OpenRA { public class ActorInfo { diff --git a/OpenRA.Game/Map.cs b/OpenRA.Game/Map.cs index 4791bf4261..c54a6914d7 100755 --- a/OpenRA.Game/Map.cs +++ b/OpenRA.Game/Map.cs @@ -123,20 +123,19 @@ namespace OpenRA int actors = 0; foreach (var kv in yaml["Actors"].Nodes) { - string[] vals = kv.Value.Value.Split(' '); - string[] loc = vals[2].Split(','); - var a = new ActorReference("Actor"+actors++, vals[0], new int2(int.Parse(loc[0]), int.Parse(loc[1])), "Neutral"); - Actors.Add(a.Id, a); + string[] vals = kv.Value.Value.Split(' '); + string[] loc = vals[2].Split(','); + Actors.Add( "Actor" + actors++, new ActorReference( vals[ 0 ] ) + { + new LocationInit( new int2( int.Parse( loc[ 0 ] ), int.Parse( loc[ 1 ] ) ) ), + new OwnerInit( "Neutral" ), + } ); } } else - { - foreach (var kv in yaml["Actors"].Nodes) - { - kv.Value.Nodes.Add( "Type", new MiniYaml( kv.Value.Value ) ); - var a = new ActorReference(kv.Key, kv.Value); - Actors.Add(a.Id, a); - } + { + foreach( var kv in yaml[ "Actors" ].Nodes ) + Actors.Add( kv.Key, new ActorReference( kv.Value.Value, kv.Value.Nodes ) ); } // Smudges @@ -173,10 +172,10 @@ namespace OpenRA p => FieldSaver.Save(p.Value)))); root.Add("Actors", - new MiniYaml(null, Actors.ToDictionary( - a => "{0}".F(a.Key), - a => FieldSaver.Save(a.Value)))); - + new MiniYaml( null, Actors.ToDictionary( + x => x.Key, + x => x.Value.Save() ) ) ); + root.Add("Waypoints", MiniYaml.FromDictionary(Waypoints)); root.Add("Smudges", MiniYaml.FromList(Smudges)); root.Add("Rules", new MiniYaml(null, Rules)); diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index f6ab5a911c..f7dd4eb396 100755 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -228,6 +228,7 @@ OpenRA.FileFormats + diff --git a/OpenRA.Mods.RA/SpawnMapActors.cs b/OpenRA.Mods.RA/SpawnMapActors.cs index efe02afbfc..7b1dc1c52e 100644 --- a/OpenRA.Mods.RA/SpawnMapActors.cs +++ b/OpenRA.Mods.RA/SpawnMapActors.cs @@ -25,8 +25,7 @@ namespace OpenRA.Mods.RA Game.skipMakeAnims = true; // rude hack foreach (var actorReference in world.Map.Actors) - MapActors[actorReference.Key] = world.CreateActor(actorReference.Value.Type, actorReference.Value.Location, - world.players.Values.FirstOrDefault(p => p.InternalName == actorReference.Value.Owner)); + MapActors[actorReference.Key] = world.CreateActor(actorReference.Value.Type, actorReference.Value.InitDict); Game.skipMakeAnims = false; }