Add ISingleInstanceInit interface.
Inits that are logically singletons (e.g. actor location or owner) should implement this interface to avoid runtime inconsistencies. Duplicate instances are rejected at init-time, allowing simpler queries when they are used.
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Eluant;
|
||||
using Eluant.ObjectBinding;
|
||||
@@ -116,13 +117,19 @@ namespace OpenRA
|
||||
|
||||
internal Actor(World world, string name, TypeDictionary initDict)
|
||||
{
|
||||
var duplicateInit = initDict.WithInterface<ISingleInstanceInit>().GroupBy(i => i.GetType())
|
||||
.FirstOrDefault(i => i.Count() > 1);
|
||||
|
||||
if (duplicateInit != null)
|
||||
throw new InvalidDataException("Duplicate initializer '{0}'".F(duplicateInit.Key.Name));
|
||||
|
||||
var init = new ActorInitializer(this, initDict);
|
||||
|
||||
readOnlyConditionCache = new ReadOnlyDictionary<string, int>(conditionCache);
|
||||
|
||||
World = world;
|
||||
ActorID = world.NextAID();
|
||||
var ownerInit = init.GetOrDefault<OwnerInit>(null);
|
||||
var ownerInit = init.GetOrDefault<OwnerInit>();
|
||||
if (ownerInit != null)
|
||||
Owner = ownerInit.Value(world);
|
||||
|
||||
|
||||
@@ -26,6 +26,12 @@ namespace OpenRA
|
||||
U GetValue<T, U>(TraitInfo info) where T : ValueActorInit<U>;
|
||||
U GetValue<T, U>(TraitInfo info, U fallback) where T : ValueActorInit<U>;
|
||||
bool Contains<T>(TraitInfo info) where T : ActorInit;
|
||||
|
||||
T GetOrDefault<T>() where T : ActorInit, ISingleInstanceInit;
|
||||
T Get<T>() where T : ActorInit, ISingleInstanceInit;
|
||||
U GetValue<T, U>() where T : ValueActorInit<U>, ISingleInstanceInit;
|
||||
U GetValue<T, U>(U fallback) where T : ValueActorInit<U>, ISingleInstanceInit;
|
||||
bool Contains<T>() where T : ActorInit, ISingleInstanceInit;
|
||||
}
|
||||
|
||||
public class ActorInitializer : IActorInitializer
|
||||
@@ -77,6 +83,29 @@ namespace OpenRA
|
||||
}
|
||||
|
||||
public bool Contains<T>(TraitInfo info) where T : ActorInit { return GetOrDefault<T>(info) != null; }
|
||||
|
||||
public T GetOrDefault<T>() where T : ActorInit, ISingleInstanceInit
|
||||
{
|
||||
return Dict.GetOrDefault<T>();
|
||||
}
|
||||
|
||||
public T Get<T>() where T : ActorInit, ISingleInstanceInit
|
||||
{
|
||||
return Dict.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; }
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -88,6 +117,9 @@ namespace OpenRA
|
||||
* finds with an argument type that matches the given LuaValue.
|
||||
* - Most ActorInits will want to inherit either ValueActorInit<T> or CompositeActorInit which hide the low-level plumbing.
|
||||
* - Inits that reference actors should use ActorInitActorReference which allows actors to be referenced by name in map.yaml
|
||||
* - Inits that should only have a single instance defined on an actor should implement ISingleInstanceInit to allow
|
||||
* direct queries and runtime enforcement.
|
||||
* - Inits that aren't ISingleInstanceInit should expose a ctor that accepts a TraitInfo to allow per-trait targeting.
|
||||
*/
|
||||
public abstract class ActorInit
|
||||
{
|
||||
@@ -104,6 +136,8 @@ namespace OpenRA
|
||||
public abstract MiniYaml Save();
|
||||
}
|
||||
|
||||
public interface ISingleInstanceInit { }
|
||||
|
||||
public abstract class ValueActorInit<T> : ActorInit
|
||||
{
|
||||
protected readonly T value;
|
||||
@@ -181,16 +215,13 @@ namespace OpenRA
|
||||
}
|
||||
}
|
||||
|
||||
public class LocationInit : ValueActorInit<CPos>
|
||||
public class LocationInit : ValueActorInit<CPos>, ISingleInstanceInit
|
||||
{
|
||||
public LocationInit(TraitInfo info, CPos value)
|
||||
: base(info, value) { }
|
||||
|
||||
public LocationInit(CPos value)
|
||||
: base(value) { }
|
||||
}
|
||||
|
||||
public class OwnerInit : ActorInit
|
||||
public class OwnerInit : ActorInit, ISingleInstanceInit
|
||||
{
|
||||
public readonly string InternalName;
|
||||
protected readonly Player value;
|
||||
|
||||
@@ -40,7 +40,14 @@ namespace OpenRA
|
||||
{
|
||||
var dict = new TypeDictionary();
|
||||
foreach (var i in inits)
|
||||
dict.Add(LoadInit(i.Key, i.Value));
|
||||
{
|
||||
var init = LoadInit(i.Key, i.Value);
|
||||
if (init is ISingleInstanceInit && dict.Contains(init.GetType()))
|
||||
throw new InvalidDataException("Duplicate initializer '{0}'".F(init.GetType().Name));
|
||||
|
||||
dict.Add(init);
|
||||
}
|
||||
|
||||
return dict;
|
||||
});
|
||||
}
|
||||
@@ -88,7 +95,14 @@ namespace OpenRA
|
||||
}
|
||||
|
||||
// for initialization syntax
|
||||
public void Add(object o) { InitDict.Add(o); }
|
||||
public void Add(ActorInit init)
|
||||
{
|
||||
if (init is ISingleInstanceInit && InitDict.Contains(init.GetType()))
|
||||
throw new InvalidDataException("Duplicate initializer '{0}'".F(init.GetType().Name));
|
||||
|
||||
InitDict.Add(init);
|
||||
}
|
||||
|
||||
public IEnumerator GetEnumerator() { return InitDict.GetEnumerator(); }
|
||||
|
||||
public ActorReference Clone()
|
||||
|
||||
@@ -41,6 +41,11 @@ namespace OpenRA.Primitives
|
||||
return data.ContainsKey(typeof(T));
|
||||
}
|
||||
|
||||
public bool Contains(Type t)
|
||||
{
|
||||
return data.ContainsKey(t);
|
||||
}
|
||||
|
||||
public T Get<T>()
|
||||
{
|
||||
return (T)Get(typeof(T), true);
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
{
|
||||
self = init.Self;
|
||||
|
||||
var returnInit = init.GetOrDefault<ChronoshiftReturnInit>(info);
|
||||
var returnInit = init.GetOrDefault<ChronoshiftReturnInit>();
|
||||
if (returnInit != null)
|
||||
{
|
||||
ReturnTicks = returnInit.Ticks;
|
||||
@@ -176,7 +176,7 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
void ITransformActorInitModifier.ModifyTransformActorInit(Actor self, TypeDictionary init) { ModifyActorInit(init); }
|
||||
}
|
||||
|
||||
public class ChronoshiftReturnInit : CompositeActorInit
|
||||
public class ChronoshiftReturnInit : CompositeActorInit, ISingleInstanceInit
|
||||
{
|
||||
public readonly int Ticks;
|
||||
public readonly int Duration;
|
||||
|
||||
@@ -95,9 +95,9 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
health = self.Trait<Health>();
|
||||
|
||||
wsb = self.TraitsImplementing<WithSpriteBody>().Single(w => w.Info.Name == info.Body);
|
||||
faction = init.GetValue<FactionInit, string>(info, self.Owner.Faction.InternalName);
|
||||
faction = init.GetValue<FactionInit, string>(self.Owner.Faction.InternalName);
|
||||
|
||||
var returnInit = init.GetOrDefault<ChronoshiftReturnInit>(info);
|
||||
var returnInit = init.GetOrDefault<ChronoshiftReturnInit>();
|
||||
if (returnInit != null)
|
||||
{
|
||||
returnTicks = returnInit.Ticks;
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
public InfiltrateForTransform(ActorInitializer init, InfiltrateForTransformInfo info)
|
||||
{
|
||||
this.info = info;
|
||||
faction = init.GetValue<FactionInit, string>(info, init.Self.Owner.Faction.InternalName);
|
||||
faction = init.GetValue<FactionInit, string>(init.Self.Owner.Faction.InternalName);
|
||||
}
|
||||
|
||||
void INotifyInfiltrated.Infiltrated(Actor self, Actor infiltrator, BitSet<TargetableType> types)
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
var bibOffset = bi.Dimensions.Y - rows;
|
||||
var centerOffset = bi.CenterOffset(init.World);
|
||||
var map = init.World.Map;
|
||||
var location = init.GetValue<LocationInit, CPos>(this, CPos.Zero);
|
||||
var location = init.GetValue<LocationInit, CPos>(CPos.Zero);
|
||||
|
||||
for (var i = 0; i < rows * width; i++)
|
||||
{
|
||||
|
||||
@@ -82,15 +82,15 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
Info = info;
|
||||
self = init.Self;
|
||||
|
||||
var locationInit = init.GetOrDefault<LocationInit>(info);
|
||||
var locationInit = init.GetOrDefault<LocationInit>();
|
||||
if (locationInit != null)
|
||||
SetPosition(self, locationInit.Value);
|
||||
|
||||
var centerPositionInit = init.GetOrDefault<CenterPositionInit>(info);
|
||||
var centerPositionInit = init.GetOrDefault<CenterPositionInit>();
|
||||
if (centerPositionInit != null)
|
||||
SetPosition(self, centerPositionInit.Value);
|
||||
|
||||
Facing = WAngle.FromFacing(init.GetValue<FacingInit, int>(info, Info.GetInitialFacing()));
|
||||
Facing = WAngle.FromFacing(init.GetValue<FacingInit, int>(Info.GetInitialFacing()));
|
||||
|
||||
// Prevent mappers from setting bogus facings
|
||||
if (Facing != Left && Facing != Right)
|
||||
|
||||
@@ -16,38 +16,38 @@ using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common
|
||||
{
|
||||
public class FacingInit : ValueActorInit<int>
|
||||
public class FacingInit : ValueActorInit<int>, ISingleInstanceInit
|
||||
{
|
||||
public FacingInit(int value)
|
||||
: base(value) { }
|
||||
}
|
||||
|
||||
public class CreationActivityDelayInit : ValueActorInit<int>
|
||||
public class CreationActivityDelayInit : ValueActorInit<int>, ISingleInstanceInit
|
||||
{
|
||||
public CreationActivityDelayInit(int value)
|
||||
: base(value) { }
|
||||
}
|
||||
|
||||
public class DynamicFacingInit : ValueActorInit<Func<int>>
|
||||
public class DynamicFacingInit : ValueActorInit<Func<int>>, ISingleInstanceInit
|
||||
{
|
||||
public DynamicFacingInit(Func<int> value)
|
||||
: base(value) { }
|
||||
}
|
||||
|
||||
public class SubCellInit : ValueActorInit<SubCell>
|
||||
public class SubCellInit : ValueActorInit<SubCell>, ISingleInstanceInit
|
||||
{
|
||||
public SubCellInit(SubCell value)
|
||||
: base(value) { }
|
||||
}
|
||||
|
||||
public class CenterPositionInit : ValueActorInit<WPos>
|
||||
public class CenterPositionInit : ValueActorInit<WPos>, ISingleInstanceInit
|
||||
{
|
||||
public CenterPositionInit(WPos value)
|
||||
: base(value) { }
|
||||
}
|
||||
|
||||
// Allows maps / transformations to specify the faction variant of an actor.
|
||||
public class FactionInit : ValueActorInit<string>
|
||||
public class FactionInit : ValueActorInit<string>, ISingleInstanceInit
|
||||
{
|
||||
public FactionInit(string value)
|
||||
: base(value) { }
|
||||
|
||||
@@ -77,6 +77,29 @@ namespace OpenRA.Mods.Common.Graphics
|
||||
return init != null ? init.Value : fallback;
|
||||
}
|
||||
|
||||
public bool Contains<T>() where T : ActorInit, ISingleInstanceInit { return GetOrDefault<T>() != null; }
|
||||
|
||||
public T GetOrDefault<T>() where T : ActorInit, ISingleInstanceInit
|
||||
{
|
||||
return dict.GetOrDefault<T>();
|
||||
}
|
||||
|
||||
public T Get<T>() where T : ActorInit, ISingleInstanceInit
|
||||
{
|
||||
return dict.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>(TraitInfo info) where T : ActorInit { return GetOrDefault<T>(info) != null; }
|
||||
|
||||
public Func<WRot> GetOrientation()
|
||||
|
||||
@@ -249,16 +249,16 @@ namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
self = init.Self;
|
||||
|
||||
var locationInit = init.GetOrDefault<LocationInit>(info);
|
||||
var locationInit = init.GetOrDefault<LocationInit>();
|
||||
if (locationInit != null)
|
||||
SetPosition(self, locationInit.Value);
|
||||
|
||||
var centerPositionInit = init.GetOrDefault<CenterPositionInit>(info);
|
||||
var centerPositionInit = init.GetOrDefault<CenterPositionInit>();
|
||||
if (centerPositionInit != null)
|
||||
SetPosition(self, centerPositionInit.Value);
|
||||
|
||||
Facing = WAngle.FromFacing(init.GetValue<FacingInit, int>(info, Info.InitialFacing));
|
||||
creationActivityDelay = init.GetValue<CreationActivityDelayInit, int>(info, 0);
|
||||
Facing = WAngle.FromFacing(init.GetValue<FacingInit, int>(Info.InitialFacing));
|
||||
creationActivityDelay = init.GetValue<CreationActivityDelayInit, int>(0);
|
||||
}
|
||||
|
||||
public WDist LandAltitude
|
||||
|
||||
@@ -183,7 +183,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
var self = init.Self;
|
||||
ActiveAttackBases = self.TraitsImplementing<AttackBase>().ToArray().Where(Exts.IsTraitEnabled);
|
||||
|
||||
stance = init.GetValue<StanceInit, UnitStance>(info, self.Owner.IsBot || !self.Owner.Playable ? info.InitialStanceAI : info.InitialStance);
|
||||
stance = init.GetValue<StanceInit, UnitStance>(self.Owner.IsBot || !self.Owner.Playable ? info.InitialStanceAI : info.InitialStance);
|
||||
|
||||
PredictedStance = stance;
|
||||
|
||||
@@ -445,7 +445,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
}
|
||||
}
|
||||
|
||||
public class StanceInit : ValueActorInit<UnitStance>
|
||||
public class StanceInit : ValueActorInit<UnitStance>, ISingleInstanceInit
|
||||
{
|
||||
public StanceInit(TraitInfo info, UnitStance value)
|
||||
: base(info, value) { }
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
this.info = info;
|
||||
var self = init.Self;
|
||||
var faction = init.GetValue<FactionInit, string>(info, self.Owner.Faction.InternalName);
|
||||
var faction = init.GetValue<FactionInit, string>(self.Owner.Faction.InternalName);
|
||||
|
||||
quantizedFacings = Exts.Lazy(() =>
|
||||
{
|
||||
|
||||
@@ -278,7 +278,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public Building(ActorInitializer init, BuildingInfo info)
|
||||
{
|
||||
self = init.Self;
|
||||
topLeft = init.GetValue<LocationInit, CPos>(info);
|
||||
topLeft = init.GetValue<LocationInit, CPos>();
|
||||
Info = info;
|
||||
influence = self.World.WorldActor.Trait<BuildingInfluence>();
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
: base(info, value) { }
|
||||
}
|
||||
|
||||
public class ParentActorInit : ValueActorInit<ActorInitActorReference>
|
||||
public class ParentActorInit : ValueActorInit<ActorInitActorReference>, ISingleInstanceInit
|
||||
{
|
||||
public ParentActorInit(Actor value)
|
||||
: base(value) { }
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
public LegacyBridgeHut(ActorInitializer init, LegacyBridgeHutInfo info)
|
||||
{
|
||||
var bridge = init.Get<ParentActorInit>(info).Value;
|
||||
var bridge = init.Get<ParentActorInit>().Value;
|
||||
init.World.AddFrameEndTask(_ =>
|
||||
{
|
||||
Bridge = bridge.Actor(init.World).Value.Trait<Bridge>();
|
||||
|
||||
@@ -16,13 +16,13 @@ using OpenRA.Traits;
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
public enum LineBuildDirection { Unset, X, Y }
|
||||
public class LineBuildDirectionInit : ValueActorInit<LineBuildDirection>
|
||||
public class LineBuildDirectionInit : ValueActorInit<LineBuildDirection>, ISingleInstanceInit
|
||||
{
|
||||
public LineBuildDirectionInit(LineBuildDirection value)
|
||||
: base(value) { }
|
||||
}
|
||||
|
||||
public class LineBuildParentInit : ValueActorInit<string[]>
|
||||
public class LineBuildParentInit : ValueActorInit<string[]>, ISingleInstanceInit
|
||||
{
|
||||
readonly Actor[] parents = null;
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public LineBuild(ActorInitializer init, LineBuildInfo info)
|
||||
{
|
||||
this.info = info;
|
||||
var lineBuildParentInit = init.GetOrDefault<LineBuildParentInit>(info);
|
||||
var lineBuildParentInit = init.GetOrDefault<LineBuildParentInit>();
|
||||
if (lineBuildParentInit != null)
|
||||
parentNodes = lineBuildParentInit.ActorValue(init.World);
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
},
|
||||
(actor, value) =>
|
||||
{
|
||||
actor.ReplaceInit(new DeployStateInit(this, value ? DeployState.Deployed : DeployState.Undeployed));
|
||||
actor.ReplaceInit(new DeployStateInit(value ? DeployState.Deployed : DeployState.Undeployed));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
checkTerrainType = info.AllowedTerrainTypes.Count > 0;
|
||||
canTurn = self.Info.HasTraitInfo<IFacingInfo>();
|
||||
move = self.TraitOrDefault<IMove>();
|
||||
deployState = init.GetValue<DeployStateInit, DeployState>(info, DeployState.Undeployed);
|
||||
deployState = init.GetValue<DeployStateInit, DeployState>(DeployState.Undeployed);
|
||||
}
|
||||
|
||||
protected override void Created(Actor self)
|
||||
@@ -337,11 +337,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
}
|
||||
}
|
||||
|
||||
public class DeployStateInit : ValueActorInit<DeployState>
|
||||
public class DeployStateInit : ValueActorInit<DeployState>, ISingleInstanceInit
|
||||
{
|
||||
public DeployStateInit(TraitInfo info, DeployState value)
|
||||
: base(info, value) { }
|
||||
|
||||
public DeployStateInit(DeployState value)
|
||||
: base(value) { }
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public GrantConditionOnFaction(ActorInitializer init, GrantConditionOnFactionInfo info)
|
||||
: base(info)
|
||||
{
|
||||
faction = init.GetValue<FactionInit, string>(info, init.Self.Owner.Faction.InternalName);
|
||||
faction = init.GetValue<FactionInit, string>(init.Self.Owner.Faction.InternalName);
|
||||
}
|
||||
|
||||
public void OnOwnerChanged(Actor self, Player oldOwner, Player newOwner)
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public GrantConditionOnLineBuildDirection(ActorInitializer init, GrantConditionOnLineBuildDirectionInfo info)
|
||||
{
|
||||
this.info = info;
|
||||
direction = init.GetValue<LineBuildDirectionInit, LineBuildDirection>(info);
|
||||
direction = init.GetValue<LineBuildDirectionInit, LineBuildDirection>();
|
||||
}
|
||||
|
||||
void INotifyCreated.Created(Actor self)
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
self = init.Self;
|
||||
this.info = info;
|
||||
|
||||
var locationInit = init.GetOrDefault<LocationInit>(info);
|
||||
var locationInit = init.GetOrDefault<LocationInit>();
|
||||
if (locationInit != null)
|
||||
SetPosition(self, locationInit.Value);
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
MaxHP = hp = info.HP > 0 ? info.HP : 1;
|
||||
|
||||
// Cast to long to avoid overflow when multiplying by the health
|
||||
var healthInit = init.GetOrDefault<HealthInit>(info);
|
||||
var healthInit = init.GetOrDefault<HealthInit>();
|
||||
if (healthInit != null)
|
||||
hp = (int)(healthInit.Value * (long)MaxHP / 100);
|
||||
|
||||
@@ -233,13 +233,10 @@ namespace OpenRA.Mods.Common.Traits
|
||||
}
|
||||
}
|
||||
|
||||
public class HealthInit : ValueActorInit<int>
|
||||
public class HealthInit : ValueActorInit<int>, ISingleInstanceInit
|
||||
{
|
||||
readonly bool allowZero;
|
||||
|
||||
public HealthInit(TraitInfo info, int value, bool allowZero = false)
|
||||
: base(info, value) { this.allowZero = allowZero; }
|
||||
|
||||
public HealthInit(int value, bool allowZero = false)
|
||||
: base(value) { this.allowZero = allowZero; }
|
||||
|
||||
|
||||
@@ -78,11 +78,11 @@ namespace OpenRA.Mods.Common.Traits
|
||||
this.info = info;
|
||||
self = init.Self;
|
||||
|
||||
TopLeft = init.GetValue<LocationInit, CPos>(info);
|
||||
CenterPosition = init.GetValue<CenterPositionInit, WPos>(info, init.World.Map.CenterOfCell(TopLeft));
|
||||
Facing = WAngle.FromFacing(init.GetValue<FacingInit, int>(info, 128));
|
||||
TopLeft = init.GetValue<LocationInit, CPos>();
|
||||
CenterPosition = init.GetValue<CenterPositionInit, WPos>(init.World.Map.CenterOfCell(TopLeft));
|
||||
Facing = WAngle.FromFacing(init.GetValue<FacingInit, int>(128));
|
||||
|
||||
dragSpeed = init.GetValue<HuskSpeedInit, int>(info, 0);
|
||||
dragSpeed = init.GetValue<HuskSpeedInit, int>(0);
|
||||
finalPosition = init.World.Map.CenterOfCell(TopLeft);
|
||||
|
||||
effectiveOwner = init.GetValue<EffectiveOwnerInit, Player>(info, self.Owner);
|
||||
@@ -171,7 +171,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
Player IEffectiveOwner.Owner { get { return effectiveOwner; } }
|
||||
}
|
||||
|
||||
public class HuskSpeedInit : ValueActorInit<int>
|
||||
public class HuskSpeedInit : ValueActorInit<int>, ISingleInstanceInit
|
||||
{
|
||||
public HuskSpeedInit(int value)
|
||||
: base(value) { }
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
public Immobile(ActorInitializer init, ImmobileInfo info)
|
||||
{
|
||||
location = init.GetValue<LocationInit, CPos>(info);
|
||||
location = init.GetValue<LocationInit, CPos>();
|
||||
position = init.World.Map.CenterOfCell(location);
|
||||
|
||||
if (info.OccupiesSpace)
|
||||
|
||||
@@ -267,25 +267,25 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
ToSubCell = FromSubCell = info.LocomotorInfo.SharesCell ? init.World.Map.Grid.DefaultSubCell : SubCell.FullCell;
|
||||
|
||||
var subCellInit = init.GetOrDefault<SubCellInit>(info);
|
||||
var subCellInit = init.GetOrDefault<SubCellInit>();
|
||||
if (subCellInit != null)
|
||||
{
|
||||
FromSubCell = ToSubCell = subCellInit.Value;
|
||||
returnToCellOnCreationRecalculateSubCell = false;
|
||||
}
|
||||
|
||||
var locationInit = init.GetOrDefault<LocationInit>(info);
|
||||
var locationInit = init.GetOrDefault<LocationInit>();
|
||||
if (locationInit != null)
|
||||
{
|
||||
fromCell = toCell = locationInit.Value;
|
||||
SetVisualPosition(self, init.World.Map.CenterOfSubCell(FromCell, FromSubCell));
|
||||
}
|
||||
|
||||
Facing = oldFacing = WAngle.FromFacing(init.GetValue<FacingInit, int>(info, info.InitialFacing));
|
||||
Facing = oldFacing = WAngle.FromFacing(init.GetValue<FacingInit, int>(info.InitialFacing));
|
||||
|
||||
// Sets the initial visual position
|
||||
// Unit will move into the cell grid (defined by LocationInit) as its initial activity
|
||||
var centerPositionInit = init.GetOrDefault<CenterPositionInit>(info);
|
||||
var centerPositionInit = init.GetOrDefault<CenterPositionInit>();
|
||||
if (centerPositionInit != null)
|
||||
{
|
||||
oldPos = centerPositionInit.Value;
|
||||
@@ -293,7 +293,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
returnToCellOnCreation = true;
|
||||
}
|
||||
|
||||
creationActivityDelay = init.GetValue<CreationActivityDelayInit, int>(info, 0);
|
||||
creationActivityDelay = init.GetValue<CreationActivityDelayInit, int>(0);
|
||||
}
|
||||
|
||||
protected override void Created(Actor self)
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
// Explore map-placed actors if the "Explore Map" option is enabled
|
||||
var shroudInfo = init.World.Map.Rules.Actors["player"].TraitInfo<ShroudInfo>();
|
||||
var exploredMap = init.World.LobbyInfo.GlobalSettings.OptionOrDefault("explored", shroudInfo.ExploredMapCheckboxEnabled);
|
||||
startsRevealed = exploredMap && init.Contains<SpawnedByMapInit>(info) && !init.Contains<HiddenUnderFogInit>(info);
|
||||
startsRevealed = exploredMap && init.Contains<SpawnedByMapInit>() && !init.Contains<HiddenUnderFogInit>();
|
||||
var buildingInfo = init.Self.Info.TraitInfoOrDefault<BuildingInfo>();
|
||||
var footprintCells = buildingInfo != null ? buildingInfo.FrozenUnderFogTiles(init.Self.Location).ToList() : new List<CPos>() { init.Self.Location };
|
||||
footprint = footprintCells.SelectMany(c => map.ProjectedCellsCovering(c.ToMPos(map))).ToArray();
|
||||
@@ -195,5 +195,5 @@ namespace OpenRA.Mods.Common.Traits
|
||||
}
|
||||
}
|
||||
|
||||
public class HiddenUnderFogInit : RuntimeFlagInit { }
|
||||
public class HiddenUnderFogInit : RuntimeFlagInit, ISingleInstanceInit { }
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
self = init.Self;
|
||||
Info = info;
|
||||
|
||||
Faction = init.GetValue<FactionInit, string>(info, self.Owner.Faction.InternalName);
|
||||
Faction = init.GetValue<FactionInit, string>(self.Owner.Faction.InternalName);
|
||||
IsValidFaction = !info.Factions.Any() || info.Factions.Contains(Faction);
|
||||
Enabled = IsValidFaction;
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (string.IsNullOrEmpty(prerequisite))
|
||||
prerequisite = init.Self.Info.Name;
|
||||
|
||||
faction = init.GetValue<FactionInit, string>(info, init.Self.Owner.Faction.InternalName);
|
||||
faction = init.GetValue<FactionInit, string>(init.Self.Owner.Faction.InternalName);
|
||||
}
|
||||
|
||||
public IEnumerable<string> ProvidesPrerequisites
|
||||
|
||||
@@ -120,7 +120,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
}
|
||||
}
|
||||
|
||||
public class PlugsInit : ValueActorInit<Dictionary<CVec, string>>
|
||||
public class PlugsInit : ValueActorInit<Dictionary<CVec, string>>, ISingleInstanceInit
|
||||
{
|
||||
public PlugsInit(Dictionary<CVec, string> value)
|
||||
: base(value) { }
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
: base(info)
|
||||
{
|
||||
rp = Exts.Lazy(() => init.Self.IsDead ? null : init.Self.TraitOrDefault<RallyPoint>());
|
||||
Faction = init.GetValue<FactionInit, string>(info, init.Self.Owner.Faction.InternalName);
|
||||
Faction = init.GetValue<FactionInit, string>(init.Self.Owner.Faction.InternalName);
|
||||
}
|
||||
|
||||
public virtual void DoProduction(Actor self, ActorInfo producee, ExitInfo exitinfo, string productionType, TypeDictionary inits)
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
{
|
||||
var sequenceProvider = init.World.Map.Rules.Sequences;
|
||||
var faction = init.GetValue<FactionInit, string>(this);
|
||||
var ownerName = init.Get<OwnerInit>(this).InternalName;
|
||||
var ownerName = init.Get<OwnerInit>().InternalName;
|
||||
var image = GetImage(init.Actor, sequenceProvider, faction);
|
||||
var palette = init.WorldRenderer.Palette(Palette ?? PlayerPalette + ownerName);
|
||||
|
||||
@@ -169,7 +169,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
public RenderSprites(ActorInitializer init, RenderSpritesInfo info)
|
||||
{
|
||||
Info = info;
|
||||
faction = init.GetValue<FactionInit, string>(info, init.Self.Owner.Faction.InternalName);
|
||||
faction = init.GetValue<FactionInit, string>(init.Self.Owner.Faction.InternalName);
|
||||
}
|
||||
|
||||
public string GetImage(Actor self)
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
{
|
||||
var body = init.Actor.TraitInfo<BodyOrientationInfo>();
|
||||
var faction = init.GetValue<FactionInit, string>(this);
|
||||
var ownerName = init.Get<OwnerInit>(this).InternalName;
|
||||
var ownerName = init.Get<OwnerInit>().InternalName;
|
||||
var sequenceProvider = init.World.Map.Rules.Sequences;
|
||||
var image = Image ?? init.Actor.Name;
|
||||
var facings = body.QuantizedFacings == -1 ?
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
p = init.WorldRenderer.Palette(Palette);
|
||||
|
||||
Func<WAngle> facing;
|
||||
var dynamicfacingInit = init.GetOrDefault<DynamicFacingInit>(this);
|
||||
var dynamicfacingInit = init.GetOrDefault<DynamicFacingInit>();
|
||||
if (dynamicfacingInit != null)
|
||||
{
|
||||
var getFacing = dynamicfacingInit.Value;
|
||||
@@ -57,7 +57,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
}
|
||||
else
|
||||
{
|
||||
var f = WAngle.FromFacing(init.GetValue<FacingInit, int>(this, 0));
|
||||
var f = WAngle.FromFacing(init.GetValue<FacingInit, int>(0));
|
||||
facing = () => f;
|
||||
}
|
||||
|
||||
|
||||
@@ -78,12 +78,12 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
p = init.WorldRenderer.Palette(Palette);
|
||||
|
||||
Func<int> facing;
|
||||
var dynamicfacingInit = init.GetOrDefault<DynamicFacingInit>(this);
|
||||
var dynamicfacingInit = init.GetOrDefault<DynamicFacingInit>();
|
||||
if (dynamicfacingInit != null)
|
||||
facing = dynamicfacingInit.Value;
|
||||
else
|
||||
{
|
||||
var f = init.GetValue<FacingInit, int>(this, 0);
|
||||
var f = init.GetValue<FacingInit, int>(0);
|
||||
facing = () => f;
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
};
|
||||
|
||||
if (IsPlayerPalette)
|
||||
p = init.WorldRenderer.Palette(Palette + init.Get<OwnerInit>(this).InternalName);
|
||||
p = init.WorldRenderer.Palette(Palette + init.Get<OwnerInit>().InternalName);
|
||||
else if (Palette != null)
|
||||
p = init.WorldRenderer.Palette(Palette);
|
||||
|
||||
|
||||
@@ -37,8 +37,8 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
yield break;
|
||||
|
||||
var adjacent = 0;
|
||||
var locationInit = init.GetOrDefault<LocationInit>(this);
|
||||
var neighbourInit = init.GetOrDefault<RuntimeNeighbourInit>(this);
|
||||
var locationInit = init.GetOrDefault<LocationInit>();
|
||||
var neighbourInit = init.GetOrDefault<RuntimeNeighbourInit>();
|
||||
|
||||
if (locationInit != null && neighbourInit != null)
|
||||
{
|
||||
@@ -168,7 +168,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
}
|
||||
}
|
||||
|
||||
public class RuntimeNeighbourInit : ValueActorInit<Dictionary<CPos, string[]>>, ISuppressInitExport
|
||||
public class RuntimeNeighbourInit : ValueActorInit<Dictionary<CPos, string[]>>, ISuppressInitExport, ISingleInstanceInit
|
||||
{
|
||||
public RuntimeNeighbourInit(Dictionary<CPos, string[]> value)
|
||||
: base(value) { }
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
: base(info)
|
||||
{
|
||||
enabled = !info.RequiresLobbyCreeps || init.Self.World.WorldActor.Trait<MapCreeps>().Enabled;
|
||||
faction = init.GetValue<FactionInit, string>(info, init.Self.Owner.Faction.InternalName);
|
||||
faction = init.GetValue<FactionInit, string>(init.Self.Owner.Faction.InternalName);
|
||||
}
|
||||
|
||||
void INotifyKilled.Killed(Actor self, AttackInfo e)
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public ProduceActorPower(ActorInitializer init, ProduceActorPowerInfo info)
|
||||
: base(init.Self, info)
|
||||
{
|
||||
faction = init.GetValue<FactionInit, string>(info, init.Self.Owner.Faction.InternalName);
|
||||
faction = init.GetValue<FactionInit, string>(init.Self.Owner.Faction.InternalName);
|
||||
}
|
||||
|
||||
public override void SelectTarget(Actor self, string order, SupportPowerManager manager)
|
||||
|
||||
@@ -65,8 +65,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
var body = self.Trait<BodyOrientation>();
|
||||
|
||||
// TODO: Carry orientation over from the parent instead of just facing
|
||||
var dynamicFacingInit = init.GetOrDefault<DynamicFacingInit>(info);
|
||||
var bodyFacing = dynamicFacingInit != null ? dynamicFacingInit.Value() : init.GetValue<FacingInit, int>(info, 0);
|
||||
var dynamicFacingInit = init.GetOrDefault<DynamicFacingInit>();
|
||||
var bodyFacing = dynamicFacingInit != null ? dynamicFacingInit.Value() : init.GetValue<FacingInit, int>(0);
|
||||
facing = WAngle.FromFacing(Turreted.TurretFacingFromInit(init, info, 0)());
|
||||
|
||||
// Calculate final position
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public TransformCrusherOnCrush(ActorInitializer init, TransformCrusherOnCrushInfo info)
|
||||
{
|
||||
this.info = info;
|
||||
faction = init.GetValue<FactionInit, string>(info, init.Self.Owner.Faction.InternalName);
|
||||
faction = init.GetValue<FactionInit, string>(init.Self.Owner.Faction.InternalName);
|
||||
}
|
||||
|
||||
void INotifyCrushed.WarnCrush(Actor self, Actor crusher, BitSet<CrushClass> crushClasses) { }
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public TransformOnCapture(ActorInitializer init, TransformOnCaptureInfo info)
|
||||
{
|
||||
this.info = info;
|
||||
faction = init.GetValue<FactionInit, string>(info, init.Self.Owner.Faction.InternalName);
|
||||
faction = init.GetValue<FactionInit, string>(init.Self.Owner.Faction.InternalName);
|
||||
}
|
||||
|
||||
void INotifyCapture.OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner, BitSet<CaptureType> captureTypes)
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
self = init.Self;
|
||||
actorInfo = self.World.Map.Rules.Actors[info.IntoActor];
|
||||
buildingInfo = actorInfo.TraitInfoOrDefault<BuildingInfo>();
|
||||
faction = init.GetValue<FactionInit, string>(info, self.Owner.Faction.InternalName);
|
||||
faction = init.GetValue<FactionInit, string>(self.Owner.Faction.InternalName);
|
||||
}
|
||||
|
||||
public string VoicePhraseForOrder(Actor self, Order order)
|
||||
|
||||
@@ -106,12 +106,12 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (turret != null)
|
||||
{
|
||||
Func<int> getFacing;
|
||||
var dynamicTurretFacingsInit = init.GetOrDefault<DynamicTurretFacingsInit>(info);
|
||||
var dynamicTurretFacingsInit = init.GetOrDefault<DynamicTurretFacingsInit>();
|
||||
if (dynamicTurretFacingsInit != null && dynamicTurretFacingsInit.Value.TryGetValue(turret, out getFacing))
|
||||
return getFacing;
|
||||
|
||||
int facing;
|
||||
var turretFacingsInit = init.GetOrDefault<TurretFacingsInit>(info);
|
||||
var turretFacingsInit = init.GetOrDefault<TurretFacingsInit>();
|
||||
if (turretFacingsInit != null && turretFacingsInit.Value.TryGetValue(turret, out facing))
|
||||
return () => facing;
|
||||
}
|
||||
@@ -123,11 +123,11 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return () => facing;
|
||||
}
|
||||
|
||||
var dynamicFacingInit = init.GetOrDefault<DynamicFacingInit>(info);
|
||||
var dynamicFacingInit = init.GetOrDefault<DynamicFacingInit>();
|
||||
if (dynamicFacingInit != null)
|
||||
return dynamicFacingInit.Value;
|
||||
|
||||
var facingInit = init.GetOrDefault<FacingInit>(info);
|
||||
var facingInit = init.GetOrDefault<FacingInit>();
|
||||
if (facingInit != null)
|
||||
{
|
||||
var facing = facingInit.Value;
|
||||
@@ -245,7 +245,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
var facings = inits.GetOrDefault<DynamicTurretFacingsInit>();
|
||||
if (facings == null)
|
||||
{
|
||||
facings = new DynamicTurretFacingsInit(Info, new Dictionary<string, Func<int>>());
|
||||
facings = new DynamicTurretFacingsInit(new Dictionary<string, Func<int>>());
|
||||
inits.Add(facings);
|
||||
}
|
||||
|
||||
@@ -278,15 +278,15 @@ namespace OpenRA.Mods.Common.Traits
|
||||
: base(value) { }
|
||||
}
|
||||
|
||||
public class TurretFacingsInit : ValueActorInit<Dictionary<string, int>>
|
||||
public class TurretFacingsInit : ValueActorInit<Dictionary<string, int>>, ISingleInstanceInit
|
||||
{
|
||||
public TurretFacingsInit(Dictionary<string, int> value)
|
||||
: base(value) { }
|
||||
}
|
||||
|
||||
public class DynamicTurretFacingsInit : ValueActorInit<Dictionary<string, Func<int>>>
|
||||
public class DynamicTurretFacingsInit : ValueActorInit<Dictionary<string, Func<int>>>, ISingleInstanceInit
|
||||
{
|
||||
public DynamicTurretFacingsInit(TraitInfo info, Dictionary<string, Func<int>> value)
|
||||
: base(info, value) { }
|
||||
public DynamicTurretFacingsInit(Dictionary<string, Func<int>> value)
|
||||
: base(value) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
}
|
||||
|
||||
public class SkipMakeAnimsInit : RuntimeFlagInit { }
|
||||
public class SpawnedByMapInit : ValueActorInit<string>, ISuppressInitExport
|
||||
public class SpawnedByMapInit : ValueActorInit<string>, ISuppressInitExport, ISingleInstanceInit
|
||||
{
|
||||
public SpawnedByMapInit(string value)
|
||||
: base(value) { }
|
||||
|
||||
Reference in New Issue
Block a user