mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-21 12:25:10 +00:00
fix alternate view perf regression (#1734)
## Description: Have the diplomacy view only draw border, not interior tiles. Drawing the interior tiles is a very expensive operation and caused main thread cpu usage to spike to close to 100%. Also change the color scheme so that neutral players are gray, and embargoed players are red. I think long term embargo should be more of a war state. Added embargo update and cleaned it up to use Player instead of PlayerID. There's no reason to pass ids around. <img width="493" height="466" alt="Screenshot 2025-08-07 at 6 25 55 PM" src="https://github.com/user-attachments/assets/75552036-42f1-4103-9537-234ff1c0464f" /> ## 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 - [x] I have read and accepted the CLA agreement (only required once). ## Please put your Discord username so you can be contacted if a bug or regression is found: evan
This commit is contained in:
@@ -531,17 +531,13 @@ export class NameLayer implements Layer {
|
||||
|
||||
// Embargo icon
|
||||
let existingEmbargo = iconsDiv.querySelector('[data-icon="embargo"]');
|
||||
const hasEmbargo =
|
||||
myPlayer &&
|
||||
(render.player.hasEmbargoAgainst(myPlayer) ||
|
||||
myPlayer.hasEmbargoAgainst(render.player));
|
||||
const isThemeEmbargoIcon =
|
||||
existingEmbargo?.getAttribute("dark-mode") === isDarkMode.toString();
|
||||
const embargoIconImageSrc = isDarkMode
|
||||
? this.embargoWhiteIconImage.src
|
||||
: this.embargoBlackIconImage.src;
|
||||
|
||||
if (myPlayer && hasEmbargo) {
|
||||
if (myPlayer?.hasEmbargo(render.player)) {
|
||||
// Create new icon to match theme
|
||||
if (existingEmbargo && !isThemeEmbargoIcon) {
|
||||
existingEmbargo.remove();
|
||||
|
||||
@@ -104,10 +104,8 @@ export class TerritoryLayer implements Layer {
|
||||
if (myPlayer) {
|
||||
updates?.[GameUpdateType.BrokeAlliance]?.forEach((update) => {
|
||||
const territory = this.game.playerBySmallID(update.betrayedID);
|
||||
console.log("betrayedID", update.betrayedID);
|
||||
console.log("territory", territory);
|
||||
if (territory && territory instanceof PlayerView) {
|
||||
this.redrawTerritory(territory);
|
||||
this.redrawBorder(territory);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -123,10 +121,23 @@ export class TerritoryLayer implements Layer {
|
||||
: update.request.requestorID;
|
||||
const territory = this.game.playerBySmallID(territoryId);
|
||||
if (territory && territory instanceof PlayerView) {
|
||||
this.redrawTerritory(territory);
|
||||
this.redrawBorder(territory);
|
||||
}
|
||||
}
|
||||
});
|
||||
updates?.[GameUpdateType.EmbargoEvent]?.forEach((update) => {
|
||||
const player = this.game.playerBySmallID(update.playerID) as PlayerView;
|
||||
const embargoed = this.game.playerBySmallID(
|
||||
update.embargoedID,
|
||||
) as PlayerView;
|
||||
|
||||
if (
|
||||
player.id() === myPlayer?.id() ||
|
||||
embargoed.id() === myPlayer?.id()
|
||||
) {
|
||||
this.redrawBorder(player, embargoed);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const focusedPlayer = this.game.focusedPlayer();
|
||||
@@ -237,7 +248,7 @@ export class TerritoryLayer implements Layer {
|
||||
if (this.highlightedTerritory) {
|
||||
territories.push(this.highlightedTerritory);
|
||||
}
|
||||
this.redrawTerritory(territories);
|
||||
this.redrawBorder(...territories);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,16 +309,15 @@ export class TerritoryLayer implements Layer {
|
||||
});
|
||||
}
|
||||
|
||||
redrawTerritory(territory: PlayerView | PlayerView[]) {
|
||||
const territories = Array.isArray(territory) ? territory : [territory];
|
||||
const territorySet = new Set(territories);
|
||||
|
||||
this.game.forEachTile((t) => {
|
||||
const owner = this.game.owner(t) as PlayerView;
|
||||
if (territorySet.has(owner)) {
|
||||
this.paintTerritory(t);
|
||||
}
|
||||
});
|
||||
redrawBorder(...players: PlayerView[]) {
|
||||
return Promise.all(
|
||||
players.map(async (player) => {
|
||||
const tiles = await player.borderTiles();
|
||||
tiles.borderTiles.forEach((tile: TileRef) => {
|
||||
this.paintTerritory(tile, true);
|
||||
});
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
initImageData() {
|
||||
@@ -419,12 +429,7 @@ export class TerritoryLayer implements Layer {
|
||||
if (this.game.isBorder(tile)) {
|
||||
const playerIsFocused = owner && this.game.focusedPlayer() === owner;
|
||||
if (myPlayer) {
|
||||
let alternativeColor = owner.isFriendly(myPlayer)
|
||||
? this.theme.allyColor()
|
||||
: this.theme.enemyColor();
|
||||
if (owner.smallID() === myPlayer.smallID()) {
|
||||
alternativeColor = this.theme.selfColor();
|
||||
}
|
||||
const alternativeColor = this.alternateViewColor(owner);
|
||||
this.paintTile(this.alternativeImageData, tile, alternativeColor, 255);
|
||||
}
|
||||
if (
|
||||
@@ -449,25 +454,12 @@ export class TerritoryLayer implements Layer {
|
||||
this.paintTile(this.imageData, tile, useBorderColor, 255);
|
||||
}
|
||||
} else {
|
||||
// Interior tiles
|
||||
const pattern = owner.cosmetics.pattern;
|
||||
const patternsEnabled = this.cachedTerritoryPatternsEnabled ?? false;
|
||||
|
||||
if (myPlayer) {
|
||||
let alternativeColor = owner.isFriendly(myPlayer)
|
||||
? this.theme.allyColor()
|
||||
: this.theme.enemyColor();
|
||||
// If the current player is the owner
|
||||
if (owner.smallID() === myPlayer.smallID()) {
|
||||
alternativeColor = this.theme.selfColor();
|
||||
}
|
||||
// If the tile is on a ally territory, use the ally color
|
||||
this.paintTile(
|
||||
this.alternativeImageData,
|
||||
tile,
|
||||
alternativeColor,
|
||||
isHighlighted ? 150 : 60,
|
||||
);
|
||||
}
|
||||
// Alternative view only shows borders.
|
||||
this.clearAlternativeTile(tile);
|
||||
|
||||
if (pattern === undefined || patternsEnabled === false) {
|
||||
this.paintTile(
|
||||
@@ -490,6 +482,28 @@ export class TerritoryLayer implements Layer {
|
||||
}
|
||||
}
|
||||
|
||||
alternateViewColor(other: PlayerView): Colord {
|
||||
const myPlayer = this.game.myPlayer();
|
||||
if (!myPlayer) {
|
||||
return this.theme.neutralColor();
|
||||
}
|
||||
if (other.smallID() === myPlayer.smallID()) {
|
||||
return this.theme.selfColor();
|
||||
}
|
||||
if (other.isFriendly(myPlayer)) {
|
||||
return this.theme.allyColor();
|
||||
}
|
||||
if (!other.hasEmbargo(myPlayer)) {
|
||||
return this.theme.neutralColor();
|
||||
}
|
||||
return this.theme.enemyColor();
|
||||
}
|
||||
|
||||
paintAlternateViewTile(tile: TileRef, other: PlayerView) {
|
||||
const color = this.alternateViewColor(other);
|
||||
this.paintTile(this.alternativeImageData, tile, color, 255);
|
||||
}
|
||||
|
||||
paintTile(imageData: ImageData, tile: TileRef, color: Colord, alpha: number) {
|
||||
const offset = tile * 4;
|
||||
imageData.data[offset] = color.rgba.r;
|
||||
@@ -504,6 +518,11 @@ export class TerritoryLayer implements Layer {
|
||||
this.alternativeImageData.data[offset + 3] = 0; // Set alpha to 0 (fully transparent)
|
||||
}
|
||||
|
||||
clearAlternativeTile(tile: TileRef) {
|
||||
const offset = tile * 4;
|
||||
this.alternativeImageData.data[offset + 3] = 0; // Set alpha to 0 (fully transparent)
|
||||
}
|
||||
|
||||
enqueueTile(tile: TileRef) {
|
||||
this.tileToRenderQueue.push({
|
||||
tile: tile,
|
||||
|
||||
Reference in New Issue
Block a user