mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-22 02:07:43 +00:00
fc45410ee5a14463218424fa54fda0ff434cc3cc
79 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
0801798fbd |
Feat: Alliance and betrayal hotkeys (#3110)
Original Feature request by @FloPinguin Resolves #3077 ## Description: Adds hotkeys for Requesting alliances and breaking alliances. This allows for players to send or break alliances whose tile is under the cursor, without opening the radial menu. Keybinds: New "Ally Keybinds" section in Settings -> Keybinds Request alliance: Default: K - sends an alliance request to the player/bot/nation under the cursor Break alliance: Default: L - breaks the alliance with the player at the cursor Behavior: - Cursor must be over a tile owned by the target player. The action runs only when the game allows it, following the same logic as the radial menu. (canSendAllianceRequest and canBreakAlliance) - When an alliance request is sent, the events log shows: "Alliance request sent to [target]" for confirmation. No extra message for breaking an alliance (betrayal/debuff message already exists and is sent upon breaking an alliance) ## Screenshots: Keybind menu: <img width="739" height="595" alt="image" src="https://github.com/user-attachments/assets/ee958eab-fd50-4971-85c5-dfd49c6f0bdc" /> In game logs: <img width="373" height="232" alt="image" src="https://github.com/user-attachments/assets/2cf6bb07-5f0d-425a-82d3-65a44fef99c5" /> ## 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 Discord username: _Dave9595_ |
||
|
|
29a1e8dfda |
feat: multi-warship selection with Shift+drag box (#3677)
Resolves #3666 ## Description: Adds RTS-style box selection for warships. Hold Shift and drag (desktop) or long-press and drag (touch/mobile) to draw a selection rectangle — all player-owned warships inside get selected at once. A subsequent click/tap on water sends them all to that location. - `SelectionBoxLayer` — pixel-dashed rectangle in world-space, player territory color; shared between desktop and touch - `UILayer` — same pulsing selection outline on each box-selected warship; clears correctly when switching between single/multi selection - `UnitLayer` — finds warships in screen rect, filters inactive ships before sending; touch support included - `InputHandler` — Shift+drag and touch long-press+drag both emit selection box events; cursor becomes crosshair on Shift; discards active ghost structure on Shift press; configurable via `shiftKey` keybind - `Transport` — single atomic `move_multiple_warships` intent (no split on socket drop) - `Schemas` + `ExecutionManager` + `MoveMultipleWarshipsExecution` — server fans out atomic intent into individual `MoveWarshipExecution` per ship - `DynamicUILayer` — `MoveIndicatorUI` chevron animation on target tile for both single and multi move - `UnitDisplay` — warship tooltip Shift hint via `translateText` - `HelpModal` — new hotkey row: Shift + drag → select multiple warships ## 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 ## UI update ### Mouse + Keyboard https://github.com/user-attachments/assets/3f35ab5e-1f3c-4c5d-bc4f-aabccf64dc60 ### Touch https://github.com/user-attachments/assets/0d6aec3f-44fa-4fee-b5c6-b267b9b14d79 ## ## Please put your Discord username so you can be contacted if a bug or regression is found: fghjk_60845 |
||
|
|
e5e1211480 |
feat: add Shift+ modifier support for keybinds (#3679)
## Description: This PR adds support for `Shift+<key>` keybind combinations across the entire keybind system. Previously, keybinds only supported a single key (e.g. `KeyB` for boat attack). Now any keybind can be configured as `Shift+KeyB`, which will only trigger when Shift is held down simultaneously. Enables to use Shift + A for "select all" feature from #3677 **Changes:** - `InputHandler.ts`: Added `parseKeybind()` helper that parses `"Shift+KeyB"` → `{ shift: true, code: "KeyB" }`. Added `keybindMatchesEvent()` for consistent matching across all keyup/keydown handlers. Updated `resolveBuildKeybind()` and all keybind comparisons to respect the shift modifier. - `SettingKeybind.ts`: When recording a keybind, lone modifier keys (Shift, Ctrl, etc.) are skipped — the component waits for the actual key. If Shift is held when the key is pressed, the value is stored as `"Shift+<code>"`. - `Utils.ts`: `formatKeyForDisplay()` now handles the `Shift+` prefix, displaying e.g. `"Shift+B"`. - `tests/InputHandler.test.ts`: Added 6 tests covering Shift+ keybind matching, negative cases (plain key not triggering Shift-bound action), coexistence of `Digit1` and `Shift+Digit1` on different actions, and Numpad alias support with Shift. ## 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 ## UI changes: <img width="2255" height="2070" alt="CleanShot 2026-04-15 at 20 23 25@2x" src="https://github.com/user-attachments/assets/96c19fc3-6294-40b7-82eb-3fde52b71618" /> ## Please put your Discord username so you can be contacted if a bug or regression is found: fghjk_60845 |
||
|
|
318d1e2c44 |
Refactor/Fix(UserSettings): last localstorage calls now use UserSettings, and Keybinds fixes (#3619)
## Description: 1) Have last localstorage calls for keybinds and attack ratio also use UserSettings cache instead, after #3481. Remaining calls to localstorage are for different things than user settings, so they are left as is. 2) Consolidate and centralize keybinds logic. And three fixes for it. - **UnitDisplay** and **UserSettingsModal**: _parsedUserKeybinds_ is introduced in **UserSettings** to centralize their logic. It is also used by _normalizedUserKeybinds_, see point below. - **UserSettingsModal** -- replaced unwanted cast `as SettingKeybind` by a typed QuerySelector. -- renamed this.keybinds to this.userKeybinds for more clarity, and distinction from defaultKeybinds. -- state private _userKeybinds_: remove type string[] since loadKeybindsFromStorage replaces a value array by its first string element, so it can not contain string[] anymore. -- _handleKeybindChange_ and _getKeyValue_: no need to check for Array.isArray anymore, see above reason. -- **Fix**: checks after calling _parsedUserKeybinds_ are improved a bit: don't delete all keybinds and print a console warning when finding just one invalid keybind and (i think i have seen people complaining about things being removed). Instead it now migrates or throws out the invalid ones but keeps the valid ones. Also works with the "Null" value expected and removed within **UserSettingsModal**._handleyKeybindChange_() and in **HelpModal**. When legacy value is an array and key is empty, don't put value as key but get first array element or empty string as key name. So that check on line 68 is true. - **HelpModal** and **InputHandler**: Also centralize/consolidate their logic more, by having __keybinds()_ from **UserSettings** perform fetching _getDefaultKeybinds_ and _normalizedUserKeybinds_. -- Functionality in _normalizedUserKeybinds_ is the same: Where HelpModal did return [k, v.value] if typeof (v as any).value === "string", this is now handled by lines 309-310 of normalizedKeybinds still the same but with less lines. Same for old HelplModal if (typeof v === "string") return [k, v], this is stil returned by line 112 of normalizedKeybinds. And return [k, undefined] when (typeof val !== "string") as was done in InputHandler, isn't needed as values that weren't strings were already filtered out right after which we still do on line 314 of normalizedKeybinds. -- **Fix** in _normalizedUserKeybinds_: added one extra thing that was a discrepancy between **HelpModal**/**InputHandler** and **UserSettingsModal** before: **UserSettingsModal** would handle array values, and normalize them by picking only the first value if it is a string. Now have _normalizedKeybinds_ do the same. Otherwise it would have thrown those values out while **UserSettingsModal** would have kept the first value. This may still help a returning player who hasn't played in the last version (i think i have seen people complaining about things being removed, but that may not have been about this). And makes the logic more consistent between **UserSettingsModal** and **HelpModal**/**InputHandler**. - **UserSettings**: -- _getDefaultKeybinds_: centralized/consolidated logic, accepts Platform.isMac parameter. In **HelpModal**, **InputHandler** and **UserSettingsModal** the same list with default keybinds was hardcoded. Now they all read from _getDefaultKeybinds_. The list of default keybinds in **HelpModal** was a little shorter, but that doesn't matter since its _render_() function has hardcoded which of the hotkeys **HelpModal** shows. Have thought about putting default keybinds in **DefaultConfig** but with all the logic handled through **UserSettings**, this seemed the better place in the current refactor. -- _removeCached_: make public, now that **InputHandler.test.ts** needs to be able to call it. We could instead make a public function like removeKeybinds() and keep removeCached() private, but went with this for now. -- _parsedUserKeybinds_: centralized/consolidated logic for **UserSettingsModal**/**UserDisplay**. Always returns an object, even an empty one if the JSON wasn't parsable. -- _normalizedKeybinds_: centralized/consolidated logic. Used by _keybinds_() which is now called by **HelpModal**/**InputHandler**. -- _keybinds_: now uses getDefaultKeybinds() and normalizedKeybinds() to get the default and user changed keybinds. -- **Fix** in _keybinds_: it now removes a key if it is Unbound by the user in **UserSettingsModal**. Instead of first loading the parsedUserKeybinds, removing "Null" keys from it, and then merging that with defaultKeybinds (so default key would overwrite an unbound key), we now merge parsedUserKeybinds with defaultKeybinds and after that remove "Null" keys from it (so that unbound key stays removed). For example if Boat Attack Up is set to "None" ("Null") by clicking Unbind, there is now no hotkey working for it anymore. Even when the default is "B". Why? This prevents the user from being confused, they have deliberately Unbound it, they don't understand why it still works (have seen bug reports and game feedback about this)? Also more importantly: they used to now be able to bind "B" to another action. Effectively making key "B" bound to two actions: the user choosen one and Boat Attack. This also makes the logic more consistent. Because building hotkeys in **UnitDisplay** already didn't work when unbound, eg. when Build Missile Silo was Unbound, the "5" key did not do anything anymore (there is a fallback in **UnitDisplay** in case the key is actually null, but it does respect "Null" as it should). -- _setKeybinds_: have it accept an object, it stringifies it itself. Callers UserSettingsModal and InputHandler.test.ts now just send either a string or an object. - **InputHandler.test.ts**: -- use **UserSettings** functions instead of localStorage for more real-world testing. -- change test "ignores non-string values and preserves defaults, removes 'Null' for unbound keys". As explained above, as a fix we no longer preserve unbound ("Null") keys within InputHandler. UserSettings.keybinds() now removes "Null" keys as explained above. - ControlPanel: use UserSettings to fetch initial attack ratio. ## 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 |
||
|
|
646d7ecaf6 |
Disable Radial Menu during spawn phase, just left click or tap to pick spawn point (#3611)
## Description: During spawn phase, disable Radial Menu further. Its options where already greyed out or non-responding on purpose, except for the attack button (middle button) which could only be used to select a spawn point but two clicks for that is convoluted. It was mostly a nuisance, especially on mobile where you where forced to go through the Radial Menu, so tap and then tap again to pick a spawn point. - Now, left click directly places a spawn point. Even if "Left click opens menu" is enabled. - And right click does not open Radial menu anymore. Which had no use anyway. And also makes touch screen and mouse players more alike in that they now both have no access to the Radial Menu (which didn't have a purpose anyway except picking spawn point in a convoluted way with two clicks). - On touch screen during spawn phase, the Radial Menu also doesn't open anymore. Instead of two taps (open Radial Menu > tap attack button), now one tap suffices to pick a spawn point just like one left mouse click now does. Fixes https://github.com/openfrontio/OpenFrontIO/issues/3609 Also from UnitLayer > onTouch: - remove redundant isValidRef check. Since isValidCoord check was added in PR 3226 above it, we know it is a correct coord and with that correct ref, already. - remove redundant comment about isValidCoord/Ref not being checked there yet intentionally, because it is actually being checked there since PR 3226. ## 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 --------- Co-authored-by: iamlewis <lewismmmm@gmail.com> |
||
|
|
e4cd753ce2 |
fix: prevent game zoom runaway after browser zoom shortcut (#3532)
## Description: When the user changes browser zoom using keyboard shortcuts (cmd+Plus / cmd+Minus on Mac, ctrl+Plus / ctrl+Minus on Windows), the game would start zooming in uncontrollably afterwards. The zoom could not be stopped — only temporarily countered by zooming out, but the game would continue zooming in on its own. **Root cause:** Two issues combined: 1. When cmd+Plus/Minus is pressed, the browser intercepts the event and handles its own zoom. The `keydown` fires and adds `Equal`/`Minus` to `activeKeys`, but the `keyup` is swallowed by the browser and never fires — leaving the key stuck. The 1ms `moveInterval` then continuously emits `ZoomEvent` forever. 2. The `onScroll` handler was passing browser-generated synthetic wheel events (fired with `ctrlKey: true` and large `deltaY`) directly to the game zoom logic, amplified by 10x. **Fix:** - Skip adding `Minus`/`Equal` to `activeKeys` when a meta/ctrl modifier is held (browser zoom combo) - On `MetaLeft`/`MetaRight` keyup, explicitly clear any stuck zoom keys - Clear all `activeKeys` on `window blur` as a general safety net - In `onScroll`, ignore synthetic wheel events with `ctrlKey: true` and `|deltaY| > 10` (browser zoom events vs real pinch-to-zoom which has small deltas) - Add a minimum delta threshold of 2 for regular scroll to cut off macOS momentum tail events ## 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: fghjk_60845 Co-authored-by: Ivan <batsulin.i@mail.ru> |
||
|
|
f356f09f81 |
Feat: Game Speed + Pause keybinds (#3397)
## Description: Can't tell you how many times I've been playing solo, I try to go change the speed from `Max` to `x1` and before I've opened the speed controls and clicked on one the AI completely wipes me. But not to worry, we now have a pause and speed toggle up/down keybinds! https://github.com/user-attachments/assets/48692c27-888f-40fb-837a-45e26f262441 Keybinds were added to "Menu Shortcuts" submenu: <img width="1750" height="1099" alt="image" src="https://github.com/user-attachments/assets/8c4500d5-f43e-4a1c-9940-04db75bf18cf" /> Tested on Solo, custom match, and public lobbies. Pause intent works correctly on solo and private match (only if you are host), and neither feature works in public matches, as expected. ## 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 |
||
|
|
aa24438edf | Fix slider focus stealing keyboard shortcuts after interaction | ||
|
|
936928fed9 |
Enhance InputHandler to allow using NumPad (#3317)
## Description: Adds **Enter** and **Numpad Enter** as confirmation for placing a ghost structure after selecting a building with hotkeys (1–0 or numpad). Players can cancel with Esc but previously had to click to confirm; they can now confirm with Enter or Numpad Enter at the current cursor position. This supports keyboard-only or mouse + numpad workflows (e.g. one hand on numpad for select + confirm, one on mouse for aiming). ## 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: .wozniakpl |
||
|
|
e137fcaa6c |
Fix/Perf/Refactor: playerActions and buildableUnits, their callers and related types (#3220)
## Description: TL;DR: it's faster. buildableUnits is called via PlayerView.actions from UnitDisplay (each tick without TileRef), BuildMenu (each tick when open), MainRadialMenu (each tick when open), PlayerPanel (each tick when open), StructureIconsLayer (when placing a building from build bar), NukeTrajectoryPreviewLayer (when placing nuke, on tick when tile changes), ClientGameRunner (on click to attack/auto-boat or hotkey B or G). After https://github.com/openfrontio/OpenFrontIO/pull/3213 got merged, the change with largest impact in https://github.com/openfrontio/OpenFrontIO/pull/3193 was done in such a different way that a new PR was needed The idea in 3193 was to not always ask for Transport Ship from buildableUnits. In such a way that very little extra data was send to the worker. This had the biggest impact on performance (the idea was months older btw, see https://github.com/openfrontio/OpenFrontIO/pull/2295). Now, we do it the other way around, by telling buildableUnits all unit types we want. Or we want them all (undefined). The downside is more data is send in the worker message. The upside is we have more options and can add more in this PR. This PR implements some of the leftovers in 3193 on top of 3213 and adds further improvements. (Some unrelated refactor/perf changes where moved out of this PR and into already merged https://github.com/openfrontio/OpenFrontIO/pull/3233, https://github.com/openfrontio/OpenFrontIO/pull/3234, https://github.com/openfrontio/OpenFrontIO/pull/3235, https://github.com/openfrontio/OpenFrontIO/pull/3236, https://github.com/openfrontio/OpenFrontIO/pull/3237, https://github.com/openfrontio/OpenFrontIO/pull/3238, https://github.com/openfrontio/OpenFrontIO/pull/3239) - **GameRunner**, **WorkerMessages**: _playerActions_ and _PlayerActionsMessage ._ Option to ask for no buildable units (null). It now has 3 modes: get all actions and all buildings (units undefined), get all actions and no buildings (units null), or get all actions and specific building (units contains Unit Types). - **GameRunner**: _playerActions_. fixes wrong assumption in PR 3213: that only if units was undefined, we have to know canAttack. ClientGameRunner wants to know both, in case of a click on non-bordering land, to decide if it should auto-boat using a Transport Ship. So units is not undefined (we only ask for Transport Ship now which has a positive effect on performance for each click/tap) but we need canAttack still. Solved by removing the unit === undefined check before _canAttack_ in _playerActions_. - **GameRunner**, **GameView**, **WorkerClient**, **WorkerMessages**, **Worker.worker**: added _playerBuildables_ / _buildables_ next to existing _playerActions_ / _actions_. With above solved, there was still no option to only get buildable units when the actions are not needed. While **StructureIconsLayer**, **NukeTrajectoryPreviewLayer**, **BuildMenu** and **UnitDisplay** need only that. To not make playerActions more convoluted with more params or so, i've added a new function _playerBuildables_ in **GameView** to only get buildable units (**GameRunner** _playerBuildables_). _playerBuildables_ has 2 modes: get all buildings (units undefined) or get specific buildings (units contains Unit Types). Also update some comments that mentioned .actions in **NukeTrajectoryPreviewLayer**. - **ClientGameRunner**, **PlayerPanel**, **BuildMenu**, **UnitDisplay**, **StructureIconsLayer** and **NukeTrajectoryPreviewLayer**: Since PR 3213, **StructureIconsLayer** and **NukeTrajectoryPreviewLayer** ask for specific types of units from **GameView** _actions_ (**GameRunner** playerActions). Now have the other files do the same. For example **BuildMenu** asks for the new _BuildMenuTypes_ when it calls ._buildables_ and **ClientGameRunner** asks for UnitType.TransportShip when sending a boat - **ClientGameRunner**: canBoatAttack now accepts BuildableUnit[] instead of PlayerActions so we can send it either actions.buildableUnits or just buildables. Have functions call myPlayer.buildables(tileRef, [UnitType.TransportShip]) when we only need a buildable unit and no actions. Or myPlayer.actions(tileRef, null) when we need actions but no buildable units. Or myPlayer.actions(tileRef, [UnitType.TransportShip]) when we need both actions, like canAttack, and a buildable unit. Then if needed send either actions.buildableUnits or buildables to to _canAutoBoat_ / _canBoatAttack_. - **MainRadialMenu**: needs all player buildable unit types including Transport Ship, so the _actions_ call argument for unit types can stay undefined (unchanged) there. - **MainRadialMenu**: now that **BuildMenu** uses _playerBuildables_ instead of _playerActions_, we must put data in _this.buildMenu.playerBuildables_. And since we're not putting the (unneeded) full _actions_ in there anymore, we can now put only the needed and expected _actions._buildableUnits_ in it. - **Game**, **PlayerImpl**, **StructureIconsLayer**: Typesafety and some added perf: new type _PlayerBuildableUnitType_ (see also the below point for how it is formed). So callers of _buildableUnits_ can never ask for the wrong type like e.g. UnitType.Train because it doesn't return data for that type. This type is now used in **PlayerImpl**, **BuildMenu**, **RadialMenuElements**, **StructureDrawingUtils** and **UnitDisplay** for that reason. And **InputHandler**, **StructureIconsLayer** and **UIState** (little more on that in point below). - **InputHandler**, **StructureIconsLayer**, **UIState**: In order to make type safety work for GhostUnit.buildableUnit.type too (line ~217 of StructureIconsLayer), changed type of interface _BuildableUnit_ to _PlayerBuildableType_. Which is only more accurate. Same for and this.structures and uiState.ghostStructure and with the latter, _renderUnitItem_ in **UnitDisplay** and _setGhostStructure_ in **InputHandler**. All Structures are of PlayerBuildableType (there are even some in PlayerBuildables that aren't Structures, but it is much more confined than UnitType). - **Game**: Typesafety and some added perf: added _BuildMenus_ and _BuildableAttacks_ in the same fashion that the existing StructureTypes was already used (simplified it a bit too, with it renamed _StructureTypes_ to _Structures_ and removed _isStructureType_). They can be used with .types or .has(). _BuildableAttacks_.has() is used in **RadialMenuElements**. _BuildableAttacks_ and existing _Structures_ now make up _BuildMenus_. Which is used in **BuildMenu**, **StructureIconsLayer** and **UnitDisplay**. Then _BuildMenus_ together with UnitType.TransportShip make up the _PlayerBuildables_. Which is used in **PlayerImpl** _buildableUnits_ (see point below). And with _PlayerBuildableUnits_ we get the new _PlayerBuildableUnitType_ (see above point on Game / PlayerImpl). - **RadialMenuElements**: replace non-central ATTACK_UNIT_TYPES in **RadialMenuElements** with centralized _BuildableAttackTypes_ too. Use _PlayerBuildableUnitType_ for more type safety (can't by mistake add UnitType.Train to its build menu). Make use of _BuildableAttackTypes_ instead of adding items hardcoded line by line in _getAllEnabledUnits_, just like we already did since PR 3239 with _StructureTypes_. And use _BuildableAttacks.types_ in the same fashion that existing _isStructureTypes_ (now Structures.types) was already used elsewhere. - **PlayerImpl**: _buildableUnits_ -- would do Object.values(UnitTypes) on every call. Now for better perf directly loop over player buildable units by using _PlayerBuildables_ (see above point). In this way we also exclude MIRVWarhead, TradeShip, Train, SamMissile and Shell so there are less unit types to loop through by default. Since a player doesn't build those by themselves, they are only build by Executions which use _canBuild_ directly and not _buildableUnits_. -- for more performance, do for loop instead of using .map and .filter, no intermediate array needed nor callback overhead. We just loop over the given units (which if undefined will contain _PlayerBuildables_). Also pre-allocate the results array to get the most out of it, even if V8 might already be very good at this. -- cache config, railNetwork and inSpawnPhase so they can be re-used inside the for loop. -- cache cost inside the loop -- it would check twice for tile!==null to decide to call findUnitToUpgrade and canBuild. Now once. -- eliminated double/triple checks for the same thing. It called _findUnitToUpgrade_ (and with that _canUpgradeUnit_) and then _canBuild_ which both check if player has enough gold for the cost of the unit type. And they both check if the unit type is disabled. Now we call private functions _canBuildUnitType_, _canUpgradeUnitType_ to first do checks on unit type level for early returns, and _findExistingUnitToUpgrade_ to find existing unit without doing anything extra. in a specific order to check everything only once. The public functions _findUnitToUpgrade_ and _canBuild_ have an unchanged functionality and we don't call them from _buildableUnits_ anymore. -- would get _overlappingRailRoads_ and _computeGhostRailPaths_ when canBuild was true. But this data is only meant for **StructureIconsLayer** and it logically only uses it when placing a new unit, not when upgrading one. Which is also commented on line 351 of **StructureIconsLayer**. So, we now only get overlapping railroads and ghost rails if we're not hovering to upgrade an existing unit. - **PlayerImpl**: _findUnitToUpgrade_: unchanged functionality, but have it call new private function _findExistingUnitToUpgrade_ to find existing unit. - **PlayerImpl**: _canBuild_: unchanged functionality, but have it call new private function _canBuildUnitType_ to do the checks it first did itself. And then new private function _canSpawnUnitType_ for the rest of the checks. This way we can call _canBuildUnitType_ and _canSpawnUnitType_ from _buildableUnits_ in a specific order to prevent double/triple checks. - **PlayerImpl**: _canBuildUnitType_: new private function to be shared by _buildableUnits_, _canBuild_ and _canUpgradeUnit_ to be able do unit type level checks in a specific order to prevent double/triple checks. Via parameter knownCost, _buildableUnits_ can send it the cost it already fetched so that it doesn't have to be fetched again. For caller _canUpgradeUnit_, the isAlive() check (which was previously only done in canBuild) is new but harmless, maybe even better to have also check isAlive() on upgrade now that Nations are also upgrading which might prevent some edge case bugs. - **PlayerImpl**: _canUpgradeUnitType_: new private function to be shared by _buildableUnits_ and _canUpgradeUnit_ to be able do unit type level checks in a specific order to prevent double/triple checks. - **PlayerImpl**: _canSpawnUnitType_: new private function to be shared by _buildableUnits_ and _canBuildUnit_ to be able do unit type level checks in a specific order to prevent double/triple checks. - **PlayerImpl**: _findExistingUnitToUpgrade_: new private function to be shared by _buildableUnits_ and _findUnitToUpgrade_ to be able do unit level checks in a specific order to prevent double/triple checks. - **PlayerImpl**: _isUnitValidToUpgrade_: new private function to be shared by _buildableUnits_ and _canUpgradeUnit_ to be able do unit level checks in a specific order to prevent double/triple checks. - **PlayerImpl.test.ts**: because of the isAlive() check in which is new for _canUpgradeUnit_ (see above at _canBuildUnitType_), the tests needed to have the players be alive at the start, in order to pass. - **BuildMenu**: use .find instead of .filter in canBuildOrUpgrade, a function we already needed to change. This is faster and prevents an allocation. **PERFORMANCE** As for calling ._buildables_ instead of unnecessarily getting ._actions_, there is an obvious win because there's less to send calculate and recieve. Also asking for only the needed buildings helps a lot (especially if TradeShip isn't needed, see the difference in benchmark in original #3193). But the real-world impact is hard to measure. gave it a try in #3193 and those results should be even better now. Now testing only _buildableUnits_ performance in a synthetic benchmark, we get these results. This is after other performance improvments so the base is already better than it was in original #3193: **BEFORE** (only buildableUnits itself) <img width="602" height="96" alt="image" src="https://github.com/user-attachments/assets/7770c0fa-a35e-42fc-90de-1de83242ec23" /> **AFTER** (only buildableUnits itself) <img width="603" height="91" alt="image" src="https://github.com/user-attachments/assets/a1578382-7010-4160-937c-7117bad18beb" /> ## 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 --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> |
||
|
|
f7598369ed |
refactor: consolidate platform detection across client components (#3325)
## Description: This PR consolidates ad hoc platform/environment/viewport detection into a single shared utility. It is scoped to this refactor only, and serves as groundwork for the mobile-focused feature work planned for the v31 milestone. ### What changed - Introduced a shared `Platform` utility centralising: - OS detection (with `userAgentData` + UA fallback) - Electron environment detection - Viewport breakpoint helpers (`isMobileWidth`, `isTabletWidth`, `isDesktopWidth`) - Replaced duplicated inline checks across client files with the shared API. - Normalised Mac detection to derive from the consolidated OS logic rather than a separate regex. ### Why - Multiple client files each independently ran `navigator.userAgent` regexes or copy-pasted `isElectron` logic — this unifies all of that. - Puts a stable, tested abstraction in place before v31 mobile work lands, so mobile feature branches have a consistent surface to build against. ## Please complete the following: - [x] I have added screenshots for all UI updates (N/A: refactor only, no visible UI changes) - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file (N/A: no new user-facing strings) - [x] I have added relevant tests to the test directory (N/A: refactor only) - [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: skigim |
||
|
|
8754f5291f |
Feat: Alphanumeric Coordinate Grid on Alternate View (#2938)
## Description: Adds a coordinate grid to the Alternate View (holding spacebar) using numbers on the X-axis, and letters on the Y-axis. No more "he's attacking you in that—well, the little peninsula thing... next to the island! which island? uhh..." moments when playing with friends. Optimally maps have letters A-J (just like in the Battleships board game) but special maps like Amazon River dynamically resize to only have 2 letters so as to not have too many number columns. This feature overall can be toggled via the settings menu. Also saw it requested on the [official discord](https://discord.com/channels/1359946986937258015/1457037351422263480) a couple times, thought it was a neat idea. ### World Map <img width="3809" height="1824" alt="image" src="https://github.com/user-attachments/assets/dab56879-a34e-48ea-a588-2907d26feb45" /> ### Scales correctly when zoomed in <img width="3798" height="1874" alt="image" src="https://github.com/user-attachments/assets/7e06a47f-d3d9-4f92-8e89-3eaf866e9b25" /> ### Amazon River <img width="3803" height="1595" alt="image" src="https://github.com/user-attachments/assets/4797c576-20b2-4aa8-8b7a-107078ab6308" /> ### Enable/Disable via settings https://github.com/user-attachments/assets/ec9f4e07-70a1-4f9d-b137-c3c3d2a2540c ## 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> |
||
|
|
bd3db55a22 |
Add configurable attack ratio keybind increment setting (#2835)
If this PR fixes an issue, link it below. If not, delete these two lines. Resolves #2822 ## Description: Adds an attack ratio keybind increment setting with a new dropdown UI, wires keybinds to use the configured step, updates the attack ratio adjustment logic, and makes the select reflect stored settings. <img width="806" height="165" alt="スクリーンショット 2026-01-12 9 11 12" src="https://github.com/user-attachments/assets/c6eaa96d-e147-4927-b3ed-964e832ecc36" /> ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: aotumuri --------- Co-authored-by: Ryan <7389646+ryanbarlow97@users.noreply.github.com> Co-authored-by: iamlewis <lewismmmm@gmail.com> |
||
|
|
ed3c7b1a22 |
make existing keybinds configurable (#2881)
## Description: This PR makes several existing keybinds configurable that were previously fixed and could not be changed in the keybind settings. This is one of the required PRs to fully remove all keybind explanations from the HelpModal. This work is based on the following feedback by @ryanbarlow97: > "This probably needs to be redone / removed from help, and just have a section saying how to get to the keybinds modal inside settings" > https://github.com/openfrontio/OpenFrontIO/pull/2872#issuecomment-3740006017 Some keybinds described in the HelpModal already existed internally, but users had no way to change them. By making these keybinds configurable, we can now safely replace those explanations with a simple reference to the keybind settings instead. This helps: - Remove keybind explanations from the HelpModal ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: aotumuri Co-authored-by: Ryan <7389646+ryanbarlow97@users.noreply.github.com> |
||
|
|
97fffaf49e |
fix: Correctly handles unbound keybinds (#2854)
Resolves #2652 #2291 ## Description: Resolves a regression after a new design changes where keybinds explicitly set to "Null" were incorrectly reverted to default values instead of remaining unbound. Updates the input handler to preserve "Null" as the designated value for an unbound key. The UI now reflects this by displaying "None" for keybinds that are set to "Null", providing clear user feedback. Before/After: <img width="378" height="371" alt="image" src="https://github.com/user-attachments/assets/d1d640f2-93aa-47f1-be8e-7d8c68183aa1" /> <img width="379" height="370" alt="image" src="https://github.com/user-attachments/assets/f0512cce-c6e9-4180-9517-7669aed76f6f" /> ## 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: webdev.js Co-authored-by: antigrid <Stepan.Hembarovskyi@Inu.edu.ua> |
||
|
|
5e6c90d9bb |
Main Menu UI Overhaul (#2829)
## Description: Overhauls the Main Menu UI, visit https://menu.openfront.dev to see everything. ## 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: w.o.n |
||
|
|
72f8924a7f |
add mobile bomb flip support (#2737)
closes #2678 ## Description: Update to enable bomb flip support by mobile users too <img width="420" height="666" alt="image" src="https://github.com/user-attachments/assets/eb2155a4-2012-4f40-8caa-bd23ebd28521" /> ---------------------------------------------------------------------------------------------------------------------------------------------------- Also, I slightly updated the player panel to make it more even and take up less space; - removed the huge header bar which took up too much space - fixed ui divider spacing Before: <img width="372" height="179" alt="image" src="https://github.com/user-attachments/assets/2cf82cda-d466-4911-be4f-36eb6e788d5b" /> After: <img width="383" height="134" alt="image" src="https://github.com/user-attachments/assets/4d827221-f456-48fe-940b-a9ba84d1f4a5" /> ## 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: w.o.n |
||
|
|
b5a0541202 |
Revert "Fix Ctrl+Click for Macs, and alphabetize gitignore (#2720)"
This reverts commit
|
||
|
|
40eea22007 |
Fix Ctrl+Click for Macs, and alphabetize gitignore (#2720)
Resolves #2719 - [X] Ran `npm run format` - [X] Ran `npm run lint:fix` - [X] Ran `npm test` - [X] Manually tested fixes ## Description: ### What problem(s) was I solving? On Mac, `Ctrl+Click` is commonly used as a substitute for right-click to open context menus. However, in OpenFront, `Ctrl+Click` was triggering both the context menu, AND causing an attack. This effectively prevented Mac users from being able to ally with bots/nations, as trying to ally would cause you to attack them. ### What changes did I make? - `Ctrl+Click` on Mac no longer triggers an attack, allowing players to properly interact with the alliance system ### How I implemented it 1. Added an `isMac()` method to `InputHandler` which encapsulates the "is mac" logic, and lets it be mocked during tests 2. In the `onPointerUp` handler, added a check: if on Mac and `ControlLeft` is held, emit a `ContextMenuEvent`, and then return (instead of continuing to also create a `MouseUpEvent`) 3. Extracted magic numbers for mouse button checks into descriptive helper methods (`isMiddleMouseButton`, `isNonLeftMouseButton`) for improved code clarity 4. Added clarifying comments throughout the pointer event handlers Last, alphabetized the `.gitignore` file and organized it into "Folders" and "Files" sections to make it easier to read. ### How to verify it #### Manual Testing - [X] On a Mac, hold `Ctrl` and left-click on another nation - verify the context menu opens (not an attack) - [X] On a Mac, right-click should still open the context menu as expected - [X] On Windows/Linux, `Ctrl+Click` continue to work as before (modifier key for build menu if configured) - [X] Regular left-click still triggers attacks/interactions as expected #### Automated Testing - [x] New unit test added: `Mac Ctrl+Click Context Menu` - verifies that `Ctrl+Click` on Mac emits `ContextMenuEvent` instead of `MouseUpEvent` ### Description for the changelog Fixed `Ctrl+Click` on Mac to properly open the context menu instead of triggering an attack, restoring the ability for Mac users to form alliances with other nations. ## 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: Terekhov |
||
|
|
f1561df470 |
Bomb Direction (#2435)
Resolves #2434 ## Description: Allows bomb direction to be inverted by pressing a hotkey - currently "U". **Check the issue for screenshots / videos.** ## 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: w.o.n --------- Co-authored-by: Evan <evanpelle@gmail.com> Co-authored-by: iamlewis <lewismmmm@gmail.com> |
||
|
|
581fec5341 |
Fix shortcut keys being blocked by quick chat guard on attack rate bar (#2723)
Resolves #2702 ## Description: This fixes the issue reported in #2702 where certain shortcut keys stopped working. The root cause was the shortcut-guard logic introduced in #2528 to prevent accidental shortcut activation while the quick chat is open. That logic was also being applied to the attack rate bar unintentionally, causing shortcuts to be blocked there as well. This PR excludes the attack rate bar from the quick chat guard so shortcuts behave correctly again. ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: aotumuri |
||
|
|
5392e0b9e3 |
Prevent keyboard shortcuts from firing while typing in quick chat search (#2528)
## Description: Guard global keydown/keyup handlers to ignore events from text/textarea/contenteditable targets (except Escape/active keys) so gameplay shortcuts don’t trigger while typing in the quick chat player search. ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: aotumuri |
||
|
|
d07f84f801 |
Move warship by a touch (of magic) (#2408)
## Description: This adds moving warships by tapping them on a touchscreen. Now you can steer them just like you already could with a mouse. Also has some earlier returns, doing checks only when needed, prevent as much duplicate checks and a bugfix. In onMouseUp: - early return if no OceanTile. Before, function findWarshipsNearCell would still go look for warships even if ocean wasn't clicked. - Move const nearbyWarShips down. It isn't needed when this.selectedUnit is true. - Remove unnecessary const clickedWarship. - Move getting clickRef from function findWarshipsNearCell into onMouseUp. Because it is needed in case of this.selectedUnit too, within onMouseUp. Getting a valid clickRef for this.selectedUnit fixes: Runtime error when clicking outside the map after selecting a warship. The isValidCoord/Ref check was missing for this.selectedUnit. For findWarshipsNearCell: - moved the cell/tile checks out to onMouseUp, the only caller of the function. - did NOT rename findWarshipsNearCell. Although it now uses tileRef as input. Renaming can cause merge issues so i only do this when needed. Added onTouch: - Tests if we need to look for warships to select/move or if we can open Radial Menu. - Prevent as much duplicated checks as possible. So if no there's no Ocean Tile found, just send the radial menu event, which checks isValidCoord anyway. isOceanTile itself works fine even if it's no valid cell (proven by this.selectedUnit working all this time in onMouseUp without an isValidCoord test). Screencap on mobile, shows selecting and moving warships, no runtime error when clicking outside the map after selecting a warship, while radial menu still opens as normal: https://github.com/user-attachments/assets/1300d557-ae2f-46e3-92bd-d434c523aae7 ## 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 |
||
|
|
7b85114194 |
Add nuke trail preview (#2350)
## Description: Implements trajectory preview for nuke selection as requested in #2346. When selecting an AtomBomb or HydrogenBomb, a dashed line preview now shows the trajectory path from the launch silo to the target location before launching. Line uses player's territory color with 70% opacity and dashed pattern for clear visibility ## Please complete the following: - [x] I have added screenshots for all UI updates <img width="716" height="483" alt="image" src="https://github.com/user-attachments/assets/4c263230-34ba-4e56-9502-4a59c84b5943" /> <img width="1199" height="965" alt="image" src="https://github.com/user-attachments/assets/72eda758-e192-45a0-b01d-5a8f413a07d5" /> - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file (No new text strings added) - [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: kerverse --------- Co-authored-by: Evan <evanpelle@gmail.com> |
||
|
|
c371112e9e |
Add performance stats (#2338)
## Description: Enhanced the performance overlay to display additional tick-related performance metrics. The overlay now shows: 1. **Tick Execution Duration** - Average and maximum time (in milliseconds) it takes to execute a game tick 2. **Tick Delay** - Average and maximum time (in milliseconds) between receiving tick updates from the server The server sends 10 updates per second (100ms interval), so these metrics help identify: - Client-side performance bottlenecks (tick execution duration) - Network latency issues (tick delay) **Additional improvements:** - Renamed `FPSDisplay` component to `PerformanceOverlay` to better reflect its expanded purpose - Updated method names (`updateFPS` → `updateFrameMetrics`) and CSS classes for consistency All metrics are tracked over the last 60 ticks, providing rolling averages and maximum values for performance analysis. ## Please complete the following: - [x] I have added screenshots for all UI updates: - <img width="495" height="227" alt="image" src="https://github.com/user-attachments/assets/142b0313-61bf-46cc-b595-61fe73f6b54c" /> - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - Translation keys already exist in en.json for "performance_overlay_label" and "performance_overlay_desc" - [x] I have added relevant tests to the test directory - All existing tests pass (309/310 tests passed) - No new tests added as this is primarily a display enhancement - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced - Tested locally with npm test - Verified performance overlay displays all metrics correctly - Confirmed tick metrics are calculated and displayed accurately ## Please put your Discord username so you can be contacted if a bug or regression is found: Discord: kerverse --------- Co-authored-by: Evan <evanpelle@gmail.com> |
||
|
|
0def339ad9 |
Fix modifierkey setting for mac (#2327)
## Description: Currently not an issue, but this is a code smell in case we ever decide to have it editable, current implementation will make the default overwrite the custom setting Pointed out by #1804 ## 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 |
||
|
|
b9a4add1ca |
Revert "Added trackpad support for moving maps (#1717)"
This reverts commit
|
||
|
|
d59b73d6b9 |
Revert "Fix: Rework wheel and touch handling for pan and zoom (#1956)"
This reverts commit
|
||
|
|
f6839ffe99 |
Fix icons and add mirv to build bar (#2154)
## Description: Fix blurry icons and add mirv to build bar <img width="792" height="101" alt="image" src="https://github.com/user-attachments/assets/a46c4724-c99b-4541-b56b-92ec662c8ec5" /> <img width="176" height="275" alt="image" src="https://github.com/user-attachments/assets/dbcd2ed4-0f21-4065-9a52-9b16e9043270" /> ## 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 |
||
|
|
311d43ab4f |
Build bar (#2059)
## Description: Make the unit display bar a proper unit build bar Add shortcuts for all structures and units Add ranges for ranged structures and units Changed the shortcuts to use the key instead of the code for internationalization purposes  <img width="285" height="517" alt="image" src="https://github.com/user-attachments/assets/91bb01e6-e48c-4255-ace1-306af9cdc25b" /> ## 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 --------- Co-authored-by: evanpelle <evanpelle@gmail.com> Co-authored-by: icslucas <carolinacarazolli@gmail.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> |
||
|
|
584acea7ed |
Fix: Rework wheel and touch handling for pan and zoom (#1956)
## Description: Fixes https://github.com/openfrontio/OpenFrontIO/issues/1827. Summary: - Restore the code of `onScroll()` method which was modified by #1717. - Rework he `wheel` event logic to better distinguish between trackpad pans and mouse wheel zooms. It now uses a heuristic where any scroll event with a horizontal component (`deltaX !== 0`) is treated as a pan, while purely vertical scrolls are treated as a zoom. This is a compromise that fixes mouse wheel behavior, with the trade-off that vertical-only trackpad swipes now also zoom (which is difficult for human fingers to trigger). - Solve the screen jittering problem when touching the screen by 2 fingers (which because when the second finger touches, `lastPointerX` and `lastPointerY` are not recalculated in time.). **Screen recording before fixing:** (macbook, broken scroll zoom) https://github.com/user-attachments/assets/5ba0fc24-2aec-4ecb-ab0f-2b0a0574d57e (iphone, 2-fingers drag works well, but screen jittering exists) https://github.com/user-attachments/assets/374f4f0f-688c-4b75-a20a-177144556c8c **and after fixing:** (macbook, scroll works well) https://github.com/user-attachments/assets/b7e3447f-9936-4971-90c4-8644d0a9619d (iphone, 2-fingers drag works well, no screen jittering) https://github.com/user-attachments/assets/9d952082-a672-42b6-a117-7a9fed6ea5f0 ## 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: yumika8269 |
||
|
|
8746df69fd |
Added trackpad support for moving maps (#1717)
## Description: Added 2-fingers control for map with trackpad ## 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: pierre_brtr |
||
|
|
c3576a50b9 |
Add auto-upgrade buildings feature with middle mouse click (#1597)
## Description: This PR implements a new feature allowing automatic upgrade of the nearest building using the middle mouse button. This feature greatly simplifies the upgrade process that previously required a right-click + building recreation. ## 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: Kipstzz --------- Co-authored-by: Scott Anderson <662325+scottanderson@users.noreply.github.com> |
||
|
|
e5f47e34d7 |
Shift scroll only increase (#1625)
## Description: Determine which scroll event delta, x or y, has the non zero value. Use it to determine troop ratio increase or decrease. Shift + Scroll can change scroll diretion from Y to X axis. If that is enabled this change will still allow troop ratio increase / decrease ## 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 - [ ] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced - [ ] 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: richard012659 --------- Co-authored-by: Drills Kibo <59177241+drillskibo@users.noreply.github.com> |
||
|
|
c5484696f7 |
Display FPS monitor overview (#1573)
## Description: Display an FPS monitor to track performance on each new feature. It only appears in the development environment, positioned at the top center to remain visible—especially on mobile. The display can be closed via a close button. I already use it to evaluate my other PR on low end device. <img width="1126" height="845" alt="image" src="https://github.com/user-attachments/assets/a7197572-6aea-47df-9dd2-e84947c7aee0" /> ## 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 aggreement (only required once). ## Please put your Discord username so you can be contacted if a bug or regression is found: devalnor |
||
|
|
71fe6a81a0 |
Improve the alternate view by adding geopolitical colors for territories and hover-based highlighting (#1320)
## 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/900 https://github.com/openfrontio/OpenFrontIO/issues/484 ## Please put your Discord username so you can be contacted if a bug or regression is found: devalnor |
||
|
|
105286ed29 |
Add new icon shapes and filter for filtering icons on the layer (#1348)
## Description: Add triangle shape for missile silos, square for sam, octagon for defense posts, and add a filter in the topbar to highlight structures   ## 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: Vivacious Box |
||
|
|
b181c6c15d |
Keybind Ground Attack (#1258)
## Description: - Implement ground attack logic in ClientGameRunner - Move cursor location logic from doBoatAttackUnderCursor to getTileUnderCursor for reusability. - New keybind G for Ground Attack - Add translations for ground attack labels in English ## 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 <img width="902" alt="image" src="https://github.com/user-attachments/assets/54bb3178-af2e-4715-bfa2-82b7fe0e8e85" /> *The getTileUnderCursor() and doGroundAttackUnderCursor() methods are private with many dependencies. I did not do isolated unit testing and thus zero tests where added. ## Please put your Discord username so you can be contacted if a bug or regression is found: eng.la --------- Co-authored-by: evanpelle <evanpelle@gmail.com> |
||
|
|
22e0de9526 |
Add a Replay speed control feature (#1106)
## Description: PR for https://github.com/openfrontio/OpenFrontIO/issues/1105 This pull request introduces a new replay-panel under options-menu to control singleplayer and replay speed.  User can select 4 different speed multipliers based on the turnIntervalMs config. I locally tested the feature in singleplayer mode. I couldn't find a way to test replay mode. Tested with the pause button, working as you would expect. Here is an example: [replay-speed.webm](https://github.com/user-attachments/assets/7b3a7616-5f8f-4fbb-88ba-0b2414c6f2ea) ## 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 ⚠️ I need help to test this feature in real conditions with a replayed game in dev env. - [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: ghisloufou --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: evanpelle <evanpelle@gmail.com> |
||
|
|
063574c224 |
fix: correct mac modifier and emoji key detection in input handler (#1118)
## Description: Fixes Command and Option Keys for Mac. Shows this modification in help  ## 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: George Co-authored-by: cmesona <christopher.mesona@ubisoft.com> |
||
|
|
4367bacf71 |
Add Boat hotkey (#1060)
## Description: Pressing B to fast boat  ## 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: dovg |
||
|
|
b29cc56abc |
added ratio controls (#963)
## Description: added custom controls for attack ration to user setting ## 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: @qqkedsi  Co-authored-by: evanpelle <evanpelle@gmail.com> |
||
|
|
70745faac4 |
Enable strictNullChecks, eqeqeq (#436)
## 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> |
||
|
|
7092e9c166 |
Added keybinding configuration. (#548)
## Description: Added support for customizable keybind settings. fixes #549 fixed these bug https://discord.com/channels/1284581928254701718/1363254158341308668 https://discord.com/channels/1284581928254701718/1362159209642459166 ## 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: aotumuri |
||
|
|
a97a608dce |
Add Alt + Click hotkey for sending emotes (#408)
## Description: Allows the player to Alt + Click to send emotes to other players or themself in order to ease communication. Of course, the hotkey can be something different. Alt + Click is just a suggestion.  ## 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: kanekane0448 PS: The new emoji table looks really good! --------- Co-authored-by: kanekane0448 <no@mail.pls> |
||
|
|
52f64db6d3 |
Fix various ESLint violations (#402)
## Description: Fixes a number of ESLint violations. Although I have tested these changes through the local dev server, I don't have a high confidence that the testing is sufficient, as I am new to this codebase. This change would benefit from heightened scrutiny. ## 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: fake.neo --------- Co-authored-by: Scott Anderson <662325+scottanderson@users.noreply.github.com> |
||
|
|
8b6895d745 | add prettier import plugin | ||
|
|
e926fb5cd5 |
handle edge case
no accessibilité |
||
|
|
44de3516e8 | fix: laptop pinch-zoom | ||
|
|
0790c3d818 |
fix: touch screen should always open menu when touch screen
Previous patch (to choos left click actions) by mistake made touchscreen by default attack with touch instead of open menu |