Remove obsolete LocomotorInfo caching.
This commit is contained in:
committed by
Matthias Mailänder
parent
49e7a33db0
commit
5a7dc385a3
@@ -24,7 +24,6 @@ namespace OpenRA.Mods.Common.Activities
|
||||
readonly Harvester harv;
|
||||
readonly HarvesterInfo harvInfo;
|
||||
readonly Mobile mobile;
|
||||
readonly LocomotorInfo locomotorInfo;
|
||||
readonly ResourceClaimLayer claimLayer;
|
||||
readonly IPathFinder pathFinder;
|
||||
readonly DomainIndex domainIndex;
|
||||
@@ -43,7 +42,6 @@ namespace OpenRA.Mods.Common.Activities
|
||||
harv = self.Trait<Harvester>();
|
||||
harvInfo = self.Info.TraitInfo<HarvesterInfo>();
|
||||
mobile = self.Trait<Mobile>();
|
||||
locomotorInfo = mobile.Info.LocomotorInfo;
|
||||
claimLayer = self.World.WorldActor.Trait<ResourceClaimLayer>();
|
||||
pathFinder = self.World.WorldActor.Trait<IPathFinder>();
|
||||
domainIndex = self.World.WorldActor.Trait<DomainIndex>();
|
||||
@@ -195,7 +193,7 @@ namespace OpenRA.Mods.Common.Activities
|
||||
// Find any harvestable resources:
|
||||
List<CPos> path;
|
||||
using (var search = PathSearch.Search(self.World, mobile.Locomotor, self, BlockedByActor.Stationary, loc =>
|
||||
domainIndex.IsPassable(self.Location, loc, locomotorInfo) && harv.CanHarvestCell(self, loc) && claimLayer.CanClaimCell(self, loc))
|
||||
domainIndex.IsPassable(self.Location, loc, mobile.Locomotor) && harv.CanHarvestCell(self, loc) && claimLayer.CanClaimCell(self, loc))
|
||||
.WithCustomCost(loc =>
|
||||
{
|
||||
if ((loc - searchFromLoc.Value).LengthSquared > searchRadiusSquared)
|
||||
|
||||
@@ -133,7 +133,7 @@ namespace OpenRA.Mods.Common.Activities
|
||||
searchCells.Clear();
|
||||
searchCellsTick = self.World.WorldTick;
|
||||
foreach (var cell in CandidateMovementCells(self))
|
||||
if (domainIndex.IsPassable(loc, cell, Mobile.Info.LocomotorInfo) && Mobile.CanEnterCell(cell))
|
||||
if (domainIndex.IsPassable(loc, cell, Mobile.Locomotor) && Mobile.CanEnterCell(cell))
|
||||
searchCells.Add(cell);
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +87,6 @@ namespace OpenRA.Mods.Common.Pathfinder
|
||||
|
||||
readonly BlockedByActor checkConditions;
|
||||
readonly Locomotor locomotor;
|
||||
readonly LocomotorInfo.WorldMovementInfo worldMovementInfo;
|
||||
readonly CellInfoLayerPool.PooledCellInfoLayer pooledLayer;
|
||||
readonly bool checkTerrainHeight;
|
||||
CellLayer<CellInfo> groundInfo;
|
||||
@@ -108,7 +107,6 @@ namespace OpenRA.Mods.Common.Pathfinder
|
||||
customLayerInfo[cml.Index] = (cml, pooledLayer.GetLayer());
|
||||
|
||||
World = world;
|
||||
worldMovementInfo = locomotorInfo.GetWorldMovementInfo(world);
|
||||
Actor = actor;
|
||||
LaneBias = 1;
|
||||
checkConditions = check;
|
||||
|
||||
@@ -145,7 +145,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
Target FindNextResource(Actor actor, HarvesterTraitWrapper harv)
|
||||
{
|
||||
Func<CPos, bool> isValidResource = cell =>
|
||||
domainIndex.IsPassable(actor.Location, cell, harv.Locomotor.Info) &&
|
||||
domainIndex.IsPassable(actor.Location, cell, harv.Locomotor) &&
|
||||
harv.Harvester.CanHarvestCell(actor, cell) &&
|
||||
claimLayer.CanClaimCell(actor, cell);
|
||||
|
||||
|
||||
@@ -29,11 +29,11 @@ namespace OpenRA.Mods.Common.Traits.BotModules.Squads
|
||||
// (Way better than finding a nearest target which is likely to be on Ground)
|
||||
// You might be tempted to move these lookups into Activate() but that causes null reference exception.
|
||||
var domainIndex = first.World.WorldActor.Trait<DomainIndex>();
|
||||
var locomotorInfo = first.Info.TraitInfo<MobileInfo>().LocomotorInfo;
|
||||
var locomotor = first.Trait<Mobile>().Locomotor;
|
||||
|
||||
var navalProductions = owner.World.ActorsHavingTrait<Building>().Where(a
|
||||
=> owner.SquadManager.Info.NavalProductionTypes.Contains(a.Info.Name)
|
||||
&& domainIndex.IsPassable(first.Location, a.Location, locomotorInfo)
|
||||
&& domainIndex.IsPassable(first.Location, a.Location, locomotor)
|
||||
&& a.AppearsHostileTo(first));
|
||||
|
||||
if (navalProductions.Any())
|
||||
|
||||
@@ -725,16 +725,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
public int MovementSpeedForCell(Actor self, CPos cell)
|
||||
{
|
||||
var index = cell.Layer == 0 ? self.World.Map.GetTerrainIndex(cell) :
|
||||
self.World.GetCustomMovementLayers()[cell.Layer].GetTerrainIndex(cell);
|
||||
|
||||
if (index == byte.MaxValue)
|
||||
return 0;
|
||||
|
||||
var terrainSpeed = Info.LocomotorInfo.TilesetTerrainInfo[self.World.Map.Rules.TileSet][index].Speed;
|
||||
if (terrainSpeed == 0)
|
||||
return 0;
|
||||
|
||||
var terrainSpeed = Locomotor.MovementSpeedForCell(cell);
|
||||
var modifiers = speedModifiers.Value.Append(terrainSpeed);
|
||||
|
||||
return Util.ApplyPercentageModifiers(Info.Speed, modifiers);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Traits;
|
||||
|
||||
@@ -62,9 +63,9 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
if (mobileInfo != null)
|
||||
{
|
||||
var locomotorInfo = mobileInfo.LocomotorInfo;
|
||||
var locomotor = self.World.WorldActor.TraitsImplementing<Locomotor>().First(l => l.Info.Name == mobileInfo.Locomotor);
|
||||
location = self.World.Map.ChooseClosestMatchingEdgeCell(self.Location,
|
||||
c => mobileInfo.CanEnterCell(self.World, null, c) && domainIndex.IsPassable(c, destinations[0], locomotorInfo));
|
||||
c => mobileInfo.CanEnterCell(self.World, null, c) && domainIndex.IsPassable(c, destinations[0], locomotor));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,24 +31,23 @@ namespace OpenRA.Mods.Common.Traits
|
||||
domainIndexes = new Dictionary<uint, MovementClassDomainIndex>();
|
||||
tileSet = world.Map.Rules.TileSet;
|
||||
var locomotors = world.WorldActor.TraitsImplementing<Locomotor>().Where(l => !string.IsNullOrEmpty(l.Info.Name));
|
||||
var movementClasses = locomotors.Select(t => (uint)t.Info.GetMovementClass(tileSet)).Distinct();
|
||||
var movementClasses = locomotors.Select(t => t.MovementClass).Distinct();
|
||||
|
||||
foreach (var mc in movementClasses)
|
||||
domainIndexes[mc] = new MovementClassDomainIndex(world, mc);
|
||||
}
|
||||
|
||||
public bool IsPassable(CPos p1, CPos p2, LocomotorInfo li)
|
||||
public bool IsPassable(CPos p1, CPos p2, Locomotor locomotor)
|
||||
{
|
||||
// HACK: Work around units in other movement layers from being blocked
|
||||
// when the point in the main layer is not pathable
|
||||
if (p1.Layer != 0 || p2.Layer != 0)
|
||||
return true;
|
||||
|
||||
if (li.DisableDomainPassabilityCheck)
|
||||
if (locomotor.Info.DisableDomainPassabilityCheck)
|
||||
return true;
|
||||
|
||||
var movementClass = li.GetMovementClass(tileSet);
|
||||
return domainIndexes[movementClass].IsPassable(p1, p2);
|
||||
return domainIndexes[locomotor.MovementClass].IsPassable(p1, p2);
|
||||
}
|
||||
|
||||
/// <summary>Regenerate the domain index for a group of cells.</summary>
|
||||
|
||||
@@ -99,21 +99,6 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return ret;
|
||||
}
|
||||
|
||||
TerrainInfo[] LoadTilesetSpeeds(TileSet tileSet)
|
||||
{
|
||||
var info = new TerrainInfo[tileSet.TerrainInfo.Length];
|
||||
for (var i = 0; i < info.Length; i++)
|
||||
info[i] = TerrainInfo.Impassable;
|
||||
|
||||
foreach (var kvp in TerrainSpeeds)
|
||||
{
|
||||
if (tileSet.TryGetTerrainIndex(kvp.Key, out var index))
|
||||
info[index] = kvp.Value;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
public class TerrainInfo
|
||||
{
|
||||
public static readonly TerrainInfo Impassable = new TerrainInfo();
|
||||
@@ -134,53 +119,6 @@ namespace OpenRA.Mods.Common.Traits
|
||||
}
|
||||
}
|
||||
|
||||
public struct WorldMovementInfo
|
||||
{
|
||||
internal readonly World World;
|
||||
internal readonly TerrainInfo[] TerrainInfos;
|
||||
internal WorldMovementInfo(World world, LocomotorInfo info)
|
||||
{
|
||||
// PERF: This struct allows us to cache the terrain info for the tileset used by the world.
|
||||
// This allows us to speed up some performance-sensitive pathfinding calculations.
|
||||
World = world;
|
||||
TerrainInfos = info.TilesetTerrainInfo[world.Map.Rules.TileSet];
|
||||
}
|
||||
}
|
||||
|
||||
public readonly Cache<TileSet, TerrainInfo[]> TilesetTerrainInfo;
|
||||
public readonly Cache<TileSet, int> TilesetMovementClass;
|
||||
|
||||
public LocomotorInfo()
|
||||
{
|
||||
TilesetTerrainInfo = new Cache<TileSet, TerrainInfo[]>(LoadTilesetSpeeds);
|
||||
TilesetMovementClass = new Cache<TileSet, int>(CalculateTilesetMovementClass);
|
||||
}
|
||||
|
||||
public int CalculateTilesetMovementClass(TileSet tileset)
|
||||
{
|
||||
// collect our ability to cross *all* terraintypes, in a bitvector
|
||||
return TilesetTerrainInfo[tileset].Select(ti => ti.Cost < short.MaxValue).ToBits();
|
||||
}
|
||||
|
||||
public uint GetMovementClass(TileSet tileset)
|
||||
{
|
||||
return (uint)TilesetMovementClass[tileset];
|
||||
}
|
||||
|
||||
public int TileSetMovementHash(TileSet tileSet)
|
||||
{
|
||||
var terrainInfos = TilesetTerrainInfo[tileSet];
|
||||
|
||||
// Compute and return the hash using aggregate
|
||||
return terrainInfos.Aggregate(terrainInfos.Length,
|
||||
(current, terrainInfo) => unchecked(current * 31 + terrainInfo.Cost));
|
||||
}
|
||||
|
||||
public WorldMovementInfo GetWorldMovementInfo(World world)
|
||||
{
|
||||
return new WorldMovementInfo(world, this);
|
||||
}
|
||||
|
||||
public virtual bool DisableDomainPassabilityCheck { get { return false; } }
|
||||
|
||||
public override object Create(ActorInitializer init) { return new Locomotor(init.Self, this); }
|
||||
@@ -203,14 +141,15 @@ namespace OpenRA.Mods.Common.Traits
|
||||
}
|
||||
|
||||
public readonly LocomotorInfo Info;
|
||||
public readonly uint MovementClass;
|
||||
CellLayer<short> cellsCost;
|
||||
CellLayer<CellCache> blockingCache;
|
||||
|
||||
readonly Dictionary<byte, CellLayer<short>> customLayerCellsCost = new Dictionary<byte, CellLayer<short>>();
|
||||
readonly Dictionary<byte, CellLayer<CellCache>> customLayerBlockingCache = new Dictionary<byte, CellLayer<CellCache>>();
|
||||
|
||||
LocomotorInfo.TerrainInfo[] terrainInfos;
|
||||
World world;
|
||||
readonly LocomotorInfo.TerrainInfo[] terrainInfos;
|
||||
readonly World world;
|
||||
readonly HashSet<CPos> dirtyCells = new HashSet<CPos>();
|
||||
|
||||
IActorMap actorMap;
|
||||
@@ -220,6 +159,15 @@ namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
Info = info;
|
||||
sharesCell = info.SharesCell;
|
||||
world = self.World;
|
||||
|
||||
var tileSet = world.Map.Rules.TileSet;
|
||||
terrainInfos = new LocomotorInfo.TerrainInfo[tileSet.TerrainInfo.Length];
|
||||
for (var i = 0; i < terrainInfos.Length; i++)
|
||||
if (!info.TerrainSpeeds.TryGetValue(tileSet.TerrainInfo[i].Type, out terrainInfos[i]))
|
||||
terrainInfos[i] = LocomotorInfo.TerrainInfo.Impassable;
|
||||
|
||||
MovementClass = (uint)terrainInfos.Select(ti => ti.Cost < short.MaxValue).ToBits();
|
||||
}
|
||||
|
||||
public short MovementCostForCell(CPos cell)
|
||||
@@ -230,6 +178,14 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return cell.Layer == 0 ? cellsCost[cell] : customLayerCellsCost[cell.Layer][cell];
|
||||
}
|
||||
|
||||
public int MovementSpeedForCell(CPos cell)
|
||||
{
|
||||
var index = cell.Layer == 0 ? world.Map.GetTerrainIndex(cell) :
|
||||
world.GetCustomMovementLayers()[cell.Layer].GetTerrainIndex(cell);
|
||||
|
||||
return terrainInfos[index].Speed;
|
||||
}
|
||||
|
||||
public short MovementCostToEnterCell(Actor actor, CPos destNode, BlockedByActor check, Actor ignoreActor)
|
||||
{
|
||||
if (!world.Map.Contains(destNode))
|
||||
@@ -404,11 +360,9 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
public void WorldLoaded(World w, WorldRenderer wr)
|
||||
{
|
||||
world = w;
|
||||
var map = w.Map;
|
||||
actorMap = w.ActorMap;
|
||||
actorMap.CellUpdated += CellUpdated;
|
||||
terrainInfos = Info.TilesetTerrainInfo[map.Rules.TileSet];
|
||||
|
||||
blockingCache = new CellLayer<CellCache>(map);
|
||||
cellsCost = new CellLayer<short>(map);
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
}
|
||||
|
||||
// If a water-land transition is required, bail early
|
||||
if (domainIndex != null && !domainIndex.IsPassable(source, target, locomotor.Info))
|
||||
if (domainIndex != null && !domainIndex.IsPassable(source, target, locomotor))
|
||||
return EmptyPath;
|
||||
|
||||
var distance = source - target;
|
||||
@@ -119,7 +119,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
// Really, we only need to check the circle perimeter, but it's not clear that would be a performance win
|
||||
if (domainIndex != null)
|
||||
{
|
||||
tilesInRange = new List<CPos>(tilesInRange.Where(t => domainIndex.IsPassable(source, t, locomotor.Info)));
|
||||
tilesInRange = new List<CPos>(tilesInRange.Where(t => domainIndex.IsPassable(source, t, locomotor)));
|
||||
if (!tilesInRange.Any())
|
||||
return EmptyPath;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user