mirror of
https://gitea.shironeko-all.duckdns.org/shironeko/Hytale-F2P-2.git
synced 2026-02-26 02:31:46 -03:00
fix hardcoded branch + pre-release/release issue
This commit is contained in:
@@ -167,6 +167,8 @@ function setupSettingsElements() {
|
|||||||
closeLauncherCheck = document.getElementById('closeLauncherCheck');
|
closeLauncherCheck = document.getElementById('closeLauncherCheck');
|
||||||
gpuPreferenceRadios = document.querySelectorAll('input[name="gpuPreference"]');
|
gpuPreferenceRadios = document.querySelectorAll('input[name="gpuPreference"]');
|
||||||
gameBranchRadios = document.querySelectorAll('input[name="gameBranch"]');
|
gameBranchRadios = document.querySelectorAll('input[name="gameBranch"]');
|
||||||
|
|
||||||
|
console.log('[Settings] gameBranchRadios found:', gameBranchRadios.length);
|
||||||
|
|
||||||
|
|
||||||
// UUID Management elements
|
// UUID Management elements
|
||||||
@@ -541,7 +543,8 @@ document.addEventListener('DOMContentLoaded', initSettings);
|
|||||||
|
|
||||||
window.SettingsAPI = {
|
window.SettingsAPI = {
|
||||||
getCurrentJavaPath,
|
getCurrentJavaPath,
|
||||||
getCurrentPlayerName
|
getCurrentPlayerName,
|
||||||
|
reloadBranch: loadVersionBranch
|
||||||
};
|
};
|
||||||
|
|
||||||
async function loadCurrentUuid() {
|
async function loadCurrentUuid() {
|
||||||
@@ -1078,11 +1081,13 @@ async function loadVersionBranch() {
|
|||||||
console.log('[Settings] Selected branch:', selectedBranch);
|
console.log('[Settings] Selected branch:', selectedBranch);
|
||||||
|
|
||||||
// Update radio buttons
|
// Update radio buttons
|
||||||
if (gameBranchRadios) {
|
if (gameBranchRadios && gameBranchRadios.length > 0) {
|
||||||
gameBranchRadios.forEach(radio => {
|
gameBranchRadios.forEach(radio => {
|
||||||
radio.checked = radio.value === selectedBranch;
|
radio.checked = radio.value === selectedBranch;
|
||||||
console.log(`[Settings] Radio ${radio.value}: ${radio.checked ? 'checked' : 'unchecked'}`);
|
console.log(`[Settings] Radio ${radio.value}: ${radio.checked ? 'checked' : 'unchecked'}`);
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
console.warn('[Settings] gameBranchRadios not found or empty');
|
||||||
}
|
}
|
||||||
|
|
||||||
return selectedBranch;
|
return selectedBranch;
|
||||||
|
|||||||
639
GUI/js/ui.js
639
GUI/js/ui.js
@@ -1,27 +1,27 @@
|
|||||||
|
|
||||||
let progressOverlay;
|
let progressOverlay;
|
||||||
let progressBar;
|
let progressBar;
|
||||||
let progressBarFill;
|
let progressBarFill;
|
||||||
let progressText;
|
let progressText;
|
||||||
let progressPercent;
|
let progressPercent;
|
||||||
let progressSpeed;
|
let progressSpeed;
|
||||||
let progressSize;
|
let progressSize;
|
||||||
let progressErrorContainer;
|
let progressErrorContainer;
|
||||||
let progressErrorMessage;
|
let progressErrorMessage;
|
||||||
let progressRetryInfo;
|
let progressRetryInfo;
|
||||||
let progressRetryBtn;
|
let progressRetryBtn;
|
||||||
|
|
||||||
// Download retry state
|
// Download retry state
|
||||||
let currentDownloadState = {
|
let currentDownloadState = {
|
||||||
isDownloading: false,
|
isDownloading: false,
|
||||||
canRetry: false,
|
canRetry: false,
|
||||||
retryData: null,
|
retryData: null,
|
||||||
lastError: null,
|
lastError: null,
|
||||||
errorType: null,
|
errorType: null,
|
||||||
branch: null,
|
branch: null,
|
||||||
fileName: null,
|
fileName: null,
|
||||||
cacheDir: null
|
cacheDir: null
|
||||||
};
|
};
|
||||||
|
|
||||||
function showPage(pageId) {
|
function showPage(pageId) {
|
||||||
const pages = document.querySelectorAll('.page');
|
const pages = document.querySelectorAll('.page');
|
||||||
@@ -29,6 +29,15 @@ function showPage(pageId) {
|
|||||||
if (page.id === pageId) {
|
if (page.id === pageId) {
|
||||||
page.classList.add('active');
|
page.classList.add('active');
|
||||||
page.style.display = '';
|
page.style.display = '';
|
||||||
|
|
||||||
|
// Reload settings when settings page becomes visible
|
||||||
|
if (pageId === 'settings-page') {
|
||||||
|
console.log('[UI] Settings page activated, reloading branch...');
|
||||||
|
// Dynamically import and call loadVersionBranch from settings
|
||||||
|
if (window.SettingsAPI && window.SettingsAPI.reloadBranch) {
|
||||||
|
window.SettingsAPI.reloadBranch();
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
page.classList.remove('active');
|
page.classList.remove('active');
|
||||||
page.style.display = 'none';
|
page.style.display = 'none';
|
||||||
@@ -159,108 +168,108 @@ function hideProgress() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateProgress(data) {
|
function updateProgress(data) {
|
||||||
// Handle retry state
|
// Handle retry state
|
||||||
if (data.retryState) {
|
if (data.retryState) {
|
||||||
currentDownloadState.retryData = data.retryState;
|
currentDownloadState.retryData = data.retryState;
|
||||||
updateRetryState(data.retryState);
|
updateRetryState(data.retryState);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.message && progressText) {
|
if (data.message && progressText) {
|
||||||
progressText.textContent = data.message;
|
progressText.textContent = data.message;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.percent !== null && data.percent !== undefined) {
|
if (data.percent !== null && data.percent !== undefined) {
|
||||||
const percent = Math.min(100, Math.max(0, Math.round(data.percent)));
|
const percent = Math.min(100, Math.max(0, Math.round(data.percent)));
|
||||||
if (progressPercent) progressPercent.textContent = `${percent}%`;
|
if (progressPercent) progressPercent.textContent = `${percent}%`;
|
||||||
if (progressBarFill) progressBarFill.style.width = `${percent}%`;
|
if (progressBarFill) progressBarFill.style.width = `${percent}%`;
|
||||||
if (progressBar) progressBar.style.width = `${percent}%`;
|
if (progressBar) progressBar.style.width = `${percent}%`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.speed && data.downloaded && data.total) {
|
if (data.speed && data.downloaded && data.total) {
|
||||||
const speedMB = (data.speed / 1024 / 1024).toFixed(2);
|
const speedMB = (data.speed / 1024 / 1024).toFixed(2);
|
||||||
const downloadedMB = (data.downloaded / 1024 / 1024).toFixed(2);
|
const downloadedMB = (data.downloaded / 1024 / 1024).toFixed(2);
|
||||||
const totalMB = (data.total / 1024 / 1024).toFixed(2);
|
const totalMB = (data.total / 1024 / 1024).toFixed(2);
|
||||||
if (progressSpeed) progressSpeed.textContent = `${speedMB} MB/s`;
|
if (progressSpeed) progressSpeed.textContent = `${speedMB} MB/s`;
|
||||||
if (progressSize) progressSize.textContent = `${downloadedMB} / ${totalMB} MB`;
|
if (progressSize) progressSize.textContent = `${downloadedMB} / ${totalMB} MB`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle error states with enhanced categorization
|
// Handle error states with enhanced categorization
|
||||||
// Don't show error during automatic retries - let the retry message display instead
|
// Don't show error during automatic retries - let the retry message display instead
|
||||||
if ((data.error || (data.message && data.message.includes('failed'))) &&
|
if ((data.error || (data.message && data.message.includes('failed'))) &&
|
||||||
!(data.retryState && data.retryState.isAutomaticRetry)) {
|
!(data.retryState && data.retryState.isAutomaticRetry)) {
|
||||||
const errorType = categorizeError(data.message);
|
const errorType = categorizeError(data.message);
|
||||||
showDownloadError(data.message, data.canRetry, errorType);
|
showDownloadError(data.message, data.canRetry, errorType);
|
||||||
} else if (data.percent === 100) {
|
} else if (data.percent === 100) {
|
||||||
hideDownloadError();
|
hideDownloadError();
|
||||||
} else if (data.retryState && data.retryState.isAutomaticRetry) {
|
} else if (data.retryState && data.retryState.isAutomaticRetry) {
|
||||||
// Hide any existing error during automatic retries
|
// Hide any existing error during automatic retries
|
||||||
hideDownloadError();
|
hideDownloadError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateRetryState(retryState) {
|
function updateRetryState(retryState) {
|
||||||
if (!progressRetryInfo) return;
|
if (!progressRetryInfo) return;
|
||||||
|
|
||||||
if (retryState.isAutomaticRetry && retryState.automaticStallRetries > 0) {
|
if (retryState.isAutomaticRetry && retryState.automaticStallRetries > 0) {
|
||||||
// Show automatic stall retry count
|
// Show automatic stall retry count
|
||||||
progressRetryInfo.textContent = `Auto-retry ${retryState.automaticStallRetries}/3`;
|
progressRetryInfo.textContent = `Auto-retry ${retryState.automaticStallRetries}/3`;
|
||||||
progressRetryInfo.style.display = 'block';
|
progressRetryInfo.style.display = 'block';
|
||||||
progressRetryInfo.style.background = 'rgba(255, 193, 7, 0.2)'; // Light orange background for auto-retries
|
progressRetryInfo.style.background = 'rgba(255, 193, 7, 0.2)'; // Light orange background for auto-retries
|
||||||
progressRetryInfo.style.color = '#ff9800'; // Orange text for auto-retries
|
progressRetryInfo.style.color = '#ff9800'; // Orange text for auto-retries
|
||||||
} else if (retryState.attempts > 1) {
|
} else if (retryState.attempts > 1) {
|
||||||
// Show manual retry count
|
// Show manual retry count
|
||||||
progressRetryInfo.textContent = `Attempt ${retryState.attempts}/${retryState.maxRetries}`;
|
progressRetryInfo.textContent = `Attempt ${retryState.attempts}/${retryState.maxRetries}`;
|
||||||
progressRetryInfo.style.display = 'block';
|
progressRetryInfo.style.display = 'block';
|
||||||
progressRetryInfo.style.background = ''; // Reset background
|
progressRetryInfo.style.background = ''; // Reset background
|
||||||
progressRetryInfo.style.color = ''; // Reset color
|
progressRetryInfo.style.color = ''; // Reset color
|
||||||
} else {
|
} else {
|
||||||
progressRetryInfo.style.display = 'none';
|
progressRetryInfo.style.display = 'none';
|
||||||
progressRetryInfo.style.background = ''; // Reset background
|
progressRetryInfo.style.background = ''; // Reset background
|
||||||
progressRetryInfo.style.color = ''; // Reset color
|
progressRetryInfo.style.color = ''; // Reset color
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showDownloadError(errorMessage, canRetry = true, errorType = 'general') {
|
function showDownloadError(errorMessage, canRetry = true, errorType = 'general') {
|
||||||
if (!progressErrorContainer || !progressErrorMessage || !progressRetryBtn) return;
|
if (!progressErrorContainer || !progressErrorMessage || !progressRetryBtn) return;
|
||||||
|
|
||||||
currentDownloadState.lastError = errorMessage;
|
currentDownloadState.lastError = errorMessage;
|
||||||
currentDownloadState.canRetry = canRetry;
|
currentDownloadState.canRetry = canRetry;
|
||||||
currentDownloadState.errorType = errorType;
|
currentDownloadState.errorType = errorType;
|
||||||
|
|
||||||
// Update retry context if available
|
// Update retry context if available
|
||||||
if (data && data.retryData) {
|
if (data && data.retryData) {
|
||||||
currentDownloadState.branch = data.retryData.branch;
|
currentDownloadState.branch = data.retryData.branch;
|
||||||
currentDownloadState.fileName = data.retryData.fileName;
|
currentDownloadState.fileName = data.retryData.fileName;
|
||||||
currentDownloadState.cacheDir = data.retryData.cacheDir;
|
currentDownloadState.cacheDir = data.retryData.cacheDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
// User-friendly error messages
|
// User-friendly error messages
|
||||||
const userMessage = getErrorMessage(errorMessage, errorType);
|
const userMessage = getErrorMessage(errorMessage, errorType);
|
||||||
progressErrorMessage.textContent = userMessage;
|
progressErrorMessage.textContent = userMessage;
|
||||||
progressErrorContainer.style.display = 'block';
|
progressErrorContainer.style.display = 'block';
|
||||||
progressRetryBtn.style.display = canRetry ? 'block' : 'none';
|
progressRetryBtn.style.display = canRetry ? 'block' : 'none';
|
||||||
|
|
||||||
// Add visual indicators based on error type
|
// Add visual indicators based on error type
|
||||||
progressErrorContainer.className = `progress-error-container error-${errorType}`;
|
progressErrorContainer.className = `progress-error-container error-${errorType}`;
|
||||||
|
|
||||||
if (progressOverlay) {
|
if (progressOverlay) {
|
||||||
progressOverlay.classList.add('error-state');
|
progressOverlay.classList.add('error-state');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function hideDownloadError() {
|
function hideDownloadError() {
|
||||||
if (!progressErrorContainer) return;
|
if (!progressErrorContainer) return;
|
||||||
|
|
||||||
progressErrorContainer.style.display = 'none';
|
progressErrorContainer.style.display = 'none';
|
||||||
currentDownloadState.canRetry = false;
|
currentDownloadState.canRetry = false;
|
||||||
currentDownloadState.lastError = null;
|
currentDownloadState.lastError = null;
|
||||||
currentDownloadState.errorType = null;
|
currentDownloadState.errorType = null;
|
||||||
|
|
||||||
if (progressOverlay) {
|
if (progressOverlay) {
|
||||||
progressOverlay.classList.remove('error-state');
|
progressOverlay.classList.remove('error-state');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupAnimations() {
|
function setupAnimations() {
|
||||||
document.body.style.opacity = '0';
|
document.body.style.opacity = '0';
|
||||||
@@ -568,24 +577,24 @@ function showNotification(message, type = 'info') {
|
|||||||
}, 5000);
|
}, 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupUI() {
|
function setupUI() {
|
||||||
progressOverlay = document.getElementById('progressOverlay');
|
progressOverlay = document.getElementById('progressOverlay');
|
||||||
progressBar = document.getElementById('progressBar');
|
progressBar = document.getElementById('progressBar');
|
||||||
progressBarFill = document.getElementById('progressBarFill');
|
progressBarFill = document.getElementById('progressBarFill');
|
||||||
progressText = document.getElementById('progressText');
|
progressText = document.getElementById('progressText');
|
||||||
progressPercent = document.getElementById('progressPercent');
|
progressPercent = document.getElementById('progressPercent');
|
||||||
progressSpeed = document.getElementById('progressSpeed');
|
progressSpeed = document.getElementById('progressSpeed');
|
||||||
progressSize = document.getElementById('progressSize');
|
progressSize = document.getElementById('progressSize');
|
||||||
progressErrorContainer = document.getElementById('progressErrorContainer');
|
progressErrorContainer = document.getElementById('progressErrorContainer');
|
||||||
progressErrorMessage = document.getElementById('progressErrorMessage');
|
progressErrorMessage = document.getElementById('progressErrorMessage');
|
||||||
progressRetryInfo = document.getElementById('progressRetryInfo');
|
progressRetryInfo = document.getElementById('progressRetryInfo');
|
||||||
progressRetryBtn = document.getElementById('progressRetryBtn');
|
progressRetryBtn = document.getElementById('progressRetryBtn');
|
||||||
|
|
||||||
// Setup draggable progress bar
|
// Setup draggable progress bar
|
||||||
setupProgressDrag();
|
setupProgressDrag();
|
||||||
|
|
||||||
// Setup retry button
|
// Setup retry button
|
||||||
setupRetryButton();
|
setupRetryButton();
|
||||||
|
|
||||||
lockPlayButton(true);
|
lockPlayButton(true);
|
||||||
|
|
||||||
@@ -753,175 +762,175 @@ function toggleMaximize() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error categorization and user-friendly messages
|
// Error categorization and user-friendly messages
|
||||||
function categorizeError(message) {
|
function categorizeError(message) {
|
||||||
const msg = message.toLowerCase();
|
const msg = message.toLowerCase();
|
||||||
|
|
||||||
if (msg.includes('network') || msg.includes('connection') || msg.includes('offline')) {
|
if (msg.includes('network') || msg.includes('connection') || msg.includes('offline')) {
|
||||||
return 'network';
|
return 'network';
|
||||||
} else if (msg.includes('stalled') || msg.includes('timeout')) {
|
} else if (msg.includes('stalled') || msg.includes('timeout')) {
|
||||||
return 'stall';
|
return 'stall';
|
||||||
} else if (msg.includes('file') || msg.includes('disk')) {
|
} else if (msg.includes('file') || msg.includes('disk')) {
|
||||||
return 'file';
|
return 'file';
|
||||||
} else if (msg.includes('permission') || msg.includes('access')) {
|
} else if (msg.includes('permission') || msg.includes('access')) {
|
||||||
return 'permission';
|
return 'permission';
|
||||||
} else if (msg.includes('server') || msg.includes('5')) {
|
} else if (msg.includes('server') || msg.includes('5')) {
|
||||||
return 'server';
|
return 'server';
|
||||||
} else if (msg.includes('corrupted') || msg.includes('pwr file') || msg.includes('unexpected eof')) {
|
} else if (msg.includes('corrupted') || msg.includes('pwr file') || msg.includes('unexpected eof')) {
|
||||||
return 'corruption';
|
return 'corruption';
|
||||||
} else if (msg.includes('butler') || msg.includes('patch installation')) {
|
} else if (msg.includes('butler') || msg.includes('patch installation')) {
|
||||||
return 'butler';
|
return 'butler';
|
||||||
} else if (msg.includes('space') || msg.includes('full') || msg.includes('device full')) {
|
} else if (msg.includes('space') || msg.includes('full') || msg.includes('device full')) {
|
||||||
return 'space';
|
return 'space';
|
||||||
} else if (msg.includes('conflict') || msg.includes('already exists')) {
|
} else if (msg.includes('conflict') || msg.includes('already exists')) {
|
||||||
return 'conflict';
|
return 'conflict';
|
||||||
} else {
|
} else {
|
||||||
return 'general';
|
return 'general';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getErrorMessage(technicalMessage, errorType) {
|
function getErrorMessage(technicalMessage, errorType) {
|
||||||
// Technical errors go to console, user gets friendly messages
|
// Technical errors go to console, user gets friendly messages
|
||||||
console.error(`Download error [${errorType}]:`, technicalMessage);
|
console.error(`Download error [${errorType}]:`, technicalMessage);
|
||||||
|
|
||||||
switch (errorType) {
|
switch (errorType) {
|
||||||
case 'network':
|
case 'network':
|
||||||
return 'Network connection lost. Please check your internet connection and retry.';
|
return 'Network connection lost. Please check your internet connection and retry.';
|
||||||
case 'stall':
|
case 'stall':
|
||||||
return 'Download stalled due to slow connection. Please retry.';
|
return 'Download stalled due to slow connection. Please retry.';
|
||||||
case 'file':
|
case 'file':
|
||||||
return 'Unable to save file. Check disk space and permissions. Please retry.';
|
return 'Unable to save file. Check disk space and permissions. Please retry.';
|
||||||
case 'permission':
|
case 'permission':
|
||||||
return 'Permission denied. Check if launcher has write access. Please retry.';
|
return 'Permission denied. Check if launcher has write access. Please retry.';
|
||||||
case 'server':
|
case 'server':
|
||||||
return 'Server error. Please wait a moment and retry.';
|
return 'Server error. Please wait a moment and retry.';
|
||||||
case 'corruption':
|
case 'corruption':
|
||||||
return 'Corrupted PWR file detected. File deleted and will retry.';
|
return 'Corrupted PWR file detected. File deleted and will retry.';
|
||||||
case 'butler':
|
case 'butler':
|
||||||
return 'Patch installation failed. Please retry.';
|
return 'Patch installation failed. Please retry.';
|
||||||
case 'space':
|
case 'space':
|
||||||
return 'Insufficient disk space. Free up space and retry.';
|
return 'Insufficient disk space. Free up space and retry.';
|
||||||
case 'conflict':
|
case 'conflict':
|
||||||
return 'Installation directory conflict. Please retry.';
|
return 'Installation directory conflict. Please retry.';
|
||||||
default:
|
default:
|
||||||
return 'Download failed. Please retry.';
|
return 'Download failed. Please retry.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connection quality indicator (simplified)
|
// Connection quality indicator (simplified)
|
||||||
function updateConnectionQuality(quality) {
|
function updateConnectionQuality(quality) {
|
||||||
if (!progressSize) return;
|
if (!progressSize) return;
|
||||||
|
|
||||||
const qualityColors = {
|
const qualityColors = {
|
||||||
'Good': '#10b981',
|
'Good': '#10b981',
|
||||||
'Fair': '#fbbf24',
|
'Fair': '#fbbf24',
|
||||||
'Poor': '#f87171'
|
'Poor': '#f87171'
|
||||||
};
|
};
|
||||||
|
|
||||||
const color = qualityColors[quality] || '#6b7280';
|
const color = qualityColors[quality] || '#6b7280';
|
||||||
progressSize.style.color = color;
|
progressSize.style.color = color;
|
||||||
|
|
||||||
// Add subtle quality indicator
|
// Add subtle quality indicator
|
||||||
if (progressSize.dataset.quality !== quality) {
|
if (progressSize.dataset.quality !== quality) {
|
||||||
progressSize.dataset.quality = quality;
|
progressSize.dataset.quality = quality;
|
||||||
progressSize.style.transition = 'color 0.5s ease';
|
progressSize.style.transition = 'color 0.5s ease';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enhanced retry button setup
|
// Enhanced retry button setup
|
||||||
function setupRetryButton() {
|
function setupRetryButton() {
|
||||||
if (!progressRetryBtn) return;
|
if (!progressRetryBtn) return;
|
||||||
|
|
||||||
progressRetryBtn.addEventListener('click', async () => {
|
progressRetryBtn.addEventListener('click', async () => {
|
||||||
if (!currentDownloadState.canRetry || currentDownloadState.isDownloading) {
|
if (!currentDownloadState.canRetry || currentDownloadState.isDownloading) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable retry button during retry
|
// Disable retry button during retry
|
||||||
progressRetryBtn.disabled = true;
|
progressRetryBtn.disabled = true;
|
||||||
progressRetryBtn.textContent = '🔄 Retrying...';
|
progressRetryBtn.textContent = '🔄 Retrying...';
|
||||||
progressRetryBtn.classList.add('retrying');
|
progressRetryBtn.classList.add('retrying');
|
||||||
currentDownloadState.isDownloading = true;
|
currentDownloadState.isDownloading = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Hide error state during retry
|
// Hide error state during retry
|
||||||
hideDownloadError();
|
hideDownloadError();
|
||||||
|
|
||||||
// Reset retry info styling for manual retries
|
// Reset retry info styling for manual retries
|
||||||
if (progressRetryInfo) {
|
if (progressRetryInfo) {
|
||||||
progressRetryInfo.style.background = '';
|
progressRetryInfo.style.background = '';
|
||||||
progressRetryInfo.style.color = '';
|
progressRetryInfo.style.color = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update progress text with context-aware message
|
// Update progress text with context-aware message
|
||||||
if (progressText) {
|
if (progressText) {
|
||||||
const contextMessage = getRetryContextMessage();
|
const contextMessage = getRetryContextMessage();
|
||||||
progressText.textContent = contextMessage;
|
progressText.textContent = contextMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure retry data exists, create defaults if null
|
// Ensure retry data exists, create defaults if null
|
||||||
if (!currentDownloadState.retryData) {
|
if (!currentDownloadState.retryData) {
|
||||||
currentDownloadState.retryData = {
|
currentDownloadState.retryData = {
|
||||||
branch: 'release',
|
branch: 'release',
|
||||||
fileName: '4.pwr'
|
fileName: '4.pwr'
|
||||||
};
|
};
|
||||||
console.log('[UI] Created default retry data:', currentDownloadState.retryData);
|
console.log('[UI] Created default retry data:', currentDownloadState.retryData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send retry request to backend
|
// Send retry request to backend
|
||||||
if (window.electronAPI && window.electronAPI.retryDownload) {
|
if (window.electronAPI && window.electronAPI.retryDownload) {
|
||||||
const result = await window.electronAPI.retryDownload(currentDownloadState.retryData);
|
const result = await window.electronAPI.retryDownload(currentDownloadState.retryData);
|
||||||
|
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
throw new Error(result.error || 'Retry failed');
|
throw new Error(result.error || 'Retry failed');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Fallback for development/testing
|
// Fallback for development/testing
|
||||||
console.warn('electronAPI.retryDownload not available, simulating retry...');
|
console.warn('electronAPI.retryDownload not available, simulating retry...');
|
||||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||||
throw new Error('Retry API not available');
|
throw new Error('Retry API not available');
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Retry failed:', error);
|
console.error('Retry failed:', error);
|
||||||
const errorType = categorizeError(error.message);
|
const errorType = categorizeError(error.message);
|
||||||
showDownloadError(`Retry failed: ${error.message}`, true, errorType);
|
showDownloadError(`Retry failed: ${error.message}`, true, errorType);
|
||||||
|
|
||||||
// Reset retry button
|
// Reset retry button
|
||||||
progressRetryBtn.disabled = false;
|
progressRetryBtn.disabled = false;
|
||||||
progressRetryBtn.textContent = '🔄 Retry Download';
|
progressRetryBtn.textContent = '🔄 Retry Download';
|
||||||
progressRetryBtn.classList.remove('retrying');
|
progressRetryBtn.classList.remove('retrying');
|
||||||
currentDownloadState.isDownloading = false;
|
currentDownloadState.isDownloading = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRetryContextMessage() {
|
function getRetryContextMessage() {
|
||||||
const errorType = currentDownloadState.errorType;
|
const errorType = currentDownloadState.errorType;
|
||||||
|
|
||||||
switch (errorType) {
|
switch (errorType) {
|
||||||
case 'network':
|
case 'network':
|
||||||
return 'Reconnecting and retrying download...';
|
return 'Reconnecting and retrying download...';
|
||||||
case 'stall':
|
case 'stall':
|
||||||
return 'Resuming stalled download...';
|
return 'Resuming stalled download...';
|
||||||
case 'server':
|
case 'server':
|
||||||
return 'Waiting for server and retrying...';
|
return 'Waiting for server and retrying...';
|
||||||
case 'corruption':
|
case 'corruption':
|
||||||
return 'Re-downloading corrupted PWR file...';
|
return 'Re-downloading corrupted PWR file...';
|
||||||
case 'butler':
|
case 'butler':
|
||||||
return 'Re-attempting patch installation...';
|
return 'Re-attempting patch installation...';
|
||||||
case 'space':
|
case 'space':
|
||||||
return 'Retrying after clearing disk space...';
|
return 'Retrying after clearing disk space...';
|
||||||
case 'permission':
|
case 'permission':
|
||||||
return 'Retrying with corrected permissions...';
|
return 'Retrying with corrected permissions...';
|
||||||
case 'conflict':
|
case 'conflict':
|
||||||
return 'Retrying after resolving conflicts...';
|
return 'Retrying after resolving conflicts...';
|
||||||
default:
|
default:
|
||||||
return 'Initiating retry download...';
|
return 'Initiating retry download...';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make toggleMaximize globally available
|
// Make toggleMaximize globally available
|
||||||
window.toggleMaximize = toggleMaximize;
|
window.toggleMaximize = toggleMaximize;
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', setupUI);
|
document.addEventListener('DOMContentLoaded', setupUI);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const os = require('os');
|
const os = require('os');
|
||||||
|
const { loadVersionBranch } = require('./config');
|
||||||
|
|
||||||
function getAppDir() {
|
function getAppDir() {
|
||||||
const home = os.homedir();
|
const home = os.homedir();
|
||||||
@@ -48,8 +49,20 @@ function expandHome(inputPath) {
|
|||||||
const APP_DIR = DEFAULT_APP_DIR;
|
const APP_DIR = DEFAULT_APP_DIR;
|
||||||
const CACHE_DIR = path.join(APP_DIR, 'cache');
|
const CACHE_DIR = path.join(APP_DIR, 'cache');
|
||||||
const TOOLS_DIR = path.join(APP_DIR, 'butler');
|
const TOOLS_DIR = path.join(APP_DIR, 'butler');
|
||||||
const GAME_DIR = path.join(APP_DIR, 'release', 'package', 'game', 'latest');
|
|
||||||
const JRE_DIR = path.join(APP_DIR, 'release', 'package', 'jre', 'latest');
|
// Dynamic GAME_DIR and JRE_DIR based on version_branch from config
|
||||||
|
function getGameDir() {
|
||||||
|
const branch = loadVersionBranch();
|
||||||
|
return path.join(APP_DIR, branch, 'package', 'game', 'latest');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getJreDir() {
|
||||||
|
const branch = loadVersionBranch();
|
||||||
|
return path.join(APP_DIR, branch, 'package', 'jre', 'latest');
|
||||||
|
}
|
||||||
|
|
||||||
|
const GAME_DIR = getGameDir();
|
||||||
|
const JRE_DIR = getJreDir();
|
||||||
const PLAYER_ID_FILE = path.join(APP_DIR, 'player_id.json');
|
const PLAYER_ID_FILE = path.join(APP_DIR, 'player_id.json');
|
||||||
|
|
||||||
function getClientCandidates(gameLatest) {
|
function getClientCandidates(gameLatest) {
|
||||||
@@ -156,7 +169,8 @@ async function getModsPath(customInstallPath = null) {
|
|||||||
installPath = getAppDir();
|
installPath = getAppDir();
|
||||||
}
|
}
|
||||||
|
|
||||||
const gameLatest = path.join(installPath, 'release', 'package', 'game', 'latest');
|
const branch = loadVersionBranch();
|
||||||
|
const gameLatest = path.join(installPath, branch, 'package', 'game', 'latest');
|
||||||
|
|
||||||
const userDataPath = findUserDataPath(gameLatest);
|
const userDataPath = findUserDataPath(gameLatest);
|
||||||
|
|
||||||
@@ -195,7 +209,8 @@ function getProfilesDir(customInstallPath = null) {
|
|||||||
}
|
}
|
||||||
if (!installPath) installPath = getAppDir();
|
if (!installPath) installPath = getAppDir();
|
||||||
|
|
||||||
const gameLatest = path.join(installPath, 'release', 'package', 'game', 'latest');
|
const branch = loadVersionBranch();
|
||||||
|
const gameLatest = path.join(installPath, branch, 'package', 'game', 'latest');
|
||||||
const userDataPath = findUserDataPath(gameLatest);
|
const userDataPath = findUserDataPath(gameLatest);
|
||||||
const profilesDir = path.join(userDataPath, 'Profiles');
|
const profilesDir = path.join(userDataPath, 'Profiles');
|
||||||
|
|
||||||
@@ -219,6 +234,8 @@ module.exports = {
|
|||||||
TOOLS_DIR,
|
TOOLS_DIR,
|
||||||
GAME_DIR,
|
GAME_DIR,
|
||||||
JRE_DIR,
|
JRE_DIR,
|
||||||
|
getGameDir,
|
||||||
|
getJreDir,
|
||||||
PLAYER_ID_FILE,
|
PLAYER_ID_FILE,
|
||||||
getClientCandidates,
|
getClientCandidates,
|
||||||
findClientPath,
|
findClientPath,
|
||||||
|
|||||||
@@ -446,7 +446,11 @@ function isGameInstalled(branchOverride = null) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function installGame(playerName = 'Player', progressCallback, javaPathOverride, installPathOverride, branchOverride = null) {
|
async function installGame(playerName = 'Player', progressCallback, javaPathOverride, installPathOverride, branchOverride = null) {
|
||||||
const branch = branchOverride || loadVersionBranch();
|
console.log(`[InstallGame] branchOverride parameter received: ${branchOverride}`);
|
||||||
|
const loadedBranch = loadVersionBranch();
|
||||||
|
console.log(`[InstallGame] loadVersionBranch() returned: ${loadedBranch}`);
|
||||||
|
const branch = branchOverride || loadedBranch;
|
||||||
|
console.log(`[InstallGame] Final branch selected: ${branch}`);
|
||||||
const customAppDir = getResolvedAppDir(installPathOverride);
|
const customAppDir = getResolvedAppDir(installPathOverride);
|
||||||
const customCacheDir = path.join(customAppDir, 'cache');
|
const customCacheDir = path.join(customAppDir, 'cache');
|
||||||
const customToolsDir = path.join(customAppDir, 'butler');
|
const customToolsDir = path.join(customAppDir, 'butler');
|
||||||
|
|||||||
458
main.js
458
main.js
@@ -255,11 +255,11 @@ app.whenReady().then(async () => {
|
|||||||
mainWindow.webContents.send('lock-play-button', true);
|
mainWindow.webContents.send('lock-play-button', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
const progressCallback = (message, percent, speed, downloaded, total, retryState) => {
|
const progressCallback = (message, percent, speed, downloaded, total, retryState) => {
|
||||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||||
mainWindow.webContents.send('first-launch-progress', { message, percent, speed, downloaded, total, retryState });
|
mainWindow.webContents.send('first-launch-progress', { message, percent, speed, downloaded, total, retryState });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const firstLaunchResult = await Promise.race([
|
const firstLaunchResult = await Promise.race([
|
||||||
handleFirstLaunchCheck(progressCallback),
|
handleFirstLaunchCheck(progressCallback),
|
||||||
@@ -346,21 +346,21 @@ app.on('window-all-closed', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
ipcMain.handle('launch-game', async (event, playerName, javaPath, installPath, gpuPreference) => {
|
ipcMain.handle('launch-game', async (event, playerName, javaPath, installPath, gpuPreference) => {
|
||||||
try {
|
try {
|
||||||
const progressCallback = (message, percent, speed, downloaded, total, retryState) => {
|
const progressCallback = (message, percent, speed, downloaded, total, retryState) => {
|
||||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||||
const data = {
|
const data = {
|
||||||
message: message || null,
|
message: message || null,
|
||||||
percent: percent !== null && percent !== undefined ? Math.min(100, Math.max(0, percent)) : null,
|
percent: percent !== null && percent !== undefined ? Math.min(100, Math.max(0, percent)) : null,
|
||||||
speed: speed !== null && speed !== undefined ? speed : null,
|
speed: speed !== null && speed !== undefined ? speed : null,
|
||||||
downloaded: downloaded !== null && downloaded !== undefined ? downloaded : null,
|
downloaded: downloaded !== null && downloaded !== undefined ? downloaded : null,
|
||||||
total: total !== null && total !== undefined ? total : null,
|
total: total !== null && total !== undefined ? total : null,
|
||||||
retryState: retryState || null
|
retryState: retryState || null
|
||||||
};
|
};
|
||||||
mainWindow.webContents.send('progress-update', data);
|
mainWindow.webContents.send('progress-update', data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = await launchGameWithVersionCheck(playerName, progressCallback, javaPath, installPath, gpuPreference);
|
const result = await launchGameWithVersionCheck(playerName, progressCallback, javaPath, installPath, gpuPreference);
|
||||||
|
|
||||||
@@ -390,108 +390,113 @@ ipcMain.handle('launch-game', async (event, playerName, javaPath, installPath, g
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle('install-game', async (event, playerName, javaPath, installPath, branch) => {
|
ipcMain.handle('install-game', async (event, playerName, javaPath, installPath, branch) => {
|
||||||
try {
|
try {
|
||||||
console.log(`[IPC] install-game called with branch: ${branch || 'default'}`);
|
console.log(`[IPC] install-game called with parameters:`);
|
||||||
|
console.log(` - playerName: ${playerName}`);
|
||||||
// Signal installation start
|
console.log(` - javaPath: ${javaPath}`);
|
||||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
console.log(` - installPath: ${installPath}`);
|
||||||
mainWindow.webContents.send('installation-start');
|
console.log(` - branch: ${branch}`);
|
||||||
}
|
console.log(`[IPC] branch type: ${typeof branch}, value: ${JSON.stringify(branch)}`);
|
||||||
|
|
||||||
const progressCallback = (message, percent, speed, downloaded, total, retryState) => {
|
// Signal installation start
|
||||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||||
const data = {
|
mainWindow.webContents.send('installation-start');
|
||||||
message: message || null,
|
}
|
||||||
percent: percent !== null && percent !== undefined ? Math.min(100, Math.max(0, percent)) : null,
|
|
||||||
speed: speed !== null && speed !== undefined ? speed : null,
|
const progressCallback = (message, percent, speed, downloaded, total, retryState) => {
|
||||||
downloaded: downloaded !== null && downloaded !== undefined ? downloaded : null,
|
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||||
total: total !== null && total !== undefined ? total : null,
|
const data = {
|
||||||
retryState: retryState || null
|
message: message || null,
|
||||||
};
|
percent: percent !== null && percent !== undefined ? Math.min(100, Math.max(0, percent)) : null,
|
||||||
mainWindow.webContents.send('progress-update', data);
|
speed: speed !== null && speed !== undefined ? speed : null,
|
||||||
}
|
downloaded: downloaded !== null && downloaded !== undefined ? downloaded : null,
|
||||||
};
|
total: total !== null && total !== undefined ? total : null,
|
||||||
|
retryState: retryState || null
|
||||||
const result = await installGame(playerName, progressCallback, javaPath, installPath, branch);
|
};
|
||||||
|
mainWindow.webContents.send('progress-update', data);
|
||||||
// Signal installation end
|
}
|
||||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
};
|
||||||
mainWindow.webContents.send('installation-end');
|
|
||||||
}
|
const result = await installGame(playerName, progressCallback, javaPath, installPath, branch);
|
||||||
|
|
||||||
// Ensure we always return a result for the IPC handler
|
// Signal installation end
|
||||||
const successResponse = result || { success: true };
|
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||||
console.log('[Main] Returning success response for install-game:', successResponse);
|
mainWindow.webContents.send('installation-end');
|
||||||
return successResponse;
|
}
|
||||||
} catch (error) {
|
|
||||||
console.error('Install error:', error);
|
// Ensure we always return a result for the IPC handler
|
||||||
const errorMessage = error.message || error.toString();
|
const successResponse = result || { success: true };
|
||||||
|
console.log('[Main] Returning success response for install-game:', successResponse);
|
||||||
// Enhanced error data extraction for both download and Butler errors
|
return successResponse;
|
||||||
let errorData = {
|
} catch (error) {
|
||||||
message: errorMessage,
|
console.error('Install error:', error);
|
||||||
error: true,
|
const errorMessage = error.message || error.toString();
|
||||||
canRetry: true,
|
|
||||||
retryData: null
|
// Enhanced error data extraction for both download and Butler errors
|
||||||
};
|
let errorData = {
|
||||||
|
message: errorMessage,
|
||||||
// Handle Butler-specific errors
|
error: true,
|
||||||
if (error.butlerError) {
|
canRetry: true,
|
||||||
console.log('[Main] Processing Butler error with retry context');
|
retryData: null
|
||||||
errorData.retryData = {
|
};
|
||||||
branch: error.branch || 'release',
|
|
||||||
fileName: error.fileName || '4.pwr',
|
// Handle Butler-specific errors
|
||||||
cacheDir: error.cacheDir
|
if (error.butlerError) {
|
||||||
};
|
console.log('[Main] Processing Butler error with retry context');
|
||||||
errorData.canRetry = error.canRetry !== undefined ? error.canRetry : true;
|
errorData.retryData = {
|
||||||
|
branch: error.branch || 'release',
|
||||||
// Add Butler-specific error details
|
fileName: error.fileName || '4.pwr',
|
||||||
if (error.stderr) {
|
cacheDir: error.cacheDir
|
||||||
console.error('[Main] Butler stderr:', error.stderr);
|
};
|
||||||
}
|
errorData.canRetry = error.canRetry !== undefined ? error.canRetry : true;
|
||||||
if (error.stdout) {
|
|
||||||
console.log('[Main] Butler stdout:', error.stdout);
|
// Add Butler-specific error details
|
||||||
}
|
if (error.stderr) {
|
||||||
if (error.errorCode) {
|
console.error('[Main] Butler stderr:', error.stderr);
|
||||||
console.log('[Main] Butler error code:', error.errorCode);
|
}
|
||||||
}
|
if (error.stdout) {
|
||||||
}
|
console.log('[Main] Butler stdout:', error.stdout);
|
||||||
// Handle PWR download errors
|
}
|
||||||
else if (error.branch && error.fileName) {
|
if (error.errorCode) {
|
||||||
console.log('[Main] Processing PWR download error with retry context');
|
console.log('[Main] Butler error code:', error.errorCode);
|
||||||
errorData.retryData = {
|
}
|
||||||
branch: error.branch,
|
}
|
||||||
fileName: error.fileName,
|
// Handle PWR download errors
|
||||||
cacheDir: error.cacheDir
|
else if (error.branch && error.fileName) {
|
||||||
};
|
console.log('[Main] Processing PWR download error with retry context');
|
||||||
errorData.canRetry = error.canRetry !== undefined ? error.canRetry : true;
|
errorData.retryData = {
|
||||||
}
|
branch: error.branch,
|
||||||
// Default fallback for other errors
|
fileName: error.fileName,
|
||||||
else {
|
cacheDir: error.cacheDir
|
||||||
console.log('[Main] Processing generic error, creating default retry data');
|
};
|
||||||
errorData.retryData = {
|
errorData.canRetry = error.canRetry !== undefined ? error.canRetry : true;
|
||||||
branch: 'release',
|
}
|
||||||
fileName: '4.pwr'
|
// Default fallback for other errors
|
||||||
};
|
else {
|
||||||
}
|
console.log('[Main] Processing generic error, creating default retry data');
|
||||||
|
errorData.retryData = {
|
||||||
// Send enhanced error info for retry UI
|
branch: 'release',
|
||||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
fileName: '4.pwr'
|
||||||
console.log('[Main] Sending error data to renderer:', errorData);
|
};
|
||||||
mainWindow.webContents.send('progress-update', errorData);
|
}
|
||||||
}
|
|
||||||
|
// Send enhanced error info for retry UI
|
||||||
// Signal installation end on error too
|
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
console.log('[Main] Sending error data to renderer:', errorData);
|
||||||
mainWindow.webContents.send('installation-end');
|
mainWindow.webContents.send('progress-update', errorData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always return a proper response to prevent timeout
|
// Signal installation end on error too
|
||||||
const errorResponse = { success: false, error: errorMessage };
|
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||||
console.log('[Main] Returning error response for install-game:', errorResponse);
|
mainWindow.webContents.send('installation-end');
|
||||||
return errorResponse;
|
}
|
||||||
}
|
|
||||||
|
// Always return a proper response to prevent timeout
|
||||||
|
const errorResponse = { success: false, error: errorMessage };
|
||||||
|
console.log('[Main] Returning error response for install-game:', errorResponse);
|
||||||
|
return errorResponse;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle('save-username', (event, username) => {
|
ipcMain.handle('save-username', (event, username) => {
|
||||||
@@ -581,19 +586,19 @@ ipcMain.handle('select-install-path', async () => {
|
|||||||
|
|
||||||
ipcMain.handle('accept-first-launch-update', async (event, existingGame) => {
|
ipcMain.handle('accept-first-launch-update', async (event, existingGame) => {
|
||||||
try {
|
try {
|
||||||
const progressCallback = (message, percent, speed, downloaded, total, retryState) => {
|
const progressCallback = (message, percent, speed, downloaded, total, retryState) => {
|
||||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||||
const data = {
|
const data = {
|
||||||
message: message || null,
|
message: message || null,
|
||||||
percent: percent !== null && percent !== undefined ? Math.min(100, Math.max(0, percent)) : null,
|
percent: percent !== null && percent !== undefined ? Math.min(100, Math.max(0, percent)) : null,
|
||||||
speed: speed !== null && speed !== undefined ? speed : null,
|
speed: speed !== null && speed !== undefined ? speed : null,
|
||||||
downloaded: downloaded !== null && downloaded !== undefined ? downloaded : null,
|
downloaded: downloaded !== null && downloaded !== undefined ? downloaded : null,
|
||||||
total: total !== null && total !== undefined ? total : null,
|
total: total !== null && total !== undefined ? total : null,
|
||||||
retryState: retryState || null
|
retryState: retryState || null
|
||||||
};
|
};
|
||||||
mainWindow.webContents.send('first-launch-progress', data);
|
mainWindow.webContents.send('first-launch-progress', data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = await proposeGameUpdate(existingGame, progressCallback);
|
const result = await proposeGameUpdate(existingGame, progressCallback);
|
||||||
|
|
||||||
@@ -636,94 +641,94 @@ ipcMain.handle('uninstall-game', async () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle('repair-game', async () => {
|
ipcMain.handle('repair-game', async () => {
|
||||||
try {
|
try {
|
||||||
const progressCallback = (message, percent, speed, downloaded, total, retryState) => {
|
const progressCallback = (message, percent, speed, downloaded, total, retryState) => {
|
||||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||||
const data = {
|
const data = {
|
||||||
message: message || null,
|
message: message || null,
|
||||||
percent: percent !== null && percent !== undefined ? Math.min(100, Math.max(0, percent)) : null,
|
percent: percent !== null && percent !== undefined ? Math.min(100, Math.max(0, percent)) : null,
|
||||||
speed: speed !== null && speed !== undefined ? speed : null,
|
speed: speed !== null && speed !== undefined ? speed : null,
|
||||||
downloaded: downloaded !== null && downloaded !== undefined ? downloaded : null,
|
downloaded: downloaded !== null && downloaded !== undefined ? downloaded : null,
|
||||||
total: total !== null && total !== undefined ? total : null,
|
total: total !== null && total !== undefined ? total : null,
|
||||||
retryState: retryState || null
|
retryState: retryState || null
|
||||||
};
|
};
|
||||||
mainWindow.webContents.send('progress-update', data);
|
mainWindow.webContents.send('progress-update', data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = await repairGame(progressCallback);
|
const result = await repairGame(progressCallback);
|
||||||
return result;
|
return result;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Repair error:', error);
|
console.error('Repair error:', error);
|
||||||
const errorMessage = error.message || error.toString();
|
const errorMessage = error.message || error.toString();
|
||||||
return { success: false, error: errorMessage };
|
return { success: false, error: errorMessage };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle('retry-download', async (event, retryData) => {
|
ipcMain.handle('retry-download', async (event, retryData) => {
|
||||||
try {
|
try {
|
||||||
console.log('[IPC] retry-download called with data:', retryData);
|
console.log('[IPC] retry-download called with data:', retryData);
|
||||||
|
|
||||||
// Handle null retry data gracefully
|
// Handle null retry data gracefully
|
||||||
if (!retryData || !retryData.branch || !retryData.fileName) {
|
if (!retryData || !retryData.branch || !retryData.fileName) {
|
||||||
console.log('[IPC] Invalid retry data, using defaults');
|
console.log('[IPC] Invalid retry data, using defaults');
|
||||||
retryData = {
|
retryData = {
|
||||||
branch: 'release',
|
branch: 'release',
|
||||||
fileName: '4.pwr'
|
fileName: '4.pwr'
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const progressCallback = (message, percent, speed, downloaded, total, retryState) => {
|
const progressCallback = (message, percent, speed, downloaded, total, retryState) => {
|
||||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||||
const data = {
|
const data = {
|
||||||
message: message || null,
|
message: message || null,
|
||||||
percent: percent !== null && percent !== undefined ? Math.min(100, Math.max(0, percent)) : null,
|
percent: percent !== null && percent !== undefined ? Math.min(100, Math.max(0, percent)) : null,
|
||||||
speed: speed !== null && speed !== undefined ? speed : null,
|
speed: speed !== null && speed !== undefined ? speed : null,
|
||||||
downloaded: downloaded !== null && downloaded !== undefined ? downloaded : null,
|
downloaded: downloaded !== null && downloaded !== undefined ? downloaded : null,
|
||||||
total: total !== null && total !== undefined ? total : null,
|
total: total !== null && total !== undefined ? total : null,
|
||||||
retryState: retryState || null
|
retryState: retryState || null
|
||||||
};
|
};
|
||||||
mainWindow.webContents.send('progress-update', data);
|
mainWindow.webContents.send('progress-update', data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Extract PWR download info from retryData
|
// Extract PWR download info from retryData
|
||||||
const branch = retryData.branch;
|
const branch = retryData.branch;
|
||||||
const fileName = retryData.fileName;
|
const fileName = retryData.fileName;
|
||||||
const cacheDir = retryData.cacheDir;
|
const cacheDir = retryData.cacheDir;
|
||||||
|
|
||||||
console.log(`[IPC] Retrying PWR download: branch=${branch}, fileName=${fileName}`);
|
console.log(`[IPC] Retrying PWR download: branch=${branch}, fileName=${fileName}`);
|
||||||
|
|
||||||
// Perform the retry with enhanced context
|
// Perform the retry with enhanced context
|
||||||
await retryPWRDownload(branch, fileName, progressCallback, cacheDir);
|
await retryPWRDownload(branch, fileName, progressCallback, cacheDir);
|
||||||
|
|
||||||
return { success: true };
|
return { success: true };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Retry download error:', error);
|
console.error('Retry download error:', error);
|
||||||
const errorMessage = error.message || error.toString();
|
const errorMessage = error.message || error.toString();
|
||||||
|
|
||||||
// Send error update to frontend with context
|
// Send error update to frontend with context
|
||||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||||
const data = {
|
const data = {
|
||||||
message: errorMessage,
|
message: errorMessage,
|
||||||
error: true,
|
error: true,
|
||||||
canRetry: true,
|
canRetry: true,
|
||||||
retryData: {
|
retryData: {
|
||||||
branch: retryData?.branch || 'release',
|
branch: retryData?.branch || 'release',
|
||||||
fileName: retryData?.fileName || '4.pwr',
|
fileName: retryData?.fileName || '4.pwr',
|
||||||
cacheDir: retryData?.cacheDir
|
cacheDir: retryData?.cacheDir
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
mainWindow.webContents.send('progress-update', data);
|
mainWindow.webContents.send('progress-update', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always return a proper response to prevent timeout
|
// Always return a proper response to prevent timeout
|
||||||
const errorResponse = { success: false, error: errorMessage };
|
const errorResponse = { success: false, error: errorMessage };
|
||||||
console.log('[Main] Returning error response for retry-download:', errorResponse);
|
console.log('[Main] Returning error response for retry-download:', errorResponse);
|
||||||
return errorResponse;
|
return errorResponse;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle('get-hytale-news', async () => {
|
ipcMain.handle('get-hytale-news', async () => {
|
||||||
try {
|
try {
|
||||||
@@ -747,8 +752,9 @@ ipcMain.handle('open-external', async (event, url) => {
|
|||||||
|
|
||||||
ipcMain.handle('open-game-location', async () => {
|
ipcMain.handle('open-game-location', async () => {
|
||||||
try {
|
try {
|
||||||
const { getResolvedAppDir } = require('./backend/launcher');
|
const { getResolvedAppDir, loadVersionBranch } = require('./backend/launcher');
|
||||||
const gameDir = path.join(getResolvedAppDir(), 'release', 'package', 'game');
|
const branch = loadVersionBranch();
|
||||||
|
const gameDir = path.join(getResolvedAppDir(), branch, 'package', 'game');
|
||||||
|
|
||||||
if (fs.existsSync(gameDir)) {
|
if (fs.existsSync(gameDir)) {
|
||||||
await shell.openPath(gameDir);
|
await shell.openPath(gameDir);
|
||||||
@@ -839,7 +845,7 @@ ipcMain.handle('load-settings', async () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const { getModsPath, loadInstalledMods, downloadMod, uninstallMod, toggleMod, getCurrentUuid, getAllUuidMappings, setUuidForUser, generateNewUuid, deleteUuidForUser, resetCurrentUserUuid } = require('./backend/launcher');
|
const { getModsPath, loadInstalledMods, downloadMod, uninstallMod, toggleMod, getCurrentUuid, getAllUuidMappings, setUuidForUser, generateNewUuid, deleteUuidForUser, resetCurrentUserUuid } = require('./backend/launcher');
|
||||||
const { retryPWRDownload } = require('./backend/managers/gameManager');
|
const { retryPWRDownload } = require('./backend/managers/gameManager');
|
||||||
const os = require('os');
|
const os = require('os');
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ const { contextBridge, ipcRenderer } = require('electron');
|
|||||||
|
|
||||||
contextBridge.exposeInMainWorld('electronAPI', {
|
contextBridge.exposeInMainWorld('electronAPI', {
|
||||||
launchGame: (playerName, javaPath, installPath, gpuPreference) => ipcRenderer.invoke('launch-game', playerName, javaPath, installPath, gpuPreference),
|
launchGame: (playerName, javaPath, installPath, gpuPreference) => ipcRenderer.invoke('launch-game', playerName, javaPath, installPath, gpuPreference),
|
||||||
installGame: (playerName, javaPath, installPath) => ipcRenderer.invoke('install-game', playerName, javaPath, installPath),
|
installGame: (playerName, javaPath, installPath, branch) => ipcRenderer.invoke('install-game', playerName, javaPath, installPath, branch),
|
||||||
closeWindow: () => ipcRenderer.invoke('window-close'),
|
closeWindow: () => ipcRenderer.invoke('window-close'),
|
||||||
minimizeWindow: () => ipcRenderer.invoke('window-minimize'),
|
minimizeWindow: () => ipcRenderer.invoke('window-minimize'),
|
||||||
maximizeWindow: () => ipcRenderer.invoke('window-maximize'),
|
maximizeWindow: () => ipcRenderer.invoke('window-maximize'),
|
||||||
|
|||||||
Reference in New Issue
Block a user