Added FieldLoader.SerializeAttribute.Required to require fields in MiniYaml
This commit is contained in:
@@ -24,6 +24,26 @@ namespace OpenRA
|
||||
{
|
||||
public static class FieldLoader
|
||||
{
|
||||
public class MissingFieldsException : YamlException
|
||||
{
|
||||
public readonly string[] Missing;
|
||||
public readonly string Header;
|
||||
public override string Message
|
||||
{
|
||||
get
|
||||
{
|
||||
return (string.IsNullOrEmpty(Header) ? "" : Header + ": ") + Missing[0]
|
||||
+ string.Concat(Missing.Skip(1).Select(m => ", " + m));
|
||||
}
|
||||
}
|
||||
|
||||
public MissingFieldsException(string[] missing, string header = null, string headerSingle = null) : base(null)
|
||||
{
|
||||
Header = missing.Length > 1 ? header : headerSingle ?? header;
|
||||
Missing = missing;
|
||||
}
|
||||
}
|
||||
|
||||
public static Func<string, Type, string, object> InvalidValueAction = (s, t, f) =>
|
||||
{
|
||||
throw new InvalidOperationException("FieldLoader: Cannot parse `{0}` into `{1}.{2}` ".F(s, f, t));
|
||||
@@ -45,6 +65,7 @@ namespace OpenRA
|
||||
public static void Load(object self, MiniYaml my)
|
||||
{
|
||||
var loadInfo = TypeLoadInfo[self.GetType()];
|
||||
var missing = new List<string>();
|
||||
|
||||
Dictionary<string, MiniYaml> md = null;
|
||||
|
||||
@@ -52,19 +73,33 @@ namespace OpenRA
|
||||
{
|
||||
object val;
|
||||
|
||||
if (md == null)
|
||||
md = my.ToDictionary();
|
||||
if (fli.Loader != null)
|
||||
val = fli.Loader(my);
|
||||
{
|
||||
if (!fli.Attribute.Required || md.ContainsKey(fli.YamlName))
|
||||
val = fli.Loader(my);
|
||||
else
|
||||
{
|
||||
missing.Add(fli.YamlName);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (md == null)
|
||||
md = my.ToDictionary();
|
||||
|
||||
if (!TryGetValueFromYaml(fli.YamlName, fli.Field, md, out val))
|
||||
{
|
||||
if (fli.Attribute.Required)
|
||||
missing.Add(fli.YamlName);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
fli.Field.SetValue(self, val);
|
||||
}
|
||||
|
||||
if (missing.Any())
|
||||
throw new MissingFieldsException(missing.ToArray());
|
||||
}
|
||||
|
||||
static bool TryGetValueFromYaml(string yamlName, FieldInfo field, Dictionary<string, MiniYaml> md, out object ret)
|
||||
@@ -557,12 +592,20 @@ namespace OpenRA
|
||||
: base(false) { }
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Field)]
|
||||
public sealed class RequireAttribute : SerializeAttribute
|
||||
{
|
||||
public RequireAttribute()
|
||||
: base(true, true) { }
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Field)]
|
||||
public sealed class LoadUsingAttribute : SerializeAttribute
|
||||
{
|
||||
public LoadUsingAttribute(string loader)
|
||||
public LoadUsingAttribute(string loader, bool required = false)
|
||||
{
|
||||
Loader = loader;
|
||||
Required = required;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -577,10 +620,12 @@ namespace OpenRA
|
||||
public string YamlName;
|
||||
public string Loader;
|
||||
public bool FromYamlKey;
|
||||
public bool Required;
|
||||
|
||||
public SerializeAttribute(bool serialize = true)
|
||||
public SerializeAttribute(bool serialize = true, bool required = false)
|
||||
{
|
||||
Serialize = serialize;
|
||||
Required = required;
|
||||
}
|
||||
|
||||
internal Func<MiniYaml, object> GetLoader(Type type)
|
||||
|
||||
@@ -94,7 +94,16 @@ namespace OpenRA
|
||||
throw new YamlException("Junk value `{0}` on trait node {1}"
|
||||
.F(my.Value, traitName));
|
||||
var info = Game.CreateObject<ITraitInfo>(traitName + "Info");
|
||||
FieldLoader.Load(info, my);
|
||||
try
|
||||
{
|
||||
FieldLoader.Load(info, my);
|
||||
}
|
||||
catch (FieldLoader.MissingFieldsException e)
|
||||
{
|
||||
var header = "Trait name " + traitName + ": " + (e.Missing.Length > 1 ? "Required properties missing" : "Required property missing");
|
||||
throw new FieldLoader.MissingFieldsException(e.Missing, header);
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Desc("This actor's experience increases when it has killed a GivesExperience actor.")]
|
||||
public class GainsExperienceInfo : ITraitInfo, Requires<ValuedInfo>, Requires<UpgradeManagerInfo>
|
||||
{
|
||||
[FieldLoader.LoadUsing("LoadUpgrades")]
|
||||
[Desc("Upgrades to grant at each level. (Required property)",
|
||||
[FieldLoader.LoadUsing("LoadUpgrades", true)]
|
||||
[Desc("Upgrades to grant at each level.",
|
||||
"Key is the XP requirements for each level as a percentage of our own value.",
|
||||
"Value is a list of the upgrade types to grant")]
|
||||
public readonly Dictionary<int, string[]> Upgrades = null;
|
||||
@@ -36,10 +36,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
static object LoadUpgrades(MiniYaml y)
|
||||
{
|
||||
MiniYaml upgrades;
|
||||
|
||||
if (!y.ToDictionary().TryGetValue("Upgrades", out upgrades))
|
||||
throw new YamlException("GainsExperience is missing Upgrades.");
|
||||
MiniYaml upgrades = y.ToDictionary()["Upgrades"];
|
||||
|
||||
return upgrades.Nodes.ToDictionary(
|
||||
kv => FieldLoader.GetValue<int>("(key)", kv.Key),
|
||||
|
||||
@@ -86,7 +86,8 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
||||
{
|
||||
var fieldDescLines = info.Field.GetCustomAttributes<DescAttribute>(true).SelectMany(d => d.Lines);
|
||||
var fieldType = FriendlyTypeName(info.Field.FieldType);
|
||||
var defaultValue = FieldSaver.SaveField(liveTraitInfo, info.Field.Name).Value.Value;
|
||||
var loadInfo = info.Field.GetCustomAttributes<FieldLoader.SerializeAttribute>(true).FirstOrDefault();
|
||||
var defaultValue = loadInfo != null && loadInfo.Required ? "<em>(required)</em>" : FieldSaver.SaveField(liveTraitInfo, info.Field.Name).Value.Value;
|
||||
doc.Append("<tr><td>{0}</td><td>{1}</td><td>{2}</td>".F(info.YamlName, defaultValue, fieldType));
|
||||
doc.Append("<td>");
|
||||
foreach (var line in fieldDescLines)
|
||||
|
||||
Reference in New Issue
Block a user