From a406660e78451ee69331f309f045a9880b3b7ebb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lancelot=20de=20Ferri=C3=A8re?= Date: Mon, 10 Aug 2026 09:15:14 +0200 Subject: [PATCH] Fix a ModifiersManager bug when changing player entities The cache invalidation was incorrectly using forEach, which failed to invalidate the cache. This never actually caused a bug because the game currently does not silently swap active player entities. --- .../simulation/components/ModifiersManager.js | 3 +- .../components/tests/test_ModifiersManager.js | 49 +++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/binaries/data/mods/public/simulation/components/ModifiersManager.js b/binaries/data/mods/public/simulation/components/ModifiersManager.js index fe58c301a7..dfdd11292d 100644 --- a/binaries/data/mods/public/simulation/components/ModifiersManager.js +++ b/binaries/data/mods/public/simulation/components/ModifiersManager.js @@ -198,7 +198,8 @@ ModifiersManager.prototype.OnGlobalPlayerEntityChanged = function(msg) if (msg.from != INVALID_PLAYER && this.playerEntitiesCached.has(msg.from)) { - this.playerEntitiesCached.get(msg.from).forEach(propName => this.InvalidateCache(propName, msg.from)); + const playerCache = this.playerEntitiesCached.get(msg.from); + playerCache.forEach((_, propName) => this.InvalidateCache(propName, msg.from, playerCache)); this.playerEntitiesCached.delete(msg.from); } }; diff --git a/binaries/data/mods/public/simulation/components/tests/test_ModifiersManager.js b/binaries/data/mods/public/simulation/components/tests/test_ModifiersManager.js index bfc4ef644b..c7f46edf01 100644 --- a/binaries/data/mods/public/simulation/components/tests/test_ModifiersManager.js +++ b/binaries/data/mods/public/simulation/components/tests/test_ModifiersManager.js @@ -248,3 +248,52 @@ TS_ASSERT_EQUALS(ApplyValueModificationsToEntity("Test_D", 10, 5), 16); Engine.PostMessage = oldPostMessage; Engine.BroadcastMessage = oldBroadcastMessage; })(); + +(function Test_PlayerEntityChangeInvalidatesCachedEntities() +{ + const PLAYER_ID = 1; + const OLD_PLAYER_ENTITY = 40; + const NEW_PLAYER_ENTITY = 41; + const TEST_ENTITY = 42; + const PROPERTY_NAME = "Test_PlayerEntityChange"; + + let playerEntity = OLD_PLAYER_ENTITY; + AddMock(SYSTEM_ENTITY, IID_PlayerManager, { + "GetPlayerByID": () => playerEntity + }); + AddMock(OLD_PLAYER_ENTITY, IID_Player, { + "GetPlayerID": () => PLAYER_ID + }); + AddMock(NEW_PLAYER_ENTITY, IID_Player, { + "GetPlayerID": () => PLAYER_ID + }); + AddMock(TEST_ENTITY, IID_Ownership, { + "GetOwner": () => PLAYER_ID + }); + AddMock(TEST_ENTITY, IID_Identity, { + "GetClassesList": () => "Unit" + }); + + const cmp = ConstructComponent(SYSTEM_ENTITY, "ModifiersManager", {}); + cmp.Init(); + cmp.OnGlobalPlayerEntityChanged({ + "player": PLAYER_ID, + "from": INVALID_ENTITY, + "to": OLD_PLAYER_ENTITY + }); + cmp.AddModifier(PROPERTY_NAME, "old player modifier", [{ + "affects": ["Unit"], + "add": 10 + }], OLD_PLAYER_ENTITY); + + TS_ASSERT_EQUALS(cmp.ApplyModifiers(PROPERTY_NAME, 5, TEST_ENTITY), 15); + + playerEntity = NEW_PLAYER_ENTITY; + cmp.OnGlobalPlayerEntityChanged({ + "player": PLAYER_ID, + "from": OLD_PLAYER_ENTITY, + "to": NEW_PLAYER_ENTITY + }); + + TS_ASSERT_EQUALS(cmp.ApplyModifiers(PROPERTY_NAME, 5, TEST_ENTITY), 5); +})();