From 901e604cf3d0d118c98888f75a7aa90f1f0c6f23 Mon Sep 17 00:00:00 2001 From: RoosterDragon Date: Thu, 3 Sep 2015 20:09:16 +0100 Subject: [PATCH] Replace arrays with sets. In places where arrays were being treated as a set, just create a set directly. This reveals the intention of such collections better, and also improves performance by allowing set based methods to be used. --- OpenRA.Game/Traits/Player/FrozenActorLayer.cs | 4 ++-- OpenRA.Game/Traits/TraitsInterfaces.cs | 4 ++-- OpenRA.Mods.Common/AI/SupportPowerDecision.cs | 4 ++-- OpenRA.Mods.Common/Lint/CheckDeathTypes.cs | 4 ++-- OpenRA.Mods.Common/Orders/UnitOrderTargeter.cs | 4 ++-- OpenRA.Mods.Common/Traits/Buildings/BuildingUtils.cs | 2 +- OpenRA.Mods.Common/Traits/Buildings/LineBuildNode.cs | 3 ++- OpenRA.Mods.Common/Traits/Cloak.cs | 4 ++-- .../Traits/Crates/DuplicateUnitCrateAction.cs | 5 +++-- OpenRA.Mods.Common/Traits/Crushable.cs | 5 +++-- OpenRA.Mods.Common/Traits/DetectCloaked.cs | 4 ++-- OpenRA.Mods.Common/Traits/Explodes.cs | 2 +- OpenRA.Mods.Common/Traits/Render/WithDeathAnimation.cs | 2 +- OpenRA.Mods.Common/Traits/Sound/DeathSounds.cs | 2 +- OpenRA.Mods.Common/Traits/Targetable.cs | 6 +++--- OpenRA.Mods.Common/Warheads/DamageWarhead.cs | 2 +- OpenRA.Mods.RA/Traits/Buildings/ClonesProducedUnits.cs | 5 +++-- OpenRA.Mods.RA/Traits/Infiltration/Infiltrates.cs | 10 +++++----- OpenRA.Mods.RA/Traits/Mine.cs | 9 +++++---- 19 files changed, 43 insertions(+), 38 deletions(-) diff --git a/OpenRA.Game/Traits/Player/FrozenActorLayer.cs b/OpenRA.Game/Traits/Player/FrozenActorLayer.cs index a1c652889d..d921a86905 100644 --- a/OpenRA.Game/Traits/Player/FrozenActorLayer.cs +++ b/OpenRA.Game/Traits/Player/FrozenActorLayer.cs @@ -27,7 +27,7 @@ namespace OpenRA.Traits public readonly PPos[] Footprint; public readonly WPos CenterPosition; public readonly Rectangle Bounds; - public readonly string[] TargetTypes; + public readonly HashSet TargetTypes; readonly IRemoveFrozenActor[] removeFrozenActors; readonly Actor actor; readonly Shroud shroud; @@ -57,7 +57,7 @@ namespace OpenRA.Traits CenterPosition = self.CenterPosition; Bounds = self.Bounds; - TargetTypes = self.TraitsImplementing().Where(Exts.IsTraitEnabled).SelectMany(t => t.TargetTypes).Distinct().ToArray(); + TargetTypes = self.TraitsImplementing().Where(Exts.IsTraitEnabled).SelectMany(t => t.TargetTypes).ToHashSet(); UpdateVisibility(); } diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index bef29acbf8..6c615eeb62 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -310,13 +310,13 @@ namespace OpenRA.Traits public interface ITargetableInfo { - string[] GetTargetTypes(); + HashSet GetTargetTypes(); } public interface ITargetable { // Check IsTraitEnabled or !IsTraitDisabled first - string[] TargetTypes { get; } + HashSet TargetTypes { get; } bool TargetableBy(Actor self, Actor byActor); bool RequiresForceFire { get; } } diff --git a/OpenRA.Mods.Common/AI/SupportPowerDecision.cs b/OpenRA.Mods.Common/AI/SupportPowerDecision.cs index 13b0ad968c..454b14f26b 100644 --- a/OpenRA.Mods.Common/AI/SupportPowerDecision.cs +++ b/OpenRA.Mods.Common/AI/SupportPowerDecision.cs @@ -100,7 +100,7 @@ namespace OpenRA.Mods.Common.AI public readonly Stance Against = Stance.Enemy; [Desc("What types should the desired targets of this power be?")] - public readonly string[] Types = { "Air", "Ground", "Water" }; + public readonly HashSet Types = new HashSet { "Air", "Ground", "Water" }; [Desc("How attractive are these types of targets?")] public readonly int Attractiveness = 100; @@ -129,7 +129,7 @@ namespace OpenRA.Mods.Common.AI if (!targetable.Any(t => t.TargetableBy(a, firedBy.PlayerActor))) return 0; - if (Types.Intersect(targetable.SelectMany(t => t.TargetTypes)).Any()) + if (Types.Overlaps(targetable.SelectMany(t => t.TargetTypes))) { switch (TargetMetric) { diff --git a/OpenRA.Mods.Common/Lint/CheckDeathTypes.cs b/OpenRA.Mods.Common/Lint/CheckDeathTypes.cs index 2dde6ecbc1..c4144487f6 100644 --- a/OpenRA.Mods.Common/Lint/CheckDeathTypes.cs +++ b/OpenRA.Mods.Common/Lint/CheckDeathTypes.cs @@ -45,10 +45,10 @@ namespace OpenRA.Mods.Common.Lint continue; // This warhead cannot affect this actor. - if (!warhead.ValidTargets.Intersect(targetable).Any()) + if (!warhead.ValidTargets.Overlaps(targetable)) continue; - if (!warhead.DamageTypes.Intersect(deathTypes).Any()) + if (!warhead.DamageTypes.Overlaps(deathTypes)) emitError("Actor type `{0}` does not define a death animation for weapon `{1}`!" .F(actorInfo.Key, weaponInfo.Key)); } diff --git a/OpenRA.Mods.Common/Orders/UnitOrderTargeter.cs b/OpenRA.Mods.Common/Orders/UnitOrderTargeter.cs index 6e873260c1..863c9e54ba 100644 --- a/OpenRA.Mods.Common/Orders/UnitOrderTargeter.cs +++ b/OpenRA.Mods.Common/Orders/UnitOrderTargeter.cs @@ -77,12 +77,12 @@ namespace OpenRA.Mods.Common.Orders public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor) { - return target.TraitsImplementing().Any(t => t.IsTraitEnabled() && t.TargetTypes.Intersect(targetTypes).Any()); + return target.TraitsImplementing().Any(t => t.IsTraitEnabled() && t.TargetTypes.Overlaps(targetTypes)); } public override bool CanTargetFrozenActor(Actor self, FrozenActor target, TargetModifiers modifiers, ref string cursor) { - return target.TargetTypes.Intersect(targetTypes).Any(); + return target.TargetTypes.Overlaps(targetTypes); } } } diff --git a/OpenRA.Mods.Common/Traits/Buildings/BuildingUtils.cs b/OpenRA.Mods.Common/Traits/Buildings/BuildingUtils.cs index 90c7695c5a..77ce4cc319 100644 --- a/OpenRA.Mods.Common/Traits/Buildings/BuildingUtils.cs +++ b/OpenRA.Mods.Common/Traits/Buildings/BuildingUtils.cs @@ -75,7 +75,7 @@ namespace OpenRA.Mods.Common.Traits if (world.ActorsWithTrait().Any(a => (a.Actor.Location == cell && a.Actor.Info.Traits.Get() - .Types.Intersect(lbi.NodeTypes).Any()))) + .Types.Overlaps(lbi.NodeTypes)))) dirs[d] = i; // Cell contains actor of correct type else dirs[d] = -1; // Cell is blocked by another actor type diff --git a/OpenRA.Mods.Common/Traits/Buildings/LineBuildNode.cs b/OpenRA.Mods.Common/Traits/Buildings/LineBuildNode.cs index 90b3ca6402..5eceef6af2 100644 --- a/OpenRA.Mods.Common/Traits/Buildings/LineBuildNode.cs +++ b/OpenRA.Mods.Common/Traits/Buildings/LineBuildNode.cs @@ -8,6 +8,7 @@ */ #endregion +using System.Collections.Generic; using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits @@ -16,7 +17,7 @@ namespace OpenRA.Mods.Common.Traits public class LineBuildNodeInfo : TraitInfo { [Desc("This actor is of LineBuild 'NodeType'...")] - public readonly string[] Types = { "wall" }; + public readonly HashSet Types = new HashSet { "wall" }; } public class LineBuildNode { } diff --git a/OpenRA.Mods.Common/Traits/Cloak.cs b/OpenRA.Mods.Common/Traits/Cloak.cs index 95860b4ed6..84fa49ce63 100644 --- a/OpenRA.Mods.Common/Traits/Cloak.cs +++ b/OpenRA.Mods.Common/Traits/Cloak.cs @@ -36,7 +36,7 @@ namespace OpenRA.Mods.Common.Traits public readonly string UncloakSound = null; [PaletteReference] public readonly string Palette = "cloak"; - public readonly string[] CloakTypes = { "Cloak" }; + public readonly HashSet CloakTypes = new HashSet { "Cloak" }; [UpgradeGrantedReference] [Desc("The upgrades to grant to self while cloaked.")] @@ -150,7 +150,7 @@ namespace OpenRA.Mods.Common.Traits return true; return self.World.ActorsWithTrait().Any(a => !a.Trait.IsTraitDisabled && a.Actor.Owner.IsAlliedWith(viewer) - && Info.CloakTypes.Intersect(a.Trait.Info.CloakTypes).Any() + && Info.CloakTypes.Overlaps(a.Trait.Info.CloakTypes) && (self.CenterPosition - a.Actor.CenterPosition).Length <= WDist.FromCells(a.Trait.Info.Range).Length); } diff --git a/OpenRA.Mods.Common/Traits/Crates/DuplicateUnitCrateAction.cs b/OpenRA.Mods.Common/Traits/Crates/DuplicateUnitCrateAction.cs index f6a83327a6..5288b975ad 100644 --- a/OpenRA.Mods.Common/Traits/Crates/DuplicateUnitCrateAction.cs +++ b/OpenRA.Mods.Common/Traits/Crates/DuplicateUnitCrateAction.cs @@ -9,6 +9,7 @@ #endregion using System; +using System.Collections.Generic; using System.Linq; using OpenRA.Primitives; using OpenRA.Traits; @@ -31,7 +32,7 @@ namespace OpenRA.Mods.Common.Traits public readonly int MaxRadius = 4; [Desc("The list of unit target types we are allowed to duplicate.")] - public readonly string[] ValidTargets = { "Ground", "Water" }; + public readonly HashSet ValidTargets = new HashSet { "Ground", "Water" }; [Desc("Which factions this crate action can occur for.")] public readonly string[] ValidFactions = { }; @@ -58,7 +59,7 @@ namespace OpenRA.Mods.Common.Traits return false; var targetable = collector.TraitsImplementing(); - if (!info.ValidTargets.Intersect(targetable.SelectMany(t => t.TargetTypes)).Any()) + if (!info.ValidTargets.Overlaps(targetable.SelectMany(t => t.TargetTypes))) return false; var positionable = collector.TraitOrDefault(); diff --git a/OpenRA.Mods.Common/Traits/Crushable.cs b/OpenRA.Mods.Common/Traits/Crushable.cs index 44a5e84dc3..943601e22e 100644 --- a/OpenRA.Mods.Common/Traits/Crushable.cs +++ b/OpenRA.Mods.Common/Traits/Crushable.cs @@ -8,6 +8,7 @@ */ #endregion +using System.Collections.Generic; using System.Linq; using OpenRA.Traits; @@ -19,7 +20,7 @@ namespace OpenRA.Mods.Common.Traits [Desc("Sound to play when being crushed.")] public readonly string CrushSound = null; [Desc("Which crush classes does this actor belong to.")] - public readonly string[] CrushClasses = { "infantry" }; + public readonly HashSet CrushClasses = new HashSet { "infantry" }; [Desc("Probability of mobile actors noticing and evading a crush attempt.")] public readonly int WarnProbability = 75; [Desc("Will friendly units just crush me instead of pathing around.")] @@ -72,7 +73,7 @@ namespace OpenRA.Mods.Common.Traits if (!info.CrushedByFriendlies && crushOwner.IsAlliedWith(self.Owner)) return false; - return info.CrushClasses.Intersect(crushClasses).Any(); + return info.CrushClasses.Overlaps(crushClasses); } } } diff --git a/OpenRA.Mods.Common/Traits/DetectCloaked.cs b/OpenRA.Mods.Common/Traits/DetectCloaked.cs index 0c28a32ca7..df1f98737f 100644 --- a/OpenRA.Mods.Common/Traits/DetectCloaked.cs +++ b/OpenRA.Mods.Common/Traits/DetectCloaked.cs @@ -8,7 +8,7 @@ */ #endregion -using OpenRA.Traits; +using System.Collections.Generic; namespace OpenRA.Mods.Common.Traits { @@ -16,7 +16,7 @@ namespace OpenRA.Mods.Common.Traits public class DetectCloakedInfo : UpgradableTraitInfo { [Desc("Specific cloak classifications I can reveal.")] - public readonly string[] CloakTypes = { "Cloak" }; + public readonly HashSet CloakTypes = new HashSet { "Cloak" }; [Desc("Measured in cells.")] public readonly int Range = 5; diff --git a/OpenRA.Mods.Common/Traits/Explodes.cs b/OpenRA.Mods.Common/Traits/Explodes.cs index 27ccd5b9de..55371037e7 100644 --- a/OpenRA.Mods.Common/Traits/Explodes.cs +++ b/OpenRA.Mods.Common/Traits/Explodes.cs @@ -51,7 +51,7 @@ namespace OpenRA.Mods.Common.Traits return; var warhead = e.Warhead as DamageWarhead; - if (info.DeathType != null && warhead != null && !info.DeathType.Intersect(warhead.DamageTypes).Any()) + if (info.DeathType != null && warhead != null && !warhead.DamageTypes.Overlaps(info.DeathType)) return; var weaponName = ChooseWeaponForExplosion(self); diff --git a/OpenRA.Mods.Common/Traits/Render/WithDeathAnimation.cs b/OpenRA.Mods.Common/Traits/Render/WithDeathAnimation.cs index 3d9eca847e..3a928aca4a 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithDeathAnimation.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithDeathAnimation.cs @@ -80,7 +80,7 @@ namespace OpenRA.Mods.Common.Traits if (Info.UseDeathTypeSuffix) { var warhead = e.Warhead as DamageWarhead; - var damageType = warhead.DamageTypes.Intersect(Info.DeathTypes.Keys).FirstOrDefault(); + var damageType = Info.DeathTypes.Keys.FirstOrDefault(warhead.DamageTypes.Contains); if (damageType == null) return; diff --git a/OpenRA.Mods.Common/Traits/Sound/DeathSounds.cs b/OpenRA.Mods.Common/Traits/Sound/DeathSounds.cs index 49a70f50db..552d4efcd5 100644 --- a/OpenRA.Mods.Common/Traits/Sound/DeathSounds.cs +++ b/OpenRA.Mods.Common/Traits/Sound/DeathSounds.cs @@ -44,7 +44,7 @@ namespace OpenRA.Mods.Common.Traits if (warhead == null) return; - if (info.DeathTypes.Intersect(warhead.DamageTypes).Any()) + if (warhead.DamageTypes.Overlaps(info.DeathTypes)) self.PlayVoiceLocal(info.Voice, info.VolumeMultiplier); } } diff --git a/OpenRA.Mods.Common/Traits/Targetable.cs b/OpenRA.Mods.Common/Traits/Targetable.cs index c7323aa7c5..45cc822a09 100644 --- a/OpenRA.Mods.Common/Traits/Targetable.cs +++ b/OpenRA.Mods.Common/Traits/Targetable.cs @@ -17,8 +17,8 @@ namespace OpenRA.Mods.Common.Traits public class TargetableInfo : UpgradableTraitInfo, ITargetableInfo { [Desc("Target type. Used for filtering (in)valid targets.")] - public readonly string[] TargetTypes = { }; - public string[] GetTargetTypes() { return TargetTypes; } + public readonly HashSet TargetTypes = new HashSet(); + public HashSet GetTargetTypes() { return TargetTypes; } public bool RequiresForceFire = false; @@ -46,7 +46,7 @@ namespace OpenRA.Mods.Common.Traits return cloak.IsVisible(self, viewer.Owner); } - public virtual string[] TargetTypes { get { return Info.TargetTypes; } } + public virtual HashSet TargetTypes { get { return Info.TargetTypes; } } public bool RequiresForceFire { get { return Info.RequiresForceFire; } } } diff --git a/OpenRA.Mods.Common/Warheads/DamageWarhead.cs b/OpenRA.Mods.Common/Warheads/DamageWarhead.cs index a6eb4ea6e8..4624861606 100644 --- a/OpenRA.Mods.Common/Warheads/DamageWarhead.cs +++ b/OpenRA.Mods.Common/Warheads/DamageWarhead.cs @@ -21,7 +21,7 @@ namespace OpenRA.Mods.Common.Warheads public readonly int Damage = 0; [Desc("Types of damage that this warhead causes. Leave empty for no damage.")] - public readonly string[] DamageTypes = new string[0]; + public readonly HashSet DamageTypes = new HashSet(); [FieldLoader.LoadUsing("LoadVersus")] [Desc("Damage percentage versus each armortype.")] diff --git a/OpenRA.Mods.RA/Traits/Buildings/ClonesProducedUnits.cs b/OpenRA.Mods.RA/Traits/Buildings/ClonesProducedUnits.cs index 2d73adb8f5..75bf52f0be 100644 --- a/OpenRA.Mods.RA/Traits/Buildings/ClonesProducedUnits.cs +++ b/OpenRA.Mods.RA/Traits/Buildings/ClonesProducedUnits.cs @@ -8,6 +8,7 @@ */ #endregion +using System.Collections.Generic; using System.Linq; using OpenRA.Mods.Common.Traits; using OpenRA.Traits; @@ -19,7 +20,7 @@ namespace OpenRA.Mods.RA.Traits { [FieldLoader.Require] [Desc("Uses the \"Cloneable\" trait to determine whether or not we should clone a produced unit.")] - public readonly string[] CloneableTypes = { }; + public readonly HashSet CloneableTypes = new HashSet(); public object Create(ActorInitializer init) { return new ClonesProducedUnits(init, this); } } @@ -44,7 +45,7 @@ namespace OpenRA.Mods.RA.Traits return; var ci = produced.Info.Traits.GetOrDefault(); - if (ci == null || !info.CloneableTypes.Intersect(ci.Types).Any()) + if (ci == null || !info.CloneableTypes.Overlaps(ci.Types)) return; production.Produce(self, produced.Info, faction); diff --git a/OpenRA.Mods.RA/Traits/Infiltration/Infiltrates.cs b/OpenRA.Mods.RA/Traits/Infiltration/Infiltrates.cs index 656ad379ac..b2e04cc20a 100644 --- a/OpenRA.Mods.RA/Traits/Infiltration/Infiltrates.cs +++ b/OpenRA.Mods.RA/Traits/Infiltration/Infiltrates.cs @@ -20,7 +20,7 @@ namespace OpenRA.Mods.RA.Traits { class InfiltratesInfo : ITraitInfo { - public readonly string[] Types = { }; + public readonly HashSet Types = new HashSet(); [VoiceReference] public readonly string Voice = "Action"; @@ -80,7 +80,7 @@ namespace OpenRA.Mods.RA.Traits targetTypes = order.TargetActor.TraitsImplementing().Where(Exts.IsTraitEnabled) .SelectMany(t => t.TargetTypes); - return targetTypes.Intersect(Info.Types).Any(); + return Info.Types.Overlaps(targetTypes); } public string VoicePhraseForOrder(Actor self, Order order) @@ -96,7 +96,7 @@ namespace OpenRA.Mods.RA.Traits var target = self.ResolveFrozenActorOrder(order, Color.Red); if (target.Type != TargetType.Actor - || target.Actor.TraitsImplementing().SelectMany(t => t.TargetTypes).Intersect(Info.Types).Any()) + || Info.Types.Overlaps(target.Actor.TraitsImplementing().SelectMany(t => t.TargetTypes))) return; if (!order.Queued) @@ -124,7 +124,7 @@ namespace OpenRA.Mods.RA.Traits if (!info.ValidStances.HasStance(stance)) return false; - return target.TraitsImplementing().Any(t => t.TargetTypes.Intersect(info.Types).Any()); + return target.TraitsImplementing().Any(t => t.TargetTypes.Overlaps(info.Types)); } public override bool CanTargetFrozenActor(Actor self, FrozenActor target, TargetModifiers modifiers, ref string cursor) @@ -134,7 +134,7 @@ namespace OpenRA.Mods.RA.Traits if (!info.ValidStances.HasStance(stance)) return false; - return target.Info.Traits.WithInterface().Any(t => t.GetTargetTypes().Intersect(info.Types).Any()); + return target.Info.Traits.WithInterface().Any(t => info.Types.Overlaps(t.GetTargetTypes())); } } } diff --git a/OpenRA.Mods.RA/Traits/Mine.cs b/OpenRA.Mods.RA/Traits/Mine.cs index 6e27882fc0..294cba560a 100644 --- a/OpenRA.Mods.RA/Traits/Mine.cs +++ b/OpenRA.Mods.RA/Traits/Mine.cs @@ -8,6 +8,7 @@ */ #endregion +using System.Collections.Generic; using System.Linq; using OpenRA.Mods.Common.Traits; using OpenRA.Traits; @@ -16,9 +17,9 @@ namespace OpenRA.Mods.RA.Traits { class MineInfo : ITraitInfo { - public readonly string[] CrushClasses = { }; + public readonly HashSet CrushClasses = new HashSet(); public readonly bool AvoidFriendly = true; - public readonly string[] DetonateClasses = { }; + public readonly HashSet DetonateClasses = new HashSet(); public object Create(ActorInitializer init) { return new Mine(init, this); } } @@ -42,7 +43,7 @@ namespace OpenRA.Mods.RA.Traits return; var mobile = crusher.TraitOrDefault(); - if (mobile != null && !info.DetonateClasses.Intersect(mobile.Info.Crushes).Any()) + if (mobile != null && !info.DetonateClasses.Overlaps(mobile.Info.Crushes)) return; self.Kill(crusher); @@ -50,7 +51,7 @@ namespace OpenRA.Mods.RA.Traits public bool CrushableBy(string[] crushClasses, Player owner) { - return info.CrushClasses.Intersect(crushClasses).Any(); + return info.CrushClasses.Overlaps(crushClasses); } }