Speed up shroud visibility updates.
A unit with the CreatesShroud or RevealsShroud trait must update all shrouds when it changes position. Calculating the tiles it can currently see is an expensive calculation that previously had to be repeated for every shroud that needed to know these tiles. Now, we lazily populate a ref parameter to allow it to be reused for an actor if possible. The biggest improvement comes from the fact that allied players can re-use this calculation when updating their shrouds. Since many games includes a neutral player allied to both sides, most games will see a decent speedup.
This commit is contained in:
@@ -36,10 +36,7 @@ namespace OpenRA.Traits
|
|||||||
{
|
{
|
||||||
cachedLocation = self.Location;
|
cachedLocation = self.Location;
|
||||||
cachedDisabled = disabled;
|
cachedDisabled = disabled;
|
||||||
|
Shroud.UpdateShroudGeneration(self.World.Players.Select(p => p.Shroud), self);
|
||||||
var shroud = self.World.Players.Select(p => p.Shroud);
|
|
||||||
foreach (var s in shroud)
|
|
||||||
s.UpdateShroudGeneration(self);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,9 +33,7 @@ namespace OpenRA.Traits
|
|||||||
if (cachedLocation != self.Location)
|
if (cachedLocation != self.Location)
|
||||||
{
|
{
|
||||||
cachedLocation = self.Location;
|
cachedLocation = self.Location;
|
||||||
|
Shroud.UpdateVisibility(self.World.Players.Select(p => p.Shroud), self);
|
||||||
foreach (var s in self.World.Players.Select(p => p.Shroud))
|
|
||||||
s.UpdateVisibility(self);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -73,10 +73,10 @@ namespace OpenRA.Traits
|
|||||||
generatedShroudCount = new CellLayer<short>(map);
|
generatedShroudCount = new CellLayer<short>(map);
|
||||||
explored = new CellLayer<bool>(map);
|
explored = new CellLayer<bool>(map);
|
||||||
|
|
||||||
self.World.ActorAdded += AddVisibility;
|
self.World.ActorAdded += a => { CPos[] visible = null; AddVisibility(a, ref visible); };
|
||||||
self.World.ActorRemoved += RemoveVisibility;
|
self.World.ActorRemoved += RemoveVisibility;
|
||||||
|
|
||||||
self.World.ActorAdded += AddShroudGeneration;
|
self.World.ActorAdded += a => { CPos[] shrouded = null; AddShroudGeneration(a, ref shrouded); };
|
||||||
self.World.ActorRemoved += RemoveShroudGeneration;
|
self.World.ActorRemoved += RemoveShroudGeneration;
|
||||||
|
|
||||||
fogVisibilities = Exts.Lazy(() => self.TraitsImplementing<IFogVisibilityModifier>().ToArray());
|
fogVisibilities = Exts.Lazy(() => self.TraitsImplementing<IFogVisibilityModifier>().ToArray());
|
||||||
@@ -98,6 +98,25 @@ namespace OpenRA.Traits
|
|||||||
Hash += 1;
|
Hash += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void UpdateVisibility(IEnumerable<Shroud> shrouds, Actor actor)
|
||||||
|
{
|
||||||
|
CPos[] visbility = null;
|
||||||
|
foreach (var shroud in shrouds)
|
||||||
|
shroud.UpdateVisibility(actor, ref visbility);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void UpdateShroudGeneration(IEnumerable<Shroud> shrouds, Actor actor)
|
||||||
|
{
|
||||||
|
CPos[] shrouded = null;
|
||||||
|
foreach (var shroud in shrouds)
|
||||||
|
shroud.UpdateShroudGeneration(actor, ref shrouded);
|
||||||
|
}
|
||||||
|
|
||||||
|
static CPos[] FindVisibleTiles(Actor actor, WRange range)
|
||||||
|
{
|
||||||
|
return GetVisOrigins(actor).SelectMany(o => FindVisibleTiles(actor.World, o, range)).Distinct().ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
static IEnumerable<CPos> FindVisibleTiles(World world, CPos position, WRange radius)
|
static IEnumerable<CPos> FindVisibleTiles(World world, CPos position, WRange radius)
|
||||||
{
|
{
|
||||||
var map = world.Map;
|
var map = world.Map;
|
||||||
@@ -110,17 +129,15 @@ namespace OpenRA.Traits
|
|||||||
yield return cell;
|
yield return cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddVisibility(Actor a)
|
void AddVisibility(Actor a, ref CPos[] visible)
|
||||||
{
|
{
|
||||||
var rs = a.TraitOrDefault<RevealsShroud>();
|
var rs = a.TraitOrDefault<RevealsShroud>();
|
||||||
if (rs == null || !a.Owner.IsAlliedWith(self.Owner) || rs.Range == WRange.Zero)
|
if (rs == null || !a.Owner.IsAlliedWith(self.Owner) || rs.Range == WRange.Zero)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var origins = GetVisOrigins(a);
|
// Lazily generate the visible tiles, allowing the caller to re-use them if desired.
|
||||||
var visible = origins.SelectMany(o => FindVisibleTiles(a.World, o, rs.Range))
|
visible = visible ?? FindVisibleTiles(a, rs.Range);
|
||||||
.Distinct().ToArray();
|
|
||||||
|
|
||||||
// Update visibility
|
|
||||||
foreach (var c in visible)
|
foreach (var c in visible)
|
||||||
{
|
{
|
||||||
visibleCount[c]++;
|
visibleCount[c]++;
|
||||||
@@ -147,24 +164,25 @@ namespace OpenRA.Traits
|
|||||||
Invalidate();
|
Invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateVisibility(Actor a)
|
void UpdateVisibility(Actor a, ref CPos[] visible)
|
||||||
{
|
{
|
||||||
// Actors outside the world don't have any vis
|
// Actors outside the world don't have any vis
|
||||||
if (!a.IsInWorld)
|
if (!a.IsInWorld)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
RemoveVisibility(a);
|
RemoveVisibility(a);
|
||||||
AddVisibility(a);
|
AddVisibility(a, ref visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddShroudGeneration(Actor a)
|
void AddShroudGeneration(Actor a, ref CPos[] shrouded)
|
||||||
{
|
{
|
||||||
var cs = a.TraitOrDefault<CreatesShroud>();
|
var cs = a.TraitOrDefault<CreatesShroud>();
|
||||||
if (cs == null || a.Owner.IsAlliedWith(self.Owner) || cs.Range == WRange.Zero)
|
if (cs == null || a.Owner.IsAlliedWith(self.Owner) || cs.Range == WRange.Zero)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var shrouded = GetVisOrigins(a).SelectMany(o => FindVisibleTiles(a.World, o, cs.Range))
|
// Lazily generate the shrouded tiles, allowing the caller to re-use them if desired.
|
||||||
.Distinct().ToArray();
|
shrouded = shrouded ?? FindVisibleTiles(a, cs.Range);
|
||||||
|
|
||||||
foreach (var c in shrouded)
|
foreach (var c in shrouded)
|
||||||
generatedShroudCount[c]++;
|
generatedShroudCount[c]++;
|
||||||
|
|
||||||
@@ -188,10 +206,10 @@ namespace OpenRA.Traits
|
|||||||
Invalidate();
|
Invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateShroudGeneration(Actor a)
|
void UpdateShroudGeneration(Actor a, ref CPos[] shrouded)
|
||||||
{
|
{
|
||||||
RemoveShroudGeneration(a);
|
RemoveShroudGeneration(a);
|
||||||
AddShroudGeneration(a);
|
AddShroudGeneration(a, ref shrouded);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdatePlayerStance(World w, Player player, Stance oldStance, Stance newStance)
|
public void UpdatePlayerStance(World w, Player player, Stance oldStance, Stance newStance)
|
||||||
@@ -201,8 +219,10 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
foreach (var a in w.Actors.Where(a => a.Owner == player))
|
foreach (var a in w.Actors.Where(a => a.Owner == player))
|
||||||
{
|
{
|
||||||
UpdateVisibility(a);
|
CPos[] visible = null;
|
||||||
UpdateShroudGeneration(a);
|
UpdateVisibility(a, ref visible);
|
||||||
|
CPos[] shrouded = null;
|
||||||
|
UpdateShroudGeneration(a, ref shrouded);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user