From 179ff4bd8fd7645ded0f0c5551c73fbb59046a73 Mon Sep 17 00:00:00 2001 From: TKTK123456 <103334266+TKTK123456@users.noreply.github.com> Date: Thu, 11 Jun 2026 15:45:04 -0400 Subject: [PATCH 01/22] Reworked InputHandler --- src/client/InputHandler.ts | 135 ++++++++++++++++++++++++++++--------- 1 file changed, 102 insertions(+), 33 deletions(-) diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts index 774ddbdcb7..26259c231f 100644 --- a/src/client/InputHandler.ts +++ b/src/client/InputHandler.ts @@ -222,6 +222,7 @@ export class InputHandler { private moveInterval: NodeJS.Timeout | null = null; private activeKeys = new Set(); private keybinds: Record = {}; + private keybindAndEvent: Map = new Map(); private coordinateGridEnabled = false; private readonly PAN_SPEED = 5; @@ -240,6 +241,69 @@ export class InputHandler { initialize() { this.keybinds = this.userSettings.keybinds(Platform.isMac); + this.addKeybindAndEvent(this.keybinds.boatAttack, () => { + this.eventBus.emit(new DoBoatAttackEvent()); + }); + this.addKeybindAndEvent(this.keybinds.groundAttack, () => { + this.eventBus.emit(new DoGroundAttackEvent()); + }); + this.addKeybindAndEvent(this.keybinds.retaliateAttack, () => { + this.eventBus.emit(new DoRetaliateAttackEvent()); + }); + this.addKeybindAndEvent(this.keybinds.centerCamera, () => { + this.eventBus.emit(new CenterCameraEvent()); + }); + this.addKeybindAndEvent(this.keybinds.selectAllWarships, () => { + this.eventBus.emit(new SelectAllWarshipsEvent()); + }); + this.addKeybindAndEvent(this.keybinds.requestAlliance, () => { + this.eventBus.emit(new DoRequestAllianceEvent()); + }); + this.addKeybindAndEvent(this.keybinds.breakAlliance, () => { + this.eventBus.emit(new DoBreakAllianceEvent()); + }); + this.addKeybindAndEvent( + this.keybinds.pauseGame, + () => { + this.eventBus.emit(new TogglePauseIntentEvent()); + }, + (e: KeyboardEvent) => !e.repeat, + ); + this.addKeybindAndEvent( + this.keybinds.gameSpeedUp, + () => { + this.eventBus.emit(new GameSpeedUpIntentEvent()); + }, + (e: KeyboardEvent) => !e.repeat, + ); + this.addKeybindAndEvent( + this.keybinds.gameSpeedDown, + () => { + this.eventBus.emit(new GameSpeedDownIntentEvent()); + }, + (e: KeyboardEvent) => !e.repeat, + ); + this.addKeybindAndEvent(this.keybinds.attackRatioDown, () => { + const increment = this.userSettings.attackRatioIncrement(); + this.eventBus.emit(new AttackRatioEvent(-increment)); + }); + this.addKeybindAndEvent(this.keybinds.attackRatioUp, () => { + const increment = this.userSettings.attackRatioIncrement(); + this.eventBus.emit(new AttackRatioEvent(increment)); + }); + this.addKeybindAndEvent(this.keybinds.swapDirection, () => { + const nextDirection = !this.uiState.rocketDirectionUp; + this.eventBus.emit(new SwapRocketDirectionEvent(nextDirection)); + }); + this.addKeybindAndEvent("Shift+KeyD", () => { + console.log("TogglePerformanceOverlayEvent"); + this.eventBus.emit(new TogglePerformanceOverlayEvent()); + }); + this.addKeybindAndEvent(this.keybinds.toggleView, () => { + this.alternateView = false; + this.eventBus.emit(new AlternateViewEvent(false)); + }); + // Listen for warship selection to change cursor this.eventBus.on(UnitSelectionEvent, (e) => { if (e.isSelected && (e.units ?? []).length > 0) { @@ -438,6 +502,8 @@ export class InputHandler { this.keybinds.shiftKey, this.keybinds.emojiMenuModifier, this.keybinds.buildMenuModifier, + "AltLeft", + "AltRight", ].includes(e.code) ) { this.activeKeys.add(e.code); @@ -475,7 +541,21 @@ export class InputHandler { this.activeKeys.delete(this.keybinds.zoomIn); this.activeKeys.delete(this.keybinds.zoomOut); } - + + for(const item of this.keybindAndEvent) { + if (this.keybindMatchesEvent(e, item[0])) { + let allConditionsFullfiled = true; + for (const i of item[1].slice(1)) { + if (!i(e)) { + allConditionsFullfiled = false + } + } + if (!allConditionsFullfiled) continue; + e.preventDefault(); + item[1][0]() + } + } + /* if (this.keybindMatchesEvent(e, this.keybinds.toggleView)) { e.preventDefault(); this.alternateView = false; @@ -483,7 +563,10 @@ export class InputHandler { } const resetKey = this.keybinds.resetGfx ?? "KeyR"; - if (e.code === resetKey && this.isAltKeyHeld(e)) { + if ( + e.code === resetKey && + (this.activeKeys.has("AltLeft") || this.activeKeys.has("AltRight")) + ) { e.preventDefault(); this.eventBus.emit(new RefreshGraphicsEvent()); } @@ -524,7 +607,7 @@ export class InputHandler { e.preventDefault(); this.eventBus.emit(new SelectAllWarshipsEvent()); } - +*/ // Two-phase build keybind matching: exact code match first, then digit/Numpad alias. if (this.canUseBuildKeybinds()) { const matchedBuild = this.resolveBuildKeybind(e.code, e.shiftKey); @@ -533,7 +616,7 @@ export class InputHandler { this.setGhostStructure(matchedBuild); } } - +/* if (this.keybindMatchesEvent(e, this.keybinds.requestAlliance)) { e.preventDefault(); this.eventBus.emit(new DoRequestAllianceEvent()); @@ -572,7 +655,7 @@ export class InputHandler { console.log("TogglePerformanceOverlayEvent"); this.eventBus.emit(new TogglePerformanceOverlayEvent()); } - +*/ this.activeKeys.delete(e.code); // Reset crosshair when Shift is released (unless selection box or multi-selection still active) @@ -916,6 +999,20 @@ export class InputHandler { return digit !== null && bindDigit !== null && digit === bindDigit; } + /** + * Add a keybind that activates on one press + * @param keybind The keybind that is being activated + * @param event The code to be exectued when this keybind is pressed + * @param conditions Optional conditions that can be added, they get the keyboard up event passed to them + */ + private addKeybindAndEvent( + keybind: string, + event: Function, + ...conditions: Function[] + ) { + this.keybindAndEvent.set(keybind, [event, ...conditions]); + } + /** * Resolves a keyup code to a build action: exact code match first, then digit/Numpad alias. * Returns the UnitType to set as ghost, or null if no build keybind matched. @@ -992,32 +1089,4 @@ export class InputHandler { } this.activeKeys.clear(); } - - private isAltKeyHeld(event: KeyboardEvent): boolean { - if ( - this.keybinds.altKey === "AltLeft" || - this.keybinds.altKey === "AltRight" - ) { - return event.altKey && !event.ctrlKey; - } - if ( - this.keybinds.altKey === "ControlLeft" || - this.keybinds.altKey === "ControlRight" - ) { - return event.ctrlKey; - } - if ( - this.keybinds.altKey === "ShiftLeft" || - this.keybinds.altKey === "ShiftRight" - ) { - return event.shiftKey; - } - if ( - this.keybinds.altKey === "MetaLeft" || - this.keybinds.altKey === "MetaRight" - ) { - return event.metaKey; - } - return false; - } } From 9c1594d31008fa715268a6ae8f1899c64388c757 Mon Sep 17 00:00:00 2001 From: TKTK123456 <103334266+TKTK123456@users.noreply.github.com> Date: Thu, 11 Jun 2026 15:51:28 -0400 Subject: [PATCH 02/22] Removed comments that had previous code --- src/client/InputHandler.ts | 97 ++------------------------------------ 1 file changed, 4 insertions(+), 93 deletions(-) diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts index 26259c231f..730b055ed0 100644 --- a/src/client/InputHandler.ts +++ b/src/client/InputHandler.ts @@ -303,6 +303,10 @@ export class InputHandler { this.alternateView = false; this.eventBus.emit(new AlternateViewEvent(false)); }); + const resetKey = this.keybinds.resetGfx ?? "KeyR"; + this.addKeybindAndEvent(resetKey, () => { + this.eventBus.emit(new RefreshGraphicsEvent()); + }, (e: KeyboardEvent) => (this.activeKeys.has("AltLeft") || this.activeKeys.has("AltRight"))); // Listen for warship selection to change cursor this.eventBus.on(UnitSelectionEvent, (e) => { @@ -555,59 +559,6 @@ export class InputHandler { item[1][0]() } } - /* - if (this.keybindMatchesEvent(e, this.keybinds.toggleView)) { - e.preventDefault(); - this.alternateView = false; - this.eventBus.emit(new AlternateViewEvent(false)); - } - - const resetKey = this.keybinds.resetGfx ?? "KeyR"; - if ( - e.code === resetKey && - (this.activeKeys.has("AltLeft") || this.activeKeys.has("AltRight")) - ) { - e.preventDefault(); - this.eventBus.emit(new RefreshGraphicsEvent()); - } - - if (this.keybindMatchesEvent(e, this.keybinds.boatAttack)) { - e.preventDefault(); - this.eventBus.emit(new DoBoatAttackEvent()); - } - - if (this.keybindMatchesEvent(e, this.keybinds.groundAttack)) { - e.preventDefault(); - this.eventBus.emit(new DoGroundAttackEvent()); - } - - if (this.keybindMatchesEvent(e, this.keybinds.retaliateAttack)) { - e.preventDefault(); - this.eventBus.emit(new DoRetaliateAttackEvent()); - } - - if (this.keybindMatchesEvent(e, this.keybinds.attackRatioDown)) { - e.preventDefault(); - const increment = this.userSettings.attackRatioIncrement(); - this.eventBus.emit(new AttackRatioEvent(-increment)); - } - - if (this.keybindMatchesEvent(e, this.keybinds.attackRatioUp)) { - e.preventDefault(); - const increment = this.userSettings.attackRatioIncrement(); - this.eventBus.emit(new AttackRatioEvent(increment)); - } - - if (this.keybindMatchesEvent(e, this.keybinds.centerCamera)) { - e.preventDefault(); - this.eventBus.emit(new CenterCameraEvent()); - } - - if (e.code === this.keybinds.selectAllWarships) { - e.preventDefault(); - this.eventBus.emit(new SelectAllWarshipsEvent()); - } -*/ // Two-phase build keybind matching: exact code match first, then digit/Numpad alias. if (this.canUseBuildKeybinds()) { const matchedBuild = this.resolveBuildKeybind(e.code, e.shiftKey); @@ -616,46 +567,6 @@ export class InputHandler { this.setGhostStructure(matchedBuild); } } -/* - if (this.keybindMatchesEvent(e, this.keybinds.requestAlliance)) { - e.preventDefault(); - this.eventBus.emit(new DoRequestAllianceEvent()); - } - - if (this.keybindMatchesEvent(e, this.keybinds.breakAlliance)) { - e.preventDefault(); - this.eventBus.emit(new DoBreakAllianceEvent()); - } - - if (this.keybindMatchesEvent(e, this.keybinds.swapDirection)) { - e.preventDefault(); - const nextDirection = !this.uiState.rocketDirectionUp; - this.eventBus.emit(new SwapRocketDirectionEvent(nextDirection)); - } - - if (!e.repeat && this.keybindMatchesEvent(e, this.keybinds.pauseGame)) { - e.preventDefault(); - this.eventBus.emit(new TogglePauseIntentEvent()); - } - if (!e.repeat && this.keybindMatchesEvent(e, this.keybinds.gameSpeedUp)) { - e.preventDefault(); - this.eventBus.emit(new GameSpeedUpIntentEvent()); - } - if ( - !e.repeat && - this.keybindMatchesEvent(e, this.keybinds.gameSpeedDown) - ) { - e.preventDefault(); - this.eventBus.emit(new GameSpeedDownIntentEvent()); - } - - // Shift-D to toggle performance overlay - if (e.code === "KeyD" && e.shiftKey) { - e.preventDefault(); - console.log("TogglePerformanceOverlayEvent"); - this.eventBus.emit(new TogglePerformanceOverlayEvent()); - } -*/ this.activeKeys.delete(e.code); // Reset crosshair when Shift is released (unless selection box or multi-selection still active) From 314584433b5787cf57747992f98a431a81882012 Mon Sep 17 00:00:00 2001 From: TKTK123456 <103334266+TKTK123456@users.noreply.github.com> Date: Thu, 11 Jun 2026 16:10:01 -0400 Subject: [PATCH 03/22] Added build keybinds to keybindAndEvent map --- src/client/InputHandler.ts | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts index 730b055ed0..1090187f59 100644 --- a/src/client/InputHandler.ts +++ b/src/client/InputHandler.ts @@ -308,6 +308,15 @@ export class InputHandler { this.eventBus.emit(new RefreshGraphicsEvent()); }, (e: KeyboardEvent) => (this.activeKeys.has("AltLeft") || this.activeKeys.has("AltRight"))); + const buildKeybinds = ["buildCity", "buildFactory", "buildPort", "buildDefensePost", "buildMissileSilo", "buildSamLauncher", "buildAtomBomb", "buildHydrogenBomb", "buildWarship", "buildMIRV"] + for (const i of buildKeybinds) { + this.addKeybindAndEvent(this.keybinds[i], (e: KeyboardEvent) => { + const matchedBuild = this.resolveBuildKeybind(e.code, e.shiftKey); + if (matchedBuild !== null) { + this.setGhostStructure(matchedBuild); + } + }, this.canUseBuildKeybinds, (e: KeyboardEvent) => (this.resolveBuildKeybind(e.code, e.shiftKey) !== null)) + } // Listen for warship selection to change cursor this.eventBus.on(UnitSelectionEvent, (e) => { if (e.isSelected && (e.units ?? []).length > 0) { @@ -556,15 +565,7 @@ export class InputHandler { } if (!allConditionsFullfiled) continue; e.preventDefault(); - item[1][0]() - } - } - // Two-phase build keybind matching: exact code match first, then digit/Numpad alias. - if (this.canUseBuildKeybinds()) { - const matchedBuild = this.resolveBuildKeybind(e.code, e.shiftKey); - if (matchedBuild !== null) { - e.preventDefault(); - this.setGhostStructure(matchedBuild); + item[1][0](e); } } this.activeKeys.delete(e.code); @@ -861,7 +862,7 @@ export class InputHandler { * Returns true if the keyboard event matches the given keybind value, * including optional Shift+ prefix support. */ - private keybindMatchesEvent(e: KeyboardEvent, keybindValue: string): boolean { + private keybindMatchesEvent(e: KeyboardEvent | { shiftKey: boolean; code: string }, keybindValue: string): boolean { const parsed = this.parseKeybind(keybindValue); return e.code === parsed.code && e.shiftKey === parsed.shift; } @@ -887,16 +888,6 @@ export class InputHandler { return null; } - /** Strict equality only: used for first-pass exact KeyboardEvent.code match. */ - private buildKeybindMatches( - code: string, - shiftKey: boolean, - keybindValue: string, - ): boolean { - const parsed = this.parseKeybind(keybindValue); - return code === parsed.code && shiftKey === parsed.shift; - } - /** Digit/Numpad alias match: used only when no exact match was found. */ private buildKeybindMatchesDigit( code: string, @@ -948,7 +939,7 @@ export class InputHandler { { key: "buildMIRV", type: UnitType.MIRV }, ]; for (const { key, type } of buildKeybinds) { - if (this.buildKeybindMatches(code, shiftKey, this.keybinds[key])) + if (this.keybindMatchesEvent({code, shiftKey}, this.keybinds[key])) return type; } for (const { key, type } of buildKeybinds) { From b8ed5c0d79e3f2dc730735842f4ac2807c7c0f13 Mon Sep 17 00:00:00 2001 From: TKTK123456 <103334266+TKTK123456@users.noreply.github.com> Date: Thu, 11 Jun 2026 16:15:51 -0400 Subject: [PATCH 04/22] Quick bug fix and format --- src/client/InputHandler.ts | 51 ++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts index 1090187f59..e357ec8e14 100644 --- a/src/client/InputHandler.ts +++ b/src/client/InputHandler.ts @@ -303,20 +303,42 @@ export class InputHandler { this.alternateView = false; this.eventBus.emit(new AlternateViewEvent(false)); }); - const resetKey = this.keybinds.resetGfx ?? "KeyR"; - this.addKeybindAndEvent(resetKey, () => { + const resetKey = this.keybinds.resetGfx ?? "KeyR"; + this.addKeybindAndEvent( + resetKey, + () => { this.eventBus.emit(new RefreshGraphicsEvent()); - }, (e: KeyboardEvent) => (this.activeKeys.has("AltLeft") || this.activeKeys.has("AltRight"))); + }, + (e: KeyboardEvent) => + this.activeKeys.has("AltLeft") || this.activeKeys.has("AltRight"), + ); - const buildKeybinds = ["buildCity", "buildFactory", "buildPort", "buildDefensePost", "buildMissileSilo", "buildSamLauncher", "buildAtomBomb", "buildHydrogenBomb", "buildWarship", "buildMIRV"] - for (const i of buildKeybinds) { - this.addKeybindAndEvent(this.keybinds[i], (e: KeyboardEvent) => { + const buildKeybinds = [ + "buildCity", + "buildFactory", + "buildPort", + "buildDefensePost", + "buildMissileSilo", + "buildSamLauncher", + "buildAtomBomb", + "buildHydrogenBomb", + "buildWarship", + "buildMIRV", + ]; + for (const i of buildKeybinds) { + this.addKeybindAndEvent( + this.keybinds[i], + (e: KeyboardEvent) => { const matchedBuild = this.resolveBuildKeybind(e.code, e.shiftKey); if (matchedBuild !== null) { this.setGhostStructure(matchedBuild); } - }, this.canUseBuildKeybinds, (e: KeyboardEvent) => (this.resolveBuildKeybind(e.code, e.shiftKey) !== null)) - } + }, + () => this.canUseBuildKeybinds(), + (e: KeyboardEvent) => + this.resolveBuildKeybind(e.code, e.shiftKey) !== null, + ); + } // Listen for warship selection to change cursor this.eventBus.on(UnitSelectionEvent, (e) => { if (e.isSelected && (e.units ?? []).length > 0) { @@ -554,13 +576,13 @@ export class InputHandler { this.activeKeys.delete(this.keybinds.zoomIn); this.activeKeys.delete(this.keybinds.zoomOut); } - - for(const item of this.keybindAndEvent) { + + for (const item of this.keybindAndEvent) { if (this.keybindMatchesEvent(e, item[0])) { let allConditionsFullfiled = true; for (const i of item[1].slice(1)) { if (!i(e)) { - allConditionsFullfiled = false + allConditionsFullfiled = false; } } if (!allConditionsFullfiled) continue; @@ -862,7 +884,10 @@ export class InputHandler { * Returns true if the keyboard event matches the given keybind value, * including optional Shift+ prefix support. */ - private keybindMatchesEvent(e: KeyboardEvent | { shiftKey: boolean; code: string }, keybindValue: string): boolean { + private keybindMatchesEvent( + e: KeyboardEvent | { shiftKey: boolean; code: string }, + keybindValue: string, + ): boolean { const parsed = this.parseKeybind(keybindValue); return e.code === parsed.code && e.shiftKey === parsed.shift; } @@ -939,7 +964,7 @@ export class InputHandler { { key: "buildMIRV", type: UnitType.MIRV }, ]; for (const { key, type } of buildKeybinds) { - if (this.keybindMatchesEvent({code, shiftKey}, this.keybinds[key])) + if (this.keybindMatchesEvent({ code, shiftKey }, this.keybinds[key])) return type; } for (const { key, type } of buildKeybinds) { From d6b9cd9521aa7d96e11d4f1045132520c7446b64 Mon Sep 17 00:00:00 2001 From: TKTK123456 <103334266+TKTK123456@users.noreply.github.com> Date: Thu, 11 Jun 2026 16:29:57 -0400 Subject: [PATCH 05/22] Fix eslint issue --- src/client/InputHandler.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts index e357ec8e14..494b4ec0f3 100644 --- a/src/client/InputHandler.ts +++ b/src/client/InputHandler.ts @@ -222,7 +222,7 @@ export class InputHandler { private moveInterval: NodeJS.Timeout | null = null; private activeKeys = new Set(); private keybinds: Record = {}; - private keybindAndEvent: Map = new Map(); + private keybindAndEvent: Map any)[]> = new Map(); private coordinateGridEnabled = false; private readonly PAN_SPEED = 5; @@ -934,8 +934,8 @@ export class InputHandler { */ private addKeybindAndEvent( keybind: string, - event: Function, - ...conditions: Function[] + event: (type: KeyboardEvent) => any, + ...conditions: ((type: KeyboardEvent) => any)[] ) { this.keybindAndEvent.set(keybind, [event, ...conditions]); } From fe048ecad7719d4f98627f889a648072acd55cbf Mon Sep 17 00:00:00 2001 From: TKTK123456 <103334266+TKTK123456@users.noreply.github.com> Date: Thu, 11 Jun 2026 20:00:32 -0400 Subject: [PATCH 06/22] Ran formatter --- src/client/InputHandler.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts index 494b4ec0f3..47658a70dd 100644 --- a/src/client/InputHandler.ts +++ b/src/client/InputHandler.ts @@ -222,7 +222,8 @@ export class InputHandler { private moveInterval: NodeJS.Timeout | null = null; private activeKeys = new Set(); private keybinds: Record = {}; - private keybindAndEvent: Map any)[]> = new Map(); + private keybindAndEvent: Map any)[]> = + new Map(); private coordinateGridEnabled = false; private readonly PAN_SPEED = 5; @@ -330,6 +331,7 @@ export class InputHandler { this.keybinds[i], (e: KeyboardEvent) => { const matchedBuild = this.resolveBuildKeybind(e.code, e.shiftKey); + if (matchedBuild !== null) { this.setGhostStructure(matchedBuild); } From d8e52eb293d39da8cee559a6fcd3d0bd04997be9 Mon Sep 17 00:00:00 2001 From: TKTK123456 <103334266+TKTK123456@users.noreply.github.com> Date: Thu, 11 Jun 2026 21:00:19 -0400 Subject: [PATCH 07/22] Added numpad compatibility to buildkeybinds --- src/client/InputHandler.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts index 47658a70dd..dcd17d103b 100644 --- a/src/client/InputHandler.ts +++ b/src/client/InputHandler.ts @@ -314,7 +314,7 @@ export class InputHandler { this.activeKeys.has("AltLeft") || this.activeKeys.has("AltRight"), ); - const buildKeybinds = [ + let buildKeybinds: string[] = [ "buildCity", "buildFactory", "buildPort", @@ -326,9 +326,14 @@ export class InputHandler { "buildWarship", "buildMIRV", ]; + buildKeybinds = buildKeybinds.map((i: string): string => { + return this.keybinds[i] + }) + buildKeybinds.push(...["Numpad0", "Numpad1", "Numpad2", "Numpad3", "Numpad4", "Numpad5", "Numpad6", "Numpad7", "Numpad8", "Numpad9"]) for (const i of buildKeybinds) { + console.log(i) this.addKeybindAndEvent( - this.keybinds[i], + i, (e: KeyboardEvent) => { const matchedBuild = this.resolveBuildKeybind(e.code, e.shiftKey); From d65b727c07cb5f0a199e50e348e9bb17eff41a03 Mon Sep 17 00:00:00 2001 From: TKTK123456 <103334266+TKTK123456@users.noreply.github.com> Date: Thu, 11 Jun 2026 21:30:09 -0400 Subject: [PATCH 08/22] Removed debugging console log --- src/client/InputHandler.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts index dcd17d103b..e30bb37dbc 100644 --- a/src/client/InputHandler.ts +++ b/src/client/InputHandler.ts @@ -331,7 +331,6 @@ export class InputHandler { }) buildKeybinds.push(...["Numpad0", "Numpad1", "Numpad2", "Numpad3", "Numpad4", "Numpad5", "Numpad6", "Numpad7", "Numpad8", "Numpad9"]) for (const i of buildKeybinds) { - console.log(i) this.addKeybindAndEvent( i, (e: KeyboardEvent) => { From 38796200712579299db6a5bb66d0cd8a049b6bcb Mon Sep 17 00:00:00 2001 From: TKTK123456 <103334266+TKTK123456@users.noreply.github.com> Date: Thu, 11 Jun 2026 21:46:49 -0400 Subject: [PATCH 09/22] Formatted --- src/client/InputHandler.ts | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts index e30bb37dbc..1b8448fd11 100644 --- a/src/client/InputHandler.ts +++ b/src/client/InputHandler.ts @@ -327,9 +327,22 @@ export class InputHandler { "buildMIRV", ]; buildKeybinds = buildKeybinds.map((i: string): string => { - return this.keybinds[i] - }) - buildKeybinds.push(...["Numpad0", "Numpad1", "Numpad2", "Numpad3", "Numpad4", "Numpad5", "Numpad6", "Numpad7", "Numpad8", "Numpad9"]) + return this.keybinds[i]; + }); + buildKeybinds.push( + ...[ + "Numpad0", + "Numpad1", + "Numpad2", + "Numpad3", + "Numpad4", + "Numpad5", + "Numpad6", + "Numpad7", + "Numpad8", + "Numpad9", + ], + ); for (const i of buildKeybinds) { this.addKeybindAndEvent( i, From 156a01633674fbfdebf69f99d5b3a254b6c881d2 Mon Sep 17 00:00:00 2001 From: TKTK123456 <103334266+TKTK123456@users.noreply.github.com> Date: Thu, 11 Jun 2026 22:03:31 -0400 Subject: [PATCH 10/22] Added shift compatibility to build keybinds --- src/client/InputHandler.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts index 1b8448fd11..0b976e611b 100644 --- a/src/client/InputHandler.ts +++ b/src/client/InputHandler.ts @@ -343,6 +343,11 @@ export class InputHandler { "Numpad9", ], ); + buildKeybinds.push( + ...buildKeybinds.map((t) => { + return "Shift+" + t; + }), + ); for (const i of buildKeybinds) { this.addKeybindAndEvent( i, From 88e9d3660d0b91198e945c7ada2c576b3830dd4d Mon Sep 17 00:00:00 2001 From: TKTK123456 <103334266+TKTK123456@users.noreply.github.com> Date: Sat, 13 Jun 2026 18:44:50 -0400 Subject: [PATCH 11/22] Added digits to buildKeybinds and made sure its unique. --- src/client/InputHandler.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts index 0b976e611b..fdc023cfcb 100644 --- a/src/client/InputHandler.ts +++ b/src/client/InputHandler.ts @@ -341,6 +341,16 @@ export class InputHandler { "Numpad7", "Numpad8", "Numpad9", + "Digit0", + "Digit1", + "Digit2", + "Digit3", + "Digit4", + "Digit5", + "Digit6", + "Digit7", + "Digit8", + "Digit9", ], ); buildKeybinds.push( @@ -348,6 +358,7 @@ export class InputHandler { return "Shift+" + t; }), ); + buildKeybinds = [... new Set(buildKeybinds)] for (const i of buildKeybinds) { this.addKeybindAndEvent( i, From b2b0e956086fc05d53042280c634e0b7cdd5657f Mon Sep 17 00:00:00 2001 From: TKTK123456 <103334266+TKTK123456@users.noreply.github.com> Date: Sat, 13 Jun 2026 18:54:26 -0400 Subject: [PATCH 12/22] Added keybind entry interface to keybindAndEvent --- src/client/InputHandler.ts | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts index fdc023cfcb..c8957e92c9 100644 --- a/src/client/InputHandler.ts +++ b/src/client/InputHandler.ts @@ -193,6 +193,11 @@ export class TickMetricsEvent implements GameEvent { ) {} } +interface KeybindEntry { + handler: (e: KeyboardEvent) => void; + conditions: Array<(e: KeyboardEvent) => boolean>; +} + export class InputHandler { private lastPointerX: number = 0; private lastPointerY: number = 0; @@ -222,8 +227,7 @@ export class InputHandler { private moveInterval: NodeJS.Timeout | null = null; private activeKeys = new Set(); private keybinds: Record = {}; - private keybindAndEvent: Map any)[]> = - new Map(); + private keybindAndEvent: [[string, KeybindEntry]] private coordinateGridEnabled = false; private readonly PAN_SPEED = 5; @@ -615,14 +619,14 @@ export class InputHandler { for (const item of this.keybindAndEvent) { if (this.keybindMatchesEvent(e, item[0])) { let allConditionsFullfiled = true; - for (const i of item[1].slice(1)) { + for (const i of item[1].conditions) { if (!i(e)) { allConditionsFullfiled = false; } } if (!allConditionsFullfiled) continue; e.preventDefault(); - item[1][0](e); + item[1].handler(e); } } this.activeKeys.delete(e.code); @@ -972,7 +976,11 @@ export class InputHandler { event: (type: KeyboardEvent) => any, ...conditions: ((type: KeyboardEvent) => any)[] ) { - this.keybindAndEvent.set(keybind, [event, ...conditions]); + const entry: KeybindEntry = { + handler: event, + conditions + } + this.keybindAndEvent.push([keybind, entry]); } /** From b7b0cb7c21622b99aa032abebf54a18e46001db2 Mon Sep 17 00:00:00 2001 From: TKTK123456 <103334266+TKTK123456@users.noreply.github.com> Date: Sat, 13 Jun 2026 18:55:31 -0400 Subject: [PATCH 13/22] Removed all undifined from buildKeybinds array --- src/client/InputHandler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts index c8957e92c9..4ece892db2 100644 --- a/src/client/InputHandler.ts +++ b/src/client/InputHandler.ts @@ -362,7 +362,7 @@ export class InputHandler { return "Shift+" + t; }), ); - buildKeybinds = [... new Set(buildKeybinds)] + buildKeybinds = [... new Set(buildKeybinds)].filter((v): v is string => v != null); for (const i of buildKeybinds) { this.addKeybindAndEvent( i, From d6ca3220a063c79b6c554dfe9f2b91d764257e1f Mon Sep 17 00:00:00 2001 From: TKTK123456 <103334266+TKTK123456@users.noreply.github.com> Date: Sat, 13 Jun 2026 18:58:32 -0400 Subject: [PATCH 14/22] Formated --- src/client/InputHandler.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts index b7b09ad8a4..c0ab9ef859 100644 --- a/src/client/InputHandler.ts +++ b/src/client/InputHandler.ts @@ -227,7 +227,7 @@ export class InputHandler { private moveInterval: NodeJS.Timeout | null = null; private activeKeys = new Set(); private keybinds: Record = {}; - private keybindAndEvent: [[string, KeybindEntry]] + private keybindAndEvent: [[string, KeybindEntry]]; private coordinateGridEnabled = false; private readonly PAN_SPEED = 5; @@ -362,7 +362,9 @@ export class InputHandler { return "Shift+" + t; }), ); - buildKeybinds = [... new Set(buildKeybinds)].filter((v): v is string => v != null); + buildKeybinds = [...new Set(buildKeybinds)].filter( + (v): v is string => v != null, + ); for (const i of buildKeybinds) { this.addKeybindAndEvent( i, @@ -978,8 +980,8 @@ export class InputHandler { ) { const entry: KeybindEntry = { handler: event, - conditions - } + conditions, + }; this.keybindAndEvent.push([keybind, entry]); } From bd9a0a277ff3f97e44ad11d2093adef6cb83c898 Mon Sep 17 00:00:00 2001 From: TKTK123456 <103334266+TKTK123456@users.noreply.github.com> Date: Sat, 13 Jun 2026 19:03:28 -0400 Subject: [PATCH 15/22] Fixed eslint issue --- src/client/InputHandler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts index c0ab9ef859..30ccdb07f0 100644 --- a/src/client/InputHandler.ts +++ b/src/client/InputHandler.ts @@ -363,7 +363,7 @@ export class InputHandler { }), ); buildKeybinds = [...new Set(buildKeybinds)].filter( - (v): v is string => v != null, + (v): v is string => v !== null, ); for (const i of buildKeybinds) { this.addKeybindAndEvent( From 106d02d38e339e93074952ac30b4404b01db0d26 Mon Sep 17 00:00:00 2001 From: TKTK123456 <103334266+TKTK123456@users.noreply.github.com> Date: Sat, 13 Jun 2026 19:08:01 -0400 Subject: [PATCH 16/22] Fixed initialization of keybindAndEvent --- src/client/InputHandler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts index 30ccdb07f0..9c3d2b88a1 100644 --- a/src/client/InputHandler.ts +++ b/src/client/InputHandler.ts @@ -227,7 +227,7 @@ export class InputHandler { private moveInterval: NodeJS.Timeout | null = null; private activeKeys = new Set(); private keybinds: Record = {}; - private keybindAndEvent: [[string, KeybindEntry]]; + private keybindAndEvent: Array<[string, KeybindEntry]> = []; private coordinateGridEnabled = false; private readonly PAN_SPEED = 5; From ae55fa773e70ab849f90dc3bcb2a2097c338aec3 Mon Sep 17 00:00:00 2001 From: TKTK123456 <103334266+TKTK123456@users.noreply.github.com> Date: Sat, 13 Jun 2026 19:56:49 -0400 Subject: [PATCH 17/22] Fixed typo --- src/client/InputHandler.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts index 9c3d2b88a1..3bd8867cf1 100644 --- a/src/client/InputHandler.ts +++ b/src/client/InputHandler.ts @@ -620,13 +620,13 @@ export class InputHandler { for (const item of this.keybindAndEvent) { if (this.keybindMatchesEvent(e, item[0])) { - let allConditionsFullfiled = true; + let allConditionsFulfilled = true; for (const i of item[1].conditions) { if (!i(e)) { - allConditionsFullfiled = false; + allConditionsFulfilled = false; } } - if (!allConditionsFullfiled) continue; + if (!allConditionsFulfilled) continue; e.preventDefault(); item[1].handler(e); } From 7a9e8aae1932efe58c6eac955ccddc6f3c5f44f5 Mon Sep 17 00:00:00 2001 From: TKTK123456 <103334266+TKTK123456@users.noreply.github.com> Date: Sat, 13 Jun 2026 19:59:01 -0400 Subject: [PATCH 18/22] Removed allConditionsFulfilled to instead break early --- src/client/InputHandler.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts index 3bd8867cf1..68716f44ee 100644 --- a/src/client/InputHandler.ts +++ b/src/client/InputHandler.ts @@ -618,15 +618,13 @@ export class InputHandler { this.activeKeys.delete(this.keybinds.zoomOut); } - for (const item of this.keybindAndEvent) { + outerLoop: for (const item of this.keybindAndEvent) { if (this.keybindMatchesEvent(e, item[0])) { - let allConditionsFulfilled = true; for (const i of item[1].conditions) { if (!i(e)) { - allConditionsFulfilled = false; + continue outerLoop } } - if (!allConditionsFulfilled) continue; e.preventDefault(); item[1].handler(e); } From 050b5e163464aa7d85d4bbb6a6fa54fd95f45900 Mon Sep 17 00:00:00 2001 From: TKTK123456 <103334266+TKTK123456@users.noreply.github.com> Date: Sat, 13 Jun 2026 20:01:30 -0400 Subject: [PATCH 19/22] Formated --- src/client/InputHandler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts index 68716f44ee..570a041054 100644 --- a/src/client/InputHandler.ts +++ b/src/client/InputHandler.ts @@ -622,7 +622,7 @@ export class InputHandler { if (this.keybindMatchesEvent(e, item[0])) { for (const i of item[1].conditions) { if (!i(e)) { - continue outerLoop + continue outerLoop; } } e.preventDefault(); From ce0302116e68e0b96f04493282ed22e637e80dec Mon Sep 17 00:00:00 2001 From: TKTK123456 <103334266+TKTK123456@users.noreply.github.com> Date: Sat, 13 Jun 2026 20:49:05 -0400 Subject: [PATCH 20/22] Added altKey for graphics refresh modifer rebindability --- resources/lang/en.json | 2 ++ src/client/InputHandler.ts | 6 ++---- src/client/UserSettingModal.ts | 29 ++++++++++++++++++++++++++++- src/core/game/UserSettings.ts | 1 + 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/resources/lang/en.json b/resources/lang/en.json index f4b489432d..fc4103b76a 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -1287,6 +1287,8 @@ "alert_frame_desc": "Toggle the alert frame. When enabled, the frame will be displayed when you are betrayed or attacked over land.", "alert_frame_label": "Alert Frame", "ally_keybinds": "Ally Keybinds", + "graphics_refresh_modifier": "Graphics refresh modifier", + "graphics_refresh_modifier_desc": "Hold this key and R to refresh graphics", "anonymous_names_desc": "Hide real player names with random ones on your screen.", "anonymous_names_label": "Hidden Names", "attack_keybinds": "Attack Keybinds", diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts index 570a041054..45836698f0 100644 --- a/src/client/InputHandler.ts +++ b/src/client/InputHandler.ts @@ -314,8 +314,7 @@ export class InputHandler { () => { this.eventBus.emit(new RefreshGraphicsEvent()); }, - (e: KeyboardEvent) => - this.activeKeys.has("AltLeft") || this.activeKeys.has("AltRight"), + (e: KeyboardEvent) => this.activeKeys.has(this.keybinds.altKey), ); let buildKeybinds: string[] = [ @@ -578,8 +577,7 @@ export class InputHandler { this.keybinds.shiftKey, this.keybinds.emojiMenuModifier, this.keybinds.buildMenuModifier, - "AltLeft", - "AltRight", + this.keybinds.altKey, ].includes(e.code) ) { this.activeKeys.add(e.code); diff --git a/src/client/UserSettingModal.ts b/src/client/UserSettingModal.ts index 13f863bf12..b134788c1b 100644 --- a/src/client/UserSettingModal.ts +++ b/src/client/UserSettingModal.ts @@ -96,7 +96,22 @@ export class UserSettingModal extends BaseModal { .filter(([k]) => k !== action) .map(([, v]) => v); - if (values.includes(value) && value !== "Null") { + //This is so that there is not conflict when remapping altKey and emojiMenuModifier back to default + let isEmojiMenuModAndAltKeyConflict = false; + if ( + ((action === "emojiMenuModifier" && + activeKeybinds["altKey"] === "AltLeft") || + (action === "altKey" && + activeKeybinds["emojiMenuModifier"] === "AltLeft")) && + value === "AltLeft" + ) { + isEmojiMenuModAndAltKeyConflict = true; + } + if ( + values.includes(value) && + value !== "Null" && + !isEmojiMenuModAndAltKeyConflict + ) { const displayKey = formatKeyForDisplay(key || value); window.dispatchEvent( new CustomEvent("show-message", { @@ -402,6 +417,18 @@ export class UserSettingModal extends BaseModal { @change=${this.handleKeybindChange} > + +

diff --git a/src/core/game/UserSettings.ts b/src/core/game/UserSettings.ts index 7031ecff74..5422cbe26b 100644 --- a/src/core/game/UserSettings.ts +++ b/src/core/game/UserSettings.ts @@ -42,6 +42,7 @@ export function getDefaultKeybinds(isMac: boolean): Record { pauseGame: "KeyP", gameSpeedUp: "Period", gameSpeedDown: "Comma", + altKey: "AltLeft", }; } From 8913f16c394486c1e6f575b0ea57f080e6a809d3 Mon Sep 17 00:00:00 2001 From: TKTK123456 <103334266+TKTK123456@users.noreply.github.com> Date: Sat, 13 Jun 2026 20:56:54 -0400 Subject: [PATCH 21/22] Sorted en.json --- resources/lang/en.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/lang/en.json b/resources/lang/en.json index fc4103b76a..c6af9c4522 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -1287,8 +1287,6 @@ "alert_frame_desc": "Toggle the alert frame. When enabled, the frame will be displayed when you are betrayed or attacked over land.", "alert_frame_label": "Alert Frame", "ally_keybinds": "Ally Keybinds", - "graphics_refresh_modifier": "Graphics refresh modifier", - "graphics_refresh_modifier_desc": "Hold this key and R to refresh graphics", "anonymous_names_desc": "Hide real player names with random ones on your screen.", "anonymous_names_label": "Hidden Names", "attack_keybinds": "Attack Keybinds", @@ -1359,6 +1357,8 @@ "game_speed_up_desc": "Cycle to next game speed (0.5, 1, 2, max). Single player only.", "go_to_player_desc": "Toggle zooming in on the player in the beginning of a game.", "go_to_player_label": "Go to player on start", + "graphics_refresh_modifier": "Graphics refresh modifier", + "graphics_refresh_modifier_desc": "Hold this key and R to refresh graphics", "graphics_settings_desc": "Adjust how the map looks", "graphics_settings_label": "Graphics Settings", "ground_attack": "Ground Attack", From c063585d8fd462645d2c0ee4f3713b17742eb907 Mon Sep 17 00:00:00 2001 From: TKTK123456 <103334266+TKTK123456@users.noreply.github.com> Date: Sat, 13 Jun 2026 21:07:02 -0400 Subject: [PATCH 22/22] Removing debug console log --- src/client/InputHandler.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts index 45836698f0..d5cfa68a98 100644 --- a/src/client/InputHandler.ts +++ b/src/client/InputHandler.ts @@ -301,7 +301,6 @@ export class InputHandler { this.eventBus.emit(new SwapRocketDirectionEvent(nextDirection)); }); this.addKeybindAndEvent("Shift+KeyD", () => { - console.log("TogglePerformanceOverlayEvent"); this.eventBus.emit(new TogglePerformanceOverlayEvent()); }); this.addKeybindAndEvent(this.keybinds.toggleView, () => {