Skip to content

Commit c6c3a8c

Browse files
pchotereaperrr
authored andcommitted
Make ActorPreview and EditorActorPreview wrap ActorReference.
1 parent ae7cfa5 commit c6c3a8c

22 files changed

+263
-160
lines changed

OpenRA.Game/Map/ActorInitializer.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,9 @@ public abstract class ValueActorInit<T> : ActorInit
145145
protected ValueActorInit(TraitInfo info, T value)
146146
: base(info.InstanceName) { this.value = value; }
147147

148+
protected ValueActorInit(string instanceName, T value)
149+
: base(instanceName) { this.value = value; }
150+
148151
protected ValueActorInit(T value) { this.value = value; }
149152

150153
public virtual T Value { get { return value; } }

OpenRA.Game/Map/ActorReference.cs

Lines changed: 102 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313
using System.Collections;
1414
using System.Collections.Generic;
1515
using System.IO;
16+
using System.Linq;
1617
using System.Runtime.Serialization;
1718
using OpenRA.Primitives;
19+
using OpenRA.Traits;
1820

1921
namespace OpenRA
2022
{
@@ -23,13 +25,10 @@ public interface ISuppressInitExport { }
2325
public class ActorReference : IEnumerable
2426
{
2527
public string Type;
26-
public TypeDictionary InitDict
27-
{
28-
get { return initDict.Value; }
29-
}
30-
3128
Lazy<TypeDictionary> initDict;
3229

30+
internal TypeDictionary InitDict { get { return initDict.Value; } }
31+
3332
public ActorReference(string type)
3433
: this(type, new Dictionary<string, MiniYaml>()) { }
3534

@@ -52,6 +51,18 @@ public ActorReference(string type, Dictionary<string, MiniYaml> inits)
5251
});
5352
}
5453

54+
public ActorReference(string type, TypeDictionary inits)
55+
{
56+
Type = type;
57+
initDict = new Lazy<TypeDictionary>(() =>
58+
{
59+
var dict = new TypeDictionary();
60+
foreach (var i in inits)
61+
dict.Add(i);
62+
return dict;
63+
});
64+
}
65+
5566
static ActorInit LoadInit(string initName, MiniYaml initYaml)
5667
{
5768
var initInstance = initName.Split(ActorInfo.TraitInstanceSeparator);
@@ -74,7 +85,7 @@ static ActorInit LoadInit(string initName, MiniYaml initYaml)
7485
public MiniYaml Save(Func<ActorInit, bool> initFilter = null)
7586
{
7687
var ret = new MiniYaml(Type);
77-
foreach (var o in InitDict)
88+
foreach (var o in initDict.Value)
7889
{
7990
var init = o as ActorInit;
8091
if (init == null || o is ISuppressInitExport)
@@ -94,7 +105,17 @@ public MiniYaml Save(Func<ActorInit, bool> initFilter = null)
94105
return ret;
95106
}
96107

97-
// for initialization syntax
108+
public IEnumerator GetEnumerator() { return initDict.Value.GetEnumerator(); }
109+
110+
public ActorReference Clone()
111+
{
112+
var clone = new ActorReference(Type);
113+
foreach (var init in initDict.Value)
114+
clone.initDict.Value.Add(init);
115+
116+
return clone;
117+
}
118+
98119
public void Add(ActorInit init)
99120
{
100121
if (init is ISingleInstanceInit && InitDict.Contains(init.GetType()))
@@ -103,15 +124,83 @@ public void Add(ActorInit init)
103124
InitDict.Add(init);
104125
}
105126

106-
public IEnumerator GetEnumerator() { return InitDict.GetEnumerator(); }
127+
public void Remove(ActorInit o) { initDict.Value.Remove(o); }
107128

108-
public ActorReference Clone()
129+
public int RemoveAll<T>() where T : ActorInit
109130
{
110-
var clone = new ActorReference(Type);
111-
foreach (var init in InitDict)
112-
clone.InitDict.Add(init);
131+
var removed = 0;
132+
foreach (var o in initDict.Value.WithInterface<T>().ToList())
133+
{
134+
removed++;
135+
initDict.Value.Remove(o);
136+
}
113137

114-
return clone;
138+
return removed;
115139
}
140+
141+
public IEnumerable<T> GetAll<T>() where T : ActorInit
142+
{
143+
return initDict.Value.WithInterface<T>();
144+
}
145+
146+
public T GetOrDefault<T>(TraitInfo info) where T : ActorInit
147+
{
148+
var inits = initDict.Value.WithInterface<T>();
149+
150+
// Traits tagged with an instance name prefer inits with the same name.
151+
// If a more specific init is not available, fall back to an unnamed init.
152+
// If duplicate inits are defined, take the last to match standard yaml override expectations
153+
if (info != null && !string.IsNullOrEmpty(info.InstanceName))
154+
return inits.LastOrDefault(i => i.InstanceName == info.InstanceName) ??
155+
inits.LastOrDefault(i => string.IsNullOrEmpty(i.InstanceName));
156+
157+
// Untagged traits will only use untagged inits
158+
return inits.LastOrDefault(i => string.IsNullOrEmpty(i.InstanceName));
159+
}
160+
161+
public T Get<T>(TraitInfo info) where T : ActorInit
162+
{
163+
var init = GetOrDefault<T>(info);
164+
if (init == null)
165+
throw new InvalidOperationException("TypeDictionary does not contain instance of type `{0}`".F(typeof(T)));
166+
167+
return init;
168+
}
169+
170+
public U GetValue<T, U>(TraitInfo info) where T : ValueActorInit<U>
171+
{
172+
return Get<T>(info).Value;
173+
}
174+
175+
public U GetValue<T, U>(TraitInfo info, U fallback) where T : ValueActorInit<U>
176+
{
177+
var init = GetOrDefault<T>(info);
178+
return init != null ? init.Value : fallback;
179+
}
180+
181+
public bool Contains<T>(TraitInfo info) where T : ActorInit { return GetOrDefault<T>(info) != null; }
182+
183+
public T GetOrDefault<T>() where T : ActorInit, ISingleInstanceInit
184+
{
185+
return initDict.Value.GetOrDefault<T>();
186+
}
187+
188+
public T Get<T>() where T : ActorInit, ISingleInstanceInit
189+
{
190+
return initDict.Value.Get<T>();
191+
}
192+
193+
public U GetValue<T, U>() where T : ValueActorInit<U>, ISingleInstanceInit
194+
{
195+
return Get<T>().Value;
196+
}
197+
198+
public U GetValue<T, U>(U fallback) where T : ValueActorInit<U>, ISingleInstanceInit
199+
{
200+
var init = GetOrDefault<T>();
201+
return init != null ? init.Value : fallback;
202+
}
203+
204+
public bool Contains<T>() where T : ActorInit, ISingleInstanceInit { return GetOrDefault<T>() != null; }
116205
}
117206
}

OpenRA.Game/Map/MapPreview.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ public void UpdateFromMap(IReadOnlyPackage p, IReadOnlyPackage parent, MapClassi
276276
foreach (var kv in actorDefinitions.Nodes.Where(d => d.Value.Value == "mpspawn"))
277277
{
278278
var s = new ActorReference(kv.Value.Value, kv.Value.ToDictionary());
279-
spawns.Add(s.InitDict.Get<LocationInit>().Value);
279+
spawns.Add(s.Get<LocationInit>().Value);
280280
}
281281

282282
newData.SpawnPoints = spawns.ToArray();

OpenRA.Game/World.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,11 @@ public Actor CreateActor(string name, TypeDictionary initDict)
334334
return CreateActor(true, name, initDict);
335335
}
336336

337+
public Actor CreateActor(bool addToWorld, ActorReference reference)
338+
{
339+
return CreateActor(addToWorld, reference.Type, reference.InitDict);
340+
}
341+
337342
public Actor CreateActor(bool addToWorld, string name, TypeDictionary initDict)
338343
{
339344
var a = new Actor(this, name, initDict);

OpenRA.Mods.Common/EditorBrushes/EditorActorBrush.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public bool HandleMouseInput(MouseInput mi)
6262
if (!actor.Footprint.All(c => world.Map.Tiles.Contains(c.Key)))
6363
return true;
6464

65-
var action = new AddActorAction(editorLayer, actor.Actor);
65+
var action = new AddActorAction(editorLayer, actor.Export());
6666
editorActionManager.Add(action);
6767
}
6868

OpenRA.Mods.Common/EditorBrushes/EditorCopyPasteBrush.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,11 +134,11 @@ void Copy(CellRegion source, CVec offset)
134134
continue;
135135

136136
var copy = preview.Export();
137-
if (copy.InitDict.Contains<LocationInit>())
137+
var locationInit = copy.GetOrDefault<LocationInit>();
138+
if (locationInit != null)
138139
{
139-
var location = copy.InitDict.Get<LocationInit>();
140-
copy.InitDict.Remove(location);
141-
copy.InitDict.Add(new LocationInit(location.Value + offset));
140+
copy.RemoveAll<LocationInit>();
141+
copy.Add(new LocationInit(locationInit.Value + offset));
142142
}
143143

144144
previews.Add(preview.ID, copy);

OpenRA.Mods.Common/Graphics/ActorPreview.cs

Lines changed: 23 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -33,74 +33,34 @@ public class ActorPreviewInitializer : IActorInitializer
3333
public readonly WorldRenderer WorldRenderer;
3434
public World World { get { return WorldRenderer.World; } }
3535

36-
readonly TypeDictionary dict;
36+
readonly ActorReference reference;
3737

3838
public ActorPreviewInitializer(ActorInfo actor, WorldRenderer worldRenderer, TypeDictionary dict)
3939
{
4040
Actor = actor;
4141
WorldRenderer = worldRenderer;
42-
this.dict = dict;
42+
reference = new ActorReference(actor.Name, dict);
4343
}
4444

45-
public T GetOrDefault<T>(TraitInfo info) where T : ActorInit
45+
public ActorPreviewInitializer(ActorReference actor, WorldRenderer worldRenderer)
4646
{
47-
var inits = dict.WithInterface<T>();
48-
49-
// Traits tagged with an instance name prefer inits with the same name.
50-
// If a more specific init is not available, fall back to an unnamed init.
51-
// If duplicate inits are defined, take the last to match standard yaml override expectations
52-
if (info != null && !string.IsNullOrEmpty(info.InstanceName))
53-
return inits.LastOrDefault(i => i.InstanceName == info.InstanceName) ??
54-
inits.LastOrDefault(i => string.IsNullOrEmpty(i.InstanceName));
55-
56-
// Untagged traits will only use untagged inits
57-
return inits.LastOrDefault(i => string.IsNullOrEmpty(i.InstanceName));
58-
}
59-
60-
public T Get<T>(TraitInfo info) where T : ActorInit
61-
{
62-
var init = GetOrDefault<T>(info);
63-
if (init == null)
64-
throw new InvalidOperationException("TypeDictionary does not contain instance of type `{0}`".F(typeof(T)));
65-
66-
return init;
67-
}
68-
69-
public U GetValue<T, U>(TraitInfo info) where T : ValueActorInit<U>
70-
{
71-
return Get<T>(info).Value;
72-
}
73-
74-
public U GetValue<T, U>(TraitInfo info, U fallback) where T : ValueActorInit<U>
75-
{
76-
var init = GetOrDefault<T>(info);
77-
return init != null ? init.Value : fallback;
78-
}
79-
80-
public bool Contains<T>() where T : ActorInit, ISingleInstanceInit { return GetOrDefault<T>() != null; }
81-
82-
public T GetOrDefault<T>() where T : ActorInit, ISingleInstanceInit
83-
{
84-
return dict.GetOrDefault<T>();
85-
}
86-
87-
public T Get<T>() where T : ActorInit, ISingleInstanceInit
88-
{
89-
return dict.Get<T>();
90-
}
91-
92-
public U GetValue<T, U>() where T : ValueActorInit<U>, ISingleInstanceInit
93-
{
94-
return Get<T>().Value;
95-
}
96-
97-
public U GetValue<T, U>(U fallback) where T : ValueActorInit<U>, ISingleInstanceInit
98-
{
99-
var init = GetOrDefault<T>();
100-
return init != null ? init.Value : fallback;
47+
Actor = worldRenderer.World.Map.Rules.Actors[actor.Type];
48+
reference = actor;
49+
WorldRenderer = worldRenderer;
10150
}
10251

103-
public bool Contains<T>(TraitInfo info) where T : ActorInit { return GetOrDefault<T>(info) != null; }
52+
// Forward IActorInitializer queries to the actor reference
53+
// ActorReference can't reference a World instance, which prevents it from implementing this directly.
54+
public T GetOrDefault<T>(TraitInfo info) where T : ActorInit { return reference.GetOrDefault<T>(info); }
55+
public T Get<T>(TraitInfo info) where T : ActorInit { return reference.Get<T>(info); }
56+
public U GetValue<T, U>(TraitInfo info) where T : ValueActorInit<U> { return reference.GetValue<T, U>(info); }
57+
public U GetValue<T, U>(TraitInfo info, U fallback) where T : ValueActorInit<U> { return reference.GetValue<T, U>(info, fallback); }
58+
public bool Contains<T>(TraitInfo info) where T : ActorInit { return reference.Contains<T>(info); }
59+
public T GetOrDefault<T>() where T : ActorInit, ISingleInstanceInit { return reference.GetOrDefault<T>(); }
60+
public T Get<T>() where T : ActorInit, ISingleInstanceInit { return reference.Get<T>(); }
61+
public U GetValue<T, U>() where T : ValueActorInit<U>, ISingleInstanceInit { return reference.GetValue<T, U>(); }
62+
public U GetValue<T, U>(U fallback) where T : ValueActorInit<U>, ISingleInstanceInit { return reference.GetValue<T, U>(fallback); }
63+
public bool Contains<T>() where T : ActorInit, ISingleInstanceInit { return reference.Contains<T>(); }
10464

10565
public Func<WRot> GetOrientation()
10666
{
@@ -109,7 +69,7 @@ public Func<WRot> GetOrientation()
10969
return () => WRot.Zero;
11070

11171
// Dynamic facing takes priority
112-
var dynamicInit = dict.GetOrDefault<DynamicFacingInit>();
72+
var dynamicInit = reference.GetOrDefault<DynamicFacingInit>();
11373
if (dynamicInit != null)
11474
{
11575
// TODO: Account for terrain slope
@@ -118,7 +78,7 @@ public Func<WRot> GetOrientation()
11878
}
11979

12080
// Fall back to initial actor facing if an Init isn't available
121-
var facingInit = dict.GetOrDefault<FacingInit>();
81+
var facingInit = reference.GetOrDefault<FacingInit>();
12282
var facing = facingInit != null ? facingInit.Value : facingInfo.GetInitialFacing();
12383
var orientation = WRot.FromFacing(facing);
12484
return () => orientation;
@@ -131,22 +91,22 @@ public Func<WAngle> GetFacing()
13191
return () => WAngle.Zero;
13292

13393
// Dynamic facing takes priority
134-
var dynamicInit = dict.GetOrDefault<DynamicFacingInit>();
94+
var dynamicInit = reference.GetOrDefault<DynamicFacingInit>();
13595
if (dynamicInit != null)
13696
{
13797
var getFacing = dynamicInit.Value;
13898
return () => WAngle.FromFacing(getFacing());
13999
}
140100

141101
// Fall back to initial actor facing if an Init isn't available
142-
var facingInit = dict.GetOrDefault<FacingInit>();
102+
var facingInit = reference.GetOrDefault<FacingInit>();
143103
var facing = WAngle.FromFacing(facingInit != null ? facingInit.Value : facingInfo.GetInitialFacing());
144104
return () => facing;
145105
}
146106

147107
public DamageState GetDamageState()
148108
{
149-
var health = dict.GetOrDefault<HealthInit>();
109+
var health = reference.GetOrDefault<HealthInit>();
150110

151111
if (health == null)
152112
return DamageState.Undamaged;

OpenRA.Mods.Common/Lint/CheckPlayers.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public void Run(Action<string> emitError, Action<string> emitWarning, ModData mo
7070
foreach (var kv in map.ActorDefinitions.Where(d => d.Value.Value == "mpspawn"))
7171
{
7272
var s = new ActorReference(kv.Value.Value, kv.Value.ToDictionary());
73-
spawns.Add(s.InitDict.Get<LocationInit>().Value);
73+
spawns.Add(s.Get<LocationInit>().Value);
7474
}
7575

7676
if (playerCount > spawns.Count)
@@ -88,7 +88,7 @@ public void Run(Action<string> emitError, Action<string> emitWarning, ModData mo
8888
foreach (var kv in map.ActorDefinitions)
8989
{
9090
var actorReference = new ActorReference(kv.Value.Value, kv.Value.ToDictionary());
91-
var ownerInit = actorReference.InitDict.GetOrDefault<OwnerInit>();
91+
var ownerInit = actorReference.GetOrDefault<OwnerInit>();
9292
if (ownerInit == null)
9393
emitError("Actor {0} is not owned by any player.".F(kv.Key));
9494
else

OpenRA.Mods.Common/Traits/Air/Aircraft.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ IEnumerable<EditorActorOption> IEditorActorOptions.ActorOptions(ActorInfo ai, Wo
184184
yield return new EditorActorSlider("Facing", EditorFacingDisplayOrder, 0, 255, 8,
185185
actor =>
186186
{
187-
var init = actor.Init<FacingInit>();
187+
var init = actor.GetInitOrDefault<FacingInit>(this);
188188
return init != null ? init.Value : InitialFacing;
189189
},
190190
(actor, value) => actor.ReplaceInit(new FacingInit((int)value)));

0 commit comments

Comments
 (0)