diff --git a/OpenRA.Game/Graphics/WorldRenderer.cs b/OpenRA.Game/Graphics/WorldRenderer.cs index d39113a935..df7c68abc8 100644 --- a/OpenRA.Game/Graphics/WorldRenderer.cs +++ b/OpenRA.Game/Graphics/WorldRenderer.cs @@ -185,8 +185,7 @@ namespace OpenRA.Graphics if (World.Type == WorldType.Regular && Game.Settings.Game.AlwaysShowStatusBars) { - foreach (var g in World.Actors.Where(a => !a.Disposed - && a.Info.HasTraitInfo() + foreach (var g in World.ActorsHavingTrait().Where(a => !a.Disposed && !World.FogObscures(a) && !World.Selection.Actors.Contains(a))) diff --git a/OpenRA.Game/TraitDictionary.cs b/OpenRA.Game/TraitDictionary.cs index 3d6a9dbe30..b8fa17ef1b 100644 --- a/OpenRA.Game/TraitDictionary.cs +++ b/OpenRA.Game/TraitDictionary.cs @@ -107,6 +107,16 @@ namespace OpenRA return InnerGet().All(); } + public IEnumerable ActorsHavingTrait() + { + return InnerGet().Actors(); + } + + public IEnumerable ActorsHavingTrait(Func predicate) + { + return InnerGet().Actors(predicate); + } + public void RemoveActor(Actor a) { foreach (var t in traits) @@ -196,6 +206,33 @@ namespace OpenRA return new AllEnumerable(this); } + public IEnumerable Actors() + { + ++Queries; + Actor last = null; + for (var i = 0; i < actors.Count; i++) + { + if (actors[i] == last) + continue; + yield return actors[i]; + last = actors[i]; + } + } + + public IEnumerable Actors(Func predicate) + { + ++Queries; + Actor last = null; + + for (var i = 0; i < actors.Count; i++) + { + if (actors[i] == last || !predicate(traits[i])) + continue; + yield return actors[i]; + last = actors[i]; + } + } + class AllEnumerable : IEnumerable> { readonly TraitContainer container; diff --git a/OpenRA.Game/World.cs b/OpenRA.Game/World.cs index e848a8db52..f6f03ced2a 100644 --- a/OpenRA.Game/World.cs +++ b/OpenRA.Game/World.cs @@ -351,6 +351,16 @@ namespace OpenRA return TraitDict.ActorsWithTrait(); } + public IEnumerable ActorsHavingTrait() + { + return TraitDict.ActorsHavingTrait(); + } + + public IEnumerable ActorsHavingTrait(Func predicate) + { + return TraitDict.ActorsHavingTrait(predicate); + } + public void OnPlayerWinStateChanged(Player player) { var pi = gameInfo.GetPlayer(player); diff --git a/OpenRA.Mods.Common/AI/BaseBuilder.cs b/OpenRA.Mods.Common/AI/BaseBuilder.cs index 30e350ab38..babe172c87 100644 --- a/OpenRA.Mods.Common/AI/BaseBuilder.cs +++ b/OpenRA.Mods.Common/AI/BaseBuilder.cs @@ -59,13 +59,8 @@ namespace OpenRA.Mods.Common.AI // If failed to place something N consecutive times, wait M ticks until resuming building production if (failCount >= ai.Info.MaximumFailedPlacementAttempts && --failRetryTicks <= 0) { - var currentBuildings = world.ActorsWithTrait() - .Where(a => a.Actor.Owner == player) - .Count(); - - var baseProviders = world.ActorsWithTrait() - .Where(a => a.Actor.Owner == player) - .Count(); + var currentBuildings = world.ActorsHavingTrait().Count(a => a.Owner == player); + var baseProviders = world.ActorsHavingTrait().Count(a => a.Owner == player); // Only bother resetting failCount if either a) the number of buildings has decreased since last failure M ticks ago, // or b) number of BaseProviders (construction yard or similar) has increased since then. @@ -89,9 +84,7 @@ namespace OpenRA.Mods.Common.AI if (waterState == Water.NotEnoughWater && --checkForBasesTicks <= 0) { - var currentBases = world.ActorsWithTrait() - .Where(a => a.Actor.Owner == player) - .Count(); + var currentBases = world.ActorsHavingTrait().Count(a => a.Owner == player); if (currentBases > cachedBases) { @@ -104,10 +97,7 @@ namespace OpenRA.Mods.Common.AI if (--waitTicks > 0) return; - playerBuildings = world.ActorsWithTrait() - .Where(a => a.Actor.Owner == player) - .Select(a => a.Actor) - .ToArray(); + playerBuildings = world.ActorsHavingTrait().Where(a => a.Owner == player).ToArray(); var active = false; foreach (var queue in ai.FindQueues(category)) @@ -158,13 +148,8 @@ namespace OpenRA.Mods.Common.AI // If we just reached the maximum fail count, cache the number of current structures if (failCount == ai.Info.MaximumFailedPlacementAttempts) { - cachedBuildings = world.ActorsWithTrait() - .Where(a => a.Actor.Owner == player) - .Count(); - - cachedBases = world.ActorsWithTrait() - .Where(a => a.Actor.Owner == player) - .Count(); + cachedBuildings = world.ActorsHavingTrait().Count(a => a.Owner == player); + cachedBases = world.ActorsHavingTrait().Count(a => a.Owner == player); } } else diff --git a/OpenRA.Mods.Common/AI/HackyAI.cs b/OpenRA.Mods.Common/AI/HackyAI.cs index 5a7ace582e..02f85a49a5 100644 --- a/OpenRA.Mods.Common/AI/HackyAI.cs +++ b/OpenRA.Mods.Common/AI/HackyAI.cs @@ -171,10 +171,8 @@ namespace OpenRA.Mods.Common.AI public CPos GetRandomBaseCenter() { - var randomBaseBuilding = World.Actors.Where( - a => a.Owner == Player - && a.Info.HasTraitInfo() - && !a.Info.HasTraitInfo()) + var randomBaseBuilding = World.ActorsHavingTrait() + .Where(a => a.Owner == Player && !a.Info.HasTraitInfo()) .RandomOrDefault(Random); return randomBaseBuilding != null ? randomBaseBuilding.Location : initialBaseCenter; @@ -288,10 +286,8 @@ namespace OpenRA.Mods.Common.AI // TODO: Possibly give this a more generic name when terrain type is unhardcoded public bool EnoughWaterToBuildNaval() { - var baseProviders = World.Actors.Where( - a => a.Owner == Player - && a.Info.HasTraitInfo() - && !a.Info.HasTraitInfo()); + var baseProviders = World.ActorsHavingTrait() + .Where(a => a.Owner == Player && !a.Info.HasTraitInfo()); foreach (var b in baseProviders) { @@ -315,10 +311,8 @@ namespace OpenRA.Mods.Common.AI // Check whether we have at least one building providing buildable area close enough to water to build naval structures public bool CloseEnoughToWater() { - var areaProviders = World.Actors.Where( - a => a.Owner == Player - && a.Info.HasTraitInfo() - && !a.Info.HasTraitInfo()); + var areaProviders = World.ActorsHavingTrait() + .Where(a => a.Owner == Player && !a.Info.HasTraitInfo()); foreach (var a in areaProviders) { @@ -361,9 +355,9 @@ namespace OpenRA.Mods.Common.AI return null; var myUnits = Player.World - .ActorsWithTrait() - .Where(a => a.Actor.Owner == Player) - .Select(a => a.Actor.Info.Name).ToList(); + .ActorsHavingTrait() + .Where(a => a.Owner == Player) + .Select(a => a.Info.Name).ToList(); foreach (var unit in Info.UnitsToBuild.Shuffle(Random)) if (buildableThings.Any(b => b.Name == unit.Key)) @@ -376,14 +370,12 @@ namespace OpenRA.Mods.Common.AI int CountBuilding(string frac, Player owner) { - return World.ActorsWithTrait() - .Count(a => a.Actor.Owner == owner && a.Actor.Info.Name == frac); + return World.ActorsHavingTrait().Count(a => a.Owner == owner && a.Info.Name == frac); } int CountUnits(string unit, Player owner) { - return World.ActorsWithTrait() - .Count(a => a.Actor.Owner == owner && a.Actor.Info.Name == unit); + return World.ActorsHavingTrait().Count(a => a.Owner == owner && a.Info.Name == unit); } int? CountBuildingByCommonName(string commonName, Player owner) @@ -391,8 +383,8 @@ namespace OpenRA.Mods.Common.AI if (!Info.BuildingCommonNames.ContainsKey(commonName)) return null; - return World.ActorsWithTrait() - .Count(a => a.Actor.Owner == owner && Info.BuildingCommonNames[commonName].Contains(a.Actor.Info.Name)); + return World.ActorsHavingTrait() + .Count(a => a.Owner == owner && Info.BuildingCommonNames[commonName].Contains(a.Info.Name)); } public ActorInfo GetBuildingInfoByCommonName(string commonName, Player owner) @@ -498,7 +490,7 @@ namespace OpenRA.Mods.Common.AI case BuildingType.Defense: // Build near the closest enemy structure - var closestEnemy = World.Actors.Where(a => !a.Disposed && a.Info.HasTraitInfo() && Player.Stances[a.Owner] == Stance.Enemy) + var closestEnemy = World.ActorsHavingTrait().Where(a => !a.Disposed && Player.Stances[a.Owner] == Stance.Enemy) .ClosestTo(World.Map.CenterOfCell(defenseCenter)); var targetCell = closestEnemy != null ? closestEnemy.Location : baseCenter; @@ -573,8 +565,8 @@ namespace OpenRA.Mods.Common.AI leastLikedEnemies.Random(Random) : liveEnemies.FirstOrDefault(); // Pick something worth attacking owned by that player - var target = World.Actors - .Where(a => a.Owner == enemy && a.OccupiesSpace != null) + var target = World.ActorsHavingTrait() + .Where(a => a.Owner == enemy) .ClosestTo(World.Map.CenterOfCell(GetRandomBaseCenter())); if (target == null) @@ -605,8 +597,8 @@ namespace OpenRA.Mods.Common.AI List FindEnemyConstructionYards() { - return World.Actors.Where(a => Player.Stances[a.Owner] == Stance.Enemy && !a.IsDead - && a.Info.HasTraitInfo() && !a.Info.HasTraitInfo()).ToList(); + return World.ActorsHavingTrait() + .Where(a => Player.Stances[a.Owner] == Stance.Enemy && !a.IsDead && !a.Info.HasTraitInfo()).ToList(); } void CleanSquads() @@ -716,10 +708,8 @@ namespace OpenRA.Mods.Common.AI void FindNewUnits(Actor self) { - var newUnits = self.World.ActorsWithTrait() - .Where(a => a.Actor.Owner == Player && !a.Actor.Info.HasTraitInfo() - && !activeUnits.Contains(a.Actor)) - .Select(a => a.Actor); + var newUnits = self.World.ActorsHavingTrait() + .Where(a => a.Owner == Player && !a.Info.HasTraitInfo() && !activeUnits.Contains(a)); foreach (var a in newUnits) { @@ -843,8 +833,7 @@ namespace OpenRA.Mods.Common.AI void InitializeBase(Actor self) { // Find and deploy our mcv - var mcv = self.World.Actors - .FirstOrDefault(a => a.Owner == Player && a.Info.HasTraitInfo()); + var mcv = self.World.ActorsHavingTrait().FirstOrDefault(a => a.Owner == Player); if (mcv != null) { @@ -865,8 +854,8 @@ namespace OpenRA.Mods.Common.AI void FindAndDeployBackupMcv(Actor self) { // HACK: This needs to query against MCVs directly - var mcvs = self.World.Actors - .Where(a => a.Owner == Player && a.Info.HasTraitInfo() && a.Info.HasTraitInfo()); + var mcvs = self.World.ActorsHavingTrait() + .Where(a => a.Owner == Player && a.Info.HasTraitInfo()); foreach (var mcv in mcvs) { @@ -1023,8 +1012,8 @@ namespace OpenRA.Mods.Common.AI return; // No construction yards - Build a new MCV - if (!HasAdequateFact() && !self.World.Actors.Any(a => - a.Owner == Player && a.Info.HasTraitInfo() && a.Info.HasTraitInfo())) + if (!HasAdequateFact() && !self.World.ActorsHavingTrait() + .Any(a => a.Owner == Player && a.Info.HasTraitInfo())) BuildUnit("Vehicle", GetUnitInfoByCommonName("Mcv", Player).Name); foreach (var q in Info.UnitQueues) diff --git a/OpenRA.Mods.Common/AI/States/StateBase.cs b/OpenRA.Mods.Common/AI/States/StateBase.cs index d8c5143ec1..b63d0d0cde 100644 --- a/OpenRA.Mods.Common/AI/States/StateBase.cs +++ b/OpenRA.Mods.Common/AI/States/StateBase.cs @@ -31,8 +31,8 @@ namespace OpenRA.Mods.Common.AI protected static CPos RandomBuildingLocation(Squad squad) { var location = squad.Bot.GetRandomBaseCenter(); - var buildings = squad.World.ActorsWithTrait() - .Where(a => a.Actor.Owner == squad.Bot.Player).Select(a => a.Actor).ToList(); + var buildings = squad.World.ActorsHavingTrait() + .Where(a => a.Owner == squad.Bot.Player).ToList(); if (buildings.Count > 0) location = buildings.Random(squad.Random).Location; return location; diff --git a/OpenRA.Mods.Common/Activities/Air/HeliReturnToBase.cs b/OpenRA.Mods.Common/Activities/Air/HeliReturnToBase.cs index 7c9ee1a58a..be38ab6235 100644 --- a/OpenRA.Mods.Common/Activities/Air/HeliReturnToBase.cs +++ b/OpenRA.Mods.Common/Activities/Air/HeliReturnToBase.cs @@ -42,9 +42,8 @@ namespace OpenRA.Mods.Common.Activities if (dest == null) { var rearmBuildings = heli.Info.RearmBuildings; - var nearestHpad = self.World.ActorsWithTrait() - .Where(a => a.Actor.Owner == self.Owner && rearmBuildings.Contains(a.Actor.Info.Name)) - .Select(a => a.Actor) + var nearestHpad = self.World.ActorsHavingTrait() + .Where(a => a.Owner == self.Owner && rearmBuildings.Contains(a.Info.Name)) .ClosestTo(self); if (nearestHpad == null) diff --git a/OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs b/OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs index ff485f4549..6a9bb29656 100644 --- a/OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs +++ b/OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs @@ -34,11 +34,10 @@ namespace OpenRA.Mods.Common.Activities public static Actor ChooseAirfield(Actor self, bool unreservedOnly) { var rearmBuildings = self.Info.TraitInfo().RearmBuildings; - return self.World.ActorsWithTrait() - .Where(a => a.Actor.Owner == self.Owner) - .Where(a => rearmBuildings.Contains(a.Actor.Info.Name) - && (!unreservedOnly || !Reservable.IsReserved(a.Actor))) - .Select(a => a.Actor) + return self.World.ActorsHavingTrait() + .Where(a => a.Owner == self.Owner + && rearmBuildings.Contains(a.Info.Name) + && (!unreservedOnly || !Reservable.IsReserved(a))) .ClosestTo(self); } diff --git a/OpenRA.Mods.Common/Activities/Hunt.cs b/OpenRA.Mods.Common/Activities/Hunt.cs index 99859b53f9..d101a3ede1 100644 --- a/OpenRA.Mods.Common/Activities/Hunt.cs +++ b/OpenRA.Mods.Common/Activities/Hunt.cs @@ -23,7 +23,7 @@ namespace OpenRA.Mods.Common.Activities public Hunt(Actor self) { var attack = self.Trait(); - targets = self.World.ActorsWithTrait().Select(p => p.Actor).Where( + targets = self.World.ActorsHavingTrait().Where( a => self != a && !a.IsDead && a.IsInWorld && a.AppearsHostileTo(self) && IsTargetable(a, self) && attack.HasAnyValidWeapons(Target.FromActor(a))); } diff --git a/OpenRA.Mods.Common/PlayerExtensions.cs b/OpenRA.Mods.Common/PlayerExtensions.cs index 62299806c1..c17495f13c 100644 --- a/OpenRA.Mods.Common/PlayerExtensions.cs +++ b/OpenRA.Mods.Common/PlayerExtensions.cs @@ -17,11 +17,9 @@ namespace OpenRA.Mods.Common { public static bool HasNoRequiredUnits(this Player player) { - return !player.World.ActorsWithTrait().Any(p => - { - return p.Actor.Owner == player && - (player.World.LobbyInfo.GlobalSettings.ShortGame ? p.Trait.Info.RequiredForShortGame : p.Actor.IsInWorld); - }); + if (player.World.LobbyInfo.GlobalSettings.ShortGame) + return !player.World.ActorsHavingTrait(t => t.Info.RequiredForShortGame).Any(a => a.Owner == player); + return !player.World.ActorsHavingTrait().Any(a => a.Owner == player && a.IsInWorld); } } } \ No newline at end of file diff --git a/OpenRA.Mods.Common/Scripting/Properties/PlayerProperties.cs b/OpenRA.Mods.Common/Scripting/Properties/PlayerProperties.cs index f723aa0b6c..190b5b7e87 100644 --- a/OpenRA.Mods.Common/Scripting/Properties/PlayerProperties.cs +++ b/OpenRA.Mods.Common/Scripting/Properties/PlayerProperties.cs @@ -55,7 +55,7 @@ namespace OpenRA.Mods.Common.Scripting [Desc("Returns an array of actors representing all ground attack units of this player.")] public Actor[] GetGroundAttackers() { - return Player.World.ActorsWithTrait().Select(a => a.Actor) + return Player.World.ActorsHavingTrait() .Where(a => a.Owner == Player && !a.IsDead && a.IsInWorld && a.Info.HasTraitInfo()) .ToArray(); } diff --git a/OpenRA.Mods.Common/Traits/Air/ReturnOnIdle.cs b/OpenRA.Mods.Common/Traits/Air/ReturnOnIdle.cs index 64c8de885b..3c21d70ad3 100644 --- a/OpenRA.Mods.Common/Traits/Air/ReturnOnIdle.cs +++ b/OpenRA.Mods.Common/Traits/Air/ReturnOnIdle.cs @@ -36,14 +36,12 @@ namespace OpenRA.Mods.Common.Traits // nowhere to land, pick something friendly and circle over it. // i'd prefer something we own - var someBuilding = self.World.ActorsWithTrait() - .Select(a => a.Actor) + var someBuilding = self.World.ActorsHavingTrait() .FirstOrDefault(a => a.Owner == self.Owner); // failing that, something unlikely to shoot at us if (someBuilding == null) - someBuilding = self.World.ActorsWithTrait() - .Select(a => a.Actor) + someBuilding = self.World.ActorsHavingTrait() .FirstOrDefault(a => self.Owner.Stances[a.Owner] == Stance.Ally); if (someBuilding == null) diff --git a/OpenRA.Mods.Common/Traits/Buildings/BuildingUtils.cs b/OpenRA.Mods.Common/Traits/Buildings/BuildingUtils.cs index 2cb56e7ffa..80fd1af5c9 100644 --- a/OpenRA.Mods.Common/Traits/Buildings/BuildingUtils.cs +++ b/OpenRA.Mods.Common/Traits/Buildings/BuildingUtils.cs @@ -72,10 +72,9 @@ namespace OpenRA.Mods.Common.Traits continue; // Cell is empty; continue search // Cell contains an actor. Is it the type we want? - if (world.ActorsWithTrait().Any(a => - (a.Actor.Location == cell && - a.Actor.Info.TraitInfo() - .Types.Overlaps(lbi.NodeTypes)))) + if (world.ActorsHavingTrait() + .Any(a => a.Location == cell + && a.Info.TraitInfo().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/Crates/GiveMcvCrateAction.cs b/OpenRA.Mods.Common/Traits/Crates/GiveMcvCrateAction.cs index fc36ddacb2..aa5b399de8 100644 --- a/OpenRA.Mods.Common/Traits/Crates/GiveMcvCrateAction.cs +++ b/OpenRA.Mods.Common/Traits/Crates/GiveMcvCrateAction.cs @@ -36,8 +36,8 @@ namespace OpenRA.Mods.Common.Traits if (!CanGiveTo(collector)) return 0; - var hasBase = collector.World.ActorsWithTrait() - .Any(a => a.Actor.Owner == collector.Owner); + var hasBase = collector.World.ActorsHavingTrait() + .Any(a => a.Owner == collector.Owner); return hasBase ? info.SelectionShares : info.NoBaseSelectionShares; } diff --git a/OpenRA.Mods.Common/Traits/Harvester.cs b/OpenRA.Mods.Common/Traits/Harvester.cs index 72b7685982..6e6f407b6d 100644 --- a/OpenRA.Mods.Common/Traits/Harvester.cs +++ b/OpenRA.Mods.Common/Traits/Harvester.cs @@ -114,9 +114,8 @@ namespace OpenRA.Mods.Common.Traits if (proc == null) return; if (proc.Disposed) return; - var linkedHarvs = proc.World.ActorsWithTrait() - .Where(a => a.Trait.LinkedProc == proc) - .Select(a => Target.FromActor(a.Actor)) + var linkedHarvs = proc.World.ActorsHavingTrait(h => h.LinkedProc == proc) + .Select(a => Target.FromActor(a)) .ToList(); proc.SetTargetLines(linkedHarvs, Color.Gold); @@ -163,7 +162,7 @@ namespace OpenRA.Mods.Common.Traits .Select(r => new { Location = r.Actor.Location + r.Trait.DeliveryOffset, Actor = r.Actor, - Occupancy = self.World.ActorsWithTrait().Count(a => a.Trait.LinkedProc == r.Actor) }) + Occupancy = self.World.ActorsHavingTrait(h => h.LinkedProc == r.Actor).Count() }) .ToDictionary(r => r.Location); // Start a search from each refinery's delivery location: diff --git a/OpenRA.Mods.Common/Traits/Player/ClassicProductionQueue.cs b/OpenRA.Mods.Common/Traits/Player/ClassicProductionQueue.cs index 23b4c88073..15655c5248 100644 --- a/OpenRA.Mods.Common/Traits/Player/ClassicProductionQueue.cs +++ b/OpenRA.Mods.Common/Traits/Player/ClassicProductionQueue.cs @@ -133,10 +133,10 @@ namespace OpenRA.Mods.Common.Traits { var type = bi.BuildAtProductionType ?? info.Type; - var selfsameBuildingsCount = self.World.ActorsWithTrait() + var selfsameProductionsCount = self.World.ActorsWithTrait() .Count(p => p.Actor.Owner == self.Owner && p.Trait.Info.Produces.Contains(type)); - var speedModifier = selfsameBuildingsCount.Clamp(1, info.BuildTimeSpeedReduction.Length) - 1; + var speedModifier = selfsameProductionsCount.Clamp(1, info.BuildTimeSpeedReduction.Length) - 1; time = (time * info.BuildTimeSpeedReduction[speedModifier]) / 100; } diff --git a/OpenRA.Mods.Common/Traits/Player/ProductionQueue.cs b/OpenRA.Mods.Common/Traits/Player/ProductionQueue.cs index 9687a6fb8b..54926d79ca 100644 --- a/OpenRA.Mods.Common/Traits/Player/ProductionQueue.cs +++ b/OpenRA.Mods.Common/Traits/Player/ProductionQueue.cs @@ -266,7 +266,7 @@ namespace OpenRA.Mods.Common.Traits if (!developerMode.AllTech && bi.BuildLimit > 0) { var inQueue = queue.Count(pi => pi.Item == order.TargetString); - var owned = self.Owner.World.ActorsWithTrait().Count(a => a.Actor.Info.Name == order.TargetString && a.Actor.Owner == self.Owner); + var owned = self.Owner.World.ActorsHavingTrait().Count(a => a.Info.Name == order.TargetString && a.Owner == self.Owner); fromLimit = bi.BuildLimit - (inQueue + owned); if (fromLimit <= 0) diff --git a/OpenRA.Mods.Common/Traits/Player/StrategicVictoryConditions.cs b/OpenRA.Mods.Common/Traits/Player/StrategicVictoryConditions.cs index ffd123d7f8..45305c9908 100644 --- a/OpenRA.Mods.Common/Traits/Player/StrategicVictoryConditions.cs +++ b/OpenRA.Mods.Common/Traits/Player/StrategicVictoryConditions.cs @@ -56,13 +56,13 @@ namespace OpenRA.Mods.Common.Traits mo = self.Trait(); } - public IEnumerable> AllPoints + public IEnumerable AllPoints { - get { return player.World.ActorsWithTrait(); } + get { return player.World.ActorsHavingTrait(); } } public int Total { get { return AllPoints.Count(); } } - int Owned { get { return AllPoints.Count(a => WorldUtils.AreMutualAllies(player, a.Actor.Owner)); } } + int Owned { get { return AllPoints.Count(a => WorldUtils.AreMutualAllies(player, a.Owner)); } } public bool Holding { get { return Owned >= info.RatioRequired * Total; } } diff --git a/OpenRA.Mods.Common/Traits/Power/Player/PowerManager.cs b/OpenRA.Mods.Common/Traits/Power/Player/PowerManager.cs index b4d4e7fb51..3bac6cf4bc 100644 --- a/OpenRA.Mods.Common/Traits/Power/Player/PowerManager.cs +++ b/OpenRA.Mods.Common/Traits/Power/Player/PowerManager.cs @@ -138,8 +138,7 @@ namespace OpenRA.Mods.Common.Traits void UpdatePowerOutageActors() { - var actors = self.World.ActorsWithTrait() - .Select(tp => tp.Actor) + var actors = self.World.ActorsHavingTrait() .Where(a => !a.IsDead && a.IsInWorld && a.Owner == self.Owner); foreach (var a in actors) diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameRadarDisplayLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameRadarDisplayLogic.cs index 20d89addac..f402e0d885 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameRadarDisplayLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameRadarDisplayLogic.cs @@ -31,8 +31,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic var ticker = widget.Get("RADAR_TICKER"); ticker.OnTick = () => { - radarEnabled = devMode.DisableShroud || world.ActorsWithTrait() - .Any(a => a.Actor.Owner == world.LocalPlayer && a.Trait.IsActive); + radarEnabled = devMode.DisableShroud || world.ActorsHavingTrait(r => r.IsActive) + .Any(a => a.Owner == world.LocalPlayer); if (radarEnabled != cachedRadarEnabled) Game.Sound.PlayNotification(world.Map.Rules, null, "Sounds", radarEnabled ? "RadarUp" : "RadarDown", null); diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/ObserverStatsLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/ObserverStatsLogic.cs index 9b7f6e02f8..b0996e4f3f 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/ObserverStatsLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/ObserverStatsLogic.cs @@ -240,12 +240,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic template.Get("SPENT").GetText = () => "$" + res.Spent; var assets = template.Get("ASSETS"); - assets.GetText = () => "$" + world.Actors - .Where(a => a.Owner == player && !a.IsDead && a.Info.HasTraitInfo()) + assets.GetText = () => "$" + world.ActorsHavingTrait() + .Where(a => a.Owner == player && !a.IsDead) .Sum(a => a.Info.TraitInfos().First().Cost); var harvesters = template.Get("HARVESTERS"); - harvesters.GetText = () => world.Actors.Count(a => a.Owner == player && !a.IsDead && a.Info.HasTraitInfo()).ToString(); + harvesters.GetText = () => world.ActorsHavingTrait().Count(a => a.Owner == player && !a.IsDead).ToString(); return template; } @@ -280,7 +280,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic { return ScrollItemWidget.Setup(template, () => false, () => { - var playerBase = world.Actors.FirstOrDefault(a => !a.IsDead && a.Info.HasTraitInfo() && a.Owner == player); + var playerBase = world.ActorsHavingTrait().FirstOrDefault(a => !a.IsDead && a.Owner == player); if (playerBase != null) worldRenderer.Viewport.Center(playerBase.CenterPosition); }); diff --git a/OpenRA.Mods.Common/Widgets/StrategicProgressWidget.cs b/OpenRA.Mods.Common/Widgets/StrategicProgressWidget.cs index 2f60452728..602da6322e 100644 --- a/OpenRA.Mods.Common/Widgets/StrategicProgressWidget.cs +++ b/OpenRA.Mods.Common/Widgets/StrategicProgressWidget.cs @@ -47,9 +47,9 @@ namespace OpenRA.Mods.Common.Widgets { WidgetUtils.DrawRGBA(ChromeProvider.GetImage("strategic", "critical_unowned"), offset + new float2(rb.Left + curX, rb.Top)); - if (world.LocalPlayer != null && WorldUtils.AreMutualAllies(a.Actor.Owner, world.LocalPlayer)) + if (world.LocalPlayer != null && WorldUtils.AreMutualAllies(a.Owner, world.LocalPlayer)) WidgetUtils.DrawRGBA(ChromeProvider.GetImage("strategic", "player_owned"), offset + new float2(rb.Left + curX, rb.Top)); - else if (!a.Actor.Owner.NonCombatant) + else if (!a.Owner.NonCombatant) WidgetUtils.DrawRGBA(ChromeProvider.GetImage("strategic", "enemy_owned"), offset + new float2(rb.Left + curX, rb.Top)); curX += 32; @@ -96,8 +96,8 @@ namespace OpenRA.Mods.Common.Widgets void Init() { - var visible = world.ActorsWithTrait().Any() && - world.ActorsWithTrait().Any(); + var visible = world.ActorsHavingTrait().Any() && + world.ActorsHavingTrait().Any(); IsVisible = () => visible; initialised = true; diff --git a/OpenRA.Mods.Common/Widgets/WorldCommandWidget.cs b/OpenRA.Mods.Common/Widgets/WorldCommandWidget.cs index 3f3af3ccf0..10c96d78f9 100644 --- a/OpenRA.Mods.Common/Widgets/WorldCommandWidget.cs +++ b/OpenRA.Mods.Common/Widgets/WorldCommandWidget.cs @@ -193,16 +193,14 @@ namespace OpenRA.Mods.Common.Widgets { var player = world.RenderPlayer ?? world.LocalPlayer; - var bases = world.ActorsWithTrait() - .Where(a => a.Actor.Owner == player) - .Select(b => b.Actor) + var bases = world.ActorsHavingTrait() + .Where(a => a.Owner == player) .ToList(); // If no BaseBuilding exist pick the first selectable Building. if (!bases.Any()) { - var building = world.ActorsWithTrait() - .Select(b => b.Actor) + var building = world.ActorsHavingTrait() .FirstOrDefault(a => a.Owner == player && a.Info.HasTraitInfo()); // No buildings left @@ -230,10 +228,9 @@ namespace OpenRA.Mods.Common.Widgets { var player = world.RenderPlayer ?? world.LocalPlayer; - var facilities = world.ActorsWithTrait() - .Where(a => a.Actor.Owner == player && !a.Actor.Info.HasTraitInfo()) - .OrderBy(f => f.Actor.Info.TraitInfo().Produces.First()) - .Select(b => b.Actor) + var facilities = world.ActorsHavingTrait() + .Where(a => a.Owner == player && !a.Info.HasTraitInfo()) + .OrderBy(f => f.Info.TraitInfo().Produces.First()) .ToList(); if (!facilities.Any()) diff --git a/OpenRA.Mods.D2k/Traits/Carryable.cs b/OpenRA.Mods.D2k/Traits/Carryable.cs index e484a3e928..4dd906ef44 100644 --- a/OpenRA.Mods.D2k/Traits/Carryable.cs +++ b/OpenRA.Mods.D2k/Traits/Carryable.cs @@ -100,9 +100,8 @@ namespace OpenRA.Mods.D2k.Traits public Actor GetClosestIdleCarrier() { // Find carriers - var carriers = self.World.ActorsWithTrait() - .Where(p => p.Actor.Owner == self.Owner && !p.Trait.IsBusy && p.Actor.IsInWorld) - .Select(h => h.Actor); + var carriers = self.World.ActorsHavingTrait(c => !c.IsBusy) + .Where(a => a.Owner == self.Owner && a.IsInWorld); return carriers.ClosestTo(self); } diff --git a/OpenRA.Mods.D2k/Traits/Player/HarvesterInsurance.cs b/OpenRA.Mods.D2k/Traits/Player/HarvesterInsurance.cs index fc947c7b03..d48535efc0 100644 --- a/OpenRA.Mods.D2k/Traits/Player/HarvesterInsurance.cs +++ b/OpenRA.Mods.D2k/Traits/Player/HarvesterInsurance.cs @@ -31,15 +31,15 @@ namespace OpenRA.Mods.D2k.Traits public void TryActivate() { - var harvesters = self.World.ActorsWithTrait().Where(x => x.Actor.Owner == self.Owner); + var harvesters = self.World.ActorsHavingTrait().Where(x => x.Owner == self.Owner); if (harvesters.Any()) return; - var refineries = self.World.ActorsWithTrait().Where(x => x.Actor.Owner == self.Owner); + var refineries = self.World.ActorsHavingTrait().Where(x => x.Owner == self.Owner); if (!refineries.Any()) return; - var refinery = refineries.First().Actor; + var refinery = refineries.First(); var delivery = refinery.Trait(); delivery.DoDelivery(refinery.Location + delivery.Info.DeliveryOffset, delivery.Info.Actor, delivery.Info.DeliveringActor); diff --git a/OpenRA.Mods.D2k/Traits/World/WormManager.cs b/OpenRA.Mods.D2k/Traits/World/WormManager.cs index 2df88515f4..78e8410257 100644 --- a/OpenRA.Mods.D2k/Traits/World/WormManager.cs +++ b/OpenRA.Mods.D2k/Traits/World/WormManager.cs @@ -48,7 +48,7 @@ namespace OpenRA.Mods.D2k.Traits public WormManager(Actor self, WormManagerInfo info) { this.info = info; - spawnPointActors = Exts.Lazy(() => self.World.ActorsWithTrait().Select(x => x.Actor).ToArray()); + spawnPointActors = Exts.Lazy(() => self.World.ActorsHavingTrait().ToArray()); } public void Tick(Actor self) diff --git a/OpenRA.Mods.RA/Traits/SupportPowers/GpsPower.cs b/OpenRA.Mods.RA/Traits/SupportPowers/GpsPower.cs index 25512c8c18..e8612a11dc 100644 --- a/OpenRA.Mods.RA/Traits/SupportPowers/GpsPower.cs +++ b/OpenRA.Mods.RA/Traits/SupportPowers/GpsPower.cs @@ -70,7 +70,7 @@ namespace OpenRA.Mods.RA.Traits void RefreshGranted() { Granted = actors.Count > 0 && Launched; - GrantedAllies = Owner.World.ActorsWithTrait().Any(p => p.Actor.Owner.IsAlliedWith(Owner) && p.Trait.Granted); + GrantedAllies = Owner.World.ActorsHavingTrait(g => g.Granted).Any(p => p.Owner.IsAlliedWith(Owner)); if (Granted || GrantedAllies) Owner.Shroud.ExploreAll(Owner.World);