From c3531d6f707f8d210618a714a991d0a2fca42dd8 Mon Sep 17 00:00:00 2001 From: RoosterDragon Date: Sat, 28 Feb 2015 19:07:54 +0000 Subject: [PATCH] Avoid duplicated frozen visibility checks. The FrozenUnderFog.Tick method will now reuse the calculation do by the frozen actor when it had to calculate its visibility, this prevents it having to re-do the fairly expensive visibility calculation. --- OpenRA.Game/Traits/Player/FrozenActorLayer.cs | 39 +++++++----- .../Traits/Modifiers/FrozenUnderFog.cs | 61 ++++++++----------- 2 files changed, 48 insertions(+), 52 deletions(-) diff --git a/OpenRA.Game/Traits/Player/FrozenActorLayer.cs b/OpenRA.Game/Traits/Player/FrozenActorLayer.cs index 54ce10142e..dc74e6c188 100644 --- a/OpenRA.Game/Traits/Player/FrozenActorLayer.cs +++ b/OpenRA.Game/Traits/Player/FrozenActorLayer.cs @@ -40,7 +40,7 @@ namespace OpenRA.Traits public bool Visible; - public FrozenActor(Actor self, MPos[] footprint, CellRegion footprintRegion) + public FrozenActor(Actor self, MPos[] footprint, CellRegion footprintRegion, Shroud shroud) { actor = self; Footprint = footprint; @@ -48,6 +48,8 @@ namespace OpenRA.Traits CenterPosition = self.CenterPosition; Bounds = self.Bounds; + + UpdateVisibility(shroud); } public uint ID { get { return actor.ActorID; } } @@ -56,7 +58,15 @@ namespace OpenRA.Traits public Actor Actor { get { return !actor.IsDead ? actor : null; } } int flashTicks; - public void Tick(World world, Shroud shroud) + public void Tick(Shroud shroud) + { + UpdateVisibility(shroud); + + if (flashTicks > 0) + flashTicks--; + } + + void UpdateVisibility(Shroud shroud) { // We are doing the following LINQ manually to avoid allocating an extra delegate since this is a hot path. // Visible = !Footprint.Any(shroud.IsVisibleTest(FootprintRegion)); @@ -68,9 +78,6 @@ namespace OpenRA.Traits Visible = false; break; } - - if (flashTicks > 0) - flashTicks--; } public void Flash() @@ -129,22 +136,24 @@ namespace OpenRA.Traits VisibilityHash = 0; FrozenHash = 0; - foreach (var kv in frozen) + foreach (var kvp in frozen) { - FrozenHash += (int)kv.Key; + var hash = (int)kvp.Key; + FrozenHash += hash; - kv.Value.Tick(self.World, self.Owner.Shroud); - if (kv.Value.Visible) - VisibilityHash += (int)kv.Key; + var frozenActor = kvp.Value; + frozenActor.Tick(self.Owner.Shroud); - if (!kv.Value.Visible && kv.Value.Actor == null) - remove.Add(kv.Key); + if (frozenActor.Visible) + VisibilityHash += hash; + else if (frozenActor.Actor == null) + remove.Add(kvp.Key); } - foreach (var r in remove) + foreach (var actorID in remove) { - world.ScreenMap.Remove(owner, frozen[r]); - frozen.Remove(r); + world.ScreenMap.Remove(owner, frozen[actorID]); + frozen.Remove(actorID); } } diff --git a/OpenRA.Mods.Common/Traits/Modifiers/FrozenUnderFog.cs b/OpenRA.Mods.Common/Traits/Modifiers/FrozenUnderFog.cs index 5daf8bcc61..9ffaa2356e 100644 --- a/OpenRA.Mods.Common/Traits/Modifiers/FrozenUnderFog.cs +++ b/OpenRA.Mods.Common/Traits/Modifiers/FrozenUnderFog.cs @@ -48,7 +48,6 @@ namespace OpenRA.Mods.Common.Traits footprint = footprintCells.Select(cell => cell.ToMPos(init.World.Map)).ToArray(); footprintRegion = CellRegion.BoundingRegion(init.World.Map.TileShape, footprintCells); tooltip = Exts.Lazy(() => init.Self.TraitsImplementing().FirstOrDefault()); - tooltip = Exts.Lazy(() => init.Self.TraitsImplementing().FirstOrDefault()); health = Exts.Lazy(() => init.Self.TraitOrDefault()); frozen = new Dictionary(); @@ -66,55 +65,43 @@ namespace OpenRA.Mods.Common.Traits return; VisibilityHash = 0; - foreach (var p in self.World.Players) - { - // We are doing the following LINQ manually to avoid allocating an extra delegate since this is a hot path. - // var isVisible = footprint.Any(p.Shroud.IsVisibleTest(footprintRegion)); - var isVisibleTest = p.Shroud.IsVisibleTest(footprintRegion); - var isVisible = false; - foreach (var uv in footprint) - if (isVisibleTest(uv)) - { - isVisible = true; - break; - } - - visible[p] = isVisible; - if (isVisible) - VisibilityHash += p.ClientIndex; - } - - if (!initialized) - { - foreach (var p in self.World.Players) - { - visible[p] |= startsRevealed; - p.PlayerActor.Trait().Add(frozen[p] = new FrozenActor(self, footprint, footprintRegion)); - } - - initialized = true; - } - foreach (var player in self.World.Players) { - if (!visible[player]) + bool isVisible; + FrozenActor frozenActor; + if (!initialized) + { + frozen[player] = frozenActor = new FrozenActor(self, footprint, footprintRegion, player.Shroud); + player.PlayerActor.Trait().Add(frozenActor); + isVisible = visible[player] |= startsRevealed; + } + else + { + frozenActor = frozen[player]; + isVisible = visible[player] = !frozenActor.Visible; + } + + if (isVisible) + VisibilityHash += player.ClientIndex; + else continue; - var actor = frozen[player]; - actor.Owner = self.Owner; + frozenActor.Owner = self.Owner; if (health.Value != null) { - actor.HP = health.Value.HP; - actor.DamageState = health.Value.DamageState; + frozenActor.HP = health.Value.HP; + frozenActor.DamageState = health.Value.DamageState; } if (tooltip.Value != null) { - actor.TooltipInfo = tooltip.Value.TooltipInfo; - actor.TooltipOwner = tooltip.Value.Owner; + frozenActor.TooltipInfo = tooltip.Value.TooltipInfo; + frozenActor.TooltipOwner = tooltip.Value.Owner; } } + + initialized = true; } public void TickRender(WorldRenderer wr, Actor self)