From 39e48d9e8d5a0d8be0d4120e97b73aa1d94d1bc5 Mon Sep 17 00:00:00 2001 From: RoosterDragon Date: Mon, 19 Dec 2022 18:18:15 +0000 Subject: [PATCH] HPF is aware of map projection changes. An event is added to Map to indicate when the cell projection is changed. This is important as this can mean Map.Contains(CPos) could now return different results for the cell. The HierarchicalPathFinder is made aware of these changes so it can rebuild any out-of-date information. This fixes prevent a crash if a cell that was previously outside the map changes height and becomes inside the map. The local path search will explore the cell as it is inside the map - but if the HPF was unaware if had been updated, it will still consider the cell to be outside the map and unreachable, resulting in a crash. --- OpenRA.Game/Map/Map.cs | 10 ++++++++-- .../Pathfinder/HierarchicalPathFinder.cs | 12 ++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/OpenRA.Game/Map/Map.cs b/OpenRA.Game/Map/Map.cs index 333aeaffa9..9921589829 100644 --- a/OpenRA.Game/Map/Map.cs +++ b/OpenRA.Game/Map/Map.cs @@ -243,6 +243,8 @@ namespace OpenRA public CellRegion AllCells { get; private set; } public List AllEdgeCells { get; private set; } + public event Action CellProjectionChanged; + // Internal data readonly ModData modData; CellLayer cachedTerrainIndexes; @@ -336,11 +338,12 @@ namespace OpenRA Height = new CellLayer(Grid.Type, size); Ramp = new CellLayer(Grid.Type, size); Tiles.Clear(terrainInfo.DefaultTerrainTile); + if (Grid.MaximumTerrainHeight > 0) { - Height.CellEntryChanged += UpdateProjection; - Tiles.CellEntryChanged += UpdateProjection; Tiles.CellEntryChanged += UpdateRamp; + Tiles.CellEntryChanged += UpdateProjection; + Height.CellEntryChanged += UpdateProjection; } PostInit(); @@ -530,6 +533,7 @@ namespace OpenRA var inverse = inverseCellProjection[uv]; inverse.Clear(); inverse.Add(uv); + CellProjectionChanged?.Invoke(cell); return; } @@ -567,6 +571,8 @@ namespace OpenRA projectedHeight[temp] = height; } } + + CellProjectionChanged?.Invoke(cell); } byte ProjectedCellHeightInner(PPos puv) diff --git a/OpenRA.Mods.Common/Pathfinder/HierarchicalPathFinder.cs b/OpenRA.Mods.Common/Pathfinder/HierarchicalPathFinder.cs index 7ba38b5692..885faed296 100644 --- a/OpenRA.Mods.Common/Pathfinder/HierarchicalPathFinder.cs +++ b/OpenRA.Mods.Common/Pathfinder/HierarchicalPathFinder.cs @@ -281,6 +281,10 @@ namespace OpenRA.Mods.Common.Pathfinder // When we build the cost table, it depends on the movement costs of the cells at that time. // When this changes, we must update the cost table. locomotor.CellCostChanged += RequireCostRefreshInCell; + + // If the map projection changes, the result of Map.Contains(CPos) may change. + // We need to rebuild grids to account for this possibility. + this.world.Map.CellProjectionChanged += RequireProjectionRefreshInCell; } public ( @@ -619,6 +623,14 @@ namespace OpenRA.Mods.Common.Pathfinder } } + /// + /// When map projection changes for a cell, marks the grid it belongs to as out of date. + /// + void RequireProjectionRefreshInCell(CPos cell) + { + dirtyGridIndexes.Add(GridIndex(cell)); + } + /// /// defines immovability based on the mobile trait. The blocking rules /// in allow units to