Reduce allocations in the main game loop.
- Cache the shroud projection even for flat maps to avoid allocating single element arrays. - Avoid LINQ in shroud and map projection queries to avoid enumerator allocations. - Avoid LINQ in calculation of sync values. - Cache enumerables in ProductionQueue. - Cache delegate in HackyAI.
This commit is contained in:
@@ -189,6 +189,7 @@ namespace OpenRA.Mods.Common.AI
|
||||
|
||||
public Player Player { get; private set; }
|
||||
|
||||
readonly Func<Actor, bool> isEnemyUnit;
|
||||
Dictionary<SupportPowerInstance, int> waitingPowers = new Dictionary<SupportPowerInstance, int>();
|
||||
Dictionary<string, SupportPowerDecision> powerDecisions = new Dictionary<string, SupportPowerDecision>();
|
||||
|
||||
@@ -229,6 +230,8 @@ namespace OpenRA.Mods.Common.AI
|
||||
{
|
||||
Info = info;
|
||||
World = init.World;
|
||||
isEnemyUnit = unit =>
|
||||
Player.Stances[unit.Owner] == Stance.Enemy && !unit.HasTrait<Husk>() && unit.HasTrait<ITargetable>();
|
||||
|
||||
foreach (var decision in info.PowerDecisions)
|
||||
powerDecisions.Add(decision.OrderName, decision);
|
||||
@@ -580,20 +583,12 @@ namespace OpenRA.Mods.Common.AI
|
||||
|
||||
internal Actor FindClosestEnemy(WPos pos)
|
||||
{
|
||||
var allEnemyUnits = World.Actors
|
||||
.Where(unit => Player.Stances[unit.Owner] == Stance.Enemy && !unit.HasTrait<Husk>() &&
|
||||
unit.HasTrait<ITargetable>());
|
||||
|
||||
return allEnemyUnits.ClosestTo(pos);
|
||||
return World.Actors.Where(isEnemyUnit).ClosestTo(pos);
|
||||
}
|
||||
|
||||
internal Actor FindClosestEnemy(WPos pos, WDist radius)
|
||||
{
|
||||
var enemyUnits = World.FindActorsInCircle(pos, radius)
|
||||
.Where(unit => Player.Stances[unit.Owner] == Stance.Enemy &&
|
||||
!unit.HasTrait<Husk>() && unit.HasTrait<ITargetable>());
|
||||
|
||||
return enemyUnits.ClosestTo(pos);
|
||||
return World.FindActorsInCircle(pos, radius).Where(isEnemyUnit).ClosestTo(pos);
|
||||
}
|
||||
|
||||
List<Actor> FindEnemyConstructionYards()
|
||||
|
||||
@@ -40,7 +40,17 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public class RepairableBuilding : UpgradableTrait<RepairableBuildingInfo>, ITick
|
||||
{
|
||||
[Sync]
|
||||
public int RepairersHash { get { return Repairers.Aggregate(0, (code, player) => code ^ Sync.HashPlayer(player)); } }
|
||||
public int RepairersHash
|
||||
{
|
||||
get
|
||||
{
|
||||
var hash = 0;
|
||||
foreach (var player in Repairers)
|
||||
hash ^= Sync.HashPlayer(player);
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
public readonly List<Player> Repairers = new List<Player>();
|
||||
|
||||
readonly Health health;
|
||||
@@ -94,7 +104,9 @@ namespace OpenRA.Mods.Common.Traits
|
||||
Repairers.RemoveAll(isNotActiveAlly);
|
||||
|
||||
// If after the previous operation there's no repairers left, stop
|
||||
if (!Repairers.Any()) return;
|
||||
if (Repairers.Count == 0)
|
||||
return;
|
||||
|
||||
var buildingValue = self.GetSellValue();
|
||||
|
||||
// The cost is the same regardless of the amount of people repairing
|
||||
|
||||
@@ -70,6 +70,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
readonly HarvesterInfo info;
|
||||
readonly Mobile mobile;
|
||||
Dictionary<ResourceTypeInfo, int> contents = new Dictionary<ResourceTypeInfo, int>();
|
||||
bool idleSmart = true;
|
||||
|
||||
[Sync] public Actor OwnerLinkedProc = null;
|
||||
[Sync] public Actor LastLinkedProc = null;
|
||||
@@ -77,8 +78,17 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Sync] int currentUnloadTicks;
|
||||
public CPos? LastHarvestedCell = null;
|
||||
public CPos? LastOrderLocation = null;
|
||||
[Sync] public int ContentValue { get { return contents.Sum(c => c.Key.ValuePerUnit * c.Value); } }
|
||||
bool idleSmart = true;
|
||||
[Sync]
|
||||
public int ContentValue
|
||||
{
|
||||
get
|
||||
{
|
||||
var value = 0;
|
||||
foreach (var c in contents)
|
||||
value += c.Key.ValuePerUnit * c.Value;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public Harvester(Actor self, HarvesterInfo info)
|
||||
{
|
||||
|
||||
@@ -58,7 +58,16 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public ReadOnlyList<MissionObjective> Objectives;
|
||||
|
||||
[Sync]
|
||||
public int ObjectivesHash { get { return Objectives.Aggregate(0, (code, objective) => code ^ Sync.Hash(objective.State)); } }
|
||||
public int ObjectivesHash
|
||||
{
|
||||
get
|
||||
{
|
||||
var hash = 0;
|
||||
foreach (var objective in objectives)
|
||||
hash ^= Sync.Hash(objective.State);
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
// This property is used as a flag in 'Cooperative' games to mark that the player has completed all his objectives.
|
||||
// The player's WinState is only updated when his allies have all completed their objective as well.
|
||||
|
||||
@@ -68,15 +68,17 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public readonly ProductionQueueInfo Info;
|
||||
readonly Actor self;
|
||||
|
||||
// A list of things we could possibly build
|
||||
readonly Dictionary<ActorInfo, ProductionState> produceable = new Dictionary<ActorInfo, ProductionState>();
|
||||
readonly List<ProductionItem> queue = new List<ProductionItem>();
|
||||
readonly IEnumerable<ActorInfo> allProduceables;
|
||||
readonly IEnumerable<ActorInfo> buildableProduceables;
|
||||
|
||||
// Will change if the owner changes
|
||||
PowerManager playerPower;
|
||||
PlayerResources playerResources;
|
||||
protected DeveloperMode developerMode;
|
||||
|
||||
// A list of things we could possibly build
|
||||
Dictionary<ActorInfo, ProductionState> produceable;
|
||||
List<ProductionItem> queue = new List<ProductionItem>();
|
||||
|
||||
public Actor Actor { get { return self; } }
|
||||
|
||||
[Sync] public int QueueLength { get { return queue.Count; } }
|
||||
@@ -101,6 +103,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
Enabled = !info.Factions.Any() || info.Factions.Contains(Faction);
|
||||
|
||||
CacheProduceables(playerActor);
|
||||
allProduceables = produceable.Where(a => a.Value.Buildable || a.Value.Visible).Select(a => a.Key);
|
||||
buildableProduceables = produceable.Where(a => a.Value.Buildable).Select(a => a.Key);
|
||||
}
|
||||
|
||||
void ClearQueue()
|
||||
@@ -143,7 +147,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
void CacheProduceables(Actor playerActor)
|
||||
{
|
||||
produceable = new Dictionary<ActorInfo, ProductionState>();
|
||||
produceable.Clear();
|
||||
if (!Enabled)
|
||||
return;
|
||||
|
||||
@@ -200,9 +204,9 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public virtual IEnumerable<ActorInfo> AllItems()
|
||||
{
|
||||
if (self.World.AllowDevCommands && developerMode.AllTech)
|
||||
return produceable.Select(a => a.Key);
|
||||
return produceable.Keys;
|
||||
|
||||
return produceable.Where(a => a.Value.Buildable || a.Value.Visible).Select(a => a.Key);
|
||||
return allProduceables;
|
||||
}
|
||||
|
||||
public virtual IEnumerable<ActorInfo> BuildableItems()
|
||||
@@ -210,9 +214,9 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (!Enabled)
|
||||
return Enumerable.Empty<ActorInfo>();
|
||||
if (self.World.AllowDevCommands && developerMode.AllTech)
|
||||
return produceable.Select(a => a.Key);
|
||||
return produceable.Keys;
|
||||
|
||||
return produceable.Where(a => a.Value.Buildable).Select(a => a.Key);
|
||||
return buildableProduceables;
|
||||
}
|
||||
|
||||
public bool CanBuild(ActorInfo actor)
|
||||
|
||||
Reference in New Issue
Block a user