From 82bea961bac22962ff40a273b75b00830b2661fd Mon Sep 17 00:00:00 2001 From: RoosterDragon Date: Fri, 23 May 2014 19:52:44 +0100 Subject: [PATCH] Checked LINQ queries and collections for inefficiencies. - Made Array.IndexOf available via extension method. - Made ToHashSet extension method. - Change collections queried often via Contains into sets. - Avoid Count() extension if Count or Length property exist. - Made Count() > 0 checks and variations calls to Any() instead. - Don't call ToList/ToArray if there is no benefit to materializing the sequence. - If the sequence does benefit from materialization, follow this general pattern: - Collection queried often via Contains use ToHashSet to speed up lookups. - Short lived variables use ToList. This is because ToArray requires an extra copy to output the final size. - Collections persisted into fields or for a long time use ToArray to minimize memory overhead. --- OpenRA.Editor/Form1.cs | 2 +- OpenRA.Game/Effects/FlashTarget.cs | 7 +++-- OpenRA.Game/Exts.cs | 12 +++++++- OpenRA.Game/Graphics/PlayerColorRemap.cs | 4 +-- OpenRA.Game/Graphics/WorldRenderer.cs | 5 ++-- OpenRA.Game/Group.cs | 4 +-- OpenRA.Game/Map/MapCache.cs | 2 +- OpenRA.Game/Map/MapPreview.cs | 10 +++---- OpenRA.Game/Orders/UnitOrderGenerator.cs | 5 ++-- OpenRA.Game/Player.cs | 2 +- OpenRA.Game/Scripting/ScriptContext.cs | 6 ++-- OpenRA.Game/Selection.cs | 28 +++++++++++++------ OpenRA.Game/Server/Server.cs | 6 ++-- OpenRA.Game/Traits/Util.cs | 5 +--- OpenRA.Game/Widgets/PerfGraphWidget.cs | 4 +-- OpenRA.Game/Widgets/WidgetUtils.cs | 2 +- OpenRA.Game/World.cs | 10 ++++++- .../Lint/CheckTraitPrerequisites.cs | 4 +-- .../Orders/PlaceBuildingOrderGenerator.cs | 4 +-- .../SpriteLoaders/ShpTDLoader.cs | 6 ++-- OpenRA.Mods.Common/Traits/Cargo.cs | 15 +++++----- .../Traits/Crates/GiveUnitCrateAction.cs | 4 +-- .../Traits/EmitInfantryOnSell.cs | 2 +- .../Traits/World/DomainIndex.cs | 6 ++-- .../Traits/World/MPStartLocations.cs | 4 +-- .../Traits/World/SmudgeLayer.cs | 2 +- .../UtilityCommands/LegacyMapImporter.cs | 3 +- .../Widgets/Logic/Ingame/IngameChatLogic.cs | 4 +-- .../Widgets/Logic/Lobby/LobbyLogic.cs | 8 +++--- .../Widgets/Logic/Lobby/LobbyUtils.cs | 12 ++++++-- .../Widgets/Logic/MapChooserLogic.cs | 6 ++-- .../Widgets/Logic/ReplayBrowserLogic.cs | 6 ++-- .../Widgets/ProductionPaletteWidget.cs | 2 +- .../Widgets/ProductionTabsWidget.cs | 2 +- .../Traits/World/ChooseBuildTabOnSelect.cs | 4 +-- OpenRA.Mods.D2k/Widgets/BuildPaletteWidget.cs | 6 ++-- OpenRA.Mods.RA/AI/HackyAI.cs | 15 ++++------ OpenRA.Mods.RA/AI/States/GroundStates.cs | 11 ++++---- OpenRA.Mods.RA/AI/States/StateBase.cs | 4 +-- .../Traits/Attack/AttackGarrisoned.cs | 8 +++--- OpenRA.Mods.RA/Traits/Harvester.cs | 5 +--- .../Traits/SupportPowers/ChronoshiftPower.cs | 6 ++-- .../Widgets/Logic/InstallFromCDLogic.cs | 2 +- OpenRA.Mods.RA/Widgets/WorldCommandWidget.cs | 12 ++++---- 44 files changed, 151 insertions(+), 126 deletions(-) diff --git a/OpenRA.Editor/Form1.cs b/OpenRA.Editor/Form1.cs index bf17a6dfaa..9e63ef1bee 100644 --- a/OpenRA.Editor/Form1.cs +++ b/OpenRA.Editor/Form1.cs @@ -170,7 +170,7 @@ namespace OpenRA.Editor foreach (var p in palettes) { p.Visible = false; p.SuspendLayout(); } var templateOrder = tileset.EditorTemplateOrder ?? new string[] { }; - foreach (var tc in tileset.Templates.GroupBy(t => t.Value.Category).OrderBy(t => Array.IndexOf(templateOrder, t.Key))) + foreach (var tc in tileset.Templates.GroupBy(t => t.Value.Category).OrderBy(t => templateOrder.IndexOf(t.Key))) { var category = tc.Key ?? "(Uncategorized)"; var categoryHeader = new Label diff --git a/OpenRA.Game/Effects/FlashTarget.cs b/OpenRA.Game/Effects/FlashTarget.cs index 12e061937b..1d6c798c44 100755 --- a/OpenRA.Game/Effects/FlashTarget.cs +++ b/OpenRA.Game/Effects/FlashTarget.cs @@ -25,8 +25,11 @@ namespace OpenRA.Effects this.target = target; player = asPlayer; remainingTicks = ticks; - foreach (var e in target.World.Effects.OfType().Where(a => a.target == target).ToArray()) - target.World.Remove(e); + target.World.RemoveAll(effect => + { + var flashTarget = effect as FlashTarget; + return flashTarget != null && flashTarget.target == target; + }); } public void Tick(World world) diff --git a/OpenRA.Game/Exts.cs b/OpenRA.Game/Exts.cs index c1305dc8b6..8bcfa82638 100644 --- a/OpenRA.Game/Exts.cs +++ b/OpenRA.Game/Exts.cs @@ -106,6 +106,11 @@ namespace OpenRA return ret; } + public static int IndexOf(this T[] array, T value) + { + return Array.IndexOf(array, value); + } + public static T Random(this IEnumerable ts, MersenneTwister r) { var xs = ts as ICollection; @@ -299,6 +304,11 @@ namespace OpenRA return ts.Concat(moreTs); } + public static HashSet ToHashSet(this IEnumerable source) + { + return new HashSet(source); + } + public static Dictionary ToDictionaryWithConflictLog(this IEnumerable source, Func keySelector, string debugName, Func logKey, Func logValue) { return ToDictionaryWithConflictLog(source, keySelector, x => x, debugName, logKey, logValue); @@ -341,7 +351,7 @@ namespace OpenRA // If any duplicates were found, throw a descriptive error if (dupKeys.Count > 0) { - var badKeysFormatted = string.Join(", ", dupKeys.Select(p => "{0}: [{1}]".F(logKey(p.Key), string.Join(",", p.Value.ToArray()))).ToArray()); + var badKeysFormatted = string.Join(", ", dupKeys.Select(p => "{0}: [{1}]".F(logKey(p.Key), string.Join(",", p.Value)))); var msg = "{0}, duplicate values found for the following keys: {1}".F(debugName, badKeysFormatted); throw new ArgumentException(msg); } diff --git a/OpenRA.Game/Graphics/PlayerColorRemap.cs b/OpenRA.Game/Graphics/PlayerColorRemap.cs index 85af1c376f..362a5166f9 100755 --- a/OpenRA.Game/Graphics/PlayerColorRemap.cs +++ b/OpenRA.Game/Graphics/PlayerColorRemap.cs @@ -32,14 +32,14 @@ namespace OpenRA.Graphics var c1 = new HSLColor(c.H, c.S, (byte)Math.Max(rampRange, c.L)).RGB; var c2 = new HSLColor(c.H, c.S, (byte)Math.Max(0, c.L - rampRange)).RGB; var baseIndex = ramp[0]; - var remapRamp = ramp.Select(r => r - ramp[0]).ToArray(); + var remapRamp = ramp.Select(r => r - ramp[0]); // reversed remapping if (ramp[0] > ramp[15]) { baseIndex = ramp[15]; for (var i = 15; i > 0; i--) - remapRamp = ramp.Select(r => r - ramp[15]).ToArray(); + remapRamp = ramp.Select(r => r - ramp[15]); } remapColors = remapRamp.Select((x, i) => Pair.New(baseIndex + i, Exts.ColorLerp(x / 16f, c1, c2))) diff --git a/OpenRA.Game/Graphics/WorldRenderer.cs b/OpenRA.Game/Graphics/WorldRenderer.cs index 867ce36010..e79e551af9 100644 --- a/OpenRA.Game/Graphics/WorldRenderer.cs +++ b/OpenRA.Game/Graphics/WorldRenderer.cs @@ -80,12 +80,11 @@ namespace OpenRA.Graphics List GenerateRenderables() { var actors = World.ScreenMap.ActorsInBox(Viewport.TopLeft, Viewport.BottomRight) - .Append(World.WorldActor) - .ToList(); + .Append(World.WorldActor); // Include player actor for the rendered player if (World.RenderPlayer != null) - actors.Add(World.RenderPlayer.PlayerActor); + actors = actors.Append(World.RenderPlayer.PlayerActor); var worldRenderables = actors.SelectMany(a => a.Render(this)); if (World.OrderGenerator != null) diff --git a/OpenRA.Game/Group.cs b/OpenRA.Game/Group.cs index e6becf9b12..bda365b597 100644 --- a/OpenRA.Game/Group.cs +++ b/OpenRA.Game/Group.cs @@ -15,7 +15,7 @@ namespace OpenRA { public class Group { - List actors; + Actor[] actors; int id; static int nextGroup; @@ -24,7 +24,7 @@ namespace OpenRA public Group(IEnumerable actors) { - this.actors = actors.ToList(); + this.actors = actors.ToArray(); foreach (var a in actors) a.Group = this; diff --git a/OpenRA.Game/Map/MapCache.cs b/OpenRA.Game/Map/MapCache.cs index d1014bc7f0..81225afdef 100644 --- a/OpenRA.Game/Map/MapCache.cs +++ b/OpenRA.Game/Map/MapCache.cs @@ -79,7 +79,7 @@ namespace OpenRA foreach (var p in maps.Values) p.UpdateRemoteSearch(MapStatus.Searching, null); - var url = Game.Settings.Game.MapRepository + "hash/" + string.Join(",", maps.Keys.ToArray()) + "/yaml"; + var url = Game.Settings.Game.MapRepository + "hash/" + string.Join(",", maps.Keys) + "/yaml"; Action onInfoComplete = (i, cancelled) => { diff --git a/OpenRA.Game/Map/MapPreview.cs b/OpenRA.Game/Map/MapPreview.cs index 31724d4bed..482729eaf2 100644 --- a/OpenRA.Game/Map/MapPreview.cs +++ b/OpenRA.Game/Map/MapPreview.cs @@ -46,7 +46,7 @@ namespace OpenRA public class MapPreview { - static readonly List NoSpawns = new List(); + static readonly CPos[] NoSpawns = new CPos[] { }; MapCache cache; public readonly string Uid; @@ -54,7 +54,7 @@ namespace OpenRA public string Type { get; private set; } public string Author { get; private set; } public int PlayerCount { get; private set; } - public List SpawnPoints { get; private set; } + public CPos[] SpawnPoints { get; private set; } public Rectangle Bounds { get; private set; } public Bitmap CustomPreview { get; private set; } public Map Map { get; private set; } @@ -112,7 +112,7 @@ namespace OpenRA Author = m.Author; PlayerCount = m.Players.Count(x => x.Value.Playable); Bounds = m.Bounds; - SpawnPoints = m.GetSpawnPoints().ToList(); + SpawnPoints = m.GetSpawnPoints(); CustomPreview = m.CustomPreview; Status = MapStatus.Available; Class = classification; @@ -143,9 +143,9 @@ namespace OpenRA PlayerCount = r.players; Bounds = r.bounds; - var spawns = new List(); + var spawns = new CPos[r.spawnpoints.Length / 2]; for (var j = 0; j < r.spawnpoints.Length; j += 2) - spawns.Add(new CPos(r.spawnpoints[j], r.spawnpoints[j + 1])); + spawns[j / 2] = new CPos(r.spawnpoints[j], r.spawnpoints[j + 1]); SpawnPoints = spawns; CustomPreview = new Bitmap(new MemoryStream(Convert.FromBase64String(r.minimap))); diff --git a/OpenRA.Game/Orders/UnitOrderGenerator.cs b/OpenRA.Game/Orders/UnitOrderGenerator.cs index 19e79e5a67..ed9714530b 100644 --- a/OpenRA.Game/Orders/UnitOrderGenerator.cs +++ b/OpenRA.Game/Orders/UnitOrderGenerator.cs @@ -37,7 +37,7 @@ namespace OpenRA.Orders var orders = world.Selection.Actors .Select(a => OrderForUnit(a, target, mi)) .Where(o => o != null) - .ToArray(); + .ToList(); var actorsInvolved = orders.Select(o => o.Actor).Distinct(); if (actorsInvolved.Any()) @@ -81,8 +81,7 @@ namespace OpenRA.Orders var orders = world.Selection.Actors .Select(a => OrderForUnit(a, target, mi)) - .Where(o => o != null) - .ToArray(); + .Where(o => o != null); var cursorName = orders.Select(o => o.Cursor).FirstOrDefault(); return cursorName ?? (useSelect ? "select" : "default"); diff --git a/OpenRA.Game/Player.cs b/OpenRA.Game/Player.cs index 5bda08ac32..85c22df9d8 100644 --- a/OpenRA.Game/Player.cs +++ b/OpenRA.Game/Player.cs @@ -50,7 +50,7 @@ namespace OpenRA { var selectableCountries = world.Map.Rules.Actors["world"].Traits .WithInterface().Where(c => c.Selectable) - .ToArray(); + .ToList(); return selectableCountries.FirstOrDefault(c => c.Race == name) ?? selectableCountries.Random(world.SharedRandom); diff --git a/OpenRA.Game/Scripting/ScriptContext.cs b/OpenRA.Game/Scripting/ScriptContext.cs index 3578169695..499de38637 100644 --- a/OpenRA.Game/Scripting/ScriptContext.cs +++ b/OpenRA.Game/Scripting/ScriptContext.cs @@ -80,7 +80,7 @@ namespace OpenRA.Scripting // The 'this.' resolves the actual (subclass) type var type = this.GetType(); var names = type.GetCustomAttributes(true); - if (names.Count() != 1) + if (names.Length != 1) throw new InvalidOperationException("[LuaGlobal] attribute not found for global table '{0}'".F(type)); Name = names.First().Name; @@ -242,13 +242,13 @@ namespace OpenRA.Scripting runtime.Dispose(); } - static Type[] ExtractRequiredTypes(Type t) + static IEnumerable ExtractRequiredTypes(Type t) { // Returns the inner types of all the Requires interfaces on this type var outer = t.GetInterfaces() .Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(Requires<>)); - return outer.SelectMany(i => i.GetGenericArguments()).ToArray(); + return outer.SelectMany(i => i.GetGenericArguments()); } static readonly object[] NoArguments = new object[0]; diff --git a/OpenRA.Game/Selection.cs b/OpenRA.Game/Selection.cs index 6ecc508d4b..7e86b519f0 100644 --- a/OpenRA.Game/Selection.cs +++ b/OpenRA.Game/Selection.cs @@ -18,7 +18,7 @@ namespace OpenRA { public class Selection { - List actors = new List(); + readonly HashSet actors = new HashSet(); public void Add(World w, Actor a) { actors.Add(a); @@ -30,20 +30,32 @@ namespace OpenRA public bool Contains(Actor a) { - return actors.AsEnumerable().Contains(a); + return actors.Contains(a); } public void Combine(World world, IEnumerable newSelection, bool isCombine, bool isClick) { - var oldSelection = actors.AsEnumerable(); - if (isClick) { var adjNewSelection = newSelection.Take(1); /* TODO: select BEST, not FIRST */ - actors = (isCombine ? oldSelection.SymmetricDifference(adjNewSelection) : adjNewSelection).ToList(); + if (isCombine) + actors.SymmetricExceptWith(adjNewSelection); + else + { + actors.Clear(); + actors.UnionWith(adjNewSelection); + } } else - actors = (isCombine ? oldSelection.Union(newSelection) : newSelection).ToList(); + { + if (isCombine) + actors.UnionWith(newSelection); + else + { + actors.Clear(); + actors.UnionWith(newSelection); + } + } var voicedUnit = actors.FirstOrDefault(a => a.Owner == world.LocalPlayer && a.IsInWorld && a.HasVoices()); if (voicedUnit != null) @@ -57,11 +69,11 @@ namespace OpenRA } public IEnumerable Actors { get { return actors; } } - public void Clear() { actors = new List(); } + public void Clear() { actors.Clear(); } public void Tick(World world) { - actors.RemoveAll(a => !a.IsInWorld || (!a.Owner.IsAlliedWith(world.RenderPlayer) && world.FogObscures(a))); + actors.RemoveWhere(a => !a.IsInWorld || (!a.Owner.IsAlliedWith(world.RenderPlayer) && world.FogObscures(a))); foreach (var cg in controlGroups.Values) { diff --git a/OpenRA.Game/Server/Server.cs b/OpenRA.Game/Server/Server.cs index dc05542f10..7636943d8a 100644 --- a/OpenRA.Game/Server/Server.cs +++ b/OpenRA.Game/Server/Server.cs @@ -406,7 +406,7 @@ namespace OpenRA.Server public void DispatchOrdersToClients(Connection conn, int frame, byte[] data) { var from = conn != null ? conn.PlayerIndex : 0; - foreach (var c in Conns.Except(conn).ToArray()) + foreach (var c in Conns.Except(conn).ToList()) DispatchOrdersToClient(c, from, frame, data); } @@ -517,9 +517,7 @@ namespace OpenRA.Server public void DropClient(Connection toDrop, int frame) { - if (PreConns.Contains(toDrop)) - PreConns.Remove(toDrop); - else + if (!PreConns.Remove(toDrop)) { Conns.Remove(toDrop); diff --git a/OpenRA.Game/Traits/Util.cs b/OpenRA.Game/Traits/Util.cs index 0dd2b69f81..290bccae12 100644 --- a/OpenRA.Game/Traits/Util.cs +++ b/OpenRA.Game/Traits/Util.cs @@ -130,10 +130,7 @@ namespace OpenRA.Traits public static IEnumerable ExpandFootprint(IEnumerable cells, bool allowDiagonal) { - var result = new Dictionary(); - foreach (var c in cells.SelectMany(c => Neighbours(c, allowDiagonal))) - result[c] = true; - return result.Keys; + return cells.SelectMany(c => Neighbours(c, allowDiagonal)).Distinct(); } public static IEnumerable AdjacentCells(World w, Target target) diff --git a/OpenRA.Game/Widgets/PerfGraphWidget.cs b/OpenRA.Game/Widgets/PerfGraphWidget.cs index 035c115342..b96a87325f 100644 --- a/OpenRA.Game/Widgets/PerfGraphWidget.cs +++ b/OpenRA.Game/Widgets/PerfGraphWidget.cs @@ -26,7 +26,7 @@ namespace OpenRA.Widgets Game.Renderer.LineRenderer.DrawLine(origin + new float2(100, 0) * basis, origin + new float2(100, 100) * basis, Color.White, Color.White); var k = 0; - foreach (var item in PerfHistory.Items.Values.ToArray()) + foreach (var item in PerfHistory.Items.Values) { var n = 0; item.Samples().Aggregate((a, b) => @@ -55,7 +55,7 @@ namespace OpenRA.Widgets } k = 0; - foreach (var item in PerfHistory.Items.Values.ToArray()) + foreach (var item in PerfHistory.Items.Values) { Game.Renderer.Fonts["Tiny"].DrawText(item.Name, new float2(rect.Left, rect.Top) + new float2(18, 10 * k - 3), Color.White); ++k; diff --git a/OpenRA.Game/Widgets/WidgetUtils.cs b/OpenRA.Game/Widgets/WidgetUtils.cs index eb7775a021..106692c69f 100644 --- a/OpenRA.Game/Widgets/WidgetUtils.cs +++ b/OpenRA.Game/Widgets/WidgetUtils.cs @@ -75,7 +75,7 @@ namespace OpenRA.Widgets public static int[] GetBorderSizes(string collection) { var images = new[] { "border-t", "border-b", "border-l", "border-r" }; - var ss = images.Select(i => ChromeProvider.GetImage(collection, i)).ToArray(); + var ss = images.Select(i => ChromeProvider.GetImage(collection, i)).ToList(); return new[] { (int)ss[0].Size.Y, (int)ss[1].Size.Y, (int)ss[2].Size.X, (int)ss[3].Size.X }; } diff --git a/OpenRA.Game/World.cs b/OpenRA.Game/World.cs index 4b5b571b4e..8467ba2439 100644 --- a/OpenRA.Game/World.cs +++ b/OpenRA.Game/World.cs @@ -26,9 +26,16 @@ namespace OpenRA public class World { + class ActorIDComparer : IComparer + { + public static readonly ActorIDComparer Instance = new ActorIDComparer(); + private ActorIDComparer() { } + public int Compare(Actor x, Actor y) { return x.ActorID.CompareTo(y.ActorID); } + } + static readonly Func FalsePredicate = _ => false; internal readonly TraitDictionary TraitDict = new TraitDictionary(); - readonly HashSet actors = new HashSet(); + readonly SortedSet actors = new SortedSet(ActorIDComparer.Instance); readonly List effects = new List(); readonly Queue> frameEndActions = new Queue>(); @@ -237,6 +244,7 @@ namespace OpenRA public void Add(IEffect b) { effects.Add(b); } public void Remove(IEffect b) { effects.Remove(b); } + public void RemoveAll(Predicate predicate) { effects.RemoveAll(predicate); } public void AddFrameEndTask(Action a) { frameEndActions.Enqueue(a); } diff --git a/OpenRA.Mods.Common/Lint/CheckTraitPrerequisites.cs b/OpenRA.Mods.Common/Lint/CheckTraitPrerequisites.cs index 107594aeb6..28203d9414 100644 --- a/OpenRA.Mods.Common/Lint/CheckTraitPrerequisites.cs +++ b/OpenRA.Mods.Common/Lint/CheckTraitPrerequisites.cs @@ -21,8 +21,8 @@ namespace OpenRA.Mods.Common.Lint foreach (var actorInfo in map.Rules.Actors.Where(a => !a.Key.StartsWith("^"))) try { - var traits = actorInfo.Value.TraitsInConstructOrder().ToArray(); - if (traits.Length == 0) + var hasTraits = actorInfo.Value.TraitsInConstructOrder().Any(); + if (!hasTraits) emitWarning("Actor {0} has no traits. Is this intended?".F(actorInfo.Key)); } catch (Exception e) diff --git a/OpenRA.Mods.Common/Orders/PlaceBuildingOrderGenerator.cs b/OpenRA.Mods.Common/Orders/PlaceBuildingOrderGenerator.cs index ff32d9d52d..606a00accd 100644 --- a/OpenRA.Mods.Common/Orders/PlaceBuildingOrderGenerator.cs +++ b/OpenRA.Mods.Common/Orders/PlaceBuildingOrderGenerator.cs @@ -47,8 +47,8 @@ namespace OpenRA.Mods.Common.Orders if (mi.Button == MouseButton.Right) world.CancelInputMode(); - var ret = InnerOrder(world, xy, mi).ToList(); - if (ret.Count > 0) + var ret = InnerOrder(world, xy, mi).ToArray(); + if (ret.Length > 0) world.CancelInputMode(); return ret; diff --git a/OpenRA.Mods.Common/SpriteLoaders/ShpTDLoader.cs b/OpenRA.Mods.Common/SpriteLoaders/ShpTDLoader.cs index 671fb0ef6c..d050b574bf 100644 --- a/OpenRA.Mods.Common/SpriteLoaders/ShpTDLoader.cs +++ b/OpenRA.Mods.Common/SpriteLoaders/ShpTDLoader.cs @@ -203,14 +203,14 @@ namespace OpenRA.Mods.Common.SpriteLoaders public static void Write(Stream s, Size size, IEnumerable frames) { - var compressedFrames = frames.Select(f => Format80.Encode(f)).ToArray(); + var compressedFrames = frames.Select(f => Format80.Encode(f)).ToList(); // note: end-of-file and all-zeroes headers - var dataOffset = 14 + (compressedFrames.Length + 2) * 8; + var dataOffset = 14 + (compressedFrames.Count + 2) * 8; using (var bw = new BinaryWriter(s)) { - bw.Write((ushort)compressedFrames.Length); + bw.Write((ushort)compressedFrames.Count); bw.Write((ushort)0); bw.Write((ushort)0); bw.Write((ushort)size.Width); diff --git a/OpenRA.Mods.Common/Traits/Cargo.cs b/OpenRA.Mods.Common/Traits/Cargo.cs index 43aaca52d2..b48ed43340 100644 --- a/OpenRA.Mods.Common/Traits/Cargo.cs +++ b/OpenRA.Mods.Common/Traits/Cargo.cs @@ -37,7 +37,7 @@ namespace OpenRA.Mods.Common.Traits { public readonly CargoInfo Info; readonly Actor self; - readonly List cargo = new List(); + readonly Stack cargo = new Stack(); readonly HashSet reserves = new HashSet(); readonly Lazy facing; @@ -59,7 +59,7 @@ namespace OpenRA.Mods.Common.Traits if (init.Contains()) { - cargo = init.Get().ToList(); + cargo = new Stack(init.Get()); totalWeight = cargo.Sum(c => GetWeight(c)); } else if (init.Contains()) @@ -69,7 +69,7 @@ namespace OpenRA.Mods.Common.Traits var unit = self.World.CreateActor(false, u.ToLowerInvariant(), new TypeDictionary { new OwnerInit(self.Owner) }); - cargo.Add(unit); + cargo.Push(unit); } totalWeight = cargo.Sum(c => GetWeight(c)); @@ -81,7 +81,7 @@ namespace OpenRA.Mods.Common.Traits var unit = self.World.CreateActor(false, u.ToLowerInvariant(), new TypeDictionary { new OwnerInit(self.Owner) }); - cargo.Add(unit); + cargo.Push(unit); } totalWeight = cargo.Sum(c => GetWeight(c)); @@ -185,13 +185,12 @@ namespace OpenRA.Mods.Common.Traits public bool HasSpace(int weight) { return totalWeight + reservedWeight + weight <= Info.MaxWeight; } public bool IsEmpty(Actor self) { return cargo.Count == 0; } - public Actor Peek(Actor self) { return cargo[0]; } + public Actor Peek(Actor self) { return cargo.Peek(); } public Actor Unload(Actor self) { - var a = cargo[0]; + var a = cargo.Pop(); - cargo.RemoveAt(0); totalWeight -= GetWeight(a); SetPassengerFacing(a); @@ -248,7 +247,7 @@ namespace OpenRA.Mods.Common.Traits public void Load(Actor self, Actor a) { - cargo.Add(a); + cargo.Push(a); var w = GetWeight(a); totalWeight += w; if (reserves.Contains(a)) diff --git a/OpenRA.Mods.Common/Traits/Crates/GiveUnitCrateAction.cs b/OpenRA.Mods.Common/Traits/Crates/GiveUnitCrateAction.cs index 3c7a513f4a..cc1d8bed3d 100644 --- a/OpenRA.Mods.Common/Traits/Crates/GiveUnitCrateAction.cs +++ b/OpenRA.Mods.Common/Traits/Crates/GiveUnitCrateAction.cs @@ -103,8 +103,8 @@ namespace OpenRA.Mods.Common.Traits CPos? ChooseEmptyCellNear(Actor a, string unit) { - var possibleCells = GetSuitableCells(a.Location, unit).Where(c => !usedCells.Contains(c)).ToArray(); - if (possibleCells.Length == 0) + var possibleCells = GetSuitableCells(a.Location, unit).Where(c => !usedCells.Contains(c)).ToList(); + if (possibleCells.Count == 0) return null; return possibleCells.Random(self.World.SharedRandom); diff --git a/OpenRA.Mods.Common/Traits/EmitInfantryOnSell.cs b/OpenRA.Mods.Common/Traits/EmitInfantryOnSell.cs index a64be601ee..c59beef480 100644 --- a/OpenRA.Mods.Common/Traits/EmitInfantryOnSell.cs +++ b/OpenRA.Mods.Common/Traits/EmitInfantryOnSell.cs @@ -43,7 +43,7 @@ namespace OpenRA.Mods.Common.Traits dudesValue /= 100; var eligibleLocations = FootprintUtils.Tiles(self).ToList(); - var actorTypes = info.ActorTypes.Select(a => new { Name = a, Cost = self.World.Map.Rules.Actors[a].Traits.Get().Cost }).ToArray(); + var actorTypes = info.ActorTypes.Select(a => new { Name = a, Cost = self.World.Map.Rules.Actors[a].Traits.Get().Cost }).ToList(); while (eligibleLocations.Count > 0 && actorTypes.Any(a => a.Cost <= dudesValue)) { diff --git a/OpenRA.Mods.Common/Traits/World/DomainIndex.cs b/OpenRA.Mods.Common/Traits/World/DomainIndex.cs index fb7977b31d..b2db3f00ec 100644 --- a/OpenRA.Mods.Common/Traits/World/DomainIndex.cs +++ b/OpenRA.Mods.Common/Traits/World/DomainIndex.cs @@ -29,9 +29,9 @@ namespace OpenRA.Mods.Common.Traits public void WorldLoaded(World world, WorldRenderer wr) { domainIndexes = new Dictionary(); - var movementClasses = new HashSet( + var movementClasses = world.Map.Rules.Actors.Where(ai => ai.Value.Traits.Contains()) - .Select(ai => (uint)ai.Value.Traits.Get().GetMovementClass(world.TileSet))); + .Select(ai => (uint)ai.Value.Traits.Get().GetMovementClass(world.TileSet)).Distinct(); foreach (var mc in movementClasses) domainIndexes[mc] = new MovementClassDomainIndex(world, mc); @@ -45,7 +45,7 @@ namespace OpenRA.Mods.Common.Traits /// Regenerate the domain index for a group of cells public void UpdateCells(World world, IEnumerable cells) { - var dirty = new HashSet(cells); + var dirty = cells.ToHashSet(); foreach (var index in domainIndexes) index.Value.UpdateCells(world, dirty); } diff --git a/OpenRA.Mods.Common/Traits/World/MPStartLocations.cs b/OpenRA.Mods.Common/Traits/World/MPStartLocations.cs index 8bb25504ee..1f530cb5ed 100644 --- a/OpenRA.Mods.Common/Traits/World/MPStartLocations.cs +++ b/OpenRA.Mods.Common/Traits/World/MPStartLocations.cs @@ -28,7 +28,7 @@ namespace OpenRA.Mods.Common.Traits public void WorldLoaded(World world, WorldRenderer wr) { - var spawns = world.Map.GetSpawnPoints().ToList(); + var spawns = world.Map.GetSpawnPoints(); var taken = world.LobbyInfo.Clients.Where(c => c.SpawnPoint != 0 && c.Slot != null) .Select(c => spawns[c.SpawnPoint - 1]).ToList(); var available = spawns.Except(taken).ToList(); @@ -85,4 +85,4 @@ namespace OpenRA.Mods.Common.Traits return sp; } } -} \ No newline at end of file +} diff --git a/OpenRA.Mods.Common/Traits/World/SmudgeLayer.cs b/OpenRA.Mods.Common/Traits/World/SmudgeLayer.cs index 9cab465549..d26f5bdf4e 100644 --- a/OpenRA.Mods.Common/Traits/World/SmudgeLayer.cs +++ b/OpenRA.Mods.Common/Traits/World/SmudgeLayer.cs @@ -70,7 +70,7 @@ namespace OpenRA.Mods.Common.Traits } // Add map smudges - foreach (var s in w.Map.Smudges.Value.Where(s => smudges.Keys.Contains(s.Type))) + foreach (var s in w.Map.Smudges.Value.Where(s => smudges.ContainsKey(s.Type))) { var smudge = new Smudge { diff --git a/OpenRA.Mods.Common/UtilityCommands/LegacyMapImporter.cs b/OpenRA.Mods.Common/UtilityCommands/LegacyMapImporter.cs index 014c9c7ec0..214de8c0bb 100644 --- a/OpenRA.Mods.Common/UtilityCommands/LegacyMapImporter.cs +++ b/OpenRA.Mods.Common/UtilityCommands/LegacyMapImporter.cs @@ -187,8 +187,7 @@ namespace OpenRA.Mods.Common.UtilityCommands var wps = file.GetSection("Waypoints") .Where(kv => Exts.ParseIntegerInvariant(kv.Value) > 0) .Select(kv => Pair.New(Exts.ParseIntegerInvariant(kv.Key), - LocationFromMapOffset(Exts.ParseIntegerInvariant(kv.Value), mapSize))) - .ToArray(); + LocationFromMapOffset(Exts.ParseIntegerInvariant(kv.Value), mapSize))); // Add waypoint actors foreach (var kv in wps) diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameChatLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameChatLogic.cs index 4bc1aec5d3..54355ccebe 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameChatLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameChatLogic.cs @@ -31,7 +31,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic readonly ContainerWidget chatTemplate; readonly TextFieldWidget chatText; - readonly List chatTraits; + readonly INotifyChat[] chatTraits; readonly TabCompletionLogic tabCompletion = new TabCompletionLogic(); @@ -45,7 +45,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic this.orderManager = orderManager; this.modRules = modRules; - chatTraits = world.WorldActor.TraitsImplementing().ToList(); + chatTraits = world.WorldActor.TraitsImplementing().ToArray(); var players = world.Players.Where(p => p != world.LocalPlayer && !p.NonCombatant && !p.IsBot); disableTeamChat = world.LocalPlayer == null || world.LobbyInfo.IsSinglePlayer || !players.Any(p => p.IsAlliedWith(world.LocalPlayer)); diff --git a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs index 0607b62057..72f92d53bd 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs @@ -459,10 +459,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic var techLevel = optionsBin.GetOrNull("TECHLEVEL_DROPDOWNBUTTON"); if (techLevel != null) { - var techTraits = modRules.Actors["player"].Traits.WithInterface().ToArray(); - techLevel.IsVisible = () => techTraits.Length > 0; - optionsBin.GetOrNull("TECHLEVEL_DESC").IsVisible = () => techTraits.Length > 0; - techLevel.IsDisabled = () => Map.Status != MapStatus.Available || Map.Map.Options.TechLevel != null || configurationDisabled() || techTraits.Length <= 1; + var techTraits = modRules.Actors["player"].Traits.WithInterface().ToList(); + techLevel.IsVisible = () => techTraits.Count > 0; + optionsBin.GetOrNull("TECHLEVEL_DESC").IsVisible = () => techTraits.Count > 0; + techLevel.IsDisabled = () => Map.Status != MapStatus.Available || Map.Map.Options.TechLevel != null || configurationDisabled() || techTraits.Count <= 1; techLevel.GetText = () => Map.Status != MapStatus.Available || Map.Map.Options.TechLevel != null ? "Not Available" : "{0}".F(orderManager.LobbyInfo.GlobalSettings.TechLevel); techLevel.OnMouseDown = _ => { diff --git a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyUtils.cs b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyUtils.cs index b275c59f67..4b3dd4bf5a 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyUtils.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyUtils.cs @@ -156,7 +156,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic { var spawns = preview.SpawnPoints; return lobbyInfo.Clients - .Where(c => (c.SpawnPoint - 1 >= 0) && (c.SpawnPoint - 1 < spawns.Count)) + .Where(c => (c.SpawnPoint - 1 >= 0) && (c.SpawnPoint - 1 < spawns.Length)) .ToDictionary(c => spawns[c.SpawnPoint - 1], c => new SpawnOccupant(c)); } @@ -164,7 +164,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic { var spawns = preview.SpawnPoints; return players - .Where(c => (c.SpawnPoint - 1 >= 0) && (c.SpawnPoint - 1 < spawns.Count)) + .Where(c => (c.SpawnPoint - 1 >= 0) && (c.SpawnPoint - 1 < spawns.Length)) .ToDictionary(c => spawns[c.SpawnPoint - 1], c => new SpawnOccupant(c)); } @@ -430,7 +430,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic { var dropdown = parent.Get("SPAWN"); dropdown.IsDisabled = () => s.LockSpawn || orderManager.LocalClient.IsReady; - dropdown.OnMouseDown = _ => ShowSpawnDropDown(dropdown, c, orderManager, Enumerable.Range(0, map.SpawnPoints.Count + 1).Except(orderManager.LobbyInfo.Clients.Where(client => client != c && client.SpawnPoint != 0).Select(client => client.SpawnPoint))); + dropdown.OnMouseDown = _ => + { + var spawnPoints = Enumerable.Range(0, map.SpawnPoints.Length + 1).Except( + orderManager.LobbyInfo.Clients.Where( + client => client != c && client.SpawnPoint != 0).Select(client => client.SpawnPoint)); + ShowSpawnDropDown(dropdown, c, orderManager, spawnPoints); + }; dropdown.GetText = () => (c.SpawnPoint == 0) ? "-" : Convert.ToChar('A' - 1 + c.SpawnPoint).ToString(); } diff --git a/OpenRA.Mods.Common/Widgets/Logic/MapChooserLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/MapChooserLogic.cs index 81abaab183..770fe328dc 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/MapChooserLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/MapChooserLogic.cs @@ -21,7 +21,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic string selectedUid; // May be a subset of available maps if a mode filter is active - List visibleMaps; + string[] visibleMaps; ScrollPanelWidget scrollpanel; ScrollItemWidget itemTemplate; @@ -103,7 +103,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic selectedUid = uid; scrollpanel.ScrollToItem(uid, smooth: true); }; - randomMapButton.IsDisabled = () => visibleMaps == null || visibleMaps.Count == 0; + randomMapButton.IsDisabled = () => visibleMaps == null || visibleMaps.Length == 0; } EnumerateMaps(onSelect, filter); @@ -158,7 +158,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic scrollpanel.AddChild(item); } - visibleMaps = maps.Select(m => m.Uid).ToList(); + visibleMaps = maps.Select(m => m.Uid).ToArray(); if (visibleMaps.Contains(selectedUid)) scrollpanel.ScrollToItem(selectedUid); } diff --git a/OpenRA.Mods.Common/Widgets/Logic/ReplayBrowserLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/ReplayBrowserLogic.cs index 840c92b21b..0dfe2ee152 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/ReplayBrowserLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/ReplayBrowserLogic.cs @@ -203,7 +203,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic var ddb = panel.GetOrNull("FLT_MAPNAME_DROPDOWNBUTTON"); if (ddb != null) { - var options = new HashSet(replays.Select(r => r.GameInfo.MapTitle), StringComparer.OrdinalIgnoreCase).ToList(); + var options = replays.Select(r => r.GameInfo.MapTitle).Distinct(StringComparer.OrdinalIgnoreCase).ToList(); options.Sort(StringComparer.OrdinalIgnoreCase); options.Insert(0, null); // no filter @@ -231,7 +231,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic var ddb = panel.GetOrNull("FLT_PLAYER_DROPDOWNBUTTON"); if (ddb != null) { - var options = new HashSet(replays.SelectMany(r => r.GameInfo.Players.Select(p => p.Name)), StringComparer.OrdinalIgnoreCase).ToList(); + var options = replays.SelectMany(r => r.GameInfo.Players.Select(p => p.Name)).Distinct(StringComparer.OrdinalIgnoreCase).ToList(); options.Sort(StringComparer.OrdinalIgnoreCase); options.Insert(0, null); // no filter @@ -295,7 +295,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic { ddb.IsDisabled = () => string.IsNullOrEmpty(filter.PlayerName); - var options = new HashSet(replays.SelectMany(r => r.GameInfo.Players.Select(p => p.FactionName).Where(n => !string.IsNullOrEmpty(n))), StringComparer.OrdinalIgnoreCase).ToList(); + var options = replays.SelectMany(r => r.GameInfo.Players.Select(p => p.FactionName).Where(n => !string.IsNullOrEmpty(n))).Distinct(StringComparer.OrdinalIgnoreCase).ToList(); options.Sort(StringComparer.OrdinalIgnoreCase); options.Insert(0, null); // no filter diff --git a/OpenRA.Mods.Common/Widgets/ProductionPaletteWidget.cs b/OpenRA.Mods.Common/Widgets/ProductionPaletteWidget.cs index fe00a21a12..7ed4db3aab 100644 --- a/OpenRA.Mods.Common/Widgets/ProductionPaletteWidget.cs +++ b/OpenRA.Mods.Common/Widgets/ProductionPaletteWidget.cs @@ -281,7 +281,7 @@ namespace OpenRA.Mods.Common.Widgets Hotkey = ks.GetProductionHotkey(DisplayedIconCount), Sprite = icon.Image, Pos = new float2(rect.Location), - Queued = CurrentQueue.AllQueued().Where(a => a.Item == item.Name).ToList(), + Queued = CurrentQueue.AllQueued().Where(a => a.Item == item.Name).ToList() }; icons.Add(rect, pi); diff --git a/OpenRA.Mods.Common/Widgets/ProductionTabsWidget.cs b/OpenRA.Mods.Common/Widgets/ProductionTabsWidget.cs index 9e172d08c3..513577f42f 100644 --- a/OpenRA.Mods.Common/Widgets/ProductionTabsWidget.cs +++ b/OpenRA.Mods.Common/Widgets/ProductionTabsWidget.cs @@ -196,7 +196,7 @@ namespace OpenRA.Mods.Common.Widgets { var allQueues = a.World.ActorsWithTrait() .Where(p => p.Actor.Owner == p.Actor.World.LocalPlayer && p.Actor.IsInWorld && p.Trait.Enabled) - .Select(p => p.Trait).ToArray(); + .Select(p => p.Trait).ToList(); foreach (var g in Groups.Values) g.Update(allQueues); diff --git a/OpenRA.Mods.D2k/Traits/World/ChooseBuildTabOnSelect.cs b/OpenRA.Mods.D2k/Traits/World/ChooseBuildTabOnSelect.cs index 0e9474abe0..1cce0d7465 100644 --- a/OpenRA.Mods.D2k/Traits/World/ChooseBuildTabOnSelect.cs +++ b/OpenRA.Mods.D2k/Traits/World/ChooseBuildTabOnSelect.cs @@ -57,9 +57,9 @@ namespace OpenRA.Mods.D2k.Traits var types = world.Selection.Actors.Where(a => a.IsInWorld && (a.World.LocalPlayer == a.Owner)) .SelectMany(a => a.TraitsImplementing()) .SelectMany(t => t.Info.Produces) - .ToArray(); + .ToHashSet(); - if (types.Length == 0) + if (types.Count == 0) return; palette.SetCurrentTab(world.LocalPlayer.PlayerActor.TraitsImplementing() diff --git a/OpenRA.Mods.D2k/Widgets/BuildPaletteWidget.cs b/OpenRA.Mods.D2k/Widgets/BuildPaletteWidget.cs index 6060e4a67d..5a02b85f29 100644 --- a/OpenRA.Mods.D2k/Widgets/BuildPaletteWidget.cs +++ b/OpenRA.Mods.D2k/Widgets/BuildPaletteWidget.cs @@ -215,12 +215,12 @@ namespace OpenRA.Mods.D2k.Widgets if (queue != null) { - var buildableItems = queue.BuildableItems().ToArray(); - var allBuildables = queue.AllItems().OrderBy(a => a.Traits.Get().BuildPaletteOrder).ToArray(); + var buildableItems = queue.BuildableItems().ToList(); + var allBuildables = queue.AllItems().OrderBy(a => a.Traits.Get().BuildPaletteOrder).ToList(); var overlayBits = new List>(); var textBits = new List>(); - numActualRows = Math.Max((allBuildables.Count() + Columns - 1) / Columns, Rows); + numActualRows = Math.Max((allBuildables.Count + Columns - 1) / Columns, Rows); // Palette Background WidgetUtils.DrawRGBA(ChromeProvider.GetImage(paletteCollection, "top"), new float2(origin.X - 9, origin.Y - 9)); diff --git a/OpenRA.Mods.RA/AI/HackyAI.cs b/OpenRA.Mods.RA/AI/HackyAI.cs index fd5f4def44..a3c605ff2e 100644 --- a/OpenRA.Mods.RA/AI/HackyAI.cs +++ b/OpenRA.Mods.RA/AI/HackyAI.cs @@ -218,7 +218,7 @@ namespace OpenRA.Mods.RA.AI if (!buildableThings.Any()) return null; - var unit = buildableThings.ElementAtOrDefault(Random.Next(buildableThings.Count())); + var unit = buildableThings.Random(Random); return HasAdequateAirUnits(unit) ? unit : null; } @@ -231,11 +231,11 @@ namespace OpenRA.Mods.RA.AI var myUnits = Player.World .ActorsWithTrait() .Where(a => a.Actor.Owner == Player) - .Select(a => a.Actor.Info.Name).ToArray(); + .Select(a => a.Actor.Info.Name).ToList(); foreach (var unit in Info.UnitsToBuild.Shuffle(Random)) if (buildableThings.Any(b => b.Name == unit.Key)) - if (myUnits.Count(a => a == unit.Key) < unit.Value * myUnits.Length) + if (myUnits.Count(a => a == unit.Key) < unit.Value * myUnits.Count) if (HasAdequateAirUnits(Map.Rules.Actors[unit.Key])) return Map.Rules.Actors[unit.Key]; @@ -463,12 +463,9 @@ namespace OpenRA.Mods.RA.AI { var enemyUnits = World.FindActorsInCircle(pos, radius) .Where(unit => Player.Stances[unit.Owner] == Stance.Enemy && - !unit.HasTrait() && unit.HasTrait()).ToList(); + !unit.HasTrait() && unit.HasTrait()); - if (enemyUnits.Count > 0) - return enemyUnits.ClosestTo(pos); - - return null; + return enemyUnits.ClosestTo(pos); } List FindEnemyConstructionYards() @@ -645,7 +642,7 @@ namespace OpenRA.Mods.RA.AI { var ownUnits = World.FindActorsInCircle(World.Map.CenterOfCell(BaseCenter), WRange.FromCells(Info.ProtectUnitScanRadius)) .Where(unit => unit.Owner == Player && !unit.HasTrait() - && unit.HasTrait()).ToList(); + && unit.HasTrait()); foreach (var a in ownUnits) protectSq.Units.Add(a); diff --git a/OpenRA.Mods.RA/AI/States/GroundStates.cs b/OpenRA.Mods.RA/AI/States/GroundStates.cs index cccf88ebe9..3851679bf5 100644 --- a/OpenRA.Mods.RA/AI/States/GroundStates.cs +++ b/OpenRA.Mods.RA/AI/States/GroundStates.cs @@ -84,7 +84,7 @@ namespace OpenRA.Mods.RA.AI if (leader == null) return; var ownUnits = owner.World.FindActorsInCircle(leader.CenterPosition, WRange.FromCells(owner.Units.Count) / 3) - .Where(a => a.Owner == owner.Units.FirstOrDefault().Owner && owner.Units.Contains(a)).ToList(); + .Where(a => a.Owner == owner.Units.FirstOrDefault().Owner && owner.Units.Contains(a)).ToHashSet(); if (ownUnits.Count < owner.Units.Count) { owner.World.IssueOrder(new Order("Stop", leader, false)); @@ -94,11 +94,12 @@ namespace OpenRA.Mods.RA.AI else { var enemies = owner.World.FindActorsInCircle(leader.CenterPosition, WRange.FromCells(12)) - .Where(a1 => !a1.Destroyed && !a1.IsDead).ToList(); - var enemynearby = enemies.Where(a1 => a1.HasTrait() && leader.Owner.Stances[a1.Owner] == Stance.Enemy).ToList(); - if (enemynearby.Any()) + .Where(a1 => !a1.Destroyed && !a1.IsDead); + var enemynearby = enemies.Where(a1 => a1.HasTrait() && leader.Owner.Stances[a1.Owner] == Stance.Enemy); + var target = enemynearby.ClosestTo(leader.CenterPosition); + if (target != null) { - owner.TargetActor = enemynearby.ClosestTo(leader.CenterPosition); + owner.TargetActor = target; owner.FuzzyStateMachine.ChangeState(owner, new GroundUnitsAttackState(), true); return; } diff --git a/OpenRA.Mods.RA/AI/States/StateBase.cs b/OpenRA.Mods.RA/AI/States/StateBase.cs index 41764b47ed..8dca82bcc0 100644 --- a/OpenRA.Mods.RA/AI/States/StateBase.cs +++ b/OpenRA.Mods.RA/AI/States/StateBase.cs @@ -34,8 +34,8 @@ namespace OpenRA.Mods.RA.AI { var location = squad.Bot.BaseCenter; var buildings = squad.World.ActorsWithTrait() - .Where(a => a.Actor.Owner == squad.Bot.Player).Select(a => a.Actor).ToArray(); - if (buildings.Length > 0) + .Where(a => a.Actor.Owner == squad.Bot.Player).Select(a => a.Actor).ToList(); + if (buildings.Count > 0) location = buildings.Random(squad.Random).Location; return location; } diff --git a/OpenRA.Mods.RA/Traits/Attack/AttackGarrisoned.cs b/OpenRA.Mods.RA/Traits/Attack/AttackGarrisoned.cs index c9aee21c23..3387c17dac 100644 --- a/OpenRA.Mods.RA/Traits/Attack/AttackGarrisoned.cs +++ b/OpenRA.Mods.RA/Traits/Attack/AttackGarrisoned.cs @@ -95,9 +95,9 @@ namespace OpenRA.Mods.RA.Traits paxFacing.Add(passenger, passenger.Trait()); paxPos.Add(passenger, passenger.Trait()); paxRender.Add(passenger, passenger.Trait()); - armaments = armaments.Append(passenger.TraitsImplementing() - .Where(a => info.Armaments.Contains(a.Info.Name)) - .ToArray()).ToList(); + armaments.AddRange( + passenger.TraitsImplementing() + .Where(a => info.Armaments.Contains(a.Info.Name))); } public void PassengerExited(Actor self, Actor passenger) @@ -189,7 +189,7 @@ namespace OpenRA.Mods.RA.Traits base.Tick(self); // Take a copy so that Tick() can remove animations - foreach (var m in muzzles.ToList()) + foreach (var m in muzzles.ToArray()) m.Animation.Tick(); } } diff --git a/OpenRA.Mods.RA/Traits/Harvester.cs b/OpenRA.Mods.RA/Traits/Harvester.cs index 661cef75c6..9aa26f02e7 100644 --- a/OpenRA.Mods.RA/Traits/Harvester.cs +++ b/OpenRA.Mods.RA/Traits/Harvester.cs @@ -137,11 +137,8 @@ namespace OpenRA.Mods.RA.Traits return occupancy * 12; })); - // Reverse the found-path to find the refinery location instead of our location: - path.Reverse(); - if (path.Count != 0) - return refs[path[0]].Actor; + return refs[path.Last()].Actor; return null; } diff --git a/OpenRA.Mods.RA/Traits/SupportPowers/ChronoshiftPower.cs b/OpenRA.Mods.RA/Traits/SupportPowers/ChronoshiftPower.cs index 4baa8ea8ce..da1481c69d 100644 --- a/OpenRA.Mods.RA/Traits/SupportPowers/ChronoshiftPower.cs +++ b/OpenRA.Mods.RA/Traits/SupportPowers/ChronoshiftPower.cs @@ -57,11 +57,11 @@ namespace OpenRA.Mods.RA.Traits { var range = ((ChronoshiftPowerInfo)Info).Range; var tiles = Self.World.Map.FindTilesInCircle(xy, range); - var units = new List(); + var units = new HashSet(); foreach (var t in tiles) - units.AddRange(Self.World.ActorMap.GetUnitsAt(t)); + units.UnionWith(Self.World.ActorMap.GetUnitsAt(t)); - return units.Distinct().Where(a => a.HasTrait() && + return units.Where(a => a.HasTrait() && !a.TraitsImplementing().Any(condition => condition.PreventsTeleport(a))); } diff --git a/OpenRA.Mods.RA/Widgets/Logic/InstallFromCDLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/InstallFromCDLogic.cs index 687616ad97..a08370cdaa 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/InstallFromCDLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/InstallFromCDLogic.cs @@ -79,7 +79,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic var extractFiles = Game.ModData.Manifest.ContentInstaller.ExtractFilesFromCD; var installCounter = 0; - var installTotal = copyFiles.Count() + extractFiles.Count(); + var installTotal = copyFiles.Length + extractFiles.Length; var onProgress = (Action)(s => Game.RunAfterTick(() => { progressBar.Percentage = installCounter * 100 / installTotal; diff --git a/OpenRA.Mods.RA/Widgets/WorldCommandWidget.cs b/OpenRA.Mods.RA/Widgets/WorldCommandWidget.cs index e06be3bb0a..e200c7dfca 100644 --- a/OpenRA.Mods.RA/Widgets/WorldCommandWidget.cs +++ b/OpenRA.Mods.RA/Widgets/WorldCommandWidget.cs @@ -188,19 +188,19 @@ namespace OpenRA.Mods.RA.Widgets { var bases = world.ActorsWithTrait() .Where(a => a.Actor.Owner == world.LocalPlayer) - .ToArray(); + .Select(b => b.Actor) + .ToList(); if (!bases.Any()) return true; var next = bases - .Select(b => b.Actor) .SkipWhile(b => !world.Selection.Actors.Contains(b)) .Skip(1) .FirstOrDefault(); if (next == null) - next = bases.Select(b => b.Actor).First(); + next = bases.First(); world.Selection.Combine(world, new Actor[] { next }, false, true); @@ -212,19 +212,19 @@ namespace OpenRA.Mods.RA.Widgets var facilities = world.ActorsWithTrait() .Where(a => a.Actor.Owner == world.LocalPlayer && !a.Actor.HasTrait()) .OrderBy(f => f.Actor.Info.Traits.Get().Produces.First()) - .ToArray(); + .Select(b => b.Actor) + .ToList(); if (!facilities.Any()) return true; var next = facilities - .Select(b => b.Actor) .SkipWhile(b => !world.Selection.Actors.Contains(b)) .Skip(1) .FirstOrDefault(); if (next == null) - next = facilities.Select(b => b.Actor).First(); + next = facilities.First(); world.Selection.Combine(world, new Actor[] { next }, false, true);