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:
Paul Chote
2020-05-30 16:48:35 +01:00
committed by reaperrr
parent 86305879cb
commit b856613194
45 changed files with 169 additions and 95 deletions

View File

@@ -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);

View File

@@ -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;

View File

@@ -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()

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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)

View File

@@ -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++)
{

View File

@@ -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)

View File

@@ -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) { }

View File

@@ -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()

View File

@@ -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

View File

@@ -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) { }

View File

@@ -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(() =>
{

View File

@@ -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>();

View File

@@ -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) { }

View File

@@ -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>();

View File

@@ -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);
}

View File

@@ -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) { }
}

View File

@@ -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)

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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; }

View File

@@ -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) { }

View File

@@ -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)

View File

@@ -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)

View File

@@ -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 { }
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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) { }

View File

@@ -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)

View File

@@ -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)

View File

@@ -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 ?

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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) { }

View File

@@ -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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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) { }

View File

@@ -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)

View File

@@ -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)

View File

@@ -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) { }
}
}

View File

@@ -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) { }