/** * AeThex Connect Plugin for Nexus Engine * Integrates AeThex Connect communication into games * * @version 1.0.0 * @license MIT */ class AeThexConnectPlugin { constructor(nexusEngine, config = {}) { this.nexus = nexusEngine; this.config = { apiUrl: config.apiUrl || 'https://connect.aethex.app/api', apiKey: config.apiKey, enableOverlay: config.enableOverlay !== false, enableNotifications: config.enableNotifications !== false, overlayPosition: config.overlayPosition || 'top-right', autoMute: config.autoMute !== false, ...config }; this.sessionId = null; this.overlayConfig = null; this.overlayElement = null; this.isInitialized = false; } /** * Initialize plugin */ async initialize() { try { console.log('[AeThex Connect] Initializing...'); // Get player info from Nexus const player = await this.nexus.getPlayer(); if (!player || !player.id) { throw new Error('Failed to get player information from Nexus'); } // Start game session with AeThex Connect const response = await fetch(`${this.config.apiUrl}/nexus/sessions/start`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Nexus-API-Key': this.config.apiKey, 'X-Nexus-Player-ID': player.id }, body: JSON.stringify({ nexusPlayerId: player.id, gameId: this.nexus.gameId, gameName: this.nexus.gameName, metadata: { platform: this.nexus.platform || 'unknown', playerName: player.displayName || player.username } }) }); const data = await response.json(); if (data.success) { this.sessionId = data.session.id; this.overlayConfig = data.overlayConfig; this.isInitialized = true; // Initialize overlay if enabled if (this.overlayConfig.enabled && this.config.enableOverlay) { this.initializeOverlay(); } // Setup event listeners this.setupEventListeners(); console.log('[AeThex Connect] Initialized successfully'); console.log('[AeThex Connect] Session ID:', this.sessionId); return true; } else { throw new Error(data.error || 'Failed to start session'); } } catch (error) { console.error('[AeThex Connect] Initialization failed:', error); return false; } } /** * Setup event listeners for game state changes */ setupEventListeners() { // When player enters match this.nexus.on('match:start', async (matchData) => { console.log('[AeThex Connect] Match started'); await this.updateSessionState('in-match', { mapName: matchData.map, gameMode: matchData.mode, teamId: matchData.teamId }); // Auto-mute if configured if (this.overlayConfig.autoMute) { this.triggerAutoMute(); } }); // When player returns to menu this.nexus.on('match:end', async (matchData) => { console.log('[AeThex Connect] Match ended'); await this.updateSessionState('in-menu', { score: matchData.score, won: matchData.won, duration: matchData.duration }); // Unmute if (this.overlayConfig.autoMute) { this.triggerAutoUnmute(); } }); // When game closes this.nexus.on('game:exit', async () => { console.log('[AeThex Connect] Game exiting'); await this.endSession(); }); // When player pauses this.nexus.on('game:pause', async () => { await this.updateSessionState('paused'); }); // When player resumes this.nexus.on('game:resume', async () => { await this.updateSessionState('active'); }); } /** * Update session state */ async updateSessionState(state, metadata = {}) { if (!this.sessionId || !this.isInitialized) return; try { await fetch(`${this.config.apiUrl}/nexus/sessions/${this.sessionId}/update`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Nexus-API-Key': this.config.apiKey }, body: JSON.stringify({ state, metadata }) }); } catch (error) { console.error('[AeThex Connect] Failed to update session:', error); } } /** * End session */ async endSession() { if (!this.sessionId || !this.isInitialized) return; try { await fetch(`${this.config.apiUrl}/nexus/sessions/${this.sessionId}/end`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Nexus-API-Key': this.config.apiKey }, body: JSON.stringify({ duration: this.getSessionDuration(), metadata: {} }) }); this.sessionId = null; this.isInitialized = false; // Remove overlay if (this.overlayElement) { this.overlayElement.remove(); this.overlayElement = null; } } catch (error) { console.error('[AeThex Connect] Failed to end session:', error); } } /** * Initialize in-game overlay */ initializeOverlay() { // Create iframe overlay const overlay = document.createElement('iframe'); overlay.id = 'aethex-connect-overlay'; overlay.src = `${this.config.apiUrl.replace('/api', '')}/overlay?session=${this.sessionId}`; // Position based on config const positions = { 'top-right': 'top: 20px; right: 20px;', 'top-left': 'top: 20px; left: 20px;', 'bottom-right': 'bottom: 20px; right: 20px;', 'bottom-left': 'bottom: 20px; left: 20px;' }; overlay.style.cssText = ` position: fixed; ${positions[this.config.overlayPosition] || positions['top-right']} width: 320px; height: 480px; border: none; z-index: 999999; opacity: ${this.overlayConfig.opacity || 0.9}; pointer-events: auto; transition: all 0.3s ease; `; // Add to DOM document.body.appendChild(overlay); this.overlayElement = overlay; // Listen for overlay messages window.addEventListener('message', (event) => { // Security check const allowedOrigins = [ 'https://connect.aethex.app', 'http://localhost:3000', 'http://localhost:5173' ]; if (!allowedOrigins.includes(event.origin)) return; this.handleOverlayMessage(event.data); }); console.log('[AeThex Connect] Overlay initialized'); } /** * Handle overlay messages */ handleOverlayMessage(message) { switch (message.type) { case 'minimize': this.minimizeOverlay(message.minimized); break; case 'notification': this.showNotification(message.data); break; case 'friend_invite': this.handleFriendInvite(message.data); break; } } /** * Minimize/restore overlay */ minimizeOverlay(minimized) { if (!this.overlayElement) return; if (minimized) { this.overlayElement.style.width = '60px'; this.overlayElement.style.height = '60px'; } else { this.overlayElement.style.width = '320px'; this.overlayElement.style.height = '480px'; } } /** * Show in-game notification */ showNotification(notification) { if (!this.config.enableNotifications) return; // Create notification element const notif = document.createElement('div'); notif.className = 'aethex-notification'; notif.innerHTML = `
${notification.icon || '💬'}
${this.escapeHtml(notification.title)}
${this.escapeHtml(notification.body)}
`; // Add styles if not already added this.injectNotificationStyles(); document.body.appendChild(notif); // Auto-remove after 5 seconds setTimeout(() => { notif.style.opacity = '0'; setTimeout(() => notif.remove(), 300); }, 5000); console.log('[AeThex Connect] Notification shown:', notification.title); } /** * Inject notification styles */ injectNotificationStyles() { if (document.getElementById('aethex-notif-styles')) return; const style = document.createElement('style'); style.id = 'aethex-notif-styles'; style.textContent = ` .aethex-notification { position: fixed; top: 20px; right: 20px; width: 320px; background: rgba(20, 20, 30, 0.95); backdrop-filter: blur(10px); border-radius: 8px; padding: 16px; display: flex; gap: 12px; box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5); animation: slideIn 0.3s ease-out; z-index: 1000000; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; transition: opacity 0.3s; } @keyframes slideIn { from { transform: translateX(400px); opacity: 0; } to { transform: translateX(0); opacity: 1; } } .aethex-notification .notif-icon { font-size: 24px; flex-shrink: 0; } .aethex-notification .notif-content { flex: 1; } .aethex-notification .notif-title { font-size: 14px; font-weight: 600; color: #fff; margin-bottom: 4px; } .aethex-notification .notif-body { font-size: 13px; color: #aaa; } `; document.head.appendChild(style); } /** * Trigger auto-mute for voice chat */ triggerAutoMute() { if (!this.overlayElement) return; this.overlayElement.contentWindow.postMessage({ type: 'auto_mute', mute: true }, '*'); console.log('[AeThex Connect] Auto-mute triggered'); } /** * Trigger auto-unmute */ triggerAutoUnmute() { if (!this.overlayElement) return; this.overlayElement.contentWindow.postMessage({ type: 'auto_mute', mute: false }, '*'); console.log('[AeThex Connect] Auto-unmute triggered'); } /** * Handle friend invite */ handleFriendInvite(data) { console.log('[AeThex Connect] Friend invite received:', data); // Game-specific handling of friend invites // Could show custom UI or trigger game's friend system } /** * Get session duration in seconds */ getSessionDuration() { // This would be calculated based on session start time // For now, return 0 as placeholder return 0; } /** * Escape HTML to prevent XSS */ escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } /** * Cleanup and destroy plugin */ destroy() { this.endSession(); if (this.overlayElement) { this.overlayElement.remove(); } console.log('[AeThex Connect] Plugin destroyed'); } } // Export for different module systems if (typeof module !== 'undefined' && module.exports) { module.exports = AeThexConnectPlugin; } if (typeof window !== 'undefined') { window.AeThexConnectPlugin = AeThexConnectPlugin; }