Merge pull request #7834 from RoosterDragon/avoid-preventable-allocations

Avoid preventable allocations
This commit is contained in:
Matthias Mailänder
2015-04-03 13:52:46 +02:00
5 changed files with 38 additions and 18 deletions

View File

@@ -33,6 +33,18 @@ namespace OpenRA.GameRules
[Desc("Delay in ticks before applying the warhead effect.", "0 = instant (old model).")] [Desc("Delay in ticks before applying the warhead effect.", "0 = instant (old model).")]
public readonly int Delay = 0; public readonly int Delay = 0;
HashSet<string> validTargetSet;
HashSet<string> invalidTargetSet;
public bool IsValidTarget(IEnumerable<string> targetTypes)
{
if (validTargetSet == null)
validTargetSet = new HashSet<string>(ValidTargets);
if (invalidTargetSet == null)
invalidTargetSet = new HashSet<string>(InvalidTargets);
return validTargetSet.Overlaps(targetTypes) && !invalidTargetSet.Overlaps(targetTypes);
}
/// <summary>Applies the warhead's effect against the target.</summary> /// <summary>Applies the warhead's effect against the target.</summary>
public abstract void DoImpact(Target target, Actor firedBy, IEnumerable<int> damageModifiers); public abstract void DoImpact(Target target, Actor firedBy, IEnumerable<int> damageModifiers);
@@ -52,8 +64,7 @@ namespace OpenRA.GameRules
return false; return false;
var cellInfo = world.Map.GetTerrainInfo(cell); var cellInfo = world.Map.GetTerrainInfo(cell);
if (!ValidTargets.Intersect(cellInfo.TargetTypes).Any() if (!IsValidTarget(cellInfo.TargetTypes))
|| InvalidTargets.Intersect(cellInfo.TargetTypes).Any())
return false; return false;
return true; return true;
@@ -81,8 +92,7 @@ namespace OpenRA.GameRules
// A target type is valid if it is in the valid targets list, and not in the invalid targets list. // A target type is valid if it is in the valid targets list, and not in the invalid targets list.
var targetable = victim.TraitOrDefault<ITargetable>(); var targetable = victim.TraitOrDefault<ITargetable>();
if (targetable == null || !ValidTargets.Intersect(targetable.TargetTypes).Any() if (targetable == null || !IsValidTarget(targetable.TargetTypes))
|| InvalidTargets.Intersect(targetable.TargetTypes).Any())
return false; return false;
return true; return true;
@@ -101,8 +111,7 @@ namespace OpenRA.GameRules
// A target type is valid if it is in the valid targets list, and not in the invalid targets list. // A target type is valid if it is in the valid targets list, and not in the invalid targets list.
var targetable = victim.Info.Traits.GetOrDefault<ITargetableInfo>(); var targetable = victim.Info.Traits.GetOrDefault<ITargetableInfo>();
if (targetable == null || !ValidTargets.Intersect(targetable.GetTargetTypes()).Any() if (targetable == null || !IsValidTarget(targetable.GetTargetTypes()))
|| InvalidTargets.Intersect(targetable.GetTargetTypes()).Any())
return false; return false;
return true; return true;

View File

@@ -30,7 +30,7 @@ namespace OpenRA.GameRules
public interface IProjectileInfo { IEffect Create(ProjectileArgs args); } public interface IProjectileInfo { IEffect Create(ProjectileArgs args); }
public class WeaponInfo public sealed class WeaponInfo
{ {
[Desc("The maximum range the weapon can fire.")] [Desc("The maximum range the weapon can fire.")]
public readonly WRange Range = WRange.Zero; public readonly WRange Range = WRange.Zero;
@@ -64,9 +64,14 @@ namespace OpenRA.GameRules
[FieldLoader.LoadUsing("LoadWarheads")] [FieldLoader.LoadUsing("LoadWarheads")]
public readonly List<Warhead> Warheads = new List<Warhead>(); public readonly List<Warhead> Warheads = new List<Warhead>();
readonly HashSet<string> validTargetSet;
readonly HashSet<string> invalidTargetSet;
public WeaponInfo(string name, MiniYaml content) public WeaponInfo(string name, MiniYaml content)
{ {
FieldLoader.Load(this, content); FieldLoader.Load(this, content);
validTargetSet = new HashSet<string>(ValidTargets);
invalidTargetSet = new HashSet<string>(InvalidTargets);
} }
static object LoadProjectile(MiniYaml yaml) static object LoadProjectile(MiniYaml yaml)
@@ -92,6 +97,11 @@ namespace OpenRA.GameRules
return retList; return retList;
} }
public bool IsValidTarget(IEnumerable<string> targetTypes)
{
return validTargetSet.Overlaps(targetTypes) && !invalidTargetSet.Overlaps(targetTypes);
}
/// <summary>Checks if the weapon is valid against (can target) the target.</summary> /// <summary>Checks if the weapon is valid against (can target) the target.</summary>
public bool IsValidAgainst(Target target, World world, Actor firedBy) public bool IsValidAgainst(Target target, World world, Actor firedBy)
{ {
@@ -108,8 +118,7 @@ namespace OpenRA.GameRules
return false; return false;
var cellInfo = world.Map.GetTerrainInfo(cell); var cellInfo = world.Map.GetTerrainInfo(cell);
if (!ValidTargets.Intersect(cellInfo.TargetTypes).Any() if (!IsValidTarget(cellInfo.TargetTypes))
|| InvalidTargets.Intersect(cellInfo.TargetTypes).Any())
return false; return false;
return true; return true;
@@ -122,8 +131,7 @@ namespace OpenRA.GameRules
public bool IsValidAgainst(Actor victim, Actor firedBy) public bool IsValidAgainst(Actor victim, Actor firedBy)
{ {
var targetable = victim.TraitOrDefault<ITargetable>(); var targetable = victim.TraitOrDefault<ITargetable>();
if (targetable == null || !ValidTargets.Intersect(targetable.TargetTypes).Any() if (targetable == null || !IsValidTarget(targetable.TargetTypes))
|| InvalidTargets.Intersect(targetable.TargetTypes).Any())
return false; return false;
if (!Warheads.Any(w => w.IsValidAgainst(victim, firedBy))) if (!Warheads.Any(w => w.IsValidAgainst(victim, firedBy)))
@@ -136,8 +144,7 @@ namespace OpenRA.GameRules
public bool IsValidAgainst(FrozenActor victim, Actor firedBy) public bool IsValidAgainst(FrozenActor victim, Actor firedBy)
{ {
var targetable = victim.Info.Traits.GetOrDefault<ITargetableInfo>(); var targetable = victim.Info.Traits.GetOrDefault<ITargetableInfo>();
if (targetable == null || !ValidTargets.Intersect(targetable.GetTargetTypes()).Any() if (targetable == null || !IsValidTarget(targetable.GetTargetTypes()))
|| InvalidTargets.Intersect(targetable.GetTargetTypes()).Any())
return false; return false;
if (!Warheads.Any(w => w.IsValidAgainst(victim, firedBy))) if (!Warheads.Any(w => w.IsValidAgainst(victim, firedBy)))

View File

@@ -18,6 +18,8 @@ namespace OpenRA.Mods.Common.AI
{ {
abstract class AirStateBase : StateBase abstract class AirStateBase : StateBase
{ {
static readonly string[] AirTargetTypes = new[] { "Air" };
protected const int MissileUnitMultiplier = 3; protected const int MissileUnitMultiplier = 3;
protected static int CountAntiAirUnits(IEnumerable<Actor> units) protected static int CountAntiAirUnits(IEnumerable<Actor> units)
@@ -34,7 +36,7 @@ namespace OpenRA.Mods.Common.AI
var arms = unit.TraitsImplementing<Armament>(); var arms = unit.TraitsImplementing<Armament>();
foreach (var a in arms) foreach (var a in arms)
{ {
if (a.Weapon.ValidTargets.Contains("Air")) if (a.Weapon.IsValidTarget(AirTargetTypes))
{ {
missileUnitsCount++; missileUnitsCount++;
break; break;

View File

@@ -69,7 +69,7 @@ namespace OpenRA.Mods.Common.AI
var arms = a.TraitsImplementing<Armament>(); var arms = a.TraitsImplementing<Armament>();
foreach (var arm in arms) foreach (var arm in arms)
if (arm.Weapon.ValidTargets.Intersect(targetable.TargetTypes).Any()) if (arm.Weapon.IsValidTarget(targetable.TargetTypes))
return true; return true;
return false; return false;

View File

@@ -34,15 +34,18 @@ namespace OpenRA.Mods.Common.Traits
{ {
[Sync] [Sync]
public int RepairersHash { get { return Repairers.Aggregate(0, (code, player) => code ^ Sync.HashPlayer(player)); } } public int RepairersHash { get { return Repairers.Aggregate(0, (code, player) => code ^ Sync.HashPlayer(player)); } }
public List<Player> Repairers = new List<Player>(); public readonly List<Player> Repairers = new List<Player>();
readonly Health health; readonly Health health;
public bool RepairActive = false; public bool RepairActive = false;
readonly Predicate<Player> isNotActiveAlly;
public RepairableBuilding(Actor self, RepairableBuildingInfo info) public RepairableBuilding(Actor self, RepairableBuildingInfo info)
: base(info) : base(info)
{ {
health = self.Trait<Health>(); health = self.Trait<Health>();
isNotActiveAlly = player => player.WinState != WinState.Undefined || player.Stances[self.Owner] != Stance.Ally;
} }
public void RepairBuilding(Actor self, Player player) public void RepairBuilding(Actor self, Player player)
@@ -81,8 +84,7 @@ namespace OpenRA.Mods.Common.Traits
if (remainingTicks == 0) if (remainingTicks == 0)
{ {
Repairers = Repairers.Where(player => player.WinState == WinState.Undefined Repairers.RemoveAll(isNotActiveAlly);
&& player.Stances[self.Owner] == Stance.Ally).ToList();
// If after the previous operation there's no repairers left, stop // If after the previous operation there's no repairers left, stop
if (!Repairers.Any()) return; if (!Repairers.Any()) return;