Locomotor cache should handle custom layers
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user