1 #region Copyright & License Information 2 /* 3 * Copyright 2007-2020 The OpenRA Developers (see AUTHORS) 4 * This file is part of OpenRA, which is free software. It is made 5 * available to you under the terms of the GNU General Public License 6 * as published by the Free Software Foundation, either version 3 of 7 * the License, or (at your option) any later version. For more 8 * information, see COPYING. 9 */ 10 #endregion 11 12 using System; 13 using System.Collections.Generic; 14 using System.Diagnostics; 15 using System.Linq; 16 using OpenRA.Support; 17 using OpenRA.Traits; 18 19 namespace OpenRA 20 { 21 public static class WorldUtils 22 { ClosestTo(this IEnumerable<Actor> actors, Actor a)23 public static Actor ClosestTo(this IEnumerable<Actor> actors, Actor a) 24 { 25 return actors.ClosestTo(a.CenterPosition); 26 } 27 ClosestTo(this IEnumerable<Actor> actors, WPos pos)28 public static Actor ClosestTo(this IEnumerable<Actor> actors, WPos pos) 29 { 30 return actors.MinByOrDefault(a => (a.CenterPosition - pos).LengthSquared); 31 } 32 PositionClosestTo(this IEnumerable<WPos> positions, WPos pos)33 public static WPos PositionClosestTo(this IEnumerable<WPos> positions, WPos pos) 34 { 35 return positions.MinByOrDefault(p => (p - pos).LengthSquared); 36 } 37 FindActorsInCircle(this World world, WPos origin, WDist r)38 public static IEnumerable<Actor> FindActorsInCircle(this World world, WPos origin, WDist r) 39 { 40 // Target ranges are calculated in 2D, so ignore height differences 41 var vec = new WVec(r, r, WDist.Zero); 42 return world.ActorMap.ActorsInBox(origin - vec, origin + vec).Where( 43 a => (a.CenterPosition - origin).HorizontalLengthSquared <= r.LengthSquared); 44 } 45 ContainsTemporaryBlocker(this World world, CPos cell, Actor ignoreActor = null)46 public static bool ContainsTemporaryBlocker(this World world, CPos cell, Actor ignoreActor = null) 47 { 48 if (!world.RulesContainTemporaryBlocker) 49 return false; 50 51 var temporaryBlockers = world.ActorMap.GetActorsAt(cell); 52 foreach (var temporaryBlocker in temporaryBlockers) 53 { 54 if (temporaryBlocker == ignoreActor) 55 continue; 56 57 var temporaryBlockerTraits = temporaryBlocker.TraitsImplementing<ITemporaryBlocker>(); 58 foreach (var temporaryBlockerTrait in temporaryBlockerTraits) 59 if (temporaryBlockerTrait.IsBlocking(temporaryBlocker, cell)) 60 return true; 61 } 62 63 return false; 64 } 65 DoTimed(this IEnumerable<T> e, Action<T> a, string text)66 public static void DoTimed<T>(this IEnumerable<T> e, Action<T> a, string text) 67 { 68 // PERF: This is a hot path and must run with minimal added overhead. 69 // Calling Stopwatch.GetTimestamp is a bit expensive, so we enumerate manually to allow us to call it only 70 // once per iteration in the normal case. 71 // See also: RunActivity 72 var longTickThresholdInStopwatchTicks = PerfTimer.LongTickThresholdInStopwatchTicks; 73 using (var enumerator = e.GetEnumerator()) 74 { 75 var start = Stopwatch.GetTimestamp(); 76 while (enumerator.MoveNext()) 77 { 78 a(enumerator.Current); 79 var current = Stopwatch.GetTimestamp(); 80 if (current - start > longTickThresholdInStopwatchTicks) 81 { 82 PerfTimer.LogLongTick(start, current, text, enumerator.Current); 83 start = Stopwatch.GetTimestamp(); 84 } 85 else 86 start = current; 87 } 88 } 89 } 90 AreMutualAllies(Player a, Player b)91 public static bool AreMutualAllies(Player a, Player b) 92 { 93 return a.Stances[b] == Stance.Ally && 94 b.Stances[a] == Stance.Ally; 95 } 96 } 97 } 98