- Updated debug visualization options to enhance issue tracking during development.
- Simplified comments for better understanding of seed handling and animation behavior.
- Adjusted blending logic to maintain a pixelated look while ensuring smooth transitions between old and new territories.
- Improved border rendering logic to reflect stable territory edges without alpha blending.
- Introduced hoverStartTime to track the duration of player hover highlights.
- Implemented logic to disable hover highlights after a specified duration of 5000 ms.
- Updated setHoveredPlayerId method to reset hoverStartTime when a new player is hovered.
- Adjusted shader logic to only draw borders in alternative view
- Updated comments for better understanding of rendering behavior in alternative view mode.
- Simplified color blending
- Updated seed validation checks to simplify smooth animation handling.
- Adjusted comments for clarity regarding seed conditions and animation behavior.
- Enhanced performance by skipping unnecessary computations when seed data is invalid.
- Updated seed distance calculations to check for valid seeds before applying smooth logic, enhancing performance.
- Simplified color mixing and edge handling based on the presence of old and new seeds, improving visual fidelity during transitions.
- Streamlined shader logic to reduce unnecessary computations when no changes are detected.
- Deleted TerrainLayer class to streamline rendering architecture.
- Updated GameRenderer to remove TerrainLayer instantiation.
- Enhanced TerritoryWebGLRenderer to manage terrain textures and rendering directly.
- Added terrain texture handling and shader updates for improved visual fidelity.
- Introduced terrainView method in GameImpl and GameMap for terrain data access.
- Introduced ENABLE_CONTEST_TRACKING constant to toggle contest tracking functionality.
- Updated TerritoryLayer to conditionally handle contest updates and rendering based on contestEnabled state.
- Refactored TerritoryWebGLRenderer to manage contest-related uploads and rendering based on contestEnabled flag.
- Improved shader logic to incorporate contestEnabled uniform for better control over contest rendering.
- Remove unused GLSL noise functions (hash12, valueNoise, fbm) from TerritoryWebGLRenderer
- Remove contested fill smoke rendering code that used these noise functions
- Add contestTileCount field to TerritoryLayer to track total contested tiles
- Update debug output to include contest tile count for monitoring
- Updated contest strength calculations to utilize troop counts directly, enhancing accuracy in contest dynamics.
- Streamlined rendering logic by eliminating unnecessary checks and textures related to contest speeds, improving performance and clarity.
- Refactored related methods to focus on contest strength, ensuring a more cohesive approach to contest state management.
- Added support for change mask textures and framebuffers to track territory ownership changes.
- Introduced a new shader program for change mask processing, enhancing visual fidelity during transitions.
- Updated rendering logic to incorporate change mask updates, improving performance and accuracy in contested areas.
- Refactored related uniform and framebuffer management for better organization and clarity.
Refactor contest management in TerritoryLayer and TerritoryWebGLRenderer
- Updated contest duration handling to use ticks instead of milliseconds for improved precision.
- Introduced new tick-based state management for contest updates and rendering.
- Enhanced interpolation logic for smoother transitions between contest states.
- Removed obsolete smooth state handling and related properties to streamline code.
- Added support for older contest states in the WebGL renderer for better visual fidelity.
feat: Add view transforms and contest speed/strength visualization
- Add contest speed tracking with exponential moving average for dynamic contest visualization
- Add contest strength calculation based on attacker/defender troop ratios
- Implement view transform support (scale/offset) for zoom and pan functionality
- Add animated contest effects with noise-based cloud rendering
- Improve smooth territory transitions with better edge handling
- Add debug overlay for development with contest and rendering stats
- Refactor WebGL renderer to support world-space rendering instead of pixel-perfect
- Removed unused variables and logic related to contest state, including attacker relations and border management.
- Streamlined rendering logic by eliminating unnecessary checks for contested states, improving code clarity and performance.
- Added playerHighlightColor method to Theme interface and implemented it in PastelTheme and PastelThemeDark classes.
- Updated TerritoryLayer to redraw when the theme changes, ensuring consistent visual updates.
- Modified hoverHighlightOptions to use the new player highlight color for improved territory visualization.
- Removed redundant smooth state handling in TerritoryLayer, replacing it with a snapshot mechanism for smoother transitions.
- Updated rendering logic in TerritoryWebGLRenderer to utilize framebuffers for state management, enhancing performance and visual fidelity.
- Adjusted shader logic to accommodate new smoothing conditions and removed obsolete properties related to smooth state tracking.
Details:
Added per‑tile smoothing state in TerritoryLayer.ts (prev owner + change mask + 100 ms timing) and feed progress into the renderer each frame.
Added JFA seed + ping‑pong passes, prevOwner/changeMask textures, and smooth uniforms in TerritoryWebGLRenderer.ts, plus shader blending based on JFA distance.
- Introduced contest management in TerritoryLayer, replacing previous transition handling with a new system for managing contests between tile owners.
- Added methods to handle contest state, including starting, updating, and expiring contests.
- Updated TerritoryWebGLRenderer to support rendering contest data, including new textures and uniforms for contest owners, IDs, and times.
- Enhanced rendering logic to visually represent contest states, including color changes and border effects during contests.
- Added shared hover helper in HoverInfo.ts (same rules as PlayerInfoOverlay, including nearby ships on water).
- PlayerInfoOverlay.ts now uses getHoverInfo(...) instead of its local hover logic.
- TerritoryLayer.ts now uses getHoverInfo(...) and highlights the unit owner when hovering ships/boats.
- Updated transition handling in TerritoryLayer, replacing epoch and progress tracking with a more efficient system using arrays for start times and active masks.
- Introduced new methods to manage transition states and ensure proper initialization of transition data.
- Modified TerritoryWebGLRenderer to align with the new transition management, removing obsolete properties and updating uniform handling for transitions.
- Improved rendering logic to support smoother visual updates during tile transitions.
Refactor TerritoryLayer and Renderer for improved transition handling
- Removed unused imports and types, streamlining the TerritoryLayer code.
- Replaced the `TerritoryRendererStrategy` interface with direct usage of `TerritoryWebGLRenderer`.
- Enhanced transition management by introducing epoch and progress tracking for tile transitions.
- Updated rendering logic to utilize the new transition properties, ensuring smoother visual updates.
- Removed the CanvasTerritoryRenderer and related logic, consolidating rendering responsibilities within the WebGL renderer.
- Introduced a new `TileTransition` type to manage tile transitions.
- Added methods to handle the beginning and updating of tile transitions.
- Enhanced `TerritoryRenderer` interfaces to support transition progress.
- Updated `TerritoryWebGLRenderer` to manage transition textures and rendering.
- Modified `GameView` to track owner changes for tiles, enabling transition effects during gameplay.
- Added `lastPaletteSignature` to track palette changes.
- Implemented `computePaletteSignature()` to generate a unique signature based on player views and settings.
- Introduced `refreshPaletteIfNeeded()` to refresh the palette when the signature changes, ensuring visual consistency in the TerritoryLayer.
## Description:
- Added `generateUniqueNationName()` to `NationCreation` because I saw a
duplicate name while spawning 300 nations on Pangaea 😄
- Switched HumansVsNations public game difficulty from hard to
impossible because I realized how crazy strong troop donations between
humans are (in an enzo HVN stream).
Maybe I have to make nations donate troops to each other, we will see...
Playtests won't tell the truth because the players attending these are
probably better than the usual OF player. I will try to check the HVN
winrate via API after launch
## 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:
FloPinguin
## Description:
### Refactor
- Moved `maybeSpawnWarship()` from `NationExecution` to
`NationWarshipBehavior`
- Moved `maybeAttack()` (and sub-methods) from `NationExecution` to
`AiAttackBehavior`
### Betrayal
- Added nice betrayal logic in `maybeBetray()`. Previously that method
was basically just a placeholder for a future implementation.
### Attacking
- Added `veryWeak()` attack strategy for hard and impossible difficulty
nations attack orders to target MIRVed players with higher priority
- Optimized the `weakest()` attack strategy so that nations don't attack
stronger players. This should make nation-attacks feel less random
(humans complained in discord)
- `findNearestIslandEnemy()` and `randomBoatTarget()` also no longer
returns stronger players
- `afk()` and `hated()` attack strategies no longer return MUCH stronger
players
- Several tiny refactorings, fixes and balance optimizations in
`AiAttackBehavior`
### Emojis
- Added some `canSendEmoji()` because I saw some "cannot send emoji"
warnings in the console
## 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:
FloPinguin
Bumps the npm_and_yarn group with 2 updates in the / directory:
[@smithy/config-resolver](https://github.com/smithy-lang/smithy-typescript/tree/HEAD/packages/config-resolver)
and [qs](https://github.com/ljharb/qs).
Updates `@smithy/config-resolver` from 4.1.4 to 4.4.5
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/smithy-lang/smithy-typescript/releases"><code>@smithy/config-resolver</code>'s
releases</a>.</em></p>
<blockquote>
<h2><code>@smithy/config-resolver</code><a
href="https://github.com/4"><code>@4</code></a>.4.5</h2>
<h3>Patch Changes</h3>
<ul>
<li>Updated dependencies [9ccb841]
<ul>
<li><code>@smithy/types</code><a
href="https://github.com/4"><code>@4</code></a>.11.0</li>
<li><code>@smithy/node-config-provider</code><a
href="https://github.com/4"><code>@4</code></a>.3.7</li>
<li><code>@smithy/util-endpoints</code><a
href="https://github.com/3"><code>@3</code></a>.2.7</li>
<li><code>@smithy/util-middleware</code><a
href="https://github.com/4"><code>@4</code></a>.2.7</li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/smithy-lang/smithy-typescript/blob/main/packages/config-resolver/CHANGELOG.md"><code>@smithy/config-resolver</code>'s
changelog</a>.</em></p>
<blockquote>
<h2>4.4.5</h2>
<h3>Patch Changes</h3>
<ul>
<li>Updated dependencies [9ccb841]
<ul>
<li><code>@smithy/types</code><a
href="https://github.com/4"><code>@4</code></a>.11.0</li>
<li><code>@smithy/node-config-provider</code><a
href="https://github.com/4"><code>@4</code></a>.3.7</li>
<li><code>@smithy/util-endpoints</code><a
href="https://github.com/3"><code>@3</code></a>.2.7</li>
<li><code>@smithy/util-middleware</code><a
href="https://github.com/4"><code>@4</code></a>.2.7</li>
</ul>
</li>
</ul>
<h2>4.4.4</h2>
<h3>Patch Changes</h3>
<ul>
<li>Updated dependencies [5a56762]
<ul>
<li><code>@smithy/types</code><a
href="https://github.com/4"><code>@4</code></a>.10.0</li>
<li><code>@smithy/node-config-provider</code><a
href="https://github.com/4"><code>@4</code></a>.3.6</li>
<li><code>@smithy/util-endpoints</code><a
href="https://github.com/3"><code>@3</code></a>.2.6</li>
<li><code>@smithy/util-middleware</code><a
href="https://github.com/4"><code>@4</code></a>.2.6</li>
</ul>
</li>
</ul>
<h2>4.4.3</h2>
<h3>Patch Changes</h3>
<ul>
<li>Updated dependencies [3926fd7]
<ul>
<li><code>@smithy/types</code><a
href="https://github.com/4"><code>@4</code></a>.9.0</li>
<li><code>@smithy/node-config-provider</code><a
href="https://github.com/4"><code>@4</code></a>.3.5</li>
<li><code>@smithy/util-endpoints</code><a
href="https://github.com/3"><code>@3</code></a>.2.5</li>
<li><code>@smithy/util-middleware</code><a
href="https://github.com/4"><code>@4</code></a>.2.5</li>
</ul>
</li>
</ul>
<h2>4.4.2</h2>
<h3>Patch Changes</h3>
<ul>
<li>372b46f: allow * region with warning</li>
</ul>
<h2>4.4.1</h2>
<h3>Patch Changes</h3>
<ul>
<li>Updated dependencies [6da0ab3]
<ul>
<li><code>@smithy/types</code><a
href="https://github.com/4"><code>@4</code></a>.8.1</li>
<li><code>@smithy/node-config-provider</code><a
href="https://github.com/4"><code>@4</code></a>.3.4</li>
<li><code>@smithy/util-endpoints</code><a
href="https://github.com/3"><code>@3</code></a>.2.4</li>
<li><code>@smithy/util-middleware</code><a
href="https://github.com/4"><code>@4</code></a>.2.4</li>
</ul>
</li>
</ul>
<h2>4.4.0</h2>
<h3>Minor Changes</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/smithy-lang/smithy-typescript/commit/521d67c38f8928c514d1fcea3fc08e40c2300513"><code>521d67c</code></a>
Version NPM packages</li>
<li><a
href="https://github.com/smithy-lang/smithy-typescript/commit/8b90f360df2a5c80c105db732b3c2f6972994854"><code>8b90f36</code></a>
Version NPM packages</li>
<li><a
href="https://github.com/smithy-lang/smithy-typescript/commit/cc0124e69e2d6943f0960854bcc3abf2defd2c20"><code>cc0124e</code></a>
Version NPM packages</li>
<li><a
href="https://github.com/smithy-lang/smithy-typescript/commit/07f95d95712b511256b542c4dfa368bd70580be8"><code>07f95d9</code></a>
Version NPM packages</li>
<li><a
href="https://github.com/smithy-lang/smithy-typescript/commit/372b46fb0751e6e61cdfccee1fa7e6a531cf6aa4"><code>372b46f</code></a>
fix(config-resolver): allow asterisk region with warning (<a
href="https://github.com/smithy-lang/smithy-typescript/tree/HEAD/packages/config-resolver/issues/1760">#1760</a>)</li>
<li><a
href="https://github.com/smithy-lang/smithy-typescript/commit/472a5ea035237e10c560ed362c0e0105805ad26f"><code>472a5ea</code></a>
Version NPM packages</li>
<li><a
href="https://github.com/smithy-lang/smithy-typescript/commit/8af2d330260513d3e51c98f1f137793b5330ceb4"><code>8af2d33</code></a>
Version NPM packages</li>
<li><a
href="https://github.com/smithy-lang/smithy-typescript/commit/13c5cd95b682c9252e6cf15b771b5decdc860729"><code>13c5cd9</code></a>
chore(config-resolver): add region validation cache (<a
href="https://github.com/smithy-lang/smithy-typescript/tree/HEAD/packages/config-resolver/issues/1750">#1750</a>)</li>
<li><a
href="https://github.com/smithy-lang/smithy-typescript/commit/f7c7b8249fa91391f73f62fb4237e5436c61be41"><code>f7c7b82</code></a>
Version NPM packages</li>
<li><a
href="https://github.com/smithy-lang/smithy-typescript/commit/9fb748e02081659c1aa523cdab64621467eddbf6"><code>9fb748e</code></a>
Version NPM packages</li>
<li>Additional commits viewable in <a
href="https://github.com/smithy-lang/smithy-typescript/commits/@smithy/config-resolver@4.4.5/packages/config-resolver">compare
view</a></li>
</ul>
</details>
<br />
Updates `qs` from 6.13.0 to 6.14.1
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/ljharb/qs/blob/main/CHANGELOG.md">qs's
changelog</a>.</em></p>
<blockquote>
<h2><strong>6.14.1</strong></h2>
<ul>
<li>[Fix] ensure arrayLength applies to <code>[]</code> notation as
well</li>
<li>[Fix] <code>parse</code>: when a custom decoder returns
<code>null</code> for a key, ignore that key</li>
<li>[Refactor] <code>parse</code>: extract key segment splitting
helper</li>
<li>[meta] add threat model</li>
<li>[actions] add workflow permissions</li>
<li>[Tests] <code>stringify</code>: increase coverage</li>
<li>[Dev Deps] update <code>eslint</code>,
<code>@ljharb/eslint-config</code>, <code>npmignore</code>,
<code>es-value-fixtures</code>, <code>for-each</code>,
<code>object-inspect</code></li>
</ul>
<h2><strong>6.14.0</strong></h2>
<ul>
<li>[New] <code>parse</code>: add
<code>throwOnParameterLimitExceeded</code> option (<a
href="https://redirect.github.com/ljharb/qs/issues/517">#517</a>)</li>
<li>[Refactor] <code>parse</code>: use <code>utils.combine</code>
more</li>
<li>[patch] <code>parse</code>: add explicit
<code>throwOnLimitExceeded</code> default</li>
<li>[actions] use shared action; re-add finishers</li>
<li>[meta] Fix changelog formatting bug</li>
<li>[Deps] update <code>side-channel</code></li>
<li>[Dev Deps] update <code>es-value-fixtures</code>,
<code>has-bigints</code>, <code>has-proto</code>,
<code>has-symbols</code></li>
<li>[Tests] increase coverage</li>
</ul>
<h2><strong>6.13.1</strong></h2>
<ul>
<li>[Fix] <code>stringify</code>: avoid a crash when a
<code>filter</code> key is <code>null</code></li>
<li>[Fix] <code>utils.merge</code>: functions should not be stringified
into keys</li>
<li>[Fix] <code>parse</code>: avoid a crash with
interpretNumericEntities: true, comma: true, and iso charset</li>
<li>[Fix] <code>stringify</code>: ensure a non-string
<code>filter</code> does not crash</li>
<li>[Refactor] use <code>__proto__</code> syntax instead of
<code>Object.create</code> for null objects</li>
<li>[Refactor] misc cleanup</li>
<li>[Tests] <code>utils.merge</code>: add some coverage</li>
<li>[Tests] fix a test case</li>
<li>[actions] split out node 10-20, and 20+</li>
<li>[Dev Deps] update <code>es-value-fixtures</code>,
<code>mock-property</code>, <code>object-inspect</code>,
<code>tape</code></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/ljharb/qs/commit/3fa11a5f643c76896387bd2d86904a2d0141fdf7"><code>3fa11a5</code></a>
v6.14.1</li>
<li><a
href="https://github.com/ljharb/qs/commit/a62670423c1ccab0dd83c621bfb98c7c024e314d"><code>a626704</code></a>
[Dev Deps] update <code>npmignore</code></li>
<li><a
href="https://github.com/ljharb/qs/commit/3086902ecf7f088d0d1803887643ac6c03d415b9"><code>3086902</code></a>
[Fix] ensure arrayLength applies to <code>[]</code> notation as
well</li>
<li><a
href="https://github.com/ljharb/qs/commit/fc7930e86c2264c1568c9f5606830e19b0bc2af2"><code>fc7930e</code></a>
[Dev Deps] update <code>eslint</code>,
<code>@ljharb/eslint-config</code></li>
<li><a
href="https://github.com/ljharb/qs/commit/0b06aac566abee45ef0327667a7cc89e7aed8b58"><code>0b06aac</code></a>
[Dev Deps] update <code>@ljharb/eslint-config</code></li>
<li><a
href="https://github.com/ljharb/qs/commit/64951f6200a1fb72cc003c6e8226dde3d2ef591f"><code>64951f6</code></a>
[Refactor] <code>parse</code>: extract key segment splitting helper</li>
<li><a
href="https://github.com/ljharb/qs/commit/e1bd2599cdff4c936ea52fb1f16f921cbe7aa88c"><code>e1bd259</code></a>
[Dev Deps] update <code>@ljharb/eslint-config</code></li>
<li><a
href="https://github.com/ljharb/qs/commit/f4b3d39709fef6ddbd85128d1ba4c6b566c4902e"><code>f4b3d39</code></a>
[eslint] add eslint 9 optional peer dep</li>
<li><a
href="https://github.com/ljharb/qs/commit/6e94d9596ca50dffafcef40a5f64eca89962cf34"><code>6e94d95</code></a>
[Dev Deps] update <code>eslint</code>,
<code>@ljharb/eslint-config</code>, <code>npmignore</code></li>
<li><a
href="https://github.com/ljharb/qs/commit/973dc3c51c86da9f4e30edeb4b1725158d439102"><code>973dc3c</code></a>
[actions] add workflow permissions</li>
<li>Additional commits viewable in <a
href="https://github.com/ljharb/qs/compare/v6.13.0...v6.14.1">compare
view</a></li>
</ul>
</details>
<br />
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/openfrontio/OpenFrontIO/network/alerts).
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
If this PR fixes an issue, link it below. If not, delete these two
lines.
Resolves
https://github.com/openfrontio/OpenFrontIO/pull/2677#issuecomment-3725268126
## Description:
Update public lobby team count strings to clarify that counts refer to
teams .
## 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:
aotumuri
## Description:
Some FX animations were previously used as UI elements (e.g. nuke area,
naval invasion target, gold text).
This PR moves those animations to a dedicated UI layer.
Those UI elements handle correctly the current zoom level and remain
sharply rendered at all zoom levels.
The new UI layer can be disabled using the same setting that disables
the FX layer.
Performance-wise, this layer is equivalent to the FX layer, as it reuses
the same animations.
### Naval target
Don't scale with the zoom level, but has a minimum zoom level so the
targeted tile can still be easily highlighted by zooming

### Nukes
Has to scale because the size is set, but the border radius is not so
the area is more visible from afar.

### Popup text
Scale with zoom level, and stop showing when zoomed-out:

## 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:
IngloriousTom
references #2001
## Description:
Improve the ranked matchmaking modal. Better messages, and show 1v1 elo
<img width="450" height="210" alt="Screenshot 2026-01-08 at 7 11 20 PM"
src="https://github.com/user-attachments/assets/e4f8323c-5d98-48de-babe-b51526a6d408"
/>
<img width="622" height="614" alt="Screenshot 2026-01-08 at 7 11 14 PM"
src="https://github.com/user-attachments/assets/73d10f84-b5b5-4ba8-95bb-a181a9fd9dae"
/>
## 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:
evan
## Description:
Simple PR, but adds the feature where using the hotkey to build a city
will show SAM radius layer to let user know safe areas to build.
<img width="2126" height="1398" alt="image"
src="https://github.com/user-attachments/assets/8aed5514-51c4-40f4-a446-e3c52346abc8"
/>
## 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:
bijx
Resolves#2823
## Description:
When playing in single-player mode, if an NPC reaches 80% land control
before the player, the game enters a broken state where:
- The game clock stops
- Win checking stops permanently
- Even if the player later conquers 100% of land, victory is never
awarded
- The game becomes "stuck" in a zombie state.
This PR addresses this allowing Nations to be set as winners in single
mode, and in this case showing a "Nation {nation} has won" modal to the
user. This WinModal is the same as the "{player} has won", with the only
change being the title.
Nation wins in FFA, from the human player perspective:
<img width="1457" height="837" alt="image"
src="https://github.com/user-attachments/assets/1ce569bd-6616-4a23-b4a4-afedad2c64f8"
/>
## 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
## Pathfinding with HPA*
Hi! The primary objective of this PR is to replace per-tile A* with
hierarchical pathfinding - HPA*. In practice, this means we create an
abstract graph on top of the actual map with far fewer points and use it
to decide on general path structure. Only then we go back to tile-level
and build path between selected waypoints. This speeds up long distance
pathfinding by over 1000x in some cases. To make the review easier, it
comes with a benchmark and visual playground.
## PREPROCESSING
H part of HPA* means "hierarchical" and requires preprocessing.
This PR includes pre-processing as part inside `new Game()` constructor.
It takes about 135ms for `giantworldmap` on my machine, which increases
the effective initialization from ~95ms to ~230ms. This time could be
reduced in different ways, which are **out of scope** for this PR.
After confirming the initialization time is bearable on low-end devices,
I argue merging this PR as-is is acceptable tradeoff. It creates small
lag at the beginning of a round but pays for itself in the first minute
of the match.
## Nerdy details
**Architecture**
- HPA*-style hierarchical pathfinding
- 32×32 sectors on minimap with gateway nodes on borders
- Gateway graph built via BFS during preprocessing
- Water component optimization skips unreachable gateway pairs
- A* on gateway graph → local A* within sectors → Bresenham path
smoothing
- Minimap upscaling identical to currently used in MiniAStar
**Key Optimizations**
- Typed arrays instead of high-level primitives
- Stamp-based visited tracking (no need to recreate buffers, O(1)
clearing)
- Optional - enabled by default - caching of tile paths between gateways
- Line of sight smoothing for the final path
## Review Focus
Play with included tools, benchmark and visualization. Pathfinding
should be safe to merge as a black box - you do not need to understand
the details. Outcomes can be tested empirically in-game. Visualize (and
share!) edge cases with included playground. Confirm the 100x speedup is
real with benchmark.
If you plan to dive into the code, I suggest the following order:
- Pathfinding abstraction in `src/core/pathfinding/`
- Pathfinding tests in `tests/core/pathfinding/`
- NavMesh in `src/core/pathfinding/navmesh/` + integration with
`Game.ts`
- Benchmark in `tests/pathfinding/benchmark/`
Do not look at playground's code, it has been created with a clanker.
The design is 100% mine and I spent way too long polishing it, but I
haven't even once edited the code manually. There is probably no
abstraction whatsoever, just do not look at the code, let it play.
## Core Changes
#### Pathfinding (`src/core/pathfinding/navmesh/`)
- HPA* + refinement -> three phased pathfinding: A* over the graph ->
naive path -> refinement
- comes with A* and BFS optimized for for specific needs
#### Pre-Processing (`src/core/pathfinding/navmesh/`)
- identify water bodies to avoid pathfinding between disconnected nodes
- create high-level graph of gateways on top of tile map
#### Abstraction (`src/core/pathfinding/`)
- common `PathFinder` interface that can return full path and also act
as state machine (`.next()`)
- adapters for both new and legacy algorithm with fallback to legacy if
navigation mesh not available
#### Benchmark (`tests/pathfinding/benchmark/`)
- `npx tsx tests/pathfinding/benchmark/run.ts` - no guesswork, numbers
- `npx tsx tests/pathfinding/benchmark/run.ts --synthetic` - 1000s of
synthetic paths
- `npx tsc tests/pathfinding/benchmark/generate.ts` - generate more as
needed, test new maps
- includes ONE synthetic scenario to avoid PR bloat, generate more
locally / later
#### Playground (`tests/pathfinding/playground/`)
- `npx tsx tests/pathfinding/playground/server.ts` - visualize paths
with both new and legacy algorithm
## Benchmarks
### Compared with legacy in default - hand picked - scenario:
```
Initialization: 95.95ms -> 227.29ms
Pathfinding: 3038.43ms -> 6.45ms
Distance: 26972 -> 26810 tiles
```
### 42,000 synthetic routes across all maps
```
Running 42 synthetic scenarios with hpa.cached adapter...
✅ synthetic/achiran | Init: 93.42ms | Path: 139.07ms | Dist: 1481630 tiles | Routes: 1000/1000
✅ synthetic/africa | Init: 87.14ms | Path: 155.08ms | Dist: 1829414 tiles | Routes: 1000/1000
✅ synthetic/asia | Init: 57.60ms | Path: 112.55ms | Dist: 1204082 tiles | Routes: 1000/1000
✅ synthetic/australia | Init: 78.18ms | Path: 77.12ms | Dist: 978375 tiles | Routes: 1000/1000
✅ synthetic/baikal | Init: 78.26ms | Path: 152.14ms | Dist: 1600016 tiles | Routes: 1000/1000
✅ synthetic/baikalnukewars | Init: 81.44ms | Path: 165.90ms | Dist: 1699283 tiles | Routes: 1000/1000
✅ synthetic/betweentwoseas | Init: 29.29ms | Path: 114.99ms | Dist: 1338075 tiles | Routes: 1000/1000
✅ synthetic/blacksea | Init: 30.66ms | Path: 93.14ms | Dist: 949217 tiles | Routes: 1000/1000
✅ synthetic/britannia | Init: 74.12ms | Path: 85.62ms | Dist: 866752 tiles | Routes: 1000/1000
✅ synthetic/deglaciatedantarctica | Init: 105.49ms | Path: 192.93ms | Dist: 1574684 tiles | Routes: 1000/1000
✅ synthetic/didier | Init: 81.51ms | Path: 153.70ms | Dist: 1734876 tiles | Routes: 1000/1000
✅ synthetic/eastasia | Init: 49.29ms | Path: 128.63ms | Dist: 1410270 tiles | Routes: 1000/1000
✅ synthetic/europe | Init: 92.55ms | Path: 178.35ms | Dist: 1525216 tiles | Routes: 1000/1000
✅ synthetic/europeclassic | Init: 33.50ms | Path: 104.40ms | Dist: 1209759 tiles | Routes: 1000/1000
✅ synthetic/falklandislands | Init: 63.00ms | Path: 107.41ms | Dist: 1080251 tiles | Routes: 1000/1000
✅ synthetic/faroeislands | Init: 71.91ms | Path: 49.52ms | Dist: 604613 tiles | Routes: 1000/1000
✅ synthetic/fourislands | Init: 45.75ms | Path: 78.91ms | Dist: 937439 tiles | Routes: 1000/1000
✅ synthetic/gatewaytotheatlantic | Init: 81.00ms | Path: 257.06ms | Dist: 2555551 tiles | Routes: 1000/1000
✅ synthetic/giantworldmap | Init: 214.25ms | Path: 220.42ms | Dist: 1976693 tiles | Routes: 1000/1000
✅ synthetic/gulfofstlawrence | Init: 45.16ms | Path: 96.05ms | Dist: 1014604 tiles | Routes: 1000/1000
✅ synthetic/halkidiki | Init: 74.68ms | Path: 149.39ms | Dist: 1546781 tiles | Routes: 1000/1000
✅ synthetic/iceland | Init: 58.72ms | Path: 78.16ms | Dist: 1001554 tiles | Routes: 1000/1000
✅ synthetic/italia | Init: 29.78ms | Path: 139.93ms | Dist: 1412024 tiles | Routes: 1000/1000
✅ synthetic/japan | Init: 161.07ms | Path: 118.65ms | Dist: 1154393 tiles | Routes: 1000/1000
✅ synthetic/lemnos | Init: 52.59ms | Path: 136.69ms | Dist: 1481101 tiles | Routes: 1000/1000
✅ synthetic/lisbon | Init: 49.27ms | Path: 86.53ms | Dist: 1032011 tiles | Routes: 1000/1000
✅ synthetic/manicouagan | Init: 53.74ms | Path: 110.52ms | Dist: 1307630 tiles | Routes: 1000/1000
✅ synthetic/mars | Init: 29.39ms | Path: 80.55ms | Dist: 1091702 tiles | Routes: 1000/1000
✅ synthetic/mena | Init: 26.37ms | Path: 120.09ms | Dist: 1272751 tiles | Routes: 1000/1000
✅ synthetic/montreal | Init: 26.08ms | Path: 106.77ms | Dist: 1187736 tiles | Routes: 1000/1000
✅ synthetic/newyorkcity | Init: 56.60ms | Path: 181.19ms | Dist: 1753875 tiles | Routes: 1000/1000
✅ synthetic/northamerica | Init: 96.29ms | Path: 123.02ms | Dist: 1217221 tiles | Routes: 1000/1000
✅ synthetic/oceania | Init: 52.81ms | Path: 51.96ms | Dist: 482373 tiles | Routes: 1000/1000
✅ synthetic/pangaea | Init: 21.29ms | Path: 56.58ms | Dist: 716189 tiles | Routes: 1000/1000
✅ synthetic/pluto | Init: 53.89ms | Path: 141.62ms | Dist: 1304362 tiles | Routes: 1000/1000
✅ synthetic/southamerica | Init: 85.19ms | Path: 123.03ms | Dist: 1301403 tiles | Routes: 1000/1000
✅ synthetic/straitofgibraltar | Init: 76.68ms | Path: 108.30ms | Dist: 1304592 tiles | Routes: 1000/1000
✅ synthetic/straitofhormuz | Init: 38.97ms | Path: 67.78ms | Dist: 754920 tiles | Routes: 1000/1000
✅ synthetic/surrounded | Init: 95.35ms | Path: 90.18ms | Dist: 1017142 tiles | Routes: 1000/1000
✅ synthetic/svalmel | Init: 60.58ms | Path: 104.75ms | Dist: 1235501 tiles | Routes: 1000/1000
✅ synthetic/twolakes | Init: 62.05ms | Path: 94.54ms | Dist: 1140807 tiles | Routes: 1000/1000
✅ synthetic/world | Init: 41.43ms | Path: 93.42ms | Dist: 873406 tiles | Routes: 1000/1000
Completed 42 scenarios
Total Initialization Time: 2796.32ms
Total Pathfinding Time: 5026.64ms
Total Distance: 53160274 tiles
```
## Playground
**That's the fun part**. Watch NavMesh running circles around legacy
`PathFinder.Mini` in real time. Debug inner workings, test edge cases,
share URLs for debugging.
https://github.com/user-attachments/assets/34e2e3f5-fbc1-4b1f-917d-820766e98d5d
## Discord Tag
`moleole`
## Description:
The new (awesome) nation emoji updates had a small bug in them when I
was playtesting with a friend where donating troops to them (a human
player) would result in the player automatically sending an emoji reply.
Sometimes these replies were negative-connotations like ❓ and 🥱, which
could impact how other players perceive their donation attempt. This PR
fixes that issue.
### Example of player nation sending emojis automatically
https://github.com/user-attachments/assets/99689966-b784-4c3f-b43b-953a4a102e2d
### Donating to player after fix
https://github.com/user-attachments/assets/ace0c1ee-3eb8-4240-9c78-167dd773cfb2
## 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:
bijx
If this PR fixes an issue, link it below. If not, delete these two
lines.
Resolves#2516
## Description:
Introduces a state to the Player Info Overlay which simply shows what
type of terrain the player is hovering on. This just builds on the
principles of continuous feedback when designing UX because players
react positively when the game responds to input action.
<img width="839" height="846" alt="image"
src="https://github.com/user-attachments/assets/4b2969e0-127d-4032-9c49-9cbff9bb2aeb"
/>
<img width="666" height="602" alt="image"
src="https://github.com/user-attachments/assets/5fd15ab1-98b1-472f-a83e-a1ee10338673"
/>
https://github.com/user-attachments/assets/7e39f53e-6d2e-479e-badd-b41484591b8b
## 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:
bijx
## Description:
Previously, the zod schemas for troop and gold donation allowed for
negative values which could open the game up to vulnerabilities through
undefined behavior in the future. We mitigate these vulnerabilities but
adding `.nonnegative` to the `DonateGoldIntentSchema` and
`DonateTroopIntentShcema` respectively. Today, code exists to prevent
this deeper in the codebase, but we should also prevent this earlier if
possible during intent validation.
## 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:
haticus
## Description:
Adds a new detailed Britannia map featuring modern UK, Ireland, and
northern France regions. The previous Britannia map has been preserved
as "Britannia Classic".
<img width="4096" height="5031" alt="United Kingdom"
src="https://github.com/user-attachments/assets/8a6ca3ab-bc91-438f-8ca7-7fdf7c5260b8"
/>
<img width="4096" height="5031" alt="United Kingdom_debug"
src="https://github.com/user-attachments/assets/a9a7bcd2-1dc5-40c6-a547-a7a79e636060"
/>
Changes
Added new Britannia map with modern county/region divisions
Renamed existing Britannia map to "Britannia Classic"
Added map-generator source assets for both maps
Updated GameMapType enum with BritanniaClassic
Configured player counts: 50/30/20 for both maps
Added playlist frequencies: Britannia (5), Britannia Classic (4)
Updated language translations
New Britannia Nations (partial list)
Ireland: Mayo, Kerry, Clare, Meath, and more
Scotland: Highland, Argyll and Bute, and more
England: North Yorkshire, and more
France: Pas-de-Calais
Britannia Classic
The original Britannia map with historical kingdoms (Dumnonia, Dyfed,
Gwent, Gwynedd, Powys, Strathclyde, Dalriata, Wessex, Sussex, Kent,
etc.) is now available as "Britannia Classic".
## 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:
TSProphet
---------
Co-authored-by: Harry <Harry.bath94@gmail.com>
Co-authored-by: iamlewis <lewismmmm@gmail.com>
Resolves#2610
## Description:
Add NUM_WORKERS env override for server worker count.
## 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:
aotumuri
---------
Co-authored-by: Evan <evanpelle@gmail.com>
## Description:
Added a public game modifier system. It causes that
5% of public games are played on the compact version of the map
10% of public games have "Random Spawn" activated
Percentages can easily get changed via `DefaultConfig`.
We can also easily add more modifiers.
Modifiers can stack, so in rare cases you will play on a compact map
with random spawn 😄
More variety!
### "Compact Map" modifier implementation
- With the "Compact Map" modifier the lobby max player count gets
reduced to 25% and only 25% of the regular bots and only 25% of the
regular nations will spawn (because the map has only 25% of its regular
size)
- In private lobbies and singleplayer the nation reduction happens too
(When "Compact Map" is enabled).
### Restrictions
- Duos/Trios/Quads team modes do not get Random Spawn (defeats the
purpose)
- Maps with smallest player count < 50 do not get Compact Map in team
games (not enough players after the reduction to 25%). I have calculated
all the possible max player counts.
### How it looks like
Random Spawn modifier:
<img width="528" height="183" alt="Screenshot 2026-01-06 194959"
src="https://github.com/user-attachments/assets/2f729da9-80c3-4548-8205-71129da2a76a"
/>
Very rare case: Two modifiers at the same time and only 10 max players
have been chosen from `[GameMapType.FaroeIslands]: [20, 15, 10]`.
Because of the 75% reduction in player count only 3 players are allowed
(3 is the minimum). I think its funny that you can play a 1v1v1 in rare
occasions 😄
<img width="526" height="184" alt="Screenshot 2026-01-06 194938"
src="https://github.com/user-attachments/assets/834326eb-df03-41b7-b1db-1efa3f1013b5"
/>
### Funny side-effect
Team games with random spawn. That will be interesting. No more "Who is
better in donating troops to the frontline". Instead you have to heavily
coordinate with your teammates.
## 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:
FloPinguin