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 += '';
content += '';
} else {
content += '';
content += '';
if (debugLogger) debugLogger.endStep('UIManager.returnToMainMenu', {
success: true,
confirmationShown: true
});
}
}
confirmReturnToMainMenu() {
try {
const debugLogger = window.debugLogger;
if (debugLogger) debugLogger.startStep('UIManager.confirmReturnToMainMenu', {
gameRunning: this.game ? this.game.isRunning : false
});
// Stop the game engine and save
if (this.game && typeof this.game.isRunning === 'boolean') {
// if (debugLogger) debugLogger.logStep('Stopping game engine and saving');
// Handle async stop properly
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) {
}
}).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 (fallbackError) {
}
});
}
// Always show main menu regardless of game state
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) {
}
}
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');
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
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 (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 {
this.game.systems.economy.updateUI();
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
});
}
}
switchQuestType(type) {
const debugLogger = window.debugLogger;
if (debugLogger) debugLogger.startStep('UIManager.switchQuestType', {
type: 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 {
this.game.systems.questSystem.updateUI();
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
});
}
// Handle UI update events from GameEngine
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 (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
});
}
updateResourceDisplay() {
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;
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;
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;
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;
// Ensure we're using the correct energy values, not credits
const currentEnergy = Math.floor(player.attributes.energy || 0);
const maxEnergy = Math.floor(player.attributes.maxEnergy || 100);
energyElement.textContent = `${currentEnergy}/${maxEnergy}`;
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');
}
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
});
}
}
updateUI() {
const debugLogger = window.debugLogger;
if (debugLogger) debugLogger.startStep('UIManager.updateUI', {
currentTab: this.currentTab,
modalOpen: this.modalOpen
});
// Update resource display
if (debugLogger) debugLogger.logStep('Updating resource display');
this.updateResourceDisplay();
// Update tab content
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 = '
';
content += '
Game Settings
';
content += '
';
content += '
Auto-Save Settings
';
content += '
Configure how often your game automatically saves:
';
content += '
';
content += '';
content += '';
content += '
';
content += '
';
content += '';
content += '
';
content += '
';
content += '
';
content += '
Reset Options
';
content += '
';
content += '
Choose your reset option:
';
content += '
';
content += '
';
content += `
Reset Character
Reset your character to level 1 and clear progress, but keep your inventory items.
Character level and stats reset
Skills and abilities reset
Quest progress cleared
Economy reset to starting values
Inventory items preserved
Hard Reset
Completely clear ALL saved data including inventory, settings, and local storage.
Character progress and stats
Inventory and items
Quest progress
Settings and preferences
All local application data
`;
content += '
';
content += '
';
content += '';
content += '
';
content += '
';
// Force modal update with timestamp to prevent caching
const timestamp = Date.now();
this.showModal('Settings', content + ``);
}
saveAutoSaveSettings() {
const autoSaveInterval = document.getElementById('autoSaveInterval');
if (autoSaveInterval) {
const selectedInterval = autoSaveInterval.value;
localStorage.setItem('autoSaveInterval', selectedInterval);
// Update game engine auto-save if game is running
if (window.game && window.game.isRunning) {
window.game.updateAutoSaveInterval(parseInt(selectedInterval));
}
this.game.showNotification(`Auto-save interval set to ${selectedInterval} minute(s)`, 'success', 3000);
}
this.closeModal();
}
confirmResetCharacter() {
let content = '
';
content += '
Reset Character
';
content += '
Warning: This will reset your character to level 1 and clear all progress, but will keep your settings and preferences.