Merge pull request #7231 from RoosterDragon/linq-checks

Checked LINQ queries and collections for inefficiencies.
This commit is contained in:
Matthias Mailänder
2015-02-01 08:56:15 +01:00
44 changed files with 151 additions and 126 deletions

View File

@@ -170,7 +170,7 @@ namespace OpenRA.Editor
foreach (var p in palettes) { p.Visible = false; p.SuspendLayout(); } foreach (var p in palettes) { p.Visible = false; p.SuspendLayout(); }
var templateOrder = tileset.EditorTemplateOrder ?? new string[] { }; 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 category = tc.Key ?? "(Uncategorized)";
var categoryHeader = new Label var categoryHeader = new Label

View File

@@ -25,8 +25,11 @@ namespace OpenRA.Effects
this.target = target; this.target = target;
player = asPlayer; player = asPlayer;
remainingTicks = ticks; remainingTicks = ticks;
foreach (var e in target.World.Effects.OfType<FlashTarget>().Where(a => a.target == target).ToArray()) target.World.RemoveAll(effect =>
target.World.Remove(e); {
var flashTarget = effect as FlashTarget;
return flashTarget != null && flashTarget.target == target;
});
} }
public void Tick(World world) public void Tick(World world)

View File

@@ -106,6 +106,11 @@ namespace OpenRA
return ret; return ret;
} }
public static int IndexOf<T>(this T[] array, T value)
{
return Array.IndexOf(array, value);
}
public static T Random<T>(this IEnumerable<T> ts, MersenneTwister r) public static T Random<T>(this IEnumerable<T> ts, MersenneTwister r)
{ {
var xs = ts as ICollection<T>; var xs = ts as ICollection<T>;
@@ -299,6 +304,11 @@ namespace OpenRA
return ts.Concat(moreTs); return ts.Concat(moreTs);
} }
public static HashSet<T> ToHashSet<T>(this IEnumerable<T> source)
{
return new HashSet<T>(source);
}
public static Dictionary<TKey, TSource> ToDictionaryWithConflictLog<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, string debugName, Func<TKey, string> logKey, Func<TSource, string> logValue) public static Dictionary<TKey, TSource> ToDictionaryWithConflictLog<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, string debugName, Func<TKey, string> logKey, Func<TSource, string> logValue)
{ {
return ToDictionaryWithConflictLog(source, keySelector, x => x, debugName, logKey, 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 any duplicates were found, throw a descriptive error
if (dupKeys.Count > 0) 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); var msg = "{0}, duplicate values found for the following keys: {1}".F(debugName, badKeysFormatted);
throw new ArgumentException(msg); throw new ArgumentException(msg);
} }

View File

@@ -32,14 +32,14 @@ namespace OpenRA.Graphics
var c1 = new HSLColor(c.H, c.S, (byte)Math.Max(rampRange, c.L)).RGB; 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 c2 = new HSLColor(c.H, c.S, (byte)Math.Max(0, c.L - rampRange)).RGB;
var baseIndex = ramp[0]; var baseIndex = ramp[0];
var remapRamp = ramp.Select(r => r - ramp[0]).ToArray(); var remapRamp = ramp.Select(r => r - ramp[0]);
// reversed remapping // reversed remapping
if (ramp[0] > ramp[15]) if (ramp[0] > ramp[15])
{ {
baseIndex = ramp[15]; baseIndex = ramp[15];
for (var i = 15; i > 0; i--) 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))) remapColors = remapRamp.Select((x, i) => Pair.New(baseIndex + i, Exts.ColorLerp(x / 16f, c1, c2)))

View File

@@ -80,12 +80,11 @@ namespace OpenRA.Graphics
List<IRenderable> GenerateRenderables() List<IRenderable> GenerateRenderables()
{ {
var actors = World.ScreenMap.ActorsInBox(Viewport.TopLeft, Viewport.BottomRight) var actors = World.ScreenMap.ActorsInBox(Viewport.TopLeft, Viewport.BottomRight)
.Append(World.WorldActor) .Append(World.WorldActor);
.ToList();
// Include player actor for the rendered player // Include player actor for the rendered player
if (World.RenderPlayer != null) if (World.RenderPlayer != null)
actors.Add(World.RenderPlayer.PlayerActor); actors = actors.Append(World.RenderPlayer.PlayerActor);
var worldRenderables = actors.SelectMany(a => a.Render(this)); var worldRenderables = actors.SelectMany(a => a.Render(this));
if (World.OrderGenerator != null) if (World.OrderGenerator != null)

View File

@@ -15,7 +15,7 @@ namespace OpenRA
{ {
public class Group public class Group
{ {
List<Actor> actors; Actor[] actors;
int id; int id;
static int nextGroup; static int nextGroup;
@@ -24,7 +24,7 @@ namespace OpenRA
public Group(IEnumerable<Actor> actors) public Group(IEnumerable<Actor> actors)
{ {
this.actors = actors.ToList(); this.actors = actors.ToArray();
foreach (var a in actors) foreach (var a in actors)
a.Group = this; a.Group = this;

View File

@@ -79,7 +79,7 @@ namespace OpenRA
foreach (var p in maps.Values) foreach (var p in maps.Values)
p.UpdateRemoteSearch(MapStatus.Searching, null); 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<DownloadDataCompletedEventArgs, bool> onInfoComplete = (i, cancelled) => Action<DownloadDataCompletedEventArgs, bool> onInfoComplete = (i, cancelled) =>
{ {

View File

@@ -46,7 +46,7 @@ namespace OpenRA
public class MapPreview public class MapPreview
{ {
static readonly List<CPos> NoSpawns = new List<CPos>(); static readonly CPos[] NoSpawns = new CPos[] { };
MapCache cache; MapCache cache;
public readonly string Uid; public readonly string Uid;
@@ -54,7 +54,7 @@ namespace OpenRA
public string Type { get; private set; } public string Type { get; private set; }
public string Author { get; private set; } public string Author { get; private set; }
public int PlayerCount { get; private set; } public int PlayerCount { get; private set; }
public List<CPos> SpawnPoints { get; private set; } public CPos[] SpawnPoints { get; private set; }
public Rectangle Bounds { get; private set; } public Rectangle Bounds { get; private set; }
public Bitmap CustomPreview { get; private set; } public Bitmap CustomPreview { get; private set; }
public Map Map { get; private set; } public Map Map { get; private set; }
@@ -112,7 +112,7 @@ namespace OpenRA
Author = m.Author; Author = m.Author;
PlayerCount = m.Players.Count(x => x.Value.Playable); PlayerCount = m.Players.Count(x => x.Value.Playable);
Bounds = m.Bounds; Bounds = m.Bounds;
SpawnPoints = m.GetSpawnPoints().ToList(); SpawnPoints = m.GetSpawnPoints();
CustomPreview = m.CustomPreview; CustomPreview = m.CustomPreview;
Status = MapStatus.Available; Status = MapStatus.Available;
Class = classification; Class = classification;
@@ -143,9 +143,9 @@ namespace OpenRA
PlayerCount = r.players; PlayerCount = r.players;
Bounds = r.bounds; Bounds = r.bounds;
var spawns = new List<CPos>(); var spawns = new CPos[r.spawnpoints.Length / 2];
for (var j = 0; j < r.spawnpoints.Length; j += 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; SpawnPoints = spawns;
CustomPreview = new Bitmap(new MemoryStream(Convert.FromBase64String(r.minimap))); CustomPreview = new Bitmap(new MemoryStream(Convert.FromBase64String(r.minimap)));

View File

@@ -37,7 +37,7 @@ namespace OpenRA.Orders
var orders = world.Selection.Actors var orders = world.Selection.Actors
.Select(a => OrderForUnit(a, target, mi)) .Select(a => OrderForUnit(a, target, mi))
.Where(o => o != null) .Where(o => o != null)
.ToArray(); .ToList();
var actorsInvolved = orders.Select(o => o.Actor).Distinct(); var actorsInvolved = orders.Select(o => o.Actor).Distinct();
if (actorsInvolved.Any()) if (actorsInvolved.Any())
@@ -81,8 +81,7 @@ namespace OpenRA.Orders
var orders = world.Selection.Actors var orders = world.Selection.Actors
.Select(a => OrderForUnit(a, target, mi)) .Select(a => OrderForUnit(a, target, mi))
.Where(o => o != null) .Where(o => o != null);
.ToArray();
var cursorName = orders.Select(o => o.Cursor).FirstOrDefault(); var cursorName = orders.Select(o => o.Cursor).FirstOrDefault();
return cursorName ?? (useSelect ? "select" : "default"); return cursorName ?? (useSelect ? "select" : "default");

View File

@@ -50,7 +50,7 @@ namespace OpenRA
{ {
var selectableCountries = world.Map.Rules.Actors["world"].Traits var selectableCountries = world.Map.Rules.Actors["world"].Traits
.WithInterface<CountryInfo>().Where(c => c.Selectable) .WithInterface<CountryInfo>().Where(c => c.Selectable)
.ToArray(); .ToList();
return selectableCountries.FirstOrDefault(c => c.Race == name) return selectableCountries.FirstOrDefault(c => c.Race == name)
?? selectableCountries.Random(world.SharedRandom); ?? selectableCountries.Random(world.SharedRandom);

View File

@@ -80,7 +80,7 @@ namespace OpenRA.Scripting
// The 'this.' resolves the actual (subclass) type // The 'this.' resolves the actual (subclass) type
var type = this.GetType(); var type = this.GetType();
var names = type.GetCustomAttributes<ScriptGlobalAttribute>(true); var names = type.GetCustomAttributes<ScriptGlobalAttribute>(true);
if (names.Count() != 1) if (names.Length != 1)
throw new InvalidOperationException("[LuaGlobal] attribute not found for global table '{0}'".F(type)); throw new InvalidOperationException("[LuaGlobal] attribute not found for global table '{0}'".F(type));
Name = names.First().Name; Name = names.First().Name;
@@ -242,13 +242,13 @@ namespace OpenRA.Scripting
runtime.Dispose(); runtime.Dispose();
} }
static Type[] ExtractRequiredTypes(Type t) static IEnumerable<Type> ExtractRequiredTypes(Type t)
{ {
// Returns the inner types of all the Requires<T> interfaces on this type // Returns the inner types of all the Requires<T> interfaces on this type
var outer = t.GetInterfaces() var outer = t.GetInterfaces()
.Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(Requires<>)); .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]; static readonly object[] NoArguments = new object[0];

View File

@@ -18,7 +18,7 @@ namespace OpenRA
{ {
public class Selection public class Selection
{ {
List<Actor> actors = new List<Actor>(); readonly HashSet<Actor> actors = new HashSet<Actor>();
public void Add(World w, Actor a) public void Add(World w, Actor a)
{ {
actors.Add(a); actors.Add(a);
@@ -30,20 +30,32 @@ namespace OpenRA
public bool Contains(Actor a) public bool Contains(Actor a)
{ {
return actors.AsEnumerable().Contains(a); return actors.Contains(a);
} }
public void Combine(World world, IEnumerable<Actor> newSelection, bool isCombine, bool isClick) public void Combine(World world, IEnumerable<Actor> newSelection, bool isCombine, bool isClick)
{ {
var oldSelection = actors.AsEnumerable();
if (isClick) if (isClick)
{ {
var adjNewSelection = newSelection.Take(1); /* TODO: select BEST, not FIRST */ 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 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()); var voicedUnit = actors.FirstOrDefault(a => a.Owner == world.LocalPlayer && a.IsInWorld && a.HasVoices());
if (voicedUnit != null) if (voicedUnit != null)
@@ -57,11 +69,11 @@ namespace OpenRA
} }
public IEnumerable<Actor> Actors { get { return actors; } } public IEnumerable<Actor> Actors { get { return actors; } }
public void Clear() { actors = new List<Actor>(); } public void Clear() { actors.Clear(); }
public void Tick(World world) 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) foreach (var cg in controlGroups.Values)
{ {

View File

@@ -406,7 +406,7 @@ namespace OpenRA.Server
public void DispatchOrdersToClients(Connection conn, int frame, byte[] data) public void DispatchOrdersToClients(Connection conn, int frame, byte[] data)
{ {
var from = conn != null ? conn.PlayerIndex : 0; 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); DispatchOrdersToClient(c, from, frame, data);
} }
@@ -517,9 +517,7 @@ namespace OpenRA.Server
public void DropClient(Connection toDrop, int frame) public void DropClient(Connection toDrop, int frame)
{ {
if (PreConns.Contains(toDrop)) if (!PreConns.Remove(toDrop))
PreConns.Remove(toDrop);
else
{ {
Conns.Remove(toDrop); Conns.Remove(toDrop);

View File

@@ -130,10 +130,7 @@ namespace OpenRA.Traits
public static IEnumerable<CPos> ExpandFootprint(IEnumerable<CPos> cells, bool allowDiagonal) public static IEnumerable<CPos> ExpandFootprint(IEnumerable<CPos> cells, bool allowDiagonal)
{ {
var result = new Dictionary<CPos, bool>(); return cells.SelectMany(c => Neighbours(c, allowDiagonal)).Distinct();
foreach (var c in cells.SelectMany(c => Neighbours(c, allowDiagonal)))
result[c] = true;
return result.Keys;
} }
public static IEnumerable<CPos> AdjacentCells(World w, Target target) public static IEnumerable<CPos> AdjacentCells(World w, Target target)

View File

@@ -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); Game.Renderer.LineRenderer.DrawLine(origin + new float2(100, 0) * basis, origin + new float2(100, 100) * basis, Color.White, Color.White);
var k = 0; var k = 0;
foreach (var item in PerfHistory.Items.Values.ToArray()) foreach (var item in PerfHistory.Items.Values)
{ {
var n = 0; var n = 0;
item.Samples().Aggregate((a, b) => item.Samples().Aggregate((a, b) =>
@@ -55,7 +55,7 @@ namespace OpenRA.Widgets
} }
k = 0; 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); Game.Renderer.Fonts["Tiny"].DrawText(item.Name, new float2(rect.Left, rect.Top) + new float2(18, 10 * k - 3), Color.White);
++k; ++k;

View File

@@ -75,7 +75,7 @@ namespace OpenRA.Widgets
public static int[] GetBorderSizes(string collection) public static int[] GetBorderSizes(string collection)
{ {
var images = new[] { "border-t", "border-b", "border-l", "border-r" }; 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 }; return new[] { (int)ss[0].Size.Y, (int)ss[1].Size.Y, (int)ss[2].Size.X, (int)ss[3].Size.X };
} }

View File

@@ -26,9 +26,16 @@ namespace OpenRA
public class World public class World
{ {
class ActorIDComparer : IComparer<Actor>
{
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<MPos, bool> FalsePredicate = _ => false; static readonly Func<MPos, bool> FalsePredicate = _ => false;
internal readonly TraitDictionary TraitDict = new TraitDictionary(); internal readonly TraitDictionary TraitDict = new TraitDictionary();
readonly HashSet<Actor> actors = new HashSet<Actor>(); readonly SortedSet<Actor> actors = new SortedSet<Actor>(ActorIDComparer.Instance);
readonly List<IEffect> effects = new List<IEffect>(); readonly List<IEffect> effects = new List<IEffect>();
readonly Queue<Action<World>> frameEndActions = new Queue<Action<World>>(); readonly Queue<Action<World>> frameEndActions = new Queue<Action<World>>();
@@ -237,6 +244,7 @@ namespace OpenRA
public void Add(IEffect b) { effects.Add(b); } public void Add(IEffect b) { effects.Add(b); }
public void Remove(IEffect b) { effects.Remove(b); } public void Remove(IEffect b) { effects.Remove(b); }
public void RemoveAll(Predicate<IEffect> predicate) { effects.RemoveAll(predicate); }
public void AddFrameEndTask(Action<World> a) { frameEndActions.Enqueue(a); } public void AddFrameEndTask(Action<World> a) { frameEndActions.Enqueue(a); }

View File

@@ -21,8 +21,8 @@ namespace OpenRA.Mods.Common.Lint
foreach (var actorInfo in map.Rules.Actors.Where(a => !a.Key.StartsWith("^"))) foreach (var actorInfo in map.Rules.Actors.Where(a => !a.Key.StartsWith("^")))
try try
{ {
var traits = actorInfo.Value.TraitsInConstructOrder().ToArray(); var hasTraits = actorInfo.Value.TraitsInConstructOrder().Any();
if (traits.Length == 0) if (!hasTraits)
emitWarning("Actor {0} has no traits. Is this intended?".F(actorInfo.Key)); emitWarning("Actor {0} has no traits. Is this intended?".F(actorInfo.Key));
} }
catch (Exception e) catch (Exception e)

View File

@@ -47,8 +47,8 @@ namespace OpenRA.Mods.Common.Orders
if (mi.Button == MouseButton.Right) if (mi.Button == MouseButton.Right)
world.CancelInputMode(); world.CancelInputMode();
var ret = InnerOrder(world, xy, mi).ToList(); var ret = InnerOrder(world, xy, mi).ToArray();
if (ret.Count > 0) if (ret.Length > 0)
world.CancelInputMode(); world.CancelInputMode();
return ret; return ret;

View File

@@ -203,14 +203,14 @@ namespace OpenRA.Mods.Common.SpriteLoaders
public static void Write(Stream s, Size size, IEnumerable<byte[]> frames) public static void Write(Stream s, Size size, IEnumerable<byte[]> 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 // 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)) 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)0); bw.Write((ushort)0);
bw.Write((ushort)size.Width); bw.Write((ushort)size.Width);

View File

@@ -37,7 +37,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
public readonly CargoInfo Info; public readonly CargoInfo Info;
readonly Actor self; readonly Actor self;
readonly List<Actor> cargo = new List<Actor>(); readonly Stack<Actor> cargo = new Stack<Actor>();
readonly HashSet<Actor> reserves = new HashSet<Actor>(); readonly HashSet<Actor> reserves = new HashSet<Actor>();
readonly Lazy<IFacing> facing; readonly Lazy<IFacing> facing;
@@ -59,7 +59,7 @@ namespace OpenRA.Mods.Common.Traits
if (init.Contains<RuntimeCargoInit>()) if (init.Contains<RuntimeCargoInit>())
{ {
cargo = init.Get<RuntimeCargoInit, Actor[]>().ToList(); cargo = new Stack<Actor>(init.Get<RuntimeCargoInit, Actor[]>());
totalWeight = cargo.Sum(c => GetWeight(c)); totalWeight = cargo.Sum(c => GetWeight(c));
} }
else if (init.Contains<CargoInit>()) else if (init.Contains<CargoInit>())
@@ -69,7 +69,7 @@ namespace OpenRA.Mods.Common.Traits
var unit = self.World.CreateActor(false, u.ToLowerInvariant(), var unit = self.World.CreateActor(false, u.ToLowerInvariant(),
new TypeDictionary { new OwnerInit(self.Owner) }); new TypeDictionary { new OwnerInit(self.Owner) });
cargo.Add(unit); cargo.Push(unit);
} }
totalWeight = cargo.Sum(c => GetWeight(c)); totalWeight = cargo.Sum(c => GetWeight(c));
@@ -81,7 +81,7 @@ namespace OpenRA.Mods.Common.Traits
var unit = self.World.CreateActor(false, u.ToLowerInvariant(), var unit = self.World.CreateActor(false, u.ToLowerInvariant(),
new TypeDictionary { new OwnerInit(self.Owner) }); new TypeDictionary { new OwnerInit(self.Owner) });
cargo.Add(unit); cargo.Push(unit);
} }
totalWeight = cargo.Sum(c => GetWeight(c)); 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 HasSpace(int weight) { return totalWeight + reservedWeight + weight <= Info.MaxWeight; }
public bool IsEmpty(Actor self) { return cargo.Count == 0; } 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) public Actor Unload(Actor self)
{ {
var a = cargo[0]; var a = cargo.Pop();
cargo.RemoveAt(0);
totalWeight -= GetWeight(a); totalWeight -= GetWeight(a);
SetPassengerFacing(a); SetPassengerFacing(a);
@@ -248,7 +247,7 @@ namespace OpenRA.Mods.Common.Traits
public void Load(Actor self, Actor a) public void Load(Actor self, Actor a)
{ {
cargo.Add(a); cargo.Push(a);
var w = GetWeight(a); var w = GetWeight(a);
totalWeight += w; totalWeight += w;
if (reserves.Contains(a)) if (reserves.Contains(a))

View File

@@ -103,8 +103,8 @@ namespace OpenRA.Mods.Common.Traits
CPos? ChooseEmptyCellNear(Actor a, string unit) CPos? ChooseEmptyCellNear(Actor a, string unit)
{ {
var possibleCells = GetSuitableCells(a.Location, unit).Where(c => !usedCells.Contains(c)).ToArray(); var possibleCells = GetSuitableCells(a.Location, unit).Where(c => !usedCells.Contains(c)).ToList();
if (possibleCells.Length == 0) if (possibleCells.Count == 0)
return null; return null;
return possibleCells.Random(self.World.SharedRandom); return possibleCells.Random(self.World.SharedRandom);

View File

@@ -43,7 +43,7 @@ namespace OpenRA.Mods.Common.Traits
dudesValue /= 100; dudesValue /= 100;
var eligibleLocations = FootprintUtils.Tiles(self).ToList(); var eligibleLocations = FootprintUtils.Tiles(self).ToList();
var actorTypes = info.ActorTypes.Select(a => new { Name = a, Cost = self.World.Map.Rules.Actors[a].Traits.Get<ValuedInfo>().Cost }).ToArray(); var actorTypes = info.ActorTypes.Select(a => new { Name = a, Cost = self.World.Map.Rules.Actors[a].Traits.Get<ValuedInfo>().Cost }).ToList();
while (eligibleLocations.Count > 0 && actorTypes.Any(a => a.Cost <= dudesValue)) while (eligibleLocations.Count > 0 && actorTypes.Any(a => a.Cost <= dudesValue))
{ {

View File

@@ -29,9 +29,9 @@ namespace OpenRA.Mods.Common.Traits
public void WorldLoaded(World world, WorldRenderer wr) public void WorldLoaded(World world, WorldRenderer wr)
{ {
domainIndexes = new Dictionary<uint, MovementClassDomainIndex>(); domainIndexes = new Dictionary<uint, MovementClassDomainIndex>();
var movementClasses = new HashSet<uint>( var movementClasses =
world.Map.Rules.Actors.Where(ai => ai.Value.Traits.Contains<MobileInfo>()) world.Map.Rules.Actors.Where(ai => ai.Value.Traits.Contains<MobileInfo>())
.Select(ai => (uint)ai.Value.Traits.Get<MobileInfo>().GetMovementClass(world.TileSet))); .Select(ai => (uint)ai.Value.Traits.Get<MobileInfo>().GetMovementClass(world.TileSet)).Distinct();
foreach (var mc in movementClasses) foreach (var mc in movementClasses)
domainIndexes[mc] = new MovementClassDomainIndex(world, mc); domainIndexes[mc] = new MovementClassDomainIndex(world, mc);
@@ -45,7 +45,7 @@ namespace OpenRA.Mods.Common.Traits
/// Regenerate the domain index for a group of cells /// Regenerate the domain index for a group of cells
public void UpdateCells(World world, IEnumerable<CPos> cells) public void UpdateCells(World world, IEnumerable<CPos> cells)
{ {
var dirty = new HashSet<CPos>(cells); var dirty = cells.ToHashSet();
foreach (var index in domainIndexes) foreach (var index in domainIndexes)
index.Value.UpdateCells(world, dirty); index.Value.UpdateCells(world, dirty);
} }

View File

@@ -28,7 +28,7 @@ namespace OpenRA.Mods.Common.Traits
public void WorldLoaded(World world, WorldRenderer wr) 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) var taken = world.LobbyInfo.Clients.Where(c => c.SpawnPoint != 0 && c.Slot != null)
.Select(c => spawns[c.SpawnPoint - 1]).ToList(); .Select(c => spawns[c.SpawnPoint - 1]).ToList();
var available = spawns.Except(taken).ToList(); var available = spawns.Except(taken).ToList();

View File

@@ -70,7 +70,7 @@ namespace OpenRA.Mods.Common.Traits
} }
// Add map smudges // 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 var smudge = new Smudge
{ {

View File

@@ -187,8 +187,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
var wps = file.GetSection("Waypoints") var wps = file.GetSection("Waypoints")
.Where(kv => Exts.ParseIntegerInvariant(kv.Value) > 0) .Where(kv => Exts.ParseIntegerInvariant(kv.Value) > 0)
.Select(kv => Pair.New(Exts.ParseIntegerInvariant(kv.Key), .Select(kv => Pair.New(Exts.ParseIntegerInvariant(kv.Key),
LocationFromMapOffset(Exts.ParseIntegerInvariant(kv.Value), mapSize))) LocationFromMapOffset(Exts.ParseIntegerInvariant(kv.Value), mapSize)));
.ToArray();
// Add waypoint actors // Add waypoint actors
foreach (var kv in wps) foreach (var kv in wps)

View File

@@ -31,7 +31,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
readonly ContainerWidget chatTemplate; readonly ContainerWidget chatTemplate;
readonly TextFieldWidget chatText; readonly TextFieldWidget chatText;
readonly List<INotifyChat> chatTraits; readonly INotifyChat[] chatTraits;
readonly TabCompletionLogic tabCompletion = new TabCompletionLogic(); readonly TabCompletionLogic tabCompletion = new TabCompletionLogic();
@@ -45,7 +45,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
this.orderManager = orderManager; this.orderManager = orderManager;
this.modRules = modRules; this.modRules = modRules;
chatTraits = world.WorldActor.TraitsImplementing<INotifyChat>().ToList(); chatTraits = world.WorldActor.TraitsImplementing<INotifyChat>().ToArray();
var players = world.Players.Where(p => p != world.LocalPlayer && !p.NonCombatant && !p.IsBot); 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)); disableTeamChat = world.LocalPlayer == null || world.LobbyInfo.IsSinglePlayer || !players.Any(p => p.IsAlliedWith(world.LocalPlayer));

View File

@@ -459,10 +459,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var techLevel = optionsBin.GetOrNull<DropDownButtonWidget>("TECHLEVEL_DROPDOWNBUTTON"); var techLevel = optionsBin.GetOrNull<DropDownButtonWidget>("TECHLEVEL_DROPDOWNBUTTON");
if (techLevel != null) if (techLevel != null)
{ {
var techTraits = modRules.Actors["player"].Traits.WithInterface<ProvidesTechPrerequisiteInfo>().ToArray(); var techTraits = modRules.Actors["player"].Traits.WithInterface<ProvidesTechPrerequisiteInfo>().ToList();
techLevel.IsVisible = () => techTraits.Length > 0; techLevel.IsVisible = () => techTraits.Count > 0;
optionsBin.GetOrNull<LabelWidget>("TECHLEVEL_DESC").IsVisible = () => techTraits.Length > 0; optionsBin.GetOrNull<LabelWidget>("TECHLEVEL_DESC").IsVisible = () => techTraits.Count > 0;
techLevel.IsDisabled = () => Map.Status != MapStatus.Available || Map.Map.Options.TechLevel != null || configurationDisabled() || techTraits.Length <= 1; 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.GetText = () => Map.Status != MapStatus.Available || Map.Map.Options.TechLevel != null ? "Not Available" : "{0}".F(orderManager.LobbyInfo.GlobalSettings.TechLevel);
techLevel.OnMouseDown = _ => techLevel.OnMouseDown = _ =>
{ {

View File

@@ -156,7 +156,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{ {
var spawns = preview.SpawnPoints; var spawns = preview.SpawnPoints;
return lobbyInfo.Clients 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)); .ToDictionary(c => spawns[c.SpawnPoint - 1], c => new SpawnOccupant(c));
} }
@@ -164,7 +164,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{ {
var spawns = preview.SpawnPoints; var spawns = preview.SpawnPoints;
return players 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)); .ToDictionary(c => spawns[c.SpawnPoint - 1], c => new SpawnOccupant(c));
} }
@@ -430,7 +430,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{ {
var dropdown = parent.Get<DropDownButtonWidget>("SPAWN"); var dropdown = parent.Get<DropDownButtonWidget>("SPAWN");
dropdown.IsDisabled = () => s.LockSpawn || orderManager.LocalClient.IsReady; 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(); dropdown.GetText = () => (c.SpawnPoint == 0) ? "-" : Convert.ToChar('A' - 1 + c.SpawnPoint).ToString();
} }

View File

@@ -21,7 +21,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
string selectedUid; string selectedUid;
// May be a subset of available maps if a mode filter is active // May be a subset of available maps if a mode filter is active
List<string> visibleMaps; string[] visibleMaps;
ScrollPanelWidget scrollpanel; ScrollPanelWidget scrollpanel;
ScrollItemWidget itemTemplate; ScrollItemWidget itemTemplate;
@@ -103,7 +103,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
selectedUid = uid; selectedUid = uid;
scrollpanel.ScrollToItem(uid, smooth: true); scrollpanel.ScrollToItem(uid, smooth: true);
}; };
randomMapButton.IsDisabled = () => visibleMaps == null || visibleMaps.Count == 0; randomMapButton.IsDisabled = () => visibleMaps == null || visibleMaps.Length == 0;
} }
EnumerateMaps(onSelect, filter); EnumerateMaps(onSelect, filter);
@@ -158,7 +158,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
scrollpanel.AddChild(item); scrollpanel.AddChild(item);
} }
visibleMaps = maps.Select(m => m.Uid).ToList(); visibleMaps = maps.Select(m => m.Uid).ToArray();
if (visibleMaps.Contains(selectedUid)) if (visibleMaps.Contains(selectedUid))
scrollpanel.ScrollToItem(selectedUid); scrollpanel.ScrollToItem(selectedUid);
} }

View File

@@ -203,7 +203,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var ddb = panel.GetOrNull<DropDownButtonWidget>("FLT_MAPNAME_DROPDOWNBUTTON"); var ddb = panel.GetOrNull<DropDownButtonWidget>("FLT_MAPNAME_DROPDOWNBUTTON");
if (ddb != null) if (ddb != null)
{ {
var options = new HashSet<string>(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.Sort(StringComparer.OrdinalIgnoreCase);
options.Insert(0, null); // no filter options.Insert(0, null); // no filter
@@ -231,7 +231,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var ddb = panel.GetOrNull<DropDownButtonWidget>("FLT_PLAYER_DROPDOWNBUTTON"); var ddb = panel.GetOrNull<DropDownButtonWidget>("FLT_PLAYER_DROPDOWNBUTTON");
if (ddb != null) if (ddb != null)
{ {
var options = new HashSet<string>(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.Sort(StringComparer.OrdinalIgnoreCase);
options.Insert(0, null); // no filter options.Insert(0, null); // no filter
@@ -295,7 +295,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{ {
ddb.IsDisabled = () => string.IsNullOrEmpty(filter.PlayerName); ddb.IsDisabled = () => string.IsNullOrEmpty(filter.PlayerName);
var options = new HashSet<string>(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.Sort(StringComparer.OrdinalIgnoreCase);
options.Insert(0, null); // no filter options.Insert(0, null); // no filter

View File

@@ -281,7 +281,7 @@ namespace OpenRA.Mods.Common.Widgets
Hotkey = ks.GetProductionHotkey(DisplayedIconCount), Hotkey = ks.GetProductionHotkey(DisplayedIconCount),
Sprite = icon.Image, Sprite = icon.Image,
Pos = new float2(rect.Location), 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); icons.Add(rect, pi);

View File

@@ -196,7 +196,7 @@ namespace OpenRA.Mods.Common.Widgets
{ {
var allQueues = a.World.ActorsWithTrait<ProductionQueue>() var allQueues = a.World.ActorsWithTrait<ProductionQueue>()
.Where(p => p.Actor.Owner == p.Actor.World.LocalPlayer && p.Actor.IsInWorld && p.Trait.Enabled) .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) foreach (var g in Groups.Values)
g.Update(allQueues); g.Update(allQueues);

View File

@@ -57,9 +57,9 @@ namespace OpenRA.Mods.D2k.Traits
var types = world.Selection.Actors.Where(a => a.IsInWorld && (a.World.LocalPlayer == a.Owner)) var types = world.Selection.Actors.Where(a => a.IsInWorld && (a.World.LocalPlayer == a.Owner))
.SelectMany(a => a.TraitsImplementing<Production>()) .SelectMany(a => a.TraitsImplementing<Production>())
.SelectMany(t => t.Info.Produces) .SelectMany(t => t.Info.Produces)
.ToArray(); .ToHashSet();
if (types.Length == 0) if (types.Count == 0)
return; return;
palette.SetCurrentTab(world.LocalPlayer.PlayerActor.TraitsImplementing<ProductionQueue>() palette.SetCurrentTab(world.LocalPlayer.PlayerActor.TraitsImplementing<ProductionQueue>()

View File

@@ -215,12 +215,12 @@ namespace OpenRA.Mods.D2k.Widgets
if (queue != null) if (queue != null)
{ {
var buildableItems = queue.BuildableItems().ToArray(); var buildableItems = queue.BuildableItems().ToList();
var allBuildables = queue.AllItems().OrderBy(a => a.Traits.Get<BuildableInfo>().BuildPaletteOrder).ToArray(); var allBuildables = queue.AllItems().OrderBy(a => a.Traits.Get<BuildableInfo>().BuildPaletteOrder).ToList();
var overlayBits = new List<Pair<Sprite, float2>>(); var overlayBits = new List<Pair<Sprite, float2>>();
var textBits = new List<Pair<float2, string>>(); var textBits = new List<Pair<float2, string>>();
numActualRows = Math.Max((allBuildables.Count() + Columns - 1) / Columns, Rows); numActualRows = Math.Max((allBuildables.Count + Columns - 1) / Columns, Rows);
// Palette Background // Palette Background
WidgetUtils.DrawRGBA(ChromeProvider.GetImage(paletteCollection, "top"), new float2(origin.X - 9, origin.Y - 9)); WidgetUtils.DrawRGBA(ChromeProvider.GetImage(paletteCollection, "top"), new float2(origin.X - 9, origin.Y - 9));

View File

@@ -218,7 +218,7 @@ namespace OpenRA.Mods.RA.AI
if (!buildableThings.Any()) if (!buildableThings.Any())
return null; return null;
var unit = buildableThings.ElementAtOrDefault(Random.Next(buildableThings.Count())); var unit = buildableThings.Random(Random);
return HasAdequateAirUnits(unit) ? unit : null; return HasAdequateAirUnits(unit) ? unit : null;
} }
@@ -231,11 +231,11 @@ namespace OpenRA.Mods.RA.AI
var myUnits = Player.World var myUnits = Player.World
.ActorsWithTrait<IPositionable>() .ActorsWithTrait<IPositionable>()
.Where(a => a.Actor.Owner == Player) .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)) foreach (var unit in Info.UnitsToBuild.Shuffle(Random))
if (buildableThings.Any(b => b.Name == unit.Key)) 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])) if (HasAdequateAirUnits(Map.Rules.Actors[unit.Key]))
return 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) var enemyUnits = World.FindActorsInCircle(pos, radius)
.Where(unit => Player.Stances[unit.Owner] == Stance.Enemy && .Where(unit => Player.Stances[unit.Owner] == Stance.Enemy &&
!unit.HasTrait<Husk>() && unit.HasTrait<ITargetable>()).ToList(); !unit.HasTrait<Husk>() && unit.HasTrait<ITargetable>());
if (enemyUnits.Count > 0)
return enemyUnits.ClosestTo(pos); return enemyUnits.ClosestTo(pos);
return null;
} }
List<Actor> FindEnemyConstructionYards() List<Actor> FindEnemyConstructionYards()
@@ -645,7 +642,7 @@ namespace OpenRA.Mods.RA.AI
{ {
var ownUnits = World.FindActorsInCircle(World.Map.CenterOfCell(BaseCenter), WRange.FromCells(Info.ProtectUnitScanRadius)) var ownUnits = World.FindActorsInCircle(World.Map.CenterOfCell(BaseCenter), WRange.FromCells(Info.ProtectUnitScanRadius))
.Where(unit => unit.Owner == Player && !unit.HasTrait<Building>() .Where(unit => unit.Owner == Player && !unit.HasTrait<Building>()
&& unit.HasTrait<AttackBase>()).ToList(); && unit.HasTrait<AttackBase>());
foreach (var a in ownUnits) foreach (var a in ownUnits)
protectSq.Units.Add(a); protectSq.Units.Add(a);

View File

@@ -84,7 +84,7 @@ namespace OpenRA.Mods.RA.AI
if (leader == null) if (leader == null)
return; return;
var ownUnits = owner.World.FindActorsInCircle(leader.CenterPosition, WRange.FromCells(owner.Units.Count) / 3) 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) if (ownUnits.Count < owner.Units.Count)
{ {
owner.World.IssueOrder(new Order("Stop", leader, false)); owner.World.IssueOrder(new Order("Stop", leader, false));
@@ -94,11 +94,12 @@ namespace OpenRA.Mods.RA.AI
else else
{ {
var enemies = owner.World.FindActorsInCircle(leader.CenterPosition, WRange.FromCells(12)) var enemies = owner.World.FindActorsInCircle(leader.CenterPosition, WRange.FromCells(12))
.Where(a1 => !a1.Destroyed && !a1.IsDead).ToList(); .Where(a1 => !a1.Destroyed && !a1.IsDead);
var enemynearby = enemies.Where(a1 => a1.HasTrait<ITargetable>() && leader.Owner.Stances[a1.Owner] == Stance.Enemy).ToList(); var enemynearby = enemies.Where(a1 => a1.HasTrait<ITargetable>() && leader.Owner.Stances[a1.Owner] == Stance.Enemy);
if (enemynearby.Any()) 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); owner.FuzzyStateMachine.ChangeState(owner, new GroundUnitsAttackState(), true);
return; return;
} }

View File

@@ -34,8 +34,8 @@ namespace OpenRA.Mods.RA.AI
{ {
var location = squad.Bot.BaseCenter; var location = squad.Bot.BaseCenter;
var buildings = squad.World.ActorsWithTrait<Building>() var buildings = squad.World.ActorsWithTrait<Building>()
.Where(a => a.Actor.Owner == squad.Bot.Player).Select(a => a.Actor).ToArray(); .Where(a => a.Actor.Owner == squad.Bot.Player).Select(a => a.Actor).ToList();
if (buildings.Length > 0) if (buildings.Count > 0)
location = buildings.Random(squad.Random).Location; location = buildings.Random(squad.Random).Location;
return location; return location;
} }

View File

@@ -95,9 +95,9 @@ namespace OpenRA.Mods.RA.Traits
paxFacing.Add(passenger, passenger.Trait<IFacing>()); paxFacing.Add(passenger, passenger.Trait<IFacing>());
paxPos.Add(passenger, passenger.Trait<IPositionable>()); paxPos.Add(passenger, passenger.Trait<IPositionable>());
paxRender.Add(passenger, passenger.Trait<RenderSprites>()); paxRender.Add(passenger, passenger.Trait<RenderSprites>());
armaments = armaments.Append(passenger.TraitsImplementing<Armament>() armaments.AddRange(
.Where(a => info.Armaments.Contains(a.Info.Name)) passenger.TraitsImplementing<Armament>()
.ToArray()).ToList(); .Where(a => info.Armaments.Contains(a.Info.Name)));
} }
public void PassengerExited(Actor self, Actor passenger) public void PassengerExited(Actor self, Actor passenger)
@@ -189,7 +189,7 @@ namespace OpenRA.Mods.RA.Traits
base.Tick(self); base.Tick(self);
// Take a copy so that Tick() can remove animations // Take a copy so that Tick() can remove animations
foreach (var m in muzzles.ToList()) foreach (var m in muzzles.ToArray())
m.Animation.Tick(); m.Animation.Tick();
} }
} }

View File

@@ -137,11 +137,8 @@ namespace OpenRA.Mods.RA.Traits
return occupancy * 12; return occupancy * 12;
})); }));
// Reverse the found-path to find the refinery location instead of our location:
path.Reverse();
if (path.Count != 0) if (path.Count != 0)
return refs[path[0]].Actor; return refs[path.Last()].Actor;
return null; return null;
} }

View File

@@ -57,11 +57,11 @@ namespace OpenRA.Mods.RA.Traits
{ {
var range = ((ChronoshiftPowerInfo)Info).Range; var range = ((ChronoshiftPowerInfo)Info).Range;
var tiles = Self.World.Map.FindTilesInCircle(xy, range); var tiles = Self.World.Map.FindTilesInCircle(xy, range);
var units = new List<Actor>(); var units = new HashSet<Actor>();
foreach (var t in tiles) 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<Chronoshiftable>() && return units.Where(a => a.HasTrait<Chronoshiftable>() &&
!a.TraitsImplementing<IPreventsTeleport>().Any(condition => condition.PreventsTeleport(a))); !a.TraitsImplementing<IPreventsTeleport>().Any(condition => condition.PreventsTeleport(a)));
} }

View File

@@ -79,7 +79,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
var extractFiles = Game.ModData.Manifest.ContentInstaller.ExtractFilesFromCD; var extractFiles = Game.ModData.Manifest.ContentInstaller.ExtractFilesFromCD;
var installCounter = 0; var installCounter = 0;
var installTotal = copyFiles.Count() + extractFiles.Count(); var installTotal = copyFiles.Length + extractFiles.Length;
var onProgress = (Action<string>)(s => Game.RunAfterTick(() => var onProgress = (Action<string>)(s => Game.RunAfterTick(() =>
{ {
progressBar.Percentage = installCounter * 100 / installTotal; progressBar.Percentage = installCounter * 100 / installTotal;

View File

@@ -188,19 +188,19 @@ namespace OpenRA.Mods.RA.Widgets
{ {
var bases = world.ActorsWithTrait<BaseBuilding>() var bases = world.ActorsWithTrait<BaseBuilding>()
.Where(a => a.Actor.Owner == world.LocalPlayer) .Where(a => a.Actor.Owner == world.LocalPlayer)
.ToArray(); .Select(b => b.Actor)
.ToList();
if (!bases.Any()) if (!bases.Any())
return true; return true;
var next = bases var next = bases
.Select(b => b.Actor)
.SkipWhile(b => !world.Selection.Actors.Contains(b)) .SkipWhile(b => !world.Selection.Actors.Contains(b))
.Skip(1) .Skip(1)
.FirstOrDefault(); .FirstOrDefault();
if (next == null) if (next == null)
next = bases.Select(b => b.Actor).First(); next = bases.First();
world.Selection.Combine(world, new Actor[] { next }, false, true); world.Selection.Combine(world, new Actor[] { next }, false, true);
@@ -212,19 +212,19 @@ namespace OpenRA.Mods.RA.Widgets
var facilities = world.ActorsWithTrait<Production>() var facilities = world.ActorsWithTrait<Production>()
.Where(a => a.Actor.Owner == world.LocalPlayer && !a.Actor.HasTrait<BaseBuilding>()) .Where(a => a.Actor.Owner == world.LocalPlayer && !a.Actor.HasTrait<BaseBuilding>())
.OrderBy(f => f.Actor.Info.Traits.Get<ProductionInfo>().Produces.First()) .OrderBy(f => f.Actor.Info.Traits.Get<ProductionInfo>().Produces.First())
.ToArray(); .Select(b => b.Actor)
.ToList();
if (!facilities.Any()) if (!facilities.Any())
return true; return true;
var next = facilities var next = facilities
.Select(b => b.Actor)
.SkipWhile(b => !world.Selection.Actors.Contains(b)) .SkipWhile(b => !world.Selection.Actors.Contains(b))
.Skip(1) .Skip(1)
.FirstOrDefault(); .FirstOrDefault();
if (next == null) if (next == null)
next = facilities.Select(b => b.Actor).First(); next = facilities.First();
world.Selection.Combine(world, new Actor[] { next }, false, true); world.Selection.Combine(world, new Actor[] { next }, false, true);