mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-05 10:32:04 +00:00
d9ec9b0e401150a42f991df41a36bc06d8490292
330 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d9ec9b0e40 | Restore troop/gold ratio slider and worker allocation | ||
|
|
c911bfb2d8 |
Packed unit updates / MotionPlans (#3292)
## Description: Reduce per-step `Unit` update traffic by shipping packed motion plans and letting the client advance plan-driven units locally. Changes: - Add packed motion plan records (`packedMotionPlans?: Uint32Array`) to game updates and transfer the buffer worker -> main. - Introduce `src/core/game/MotionPlans.ts` (schema + pack/unpack) for grid + train motion plans. - Extend `Game` with `recordMotionPlan(...)` and `drainPackedMotionPlans()`, and implement buffering/packing in `GameImpl`. - Treat units with motion plans as “plan-driven”: suppress per-tile `Unit` updates on `move()` and advance positions client-side. - Emit motion plans from executions: - `TradeShipExecution`: record/update grid motion plans and `touch()` when changing target after capture. - `TransportShipExecution`: record initial plan and update it when destination changes. - `TrainExecution`: record a train plan on init (engine + cars). - Client: apply motion plans in `GameView` and ensure `UnitLayer` updates sprites for motion-planned units even when no `Unit` updates arrived. ## Please complete the following: - [ ] I have added screenshots for all UI updates - [ ] 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 - [ ] 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 |
||
|
|
339ace0bd6 |
v30 nuke wars preparation: Disable boats & Team spawn zones (#3263)
## Description: Preparation for nuke wars, for v30. Next PR will be adding the nuke wars modifier for public games, but Wonders https://github.com/openfrontio/OpenFrontIO/pull/3224 needs to be merged first to avoid merge conflicts. ### 1. Disable boats setting It's possible to disable `UnitType.TransportShip` now. Because they are not needed in nuke wars and can even be annoying. <img width="720" height="320" alt="image" src="https://github.com/user-attachments/assets/661bc10d-b204-4b4f-b876-ee7c9b92de8c" /> ### 2. Team spawn zones for random spawn Maps can have `teamGameSpawnAreas` in their json file now. Spawn areas are currently active if - a supported map is chosen (Baikal Nuke Wars or Four Islands) - a supported team size is chosen (2 teams on Baikal Nuke Wars or 2/4 teams on Four Islands) - random spawn is enabled ## 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 |
||
|
|
ea2a76609f |
perf(core): speed up packedTileUpdates (Uint32 pairs, no tile wrappers) (#3255)
## Description Reduces CPU + GC pressure from tile update serialization. **What changed** - Switched `packedTileUpdates` from `BigUint64Array` (BigInt packing) to `Uint32Array` `[tileRef, state]` pairs, updating `GameView` ingestion. - Updated tile state to use `GameMap.tileState(tile)` and `GameMap.updateTile(tile, state)`. - Removed per-tile `GameUpdateType.Tile` wrapper allocations by recording raw `(tile, state)` pairs in `GameImpl` and draining them via `drainPackedTileUpdates()` in `GameRunner`. **Why it’s faster** - Avoids BigInt and pack/unpack. - Avoids per-tile object allocations. **Compatibility** - Wire format change: `packedTileUpdates` is now `Uint32Array` pairs instead of `BigUint64Array`. ## Please complete the following: - [ ] I have added screenshots for all UI updates - [ ] 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 - [ ] 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 |
||
|
|
90204f6628 |
Add alliance renewal action to Radial Menu (#3148)
## Description: The following PR replaces the (disabled) alliance request button with an alliance extension/renewal button when the alliance with the target player is expiring. Agreeing to renewal via radial menu also hides the message in the EventsDisplay. <img width="369" height="364" alt="image" src="https://github.com/user-attachments/assets/d8040f5c-ad7b-47d0-852f-925ecbf273a8" /> https://github.com/user-attachments/assets/aa589edf-6505-46bf-88a3-aa4c2df9137f Icon size adjusted: <img width="294" height="252" alt="image" src="https://github.com/user-attachments/assets/7ca63500-b1fb-427b-965c-cf121a5213da" /> ## 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 --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> |
||
|
|
8b66c8bd53 |
Perf/refactor: use StructureTypes, remove territoryBound (#3238)
## Description: PR 6/x in effort to break up PR https://github.com/openfrontio/OpenFrontIO/pull/3220. Follows on already merged https://github.com/openfrontio/OpenFrontIO/pull/3237. Please see if these can be merged for v30. - **PlayerImpl**: validStructureSpawnTiles did a filter on unit types to get isTerroritoryBound units, on every call again. It read this from unit info in DefaultConfig. While having it centrally in DefaultConfig unitInfo is good for maintainability, other code uses hardcoded StructureTypes and isisStructureType from Game.ts. Which has the same purpose and thus contains the same unit types. StructureTypes and isisStructureType do need manual maintainance outside of DefaultConfig. And are more bug prone/less type safe. But, using them gives more speed compared to getting these unit types out of DefaultConfig unitInfo centrally with some cached function in GameImpl for example (tested with buildableUnits and MIRVPerf.ts). So I went with StructureTypes in validStructureSpawnTiles too. - **PlayerExecution**: now validStructureSpawnTiles no longer needs isTerritoryBound (see the point above), PlayerExecution is the last place where it was used. Replaced it for isStructureType here too (since it has the same meaning and outcome). - **Game.ts** and **DefaultConfig** unitInfo: remove the now unused _territoryBound_. As it was only used in validStructureSpawnTiles and PlayerExecution and has been replaced in both (see the two points above). ## 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: tryout33 |
||
|
|
4f08e57304 |
Small refactor: nearbyUnits readonly UnitType[] (#3236)
## Description: PR 4/x in effort to break up PR https://github.com/openfrontio/OpenFrontIO/pull/3220. Follows on already merged https://github.com/openfrontio/OpenFrontIO/pull/3235. Please see if these can be merged for v30. - **Game**/**GameImpl**/**GameView**: nearbyUnits required "UnitType | UnitType[]" for tiles, but calls UnitGrid nearbyUnits which requires "UnitType | readonly UnitType[]". Made the requirement the same for Game/GameImpl/GameView nearbyUnits. This way, we don't have make a shallow copy of the StructureTypes array everytime we want to send it as an argument. Other callers than listNukeBreakAlliance in Util.ts are unaffected. - **Util.ts**: listNukeBreakAlliance needs no shallow copy of StructureTypes anymore as argument for NearbyUnits ## 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: tryout33 |
||
|
|
ba2a947061 |
Feat: Display ghost railways when building cities and ports (#3202)
## Description: Based on [this suggestion on Discord](https://discord.com/channels/1284581928254701718/1447110257196138577) and feedback gathered in [this thread](https://discord.com/channels/1359946986937258015/1469598906173227184). Supersedes #3143 This PR introduces "ghost railways": when you are going to place a city or port, previews railway connections that will be made when actually building the structure. Ghost railways are skipped if the structure is going to be snapped to existing railways (as in railway snapping functionality introduced in #3156 ). ### Video https://github.com/user-attachments/assets/ff8cf325-6501-4df8-801d-c8ae3ced3d0e ### Ghost rails color revisited black with 40% opacity <img width="695" height="430" alt="image" src="https://github.com/user-attachments/assets/272efbcc-4185-426a-921c-7fae61f6c462" /> ## 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 |
||
|
|
52036cc20c |
Cleanup: remove unused code from four files (#3234)
## Description: PR 2/x in effort to break up PR https://github.com/openfrontio/OpenFrontIO/pull/3220. Removes unused code and properties. - **Game.ts** and **DefaultConfig** unitInfo: removed _canBuildTrainStation_ and _expirimental_ properties, as they weren't used anywhere anymore. - **PlayerActionHandler**: remove unused getPlayerActions, the only potential caller MainRadialMenu already just calls myPlayer.actions via GameView directly. - **StructureIconsLayer**: remove unused PlayerActions ## 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: tryout33 |
||
|
|
0b46f90d81 |
Feature add alps clean (#3229)
## Description: Fixes closed PR and adds the new “Alps” map and register it in the game/map playlist. With 7 geographically accurate nations. Pure large land map for land warfare only. <img width="2564" height="1400" alt="Untitled" src="https://github.com/user-attachments/assets/2c51fad3-7345-46a8-9256-2874d1c4211b" /> <img width="2000" height="1837" alt="551068953-fe4445cd-c0b2-4a5a-b652-1e480e38cdb6" src="https://github.com/user-attachments/assets/1c466262-e20b-46bc-b782-944cbf6ee62a" />  ## 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 |
||
|
|
86e51ab790 |
Fix nation spawnkilling 🔧 (#3222)
## Description: As far as I can remember, in v28 the spawn immunity applied to both humans and nations. With the configurable spawn immunity (added for v29) the spawn immunity no longer applies to nations... Because its called PVP immunity now. So right now it's possible to spawnkill nations. This is a big problem for the 5M gold modifier games... And you can "cheat" in singleplayer. This PR changes two things: - Nations always have 5 seconds spawn immunity now, no matter whats configured for the PVP immunity - Nations attack TerraNullius earlier (Otherwise the easy nations would sometimes do their first attack after the 5 seconds are over, spawnkills would still be possible) ## 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 --------- Co-authored-by: Ryan <7389646+ryanbarlow97@users.noreply.github.com> |
||
|
|
040766d417 |
Add units filter on playeractions for performance (#3213)
## Description: The ghost structure calls player actions each frame, which is costly since it's checking for all possible actions. This add a unit list filter in actions so if there are units it only checks for buildability of those units. Before:  Player actions takes 20-30% of the worker After: <img width="825" height="342" alt="image" src="https://github.com/user-attachments/assets/36e47547-5028-4dc9-bc42-e17df4a87200" /> Player actions takes 1-3% of the worker Both performances are relevant only when a ghost structure is selected ## 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: Mr. Box |
||
|
|
6e557c52db |
Add Hawaii map (#3187)
## Description: Add Hawaii as a new regional map. Features 9 nations across the Hawaiian island chain (Niihau, Kauai, Oahu, Molokai, Lanai, Kahoolawe, Maui, Kona, Hilo). ~~612K land tiles at 3920x2544~~ 408K land tiles at 3200x2076, terrain generated from real relief data with accurate volcanic peaks and coastal lowlands. Playlist frequency: 4.  ## Checklist - [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 Source: https://commons.wikimedia.org/wiki/File:USA_Hawaii_relief_location_map.svg Discord: gabigabogabu |
||
|
|
07e13b3479 |
Fix: remove alliances on death (#3168)
## Description: - Remove alliances on death: after death, alliances would stay active including countdown timers and (when dead player kept spectating) icons. Now remove them when player becomes inActive. - Moved code to private method within PlayerExecution + added comments in NationExecution and BotExecution for more clarity as to where removals are performed from at death - Remove renewal request from Events Display when Alliance doesn't exist anymore (after death or otherwise). - Also cleanup this.alliancesCheckedAt when alliance doesn't exist anymore. Before, old/broken alliance id's would accumulate in it during a game. - Removed now-redundant isAlive check in EventsDisplay. Both the alliances array as the isAlive are updated in the same tick from PlayerUpdates so now alliance is removed from alliances array on player death, the other.isAlive() check is no longer needed. Of course we could keep it in just to be very safe, so just let me know when you're doubtful about this. - Attack.test.ts: fix failing test. Player B dies because of the attack, meaning the alliance now gets removed. Prevent this by gving both a different, adjecent, starting tile. And to be more clear about what is needed for the test to pass, add isAlive check for both of them after the attacks. ## 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: tryout33 |
||
|
|
c44130cf32 |
New map! "Traders Dream" 🏝️ (#3177)
## Description: A redditor posted this, got quite a few upvotes <img width="753" height="667" alt="image" src="https://github.com/user-attachments/assets/9cd6664f-6afa-428a-b85e-4c335dbe1699" /> https://www.reddit.com/r/Openfront/comments/1qlrqro/these_maps_are_so_fun_i_want_more/ So I thought why not make another one, this time a bit focused on traders (tiny islands to trademaxx) And two big islands (about 50% of the map land tiles). So its big islands vs small islands. <img width="1098" height="959" alt="Screenshot 2026-02-10 231024" src="https://github.com/user-attachments/assets/32368223-bef4-4ba1-a203-29d9afd5b762" /> 13 nations :) 2200 × 1920 ## 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 |
||
|
|
c6c793f6b3 |
Highlight hovering railroad (#3156)
## Description:  The `RailroadLayer` simply displays tiles as instructed by the core worker. While it's practical for the layer to only care about the tiles, it also means it has no understanding of railroads as entities (their paths, connections, or identities). It also means that the core worker is responsible for rendering tasks such as tile orientation and construction animation, which is not expected. To support ID-based events and better separation of concerns, the rendering layer needs to be aware of complete railroads. With this change, the core worker can send the tiles once and subsequently reference railroads only by ID for all other events. #### Changes: - `RailroadLayer` now stores full railroad data instead of only individual tiles - `RailroadLayer` is responsible for animating newly built railroads - Add a new `RailroadSnapUpdate` sent when a new structure is built over an existing railroad. This event is used by `RailroadLayer` to keep railroad ID in sync. - When hovering over a railroad, the render worker is querying the core worker about overlapping railroads. Alternatively, RailroadLayer could compute overlaps itself now that it has full railroad knowledge, but this logic would need to be duplicated and kept in sync across workers. Keeping a single source of truth in the core worker is preferred. #### Edgecases: - When a structure snaps over a railroad, the original railroad is split into two new railroads. If the construction animation is still in progress, instead of resuming the animation at the correct point on the new railroads, all remaining tiles are rendered immediately - Previously, `RailroadUpdate` handled both construction and destruction. This no longer works with `RailroadSnapUpdate`, as event ordering is now pretty important and IDs may be lost before they are consumed. To address this, RailroadUpdate is split in two: `RailroadConstructionUpdate` and `RailroadDestructionUpdate`. ## 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 --------- Co-authored-by: jrouillard <jon@rouillard.org> |
||
|
|
e97f4650b7 |
Readd Yenisei (#3145)
## Description: This PR readds the Yenisei map, with it being about 3 times smaller than before. I haven't updated the en.json file, as it still has the string for the map, which was probably forgotten when the map got removed from the repo. ## 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 Nikola123 |
||
|
|
13117251af |
Add new map “The Box” (#3054)
<img width="1670" height="200" alt="banner" src="https://github.com/user-attachments/assets/b6561231-71dc-46dd-a521-453d4e97931f" /> ## Description: This proposal adds a new, completely flat map called "The Box," where players will find themselves on a completely flat landmass and will only be able to trade by land using trains and factories. - Map size: 2048×2048 pixels - Binaries generated with MapGenerator (map.bin, map4x.bin, map16x.bin) - Integrated into arcade category and multiplayer playlist - English and Spanish translations added - 13 nations/bots with unique and thematic names: > - **Middle Defender (located in the center)** > - **King of the Corner (located in the top-left corner)** > - Suspicious Ally > - Punch Merchant > - Nuke Thrower > - Fullsender > - Factory Builder > - Front Manager > - Box Fighter > - Cage Liberator > - Train Trader > - Non-peaceful Bot > - **Evan The Dev** (special mention) All other bots are distributed to cover the map evenly. <img width="838" height="835" alt="Screenshot 2026-01-28 at 17 39 45" src="https://github.com/user-attachments/assets/4665088d-cb94-4db3-8602-8a22b63bfee2" /> ## 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: sardidefcon |
||
|
|
7942990037 |
Crowded modifier 😄 (#3023)
## Description: To increase variety a bit more I present: The "crowded" public game modifier :) It basically simulates a crazy youtuber lobby. Cramp a lot of players on a small map 😄 I think its fun, exciting and you actually need skill to manage the chaos. 5% of public games get this modifier, but because we remove the modifier for big maps its more like 2.5% (should be something special) | <img width="321" height="269" alt="Screenshot 2026-01-25 200427" src="https://github.com/user-attachments/assets/7d2e90c1-e6bc-40a8-a19e-a0849612f472" /> | <img width="317" height="264" alt="Screenshot 2026-01-25 200554" src="https://github.com/user-attachments/assets/8b4bd5da-bed1-4743-a107-9ce07fce3040" /> | <img width="317" height="244" alt="Screenshot 2026-01-25 200521" src="https://github.com/user-attachments/assets/16293de3-0fc4-431f-8151-31b4e11040fe" /> | |---|---|---| ## 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 |
||
|
|
f7d3c2e0bc |
Nations donate troops now 💀 (In team games) (#2984)
## Description: For v29, balances the HvN winrate. In team games, nations now donate troops to their weakest team members (if they have no attack options available). How often they donate depends on the difficulty. This PR also has some other little fixes: - For HvN games, always return true in `shouldAttack()` (make nations a bit more aggressive). - Early exit in `attackWithRandomBoat()` for performance - Early exit in `findNearestIslandEnemy()` for performance AND to make sure nations which are encircled by friends don't run into this method (=> no donation happening!) ## 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 |
||
|
|
a4a41ac9f4 |
Fix map name formatting for Baikal Nuke Wars 🔧 (#2922)
## Description: Fixes this little i18n problem: <img width="732" height="172" alt="Screenshot 2026-01-16 050833" src="https://github.com/user-attachments/assets/65fe27a6-f77a-49d9-94a9-145b4e719a88" /> ## 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 Co-authored-by: Ryan <7389646+ryanbarlow97@users.noreply.github.com> |
||
|
|
fb910cbff5 |
Lobby Gold Options (Starting Gold, Gold Multiplier) 💰 (#2915)
## Description: We might want to add this to v29 to have a third possible public game modifier from the beginning on 😄 Would be fun - Add starting gold option (0 to 1_000_000_000 allowed, also applies to nations) - Add gold multiplier option (0.1 to 1000 allowed, also applies to nations and bots) - Add third public game modifier (3% chance of starting with 5M gold) - Why 5M? It's enough gold to massively change the game start but not enough to insta-hydro someone (launcher + hydro is 6M) <img width="357" height="140" alt="image" src="https://github.com/user-attachments/assets/72acc15c-e788-4e04-8590-ac72dd9657c7" /> ## 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 |
||
|
|
42c944c9cc |
Create ranked type enum, last person not afk wins in 1v1 (#2892)
## Description: * Add RankedType enum, for now it's just 1v1 * Add new method to MapPlaylist to create 1v1 game config * Update WinCheck so the last player is declared a winner on 1v1. ## 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 |
||
|
|
35b7213c5c |
Enhance nuke alliance breaking logic to account for allied structures in blast radius 💣 (#2887)
## Description: Doesn't need a description :D https://github.com/user-attachments/assets/8de576fd-050b-4b35-8526-e4c88d1a9f25 https://github.com/user-attachments/assets/c99147a1-efdf-426b-96d1-e996e01f89aa ## 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 |
||
|
|
0e3ced3bfa |
Pathfinding Refactor pt. 2 (#2866)
## Playtest https://pf-pt-2.openfront.dev/ ## Pathfinding Refactor pt. 2 <img width="1536" height="1024" alt="image" src="https://github.com/user-attachments/assets/9477958e-54b7-4c83-b317-ba789e809e9e" /> This is a follow-up to a previous PR introducing pathfinding changes. This time, it introduces a complete refactor of `pathfinding` directory and breakdown into composable pieces. ### Unified PathFinder interface `PathFinder<T>` and `SteppingPathFinder<T>` are introduced to unify **all** pathfinding across the application. First one exposes complete path, while stepping variant allows the callee to iterate over the path by calling `.next`. All pathfinders share this one common interface, which makes them easy to use in any scenario - `PathFinding.Water(game).search(from, to)`. `SteppingPathFinder<T>` extends `PathFinder<T>` with an ability to iterate over the path. It handles caching, storing current index and invalidation. This allows the units to not care about the inner workings of the pathfinder and just call `pf.next(current, target)` and receive instructions on what to do next. ### Common entry point All pathfinders are now exposed from common `PathFinding` entrypoint: - `PathFinding.Water` - `PathFinding.Rail` - `PathFinding.Stations` - `PathFinding.Rail` Additional entry point is introduced for pathfinders which need to work both in the worker, but also on the frontend, which lacks `Game` interface. Currently only `UniversalPathFinding.Parabola` is available. ### Spatial Query New module has been introduced close to `pathfinding` - `SpatialQuery`. It aims to resolve any questions game may have about finding tiles meeting criteria. Currently `SpatialQuery.closestShore(player, target)` and `SpatialQuery.closestShoreByWater(player, target)` are available - they help answering questions about naval invasion: "What is the best landing location from user's click?" and "Which our tile should be used to launch the transport ship?". Under the hood they use very similar mechanics to pathfinding, so it felt right to put them close by. ### Modular architecture Pathfinders now support transformers: `MiniMapTransformer`, `ShoreCoercingTransformer`, `ComponentCheckTransformer`, `SmoothingTransformer`. Transformers functions like a middleware in the pathfinding chain. They wrap around the pathfinder and provide additional functionality. This allows the pathfinder to focus on actually finding the path instead of doing unrelated things. Example chain for simple (A*) water pathfinding: ```ts static WaterSimple(game: Game): SteppingPathFinder<TileRef> { const miniMap = game.miniMap(); const pf = new AStarWater(miniMap); return PathFinderBuilder.create(pf) .wrap((pf) => new ShoreCoercingTransformer(pf, miniMap)) .wrap((pf) => new MiniMapTransformer(pf, game.map(), miniMap)) .buildWithStepper(tileStepperConfig(game)); } ``` The Pathfinder - here `AStarWater` - does not care about the conversion between minimap and main map tiles. It also does not care if the source or destination is a land tile. The transformers take care of that. The pathfinder gets a set of valid coordinates and produces the path - that's it. Modular approach makes working on a particular set of utilities much easier - for example map upscaling is handled consistently across all pathfinders. Additionally, the pathfinders are not tied to the particular map resolution used. Pass them a different map and they will work the same. ### Algorithms Algorithms used are neatly organized inside `src/core/pathfinding/algorithms`. They are prefixed with the algorithm name and suffixed with the use case. File without suffix exposes generic version ready to traverse any graph with adapters. Specialized versions either use an adapter or inline logic when performance is critical - using adapters leads to 20-30% performance loss. The directory includes `A*` and `BFS` but also other useful utils, such as `AbstractGraph` used to generate... an abstract graph on top of the tile map and `ConnectedComponents` helping to identify whether two tiles are connected by a path without actually computing the path. ### Playground The playground have been updated with new algorithms, including tweaked very greedy `A*`. <img width="2175" height="1424" alt="image" src="https://github.com/user-attachments/assets/1f833651-0024-4299-bf86-882f5368358c" /> ### Tests Yeah, there are some, a little too many if I say so myself. But there are no useless tests. I had to ensure refactored code works somehow reliably. This PR comes with trust me bro guarantee, but I would appreciate someone confirming **naval invasions, nukes (esp. MIRV) and warships**. ### Discord `moleole` GL & HF |
||
|
|
e130574c5c |
Very small UI fix 🔧 (#2862)
## Description: Didier map name had a little UI problem. And unrelated change: Because Lewis today said "it should be super low" I turned down the frequency of this map from 2 to 1. Previous: <img width="1916" height="1312" alt="image2" src="https://github.com/user-attachments/assets/0a84160b-91a8-4d02-b707-fa9eea1a15fd" /> Fixed: <img width="562" height="476" alt="image" src="https://github.com/user-attachments/assets/31fed7b5-c128-45cd-a63d-0aab3345cea3" /> ## 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 |
||
|
|
dc118708c0 |
Second Didier Map for Fuze 🧸 (#2846)
## Description: Discussed that with Lewis. Fuze liked the Didier map without the real france more... So here it is. It won't get added to the playlist, the france version stays in the playlist. (Unrelated: Also quickly changed "Europe (classic)" to Europe (Classic)" to match with "Britannia (Classic)") <img width="934" height="839" alt="Screenshot 2026-01-10 005646" src="https://github.com/user-attachments/assets/64925635-c15a-4167-a5bc-5cf7b3b140f8" /> <img width="1064" height="961" alt="Screenshot 2026-01-10 003335" src="https://github.com/user-attachments/assets/9b6aa936-2c33-4a24-8076-a74a4704adc4" /> <img width="635" height="427" alt="Screenshot 2026-01-10 003316" src="https://github.com/user-attachments/assets/e2b46db8-ef0b-4b45-8ea7-711b9b8f7524" /> ## 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 |
||
|
|
8b6dfeaf4a |
Feat: Sierpinski map - live play-tested (#2819)
## Description: Map requested by creator on [dev discord](https://discord.com/channels/1359946986937258015/1458638914012315741/1458638914012315741) and playtested by 42 players on [Rex's stream](https://www.youtube.com/watch?v=r9w9nr5Toso), adds map Sierpinski, which is a sierpinski carpet shape. The map is a "party map" great for private matches, but is not part of the public map rotation. <img width="1400" height="1400" alt="image" src="https://github.com/user-attachments/assets/8eead359-73d5-497f-8fee-40f413a22d0e" /> https://github.com/user-attachments/assets/3a726343-18e4-4f91-9f5c-1fff459d5a5f ## 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 --------- Co-authored-by: iamlewis <lewismmmm@gmail.com> |
||
|
|
971e7f4a45 |
Move UI elements from the FX layer to a new UI layer (#2827)
## 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 |
||
|
|
b090f2f624 |
HPA* Pathfinding (#2815)
## 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:
|
||
|
|
516d268c88 |
Restructured PR for Britannia Remastered Addition (#2813)
## 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> |
||
|
|
ebcb654825 |
Added a public game modifier system 😮 For more variety (#2801)
## 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 |
||
|
|
387190b916 |
New map! "Amazon River" 🏞️ (#2798)
## Description: We didn't have a river map and we didn't have a map with a crazy size. So I made a "Amazon River" map with a crazy size. 280 x 5536! 21 nations based on real locations. Should be interesting gameplay because you don't have many attack options, your only escape is the river. The land tiles size is similar to the achiran and iceland map. <img width="2442" height="147" alt="Screenshot 2026-01-06 150831" src="https://github.com/user-attachments/assets/91c4142d-c1e3-4aee-ac49-529b8d9f60c4" /> <img width="2324" height="139" alt="Screenshot 2026-01-06 150957" src="https://github.com/user-attachments/assets/5e049ae5-f32a-495f-afde-9e20257b3676" /> Because the map is so wide, it looked really ugly stretched in the thumbnails. So I added some CSS which removes the thumbnail stretching of the Amazon River map. We can also use this logic for other thumbnails which shouldn't get stretched. In `Maps.ts`, `PublicLobby.ts` and `GameInfoModal.ts`. ## 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 |
||
|
|
ecc174d248 |
New map! "Didier" 🧸 (#2794)
## Description: Didier map for the big french youtuber Fuze which already published several OpenFront videos. I took the real france, cut away the bordering countries and made it look like Didier 😄 Gave it eyes, hands and feet. Made sure we have some rivers, also put Corsica in the right bottom corner! It's quite large. Similar to the europe map. Has 42 nations (38 french cities and 4 funny custom nations for the youtuber). Made with [TsProphets map generator](https://github.com/TsProphet94/OpenFrontMapGenerator), QGIS and GIMP. For public games I put a rare map frequenzy of 2 because most people probably don't know Fuze. @ibnhalwa from discord gave some insider knowledge about Fuze (He's french, I'm not). <img width="2100" height="2250" alt="image" src="https://github.com/user-attachments/assets/5d1c3c45-4b2e-4f60-a02f-89b26f938652" /> <img width="1278" height="1218" alt="Screenshot 2026-01-05 184540" src="https://github.com/user-attachments/assets/6e300bb0-6e9f-4b0f-bad8-94f031d250b1" />  ## 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 |
||
|
|
af0b8a8d50 |
Configurable immunity timer (#2763)
## Description: Resolve discussions about stalled PR https://github.com/openfrontio/OpenFrontIO/pull/2460 <img width="724" height="348" alt="image" src="https://github.com/user-attachments/assets/c2c9fa79-cace-431a-9ca4-b3656612fa9d" /> Changes: - Added a `Player::canAttackPlayer(other)` function to determine whether a player can be attacked. - This function is now used in most places where a fight can occur: - AttackExecution (land attacks) - Naval invasion - Warship fight - Nukes can't be thrown during the truce - Immunity only affect human players. Nations and bot will fight as usual, and can be fought against. - The immunity timer uses minutes in the modal window. UI: - The immunity phase is displayed with a timer bar at the top. This is from the original PR, to be discussed if it's not deemed visible enough: <img width="632" height="215" alt="image" src="https://github.com/user-attachments/assets/f5ab9aa0-bd4f-4503-b8d6-b40b121fba65" /> ## 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 --------- Co-authored-by: newyearnewphil <git@nynp.dev> |
||
|
|
ab5b044362 |
Fix train was destroyed message spam (#2774)
## Description: Trains are made of a primary unit (`TrainExecution.train`) followed by 6 cars (`TrainExecution.cars`). Currently when any of the units is destroyed, a message "Your Train was destroyed" is shown. In worst case scenario, when all cars are blasted by a nuke, 7 messages are displayed to the user, but the train continues. Since the actual logic is unaffected as long as the primary unit stays alive, displaying messages is confusing. This PR fixes it. The message is only displayed when the primary unit is destroyed. The following cars are only there for fancy visuals. ## Screencast ##### Current - multiple messages for single train https://github.com/user-attachments/assets/3df04c71-d899-4f68-af83-36c9d0ffa730 First nuke was a test. Second nuke destroyed the entire train, prompting 7 messages. Third nuke destroyed one full train and then some. Prompting many too many messages. ##### Fixed - one message, only if train was fully destroyed https://github.com/user-attachments/assets/1f3840a7-6c62-487d-af3a-82de39dad9e8 First train was only partially destroyed, no message was shown, delivery mission completed A+. Following 2 trains had the front engine destroyed and therefore were promptly decommissioned. ## Please complete the following: - [x] I have added screenshots for all UI updates - [ ] 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 ## Please put your Discord username so you can be contacted if a bug or regression is found: moleole |
||
|
|
1eee8b4ddb |
New Map! "Surrounded" 🏝️ (#2770)
## Description: A new map where you basically have to hop from island to island :) We don't have such a map at the moment. There is a special center island which isn't necessary to get 80% of the map. This map could be very interesting in team games. One hydro will destroy an entire island. Size: 1976 x 1976 Nations: 8 <img width="949" height="951" alt="Screenshot 2026-01-02 214219" src="https://github.com/user-attachments/assets/7139bcc9-6a05-414d-90c1-33cc36dd94fb" /> ## 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 |
||
|
|
9d5f167446 |
Feat: Strait of Hormuz map (#2747)
## Description: Introduces the Strait of Hormuz section in the Persian Gulf as a map! This map is actually crazy fun to play on because of how the water narrows to a small strait where control is necessary otherwise enemies can transport boat to you easily. I figured a strategic map based on modern-ish day conflicts would fit the theme, but man it's a great map to play on. ### Full Map <img width="2739" height="1822" alt="image" src="https://github.com/user-attachments/assets/f35bdefa-723a-4bb2-9dc9-fb42898528ce" /> ### In game with nations <img width="2218" height="1502" alt="image" src="https://github.com/user-attachments/assets/00e350cf-8654-4638-8654-178accdf6a48" /> ## 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 |
||
|
|
11b2591fa6 |
Add Two Lakes (#2743)
## Description: This PR adds the Two Lakes map, based on the irl area around lake Ohrid and lake Prespa Describe the PR. ## 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 Nikola123 |
||
|
|
f6412a5979 |
Re-Enable HumansVsNations 🎉 (#2689)
## Description: **HumansVsNations is back!** The original PR had an issue: only the nations listed in the map’s `manifest.json` were being spawned, which resulted in completely unbalanced games. What did I change with this PR? - The number of humans and nations is now always the same. - If a map contains too many nations, we take a random subset. - If a map doesn’t contain enough nations, we dynamically add additional ones. These get random spawn locations, and their names are taken from the new name generator `NationNames.ts`. The name generator was taken from the closed PR #2245 (idea from @VariableVince). These changes apply to private lobbies and singleplayer as well. In singleplayer, you now simply play a 1-vs-1 against a nation. For public lobbies, we use 50% of the regular team-game player count. The remaining 50% are nations. We are also using the Hard difficulty for HumansVsNations. At the moment, it’s important that nations cheat a little because humans can donate troops, whereas nations cannot, at least not yet. In the future, we may make that work. We might need to adjust the difficulty or do fine-tuning depending on the humans’ win rate in production. Ideally, we want a ~50% win rate; otherwise, the mode may become boring. Over time, humans will likely develop strategies that nations can’t counter, in which case we’ll need to improve the nation AI. Here is a screenshot showing that the number of nations now matches the number of humans in the private lobby UI: <img width="806" height="304" alt="Screenshot 2025-12-25 004023" src="https://github.com/user-attachments/assets/cb4ac6f6-13cc-452c-8cc5-7a500670d7f2" /> The `PuplicLobby` display was a bit bugged for HumansVsNations: <img width="532" height="191" alt="Screenshot 2025-12-23 221832" src="https://github.com/user-attachments/assets/3950bcd9-0072-4c28-b1a0-83c0a24e9b8e" /> So I fixed it to look like this; <img width="532" height="195" alt="Screenshot 2025-12-23 224127" src="https://github.com/user-attachments/assets/690fc554-b607-4c8a-8b22-0c2912ee671a" /> ## 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 --------- Co-authored-by: iamlewis <lewismmmm@gmail.com> |
||
|
|
5d52f73278 |
The clown is gone! 🤡 Nations send much better emojis now (#2696)
## Description: Previously, nations just spammed these two rather toxic emojis: 🤡😡 They now send fewer emojis while attacking, and the clown emoji is reserved for special cases. They got the ability to send emojis in much more cases: - Human didn't donate enough for relation update - Human did donate an ok amount - Human did donate a lot - Responding to emojis that they get sent from a human - Nuke sent - MIRV sent - Retaliation warship sent - Traitor tries to ally - Threat asks for / accepts an alliance request - Disliked human tries to ally - Friendly human tries to ally - They are getting attacked by very much troops - They are getting attacked by very little troops - Congratulating the winner - Bragging with their crown - Charming their allies - Clown-Emoting traitors - Easteregg: Sending a rat emoji to very small humans ## 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 --------- Co-authored-by: iamlewis <lewismmmm@gmail.com> |
||
|
|
677a17d05a |
Feat: Lemnos Map (#2683)
## Description: Introduces the Greek island, Lemnos, as a map. The island is both fun and challenging to play (because of the terrain and elevation) and this addition was inspired by Altis from the game [Arma 3](https://armedassault.fandom.com/wiki/Altis). The nation names are set based on the real landmarks, towns, and regions. <img width="2190" height="1791" alt="image" src="https://github.com/user-attachments/assets/a7a6de54-f376-43ac-87da-f20aecfebbe0" /> <img width="1994" height="1608" alt="image" src="https://github.com/user-attachments/assets/bc280780-298f-4342-8313-db6cc27ac188" /> ## 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 |
||
|
|
1c52d20e83 |
Added pause functionality for private multiplayer games (#2657)
If this PR fixes an issue, link it below. If not, delete these two lines. Resolves #2491 ## Description: Adds pause/unpause functionality for private multiplayer games. Only the lobby creator can pause the game, and all players see a pause overlay when the game is paused. **Key features:** - Lobby creator sees pause/play button in control panel (alongside existing singleplayer/replay controls) - Server validates that only lobby creator can toggle pause - All players see "Game paused by Lobby Creator" overlay when paused - Game state freezes (no turn execution) while paused - Unpause resumes normal gameplay **Implementation details:** - Server-side pause state (`isPaused`) prevents turn execution during pause - Each client receives `isLobbyCreator` flag in `GameStartInfo` to show/hide pause button - Added `TogglePauseIntent` that broadcasts to all clients via `NoOpExecution` - New `PauseOverlay` component (shows in single player also) ## 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: furo18 <img width="1459" height="861" alt="Screenshot 2025-12-20 at 15 16 33" src="https://github.com/user-attachments/assets/f5a3222f-f54b-473c-b0f6-104ce4c1e7a8" /> |
||
|
|
6112547273 |
Improve random spawn (#2503)
## Description: This is a previously approved PR with an additional commit that fixes case when nations change spawn & jump around, their previous territory wasn't getting deleted. ## 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: nikolaj_mykola --------- Co-authored-by: Evan <evanpelle@gmail.com> |
||
|
|
e554ffb1b0 |
Cleanup nations (Part 3) 🧹 Remove nation strength (#2649)
## Description: This PR removes the nation strength. Reasoning: - It is currently unused. The backstory can be found in #2498 - It forces map-makers to do balancing work, which is probably not a good idea - It increases map-making work - It increases nation balancing complexity by a lot (we need to have all the json files in mind) - It makes humans avoid map areas completely because there is always that one, same, strong nation - The map lead Nikola123 wants to "not deal with the stupid nations and their balancing" If the goal of nation strength was to make them feel different I would suggest a nation personality system. Nations that love to boat, love to ally, love to nuke, love to fullsend, etc. Link to a discord discussion about nation strength: https://discord.com/channels/1359946986937258015/1360078040222142564/1450973197251117218 ## 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 |
||
|
|
4d5bb7a835 |
Cleanup nations (Part 1) 🧹 (#2637)
## Description: 1. Using the wording `"Nation"`, `"FakeHuman"` and `"NPC"` at the same time is confusing. So I renamed every mention of `"FakeHuman"` and `"NPC"` in the entire project to `"Nation"`. Just like they are called ingame. 2. `BotBehavior.ts` was originally intended for sharing the logic between nations and bots. But at the moment, the logic there isn't really shared and it's basically just about attacking. So I renamed `BotBehavior.ts` to `AiAttackBehavior.ts`. I use "Ai" to indicate that this file is used by bots AND nations. 3. Moved `execuction/utils/AllianceBehavior.ts` to `execuction/nation/NationAllianceBehavior.ts` to make sure everybody understands that this file is not about alliances in general. It's just about nations and how they handle alliances. 4. Removed `difficultyModifier` from `DefaultConfig`. It's unused and I think we usually want to finetune the difficulty instead of using that method. 5. Added `assertNever` in all `switch (difficulty)` default cases. ## 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 |
||
|
|
690b7e1155 |
Add Manicouagan Map and Credit OpenTopography (#2620)
## Description: Adds a map based on the Manicouagan Reservoir in Quebec and credits OpenTopography ## Checklist: - [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 <img width="1017" height="1017" alt="Screenshot 2025-12-14 214706" src="https://github.com/user-attachments/assets/030c4bbd-0325-4da4-bef5-71053dc8f183" /> ## Discord username: sehentsin |
||
|
|
71cf309252 |
increase mirv price with total number of merged launched (#2621)
## Description: To prevent MAD stalemates, have the price of MIRVs increase after each launch. This will encourage players to launch a MIRV once they have enough money for it. Also reduce the price of the first MIRV to 25 million to reduce snowballing, each subsequent MIRV cost an extra 15 million: 1. 25 million 2. 40 million 3. 60 million 4. etc ## 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 |
||
|
|
e290e587ea |
perf: Optimize cluster calculation with DFS and zero-allocation patterns (#2539)
## Description: Replace BFS with DFS and eliminate GC pressure in calculateClusters(): - Switch from O(N) queue.shift() to O(1) stack.pop() operations - Replace Set.has()/Set.add() with Uint8Array bitfield - Add reusable buffer management to avoid repeated allocations - Implement callback-based neighbor iteration to eliminate array allocations - Add forEachNeighborWithDiag() method to Game interface and GameImpl - Remove now unused GameImpl import from PlayerExecution Describe the PR. ## 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 |
||
|
|
1f8adb4849 |
Add Svalmel (#2600)
## Description: This PR adds the Christmas map Svalmel with 5 nations. Describe the PR. ## 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 Nikola123 |