Make ActorPreview and EditorActorPreview wrap ActorReference.

This commit is contained in:
Paul Chote
2020-06-12 13:21:09 +01:00
committed by reaperrr
parent ae7cfa56b7
commit c6c3a8c60d
22 changed files with 265 additions and 162 deletions

View File

@@ -145,6 +145,9 @@ namespace OpenRA
protected ValueActorInit(TraitInfo info, T value)
: base(info.InstanceName) { this.value = value; }
protected ValueActorInit(string instanceName, T value)
: base(instanceName) { this.value = value; }
protected ValueActorInit(T value) { this.value = value; }
public virtual T Value { get { return value; } }

View File

@@ -13,8 +13,10 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA
{
@@ -23,13 +25,10 @@ namespace OpenRA
public class ActorReference : IEnumerable
{
public string Type;
public TypeDictionary InitDict
{
get { return initDict.Value; }
}
Lazy<TypeDictionary> initDict;
internal TypeDictionary InitDict { get { return initDict.Value; } }
public ActorReference(string type)
: this(type, new Dictionary<string, MiniYaml>()) { }
@@ -52,6 +51,18 @@ namespace OpenRA
});
}
public ActorReference(string type, TypeDictionary inits)
{
Type = type;
initDict = new Lazy<TypeDictionary>(() =>
{
var dict = new TypeDictionary();
foreach (var i in inits)
dict.Add(i);
return dict;
});
}
static ActorInit LoadInit(string initName, MiniYaml initYaml)
{
var initInstance = initName.Split(ActorInfo.TraitInstanceSeparator);
@@ -74,7 +85,7 @@ namespace OpenRA
public MiniYaml Save(Func<ActorInit, bool> initFilter = null)
{
var ret = new MiniYaml(Type);
foreach (var o in InitDict)
foreach (var o in initDict.Value)
{
var init = o as ActorInit;
if (init == null || o is ISuppressInitExport)
@@ -94,7 +105,17 @@ namespace OpenRA
return ret;
}
// for initialization syntax
public IEnumerator GetEnumerator() { return initDict.Value.GetEnumerator(); }
public ActorReference Clone()
{
var clone = new ActorReference(Type);
foreach (var init in initDict.Value)
clone.initDict.Value.Add(init);
return clone;
}
public void Add(ActorInit init)
{
if (init is ISingleInstanceInit && InitDict.Contains(init.GetType()))
@@ -103,15 +124,83 @@ namespace OpenRA
InitDict.Add(init);
}
public IEnumerator GetEnumerator() { return InitDict.GetEnumerator(); }
public void Remove(ActorInit o) { initDict.Value.Remove(o); }
public ActorReference Clone()
public int RemoveAll<T>() where T : ActorInit
{
var clone = new ActorReference(Type);
foreach (var init in InitDict)
clone.InitDict.Add(init);
var removed = 0;
foreach (var o in initDict.Value.WithInterface<T>().ToList())
{
removed++;
initDict.Value.Remove(o);
}
return clone;
return removed;
}
public IEnumerable<T> GetAll<T>() where T : ActorInit
{
return initDict.Value.WithInterface<T>();
}
public T GetOrDefault<T>(TraitInfo info) where T : ActorInit
{
var inits = initDict.Value.WithInterface<T>();
// Traits tagged with an instance name prefer inits with the same name.
// If a more specific init is not available, fall back to an unnamed init.
// If duplicate inits are defined, take the last to match standard yaml override expectations
if (info != null && !string.IsNullOrEmpty(info.InstanceName))
return inits.LastOrDefault(i => i.InstanceName == info.InstanceName) ??
inits.LastOrDefault(i => string.IsNullOrEmpty(i.InstanceName));
// Untagged traits will only use untagged inits
return inits.LastOrDefault(i => string.IsNullOrEmpty(i.InstanceName));
}
public T Get<T>(TraitInfo info) where T : ActorInit
{
var init = GetOrDefault<T>(info);
if (init == null)
throw new InvalidOperationException("TypeDictionary does not contain instance of type `{0}`".F(typeof(T)));
return init;
}
public U GetValue<T, U>(TraitInfo info) where T : ValueActorInit<U>
{
return Get<T>(info).Value;
}
public U GetValue<T, U>(TraitInfo info, U fallback) where T : ValueActorInit<U>
{
var init = GetOrDefault<T>(info);
return init != null ? init.Value : fallback;
}
public bool Contains<T>(TraitInfo info) where T : ActorInit { return GetOrDefault<T>(info) != null; }
public T GetOrDefault<T>() where T : ActorInit, ISingleInstanceInit
{
return initDict.Value.GetOrDefault<T>();
}
public T Get<T>() where T : ActorInit, ISingleInstanceInit
{
return initDict.Value.Get<T>();
}
public U GetValue<T, U>() where T : ValueActorInit<U>, ISingleInstanceInit
{
return Get<T>().Value;
}
public U GetValue<T, U>(U fallback) where T : ValueActorInit<U>, ISingleInstanceInit
{
var init = GetOrDefault<T>();
return init != null ? init.Value : fallback;
}
public bool Contains<T>() where T : ActorInit, ISingleInstanceInit { return GetOrDefault<T>() != null; }
}
}

View File

@@ -276,7 +276,7 @@ namespace OpenRA
foreach (var kv in actorDefinitions.Nodes.Where(d => d.Value.Value == "mpspawn"))
{
var s = new ActorReference(kv.Value.Value, kv.Value.ToDictionary());
spawns.Add(s.InitDict.Get<LocationInit>().Value);
spawns.Add(s.Get<LocationInit>().Value);
}
newData.SpawnPoints = spawns.ToArray();

View File

@@ -334,6 +334,11 @@ namespace OpenRA
return CreateActor(true, name, initDict);
}
public Actor CreateActor(bool addToWorld, ActorReference reference)
{
return CreateActor(addToWorld, reference.Type, reference.InitDict);
}
public Actor CreateActor(bool addToWorld, string name, TypeDictionary initDict)
{
var a = new Actor(this, name, initDict);