## Description:
Adds a reusable FrameProfiler utility, and a way to export profiling
data for offline analysis.
### What this PR changes in the existing performance monitor
This PR enhances the performance monitor by:
- **Introducing a reusable `FrameProfiler` utility**
- New `FrameProfiler` singleton in
`src/client/graphics/FrameProfiler.ts`.
- Profiling is only active when the performance overlay is visible
(toggled via user settings), to avoid unnecessary overhead.
- **Per-layer and span-level timing integration**
- `GameRenderer.renderGame` now:
- Clears the profiler at the start of each frame.
- Wraps each `layer.renderLayer?.(this.context)` call with
`FrameProfiler.start()/end()`, keyed by the layer’s constructor name.
- Consumes the recorded timings at the end of the frame and passes them
into `PerformanceOverlay.updateFrameMetrics(frameDuration,
layerDurations)`.
- `TerritoryLayer` instruments key operations:
- `renderTerritory`
- `putImageData`
- Drawing the main canvas
- Drawing the highlight canvas during spawn
- These show up in the performance overlay as additional entries (e.g.
`TerritoryLayer:renderTerritory`).
- **JSON export of performance snapshots**
- `PerformanceOverlay` can now build a full performance snapshot
(`buildPerformanceSnapshot`) containing:
- FPS and frame time stats (current, 60s average, 60s history).
- Tick metrics (avg/max execution and delay, plus raw samples).
- Layer breakdown (EMA-smoothed avg, max, total time per layer/span).
- A new “Copy JSON” button:
- Uses `navigator.clipboard.writeText` when available and falls back to
a hidden `<textarea>` + `document.execCommand("copy")`.
- Provides user feedback via a transient status ("Copy JSON" → "Copied!"
or "Failed to copy").
- **Enable/disable functionality hooked into the UI**
- `FrameProfiler.setEnabled(visible)` is invoked:
- When the overlay visibility is toggled (`init` → `setVisible`).
- When the overlay re-checks visibility in `updateFrameMetrics`, so the
profiler state stays in sync with user settings.
- When disabled, `FrameProfiler` becomes a no-op (returns `0` from
`start`, ignores `record`/`end`, and `consume` returns an empty object),
ensuring minimal overhead when performance monitoring is off.
- **Performance overlay UX and i18n improvements**
- New controls:
- **Reset** button to clear all FPS/tick/layer stats.
- **Copy JSON** button with a tooltip and transient status text.
- Visual enhancements:
- Wider overlay (`min-width: 420px`) and extra padding for readability.
- Layer breakdown section with:
- A list that is now sorted by total accumulated time.
- A horizontal bar per entry, scaled by average cost.
- Avg / max time display per layer/span.
- All new text is routed through `translateText` and backed by
`en.json`:
- `performance_overlay.reset`
- `performance_overlay.copy_json_title`
- `performance_overlay.copy_clipboard`
- `performance_overlay.copied`
- `performance_overlay.failed_copy`
- `performance_overlay.fps`
- `performance_overlay.avg_60s`
- `performance_overlay.frame`
- `performance_overlay.tick_exec`
- `performance_overlay.tick_delay`
- `performance_overlay.layers_header`
---
### How to set up profiling for new functions / code paths
For any function or code block you want to profile during a frame:
```ts
import { FrameProfiler } from "../FrameProfiler";
function heavyOperation() {
const spanStart = FrameProfiler.start();
// ... your existing work ...
FrameProfiler.end("MyFeature:heavyOperation", spanStart);
}
```
Guidelines:
- Use descriptive, stable names:
- Prefix with the component or layer name, e.g.:
- `"TerritoryLayer:prepareTiles"`
- `"GameRenderer:resolveVisibility"`
- `"FooFeature:fetchData"`
- The same name can be called multiple times per frame; the profiler
accumulates the durations in that frame.
- The accumulated values will appear:
- In `layerDurations` consumed at the end of the frame.
- In the overlay “Layers (avg / max, sorted by total time)” section.
- In the exported JSON under `layers` with `avg`, `max`, and `total`.
**3. Record pre-computed durations (optional)**
If you already have a measured duration and just want to attach it:
```ts
FrameProfiler.record("MyFeature:step1", someDurationInMs);
```
- This is equivalent to calling `start`/`end` but with your own timing
logic.
- Again, multiple calls with the same name in one frame will be summed.
---
<img width="466" height="823" alt="image"
src="https://github.com/user-attachments/assets/354b249a-25eb-4c3f-bd2e-9906372f761b"
/>
## 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
- [ ] 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
---------
Co-authored-by: Evan <evanpelle@gmail.com>
## Description:
This PR addresses issue #2302: where there is no obvious information
about the self-player's team during the spawn phase of the game.
Currently, during TEAM games (where there is a set number of teams
defined), the self player's spawn highlight color is white, while all
other players are shown with a team-based spawn highlight color. This
makes it difficult to discern who is a teammate, especially since the
current live version (v0.26.7) uses green/yellow for other players to
depict teammate/other team, respectively.
Technically, the same is true for Duos, Trios, and Quads games, although
this has been addressed separately with PR #2298 by reverting to
green/yellow for teammate/other team players.
This PR changes the color of the self player's breathing spawn highlight
ring to match their assigned team color (with `alpha=0.5` for
transparency). The breathing ring is semi transparent on top of the
existing white static semi-transparent ring, giving the breathing ring a
**tint** of the team color instead of the exact team color.
This allows a player to immediately identify their assigned team and
maintains overall consistency with FFA, Duos, Trios, and Quads game
modes.
See below for example implementation. In this screenshot, the self
player is on the red team as shown by the red tint to the breathing
spawn highlight ring. The screenshot also shows some of the static white
semi-transparent ring around the spawn location. The self player's
teammate is to the top left of the image with a solid red spawn
highlight. The non-player (nation) opponent on the blue team is shown to
the bottom left. In online games, nations are not present in team games.
In single player or private lobby games they are shown as here, without
a spawn color highlight and only a territory color.
<img width="402" height="292" alt="Team Spawn Color Tint"
src="https://github.com/user-attachments/assets/5696a408-a633-4ec8-bf93-c8afa8e2e121"
/>
## 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:
GlacialDrift
## Description:
This PR addresses issue #2297 - Spawn Color Overload in DUOS, TRIOS, and
QUADS game modes. This PR reverts the spawn highlight color behavior for
these game modes so that the player can identify their teammates more
easily in these modes.
See below for example fix. The "self" player and their teammate in this
DUOS mode game are the same `light blue` color as shown in issue #2297
and their opponent is still the same `brown` color as shown in that
issue.
However, now the player's teammate has a green spawn highlight color
(same as v0.26.7 and earlier) and the players on other teams have a
yellow spawn highlight color (same as v0.26.7 and earlier).
<img width="605" height="657" alt="Duos Teammate ID Resolution"
src="https://github.com/user-attachments/assets/6e62830a-31bb-4d3d-ae5a-34b809ea4e13"
/>
The "self" player's spawn highlight color remains a breathing white
ring, consistent with other game modes.
## 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:
GlacialDrift
**This PR improves spawn highlighting to identify self and friend/foe.
Suggested Label: Feature
Suggested Milestone: v26 or v27**
## Description:
**This PR changes the behavior for spawn color highlighting and
addresses issue #2270.**
Currently, the user's spawn highlight color is the same as all other
players in FFA and the same as all enemies in Team games. Although
"breathing" rings were added recently for the user's spawn highlight,
this can still be difficult to find on the map, especially with large
player counts.
This PR modifies how spawn highlights are drawn for the user and for
allies and enemies in Team games.
### User Spawn Color Updates
First, an additional spawn highlight color was added for the user in
`src/core/configuration/PastelTheme.ts`: `_spawnHighlightSelfColor`.
This is defined to be white (0xFFFFFF).
Second, the breathing ring was modified to improve visibility (all in
`src/client/graphics/layers/TerritoryLayer.ts`) :
- A radial-gradient transparent ring in the spawn color (white) is drawn
at all times
- The ring is transparent for `radius = 8` pixels from the player's
center point
- The gradient extends from `8` to `24` pixels from the player's center
point
- The first 10% of the ring (~ 1 pixel) is solid
- The remaining ring fades to transparent at `24` pixels
- A solid, "breathing" ring is drawn on top of the transparent ring
- The solid ring is also transparent for `radius = 8` pixels from the
center point
- The outer radius of the solid ring is a function of "time" in the same
way that the current breathing ring is implemented.
- The solid ring therefore grows and shrinks to cover the transparent
ring
### Other Player Spawn Color Updates
In FFA games, no change is made to the spawn color highlight of other
players. It remains `rgb(255,213,79)`.
In team games, the spawn color highlight of other players is updated to
use their team colors. For example, a player on the red team will have a
red spawn highlight, while a player on the purple team will have a
purple spawn highlight.
Both of these changes are handled with a simple update in
`src/client/graphics/layers/TerritoryLayer.ts` within the
`spawnHighlight()` method:
```typescript
const myPlayer = this.game.myPlayer();
if (myPlayer !== null && myPlayer !== human && myPlayer.team() === null) {
// In FFA games (when team === null), use default yellow spawn highlight color
color = this.theme.spawnHighlightColor();
} else if (myPlayer !== null && myPlayer !== human) {
// In Team games, the spawn highlight color becomes that player's team color
// Optionally, this could be broken down to teammate or enemy and simplified to green and red, respectively
const team = human.team();
if (team !== null) color = this.theme.teamColor(team);
}
```
### Attached Images
Three images have been attached. The three images show a progression of
the "breathing" user highlight. They also show the team-specific
highlights of players on other teams. (Note that Nations in the private
game were assigned teams but do not have spawn highlights).
<img width="1161" height="895" alt="Screenshot 2025-10-22 211929"
src="https://github.com/user-attachments/assets/71d466b8-61e4-4e30-83e5-06efdfc706ce"
/>
<img width="1322" height="934" alt="Screenshot 2025-10-22 212003"
src="https://github.com/user-attachments/assets/4e6c18b7-7f9e-436d-afb9-85a08a11c40b"
/>
<img width="1340" height="954" alt="Screenshot 2025-10-22 212028"
src="https://github.com/user-attachments/assets/597d0ed5-5519-4cf7-bc60-9963da3f7d7f"
/>
### Misc.
- I added `.idea/` to `.gitignore` because I use JetBrains IDEs
- I expanded the `fallbackColors` list. Right now it has a lot of green
colors, so I added equivalents for red, blue, cyan, magenta, and yellow.
## 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:
GlacialDrift
## Description:
The PR that added a highlight ring, broke highlights for other player
spawns. This PR fixes that, and makes the highlight ring more visible.
## 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:
### ✅ Summary of Changes
This PR enables the ESLint rule **`@typescript-eslint/no-unused-vars`**
as requested in the issue and applies the necessary code adjustments
across the project.
#### 🔧 What was done:
- Activated the rule `@typescript-eslint/no-unused-vars` in the ESLint
config.
- Updated ~70 files to comply with the rule:
- Replaced unused variables with a `_` prefix where appropriate.
- Added inline ESLint disable comments (`eslint-disable-next-line`) for
specific cases where the variable or code block seemed important for
context, readability, or future use.
- Ensured no linting errors remain related to this rule.
---
### ❓ Clarification
Some cases were handled with inline disable comments instead of removing
the variable entirely, to avoid accidental breaking changes or loss of
intent.
If a different approach is preferred (e.g., stricter removal or
alternative handling), I’m happy to adjust the implementation
accordingly — just let me know!
---
### 🙌 Next Steps
Please review and let me know if:
- Any file should be handled differently.
- You prefer removal instead of disabling in certain areas.
- Additional rules should be enforced or reverted.
I’m available to make any follow-up improvements needed.
---
### 🎃 Hacktoberfest Note
I'm participating in **Hacktoberfest**, so if this PR is accepted,
please add the label:
`hacktoberfest-accepted`
Thank you!
#1784
## 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:
DISCORD_USERNAME
## Description:
Add support for colored territory patterns/skins
* Refactored & updated territory pattern rendering to render colored
skins
* rename public from pattern to skin (keep pattern name internally, too
difficult to rename)
* Moved all territory color logic to PlayerView
* Updated WinModal to show colored skins
* Refactored decode logic into a separate function: decodePatternData
* Refactored/updated how cosmetics are sent to server. Players now send
a PlayerCosmeticRefsSchema in the ClientJoinMessage.
PlayerCosmeticRefsSchema just contains names of the cosmetics, and the
server replaces the names/references with actual cosmetic data
* Refactored PastelThemeDark: have it extend Pastel theme so duplicate
logic can be removed.
*
## 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:
Noticed many people are struggling to see where they choose to spawn or
forget where they chose , what leads to confusion.
solved it with this animation around the spawning player cell.

<img width="231" height="265" alt="image"
src="https://github.com/user-attachments/assets/22e157a5-301d-4d41-8f2c-21a9dd09a1f6"
/>
ALSO: Added a missing translation for hebrew
## 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:
boostry
Co-authored-by: evanpelle <evanpelle@gmail.com>
## 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
## Description:
Improve existing alternate view (space bar).
It now displays territories in different colours based on their status
(enemy, allied, or your own).
Hovering over a territory highlights it. I tested several approaches,
and this one delivers excellent performance (on mobile too).


## 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
Related issue:
https://github.com/openfrontio/OpenFrontIO/issues/900https://github.com/openfrontio/OpenFrontIO/issues/484
## Please put your Discord username so you can be contacted if a bug or
regression is found:
devalnor
## Description:
Make territory pattern less dark, from .2 => .125 darker. It's still
very legible and a bit less harsh.
I think we should err on the side of being too light, because we can
always darken it, but people will be upset if we ever lighten it in the
future since they'll feel rug pulled after paying for the pattern.
## Please complete the following:
.2
<img width="496" alt="Screenshot 2025-07-02 at 10 53 44 AM"
src="https://github.com/user-attachments/assets/0ee29bc0-ec05-482d-bfa7-b032cef57eba"
/>
.125
<img width="577" alt="Screenshot 2025-07-02 at 11 09 55 AM"
src="https://github.com/user-attachments/assets/83dcac0d-169b-47a4-bf6b-d4778ca496ba"
/>
.1
<img width="594" alt="Screenshot 2025-07-02 at 10 54 47 AM"
src="https://github.com/user-attachments/assets/893a18f2-9e56-464e-b072-c2bd7f464f02"
/>
- [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:
evan
## Description:
Replace the HTML element pattern grid with a PNG image.


## 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
## Description:
Remove Cosmetics from PlayerInfo. The game engine should have no
knowledge of cosmetics since they shouldn't affect game play at all.
Instead pass player cosmetics into the GameView.
## 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:
evan
## Description:
This is meant to give players more customization options.
Permission handling hasn’t really been implemented yet.
## 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:
aotumuri
## Description:
this is a fix for the "possibly null" error. dosent seem to cause
runtime issues but does cause the compiler to throw an error this just
adds a safety check
## Please complete the following:
- [x] I have added screenshots for all UI updates (No UI Updates)
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file (No Text Updates)
- [x] I have added relevant tests to the test directory (No Tests to
add)
- [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:
jerryslang
## Description:
Tiles are only run through putImageData() if they are currently viewed
by the player.
This significantly (usually between 20-80%) reduces the computation time
of putImageData() on large maps.
## Please complete the following:
- [x] I have added screenshots for all UI updates
- [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:
1brucben
---------
Co-authored-by: evanpelle <evanpelle@gmail.com>
## Description:
Improve type safety and runtime correctness by:
1. Enabling TypeScript's
[strictNullChecks](https://www.typescriptlang.org/tsconfig/#strictNullChecks)
compiler option.
2. Replacing all loose equality operators (`==` and `!=`) with strict
equality operators (`===` and `!==`).
3. Cleaning up of type declarations, null handling logic, and equality
expressions throughout the project.
Currently, the code allows implicit assumptions that `null` and
`undefined` are interchangeable, and relies on type-coercing equality
checks that can introduce subtle bugs. These practices make it difficult
to reason about when values may be absent and hinder the effectiveness
of static analysis.
Migrating to strict null checks and enforcing strict equality
comparisons will clarify intent, reduce bugs, and make the codebase
safer and easier to maintain.
Fixes#466
## Please complete the following:
- [x] I have added screenshots for all UI updates
- [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
---------
Co-authored-by: Scott Anderson <662325+scottanderson@users.noreply.github.com>
Co-authored-by: evanpelle <openfrontio@gmail.com>
## Description:
Small optimisation in TerritoryLayer.renderLayer call to dedupe
Date.now()
## Please complete the following:
- [-] I have added screenshots for all UI updates
- [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:
N/A
Co-authored-by: robertpitt <robertpitt1988@gmail.com>
## Description:
Fixes a couple of bugs with the defended border color:
- When a defense post is destroyed it doesnt redraw defended border to
normal ones
- The distance to draw borders at unit update is not the same as
territory update
- When a defense post changes owner, only the directly touching borders
were redrawn. Had to refactor units a bit so it keeps track of the last
owner
## Gifs:
Before fix:

After fix:


## Please complete the following:
- [x] I have added screenshots for all UI updates
- [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:
VivaciousBox
## Description:
The borders near a defense post are currently colored differently, but
too discreetly for the user.
I suggest coloring them with a checkerboard pattern.


## Please complete the following:
- [x] I have added screenshots for all UI updates
- [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
## Description:
## Please complete the following:
- [x] I have added screenshots for all UI updates
- [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:
Readix
Tried to implement feature to outline player under mouse cursor.
Intention is to improve gameplay and provide a way to estimate players
territories for strategic planning / avoid attacking wrong players with
confusingly similar colors.
When you stop cursor at the player - his borders will be drawn in white
color.
To focus on other player - click or move cursor to other player.
To hide outline - click on empty space (water, land).
"Focus" UI feature also triggers outline for the target player (easier
to see who exactly is that you are looking at).




Done via getting player under mouse cursor, setting it as global
focusedPlayer and painting borders in white color.
Tried to maintain minimal changes and utilize existing rendering queue.
Also added hover delays to avoid excessive redraws and provide better
experience. Redraws only happens when focusedPlayer changes - one time
for old focused player to clean outline and one time for new focused
player.
added a unitgrid instead of a defensepostgrid for all units to be able
to see if a tile is inside the range of a unit by a custom distance
this is used for the sam launcher to draw a circle around the area it
protects
removed all parts that use the defensepostgrid and made it use the
unitgrid instead