Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions resources/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,8 @@
"view_options": "View Options",
"toggle_view": "Toggle View",
"toggle_view_desc": "Alternate view (terrain/countries)",
"reset_gfx": "Reset Graphics",
"reset_gfx_desc": "Reset / refresh the graphics renderer.",
"build_controls": "Build Controls",
"build_city": "Build City",
"build_city_desc": "Build a City under your cursor.",
Expand All @@ -767,6 +769,8 @@
"build_menu_modifier_desc": "Hold this key while clicking to open the build menu.",
"emoji_menu_modifier": "Emoji Menu Modifier",
"emoji_menu_modifier_desc": "Hold this key while clicking to open the emoji menu.",
"shift_key": "Warship Box Select",
"shift_key_desc": "Hold this key and drag to draw a selection box that selects all warships within it.",
"pause_game": "Pause",
"pause_game_desc": "Pause or resume the game (single player and custom games for host).",
"game_speed_up": "Game Speed Up",
Expand Down Expand Up @@ -794,6 +798,8 @@
"break_alliance_desc": "Break alliance with the player whose tile is under your cursor.",
"swap_direction": "Swap Rocket Direction",
"swap_direction_desc": "Toggle rocket launch direction (up/down).",
"select_all_warships": "Select All Warships",
"select_all_warships_desc": "Select all your warships at once.",
"zoom_controls": "Zoom Controls",
"zoom_out": "Zoom Out",
"zoom_out_desc": "Zoom out the map",
Expand Down
31 changes: 21 additions & 10 deletions src/client/InputHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -482,8 +482,7 @@ export class InputHandler {
this.eventBus.emit(new AlternateViewEvent(false));
}

const resetKey = this.keybinds.resetGfx ?? "KeyR";
if (e.code === resetKey && this.isAltKeyHeld(e)) {
if (this.keybindMatchesEvent(e, this.keybinds.resetGfx ?? "Alt+KeyR")) {
e.preventDefault();
this.eventBus.emit(new RefreshGraphicsEvent());
}
Expand Down Expand Up @@ -854,24 +853,36 @@ export class InputHandler {
}

/**
* Parses a keybind value that may include a "Shift+" prefix.
* e.g. "Shift+KeyB" → { shift: true, code: "KeyB" }
* "KeyB" → { shift: false, code: "KeyB" }
* Parses a keybind value that may include a "Shift+" or "Alt+" prefix.
* e.g. "Shift+KeyB" → { shift: true, alt: false, code: "KeyB" }
* "Alt+KeyR" → { shift: false, alt: true, code: "KeyR" }
* "KeyB" → { shift: false, alt: false, code: "KeyB" }
*/
private parseKeybind(value: string): { shift: boolean; code: string } {
private parseKeybind(value: string): {
shift: boolean;
alt: boolean;
code: string;
} {
if (value?.startsWith("Shift+")) {
return { shift: true, code: value.slice(6) };
return { shift: true, alt: false, code: value.slice(6) };
}
return { shift: false, code: value };
if (value?.startsWith("Alt+")) {
return { shift: false, alt: true, code: value.slice(4) };
}
return { shift: false, alt: false, code: value };
}

/**
* Returns true if the keyboard event matches the given keybind value,
* including optional Shift+ prefix support.
* including optional Shift+ and Alt+ prefix support.
*/
private keybindMatchesEvent(e: KeyboardEvent, keybindValue: string): boolean {
const parsed = this.parseKeybind(keybindValue);
return e.code === parsed.code && e.shiftKey === parsed.shift;
return (
e.code === parsed.code &&
e.shiftKey === parsed.shift &&
e.altKey === parsed.alt
);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

/**
Expand Down
31 changes: 30 additions & 1 deletion src/client/UserSettingModal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ export class UserSettingModal extends BaseModal {
activeKeybinds[k] = normalizedValue;
}
}

const values = Object.entries(activeKeybinds)
.filter(([k]) => k !== action)
.map(([, v]) => v);
Expand Down Expand Up @@ -401,6 +400,16 @@ export class UserSettingModal extends BaseModal {
@change=${this.handleKeybindChange}
></setting-keybind>

<setting-keybind
action="resetGfx"
label=${translateText("user_setting.reset_gfx")}
description=${translateText("user_setting.reset_gfx_desc")}
.defaultKey=${this.defaultKeybinds.resetGfx}
.value=${this.getKeyValue("resetGfx")}
.display=${this.getKeyChar("resetGfx")}
@change=${this.handleKeybindChange}
></setting-keybind>

<h2
class="text-blue-200 text-xl font-bold mt-8 mb-3 border-b border-white/10 pb-2"
>
Expand Down Expand Up @@ -639,6 +648,26 @@ export class UserSettingModal extends BaseModal {
@change=${this.handleKeybindChange}
></setting-keybind>

<setting-keybind
action="selectAllWarships"
label=${translateText("user_setting.select_all_warships")}
description=${translateText("user_setting.select_all_warships_desc")}
.defaultKey=${this.defaultKeybinds.selectAllWarships}
.value=${this.getKeyValue("selectAllWarships")}
.display=${this.getKeyChar("selectAllWarships")}
@change=${this.handleKeybindChange}
></setting-keybind>

<setting-keybind
action="shiftKey"
label=${translateText("user_setting.shift_key")}
description=${translateText("user_setting.shift_key_desc")}
.defaultKey=${this.defaultKeybinds.shiftKey}
.value=${this.getKeyValue("shiftKey")}
.display=${this.getKeyChar("shiftKey")}
@change=${this.handleKeybindChange}
></setting-keybind>
Comment on lines +651 to +669
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

New warship keybind settings can save combos that gameplay may not execute.

These new controls accept modifier combos, but runtime matching for these actions is still not fully modifier-aware. Users can configure valid-looking binds that won’t trigger.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/client/UserSettingModal.ts` around lines 651 - 669, The new warship
keybind controls allow modifier combos that the runtime doesn't support; update
the keybind-saving flow to validate/normalize binds for the affected actions
(e.g., action="selectAllWarships" and action="shiftKey") by changing
handleKeybindChange to detect modifier-inclusive combos and either strip
modifiers or reject them (fallback to this.defaultKeybinds.selectAllWarships)
before persisting, and ensure getKeyValue/getKeyChar are consistent with that
normalized format so saved values cannot be a modifier-only or
modifier-combination that won’t match at runtime.


<h2
class="text-blue-200 text-xl font-bold mt-8 mb-3 border-b border-white/10 pb-2"
>
Expand Down
5 changes: 5 additions & 0 deletions src/client/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,11 @@ export function formatKeyForDisplay(value: string): string {
return "Shift+" + formatKeyForDisplay(value.slice(6));
}

// Handle Alt+ prefix: format as "Alt+X"
if (value.startsWith("Alt+")) {
return "Alt+" + formatKeyForDisplay(value.slice(4));
}

// Handle space character or "Space" key
if (value === " " || value === "Space") return "Space";

Expand Down
14 changes: 12 additions & 2 deletions src/client/components/baseComponents/setting/SettingKeybind.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,18 @@ export class SettingKeybind extends LitElement {
// Prevent default only for keys we're actually capturing
e.preventDefault();

const code = e.shiftKey ? `Shift+${e.code}` : e.code;
const displayKey = e.shiftKey ? `Shift+${e.key.toUpperCase()}` : e.key;
let code: string;
let displayKey: string;
if (e.shiftKey) {
code = `Shift+${e.code}`;
displayKey = `Shift+${e.key.toUpperCase()}`;
} else if (e.altKey) {
code = `Alt+${e.code}`;
displayKey = code; // e.key would give special chars (e.g. ® for Alt+R); use code instead
} else {
code = e.code;
displayKey = e.key;
}
const prevValue = this.value;

// Temporarily set the value to the new code for validation in parent
Expand Down
2 changes: 1 addition & 1 deletion src/core/game/UserSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export function getDefaultKeybinds(isMac: boolean): Record<string, string> {
modifierKey: isMac ? "MetaLeft" : "ControlLeft",
altKey: "AltLeft",
shiftKey: "ShiftLeft",
resetGfx: "KeyR",
resetGfx: "Alt+KeyR",
Comment thread
coderabbitai[bot] marked this conversation as resolved.
selectAllWarships: "KeyF",
pauseGame: "KeyP",
gameSpeedUp: "Period",
Expand Down
Loading