Add territory renderer fallback controller

This commit is contained in:
scamiv
2026-05-26 22:43:23 +02:00
parent d0be9e26d5
commit d8841fd1ed
19 changed files with 7519 additions and 369 deletions
+1
View File
@@ -205,6 +205,7 @@ export interface Theme {
allyColor(): Colord;
neutralColor(): Colord;
enemyColor(): Colord;
playerHighlightColor(): Colord;
spawnHighlightColor(): Colord;
spawnHighlightSelfColor(): Colord;
spawnHighlightTeamColor(): Colord;
+5
View File
@@ -35,6 +35,8 @@ export class PastelTheme implements Theme {
/** Alternate View colors for enemies, red */
private _enemyColor = colord("rgb(255,0,0)");
/** Hover highlight color for player territories */
private _playerHighlightColor = colord("rgb(221, 221, 221)");
/** Default spawn highlight colors for other players in FFA, yellow */
private _spawnHighlightColor = colord("rgb(255,213,79)");
/** Added non-default spawn highlight colors for self, full white */
@@ -209,6 +211,9 @@ export class PastelTheme implements Theme {
enemyColor(): Colord {
return this._enemyColor;
}
playerHighlightColor(): Colord {
return this._playerHighlightColor;
}
spawnHighlightColor(): Colord {
return this._spawnHighlightColor;
@@ -8,6 +8,7 @@ export class PastelThemeDark extends PastelTheme {
private darkWater = colord("rgb(14,11,30)");
private darkShorelineWater = colord("rgb(50,50,50)");
private darkPlayerHighlight = colord("rgb(99, 42, 42)");
// | Terrain Type | Magnitude | Base Color Logic | Visual Description |
// | :---------------- | :-------- | :---------------------------------------------- | :-------------------- |
@@ -59,4 +60,8 @@ export class PastelThemeDark extends PastelTheme {
});
}
}
playerHighlightColor(): Colord {
return this.darkPlayerHighlight;
}
}
+56
View File
@@ -692,6 +692,7 @@ export class GameImpl implements Game {
owner._lastTileChange = this._ticks;
this.updateBorders(tile);
this._map.setFallout(tile, false);
this.updateDefendedStateForTileChange(tile, owner);
this.recordTileUpdate(tile);
}
@@ -710,6 +711,9 @@ export class GameImpl implements Game {
this._map.setOwnerID(tile, 0);
this.updateBorders(tile);
if (this._map.isDefended(tile)) {
this._map.setDefended(tile, false);
}
this.recordTileUpdate(tile);
}
@@ -971,9 +975,18 @@ export class GameImpl implements Game {
}
}
updateUnitTile(u: Unit) {
if (u.type() === UnitType.DefensePost) {
this.updateDefendedStateForDefensePost(u.tile(), u.owner() as PlayerImpl);
}
this.unitGrid.updateUnitCell(u);
}
refreshDefensePostDefendedState(u: Unit) {
if (u.type() === UnitType.DefensePost) {
this.updateDefendedStateForDefensePost(u.tile(), u.owner() as PlayerImpl);
}
}
hasUnitNearby(
tile: TileRef,
searchRange: number,
@@ -1254,6 +1267,49 @@ export class GameImpl implements Game {
gold: goldCaptured,
});
}
private updateDefendedStateForDefensePost(
center: TileRef,
owner: PlayerImpl,
) {
const range = this.config().defensePostRange();
const rangeSq = range * range;
for (const tile of owner._borderTiles) {
if (this._map.euclideanDistSquared(center, tile) <= rangeSq) {
const wasDefended = this._map.isDefended(tile);
const isDefended = this.unitGrid.hasUnitNearby(
tile,
range,
UnitType.DefensePost,
owner.id(),
);
if (wasDefended !== isDefended) {
this._map.setDefended(tile, isDefended);
this.recordTileUpdate(tile);
}
}
}
}
private updateDefendedStateForTileChange(tile: TileRef, owner: PlayerImpl) {
const wasDefended = this._map.isDefended(tile);
const isDefended = this.unitGrid.hasUnitNearby(
tile,
this.config().defensePostRange(),
UnitType.DefensePost,
owner.id(),
);
if (wasDefended !== isDefended) {
this._map.setDefended(tile, isDefended);
}
if (
this.unitGrid.hasUnitNearby(tile, 0, UnitType.DefensePost, owner.id())
) {
this.updateDefendedStateForDefensePost(tile, owner);
}
}
}
// Or a more dynamic approach that will catch new enum values:
+23
View File
@@ -669,6 +669,11 @@ export class GameView implements GameMap {
private _units = new Map<number, UnitView>();
private updatedTiles: TileRef[] = [];
private updatedTerrainTiles: TileRef[] = [];
private updatedOwnerChanges: Array<{
tile: TileRef;
previousOwner: number;
newOwner: number;
}> = [];
private _myPlayer: PlayerView | null = null;
@@ -780,15 +785,25 @@ export class GameView implements GameMap {
this.updatedTiles = [];
this.updatedTerrainTiles = [];
this.updatedOwnerChanges = [];
const packed = this.lastUpdate.packedTileUpdates;
for (let i = 0; i + 1 < packed.length; i += 2) {
const tile = packed[i];
const state = packed[i + 1];
const previousOwner = this._map.ownerID(tile);
const terrainChanged = this.updateTile(tile, state);
this.updatedTiles.push(tile);
if (terrainChanged) {
this.updatedTerrainTiles.push(tile);
}
const newOwner = this._map.ownerID(tile);
if (previousOwner !== newOwner) {
this.updatedOwnerChanges.push({
tile,
previousOwner,
newOwner,
});
}
}
if (gu.packedMotionPlans) {
@@ -1107,6 +1122,14 @@ export class GameView implements GameMap {
return this.updatedTerrainTiles;
}
recentlyUpdatedOwnerTiles(): Array<{
tile: TileRef;
previousOwner: number;
newOwner: number;
}> {
return this.updatedOwnerChanges;
}
nearbyUnits(
tile: TileRef,
searchRange: number,
+3
View File
@@ -433,6 +433,9 @@ export class UnitImpl implements Unit {
setUnderConstruction(underConstruction: boolean): void {
if (this._underConstruction !== underConstruction) {
this._underConstruction = underConstruction;
if (this._type === UnitType.DefensePost) {
this.mg.refreshDefensePostDefendedState(this);
}
this.mg.addUpdate(this.toUpdate());
}
}
+28 -1
View File
@@ -47,6 +47,12 @@ export const COLOR_KEY = "settings.territoryColor";
export const DARK_MODE_KEY = "settings.darkMode";
export const PERFORMANCE_OVERLAY_KEY = "settings.performanceOverlay";
export const KEYBINDS_KEY = "settings.keybinds";
export const TERRITORY_RENDERER_KEY = "settings.territoryRenderer";
export type TerritoryRendererPreference =
| "auto"
| "classic"
| "webgl"
| "webgpu";
export class UserSettings {
private static cache = new Map<string, string | null>();
@@ -154,7 +160,7 @@ export class UserSettings {
}
webgpuDebug(): boolean {
return this.get("settings.webgpuDebug", true);
return this.get("settings.webgpuDebug", false);
}
alertFrame() {
@@ -197,6 +203,27 @@ export class UserSettings {
return this.getInt("settings.territoryBorderMode", 1);
}
territoryRenderer(): TerritoryRendererPreference {
const value = this.getString(TERRITORY_RENDERER_KEY, "auto");
if (
value === "auto" ||
value === "classic" ||
value === "webgl" ||
value === "webgpu"
) {
return value;
}
return "auto";
}
setTerritoryRenderer(value: string): void {
const renderer =
value === "classic" || value === "webgl" || value === "webgpu"
? value
: "auto";
this.setString(TERRITORY_RENDERER_KEY, renderer);
}
toggleAttackingTroopsOverlay() {
this.setBool(
"settings.attackingTroopsOverlay",