Merge pull request #172 from Rahul-Sahani04/develop

feat: Add option to toggle hardware acceleration for launcher. Issue #170
This commit is contained in:
Fazri Gading
2026-01-26 05:10:24 +08:00
committed by GitHub
8 changed files with 421 additions and 307 deletions

1
.gitignore vendored
View File

@@ -20,3 +20,4 @@ backend/patcher/
# macOS Specific # macOS Specific
.DS_Store .DS_Store
*.zst.DS_Store *.zst.DS_Store
bun.lock

View File

@@ -127,17 +127,20 @@
<label class="form-label" data-i18n="install.gameBranch">Game Version</label> <label class="form-label" data-i18n="install.gameBranch">Game Version</label>
<div class="radio-group"> <div class="radio-group">
<label class="radio-label"> <label class="radio-label">
<input type="radio" name="installBranch" value="release" class="custom-radio" checked> <input type="radio" name="installBranch" value="release" class="custom-radio"
checked>
<span class="radio-text"> <span class="radio-text">
<i class="fas fa-check-circle mr-2"></i> <i class="fas fa-check-circle mr-2"></i>
<span data-i18n="install.releaseVersion">Release (Stable)</span> <span data-i18n="install.releaseVersion">Release (Stable)</span>
</span> </span>
</label> </label>
<label class="radio-label"> <label class="radio-label">
<input type="radio" name="installBranch" value="pre-release" class="custom-radio"> <input type="radio" name="installBranch" value="pre-release"
class="custom-radio">
<span class="radio-text"> <span class="radio-text">
<i class="fas fa-flask mr-2"></i> <i class="fas fa-flask mr-2"></i>
<span data-i18n="install.preReleaseVersion">Pre-Release (Experimental)</span> <span data-i18n="install.preReleaseVersion">Pre-Release
(Experimental)</span>
</span> </span>
</label> </label>
</div> </div>
@@ -361,20 +364,27 @@
<div class="settings-option"> <div class="settings-option">
<div class="settings-input-group"> <div class="settings-input-group">
<label class="settings-input-label" data-i18n="settings.gameBranch">Game Branch</label> <label class="settings-input-label" data-i18n="settings.gameBranch">Game
Branch</label>
<div class="segmented-control"> <div class="segmented-control">
<input type="radio" id="branch-release" name="gameBranch" value="release" checked> <input type="radio" id="branch-release" name="gameBranch"
<label for="branch-release" data-i18n="settings.branchRelease">Release</label> value="release" checked>
<input type="radio" id="branch-pre-release" name="gameBranch" value="pre-release"> <label for="branch-release"
<label for="branch-pre-release" data-i18n="settings.branchPreRelease">Pre-Release</label> data-i18n="settings.branchRelease">Release</label>
<input type="radio" id="branch-pre-release" name="gameBranch"
value="pre-release">
<label for="branch-pre-release"
data-i18n="settings.branchPreRelease">Pre-Release</label>
</div> </div>
<p class="settings-hint"> <p class="settings-hint">
<i class="fas fa-info-circle"></i> <i class="fas fa-info-circle"></i>
<span data-i18n="settings.branchHint">Switch between stable release and experimental pre-release versions</span> <span data-i18n="settings.branchHint">Switch between stable release and
experimental pre-release versions</span>
</p> </p>
<p class="settings-hint" style="color: #f39c12;"> <p class="settings-hint" style="color: #f39c12;">
<i class="fas fa-exclamation-triangle"></i> <i class="fas fa-exclamation-triangle"></i>
<span data-i18n="settings.branchWarning">Changing branch will download and install a different game version</span> <span data-i18n="settings.branchWarning">Changing branch will download
and install a different game version</span>
</p> </p>
</div> </div>
</div> </div>
@@ -383,8 +393,7 @@
<label class="settings-input-label" data-i18n="settings.gpuPreference">GPU <label class="settings-input-label" data-i18n="settings.gpuPreference">GPU
Preference</label> Preference</label>
<div class="segmented-control"> <div class="segmented-control">
<input type="radio" id="gpu-auto" name="gpuPreference" value="auto" <input type="radio" id="gpu-auto" name="gpuPreference" value="auto" checked>
checked>
<label for="gpu-auto" data-i18n="settings.gpuAuto">Auto</label> <label for="gpu-auto" data-i18n="settings.gpuAuto">Auto</label>
<input type="radio" id="gpu-integrated" name="gpuPreference" <input type="radio" id="gpu-integrated" name="gpuPreference"
value="integrated"> value="integrated">
@@ -462,8 +471,8 @@
<div class="checkbox-content"> <div class="checkbox-content">
<div class="checkbox-title" data-i18n="settings.enableRPC">Enable <div class="checkbox-title" data-i18n="settings.enableRPC">Enable
Discord Rich Presence</div> Discord Rich Presence</div>
<div class="checkbox-description" <div class="checkbox-description" data-i18n="settings.discordDescription">
data-i18n="settings.discordDescription">Show your launcher activity Show your launcher activity
on Discord on Discord
</div> </div>
</div> </div>
@@ -482,13 +491,28 @@
<input type="checkbox" id="closeLauncherCheck" /> <input type="checkbox" id="closeLauncherCheck" />
<span class="checkmark"></span> <span class="checkmark"></span>
<div class="checkbox-content"> <div class="checkbox-content">
<div class="checkbox-title" data-i18n="settings.closeOnStart">Close Launcher on game start</div> <div class="checkbox-title" data-i18n="settings.closeOnStart">Close Launcher
<div class="checkbox-description" data-i18n="settings.closeOnStartDescription"> on game start</div>
<div class="checkbox-description"
data-i18n="settings.closeOnStartDescription">
Automatically close the launcher after Hytale has launched Automatically close the launcher after Hytale has launched
</div> </div>
</div> </div>
</label> </label>
</div> </div>
<div class="settings-option">
<label class="settings-checkbox">
<input type="checkbox" id="launcherHwAccelCheck" />
<span class="checkmark"></span>
<div class="checkbox-content">
<div class="checkbox-title" data-i18n="settings.hwAccel">Launcher Hardware
Acceleration</div>
<div class="checkbox-description" data-i18n="settings.hwAccelDescription">
Enable hardware acceleration for the launcher UI (Requires restart)
</div>
</div>
</label>
</div>
</div> </div>
@@ -541,8 +565,8 @@
<div class="settings-option"> <div class="settings-option">
<div class="settings-input-group"> <div class="settings-input-group">
<label class="settings-input-label" <label class="settings-input-label" data-i18n="settings.selectLanguage">Select
data-i18n="settings.selectLanguage">Select Language</label> Language</label>
<select id="languageSelect" class="settings-input"> <select id="languageSelect" class="settings-input">
<!-- Options populated by i18n.js --> <!-- Options populated by i18n.js -->
</select> </select>
@@ -602,7 +626,7 @@
</div> </div>
</div> </div>
<div id="progressOverlay" class="progress-overlay" style="display: none;"> <div id="progressOverlay" class="progress-overlay" style="display: none;">
<div class="progress-content"> <div class="progress-content">
<div class="progress-info"> <div class="progress-info">
<span id="progressText" data-i18n="progress.initializing">Initializing...</span> <span id="progressText" data-i18n="progress.initializing">Initializing...</span>

View File

@@ -6,6 +6,7 @@ let browseJavaBtn;
let settingsPlayerName; let settingsPlayerName;
let discordRPCCheck; let discordRPCCheck;
let closeLauncherCheck; let closeLauncherCheck;
let launcherHwAccelCheck;
let gpuPreferenceRadios; let gpuPreferenceRadios;
let gameBranchRadios; let gameBranchRadios;
@@ -165,6 +166,7 @@ function setupSettingsElements() {
settingsPlayerName = document.getElementById('settingsPlayerName'); settingsPlayerName = document.getElementById('settingsPlayerName');
discordRPCCheck = document.getElementById('discordRPCCheck'); discordRPCCheck = document.getElementById('discordRPCCheck');
closeLauncherCheck = document.getElementById('closeLauncherCheck'); closeLauncherCheck = document.getElementById('closeLauncherCheck');
launcherHwAccelCheck = document.getElementById('launcherHwAccelCheck');
gpuPreferenceRadios = document.querySelectorAll('input[name="gpuPreference"]'); gpuPreferenceRadios = document.querySelectorAll('input[name="gpuPreference"]');
gameBranchRadios = document.querySelectorAll('input[name="gameBranch"]'); gameBranchRadios = document.querySelectorAll('input[name="gameBranch"]');
@@ -206,6 +208,10 @@ function setupSettingsElements() {
closeLauncherCheck.addEventListener('change', saveCloseLauncher); closeLauncherCheck.addEventListener('change', saveCloseLauncher);
} }
if (launcherHwAccelCheck) {
launcherHwAccelCheck.addEventListener('change', saveLauncherHwAccel);
}
// UUID event listeners // UUID event listeners
if (copyUuidBtn) { if (copyUuidBtn) {
@@ -391,6 +397,35 @@ async function loadCloseLauncher() {
} }
} }
async function saveLauncherHwAccel() {
try {
if (window.electronAPI && window.electronAPI.saveLauncherHardwareAcceleration && launcherHwAccelCheck) {
const enabled = launcherHwAccelCheck.checked;
await window.electronAPI.saveLauncherHardwareAcceleration(enabled);
const msg = window.i18n ? window.i18n.t('notifications.hwAccelSaved') : 'Setting saved. Please restart the launcher to apply changes.';
showNotification(msg, 'success');
}
} catch (error) {
console.error('Error saving hardware acceleration setting:', error);
const msg = window.i18n ? window.i18n.t('notifications.hwAccelSaveFailed') : 'Failed to save setting';
showNotification(msg, 'error');
}
}
async function loadLauncherHwAccel() {
try {
if (window.electronAPI && window.electronAPI.loadLauncherHardwareAcceleration) {
const enabled = await window.electronAPI.loadLauncherHardwareAcceleration();
if (launcherHwAccelCheck) {
launcherHwAccelCheck.checked = enabled;
}
}
} catch (error) {
console.error('Error loading hardware acceleration setting:', error);
}
}
async function savePlayerName() { async function savePlayerName() {
try { try {
@@ -507,6 +542,7 @@ async function loadAllSettings() {
await loadCurrentUuid(); await loadCurrentUuid();
await loadDiscordRPC(); await loadDiscordRPC();
await loadCloseLauncher(); await loadCloseLauncher();
await loadLauncherHwAccel();
await loadGpuPreference(); await loadGpuPreference();
await loadVersionBranch(); await loadVersionBranch();
} }
@@ -767,7 +803,7 @@ async function setCustomUuid() {
} }
} }
async function performSetCustomUuid(uuid) { async function performSetCustomUuid(uuid) {
try { try {
if (window.electronAPI && window.electronAPI.setUuidForUser) { if (window.electronAPI && window.electronAPI.setUuidForUser) {
const username = getCurrentPlayerName(); const username = getCurrentPlayerName();
@@ -791,9 +827,9 @@ async function setCustomUuid() {
const msg = window.i18n ? window.i18n.t('notifications.uuidSetFailed').replace('{error}', error.message) : `Failed to set custom UUID: ${error.message}`; const msg = window.i18n ? window.i18n.t('notifications.uuidSetFailed').replace('{error}', error.message) : `Failed to set custom UUID: ${error.message}`;
showNotification(msg, 'error'); showNotification(msg, 'error');
} }
} }
window.copyUuid = async function(uuid) { window.copyUuid = async function (uuid) {
try { try {
if (navigator.clipboard) { if (navigator.clipboard) {
await navigator.clipboard.writeText(uuid); await navigator.clipboard.writeText(uuid);
@@ -807,7 +843,7 @@ window.copyUuid = async function(uuid) {
} }
}; };
window.deleteUuid = async function(username) { window.deleteUuid = async function (username) {
try { try {
const message = window.i18n ? window.i18n.t('confirm.deleteUuidMessage').replace('{username}', username) : `Are you sure you want to delete the UUID for "${username}"? This action cannot be undone.`; const message = window.i18n ? window.i18n.t('confirm.deleteUuidMessage').replace('{username}', username) : `Are you sure you want to delete the UUID for "${username}"? This action cannot be undone.`;
const title = window.i18n ? window.i18n.t('confirm.deleteUuidTitle') : 'Delete UUID'; const title = window.i18n ? window.i18n.t('confirm.deleteUuidTitle') : 'Delete UUID';

View File

@@ -131,6 +131,8 @@
"closeLauncher": "Launcher Behavior", "closeLauncher": "Launcher Behavior",
"closeOnStart": "Close Launcher on game start", "closeOnStart": "Close Launcher on game start",
"closeOnStartDescription": "Automatically close the launcher after Hytale has launched", "closeOnStartDescription": "Automatically close the launcher after Hytale has launched",
"hwAccel": "Hardware Acceleration",
"hwAccelDescription": "Enable hardware acceleration for the launcher",
"gameBranch": "Game Branch", "gameBranch": "Game Branch",
"branchRelease": "Release", "branchRelease": "Release",
"branchPreRelease": "Pre-Release", "branchPreRelease": "Pre-Release",
@@ -207,7 +209,9 @@
"modsDownloadFailed": "Failed to download mod: {error}", "modsDownloadFailed": "Failed to download mod: {error}",
"modsToggleFailed": "Failed to toggle mod: {error}", "modsToggleFailed": "Failed to toggle mod: {error}",
"modsDeleteFailed": "Failed to delete mod: {error}", "modsDeleteFailed": "Failed to delete mod: {error}",
"modsModNotFound": "Mod information not found" "modsModNotFound": "Mod information not found",
"hwAccelSaved": "Hardware acceleration setting saved",
"hwAccelSaveFailed": "Failed to save hardware acceleration setting"
}, },
"confirm": { "confirm": {
"defaultTitle": "Confirm action", "defaultTitle": "Confirm action",

View File

@@ -166,6 +166,15 @@ function loadCloseLauncherOnStart() {
return config.closeLauncherOnStart !== undefined ? config.closeLauncherOnStart : false; return config.closeLauncherOnStart !== undefined ? config.closeLauncherOnStart : false;
} }
function saveLauncherHardwareAcceleration(enabled) {
saveConfig({ launcherHardwareAcceleration: !!enabled });
}
function loadLauncherHardwareAcceleration() {
const config = loadConfig();
return config.launcherHardwareAcceleration !== undefined ? config.launcherHardwareAcceleration : true;
}
function saveModsToConfig(mods) { function saveModsToConfig(mods) {
try { try {
const config = loadConfig(); const config = loadConfig();
@@ -369,6 +378,11 @@ module.exports = {
// Close Launcher export // Close Launcher export
saveCloseLauncherOnStart, saveCloseLauncherOnStart,
loadCloseLauncherOnStart, loadCloseLauncherOnStart,
// Hardware Acceleration functions
saveLauncherHardwareAcceleration,
loadLauncherHardwareAcceleration,
// Version Management exports // Version Management exports
saveVersionClient, saveVersionClient,
loadVersionClient, loadVersionClient,

View File

@@ -19,6 +19,12 @@ const {
loadLanguage, loadLanguage,
saveCloseLauncherOnStart, saveCloseLauncherOnStart,
loadCloseLauncherOnStart, loadCloseLauncherOnStart,
// Hardware Acceleration
saveLauncherHardwareAcceleration,
loadLauncherHardwareAcceleration,
saveModsToConfig, saveModsToConfig,
loadModsFromConfig, loadModsFromConfig,
getUuidForUser, getUuidForUser,
@@ -134,6 +140,10 @@ module.exports = {
saveCloseLauncherOnStart, saveCloseLauncherOnStart,
loadCloseLauncherOnStart, loadCloseLauncherOnStart,
// Hardware Acceleration functions
saveLauncherHardwareAcceleration,
loadLauncherHardwareAcceleration,
// GPU Preference functions // GPU Preference functions
saveGpuPreference, saveGpuPreference,
loadGpuPreference, loadGpuPreference,

22
main.js
View File

@@ -3,9 +3,20 @@ require('dotenv').config({ path: path.join(__dirname, '.env') });
const { app, BrowserWindow, ipcMain, dialog, shell } = require('electron'); const { app, BrowserWindow, ipcMain, dialog, shell } = require('electron');
const { autoUpdater } = require('electron-updater'); const { autoUpdater } = require('electron-updater');
const fs = require('fs'); const fs = require('fs');
const { launchGame, launchGameWithVersionCheck, installGame, saveUsername, loadUsername, saveChatUsername, loadChatUsername, saveChatColor, loadChatColor, saveJavaPath, loadJavaPath, saveInstallPath, loadInstallPath, saveDiscordRPC, loadDiscordRPC, saveLanguage, loadLanguage, saveCloseLauncherOnStart, loadCloseLauncherOnStart, isGameInstalled, uninstallGame, repairGame, getHytaleNews, handleFirstLaunchCheck, proposeGameUpdate, markAsLaunched } = require('./backend/launcher'); const { launchGame, launchGameWithVersionCheck, installGame, saveUsername, loadUsername, saveChatUsername, loadChatUsername, saveChatColor, loadChatColor, saveJavaPath, loadJavaPath, saveInstallPath, loadInstallPath, saveDiscordRPC, loadDiscordRPC, saveLanguage, loadLanguage, saveCloseLauncherOnStart, loadCloseLauncherOnStart, saveLauncherHardwareAcceleration, loadLauncherHardwareAcceleration, isGameInstalled, uninstallGame, repairGame, getHytaleNews, handleFirstLaunchCheck, proposeGameUpdate, markAsLaunched } = require('./backend/launcher');
const { retryPWRDownload } = require('./backend/managers/gameManager'); const { retryPWRDownload } = require('./backend/managers/gameManager');
// Handle Hardware Acceleration
try {
const hwEnabled = loadLauncherHardwareAcceleration();
if (!hwEnabled) {
console.log('Hardware acceleration disabled by user setting');
app.disableHardwareAcceleration();
}
} catch (error) {
console.error('Failed to load hardware acceleration setting:', error);
}
const logger = require('./backend/logger'); const logger = require('./backend/logger');
const profileManager = require('./backend/managers/profileManager'); const profileManager = require('./backend/managers/profileManager');
@@ -625,6 +636,15 @@ ipcMain.handle('load-close-launcher', () => {
return loadCloseLauncherOnStart(); return loadCloseLauncherOnStart();
}); });
ipcMain.handle('save-launcher-hw-accel', (event, enabled) => {
saveLauncherHardwareAcceleration(enabled);
return { success: true };
});
ipcMain.handle('load-launcher-hw-accel', () => {
return loadLauncherHardwareAcceleration();
});
ipcMain.handle('select-install-path', async () => { ipcMain.handle('select-install-path', async () => {
const result = await dialog.showOpenDialog(mainWindow, { const result = await dialog.showOpenDialog(mainWindow, {

View File

@@ -23,6 +23,11 @@ contextBridge.exposeInMainWorld('electronAPI', {
loadLanguage: () => ipcRenderer.invoke('load-language'), loadLanguage: () => ipcRenderer.invoke('load-language'),
saveCloseLauncher: (enabled) => ipcRenderer.invoke('save-close-launcher', enabled), saveCloseLauncher: (enabled) => ipcRenderer.invoke('save-close-launcher', enabled),
loadCloseLauncher: () => ipcRenderer.invoke('load-close-launcher'), loadCloseLauncher: () => ipcRenderer.invoke('load-close-launcher'),
// Harwadre Acceleration
saveLauncherHardwareAcceleration: (enabled) => ipcRenderer.invoke('save-launcher-hw-accel', enabled),
loadLauncherHardwareAcceleration: () => ipcRenderer.invoke('load-launcher-hw-accel'),
selectInstallPath: () => ipcRenderer.invoke('select-install-path'), selectInstallPath: () => ipcRenderer.invoke('select-install-path'),
browseJavaPath: () => ipcRenderer.invoke('browse-java-path'), browseJavaPath: () => ipcRenderer.invoke('browse-java-path'),
isGameInstalled: () => ipcRenderer.invoke('is-game-installed'), isGameInstalled: () => ipcRenderer.invoke('is-game-installed'),