/**
* Galaxy Strike Online - UI Manager
* Handles all user interface interactions and updates
*/
class UIManager {
constructor(gameEngine) {
const debugLogger = window.debugLogger;
if (debugLogger) debugLogger.startStep('UIManager.constructor', {
gameEngineProvided: !!gameEngine
});
this.game = gameEngine;
// UI state
this.currentTab = 'dashboard';
this.modalOpen = false;
this.notifications = [];
// Note: setupEventListeners() called in proceedWithInitialization() to prevent duplicates
if (debugLogger) debugLogger.endStep('UIManager.constructor', {
currentTab: this.currentTab,
modalOpen: this.modalOpen,
notificationsCount: this.notifications.length,
gameEngineSet: !!this.game,
eventListenersSetup: true
});
}
async initialize() {
const debugLogger = window.debugLogger;
if (debugLogger) debugLogger.startStep('UIManager.initialize', {
currentTab: this.currentTab,
modalOpen: this.modalOpen,
notificationsCount: this.notifications.length
});
// Wait for DOM to be ready and game interface to be visible
const waitForDOM = () => {
const gameInterface = document.getElementById('gameInterface');
const navButtons = document.querySelectorAll('.nav-btn');
console.log('[UI MANAGER] DOM Check:', {
gameInterfaceExists: !!gameInterface,
gameInterfaceHidden: gameInterface?.classList.contains('hidden'),
navButtonsFound: navButtons.length,
documentReady: document.readyState
});
// Less strict condition - proceed if we have nav buttons, even if interface is still hidden
if (navButtons.length > 0) {
console.log('[UI MANAGER] Navigation buttons found, proceeding with initialization');
this.proceedWithInitialization();
} else {
console.log('[UI MANAGER] Waiting for navigation buttons...');
setTimeout(waitForDOM, 100);
}
};
// Start the DOM check
waitForDOM();
}
proceedWithInitialization() {
const debugLogger = window.debugLogger;
// Setup navigation
// if (debugLogger) debugLogger.logStep('Setting up navigation');
this.setupNavigation();
// Setup event listeners
// if (debugLogger) debugLogger.logStep('Setting up event listeners');
this.setupEventListeners();
// Setup resource display
// if (debugLogger) debugLogger.logStep('Setting up resource display');
this.setupResourceDisplay();
if (debugLogger) debugLogger.endStep('UIManager.initialize', {
currentTab: this.currentTab,
modalOpen: this.modalOpen,
notificationsCount: this.notifications.length,
navigationSetup: true,
eventListenersSetup: true,
resourceDisplaySetup: true
});
}
setupNavigation() {
const debugLogger = window.debugLogger;
if (debugLogger) debugLogger.startStep('UIManager.setupNavigation');
// Navigation setup moved to setupEventListeners to fix scope issues
if (debugLogger) debugLogger.endStep('UIManager.setupNavigation', {
success: true
});
const craftingCatButtons = document.querySelectorAll('.crafting-cat-btn');
if (debugLogger) debugLogger.logStep('Setting up crafting category navigation', {
craftingCatButtonsCount: craftingCatButtons.length
});
craftingCatButtons.forEach(btn => {
btn.addEventListener('click', (e) => {
const category = e.currentTarget.dataset.category;
if (debugLogger) debugLogger.log('Crafting category button clicked', {
buttonElement: btn.tagName,
buttonText: btn.textContent,
category: category
});
this.switchCraftingCategory(category);
});
});
if (debugLogger) debugLogger.endStep('UIManager.setupNavigation', {
craftingCatButtonsSetup: craftingCatButtons.length
});
}
setupEventListeners() {
const debugLogger = window.debugLogger;
if (debugLogger) debugLogger.startStep('UIManager.setupEventListeners');
// Setup tab navigation here to fix scope issues with endStep
const navButtons = document.querySelectorAll('.nav-btn');
console.log(`[UIManager] Found ${navButtons.length} navigation buttons`);
if (debugLogger) debugLogger.logStep('Setting up tab navigation', {
navButtonsCount: navButtons.length
});
if (navButtons.length === 0) {
console.warn('[UIManager] No navigation buttons found!');
if (debugLogger) debugLogger.logStep('No navigation buttons found');
return;
}
navButtons.forEach((btn, index) => {
console.log(`[UIManager] Setting up button ${index}:`, btn.dataset.tab, btn);
// Check if button already has a listener to prevent duplicates
if (btn.getAttribute('data-has-listener') === 'true') {
console.log(`[UIManager] Button ${btn.dataset.tab} already has listener, skipping`);
return;
}
btn.addEventListener('click', (e) => {
console.log(`[UIManager] Navigation button clicked: ${btn.dataset.tab}`, e);
const tab = btn.dataset.tab;
if (tab) {
this.switchTab(tab);
} else {
console.warn('[UIManager] Button clicked but no tab data found');
}
});
// Mark as having listener
btn.setAttribute('data-has-listener', 'true');
console.log(`[UIManager] Event listener added to button: ${btn.dataset.tab}`);
});
// Add a global fallback click handler for navigation buttons
document.addEventListener('click', (e) => {
if (e.target.classList.contains('nav-btn') || e.target.closest('.nav-btn')) {
const button = e.target.classList.contains('nav-btn') ? e.target : e.target.closest('.nav-btn');
const tab = button.dataset.tab;
if (tab && window.game && window.game.systems && window.game.systems.ui) {
console.log('[UI MANAGER] Global fallback: Navigation button clicked:', tab);
window.game.systems.ui.switchTab(tab);
}
}
});
// Set up UI update event listener from GameEngine
if (this.game) {
this.game.addEventListener('uiUpdate', (event) => {
this.handleUIUpdate(event.detail);
});
// if (debugLogger) debugLogger.logStep('UI update event listener set up');
}
// Modal controls
const modalClose = document.getElementById('modalClose');
const modalOverlay = document.getElementById('modalOverlay');
if (debugLogger) debugLogger.logStep('Setting up modal controls', {
modalCloseExists: !!modalClose,
modalOverlayExists: !!modalOverlay
});
if (modalClose) {
// Check if already has listener
if (modalClose.getAttribute('data-has-listener') === 'true') {
if (debugLogger) debugLogger.log('Modal close button already has listener, skipping');
} else {
modalClose.addEventListener('click', () => {
if (debugLogger) debugLogger.log('Modal close button clicked');
this.closeModal();
});
modalClose.setAttribute('data-has-listener', 'true');
}
}
if (modalOverlay) {
// Check if already has listener
if (modalOverlay.getAttribute('data-has-listener') === 'true') {
if (debugLogger) debugLogger.log('Modal overlay already has listener, skipping');
} else {
modalOverlay.addEventListener('click', (e) => {
if (e.target === modalOverlay) {
if (debugLogger) debugLogger.log('Modal overlay clicked - closing modal');
this.closeModal();
}
});
modalOverlay.setAttribute('data-has-listener', 'true');
}
}
// Quick action buttons
const claimOfflineBtn = document.getElementById('claimOfflineBtn');
if (claimOfflineBtn) {
// Check if already has listener
if (claimOfflineBtn.getAttribute('data-has-listener') === 'true') {
if (debugLogger) debugLogger.log('Claim offline button already has listener, skipping');
} else {
// if (debugLogger) debugLogger.logStep('Setting up claim offline rewards button');
claimOfflineBtn.addEventListener('click', () => {
if (debugLogger) debugLogger.log('Claim offline rewards button clicked');
this.game.systems.idleSystem.claimOfflineRewards();
});
claimOfflineBtn.setAttribute('data-has-listener', 'true');
}
}
const quickDungeonBtn = document.getElementById('quickDungeonBtn');
if (quickDungeonBtn) {
// if (debugLogger) debugLogger.logStep('Setting up quick dungeon button');
quickDungeonBtn.addEventListener('click', () => {
if (debugLogger) debugLogger.log('Quick dungeon button clicked', {
currentTab: this.currentTab,
targetTab: 'dungeons'
});
this.switchTab('dungeons');
});
}
// Settings and Discord buttons
const settingsBtn = document.getElementById('settingsBtn');
if (settingsBtn) {
// Check if already has listener
if (settingsBtn.getAttribute('data-has-listener') === 'true') {
if (debugLogger) debugLogger.log('Settings button already has listener, skipping');
} else {
// if (debugLogger) debugLogger.logStep('Setting up settings button');
settingsBtn.addEventListener('click', () => {
if (debugLogger) debugLogger.log('Settings button clicked');
this.showSettingsMenu();
});
settingsBtn.setAttribute('data-has-listener', 'true');
}
}
const discordBtn = document.getElementById('discordBtn');
if (discordBtn) {
// if (debugLogger) debugLogger.logStep('Setting up Discord button');
discordBtn.addEventListener('click', () => {
if (debugLogger) debugLogger.log('Discord button clicked');
this.showDiscordIntegration();
});
}
// Local Server button
const localServerBtn = document.getElementById('localServerBtn');
if (localServerBtn) {
// if (debugLogger) debugLogger.logStep('Setting up local server button');
localServerBtn.addEventListener('click', () => {
if (debugLogger) debugLogger.log('Local server button clicked');
this.showLocalServerControls();
});
}
// Return to Main Menu button
const returnToMenuBtn = document.getElementById('returnToMenuBtn');
if (returnToMenuBtn) {
// Check if button already has a listener to prevent duplicates
if (returnToMenuBtn.getAttribute('data-has-listener') === 'true') {
if (debugLogger) debugLogger.log('Return to menu button already has listener, skipping');
return;
}
// if (debugLogger) debugLogger.logStep('Setting up return to menu button');
returnToMenuBtn.addEventListener('click', () => {
if (debugLogger) debugLogger.log('Return to menu button clicked');
this.showReturnToMainMenuModal();
});
// Mark as having listener
returnToMenuBtn.setAttribute('data-has-listener', 'true');
}
// Setup sub-panel category buttons
const skillCatButtons = document.querySelectorAll('.skill-cat-btn');
if (debugLogger) debugLogger.logStep('Setting up skill category navigation', {
skillCatButtonsCount: skillCatButtons.length
});
skillCatButtons.forEach(btn => {
// Check if button already has a listener to prevent duplicates
if (btn.getAttribute('data-has-listener') === 'true') {
return;
}
btn.addEventListener('click', (e) => {
const category = btn.dataset.category;
if (debugLogger) debugLogger.log('Skill category button clicked', {
buttonElement: btn.tagName,
buttonText: btn.textContent,
category: category
});
this.switchSkillCategory(category);
});
// Mark button as having a listener
btn.setAttribute('data-has-listener', 'true');
});
const questTabButtons = document.querySelectorAll('.quest-tab-btn');
if (debugLogger) debugLogger.logStep('Setting up quest tab navigation', {
questTabButtonsCount: questTabButtons.length
});
questTabButtons.forEach(btn => {
// Check if button already has a listener to prevent duplicates
if (btn.getAttribute('data-has-listener') === 'true') {
return;
}
btn.addEventListener('click', (e) => {
const type = btn.dataset.type;
if (debugLogger) debugLogger.log('Quest tab button clicked', {
buttonElement: btn.tagName,
buttonText: btn.textContent,
type: type
});
this.switchQuestType(type);
});
// Mark button as having a listener
btn.setAttribute('data-has-listener', 'true');
});
const craftingCatButtons = document.querySelectorAll('.crafting-cat-btn');
if (debugLogger) debugLogger.logStep('Setting up crafting category navigation', {
craftingCatButtonsCount: craftingCatButtons.length
});
craftingCatButtons.forEach(btn => {
// Check if button already has a listener to prevent duplicates
if (btn.getAttribute('data-has-listener') === 'true') {
return;
}
btn.addEventListener('click', (e) => {
const category = e.currentTarget.dataset.category;
if (debugLogger) debugLogger.log('Crafting category button clicked', {
buttonElement: btn.tagName,
buttonText: btn.textContent,
category: category
});
this.switchCraftingCategory(category);
});
// Mark button as having a listener
btn.setAttribute('data-has-listener', 'true');
});
const shopCatButtons = document.querySelectorAll('.shop-cat-btn');
if (debugLogger) debugLogger.logStep('Setting up shop category navigation', {
shopCatButtonsCount: shopCatButtons.length
});
shopCatButtons.forEach(btn => {
// Check if button already has a listener to prevent duplicates
if (btn.getAttribute('data-has-listener') === 'true') {
return;
}
btn.addEventListener('click', (e) => {
const category = btn.dataset.category;
if (debugLogger) debugLogger.log('Shop category button clicked', {
buttonElement: btn.tagName,
buttonText: btn.textContent,
category: category
});
this.switchShopCategory(category);
});
// Mark button as having a listener
btn.setAttribute('data-has-listener', 'true');
});
// Keyboard shortcuts for tab switching removed
if (debugLogger) debugLogger.endStep('UIManager.setupEventListeners', {
modalControlsSetup: !!(modalClose || modalOverlay),
quickActionButtonsSetup: !!(claimOfflineBtn || quickDungeonBtn),
settingsButtonsSetup: !!(settingsBtn || discordBtn),
returnMenuButtonSetup: !!returnToMenuBtn,
navigationButtonsSetup: navButtons.length > 0,
navigationButtonsCount: navButtons.length,
skillCategoryButtonsSetup: skillCatButtons.length,
questTabButtonsSetup: questTabButtons.length,
craftingCategoryButtonsSetup: craftingCatButtons.length,
shopCategoryButtonsSetup: shopCatButtons.length
});
}
async saveGame() {
const debugLogger = window.debugLogger;
// if (debugLogger) debugLogger.startStep('UIManager.saveGame');
try {
// Show saving notification
// this.game.showNotification('Saving game...', 'info', 2000);
// Call the game engine's save method
await this.game.save();
// Show success notification
// this.game.showNotification('Game saved successfully!', 'success', 3000);
// if (debugLogger) debugLogger.endStep('UIManager.saveGame', {
// success: true
// });
} catch (error) {
// Show error notification
this.game.showNotification('Failed to save game!', 'error', 3000);
if (debugLogger) debugLogger.errorEvent(error, 'UIManager.saveGame');
}
}
showLocalServerControls() {
const debugLogger = window.debugLogger;
if (debugLogger) debugLogger.startStep('UIManager.showLocalServerControls');
// Get current server status
const serverInfo = window.localServerManager ? window.localServerManager.getServerInfo() : {
isRunning: false,
status: 'Unknown',
port: null,
url: null,
connectedClients: 0,
uptime: 0
};
let content = '
';
content += '
';
content += `
Status: ${serverInfo.status}
`;
if (serverInfo.isRunning) {
content += `
Port: ${serverInfo.port}
`;
content += `
URL: ${serverInfo.url}
`;
content += `
Connected Clients: ${serverInfo.connectedClients}
`;
content += `
Uptime: ${Math.floor(serverInfo.uptime)}s
`;
}
content += '
';
// Control buttons
content += '
';
if (serverInfo.isRunning) {
content += '';
content += ' Stop Server';
content += ' ';
content += '';
content += ' Restart Server';
content += ' ';
} else {
content += '';
content += ' Start Server';
content += ' ';
}
content += '
';
// Information section
content += '
';
content += '
The local server enables singleplayer mode when external servers are unavailable. Save data is stored locally on your computer. No internet connection required for local gameplay.
';
content += '
';
content += '
';
this.showModal('Local Server', content);
if (debugLogger) debugLogger.endStep('UIManager.showLocalServerControls', {
serverRunning: serverInfo.isRunning,
serverPort: serverInfo.port
});
}
async startLocalServer() {
const debugLogger = window.debugLogger;
if (debugLogger) debugLogger.startStep('UIManager.startLocalServer');
try {
if (!window.localServerManager) {
this.game.showNotification('Local server manager not available', 'error', 3000);
return;
}
const result = await window.localServerManager.startServer();
if (result.success) {
this.game.showNotification(`Local server started on port ${result.port}`, 'success', 3000);
this.closeModal();
// Refresh the modal to show updated status
setTimeout(() => {
this.showLocalServerControls();
}, 500);
} else {
this.game.showNotification(`Failed to start server: ${result.error}`, 'error', 3000);
}
if (debugLogger) debugLogger.endStep('UIManager.startLocalServer', {
success: result.success,
port: result.port
});
} catch (error) {
this.game.showNotification('Error starting local server', 'error', 3000);
if (debugLogger) debugLogger.errorEvent(error, 'UIManager.startLocalServer');
}
}
async stopLocalServer() {
const debugLogger = window.debugLogger;
if (debugLogger) debugLogger.startStep('UIManager.stopLocalServer');
try {
if (!window.localServerManager) {
this.game.showNotification('Local server manager not available', 'error', 3000);
return;
}
const result = await window.localServerManager.stopServer();
if (result.success) {
this.game.showNotification('Local server stopped', 'success', 3000);
this.closeModal();
// Refresh the modal to show updated status
setTimeout(() => {
this.showLocalServerControls();
}, 500);
} else {
this.game.showNotification(`Failed to stop server: ${result.error}`, 'error', 3000);
}
if (debugLogger) debugLogger.endStep('UIManager.stopLocalServer', {
success: result.success
});
} catch (error) {
this.game.showNotification('Error stopping local server', 'error', 3000);
if (debugLogger) debugLogger.errorEvent(error, 'UIManager.stopLocalServer');
}
}
async restartLocalServer() {
const debugLogger = window.debugLogger;
if (debugLogger) debugLogger.startStep('UIManager.restartLocalServer');
try {
if (!window.localServerManager) {
this.game.showNotification('Local server manager not available', 'error', 3000);
return;
}
// Stop first
await this.stopLocalServer();
// Wait a moment
await new Promise(resolve => setTimeout(resolve, 1000));
// Start again
await this.startLocalServer();
if (debugLogger) debugLogger.endStep('UIManager.restartLocalServer', {
success: true
});
} catch (error) {
this.game.showNotification('Error restarting local server', 'error', 3000);
if (debugLogger) debugLogger.errorEvent(error, 'UIManager.restartLocalServer');
}
}
returnToMainMenu() {
const debugLogger = window.debugLogger;
if (debugLogger) debugLogger.startStep('UIManager.returnToMainMenu');
// Go directly to server selection without confirmation modal
this.showMainMenu();
this.closeModal();
if (debugLogger) debugLogger.endStep('UIManager.returnToMainMenu', {
success: true,
directToServerSelection: true
});
}
async stopLocalServer() {
const debugLogger = window.debugLogger;
if (debugLogger) debugLogger.startStep('UIManager.stopLocalServer');
try {
if (!window.localServerManager) {
this.game.showNotification('Local server manager not available', 'error', 3000);
return;
}
const result = await window.localServerManager.stopServer();
if (result.success) {
this.game.showNotification('Local server stopped', 'success', 3000);
this.closeModal();
// Refresh the modal to show updated status
setTimeout(() => {
this.showLocalServerControls();
}, 500);
} else {
this.game.showNotification(`Failed to stop server: ${result.error}`, 'error', 3000);
}
if (debugLogger) debugLogger.endStep('UIManager.stopLocalServer', {
success: result.success
});
} catch (error) {
this.game.showNotification('Error stopping local server', 'error', 3000);
if (debugLogger) debugLogger.errorEvent(error, 'UIManager.stopLocalServer');
}
}
async restartLocalServer() {
const debugLogger = window.debugLogger;
if (debugLogger) debugLogger.startStep('UIManager.restartLocalServer');
try {
if (!window.localServerManager) {
this.game.showNotification('Local server manager not available', 'error', 3000);
return;
}
// Stop first
await this.stopLocalServer();
// Wait a moment
await new Promise(resolve => setTimeout(resolve, 1000));
// Start again
await this.startLocalServer();
if (debugLogger) debugLogger.endStep('UIManager.restartLocalServer', {
success: true
});
} catch (error) {
this.game.showNotification('Error restarting local server', 'error', 3000);
if (debugLogger) debugLogger.errorEvent(error, 'UIManager.restartLocalServer');
}
}
showReturnToMainMenuModal() {
const debugLogger = window.debugLogger;
// Show confirmation modal instead of browser confirm dialog
let content = '';
content += '
Are you sure you want to return to the main menu?
';
content += '
Warning: Any unsaved progress will be lost.
';
content += '
';
// Check if using fallback GameEngine
if (window.game && window.game.isFallback) {
content += 'Return to Menu ';
content += 'Cancel ';
} else {
content += 'Return to Menu ';
content += 'Cancel ';
}
content += '
';
content += '
';
this.showModal('Return to Main Menu', content);
if (debugLogger) debugLogger.endStep('UIManager.returnToMainMenu', {
success: true,
confirmationShown: true
});
}
async confirmReturnToMainMenu() {
try {
const debugLogger = window.debugLogger;
// Reset multiplayer mode when returning to main menu
if (window.smartSaveManager) {
window.smartSaveManager.setMultiplayerMode(false);
}
// Check if we're in multiplayer mode - if so, don't save locally
const isMultiplayer = window.smartSaveManager?.isMultiplayer;
// Always stop the game and clear timers regardless of mode
this.game.isRunning = false;
// Force save before stopping in multiplayer mode
if (isMultiplayer && this.game && this.game.save) {
console.log('[UI MANAGER] Force saving game before leaving multiplayer mode');
try {
await this.game.save();
console.log('[UI MANAGER] Game saved successfully before leaving server');
} catch (error) {
console.error('[UI MANAGER] Error saving game before leaving server:', error);
}
}
// Clear game logic timer
if (this.game.gameLogicTimer) {
clearInterval(this.game.gameLogicTimer);
this.game.gameLogicTimer = null;
}
// Clear auto-save timer
if (this.game.autoSaveTimer) {
clearInterval(this.game.autoSaveTimer);
this.game.autoSaveTimer = null;
}
// Stop economy system timers
if (this.game.systems.economy) {
this.game.systems.economy.stopShopRefreshTimer();
}
if (isMultiplayer) {
console.log('[UI MANAGER] Skipping local save - returning from multiplayer mode');
// Show main menu immediately
this.showMainMenu();
this.closeModal();
if (debugLogger) debugLogger.endStep('UIManager.confirmReturnToMainMenu', {
success: true,
multiplayerMode: true,
localSaveSkipped: true,
mainMenuShown: true
});
} else {
// Handle async stop properly for singleplayer mode
this.game.stop().then(() => {
try {
// if (debugLogger) debugLogger.logStep('Game saved successfully');
this.showMainMenu();
this.closeModal();
if (debugLogger) debugLogger.endStep('UIManager.confirmReturnToMainMenu', {
success: true,
gameStopped: true,
mainMenuShown: true
});
} catch (error) {
try {
if (debugLogger) debugLogger.errorEvent('UIManager.confirmReturnToMainMenu', error, {
phase: 'game_stop_and_save'
});
// Still return to menu even if save fails
this.showMainMenu();
this.closeModal();
if (debugLogger) debugLogger.endStep('UIManager.confirmReturnToMainMenu', {
success: true,
gameStopped: true,
saveError: true,
mainMenuShown: true
});
} catch (loggerError) {
console.error('[UI MANAGER] Debug logger error:', loggerError);
}
}
}).catch(error => {
try {
if (debugLogger) debugLogger.errorEvent('UIManager.confirmReturnToMainMenu', error, {
phase: 'game_stop_and_save'
});
// Still return to menu even if save fails
this.showMainMenu();
this.closeModal();
if (debugLogger) debugLogger.endStep('UIManager.confirmReturnToMainMenu', {
success: true,
gameStopped: true,
saveError: true,
mainMenuShown: true
});
} catch (loggerError) {
console.error('[UI MANAGER] Debug logger error:', loggerError);
}
});
}
} catch (error) {
console.error('[UI MANAGER] Error in confirmReturnToMainMenu:', error);
if (debugLogger) debugLogger.errorEvent('UIManager.confirmReturnToMainMenu', error, {
phase: 'main_logic'
});
}
// Always show main menu regardless of game state
try {
setTimeout(() => {
this.showMainMenu();
this.closeModal();
}, 5000); // 5 second delay to ensure full cleanup and menu readiness
if (debugLogger) debugLogger.endStep('UIManager.confirmReturnToMainMenu', {
success: true,
gameStopped: this.game ? !this.game.isRunning : false,
mainMenuShown: true
});
} catch (error) {
console.error('[UI MANAGER] Error during return to main menu:', error);
if (debugLogger) debugLogger.errorEvent('UIManager.confirmReturnToMainMenu', error, {
phase: 'return_to_main_menu'
});
}
}
showMainMenu() {
const debugLogger = window.debugLogger;
if (debugLogger) debugLogger.startStep('UIManager.showMainMenu');
// Disconnect from server first
if (window.gameInitializer && window.gameInitializer.socket) {
window.gameInitializer.socket.disconnect();
}
const gameInterface = document.getElementById('gameInterface');
if (gameInterface) {
gameInterface.classList.add('hidden');
// if (debugLogger) debugLogger.logStep('Game interface hidden');
} else {
if (debugLogger) debugLogger.log('Game interface element not found');
}
// Show main menu
if (window.liveMainMenu) {
// if (debugLogger) debugLogger.logStep('About to show main menu using LiveMainMenu');
try {
// Show the main menu DOM element and use LiveMainMenu to show appropriate section
const mainMenuElement = document.getElementById('mainMenu');
if (mainMenuElement) {
mainMenuElement.classList.remove('hidden');
}
// Show the server section (most appropriate for returning to menu)
if (window.liveMainMenu && typeof window.liveMainMenu.showServerSection === 'function') {
window.liveMainMenu.showServerSection();
} else {
// Fallback: manually show server section
console.warn('LiveMainMenu.showServerSection not available, using fallback');
// Ensure main menu is visible (using the already declared mainMenuElement)
if (mainMenuElement) {
mainMenuElement.classList.remove('hidden');
}
const serverSection = document.getElementById('serverSection');
const loginSection = document.getElementById('loginSection');
const serverConfirmSection = document.getElementById('serverConfirmSection');
const optionsSection = document.getElementById('optionsSection');
// Hide all sections first
if (loginSection) loginSection.classList.add('hidden');
if (serverConfirmSection) serverConfirmSection.classList.add('hidden');
if (optionsSection) optionsSection.classList.add('hidden');
// Show server section
if (serverSection) {
serverSection.classList.remove('hidden');
}
// Try to refresh server list if available
if (window.liveMainMenu && typeof window.liveMainMenu.refreshServerList === 'function') {
window.liveMainMenu.refreshServerList();
}
}
// if (debugLogger) debugLogger.logStep('LiveMainMenu showServerSection() completed successfully');
} catch (error) {
// if (debugLogger) debugLogger.logStep('Error in LiveMainMenu operations', { error: error.message });
}
// Show save section specifically for returning to menu
setTimeout(() => {
try {
// Note: LiveMainMenu doesn't have save methods, so we'll just log this
if (debugLogger) debugLogger.logStep('Save section operations skipped - LiveMainMenu doesn\'t have save methods');
} catch (error) {
if (debugLogger) debugLogger.logStep('Error in save section operations', { error: error.message });
}
}, 500);
} else if (window.mainMenu) {
// Fallback to just showing the DOM element
// if (debugLogger) debugLogger.logStep('Using fallback DOM display for main menu');
try {
const mainMenuElement = document.getElementById('mainMenu');
if (mainMenuElement) {
mainMenuElement.classList.remove('hidden');
// Also show server section in fallback mode
const serverSection = document.getElementById('serverSection');
const loginSection = document.getElementById('loginSection');
const serverConfirmSection = document.getElementById('serverConfirmSection');
const optionsSection = document.getElementById('optionsSection');
// Hide all sections first
if (loginSection) loginSection.classList.add('hidden');
if (serverConfirmSection) serverConfirmSection.classList.add('hidden');
if (optionsSection) optionsSection.classList.add('hidden');
// Show server section
if (serverSection) {
serverSection.classList.remove('hidden');
}
// if (debugLogger) debugLogger.logStep('Main menu DOM element shown via fallback with server section');
}
} catch (error) {
// if (debugLogger) debugLogger.logStep('Error in fallback main menu display', { error: error.message });
}
} else {
// Final fallback: directly manipulate DOM to show server section
console.warn('Neither LiveMainMenu nor mainMenu available, using final fallback');
try {
const mainMenuElement = document.getElementById('mainMenu');
const serverSection = document.getElementById('serverSection');
const loginSection = document.getElementById('loginSection');
const serverConfirmSection = document.getElementById('serverConfirmSection');
const optionsSection = document.getElementById('optionsSection');
const gameInterface = document.getElementById('gameInterface');
// Hide game interface
if (gameInterface) {
gameInterface.classList.add('hidden');
}
// Show main menu
if (mainMenuElement) {
mainMenuElement.classList.remove('hidden');
}
// Hide all sections first
if (loginSection) loginSection.classList.add('hidden');
if (serverConfirmSection) serverConfirmSection.classList.add('hidden');
if (optionsSection) optionsSection.classList.add('hidden');
// Show server section
if (serverSection) {
serverSection.classList.remove('hidden');
}
} catch (error) {
console.error('Error in final fallback server section display', error);
}
}
if (debugLogger) debugLogger.endStep('UIManager.showMainMenu', {
success: true,
mainMenuShown: !!window.mainMenu
});
}
// Tab management
switchTab(tabName) {
if (debugLogger) debugLogger.startStep('UIManager.switchTab', {
fromTab: this.currentTab,
toTab: tabName,
sameTab: this.currentTab === tabName
});
if (this.currentTab === tabName) {
if (debugLogger) debugLogger.log('Switching to same tab, no action needed', {
tabName: tabName
});
if (debugLogger) debugLogger.endStep('UIManager.switchTab', {
success: true,
action: 'no_change_needed',
currentTab: this.currentTab
});
return;
}
const oldTab = this.currentTab;
// Update navigation buttons
const navButtons = document.querySelectorAll('.nav-btn, .bottom-nav-btn, .nav-drawer-btn');
let navButtonsUpdated = 0;
navButtons.forEach(btn => {
const wasActive = btn.classList.contains('active');
const shouldBeActive = btn.dataset.tab === tabName;
btn.classList.toggle('active', shouldBeActive);
if (wasActive !== shouldBeActive) {
navButtonsUpdated++;
}
});
if (debugLogger) debugLogger.logStep('Navigation buttons updated', {
totalButtons: navButtons.length,
buttonsUpdated: navButtonsUpdated
});
// Update tab content
const tabContents = document.querySelectorAll('.tab-content');
let tabContentsUpdated = 0;
tabContents.forEach(content => {
const wasActive = content.classList.contains('active');
const shouldBeActive = content.id === `${tabName}-tab`;
content.classList.toggle('active', shouldBeActive);
if (wasActive !== shouldBeActive) {
tabContentsUpdated++;
}
});
if (debugLogger) debugLogger.logStep('Tab contents updated', {
totalContents: tabContents.length,
contentsUpdated: tabContentsUpdated
});
this.currentTab = tabName;
this.game.state.currentTab = tabName;
if (debugLogger) debugLogger.logStep('Tab state updated', {
oldTab: oldTab,
newTab: this.currentTab,
gameStateUpdated: true
});
// Update specific tab content only if in multiplayer mode or game is actively running
if (this.shouldUpdateUI()) {
this.updateTabContent(tabName);
}
if (debugLogger) debugLogger.endStep('UIManager.switchTab', {
success: true,
oldTab: oldTab,
newTab: this.currentTab,
navButtonsUpdated: navButtonsUpdated,
tabContentsUpdated: tabContentsUpdated,
tabContentUpdated: true
});
}
updateTabContent(tabName) {
if (!this.shouldUpdateUI()) {
return;
}
if (debugLogger) debugLogger.startStep('UIManager.updateTabContent', {
tabName: tabName,
currentTab: this.currentTab
});
let contentUpdated = false;
let updateError = null;
try {
switch(tabName) {
case 'dashboard':
// if (debugLogger) debugLogger.logStep('Updating dashboard tab content');
// Dashboard is the default view, no additional content to update
contentUpdated = true;
break;
case 'dungeons':
// if (debugLogger) debugLogger.logStep('Updating dungeons tab content');
// Ensure dungeon list is generated
if (window.game && window.game.systems && window.game.systems.dungeonSystem) {
// if (debugLogger) debugLogger.logStep('Ensuring dungeon list is generated...');
try {
window.game.systems.dungeonSystem.generateDungeonList();
} catch (error) {
if (debugLogger) debugLogger.errorEvent('UIManager.updateTabContent', error, {
tabName: tabName
});
}
}
// Only regenerate dungeon list if it's empty (first time load)
const dungeonListElement = document.getElementById('dungeonList');
if (dungeonListElement && dungeonListElement.children.length === 0) {
if (this.game && this.game.systems && this.game.systems.dungeonSystem) {
this.game.systems.dungeonSystem.generateDungeonList();
} else {
if (debugLogger) debugLogger.log('Dungeon system not available');
}
}
contentUpdated = true;
break;
case 'skills':
// if (debugLogger) debugLogger.logStep('Updating skills tab content');
if (this.game && this.game.systems && this.game.systems.skillSystem) {
this.game.systems.skillSystem.updateUI();
} else {
if (debugLogger) debugLogger.log('Skill system not available');
}
contentUpdated = true;
break;
case 'base':
// if (debugLogger) debugLogger.logStep('Updating base tab content');
if (this.game && this.game.systems && this.game.systems.baseSystem) {
this.game.systems.baseSystem.updateUI();
} else {
if (debugLogger) debugLogger.log('Base system not available');
}
contentUpdated = true;
break;
case 'quests':
// if (debugLogger) debugLogger.logStep('Updating quests tab content');
if (this.game && this.game.systems && this.game.systems.questSystem) {
this.game.systems.questSystem.updateUI();
} else {
if (debugLogger) debugLogger.log('Quest system not available');
}
contentUpdated = true;
break;
case 'inventory':
// if (debugLogger) debugLogger.logStep('Updating inventory tab content');
if (this.game && this.game.systems && this.game.systems.inventory) {
this.game.systems.inventory.updateUI();
} else {
if (debugLogger) debugLogger.log('Inventory system not available');
}
contentUpdated = true;
break;
case 'shop':
// if (debugLogger) debugLogger.logStep('Updating shop tab content');
if (this.game && this.game.systems && this.game.systems.economy) {
this.game.systems.economy.updateUI();
} else {
if (debugLogger) debugLogger.log('Economy system not available');
}
contentUpdated = true;
break;
case 'crafting':
// if (debugLogger) debugLogger.logStep('Updating crafting tab content');
if (this.game && this.game.systems && this.game.systems.crafting) {
this.game.systems.crafting.updateUI();
} else {
if (debugLogger) debugLogger.log('Crafting system not available');
}
contentUpdated = true;
break;
default:
// if (debugLogger) debugLogger.log('Unknown tab name, no content updated', {
// tabName: tabName
// });
contentUpdated = false;
}
} catch (error) {
updateError = error;
if (debugLogger) debugLogger.errorEvent('UIManager.updateTabContent', error, {
tabName: tabName
});
}
if (debugLogger) debugLogger.endStep('UIManager.updateTabContent', {
tabName: tabName,
contentUpdated: contentUpdated,
updateError: updateError ? updateError.message : null
});
}
// Category switching
switchSkillCategory(category) {
const debugLogger = window.debugLogger;
if (debugLogger) debugLogger.startStep('UIManager.switchSkillCategory', {
category: category
});
const skillCatButtons = document.querySelectorAll('.skill-cat-btn');
let buttonsUpdated = 0;
skillCatButtons.forEach(btn => {
const wasActive = btn.classList.contains('active');
const shouldBeActive = btn.dataset.category === category;
btn.classList.toggle('active', shouldBeActive);
if (wasActive !== shouldBeActive) {
buttonsUpdated++;
}
});
if (debugLogger) debugLogger.logStep('Skill category buttons updated', {
totalButtons: skillCatButtons.length,
buttonsUpdated: buttonsUpdated
});
try {
this.game.systems.skillSystem.updateUI();
if (debugLogger) debugLogger.endStep('UIManager.switchSkillCategory', {
success: true,
category: category,
buttonsUpdated: buttonsUpdated,
skillUIUpdated: true
});
} catch (error) {
if (debugLogger) debugLogger.errorEvent('UIManager.switchSkillCategory', error, {
category: category
});
if (debugLogger) debugLogger.endStep('UIManager.switchSkillCategory', {
success: false,
category: category,
error: error.message
});
}
}
switchShopCategory(category) {
const debugLogger = window.debugLogger;
if (debugLogger) debugLogger.startStep('UIManager.switchShopCategory', {
category: category
});
const shopCatButtons = document.querySelectorAll('.shop-cat-btn');
let buttonsUpdated = 0;
shopCatButtons.forEach(btn => {
const wasActive = btn.classList.contains('active');
const shouldBeActive = btn.dataset.category === category;
btn.classList.toggle('active', shouldBeActive);
if (wasActive !== shouldBeActive) {
buttonsUpdated++;
}
});
if (debugLogger) debugLogger.logStep('Shop category buttons updated', {
totalButtons: shopCatButtons.length,
buttonsUpdated: buttonsUpdated
});
try {
// Call economy system update
this.game.systems.economy.updateUI();
// Also call global shop display function for additional debugging
if (typeof updateShopDisplay === 'function') {
updateShopDisplay();
}
if (debugLogger) debugLogger.endStep('UIManager.switchShopCategory', {
success: true,
category: category,
buttonsUpdated: buttonsUpdated,
economyUIUpdated: true
});
} catch (error) {
if (debugLogger) debugLogger.errorEvent('UIManager.switchShopCategory', error, {
category: category
});
if (debugLogger) debugLogger.endStep('UIManager.switchShopCategory', {
success: false,
category: category,
error: error.message
});
}
}
updateQuestTabs(type) {
const questTabButtons = document.querySelectorAll('.quest-tab-btn');
let buttonsUpdated = 0;
questTabButtons.forEach(btn => {
const wasActive = btn.classList.contains('active');
const shouldBeActive = btn.dataset.type === type;
btn.classList.toggle('active', shouldBeActive);
if (wasActive !== shouldBeActive) {
buttonsUpdated++;
}
});
if (debugLogger) debugLogger.logStep('Quest tab buttons updated', {
totalButtons: questTabButtons.length,
buttonsUpdated: buttonsUpdated
});
try {
// REMOVED: Client-side QuestSystem is now server-driven
// this.game.systems.questSystem.updateUI();
// Call the global quest display update function instead
if (typeof updateQuestDisplay === 'function') {
updateQuestDisplay();
}
if (debugLogger) debugLogger.endStep('UIManager.switchQuestType', {
success: true,
type: type,
buttonsUpdated: buttonsUpdated,
questUIUpdated: true
});
} catch (error) {
if (debugLogger) debugLogger.errorEvent('UIManager.switchQuestType', error, {
type: type
});
if (debugLogger) debugLogger.endStep('UIManager.switchQuestType', {
success: false,
type: type,
error: error.message
});
}
}
switchCraftingCategory(category) {
const debugLogger = window.debugLogger;
if (debugLogger) debugLogger.startStep('UIManager.switchCraftingCategory', {
category: category
});
const craftingCatButtons = document.querySelectorAll('.crafting-cat-btn');
let buttonsUpdated = 0;
craftingCatButtons.forEach(btn => {
const wasActive = btn.classList.contains('active');
const shouldBeActive = btn.dataset.category === category;
btn.classList.toggle('active', shouldBeActive);
if (wasActive !== shouldBeActive) {
buttonsUpdated++;
}
});
if (debugLogger) debugLogger.logStep('Crafting category buttons updated', {
totalButtons: craftingCatButtons.length,
buttonsUpdated: buttonsUpdated
});
try {
this.game.systems.crafting.switchCategory(category);
if (debugLogger) debugLogger.endStep('UIManager.switchCraftingCategory', {
success: true,
category: category,
buttonsUpdated: buttonsUpdated,
craftingUIUpdated: true
});
} catch (error) {
if (debugLogger) debugLogger.errorEvent('UIManager.switchCraftingCategory', error, {
category: category
});
if (debugLogger) debugLogger.endStep('UIManager.switchCraftingCategory', {
success: false,
category: category,
error: error.message
});
}
}
// Modal management
showModal(title, content) {
const debugLogger = window.debugLogger;
if (debugLogger) debugLogger.startStep('UIManager.showModal', {
title: title,
contentLength: content.length,
modalWasOpen: this.modalOpen
});
const modalOverlay = document.getElementById('modalOverlay');
const modalTitle = document.getElementById('modalTitle');
const modalBody = document.getElementById('modalBody');
if (!modalOverlay || !modalTitle || !modalBody) {
const missingElements = {
modalOverlay: !modalOverlay,
modalTitle: !modalTitle,
modalBody: !modalBody
};
if (debugLogger) debugLogger.endStep('UIManager.showModal', {
success: false,
reason: 'missing_modal_elements',
missingElements: missingElements
});
return;
}
const oldTitle = modalTitle.textContent;
const oldContent = modalBody.innerHTML;
modalTitle.textContent = title;
modalBody.innerHTML = content;
modalOverlay.classList.remove('hidden');
this.modalOpen = true;
if (debugLogger) debugLogger.endStep('UIManager.showModal', {
success: true,
title: title,
contentLength: content.length,
oldTitle: oldTitle,
oldContentLength: oldContent.length,
modalNowOpen: true
});
}
closeModal() {
const debugLogger = window.debugLogger;
if (debugLogger) debugLogger.startStep('UIManager.closeModal', {
modalWasOpen: this.modalOpen
});
const modalOverlay = document.getElementById('modalOverlay');
if (modalOverlay) {
const wasHidden = modalOverlay.classList.contains('hidden');
modalOverlay.classList.add('hidden');
if (debugLogger) debugLogger.logStep('Modal overlay hidden', {
wasAlreadyHidden: wasHidden
});
} else {
if (debugLogger) debugLogger.log('Modal overlay element not found');
}
const wasModalOpen = this.modalOpen;
this.modalOpen = false;
if (debugLogger) debugLogger.endStep('UIManager.closeModal', {
success: true,
modalOverlayFound: !!modalOverlay,
wasModalOpen: wasModalOpen,
modalNowClosed: !this.modalOpen
});
}
// Force refresh all UI elements (called when server data is updated)
forceRefreshAllUI() {
if (window.smartSaveManager?.isMultiplayer) {
console.log('[UI MANAGER] Force refreshing all UI elements with server data');
// Update all resource displays
this.updateResourceDisplay();
// Update current tab content
if (this.currentTab) {
this.updateTabContent(this.currentTab);
}
// Update quest system
if (this.game && this.game.systems && this.game.systems.questSystem) {
this.game.systems.questSystem.updateUI();
}
console.log('[UI MANAGER] UI refresh completed');
}
}
// Handle UI update events from game engine
handleUIUpdate(data) {
const debugLogger = window.debugLogger;
if (debugLogger) debugLogger.startStep('UIManager.handleUIUpdate', data);
if (debugLogger) debugLogger.log('Handling UI update event:', data);
switch (data.type) {
case 'full':
this.updateAllUI();
break;
case 'economy':
this.updateResourceDisplay();
break;
case 'player':
this.updateResourceDisplay();
break;
case 'quests':
if (this.game && this.game.systems && this.game.systems.questSystem) {
this.game.systems.questSystem.updateUI();
}
break;
case 'dailyCountdown':
if (this.game && this.game.systems && this.game.systems.questSystem) {
this.game.systems.questSystem.updateDailyCountdown();
}
break;
case 'weeklyCountdown':
if (this.game && this.game.systems && this.game.systems.questSystem) {
this.game.systems.questSystem.updateWeeklyCountdown();
}
break;
default:
if (debugLogger) debugLogger.log('Unknown update type:', data.type);
}
if (debugLogger) debugLogger.endStep('UIManager.handleUIUpdate', {
type: data.type,
handled: true
});
}
updateAllUI() {
if (!this.shouldUpdateUI()) {
return;
}
// if (debugLogger) debugLogger.log('Updating all UI elements');
this.updateResourceDisplay();
// Update other UI components as needed
if (this.game && this.game.systems) {
// Update quest system
if (this.game.systems.questSystem) {
this.game.systems.questSystem.updateUI();
}
// Update daily countdown
if (this.game.systems.questSystem) {
this.game.systems.questSystem.updateDailyCountdown();
this.game.systems.questSystem.updateWeeklyCountdown();
}
}
// if (debugLogger) debugLogger.log('All UI elements updated');
}
// Resource display
setupResourceDisplay() {
const debugLogger = window.debugLogger;
if (debugLogger) debugLogger.startStep('UIManager.setupResourceDisplay');
// Resource display is handled in updateResourceDisplay method
if (debugLogger) debugLogger.endStep('UIManager.setupResourceDisplay', {
setupCompleted: true
});
}
// Centralized UI update control - blocks all UI updates when not in multiplayer mode
shouldUpdateUI() {
const shouldUpdate = window.smartSaveManager?.isMultiplayer || this.game?.isRunning;
if (!shouldUpdate) {
console.log('[UI MANAGER] Blocking UI update - not in multiplayer mode');
return false;
}
return true;
}
// Centralized update resource display - all calls should go through this
updateResourceDisplay() {
if (!this.shouldUpdateUI()) {
return;
}
// In multiplayer mode, ensure we're using server data
if (window.smartSaveManager?.isMultiplayer) {
// console.log('[UI MANAGER] Updating resource display in multiplayer mode - using server data');
}
// const debugLogger = window.debugLogger;
try {
// Safety checks - return early if systems aren't available
if (!this.game || !this.game.systems) {
// if (debugLogger) debugLogger.log('Game systems not available, skipping resource display update');
return;
}
if (!this.game.systems.player || !this.game.systems.economy) {
// if (debugLogger) debugLogger.log('Player or economy system not available, skipping resource display update');
return;
}
const player = this.game.systems.player;
const economy = this.game.systems.economy;
// Additional safety checks for player properties
if (!player.stats || !player.attributes || !player.ship) {
// if (debugLogger) debugLogger.log('Player properties not fully initialized, skipping resource display update');
return;
}
// if (debugLogger) debugLogger.startStep('UIManager.updateResourceDisplay', {
// gameSystemsAvailable: !!(this.game && this.game.systems),
// playerSystemAvailable: !!(this.game && this.game.systems && this.game.systems.player),
// economySystemAvailable: !!(this.game && this.game.systems && this.game.systems.economy),
// playerStatsAvailable: !!player.stats,
// playerAttributesAvailable: !!player.attributes,
// playerShipAvailable: !!player.ship
// });
let elementsUpdated = 0;
let elementsNotFound = 0;
// Update player level with safety checks
const playerLevelElement = document.getElementById('playerLevel');
if (playerLevelElement) {
const oldLevel = playerLevelElement.textContent;
const playerLevel = player.stats.level || 1;
// console.log('[UI MANAGER] Updating player level:', { oldLevel, newLevel: playerLevel, playerStats: player.stats });
playerLevelElement.textContent = `Lv. ${playerLevel}`;
elementsUpdated++;
if (debugLogger) debugLogger.logStep('Player level updated', {
oldLevel: oldLevel,
newLevel: playerLevelElement.textContent,
playerStatsLevel: player.stats.level
});
} else {
elementsNotFound++;
// if (debugLogger) debugLogger.log('Player level element not found');
}
// Update ship level with safety checks
const shipLevelElement = document.getElementById('currentShipLevel');
if (shipLevelElement) {
const oldShipLevel = shipLevelElement.textContent;
const shipLevel = player.ship.level || player.stats.level || 1;
shipLevelElement.textContent = shipLevel;
elementsUpdated++;
if (debugLogger) debugLogger.logStep('Ship level updated', {
oldShipLevel: oldShipLevel,
newShipLevel: shipLevelElement.textContent,
playerShipLevel: player.ship.level,
playerStatsLevel: player.stats.level
});
} else {
elementsNotFound++;
if (debugLogger) debugLogger.log('Ship level element not found');
}
// Update credits with safety checks
const creditsElement = document.getElementById('credits');
if (creditsElement) {
const oldCredits = creditsElement.textContent;
const creditsAmount = economy.credits || 0;
if (oldCredits !== this.game.formatNumber(creditsAmount)) {
console.log('[UI MANAGER] Credits updated:', this.game.formatNumber(creditsAmount));
}
creditsElement.textContent = this.game.formatNumber(creditsAmount);
elementsUpdated++;
if (debugLogger) debugLogger.logStep('Credits updated', {
oldCredits: oldCredits,
newCredits: creditsElement.textContent,
economyCredits: economy.credits,
formattedCredits: this.game.formatNumber(creditsAmount)
});
} else {
elementsNotFound++;
if (debugLogger) debugLogger.log('Credits element not found');
}
// Update gems with safety checks
const gemsElement = document.getElementById('gems');
if (gemsElement) {
const oldGems = gemsElement.textContent;
const gemsAmount = economy.gems || 0;
if (oldGems !== this.game.formatNumber(gemsAmount)) {
console.log('[UI MANAGER] Gems updated:', this.game.formatNumber(gemsAmount));
}
gemsElement.textContent = this.game.formatNumber(gemsAmount);
elementsUpdated++;
if (debugLogger) debugLogger.logStep('Gems updated', {
oldGems: oldGems,
newGems: gemsElement.textContent,
economyGems: economy.gems,
formattedGems: this.game.formatNumber(gemsAmount)
});
} else {
elementsNotFound++;
if (debugLogger) debugLogger.log('Gems element not found');
}
// Update energy with safety checks
const energyElement = document.getElementById('energy');
if (energyElement) {
const oldEnergy = energyElement.textContent;
const currentEnergy = player.attributes.currentEnergy || player.attributes.energy || 0;
const maxEnergy = player.attributes.maxEnergy || 100;
const newEnergy = `${currentEnergy}/${maxEnergy}`;
if (oldEnergy !== newEnergy) {
console.log('[UI MANAGER] Energy updated:', newEnergy);
}
energyElement.textContent = newEnergy;
elementsUpdated++;
if (debugLogger) debugLogger.logStep('Energy updated', {
oldEnergy: oldEnergy,
newEnergy: energyElement.textContent,
currentEnergy: currentEnergy,
maxEnergy: maxEnergy,
playerEnergy: player.attributes.energy,
playerMaxEnergy: player.attributes.maxEnergy
});
} else {
elementsNotFound++;
if (debugLogger) debugLogger.log('Energy element not found');
}
// Update play time (keep this here as it's part of the core resource display)
const playTimeElement = document.getElementById('playTime');
if (playTimeElement) {
const playTimeMs = player.stats.playTime || 0;
playTimeElement.textContent = this.formatPlayTime(playTimeMs);
elementsUpdated++;
}
// Update player stats panel
const playerLevelDisplayElement = document.getElementById('playerLevelDisplay');
if (playerLevelDisplayElement) {
playerLevelDisplayElement.textContent = player.stats.level || 1;
elementsUpdated++;
}
const playerXPElement = document.getElementById('playerXP');
if (playerXPElement) {
const currentXP = player.stats.experience || 0;
const xpToNext = player.stats.experienceToNext || 100;
playerXPElement.textContent = `${currentXP} / ${xpToNext}`;
elementsUpdated++;
}
const skillPointsElement = document.getElementById('skillPoints');
if (skillPointsElement) {
skillPointsElement.textContent = player.stats.skillPoints || 0;
elementsUpdated++;
}
const totalXPElement = document.getElementById('totalXP');
if (totalXPElement) {
totalXPElement.textContent = this.game.formatNumber(player.stats.totalXP || 0);
elementsUpdated++;
}
const questsCompletedElement = document.getElementById('questsCompleted');
if (questsCompletedElement) {
// Use player stats from server first, then quest system stats as fallback
const questsCompleted = player.stats.questsCompleted ||
(this.game.systems.questSystem?.stats?.questsCompleted) || 0;
questsCompletedElement.textContent = questsCompleted;
elementsUpdated++;
}
const lastLoginElement = document.getElementById('lastLogin');
if (lastLoginElement) {
const lastLogin = player.stats.lastLogin;
if (lastLogin) {
const loginDate = new Date(lastLogin);
lastLoginElement.textContent = loginDate.toLocaleDateString() + ' ' + loginDate.toLocaleTimeString();
} else {
lastLoginElement.textContent = 'Never';
}
elementsUpdated++;
}
// Update all player stats
this.updatePlayerStats();
if (debugLogger) debugLogger.endStep('UIManager.updateResourceDisplay', {
elementsUpdated: elementsUpdated,
elementsNotFound: elementsNotFound,
playerLevel: player.stats.level || 1,
shipLevel: player.ship.level || player.stats.level || 1,
credits: economy.credits || 0,
gems: economy.gems || 0,
currentEnergy: Math.floor(player.attributes.energy || 0),
maxEnergy: Math.floor(player.attributes.maxEnergy || 100)
});
} catch (error) {
if (debugLogger) debugLogger.log('Error in updateResourceDisplay', {
error: error.message,
stack: error.stack
});
}
}
formatPlayTime(milliseconds) {
// Format play time showing only the two most relevant units
const totalSeconds = Math.floor(milliseconds / 1000);
if (totalSeconds < 60) {
// Less than 1 minute: show seconds only
return `${totalSeconds}s`;
} else if (totalSeconds < 3600) {
// Less than 1 hour: show minutes and seconds
const minutes = Math.floor(totalSeconds / 60);
const seconds = totalSeconds % 60;
return `${minutes}m ${seconds}s`;
} else if (totalSeconds < 86400) {
// Less than 1 day: show hours and minutes
const hours = Math.floor(totalSeconds / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
return `${hours}h ${minutes}m`;
} else {
// 1 day or more: show days and hours
const days = Math.floor(totalSeconds / 86400);
const hours = Math.floor((totalSeconds % 86400) / 3600);
return `${days}d ${hours}h`;
}
}
updatePlayerStats() {
// Update just the player stats panel (excluding those handled in updateResourceDisplay)
if (!this.game || !this.game.systems || !this.game.systems.player) {
return;
}
const player = this.game.systems.player;
let elementsUpdated = 0;
// Update player stats panel
const playerLevelDisplayElement = document.getElementById('playerLevelDisplay');
if (playerLevelDisplayElement) {
playerLevelDisplayElement.textContent = player.stats.level || 1;
elementsUpdated++;
}
const playerXPElement = document.getElementById('playerXP');
if (playerXPElement) {
const currentXP = player.stats.experience || 0;
const xpToNext = player.stats.experienceToNext || 100;
playerXPElement.textContent = `${currentXP} / ${xpToNext}`;
elementsUpdated++;
}
const skillPointsElement = document.getElementById('skillPoints');
if (skillPointsElement) {
skillPointsElement.textContent = player.stats.skillPoints || 0;
elementsUpdated++;
}
const totalXPElement = document.getElementById('totalXP');
if (totalXPElement) {
totalXPElement.textContent = this.game.formatNumber(player.stats.totalXP || 0);
elementsUpdated++;
}
const questsCompletedElement = document.getElementById('questsCompleted');
if (questsCompletedElement) {
// Use player stats from server first, then quest system stats as fallback
const questsCompleted = player.stats.questsCompleted ||
(this.game.systems.questSystem?.stats?.questsCompleted) || 0;
questsCompletedElement.textContent = questsCompleted;
elementsUpdated++;
}
const lastLoginElement = document.getElementById('lastLogin');
if (lastLoginElement) {
const lastLogin = player.stats.lastLogin;
if (lastLogin) {
const loginDate = new Date(lastLogin);
lastLoginElement.textContent = loginDate.toLocaleDateString() + ' ' + loginDate.toLocaleTimeString();
} else {
lastLoginElement.textContent = 'Never';
}
elementsUpdated++;
}
// Update stats moved from Idle Progress card
const totalKillsElement = document.getElementById('totalKills');
if (totalKillsElement) {
totalKillsElement.textContent = this.game.formatNumber(player.stats.totalKills || 0);
elementsUpdated++;
}
const dungeonsClearedElement = document.getElementById('dungeonsCleared');
if (dungeonsClearedElement) {
dungeonsClearedElement.textContent = player.stats.dungeonsCleared || 0;
elementsUpdated++;
}
// DISABLED: Reduce console spam for quest debugging
// console.log(`[UI MANAGER] Player stats updated: ${elementsUpdated} elements`);
}
updateUI() {
// const debugLogger = window.debugLogger;
// if (debugLogger) debugLogger.startStep('UIManager.updateUI', {
// currentTab: this.currentTab,
// modalOpen: this.modalOpen
// });
// Update resource display only if in multiplayer mode or game is actively running
if (this.shouldUpdateUI()) {
// if (debugLogger) debugLogger.logStep('Updating resource display');
this.updateResourceDisplay();
}
// Update tab content only if in multiplayer mode or game is actively running
if (this.shouldUpdateUI()) {
// if (debugLogger) debugLogger.logStep('Updating tab content', {
// currentTab: this.currentTab
// });
this.updateTabContent(this.currentTab);
}
// if (debugLogger) debugLogger.endStep('UIManager.updateUI', {
// resourceDisplayUpdated: true,
// tabContentUpdated: true,
// currentTab: this.currentTab
// });
}
// Menus
showSettingsMenu() {
// Clear any existing modal content first
const modalBody = document.getElementById('modalBody');
if (modalBody) {
modalBody.innerHTML = '';
}
// Get current auto-save setting
const currentAutoSaveInterval = localStorage.getItem('autoSaveInterval') || '5';
let content = '