diff --git a/OpenRA.Game/TraitDictionary.cs b/OpenRA.Game/TraitDictionary.cs index 774563c27c..4d91bba30d 100644 --- a/OpenRA.Game/TraitDictionary.cs +++ b/OpenRA.Game/TraitDictionary.cs @@ -11,8 +11,10 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using OpenRA.Primitives; +using OpenRA.Support; namespace OpenRA { @@ -122,6 +124,16 @@ namespace OpenRA t.Value.RemoveActor(a.ActorID); } + public void ApplyToActorsWithTrait(Action action) + { + InnerGet().ApplyToAll(action); + } + + public void ApplyToActorsWithTraitTimed(Action action, string text) + { + InnerGet().ApplyToAllTimed(action, text); + } + interface ITraitContainer { void Add(Actor actor, object trait); @@ -277,6 +289,32 @@ namespace OpenRA actors.RemoveRange(startIndex, count); traits.RemoveRange(startIndex, count); } + + public void ApplyToAll(Action action) + { + for (var i = 0; i < actors.Count; i++) + action(actors[i], traits[i]); + } + + public void ApplyToAllTimed(Action action, string text) + { + var longTickThresholdInStopwatchTicks = PerfTimer.LongTickThresholdInStopwatchTicks; + var start = Stopwatch.GetTimestamp(); + for (var i = 0; i < actors.Count; i++) + { + var actor = actors[i]; + var trait = traits[i]; + action(actor, trait); + var current = Stopwatch.GetTimestamp(); + if (current - start > longTickThresholdInStopwatchTicks) + { + PerfTimer.LogLongTick(start, current, text, trait); + start = Stopwatch.GetTimestamp(); + } + else + start = current; + } + } } } } diff --git a/OpenRA.Game/World.cs b/OpenRA.Game/World.cs index d29aec8aef..59a0e536f6 100644 --- a/OpenRA.Game/World.cs +++ b/OpenRA.Game/World.cs @@ -465,7 +465,7 @@ namespace OpenRA foreach (var a in actors.Values) a.Tick(); - ActorsWithTrait().DoTimed(x => x.Trait.Tick(x.Actor), "Trait"); + ApplyToActorsWithTraitTimed((Actor actor, ITick trait) => trait.Tick(actor), "Trait"); effects.DoTimed(e => e.Tick(this), "Effect"); } @@ -477,7 +477,7 @@ namespace OpenRA // For things that want to update their render state once per tick, ignoring pause state public void TickRender(WorldRenderer wr) { - ActorsWithTrait().DoTimed(x => x.Trait.TickRender(wr, x.Actor), "Render"); + ApplyToActorsWithTraitTimed((Actor actor, ITickRender trait) => trait.TickRender(wr, actor), "Render"); ScreenMap.TickRender(); } @@ -536,6 +536,11 @@ namespace OpenRA return TraitDict.ActorsWithTrait(); } + public void ApplyToActorsWithTraitTimed(Action action, string text) + { + TraitDict.ApplyToActorsWithTraitTimed(action, text); + } + public IEnumerable ActorsHavingTrait() { return TraitDict.ActorsHavingTrait();