API/Client/js/main.js

719 lines
30 KiB
JavaScript

/**
* Galaxy Strike Online - Main Entry Point
* Initializes and starts the game
*/
console.log('[MAIN] main.js script loaded');
// Wait for DOM to be loaded
document.addEventListener('DOMContentLoaded', async () => {
const debugLogger = window.debugLogger;
if (debugLogger) debugLogger.startStep('main.domContentLoaded', {
timestamp: new Date().toISOString(),
userAgent: navigator.userAgent,
url: window.location.href
});
const loadingIndicator = document.getElementById('loadingIndicator');
const loadingStatus = document.getElementById('loadingStatus');
if (debugLogger) debugLogger.logStep('DOM elements found', {
loadingIndicator: !!loadingIndicator,
loadingStatus: !!loadingStatus
});
try {
// Start debug logging
if (window.debugLogger) {
window.debugLogger.startStep('domLoad');
window.debugLogger.logStep('DOM loaded, starting initialization');
}
// Show loading indicator
if (loadingIndicator) loadingIndicator.classList.remove('hidden');
if (loadingStatus) {
loadingStatus.textContent = 'Initializing application...';
loadingStatus.classList.remove('hidden');
}
if (debugLogger) debugLogger.logStep('Loading indicator shown');
// Initialize title bar controls immediately (don't wait for DOMContentLoaded)
console.log('[MAIN] Initializing title bar controls immediately');
if (debugLogger) debugLogger.logStep('Initializing title bar controls');
initializeTitleBar();
// Wait for DOM to be ready
document.addEventListener('DOMContentLoaded', async () => {
if (debugLogger) debugLogger.startStep('main.secondDOMContentLoaded', {
timestamp: new Date().toISOString()
});
window.debugLogger.startStep('domLoad');
window.debugLogger.logStep('DOM loaded, starting initialization');
// Auto-start local server for singleplayer mode (DISABLED to prevent auto-start after multiplayer disconnect)
console.log('[MAIN] Skipping local server auto-start to prevent conflicts with multiplayer mode');
/*
if (window.localServerManager) {
try {
const serverResult = await window.localServerManager.autoStartIfSingleplayer();
if (serverResult.success) {
console.log('[MAIN] Local server started successfully:', serverResult);
if (debugLogger) debugLogger.logStep('Local server auto-started', {
port: serverResult.port,
url: serverResult.url
});
} else {
console.log('[MAIN] Local server not started:', serverResult.reason || serverResult.error);
if (debugLogger) debugLogger.logStep('Local server not started', {
reason: serverResult.reason || serverResult.error
});
}
} catch (error) {
console.error('[MAIN] Error starting local server:', error);
if (debugLogger) debugLogger.errorEvent(error, 'Local server startup');
}
} else {
console.warn('[MAIN] LocalServerManager not available');
}
*/
// Title bar is already initialized, just log it
console.log('[MAIN] DOM loaded - title bar should already be working');
if (debugLogger) debugLogger.logStep('DOM loaded - title bar should be working');
// Show main menu instead of directly loading game
if (loadingStatus) {
loadingStatus.textContent = 'Ready';
loadingStatus.classList.add('hidden');
}
if (debugLogger) debugLogger.logStep('Loading status updated to Ready');
// Hide loading screen and show main menu
const loadingScreen = document.getElementById('loadingScreen');
const mainMenu = document.getElementById('mainMenu');
if (loadingScreen) loadingScreen.classList.add('hidden');
if (mainMenu) mainMenu.classList.remove('hidden');
if (debugLogger) debugLogger.logStep('Loading screen hidden, main menu shown', {
loadingScreenFound: !!loadingScreen,
mainMenuFound: !!mainMenu,
liveMainMenuReady: !!window.liveMainMenu
});
// The LiveMainMenu will initialize itself and handle authentication
console.log('[MAIN] Main menu displayed - LiveMainMenu will handle authentication and server browsing');
if (debugLogger) debugLogger.endStep('main.secondDOMContentLoaded', {
success: true,
mainMenuDisplayed: !!mainMenu
});
});
if (debugLogger) debugLogger.endStep('main.domContentLoaded', {
success: true,
titleBarInitialized: true
});
} catch (error) {
console.error('Failed to initialize game:', error);
if (debugLogger) debugLogger.errorEvent('main.domContentLoaded', error, {
phase: 'initialization',
timestamp: new Date().toISOString()
});
if (window.debugLogger) {
window.debugLogger.log('CRITICAL ERROR: Initialization failed', {
error: error.message,
stack: error.stack,
timestamp: new Date().toISOString()
});
}
// Show error state
if (loadingIndicator) loadingIndicator.classList.add('error');
if (loadingStatus) {
loadingStatus.textContent = 'Failed to load application';
loadingStatus.classList.add('error');
}
if (debugLogger) debugLogger.logStep('Error state displayed');
const logger = window.logger;
if (logger) {
await logger.errorEvent(error, 'Main.js Initialization');
}
if (debugLogger) debugLogger.endStep('main.domContentLoaded', {
success: false,
error: error.message
});
}
});
// Initialize title bar controls
function initializeTitleBar() {
const debugLogger = window.debugLogger;
if (debugLogger) debugLogger.startStep('main.initializeTitleBar', {
timestamp: new Date().toISOString(),
electronAPIAvailable: !!window.electronAPI
});
console.log('[TITLE BAR] Starting title bar initialization');
// Wait for both electronAPI and DOM elements to be available
const checkReady = () => {
const hasElectronAPI = !!window.electronAPI;
const hasMinimizeBtn = !!document.getElementById('minimizeBtn');
const hasCloseBtn = !!document.getElementById('closeBtn');
const hasFullscreenBtn = !!document.getElementById('fullscreenBtn');
const readyState = {
hasElectronAPI,
hasMinimizeBtn,
hasCloseBtn,
hasFullscreenBtn
};
console.log(`[TITLE BAR] electronAPI: ${hasElectronAPI}, minimizeBtn: ${hasMinimizeBtn}, closeBtn: ${hasCloseBtn}, fullscreenBtn: ${hasFullscreenBtn}`);
if (debugLogger) debugLogger.logStep('Title bar readiness check', readyState);
if (hasElectronAPI && hasMinimizeBtn && hasCloseBtn && hasFullscreenBtn) {
console.log('[TITLE BAR] All elements ready, setting up events');
if (debugLogger) debugLogger.logStep('All title bar elements ready, setting up events');
setupTitleBarEvents();
// Hide the "Initializing application..." text since title bar is now working
const loadingStatus = document.getElementById('loadingStatus');
if (loadingStatus && loadingStatus.textContent === 'Initializing application...') {
console.log('[TITLE BAR] Hiding initializing text');
loadingStatus.classList.add('hidden');
if (debugLogger) debugLogger.logStep('Hiding initializing text');
}
if (debugLogger) debugLogger.endStep('main.initializeTitleBar', {
success: true,
allElementsReady: true
});
} else {
if (debugLogger) debugLogger.logStep('Not all elements ready, retrying in 50ms', {
missingElements: Object.keys(readyState).filter(key => !readyState[key])
});
setTimeout(checkReady, 50);
}
};
checkReady();
}
function setupTitleBarEvents() {
const debugLogger = window.debugLogger;
if (debugLogger) debugLogger.startStep('main.setupTitleBarEvents');
const minimizeBtn = document.getElementById('minimizeBtn');
const closeBtn = document.getElementById('closeBtn');
const fullscreenBtn = document.getElementById('fullscreenBtn');
console.log('[TITLE BAR] Setting up event listeners');
if (debugLogger) debugLogger.logStep('Title bar buttons found', {
minimizeBtn: !!minimizeBtn,
closeBtn: !!closeBtn,
fullscreenBtn: !!fullscreenBtn
});
let eventsSetup = 0;
if (minimizeBtn) {
console.log('[TITLE BAR] Adding minimize button listener');
if (debugLogger) debugLogger.logStep('Setting up minimize button listener');
minimizeBtn.addEventListener('click', (e) => {
console.log('[TITLE BAR] Minimize button clicked');
if (debugLogger) debugLogger.log('Title bar minimize button clicked');
e.preventDefault();
e.stopPropagation();
if (window.electronAPI && window.electronAPI.minimize) {
window.electronAPI.minimize();
if (debugLogger) debugLogger.logStep('Window minimized via electronAPI');
} else {
console.error('[TITLE BAR] electronAPI not available when minimize clicked');
if (debugLogger) debugLogger.log('electronAPI not available for minimize');
}
});
eventsSetup++;
} else {
console.error('[TITLE BAR] Minimize button not found during setup');
if (debugLogger) debugLogger.log('Minimize button not found');
}
if (closeBtn) {
console.log('[TITLE BAR] Adding close button listener');
if (debugLogger) debugLogger.logStep('Setting up close button listener');
closeBtn.addEventListener('click', (e) => {
console.log('[TITLE BAR] Close button clicked');
if (debugLogger) debugLogger.log('Title bar close button clicked');
e.preventDefault();
// ... rest of the code remains the same ...
e.stopPropagation();
if (window.electronAPI && window.electronAPI.closeWindow) {
window.electronAPI.closeWindow();
if (debugLogger) debugLogger.logStep('Window closed via electronAPI');
} else {
console.error('[TITLE BAR] electronAPI not available when close clicked');
if (debugLogger) debugLogger.log('electronAPI not available for close');
}
});
eventsSetup++;
} else {
console.error('[TITLE BAR] Close button not found during setup');
if (debugLogger) debugLogger.log('Close button not found');
}
if (fullscreenBtn) {
console.log('[TITLE BAR] Adding fullscreen button listener');
if (debugLogger) debugLogger.logStep('Setting up fullscreen button listener');
fullscreenBtn.addEventListener('click', (e) => {
console.log('[TITLE BAR] Fullscreen button clicked');
if (debugLogger) debugLogger.log('Title bar fullscreen button clicked');
e.preventDefault();
e.stopPropagation();
if (window.electronAPI && window.electronAPI.toggleFullscreen) {
window.electronAPI.toggleFullscreen();
if (debugLogger) debugLogger.logStep('Fullscreen toggled via electronAPI');
// Toggle fullscreen class on body
document.body.classList.toggle('fullscreen');
document.body.classList.toggle('fullscreen');
// Update icon
const icon = fullscreenBtn.querySelector('i');
if (document.body.classList.contains('fullscreen')) {
icon.className = 'fas fa-compress';
if (debugLogger) debugLogger.logStep('Fullscreen mode activated, icon changed to compress');
} else {
icon.className = 'fas fa-expand';
if (debugLogger) debugLogger.logStep('Fullscreen mode deactivated, icon changed to expand');
}
} else {
console.error('[TITLE BAR] electronAPI not available when fullscreen clicked');
if (debugLogger) debugLogger.log('electronAPI not available for fullscreen');
}
});
eventsSetup++;
} else {
console.error('[TITLE BAR] Fullscreen button not found during setup');
if (debugLogger) debugLogger.log('Fullscreen button not found');
}
console.log('[TITLE BAR] Event listeners setup complete');
if (debugLogger) debugLogger.endStep('main.setupTitleBarEvents', {
eventsSetup: eventsSetup,
totalExpectedEvents: 3
});
}
// Global utility functions for onclick handlers
window.game = null;
// Error handling
window.addEventListener('error', (event) => {
console.error('Game error:', event.error);
if (window.game) {
window.game.showNotification('An error occurred. Please refresh the page.', 'error', 5000);
}
});
// Shutdown handler for debug logging
window.addEventListener('beforeunload', async () => {
if (window.debugLogger) {
try {
await window.debugLogger.shutdown();
} catch (error) {
console.error('[MAIN] Failed to shutdown debug logger:', error);
}
}
});
// Performance monitoring
if (window.performance && window.performance.memory) {
setInterval(() => {
if (window.game && window.game.isRunning) {
const stats = window.game.getPerformanceStats();
if (stats.memory && stats.memory.used / stats.memory.limit > 0.8) {
console.warn('High memory usage detected:', stats.memory);
}
}
}, 30000); // Check every 30 seconds
}
// Global console functions
function toggleConsole() {
console.log('[DEBUG] toggleConsole called');
const consoleWindow = document.getElementById('consoleWindow');
const consoleInput = document.getElementById('consoleInput');
console.log('[DEBUG] consoleWindow element:', consoleWindow);
console.log('[DEBUG] consoleInput element:', consoleInput);
if (!consoleWindow) {
console.error('[DEBUG] consoleWindow element not found!');
return;
}
if (consoleWindow.style.display === 'flex') {
consoleWindow.style.display = 'none';
console.log('[DEBUG] Console hidden');
} else {
consoleWindow.style.display = 'flex';
console.log('[DEBUG] Console shown');
if (consoleInput) {
consoleInput.focus();
}
}
}
function handleConsoleInput(event) {
if (event.key === 'Enter') {
const input = event.target;
const command = input.value.trim();
if (command) {
executeConsoleCommand(command);
input.value = '';
}
}
}
function executeConsoleCommand(command) {
const output = document.getElementById('consoleOutput');
const commandLine = document.createElement('div');
commandLine.className = 'console-line';
commandLine.textContent = `> ${command}`;
output.appendChild(commandLine);
// Log command to file and browser console
console.log(`[CONSOLE] Command: ${command}`);
if (window.logger) {
window.logger.playerAction('Console Command', { command: command });
}
try {
const result = processCommand(command);
const resultLine = document.createElement('div');
resultLine.className = `console-line ${result.type || 'success'}`;
// Convert line breaks to HTML for proper rendering
resultLine.innerHTML = result.message.replace(/\n/g, '<br>');
output.appendChild(resultLine);
// Log result to file and browser console
const consoleMethod = result.type === 'error' ? console.error :
result.type === 'info' ? console.info : console.log;
consoleMethod(`[CONSOLE] Result (${result.type}): ${result.message.replace(/\n/g, ' ')}`);
if (window.logger) {
window.logger.playerAction('Console Result', {
command: command,
result: result.type,
message: result.message
});
}
} catch (error) {
const errorLine = document.createElement('div');
errorLine.className = 'console-line console-error';
errorLine.textContent = `Error: ${error.message}`;
output.appendChild(errorLine);
// Log error to file and browser console
console.error(`[CONSOLE] Error: ${error.message}`);
if (window.logger) {
window.logger.errorEvent(error, 'Console Command', { command: command });
}
}
// Scroll to bottom
output.scrollTop = output.scrollHeight;
}
function processCommand(command) {
const parts = command.split(' ');
const cmd = parts[0].toLowerCase();
const args = parts.slice(1);
switch (cmd) {
case 'help':
return {
type: 'info',
message: `Available commands:\nhelp - Show this help message\nclear - Clear console output\ncoins <amount> - Add coins to player (e.g., "coins 1000")\ngems <amount> - Add gems to player (e.g., "gems 100")\nresearch <amount> - Add research points (e.g., "research 500")\ncraftingxp <amount> - Add crafting experience (e.g., "craftingxp 200")\ngiveitem <item_id> <quantity> - Add item to inventory (e.g., "giveitem iron_ore 10")\nhealth <amount> - Set current ship health (e.g., "health 150")\nlevel <level> - Set current ship level (e.g., "level 5")\nunlock <ship_id> - Unlock a ship (e.g., "unlock heavy_fighter")\nstats - Show current player stats\nships - List all ships\ncurrent - Show current ship info`
};
case 'clear':
const output = document.getElementById('consoleOutput');
output.innerHTML = '';
return { type: 'success', message: 'Console cleared' };
case 'coins':
if (args.length === 0) {
return { type: 'error', message: 'Usage: coins <amount>' };
}
const amount = parseInt(args[0]);
if (isNaN(amount)) {
return { type: 'error', message: 'Invalid amount' };
}
if (window.game && window.game.systems && window.game.systems.economy) {
window.game.systems.economy.addCredits(amount, 'console');
window.game.systems.economy.updateUI();
return { type: 'success', message: `Added ${amount} credits` };
}
return { type: 'error', message: 'Economy system not available' };
case 'gems':
if (args.length === 0) {
return { type: 'error', message: 'Usage: gems <amount>' };
}
const gemAmount = parseInt(args[0]);
if (isNaN(gemAmount)) {
return { type: 'error', message: 'Invalid amount' };
}
if (window.game && window.game.systems && window.game.systems.economy) {
window.game.systems.economy.addGems(gemAmount, 'console');
window.game.systems.economy.updateUI();
return { type: 'success', message: `Added ${gemAmount} gems` };
}
return { type: 'error', message: 'Economy system not available' };
case 'research':
if (args.length === 0) {
return { type: 'error', message: 'Usage: research <amount>' };
}
const researchAmount = parseInt(args[0]);
if (isNaN(researchAmount)) {
return { type: 'error', message: 'Invalid amount' };
}
if (window.game && window.game.systems && window.game.systems.player) {
const currentSkillPoints = window.game.systems.player.stats.skillPoints || 0;
window.game.systems.player.stats.skillPoints = currentSkillPoints + researchAmount;
window.game.systems.player.updateUI();
// Also update skill system UI
if (window.game.systems.skillSystem) {
window.game.systems.skillSystem.updateUI();
}
return { type: 'success', message: `Added ${researchAmount} skill points (Total: ${window.game.systems.player.stats.skillPoints})` };
}
return { type: 'error', message: 'Player system not available' };
case 'craftingxp':
if (args.length === 0) {
return { type: 'error', message: 'Usage: craftingxp <amount>' };
}
const craftingXpAmount = parseInt(args[0]);
if (isNaN(craftingXpAmount)) {
return { type: 'error', message: 'Invalid amount' };
}
if (window.game && window.game.systems && window.game.systems.skillSystem) {
window.game.systems.skillSystem.awardCraftingExperience(craftingXpAmount);
const currentLevel = window.game.systems.skillSystem.getSkillLevel('crafting');
const currentExp = window.game.systems.skillSystem.getSkillExperience('crafting');
return { type: 'success', message: `Added ${craftingXpAmount} crafting experience (Level: ${currentLevel}, XP: ${currentExp})` };
}
return { type: 'error', message: 'Skill system not available' };
case 'giveitem':
if (args.length < 2) {
return { type: 'error', message: 'Usage: giveitem <item_id> <quantity>' };
}
const itemId = args[0];
const quantity = parseInt(args[1]);
if (isNaN(quantity)) {
return { type: 'error', message: 'Invalid quantity' };
}
if (window.game && window.game.systems && window.game.systems.inventory) {
window.game.systems.inventory.addItem(itemId, quantity);
window.game.systems.ui.updateInventory();
return { type: 'success', message: `Added ${quantity}x ${itemId} to inventory` };
}
return { type: 'error', message: 'Inventory system not available' };
case 'health':
if (args.length === 0) {
return { type: 'error', message: 'Usage: health <amount>' };
}
const healthAmount = parseInt(args[0]);
if (isNaN(healthAmount)) {
return { type: 'error', message: 'Invalid amount' };
}
if (window.game && window.game.systems && window.game.systems.ship) {
const currentShip = window.game.systems.ship.currentShip;
if (currentShip) {
currentShip.health = Math.min(healthAmount, currentShip.maxHealth);
window.game.systems.ship.updateCurrentShipDisplay();
return { type: 'success', message: `Set ship health to ${currentShip.health}/${currentShip.maxHealth}` };
}
}
return { type: 'error', message: 'Ship system not available' };
case 'level':
if (args.length === 0) {
return { type: 'error', message: 'Usage: level <level>' };
}
const levelAmount = parseInt(args[0]);
if (isNaN(levelAmount)) {
return { type: 'error', message: 'Invalid level' };
}
if (window.game && window.game.systems && window.game.systems.player) {
window.game.systems.player.stats.level = levelAmount;
window.game.systems.player.updateTitle();
window.game.systems.player.updateUI();
return { type: 'success', message: `Set player level to ${levelAmount}` };
}
return { type: 'error', message: 'Player system not available' };
case 'unlock':
if (args.length === 0) {
return { type: 'error', message: 'Usage: unlock <ship_id>' };
}
const shipId = args[0];
if (window.game && window.game.systems && window.game.systems.ship) {
const ship = window.game.systems.ship.ships.find(s => s.id === shipId);
if (ship) {
ship.status = 'inactive';
window.game.systems.ship.renderShips();
return { type: 'success', message: `Unlocked ship: ${ship.name}` };
} else {
return { type: 'error', message: `Ship not found: ${shipId}` };
}
}
return { type: 'error', message: 'Ship system not available' };
case 'stats':
if (window.game && window.game.systems && window.game.systems.player && window.game.systems.economy) {
const player = window.game.systems.player;
const economy = window.game.systems.economy;
return {
type: 'info',
message: `Player Stats:\nLevel: ${player.stats.level}\nExperience: ${player.stats.experience}/${player.stats.experienceToNext}\nCredits: ${economy.credits}\nGems: ${economy.gems}\nTotal Kills: ${player.stats.totalKills}\nDungeons Cleared: ${player.stats.dungeonsCleared}\nTitle: ${player.info.title}`
};
}
return { type: 'error', message: 'Player or Economy system not available' };
case 'ships':
if (window.game && window.game.systems && window.game.systems.ship) {
const ships = window.game.systems.ship.ships;
const currentShip = window.game.systems.ship.currentShip;
const shipList = ships.map(ship =>
`- ${ship.name} (${ship.id}) - Level ${ship.level} - ${ship.status} - ${ship.rarity}${currentShip.id === ship.id ? ' [CURRENT]' : ''}`
).join('\n');
return {
type: 'info',
message: `Available Ships:\n${shipList}`
};
}
return { type: 'error', message: 'Ship system not available' };
case 'current':
if (window.game && window.game.systems && window.game.systems.ship) {
const currentShip = window.game.systems.ship.currentShip;
if (currentShip) {
return {
type: 'info',
message: `Current Ship:
- Name: ${currentShip.name}
- Class: ${currentShip.class}
- Level: ${currentShip.level}
- Health: ${currentShip.health}/${currentShip.maxHealth}
- Attack: ${currentShip.attack}
- Defense: ${currentShip.defense}
- Speed: ${currentShip.speed}
- Rarity: ${currentShip.rarity}`
};
}
}
return { type: 'error', message: 'Ship system not available' };
default:
return { type: 'error', message: `Unknown command: ${cmd}. Type 'help' for available commands.` };
}
}
// Keyboard shortcut listener
document.addEventListener('DOMContentLoaded', function() {
console.log('[DEBUG] DOMContentLoaded event fired for keyboard shortcuts');
document.addEventListener('keydown', function(event) {
// Log all key combinations for debugging
if (event.ctrlKey || event.altKey || event.shiftKey) {
console.log('[DEBUG] Key pressed:', {
key: event.key,
ctrlKey: event.ctrlKey,
altKey: event.altKey,
shiftKey: event.shiftKey,
code: event.code
});
}
// Ctrl+Alt+Shift+C to toggle console
if (event.ctrlKey && event.altKey && event.shiftKey && event.key === 'C') {
console.log('[DEBUG] Ctrl+Alt+Shift+C detected!');
event.preventDefault();
// Check if toggleConsole function exists
if (typeof toggleConsole === 'function') {
console.log('[DEBUG] toggleConsole function exists, calling it');
toggleConsole();
} else {
console.error('[DEBUG] toggleConsole function not found!');
}
}
// Escape to close console
if (event.key === 'Escape') {
const consoleWindow = document.getElementById('consoleWindow');
if (consoleWindow && consoleWindow.style.display === 'flex') {
consoleWindow.style.display = 'none';
}
}
});
});
// Initialize console output with welcome message
document.addEventListener('DOMContentLoaded', function() {
const output = document.getElementById('consoleOutput');
if (output) {
const welcomeLine = document.createElement('div');
welcomeLine.className = 'console-line console-info';
welcomeLine.textContent = 'Developer Console ready. Type "help" for available commands.';
output.appendChild(welcomeLine);
}
});