mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-28 13:24:16 +00:00
e4e17ffb13
## Description: Fix bug that made railroads disappear when switching to dark mode. ## 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 understand that submitting code with bugs that could have been caught through manual testing blocks releases and new features for all contributors ## Please put your Discord username so you can be contacted if a bug or regression is found: IngloriousTom
169 lines
4.8 KiB
TypeScript
169 lines
4.8 KiB
TypeScript
import { Colord } from "colord";
|
|
import { Theme } from "../../../core/configuration/Config";
|
|
import { PlayerID } from "../../../core/game/Game";
|
|
import { TileRef } from "../../../core/game/GameMap";
|
|
import {
|
|
GameUpdateType,
|
|
RailroadUpdate,
|
|
RailTile,
|
|
RailType,
|
|
} from "../../../core/game/GameUpdates";
|
|
import { GameView, PlayerView } from "../../../core/game/GameView";
|
|
import { Layer } from "./Layer";
|
|
import { getRailroadRects } from "./RailroadSprites";
|
|
|
|
type RailRef = {
|
|
tile: RailTile;
|
|
numOccurence: number;
|
|
lastOwnerId: PlayerID | null;
|
|
};
|
|
|
|
export class RailroadLayer implements Layer {
|
|
private canvas: HTMLCanvasElement;
|
|
private context: CanvasRenderingContext2D;
|
|
private theme: Theme;
|
|
// Save the number of railroads per tiles. Delete when it reaches 0
|
|
private existingRailroads = new Map<TileRef, RailRef>();
|
|
private nextRailIndexToCheck = 0;
|
|
private railTileList: TileRef[] = [];
|
|
|
|
constructor(private game: GameView) {
|
|
this.theme = game.config().theme();
|
|
}
|
|
|
|
shouldTransform(): boolean {
|
|
return true;
|
|
}
|
|
|
|
tick() {
|
|
const updates = this.game.updatesSinceLastTick();
|
|
const railUpdates =
|
|
updates !== null ? updates[GameUpdateType.RailroadEvent] : [];
|
|
for (const rail of railUpdates) {
|
|
this.handleRailroadRendering(rail);
|
|
}
|
|
}
|
|
|
|
updateRailColors() {
|
|
const maxTilesPerFrame = this.railTileList.length / 60;
|
|
let checked = 0;
|
|
|
|
while (checked < maxTilesPerFrame && this.railTileList.length > 0) {
|
|
const tile = this.railTileList[this.nextRailIndexToCheck];
|
|
const railRef = this.existingRailroads.get(tile);
|
|
if (railRef) {
|
|
const currentOwner = this.game.owner(tile)?.id() ?? null;
|
|
if (railRef.lastOwnerId !== currentOwner) {
|
|
railRef.lastOwnerId = currentOwner;
|
|
this.paintRail(railRef.tile);
|
|
}
|
|
}
|
|
|
|
this.nextRailIndexToCheck++;
|
|
if (this.nextRailIndexToCheck >= this.railTileList.length) {
|
|
this.nextRailIndexToCheck = 0;
|
|
}
|
|
checked++;
|
|
}
|
|
}
|
|
|
|
init() {
|
|
this.redraw();
|
|
}
|
|
|
|
redraw() {
|
|
this.canvas = document.createElement("canvas");
|
|
const context = this.canvas.getContext("2d", { alpha: true });
|
|
if (context === null) throw new Error("2d context not supported");
|
|
this.context = context;
|
|
|
|
// Enable smooth scaling
|
|
this.context.imageSmoothingEnabled = true;
|
|
this.context.imageSmoothingQuality = "high";
|
|
|
|
this.canvas.width = this.game.width() * 2;
|
|
this.canvas.height = this.game.height() * 2;
|
|
|
|
for (const [_, rail] of this.existingRailroads) {
|
|
this.paintRail(rail.tile);
|
|
}
|
|
}
|
|
|
|
renderLayer(context: CanvasRenderingContext2D) {
|
|
this.updateRailColors();
|
|
context.drawImage(
|
|
this.canvas,
|
|
-this.game.width() / 2,
|
|
-this.game.height() / 2,
|
|
this.game.width(),
|
|
this.game.height(),
|
|
);
|
|
}
|
|
|
|
private handleRailroadRendering(railUpdate: RailroadUpdate) {
|
|
for (const railRoad of railUpdate.railTiles) {
|
|
const x = this.game.x(railRoad.tile);
|
|
const y = this.game.y(railRoad.tile);
|
|
if (railUpdate.isActive) {
|
|
this.paintRailroad(railRoad);
|
|
} else {
|
|
this.clearRailroad(railRoad);
|
|
}
|
|
}
|
|
}
|
|
|
|
private paintRailroad(railRoad: RailTile) {
|
|
const currentOwner = this.game.owner(railRoad.tile)?.id() ?? null;
|
|
const railTile = this.existingRailroads.get(railRoad.tile);
|
|
|
|
if (railTile) {
|
|
railTile.numOccurence++;
|
|
railTile.tile = railRoad;
|
|
railTile.lastOwnerId = currentOwner;
|
|
} else {
|
|
this.existingRailroads.set(railRoad.tile, {
|
|
tile: railRoad,
|
|
numOccurence: 1,
|
|
lastOwnerId: currentOwner,
|
|
});
|
|
this.railTileList.push(railRoad.tile);
|
|
this.paintRail(railRoad);
|
|
}
|
|
}
|
|
|
|
private clearRailroad(railRoad: RailTile) {
|
|
const ref = this.existingRailroads.get(railRoad.tile);
|
|
if (ref) ref.numOccurence--;
|
|
|
|
if (!ref || ref.numOccurence <= 0) {
|
|
this.existingRailroads.delete(railRoad.tile);
|
|
this.railTileList = this.railTileList.filter((t) => t !== railRoad.tile);
|
|
this.context.clearRect(
|
|
this.game.x(railRoad.tile) * 2 - 1,
|
|
this.game.y(railRoad.tile) * 2 - 1,
|
|
3,
|
|
3,
|
|
);
|
|
}
|
|
}
|
|
|
|
paintRail(railRoad: RailTile) {
|
|
const x = this.game.x(railRoad.tile);
|
|
const y = this.game.y(railRoad.tile);
|
|
const owner = this.game.owner(railRoad.tile);
|
|
const recipient = owner.isPlayer() ? (owner as PlayerView) : null;
|
|
const color = recipient
|
|
? this.theme.railroadColor(recipient)
|
|
: new Colord({ r: 255, g: 255, b: 255, a: 1 });
|
|
this.context.fillStyle = color.toRgbString();
|
|
this.paintRailRects(x, y, railRoad.railType);
|
|
}
|
|
|
|
private paintRailRects(x: number, y: number, direction: RailType) {
|
|
const railRects = getRailroadRects(direction);
|
|
for (const [dx, dy, w, h] of railRects) {
|
|
this.context.fillRect(x * 2 + dx, y * 2 + dy, w, h);
|
|
}
|
|
}
|
|
}
|