Cache TargetablePositions in Actor

To speed up Target.Positions.
This commit is contained in:
reaperrr
2018-03-14 01:48:24 +01:00
committed by Paul Chote
parent 4c16e51f92
commit 0c52ff3ae5
5 changed files with 29 additions and 10 deletions

View File

@@ -77,6 +77,8 @@ namespace OpenRA
readonly IMouseBounds[] mouseBounds; readonly IMouseBounds[] mouseBounds;
readonly IVisibilityModifier[] visibilityModifiers; readonly IVisibilityModifier[] visibilityModifiers;
readonly IDefaultVisibility defaultVisibility; readonly IDefaultVisibility defaultVisibility;
readonly ITargetablePositions[] targetablePositions;
WPos[] staticTargetablePositions;
internal Actor(World world, string name, TypeDictionary initDict) internal Actor(World world, string name, TypeDictionary initDict)
{ {
@@ -118,6 +120,15 @@ namespace OpenRA
visibilityModifiers = TraitsImplementing<IVisibilityModifier>().ToArray(); visibilityModifiers = TraitsImplementing<IVisibilityModifier>().ToArray();
defaultVisibility = Trait<IDefaultVisibility>(); defaultVisibility = Trait<IDefaultVisibility>();
Targetables = TraitsImplementing<ITargetable>().ToArray(); Targetables = TraitsImplementing<ITargetable>().ToArray();
targetablePositions = TraitsImplementing<ITargetablePositions>().ToArray();
world.AddFrameEndTask(w =>
{
// Caching this in a AddFrameEndTask, because trait construction order might cause problems if done directly at creation time.
// All actors that can move should have IMove, if not it's pretty safe to assume the actor is immobile and
// all targetable positions can be cached if all ITargetablePositions have no conditional requirements.
if (!Info.HasTraitInfo<IMoveInfo>() && targetablePositions.All(tp => tp.AlwaysEnabled))
staticTargetablePositions = targetablePositions.SelectMany(tp => tp.TargetablePositions(this)).ToArray();
});
SyncHashes = TraitsImplementing<ISync>().Select(sync => new SyncHash(sync)).ToArray(); SyncHashes = TraitsImplementing<ISync>().Select(sync => new SyncHash(sync)).ToArray();
} }
@@ -368,6 +379,18 @@ namespace OpenRA
return false; return false;
} }
public IEnumerable<WPos> GetTargetablePositions()
{
if (staticTargetablePositions != null)
return staticTargetablePositions;
var enabledTargetablePositionTraits = targetablePositions.Where(Exts.IsTraitEnabled);
if (enabledTargetablePositionTraits.Any())
return enabledTargetablePositionTraits.SelectMany(tp => tp.TargetablePositions(this));
return new[] { this.CenterPosition };
}
#region Scripting interface #region Scripting interface
Lazy<ScriptActorInterface> luaInterface; Lazy<ScriptActorInterface> luaInterface;

View File

@@ -157,14 +157,7 @@ namespace OpenRA.Traits
if (!actor.Targetables.Any(Exts.IsTraitEnabled)) if (!actor.Targetables.Any(Exts.IsTraitEnabled))
return new[] { actor.CenterPosition }; return new[] { actor.CenterPosition };
var targetablePositions = actor.TraitsImplementing<ITargetablePositions>().Where(Exts.IsTraitEnabled); return actor.GetTargetablePositions();
if (targetablePositions.Any())
{
var target = this;
return targetablePositions.SelectMany(tp => tp.TargetablePositions(target.actor));
}
return new[] { actor.CenterPosition };
case TargetType.FrozenActor: case TargetType.FrozenActor:
return new[] { frozen.CenterPosition }; return new[] { frozen.CenterPosition };
case TargetType.Terrain: case TargetType.Terrain:

View File

@@ -387,8 +387,11 @@ namespace OpenRA.Traits
public interface ITargetablePositions public interface ITargetablePositions
{ {
IEnumerable<WPos> TargetablePositions(Actor self); IEnumerable<WPos> TargetablePositions(Actor self);
bool AlwaysEnabled { get; }
} }
public interface IMoveInfo : ITraitInfoInterface { }
[RequireExplicitImplementation] [RequireExplicitImplementation]
public interface IGameOver { void GameOver(World world); } public interface IGameOver { void GameOver(World world); }

View File

@@ -73,6 +73,8 @@ namespace OpenRA.Mods.Common.Traits
base.Created(self); base.Created(self);
} }
bool ITargetablePositions.AlwaysEnabled { get { return Info.RequiresCondition == null; } }
IEnumerable<WPos> ITargetablePositions.TargetablePositions(Actor self) IEnumerable<WPos> ITargetablePositions.TargetablePositions(Actor self)
{ {
if (IsTraitDisabled) if (IsTraitDisabled)

View File

@@ -334,8 +334,6 @@ namespace OpenRA.Mods.Common.Traits
IEnumerable<object> ActorPreviewInits(ActorInfo ai, ActorPreviewType type); IEnumerable<object> ActorPreviewInits(ActorInfo ai, ActorPreviewType type);
} }
public interface IMoveInfo : ITraitInfoInterface { }
public interface IMove public interface IMove
{ {
Activity MoveTo(CPos cell, int nearEnough); Activity MoveTo(CPos cell, int nearEnough);