From 7b785ea79aaa65fd09778363236082bec2575052 Mon Sep 17 00:00:00 2001 From: Mattia Migliorini Date: Thu, 26 Feb 2026 04:12:58 +0100 Subject: [PATCH] Fix alliance renewal prompt incorrectly dismissed for both players (#3297) ## Description: NOTE: Applies to current main / beta version. Needs to be included in v30. When a player clicked "Renew Alliance", the `AllianceExtensionUpdate` broadcast caused both players' renewal prompts to be removed, even the one who hadn't yet acted. This happened because `onAllianceExtensionEvent` called `removeAllianceRenewalEvents` unconditionally on every client. This PR fixes the behavior by calling `removeAllianceRenewalEvents` only for the player that executed the action. ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: deshack_82603 --- src/client/graphics/layers/EventsDisplay.ts | 2 + .../layers/EventDisplayAlliance.test.ts | 68 +++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/src/client/graphics/layers/EventsDisplay.ts b/src/client/graphics/layers/EventsDisplay.ts index 1d39d7af9..f36de2c5e 100644 --- a/src/client/graphics/layers/EventsDisplay.ts +++ b/src/client/graphics/layers/EventsDisplay.ts @@ -626,6 +626,8 @@ export class EventsDisplay extends LitElement implements Layer { } private onAllianceExtensionEvent(update: AllianceExtensionUpdate) { + const myPlayer = this.game.myPlayer(); + if (!myPlayer || myPlayer.smallID() !== update.playerID) return; this.removeAllianceRenewalEvents(update.allianceID); this.requestUpdate(); } diff --git a/tests/client/graphics/layers/EventDisplayAlliance.test.ts b/tests/client/graphics/layers/EventDisplayAlliance.test.ts index 7eccc0136..82f4945eb 100644 --- a/tests/client/graphics/layers/EventDisplayAlliance.test.ts +++ b/tests/client/graphics/layers/EventDisplayAlliance.test.ts @@ -1,3 +1,5 @@ +import { GameUpdateType } from "../../../../src/core/game/GameUpdates"; + vi.mock("lit", () => ({ html: () => {}, LitElement: class {}, @@ -102,6 +104,72 @@ describe("EventsDisplay - alliance renewal cleanup (allianceID based)", () => { expect(remaining[0].allianceID).toBe(allianceCD); }); + test("onAllianceExtensionEvent removes renewal when playerID matches myPlayer", () => { + const display = new EventsDisplay(); + + const allianceID = 42; + const mySmallID = 7; + + (display as any).game = { + myPlayer: () => ({ smallID: () => mySmallID }), + }; + (display as any).requestUpdate = () => {}; + (display as any).events = [makeRenewal(allianceID, mySmallID)]; + + (display as any).onAllianceExtensionEvent({ + type: GameUpdateType.AllianceExtension, + playerID: mySmallID, + allianceID, + }); + + const remaining = (display as any).events; + expect(remaining.some((e: any) => e.allianceID === allianceID)).toBe(false); + }); + + test("onAllianceExtensionEvent keeps renewal when playerID does not match myPlayer", () => { + const display = new EventsDisplay(); + + const allianceID = 42; + const mySmallID = 7; + const otherSmallID = 9; + + (display as any).game = { + myPlayer: () => ({ smallID: () => mySmallID }), + }; + (display as any).requestUpdate = () => {}; + (display as any).events = [makeRenewal(allianceID, mySmallID)]; + + (display as any).onAllianceExtensionEvent({ + type: "AllianceExtension", + playerID: otherSmallID, + allianceID, + }); + + const remaining = (display as any).events; + expect(remaining.some((e: any) => e.allianceID === allianceID)).toBe(true); + }); + + test("onAllianceExtensionEvent keeps renewal when myPlayer is null", () => { + const display = new EventsDisplay(); + + const allianceID = 42; + + (display as any).game = { + myPlayer: () => null, + }; + (display as any).requestUpdate = () => {}; + (display as any).events = [makeRenewal(allianceID, 1)]; + + (display as any).onAllianceExtensionEvent({ + type: "AllianceExtension", + playerID: 1, + allianceID, + }); + + const remaining = (display as any).events; + expect(remaining.some((e: any) => e.allianceID === allianceID)).toBe(true); + }); + test("does not affect non-RENEW_ALLIANCE events", () => { const display = new EventsDisplay();