1
1
forked from 0ad/0ad

Fix UpdateComponents logic for pathfinding following d592bf9cb6

Following d592bf9cb6, paths requested at turn N were set-up to be
computed between the end of turn N and the start of turn N+1 (which
would ultimately allow threading this computation), via calls to
'StartProcessingMoves' and 'FetchAsyncResultsAndSendMessages'.

However, the call to UpdateGrid() remained at the start of turn N+1,
between the 'start' and 'fetch' calls. Since all paths are currently
computed on the 'start' call, this means all paths are computed on a
(possibly) dirty pathfinder grid.
In particular, this leads to OOS on rejoin since the rejoiner will
recompute the grid before computing the outstanding paths.

This would also obviously be buggy in a threaded environment, since some
paths might be computed on the fresh and some on the dirty grid.

Finally, MT_TurnStart was sent before the paths were computed, which
might lead to further pathfinder grid changes (not a crashing problem
without threading, but still conceptually odd). The 'fetch' call is thus
moved before it.
This thus fixes d592bf9cb6/D1918, after 92ad6a61fa already fixed a first
issue.

Since the grid is now only updated at the end of a turn, we need to
ensure that it is correct on Turn 0, thus the pathfinder recomputes it
on InitGame.

Refs D14

Reported by: Itms
Fixes #5851

Differential Revision: https://code.wildfiregames.com/D3064
This was SVN commit r24142.
This commit is contained in:
wraitii 2020-11-08 08:58:19 +00:00
parent 9d53bed0bd
commit ad7ac8d595
4 changed files with 11 additions and 9 deletions

View File

@ -72,6 +72,9 @@ function InitGame(settings)
if (settings.WorldPopulationCap)
Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).SetMaxWorldPopulation(settings.WorldPopulationCap);
// Update the grid with all entities created for the map init.
Engine.QueryInterface(SYSTEM_ENTITY, IID_Pathfinder).UpdateGrid();
// Map or player data (handicap...) dependent initialisations of components (i.e. garrisoned units).
Engine.BroadcastMessage(MT_InitGame, {});

View File

@ -531,19 +531,16 @@ void CSimulation2Impl::UpdateComponents(CSimContext& simContext, fixed turnLengt
CComponentManager& componentManager = simContext.GetComponentManager();
CmpPtr<ICmpPathfinder> cmpPathfinder(simContext, SYSTEM_ENTITY);
if (cmpPathfinder)
cmpPathfinder->FetchAsyncResultsAndSendMessages();
{
PROFILE2("Sim - Update Start");
CMessageTurnStart msgTurnStart;
componentManager.BroadcastMessage(msgTurnStart);
}
CmpPtr<ICmpPathfinder> cmpPathfinder(simContext, SYSTEM_ENTITY);
if (cmpPathfinder)
{
cmpPathfinder->FetchAsyncResultsAndSendMessages();
cmpPathfinder->UpdateGrid();
}
// Push AI commands onto the queue before we use them
CmpPtr<ICmpAIManager> cmpAIManager(simContext, SYSTEM_ENTITY);
if (cmpAIManager)
@ -594,7 +591,10 @@ void CSimulation2Impl::UpdateComponents(CSimContext& simContext, fixed turnLengt
// Process all remaining moves
if (cmpPathfinder)
{
cmpPathfinder->UpdateGrid();
cmpPathfinder->StartProcessingMoves(false);
}
}
void CSimulation2Impl::Interpolate(float simFrameLength, float frameOffset, float realFrameLength)

View File

@ -89,12 +89,10 @@ public:
static void ClassInit(CComponentManager& componentManager)
{
componentManager.SubscribeToMessageType(MT_Deserialized);
componentManager.SubscribeToMessageType(MT_Update);
componentManager.SubscribeToMessageType(MT_RenderSubmit); // for debug overlays
componentManager.SubscribeToMessageType(MT_TerrainChanged);
componentManager.SubscribeToMessageType(MT_WaterChanged);
componentManager.SubscribeToMessageType(MT_ObstructionMapShapeChanged);
componentManager.SubscribeToMessageType(MT_TurnStart);
}
~CCmpPathfinder();

View File

@ -25,4 +25,5 @@ BEGIN_INTERFACE_WRAPPER(Pathfinder)
DEFINE_INTERFACE_METHOD_1("SetDebugOverlay", void, ICmpPathfinder, SetDebugOverlay, bool)
DEFINE_INTERFACE_METHOD_1("SetHierDebugOverlay", void, ICmpPathfinder, SetHierDebugOverlay, bool)
DEFINE_INTERFACE_METHOD_CONST_1("GetPassabilityClass", pass_class_t, ICmpPathfinder, GetPassabilityClass, std::string)
DEFINE_INTERFACE_METHOD_0("UpdateGrid", void, ICmpPathfinder, UpdateGrid)
END_INTERFACE_WRAPPER(Pathfinder)