refactor: remove matchmaker accept hotkey and always auto-join

This commit is contained in:
2026-04-15 08:44:20 -07:00
parent db89352ed8
commit ae359497be
4 changed files with 26 additions and 128 deletions
-4
View File
@@ -54,7 +54,6 @@ export interface AppConfig {
maxPlayers: number;
minRemainingTime: number;
openServerBrowser: boolean;
autoJoin: boolean;
sortByPlayers: boolean;
};
keybinds: {
@@ -64,7 +63,6 @@ export interface AppConfig {
joinFromClipboard: Keybind;
devTools: Keybind;
matchmaker: Keybind;
matchmakerAccept: Keybind;
matchmakerCancel: Keybind;
fullscreenToggle: Keybind;
};
@@ -120,7 +118,6 @@ export const DEFAULT_KEYBINDS: AppConfig['keybinds'] = {
joinFromClipboard: { key: 'j', ctrl: true, shift: false, alt: false },
devTools: { key: 'F12', ctrl: false, shift: false, alt: false },
matchmaker: { key: 'F6', ctrl: false, shift: false, alt: false },
matchmakerAccept: { key: 'Enter', ctrl: false, shift: false, alt: false },
matchmakerCancel: { key: 'Escape', ctrl: false, shift: false, alt: false },
fullscreenToggle: { key: 'F11', ctrl: false, shift: false, alt: false },
};
@@ -169,7 +166,6 @@ export const config = new Store<AppConfig>({
maxPlayers: 6,
minRemainingTime: 120,
openServerBrowser: true,
autoJoin: false,
sortByPlayers: false,
},
keybinds: DEFAULT_KEYBINDS,
-2
View File
@@ -389,7 +389,6 @@ async function launchApp(): Promise<void> {
if (mm.enabled) {
win.webContents.send('matchmaker-find', {
...mm,
acceptKey: binds.matchmakerAccept,
cancelKey: binds.matchmakerCancel,
});
} else {
@@ -411,7 +410,6 @@ async function launchApp(): Promise<void> {
if (mm.enabled) {
win.webContents.send('matchmaker-find', {
...mm,
acceptKey: binds.matchmakerAccept,
cancelKey: binds.matchmakerCancel,
});
} else {
+1 -13
View File
@@ -853,7 +853,7 @@ function buildAppearanceSection(body: HTMLElement, uiConfRaw: any): void {
}
function buildMatchmakerSection(body: HTMLElement, mmConf: any, bag: SettingsBag): void {
const mm = mmConf || { enabled: true, regions: [], gamemodes: [], minPlayers: 1, maxPlayers: 6, minRemainingTime: 120, openServerBrowser: true, autoJoin: false };
const mm = mmConf || { enabled: true, regions: [], gamemodes: [], minPlayers: 1, maxPlayers: 6, minRemainingTime: 120, openServerBrowser: true, sortByPlayers: false };
function saveMM(): void {
ipcRenderer.invoke('set-config', 'matchmaker', mm);
@@ -873,13 +873,6 @@ function buildMatchmakerSection(body: HTMLElement, mmConf: any, bag: SettingsBag
onChange: (v) => { mm.openServerBrowser = v; saveMM(); },
}));
body.appendChild(createToggleRow({
label: 'Auto-Join',
desc: 'Automatically join the best match without showing the popup',
checked: mm.autoJoin ?? false, instant: true,
onChange: (v) => { mm.autoJoin = v; saveMM(); },
}));
body.appendChild(createToggleRow({
label: 'Prioritize Player Count',
desc: 'Sort results by most players first, then by ping (default is ping first)',
@@ -891,10 +884,6 @@ function buildMatchmakerSection(body: HTMLElement, mmConf: any, bag: SettingsBag
bag.binds.matchmaker = b;
bag.saveBinds();
}, undefined, true));
body.appendChild(createKeybindRow('Matchmaker Accept', 'Key to accept a found game', bag.binds.matchmakerAccept, (b) => {
bag.binds.matchmakerAccept = b;
bag.saveBinds();
}, undefined, true));
body.appendChild(createKeybindRow('Matchmaker Cancel', 'Key to dismiss the matchmaker popup', bag.binds.matchmakerCancel, (b) => {
bag.binds.matchmakerCancel = b;
bag.saveBinds();
@@ -1363,7 +1352,6 @@ function renderSettings(searchQuery?: string): void {
const translatorConf = allConf.translator;
const defaultBinds = {
matchmaker: { key: 'F6', ctrl: false, shift: false, alt: false },
matchmakerAccept: { key: 'Enter', ctrl: false, shift: false, alt: false },
matchmakerCancel: { key: 'Escape', ctrl: false, shift: false, alt: false },
fullscreenToggle: { key: 'F11', ctrl: false, shift: false, alt: false },
};
+25 -109
View File
@@ -65,19 +65,10 @@ export interface MatchmakerConfig {
maxPlayers: number;
minRemainingTime: number;
openServerBrowser: boolean;
autoJoin: boolean;
sortByPlayers: boolean;
acceptKey: Keybind;
cancelKey: Keybind;
}
function secondsToTimestring(num: number): string {
const minutes = Math.floor(num / 60);
const seconds = num % 60;
if (minutes < 1) return `${num}s`;
return `${minutes}m ${seconds}s`;
}
function matchesKey(bind: Keybind, event: KeyboardEvent): boolean {
if ((document.activeElement as HTMLElement)?.tagName === 'INPUT') return false;
return event.key === bind.key
@@ -103,21 +94,17 @@ popupElement.appendChild(popupDescription);
const popupOptions = document.createElement('div');
popupOptions.id = 'matchmakerPopupOptions';
const popupConfirmBtn = document.createElement('div');
popupConfirmBtn.id = 'matchmakerConfirmButton';
popupConfirmBtn.className = 'matchmakerPopupButton bigShadowT';
popupConfirmBtn.textContent = 'Join';
popupConfirmBtn.setAttribute('onmouseenter', 'playTick()');
popupConfirmBtn.addEventListener('click', () => decideMatchmakerDecision(true));
const popupCancelBtn = document.createElement('div');
popupCancelBtn.id = 'matchmakerCancelButton';
popupCancelBtn.className = 'matchmakerPopupButton bigShadowT';
popupCancelBtn.textContent = 'Cancel';
popupCancelBtn.setAttribute('onmouseenter', 'playTick()');
popupCancelBtn.addEventListener('click', () => decideMatchmakerDecision(false));
popupCancelBtn.addEventListener('click', () => {
const w = window as any;
if (typeof w.playSelect === 'function') w.playSelect();
dismissPopup();
});
popupOptions.appendChild(popupConfirmBtn);
popupOptions.appendChild(popupCancelBtn);
popupElement.appendChild(popupOptions);
@@ -147,10 +134,8 @@ searchContainer.appendChild(searchCancelBtn);
popupElement.appendChild(searchContainer);
// ── State ──
let popupGameID = '';
let popupCandidates: MatchmakerGame[] = [];
let openServerBrowser = true;
let confirmKey: Keybind = { key: 'Enter', ctrl: false, shift: false, alt: false };
let cancelKey: Keybind = { key: 'Escape', ctrl: false, shift: false, alt: false };
let searchAborted = false;
@@ -192,25 +177,11 @@ async function verifyAndJoin(gameID: string): Promise<void> {
function dismissPopup(): void {
document.removeEventListener('keydown', handleSearchBind, true);
document.removeEventListener('keydown', handleMatchmakerBind, true);
if (popupElement.parentNode) popupElement.remove();
popupElement.classList.remove('searching');
}
function decideMatchmakerDecision(accept: boolean): void {
const w = window as any;
if (typeof w.playSelect === 'function') w.playSelect();
if (accept && popupGameID !== 'none') {
verifyAndJoin(popupGameID);
} else {
dismissPopup();
if (popupGameID === 'none' && openServerBrowser && typeof w.openServerWindow === 'function') {
w.openServerWindow(0);
}
}
}
function handleSearchBind(event: KeyboardEvent): void {
if (document.pointerLockElement) return;
if (matchesKey(cancelKey, event)) {
@@ -220,42 +191,6 @@ function handleSearchBind(event: KeyboardEvent): void {
}
}
function handleMatchmakerBind(event: KeyboardEvent): void {
if (document.pointerLockElement) return;
const isAccept = matchesKey(confirmKey, event);
const isCancel = matchesKey(cancelKey, event);
if (isAccept || isCancel) {
document.removeEventListener('keydown', handleMatchmakerBind, true);
decideMatchmakerDecision(isAccept);
}
}
function showResultPopup(game: MatchmakerGame): void {
popupElement.classList.remove('searching');
const mapIdx = MAP_ICON_INDICES.indexOf(game.map);
popupElement.style.backgroundImage = `url(https://assets.krunker.io/img/maps/map_${mapIdx >= 0 ? mapIdx : 0}.png)`;
popupGameID = game.gameID;
if (game.gameID === 'none') {
popupTitle.innerText = 'No Games Found...';
popupDescription.innerHTML = 'Check the server browser to see other lobbies.';
popupConfirmBtn.style.display = 'none';
} else {
popupTitle.innerText = 'Game Found!';
const regionName = MATCHMAKER_REGION_NAMES[game.region] ?? 'Unknown Region';
popupDescription.innerHTML = `${escapeHtml(game.gamemode)} on ${escapeHtml(game.map)} (${escapeHtml(regionName)})<br/>${game.playerCount}/${game.playerLimit} Players, ${secondsToTimestring(game.remainingTime)} Left`;
popupConfirmBtn.style.display = 'block';
}
// Re-trigger slide animation
popupElement.style.animation = 'none';
void popupElement.offsetWidth;
popupElement.style.animation = '';
document.removeEventListener('keydown', handleSearchBind, true);
document.addEventListener('keydown', handleMatchmakerBind, true);
}
function showSearchPopup(): void {
searchAborted = false;
popupElement.classList.add('searching');
@@ -264,7 +199,7 @@ function showSearchPopup(): void {
searchFeed.innerHTML = '';
searchCounter.textContent = '';
document.removeEventListener('keydown', handleMatchmakerBind, true);
document.addEventListener('keydown', handleSearchBind, true);
const uiBase = document.getElementById('uiBase');
@@ -374,7 +309,6 @@ function sortGames(games: MatchmakerGame[], pings: Record<string, number>, sortB
export async function fetchGame(mmConfig: MatchmakerConfig, _con?: SavedConsole): Promise<void> {
openServerBrowser = mmConfig.openServerBrowser;
confirmKey = mmConfig.acceptKey;
cancelKey = mmConfig.cancelKey;
// Dismiss existing popup if active (also aborts in-flight search)
@@ -434,45 +368,27 @@ export async function fetchGame(mmConfig: MatchmakerConfig, _con?: SavedConsole)
const best = pool[Math.floor(Math.random() * pool.length)];
_con?.log('[KCC-MM] Best match:', best.gameID, best.region, best.map, `(${pings[best.region] ?? '?'}ms, pool: ${pool.length})`);
if (mmConfig.autoJoin) {
// Brief "Lobby Found!" flash before joining
const regionName = MATCHMAKER_REGION_NAMES[best.region] ?? best.region;
searchStatus.textContent = 'Lobby Found!';
searchFeed.innerHTML = '';
const found = document.createElement('div');
found.className = 'mm-feed-entry mm-pass';
found.style.cssText = 'font-size:1.1em;justify-content:center;';
found.innerHTML =
`<span class="mm-feed-region">${escapeHtml(best.region)}</span>` +
`<span class="mm-feed-map">${escapeHtml(best.map)}</span>` +
`<span class="mm-feed-players">${best.playerCount}/${best.playerLimit}</span>`;
searchFeed.appendChild(found);
searchCounter.textContent = `${best.gamemode} \u00B7 ${regionName} \u00B7 ${pings[best.region] ?? '?'}ms`;
await new Promise(r => setTimeout(r, 1200));
await verifyAndJoin(best.gameID);
return;
}
showResultPopup(best);
// Brief "Lobby Found!" flash before auto-joining
const regionName = MATCHMAKER_REGION_NAMES[best.region] ?? best.region;
searchStatus.textContent = 'Lobby Found!';
searchFeed.innerHTML = '';
const found = document.createElement('div');
found.className = 'mm-feed-entry mm-pass';
found.style.cssText = 'font-size:1.1em;justify-content:center;';
found.innerHTML =
`<span class="mm-feed-region">${escapeHtml(best.region)}</span>` +
`<span class="mm-feed-map">${escapeHtml(best.map)}</span>` +
`<span class="mm-feed-players">${best.playerCount}/${best.playerLimit}</span>`;
searchFeed.appendChild(found);
searchCounter.textContent = `${best.gamemode} \u00B7 ${regionName} \u00B7 ${pings[best.region] ?? '?'}ms`;
await new Promise(r => setTimeout(r, 1200));
await verifyAndJoin(best.gameID);
} else {
_con?.log('[KCC-MM] No matching games found');
if (mmConfig.autoJoin) {
dismissPopup();
if (openServerBrowser && typeof (window as any).openServerWindow === 'function') {
(window as any).openServerWindow(0);
}
return;
dismissPopup();
if (openServerBrowser && typeof (window as any).openServerWindow === 'function') {
(window as any).openServerWindow(0);
}
showResultPopup({
gameID: 'none',
region: 'none',
playerCount: 0,
playerLimit: 0,
map: MAP_ICON_INDICES[0],
gamemode: MATCHMAKER_GAMEMODES[0],
remainingTime: 0,
});
}
}