Merge branch 'main' into patterned-territory

This commit is contained in:
Aotumuri
2025-05-31 21:09:00 +09:00
committed by GitHub
15 changed files with 107 additions and 87 deletions
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 KiB

+6 -6
View File
@@ -187,7 +187,7 @@
"coordinates": [1254, 899],
"name": "Slovak Republic",
"strength": 3,
"flag": "SK"
"flag": "sk"
},
{
"coordinates": [1002, 1061],
@@ -244,7 +244,7 @@
"flag": "gb-sct"
},
{
"coordinates": [2239, 3215],
"coordinates": [2300, 510],
"name": "USSR",
"strength": 3,
"flag": "ussr"
@@ -259,7 +259,7 @@
"coordinates": [1522, 48],
"name": "Polar Bears",
"strength": 2,
"flag": "polar_bear"
"flag": "polar_bears"
},
{
"coordinates": [821, 628],
@@ -280,7 +280,7 @@
"flag": "eg"
},
{
"coordinates": [1188, 1612],
"coordinates": [1115, 1650],
"name": "State of Libya",
"strength": 1,
"flag": "ly"
@@ -289,13 +289,13 @@
"coordinates": [1919, 1608],
"name": "Hashemite Kingdom of Jordan",
"strength": 1,
"flag": "hu"
"flag": "jo"
},
{
"coordinates": [1898, 1535],
"name": "Lebanese Republic",
"strength": 1,
"flag": "hu"
"flag": "lb"
}
]
}
+8 -8
View File
@@ -19,7 +19,7 @@
"coordinates": [1334, 537],
"name": "Duchy of Aquitaine",
"strength": 2,
"flag": "aquitane"
"flag": "aquitaine"
},
{
"coordinates": [2115, 684],
@@ -31,7 +31,7 @@
"coordinates": [1207, 763],
"name": "The Basque",
"strength": 3,
"flag": ""
"flag": "es-pv"
},
{
"coordinates": [1281, 1142],
@@ -49,7 +49,7 @@
"coordinates": [561, 764],
"name": "Kingdom of Galicia",
"strength": 2,
"flag": "galicia"
"flag": "es-ga"
},
{
"coordinates": [1004, 1436],
@@ -115,13 +115,13 @@
"coordinates": [1755, 1130],
"name": "The Old Ones",
"strength": 3,
"flag": "nuragic"
"flag": "neuragic_empire"
},
{
"coordinates": [2097, 1670],
"name": "Jesuit Monks",
"name": "Tamazgha",
"strength": 2,
"flag": ""
"flag": "Amazigh flag"
},
{
"coordinates": [979, 1013],
@@ -151,7 +151,7 @@
"coordinates": [1017, 180],
"name": "Kingdom of Brittany",
"strength": 2,
"flag": "britanny"
"flag": "brittany"
},
{
"coordinates": [2072, 567],
@@ -175,7 +175,7 @@
"coordinates": [1475, 1657],
"name": "French Foreign Legion",
"strength": 3,
"flag": "french_foreign_legion"
"flag": "French foreign legion"
},
{
"coordinates": [1685, 417],
+3 -3
View File
@@ -4,7 +4,7 @@
"height": 1646,
"nations": [
{
"coordinates": [1151, 709],
"coordinates": [1150, 660],
"name": "Hokkaido",
"strength": 1,
"flag": "jp"
@@ -31,7 +31,7 @@
"coordinates": [1162, 154],
"name": "Sakhalin",
"strength": 2,
"flag": ""
"flag": "Sakhalin"
},
{
"coordinates": [571, 1116],
@@ -40,7 +40,7 @@
"flag": "jp"
},
{
"coordinates": [8612, 1183],
"coordinates": [595, 1190],
"name": "Shikoku",
"strength": 2,
"flag": "jp"
+1 -1
View File
@@ -13,7 +13,7 @@
"coordinates": [122, 750],
"name": "USSR",
"strength": 2,
"flag": ""
"flag": "ussr"
},
{
"coordinates": [1232, 735],
+10 -10
View File
@@ -4,37 +4,37 @@
"height": 1448,
"nations": [
{
"coordinates": [1693, 1045],
"coordinates": [1625, 1040],
"name": "Florida",
"strength": 3,
"flag": "Florida"
},
{
"coordinates": [1001, 427],
"coordinates": [1010, 435],
"name": "Canada",
"strength": 2,
"flag": "ca"
},
{
"coordinates": [1364, 1179],
"coordinates": [1250, 1130],
"name": "Mexico",
"strength": 2,
"flag": "mx"
},
{
"coordinates": [1556, 1295],
"coordinates": [1460, 1275],
"name": "Guatemala",
"strength": 1,
"flag": "gt"
},
{
"coordinates": [1612, 1289],
"coordinates": [1530, 1290],
"name": "Honduras",
"strength": 1,
"flag": "hn"
},
{
"coordinates": [1642, 1348],
"coordinates": [1570, 1350],
"name": "Nicaragua",
"strength": 1,
"flag": "ni"
@@ -58,7 +58,7 @@
"flag": "ve"
},
{
"coordinates": [1775, 1183],
"coordinates": [1725, 1180],
"name": "Cuba",
"strength": 1,
"flag": "cu"
@@ -94,7 +94,7 @@
"flag": "Georgia_US"
},
{
"coordinates": [420, 1209],
"coordinates": [250, 1200],
"name": "Hawaii",
"strength": 1,
"flag": "Hawaii"
@@ -283,10 +283,10 @@
"coordinates": [1189, 240],
"name": "Polar Bears",
"strength": 3,
"flag": "polar_bear"
"flag": "polar_bears"
},
{
"coordinates": [1480, 343],
"coordinates": [1480, 350],
"name": "Frost Giants",
"strength": 3,
"flag": "frost_giant"
+3 -3
View File
@@ -1,7 +1,7 @@
{
"name": "Americas",
"width": 1746,
"height": 2380,
"height": 2378,
"nations": [
{
"coordinates": [438, 58],
@@ -94,7 +94,7 @@
"flag": "gf"
},
{
"coordinates": [801, 242],
"coordinates": [800, 410],
"name": "Guyana",
"strength": 1,
"flag": "gy"
@@ -133,7 +133,7 @@
"coordinates": [1270, 1035],
"name": "The Biggest Snakes",
"strength": 3,
"flag": ""
"flag": "Aztec Empire"
},
{
"coordinates": [894, 693],
+1 -1
View File
@@ -203,8 +203,8 @@ class Client {
logoutDiscordButton.hidden = true;
return;
}
// TODO: Update the page for logged in user
loginDiscordButton.translationKey = "main.logged_in";
loginDiscordButton.hidden = true;
const { user, player } = userMeResponse;
TerritoryModal.onUserMe(userMeResponse);
});
+1 -1
View File
@@ -47,7 +47,7 @@ export class UsernameInput extends LitElement {
/>
${this.validationError
? html`<div
class="absolute w-full mt-2 px-3 py-1 text-lg border rounded bg-white text-red-600 border-red-600 dark:bg-gray-700 dark:text-red-300 dark:border-red-300"
class="absolute z-10 w-full mt-2 px-3 py-1 text-lg border rounded bg-white text-red-600 border-red-600 dark:bg-gray-700 dark:text-red-300 dark:border-red-300"
>
${this.validationError}
</div>`
+1 -1
View File
@@ -191,7 +191,7 @@ export function createRenderer(
const layers: Layer[] = [
new TerrainLayer(game, transformHandler),
new TerritoryLayer(game, eventBus),
new TerritoryLayer(game, eventBus, transformHandler),
structureLayer,
new UnitLayer(game, eventBus, transformHandler),
new FxLayer(game),
+5 -5
View File
@@ -16,13 +16,13 @@ export class ControlPanel extends LitElement implements Layer {
public uiState: UIState;
@state()
private attackRatio: number = 0.2;
private attackRatio: number = 0.3;
@state()
private targetTroopRatio = 0.95;
private targetTroopRatio = 0.6;
@state()
private currentTroopRatio = 0.95;
private currentTroopRatio = 0.6;
@state()
private _population: number;
@@ -59,10 +59,10 @@ export class ControlPanel extends LitElement implements Layer {
init() {
this.attackRatio = Number(
localStorage.getItem("settings.attackRatio") ?? "0.2",
localStorage.getItem("settings.attackRatio") ?? "0.3",
);
this.targetTroopRatio = Number(
localStorage.getItem("settings.troopRatio") ?? "0.95",
localStorage.getItem("settings.troopRatio") ?? "0.6",
);
this.init_ = true;
this.uiState.attackRatio = this.attackRatio;
+13 -4
View File
@@ -218,10 +218,19 @@ export class NameLayer implements Layer {
shieldDiv.style.display = "flex";
shieldDiv.style.alignItems = "center";
shieldDiv.style.gap = "0px";
shieldDiv.innerHTML = `
<img src="${this.shieldIconImage.src}" style="width: 16px; height: 16px;" />
<span style="color: black; font-size: 10px; margin-top: -2px;">0</span>
`;
const shieldImg = document.createElement("img");
shieldImg.src = this.shieldIconImage.src;
shieldImg.style.width = "16px";
shieldImg.style.height = "16px";
const shieldSpan = document.createElement("span");
shieldSpan.textContent = "0";
shieldSpan.style.color = "black";
shieldSpan.style.fontSize = "10px";
shieldSpan.style.marginTop = "-2px";
shieldDiv.appendChild(shieldImg);
shieldDiv.appendChild(shieldSpan);
element.appendChild(shieldDiv);
// Start off invisible so it doesn't flash at 0,0
+43 -42
View File
@@ -9,6 +9,7 @@ import { GameView, PlayerView } from "../../../core/game/GameView";
import { PseudoRandom } from "../../../core/PseudoRandom";
import { AlternateViewEvent, DragEvent } from "../../InputHandler";
import { PatternDecoder } from "../../TerritoryPatterns";
import { TransformHandler } from "../TransformHandler";
import { Layer } from "./Layer";
export class TerritoryLayer implements Layer {
@@ -33,7 +34,7 @@ export class TerritoryLayer implements Layer {
private lastDragTime = 0;
private nodrawDragDuration = 200;
private refreshRate = 10;
private refreshRate = 10; //refresh every 10ms
private lastRefresh = 0;
private lastFocusedPlayer: PlayerView | null = null;
@@ -41,6 +42,7 @@ export class TerritoryLayer implements Layer {
constructor(
private game: GameView,
private eventBus: EventBus,
private transformHandler: TransformHandler,
) {
this.theme = game.config().theme();
}
@@ -49,11 +51,10 @@ export class TerritoryLayer implements Layer {
return true;
}
paintPlayerBorder(player: PlayerView) {
player.borderTiles().then((playerBorderTiles) => {
playerBorderTiles.borderTiles.forEach((tile: TileRef) => {
this.paintTerritory(tile, true); // Immediately paint the tile instead of enqueueing
});
async paintPlayerBorder(player: PlayerView) {
const tiles = await player.borderTiles();
tiles.borderTiles.forEach((tile: TileRef) => {
this.paintTerritory(tile, true); // Immediately paint the tile instead of enqueueing
});
}
@@ -129,11 +130,7 @@ export class TerritoryLayer implements Layer {
euclDistFN(centerTile, 9, true),
)) {
if (!this.game.hasOwner(tile)) {
this.paintHighlightCell(
new Cell(this.game.x(tile), this.game.y(tile)),
color,
255,
);
this.paintHighlightTile(tile, color, 255);
}
}
}
@@ -156,16 +153,16 @@ export class TerritoryLayer implements Layer {
const context = this.canvas.getContext("2d");
if (context === null) throw new Error("2d context not supported");
this.context = context;
this.canvas.width = this.game.width();
this.canvas.height = this.game.height();
this.imageData = this.context.getImageData(
0,
0,
this.game.width(),
this.game.height(),
this.canvas.width,
this.canvas.height,
);
this.initImageData();
this.canvas.width = this.game.width();
this.canvas.height = this.game.height();
this.context.putImageData(this.imageData, 0, 0);
// Add a second canvas for highlights
@@ -200,7 +197,19 @@ export class TerritoryLayer implements Layer {
) {
this.lastRefresh = now;
this.renderTerritory();
this.context.putImageData(this.imageData, 0, 0);
const [topLeft, bottomRight] = this.transformHandler.screenBoundingRect();
const vx0 = Math.max(0, topLeft.x);
const vy0 = Math.max(0, topLeft.y);
const vx1 = Math.min(this.game.width() - 1, bottomRight.x);
const vy1 = Math.min(this.game.height() - 1, bottomRight.y);
const w = vx1 - vx0 + 1;
const h = vy1 - vy0 + 1;
if (w > 0 && h > 0) {
this.context.putImageData(this.imageData, 0, 0, vx0, vy0, w, h);
}
}
if (this.alternativeView) {
return;
@@ -246,15 +255,10 @@ export class TerritoryLayer implements Layer {
}
if (!this.game.hasOwner(tile)) {
if (this.game.hasFallout(tile)) {
this.paintCell(
this.game.x(tile),
this.game.y(tile),
this.theme.falloutColor(),
150,
);
this.paintTile(tile, this.theme.falloutColor(), 150);
return;
}
this.clearCell(new Cell(this.game.x(tile), this.game.y(tile)));
this.clearTile(tile);
return;
}
const owner = this.game.owner(tile) as PlayerView;
@@ -274,17 +278,12 @@ export class TerritoryLayer implements Layer {
const lightTile =
(x % 2 === 0 && y % 2 === 0) || (y % 2 === 1 && x % 2 === 1);
const borderColor = lightTile ? borderColors.light : borderColors.dark;
this.paintCell(x, y, borderColor, 255);
this.paintTile(tile, borderColor, 255);
} else {
const useBorderColor = playerIsFocused
? this.theme.focusedBorderColor()
: this.theme.borderColor(owner);
this.paintCell(
this.game.x(tile),
this.game.y(tile),
useBorderColor,
255,
);
this.paintTile(tile, useBorderColor, 255);
}
} else {
const patternName = owner.pattern();
@@ -303,23 +302,21 @@ export class TerritoryLayer implements Layer {
const decoder = new PatternDecoder(patternName ?? "");
const bit = decoder.isSet(x, y) ? 1 : 0;
const colorToUse = bit ? baseColor.darken(0.2) : baseColor;
this.paintCell(x, y, colorToUse, 150);
this.paintTile(tile, colorToUse, 150);
}
}
}
paintCell(x: number, y: number, color: Colord, alpha: number) {
const index = y * this.game.width() + x;
const offset = index * 4;
paintTile(tile: TileRef, color: Colord, alpha: number) {
const offset = tile * 4;
this.imageData.data[offset] = color.rgba.r;
this.imageData.data[offset + 1] = color.rgba.g;
this.imageData.data[offset + 2] = color.rgba.b;
this.imageData.data[offset + 3] = alpha;
}
clearCell(cell: Cell) {
const index = cell.y * this.game.width() + cell.x;
const offset = index * 4;
clearTile(tile: TileRef) {
const offset = tile * 4;
this.imageData.data[offset + 3] = 0; // Set alpha to 0 (fully transparent)
}
@@ -337,13 +334,17 @@ export class TerritoryLayer implements Layer {
});
}
paintHighlightCell(cell: Cell, color: Colord, alpha: number) {
this.clearCell(cell);
paintHighlightTile(tile: TileRef, color: Colord, alpha: number) {
this.clearTile(tile);
const x = this.game.x(tile);
const y = this.game.y(tile);
this.highlightContext.fillStyle = color.alpha(alpha / 255).toRgbString();
this.highlightContext.fillRect(cell.x, cell.y, 1, 1);
this.highlightContext.fillRect(x, y, 1, 1);
}
clearHighlightCell(cell: Cell) {
this.highlightContext.clearRect(cell.x, cell.y, 1, 1);
clearHighlightTile(tile: TileRef) {
const x = this.game.x(tile);
const y = this.game.y(tile);
this.highlightContext.clearRect(x, y, 1, 1);
}
}
+8 -1
View File
@@ -99,6 +99,11 @@
display: none;
}
}
/* display:none if child has class parent-hidden since we can't use shadow DOM in Lit due to Tailwind */
.component-hideable:has(> .parent-hidden) {
display: none;
}
</style>
<!-- Immediate execution to prevent FOUC -->
@@ -231,7 +236,9 @@
></button>
</territory-patterns-modal>
<username-input class="relative w-full"></username-input>
<news-button class="w-[20%] md:w-[15%]"></news-button>
<news-button
class="w-[20%] md:w-[15%] component-hideable"
></news-button>
</div>
<div></div>
<div>
+1 -1
View File
@@ -107,7 +107,7 @@ export class PlayerImpl implements Player {
private readonly _team: Team | null,
) {
this._name = sanitizeUsername(playerInfo.name);
this._targetTroopRatio = 95n;
this._targetTroopRatio = 60n;
this._troops = toInt(startTroops);
this._workers = 0n;
this._gold = 0n;