diff --git a/GUI/index.html b/GUI/index.html index 507ca85..1280900 100644 --- a/GUI/index.html +++ b/GUI/index.html @@ -849,6 +849,7 @@ + diff --git a/GUI/js/settings.js b/GUI/js/settings.js index 0d268b8..6dd54b5 100644 --- a/GUI/js/settings.js +++ b/GUI/js/settings.js @@ -152,9 +152,9 @@ function showCustomConfirm(message, title, onConfirm, onCancel = null, confirmTe } -export function initSettings() { +export async function initSettings() { setupSettingsElements(); - loadAllSettings(); + await loadAllSettings(); } function setupSettingsElements() { @@ -953,14 +953,7 @@ async function switchBranch(newBranch) { playButton.classList.add('disabled'); } - // Save new branch - await window.electronAPI.saveVersionBranch(newBranch); - - const switchedMsg = window.i18n ? - window.i18n.t('settings.branchSwitched').replace('{branch}', newBranch) : - `Switched to ${newBranch} successfully!`; - - showNotification(switchedMsg, 'success'); + // DON'T save branch yet - wait for installation confirmation // Suggest reinstalling setTimeout(() => { @@ -986,12 +979,24 @@ async function switchBranch(newBranch) { const result = await window.electronAPI.installGame(playerName || 'Player', '', '', newBranch); if (result.success) { + // Save branch ONLY after successful installation + await window.electronAPI.saveVersionBranch(newBranch); + + const switchedMsg = window.i18n ? + window.i18n.t('settings.branchSwitched').replace('{branch}', newBranch) : + `Switched to ${newBranch} successfully!`; + const successMsg = window.i18n ? window.i18n.t('progress.installationComplete') : 'Installation completed successfully!'; + showNotification(switchedMsg, 'success'); showNotification(successMsg, 'success'); + // Refresh radio buttons to reflect the new branch + await loadVersionBranch(); + console.log('[Settings] Radio buttons updated after branch switch'); + setTimeout(() => { if (window.LauncherUI) { window.LauncherUI.hideProgress(); @@ -1019,6 +1024,14 @@ async function switchBranch(newBranch) { window.LauncherUI.hideProgress(); } + // Revert radio selection to old branch + loadVersionBranch().then(oldBranch => { + const radioToCheck = document.querySelector(`input[name="gameBranch"][value="${oldBranch}"]`); + if (radioToCheck) { + radioToCheck.checked = true; + } + }); + // Unlock play button const playButton = document.getElementById('playButton'); if (playButton) { @@ -1058,15 +1071,21 @@ async function loadVersionBranch() { try { if (window.electronAPI && window.electronAPI.loadVersionBranch) { const branch = await window.electronAPI.loadVersionBranch(); + console.log('[Settings] Loaded version_branch from config:', branch); + + // Use default if branch is null/undefined + const selectedBranch = branch || 'release'; + console.log('[Settings] Selected branch:', selectedBranch); // Update radio buttons if (gameBranchRadios) { gameBranchRadios.forEach(radio => { - radio.checked = radio.value === branch; + radio.checked = radio.value === selectedBranch; + console.log(`[Settings] Radio ${radio.value}: ${radio.checked ? 'checked' : 'unchecked'}`); }); } - return branch; + return selectedBranch; } return 'release'; // Default } catch (error) { diff --git a/backend/logger.js b/backend/logger.js index 2064969..95852b8 100644 --- a/backend/logger.js +++ b/backend/logger.js @@ -85,7 +85,7 @@ class Logger { fs.appendFileSync(this.logFile, message, 'utf8'); } catch (error) { - this.originalConsole.error('Impossible d\'écrire dans le fichier de log:', error.message); + this.originalConsole.error('Unable to write to log file:', error.message); } } diff --git a/backend/managers/gameManager.js b/backend/managers/gameManager.js index 1785461..109651b 100644 --- a/backend/managers/gameManager.js +++ b/backend/managers/gameManager.js @@ -23,13 +23,32 @@ async function downloadPWR(branch = 'release', fileName = '4.pwr', progressCallb const dest = path.join(cacheDir, `${branch}_${fileName}`); + // Check if file exists and validate it if (fs.existsSync(dest)) { console.log('PWR file found in cache:', dest); - return dest; + + // Validate file size (PWR files should be > 1MB) + const stats = fs.statSync(dest); + if (stats.size < 1024 * 1024) { + console.log('Cached PWR file seems corrupted (too small), re-downloading...'); + fs.unlinkSync(dest); + } else { + return dest; + } } console.log('Fetching PWR patch file:', url); await downloadFile(url, dest, progressCallback); + + // Validate downloaded file + const stats = fs.statSync(dest); + console.log(`PWR file downloaded, size: ${(stats.size / 1024 / 1024).toFixed(2)} MB`); + + if (stats.size < 1024 * 1024) { + fs.unlinkSync(dest); + throw new Error('Downloaded PWR file is corrupted (file too small)'); + } + console.log('PWR saved to:', dest); return dest; @@ -85,7 +104,13 @@ async function applyPWR(pwrFile, progressCallback, gameDir = GAME_DIR, toolsDir if (error) { console.error('Butler stderr:', stderr); console.error('Butler stdout:', stdout); - reject(new Error(`Patch installation failed: ${error.message}${stderr ? '\n' + stderr : ''}`)); + + // Check for EOF error (corrupted PWR file) + if (stderr && stderr.includes('unexpected EOF')) { + reject(new Error(`Corrupted PWR file detected. Please delete the cache and reinstall: ${pwrFile}`)); + } else { + reject(new Error(`Patch installation failed: ${error.message}${stderr ? '\n' + stderr : ''}`)); + } } else { resolve(); } @@ -114,7 +139,9 @@ async function updateGameFiles(newVersion, progressCallback, gameDir = GAME_DIR, // Vérifier si on a version_client et version_branch dans config.json const config = loadConfig(); const hasVersionConfig = !!(config.version_client && config.version_branch); + const oldBranch = config.version_branch || 'release'; // L'ancienne branche pour le backup console.log(`[UpdateGameFiles] hasVersionConfig: ${hasVersionConfig}`); + console.log(`[UpdateGameFiles] Switching from ${oldBranch} to ${branch}`); try { if (progressCallback) { @@ -145,11 +172,15 @@ async function updateGameFiles(newVersion, progressCallback, gameDir = GAME_DIR, progressCallback('Backing up user data...', 70, null, null, null); } - // Backup UserData using new system + // Backup UserData from OLD branch (before switching) try { - backupPath = await userDataBackup.backupUserData(installPath, branch, hasVersionConfig); + console.log(`[UpdateGameFiles] Attempting to backup UserData from old branch: ${oldBranch}`); + backupPath = await userDataBackup.backupUserData(installPath, oldBranch, hasVersionConfig); + if (backupPath) { + console.log(`[UpdateGameFiles] ✓ UserData backed up from ${oldBranch}: ${backupPath}`); + } } catch (backupError) { - console.warn('UserData backup failed:', backupError.message); + console.warn('[UpdateGameFiles] ✗ UserData backup failed:', backupError.message); } if (progressCallback) { @@ -169,6 +200,13 @@ async function updateGameFiles(newVersion, progressCallback, gameDir = GAME_DIR, const logoResult = await downloadAndReplaceLogo(gameDir, progressCallback); console.log('Logo@2x.png update result after update:', logoResult); + // Ensure UserData directory exists + const userDataDir = path.join(gameDir, 'Client', 'UserData'); + if (!fs.existsSync(userDataDir)) { + console.log(`[UpdateGameFiles] Creating UserData directory at: ${userDataDir}`); + fs.mkdirSync(userDataDir, { recursive: true }); + } + if (progressCallback) { progressCallback('Restoring user data...', 90, null, null, null); } @@ -176,11 +214,16 @@ async function updateGameFiles(newVersion, progressCallback, gameDir = GAME_DIR, // Restore UserData using new system if (backupPath) { try { + console.log(`[UpdateGameFiles] Restoring UserData from ${oldBranch} to ${branch}`); + console.log(`[UpdateGameFiles] Source backup: ${backupPath}`); await userDataBackup.restoreUserData(backupPath, installPath, branch); await userDataBackup.cleanupBackup(backupPath); + console.log(`[UpdateGameFiles] ✓ UserData migrated successfully from ${oldBranch} to ${branch}`); } catch (restoreError) { - console.warn('UserData restore failed:', restoreError.message); + console.warn('[UpdateGameFiles] ✗ UserData restore failed:', restoreError.message); } + } else { + console.log('[UpdateGameFiles] No backup to restore, empty UserData folder created'); } console.log(`Game files updated successfully to version: ${newVersion}`); @@ -238,7 +281,7 @@ async function installGame(playerName = 'Player', progressCallback, javaPathOver // Vérifier si on a version_client et version_branch dans config.json const config = loadConfig(); const hasVersionConfig = !!(config.version_client && config.version_branch); - console.log(`[InstallGame] Configuration détectée - version_client: ${config.version_client}, version_branch: ${config.version_branch}`); + console.log(`[InstallGame] Configuration detected - version_client: ${config.version_client}, version_branch: ${config.version_branch}`); console.log(`[InstallGame] hasVersionConfig: ${hasVersionConfig}`); // Backup UserData AVANT l'installation si nécessaire @@ -248,13 +291,13 @@ async function installGame(playerName = 'Player', progressCallback, javaPathOver } try { - console.log(`[InstallGame] Tentative de backup UserData (hasVersionConfig: ${hasVersionConfig})...`); + console.log(`[InstallGame] Attempting UserData backup (hasVersionConfig: ${hasVersionConfig})...`); backupPath = await userDataBackup.backupUserData(customAppDir, branch, hasVersionConfig); if (backupPath) { - console.log(`[InstallGame] ✓ UserData sauvegardé dans: ${backupPath}`); + console.log(`[InstallGame] ✓ UserData backed up to: ${backupPath}`); } } catch (backupError) { - console.warn('[InstallGame] ✗ Backup UserData échoué:', backupError.message); + console.warn('[InstallGame] ✗ UserData backup failed:', backupError.message); } [customAppDir, customCacheDir, customToolsDir].forEach(dir => { @@ -332,7 +375,7 @@ async function installGame(playerName = 'Player', progressCallback, javaPathOver // Ensure UserData directory exists if (!fs.existsSync(userDataDir)) { - console.log(`[InstallGame] Création du dossier UserData dans: ${userDataDir}`); + console.log(`[InstallGame] Creating UserData directory at: ${userDataDir}`); fs.mkdirSync(userDataDir, { recursive: true }); } @@ -343,15 +386,15 @@ async function installGame(playerName = 'Player', progressCallback, javaPathOver } try { - console.log(`[InstallGame] Restauration du UserData depuis: ${backupPath}`); + console.log(`[InstallGame] Restoring UserData from: ${backupPath}`); await userDataBackup.restoreUserData(backupPath, customAppDir, branch); await userDataBackup.cleanupBackup(backupPath); - console.log('[InstallGame] ✓ UserData restauré avec succès'); + console.log('[InstallGame] ✓ UserData restored successfully'); } catch (restoreError) { - console.warn('[InstallGame] ✗ Erreur lors de la restauration UserData:', restoreError.message); + console.warn('[InstallGame] ✗ UserData restore failed:', restoreError.message); } } else { - console.log('[InstallGame] Aucun backup à restaurer, dossier UserData vide créé'); + console.log('[InstallGame] No backup to restore, empty UserData folder created'); } if (progressCallback) { diff --git a/backend/utils/userDataBackup.js b/backend/utils/userDataBackup.js index df1b69b..0da8614 100644 --- a/backend/utils/userDataBackup.js +++ b/backend/utils/userDataBackup.js @@ -19,36 +19,36 @@ class UserDataBackup { // c'est une ancienne installation, on cherche dans installPath/HytaleF2P/release if (!hasVersionConfig) { const oldPath = path.join(installPath, 'HytaleF2P', 'release', 'package', 'game', 'latest', 'Client', 'UserData'); - console.log(`[UserDataBackup] Pas de version_client/version_branch détecté, recherche ancienne installation dans: ${oldPath}`); + console.log(`[UserDataBackup] No version_client/version_branch detected, searching old installation in: ${oldPath}`); if (fs.existsSync(oldPath)) { userDataPath = oldPath; - console.log(`[UserDataBackup] ✓ Ancienne installation trouvée ! UserData existe dans l'ancien emplacement`); + console.log(`[UserDataBackup] ✓ Old installation found! UserData exists in old location`); } else { - console.log(`[UserDataBackup] ✗ Aucune ancienne installation trouvée dans ${oldPath}`); + console.log(`[UserDataBackup] ✗ No old installation found in ${oldPath}`); userDataPath = path.join(installPath, branch, 'package', 'game', 'latest', 'Client', 'UserData'); } } else { // Si on a version_client/version_branch, on cherche dans installPath/HytaleF2P/ userDataPath = path.join(installPath, branch, 'package', 'game', 'latest', 'Client', 'UserData'); - console.log(`[UserDataBackup] Version configurée, recherche dans: ${userDataPath}`); + console.log(`[UserDataBackup] Version configured, searching in: ${userDataPath}`); } if (!fs.existsSync(userDataPath)) { - console.log(`[UserDataBackup] ✗ Aucun UserData trouvé à ${userDataPath}, backup ignoré`); + console.log(`[UserDataBackup] ✗ No UserData found at ${userDataPath}, backup skipped`); return null; } - console.log(`[UserDataBackup] ✓ UserData trouvé à ${userDataPath}`); + console.log(`[UserDataBackup] ✓ UserData found at ${userDataPath}`); const backupPath = path.join(installPath, `UserData_backup_${branch}_${Date.now()}`); try { - console.log(`[UserDataBackup] Copie de ${userDataPath} vers ${backupPath}...`); + console.log(`[UserDataBackup] Copying from ${userDataPath} to ${backupPath}...`); await fs.copy(userDataPath, backupPath, { overwrite: true, errorOnExist: false }); - console.log('[UserDataBackup] ✓ Backup complété avec succès'); + console.log('[UserDataBackup] ✓ Backup completed successfully'); return backupPath; } catch (error) { console.error('[UserDataBackup] ✗ Erreur lors du backup:', error);