Locomotor cache should handle custom layers

This commit is contained in:
teinarss
2019-09-01 20:14:54 +02:00
committed by abcdefg30
parent 912a424596
commit d712bdea85

View File

@@ -220,6 +220,9 @@ namespace OpenRA.Mods.Common.Traits
CellLayer<short> cellsCost; CellLayer<short> cellsCost;
CellLayer<CellCache> blockingCache; 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; LocomotorInfo.TerrainInfo[] terrainInfos;
World world; World world;
readonly HashSet<CPos> dirtyCells = new HashSet<CPos>(); readonly HashSet<CPos> dirtyCells = new HashSet<CPos>();
@@ -238,7 +241,7 @@ namespace OpenRA.Mods.Common.Traits
if (!world.Map.Contains(cell)) if (!world.Map.Contains(cell))
return short.MaxValue; return short.MaxValue;
return cellsCost[cell]; return cell.Layer == 0 ? cellsCost[cell] : customLayerCellsCost[cell.Layer][cell];
} }
public short MovementCostToEnterCell(Actor actor, CPos destNode, Actor ignoreActor, CellConditions check) public short MovementCostToEnterCell(Actor actor, CPos destNode, Actor ignoreActor, CellConditions check)
@@ -246,7 +249,7 @@ namespace OpenRA.Mods.Common.Traits
if (!world.Map.Contains(destNode)) if (!world.Map.Contains(destNode))
return short.MaxValue; return short.MaxValue;
var cellCost = cellsCost[destNode]; var cellCost = destNode.Layer == 0 ? cellsCost[destNode] : customLayerCellsCost[destNode.Layer][destNode];
if (cellCost == short.MaxValue || if (cellCost == short.MaxValue ||
!CanMoveFreelyInto(actor, destNode, ignoreActor, check)) !CanMoveFreelyInto(actor, destNode, ignoreActor, check))
@@ -376,16 +379,40 @@ namespace OpenRA.Mods.Common.Traits
var map = w.Map; var map = w.Map;
actorMap = w.ActorMap; actorMap = w.ActorMap;
actorMap.CellUpdated += CellUpdated; actorMap.CellUpdated += CellUpdated;
terrainInfos = Info.TilesetTerrainInfo[map.Rules.TileSet];
blockingCache = new CellLayer<CellCache>(map); blockingCache = new CellLayer<CellCache>(map);
cellsCost = new CellLayer<short>(map); cellsCost = new CellLayer<short>(map);
terrainInfos = Info.TilesetTerrainInfo[map.Rules.TileSet];
foreach (var cell in map.AllCells) foreach (var cell in map.AllCells)
UpdateCellCost(cell); UpdateCellCost(cell);
map.CustomTerrain.CellEntryChanged += UpdateCellCost; map.CustomTerrain.CellEntryChanged += UpdateCellCost;
map.Tiles.CellEntryChanged += UpdateCellCost; map.Tiles.CellEntryChanged += UpdateCellCost;
// This section needs to run after WorldLoaded() because we need to be sure that all types of ICustomMovementLayer have been initialized.
w.AddFrameEndTask(_ =>
{
var customMovementLayers = w.WorldActor.TraitsImplementing<ICustomMovementLayer>();
foreach (var cml in customMovementLayers)
{
var cellLayer = new CellLayer<short>(map);
customLayerCellsCost[cml.Index] = cellLayer;
customLayerBlockingCache[cml.Index] = new CellLayer<CellCache>(map);
foreach (var cell in map.AllCells)
{
var index = cml.GetTerrainIndex(cell);
var cost = short.MaxValue;
if (index != byte.MaxValue)
cost = terrainInfos[index].Cost;
cellLayer[cell] = cost;
}
}
});
} }
CellCache GetCache(CPos cell) CellCache GetCache(CPos cell)
@@ -396,7 +423,9 @@ namespace OpenRA.Mods.Common.Traits
dirtyCells.Remove(cell); dirtyCells.Remove(cell);
} }
return blockingCache[cell]; var cache = cell.Layer == 0 ? blockingCache : customLayerBlockingCache[cell.Layer];
return cache[cell];
} }
void CellUpdated(CPos cell) void CellUpdated(CPos cell)
@@ -415,24 +444,28 @@ namespace OpenRA.Mods.Common.Traits
if (index != byte.MaxValue) if (index != byte.MaxValue)
cost = terrainInfos[index].Cost; cost = terrainInfos[index].Cost;
cellsCost[cell] = cost; var cache = cell.Layer == 0 ? cellsCost : customLayerCellsCost[cell.Layer];
cache[cell] = cost;
} }
void UpdateCellBlocking(CPos cell) void UpdateCellBlocking(CPos cell)
{ {
using (new PerfSample("locomotor_cache")) using (new PerfSample("locomotor_cache"))
{ {
var cache = cell.Layer == 0 ? blockingCache : customLayerBlockingCache[cell.Layer];
var actors = actorMap.GetActorsAt(cell); var actors = actorMap.GetActorsAt(cell);
if (!actors.Any()) if (!actors.Any())
{ {
blockingCache[cell] = new CellCache(default(LongBitSet<PlayerBitMask>), CellFlag.HasFreeSpace); cache[cell] = new CellCache(default(LongBitSet<PlayerBitMask>), CellFlag.HasFreeSpace);
return; return;
} }
if (sharesCell && actorMap.HasFreeSubCell(cell)) if (sharesCell && actorMap.HasFreeSubCell(cell))
{ {
blockingCache[cell] = new CellCache(default(LongBitSet<PlayerBitMask>), CellFlag.HasFreeSpace); cache[cell] = new CellCache(default(LongBitSet<PlayerBitMask>), CellFlag.HasFreeSpace);
return; return;
} }
@@ -474,7 +507,7 @@ namespace OpenRA.Mods.Common.Traits
cellBlockedPlayers = cellBlockedPlayers.Union(actorBlocksPlayers); cellBlockedPlayers = cellBlockedPlayers.Union(actorBlocksPlayers);
} }
blockingCache[cell] = new CellCache(cellBlockedPlayers, cellFlag, cellCrushablePlayers); cache[cell] = new CellCache(cellBlockedPlayers, cellFlag, cellCrushablePlayers);
} }
} }
} }