Drawaria Interactive Pixel Companions

Pixel companions With player selector and very optimized

// ==UserScript==
// @name         Drawaria Interactive Pixel Companions
// @namespace    http://tampermonkey.net/
// @version      3.5
// @description  Pixel companions With player selector and very optimized
// @author       YouTubeDrawaria
// @match        https://drawaria.online/*
// @match        https://*.drawaria.online/*
// @grant        none
// @license      MIT
// @icon         https://www.google.com/s2/favicons?sz=64&domain=drawaria.online
// ==/UserScript==

(function() {
    'use strict';

    /* ----------  SISTEMA BASE OPTIMIZADO  ---------- */
    let drawariaSocket = null;
    let drawariaCanvas = null;
    let drawariaCtx = null;

    // Queue optimizado para comandos con batching inteligente
    const commandQueue = [];
    let batchProcessor = null;
    const BATCH_SIZE = 8;
    const BATCH_INTERVAL = 60;

    // Variables de control del sistema
    let systemActive = false;
    let selectedPlayerId = null;
    let selectedPlayerName = null;
    let activeComponents = {
        hearts: true,
        sword: true,
        shield: true
    };

    // Función auxiliar para delays
    function sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    // Intercept WebSocket optimizado
    const originalWebSocketSend = WebSocket.prototype.send;
    WebSocket.prototype.send = function (...args) {
        if (!drawariaSocket && this.url && this.url.includes('drawaria')) {
            drawariaSocket = this;
            console.log('🔗 [PIXEL COMPANIONS] Socket capturado para Pixel Companions');
            startBatchProcessor();
        }
        return originalWebSocketSend.apply(this, args);
    };

    function startBatchProcessor() {
        if (batchProcessor) return;
        batchProcessor = setInterval(() => {
            if (!drawariaSocket || drawariaSocket.readyState !== WebSocket.OPEN || commandQueue.length === 0) {
                return;
            }
            const batch = commandQueue.splice(0, BATCH_SIZE);
            batch.forEach(cmd => {
                try {
                    drawariaSocket.send(cmd);
                } catch (e) {
                    console.warn('⚠️ [PIXEL COMPANIONS] Error enviando comando:', e);
                }
            });
        }, BATCH_INTERVAL);
    }

    /* ----------  PATRONES PIXEL ART OPTIMIZADOS  ---------- */
    const pixelPatterns = {
        'heart': [
            " RR   RR ",
            "RRRR RRRR",
            "RRRRRRRRR",
            " RRRRRRR ",
            "  RRRRR  ",
            "   RRR   ",
            "    R    "
        ],
        'sword': [
            "    W    ",
            "    W    ",
            "    W    ",
            "    W    ",
            "    W    ",
            "    W    ",
            "    W    ",
            "  BBBBB  ",
            "    B    ",
            "    B    "
        ],
        'shield': [
            "  BBBBB  ",
            " BWWWWWB ",
            "BWWWWWWB",
            "BWWWWWWB",
            "BWWWWWWB",
            "BWWWWWWB",
            " BWWWWB ",
            "  BWWB  ",
            "   BB   "
        ]
    };

    const specificColorSchemes = {
        heart: {
            classic: { 'R': '#FF0000', 'W': '#FFFFFF', 'B': '#000000', ' ': null },
            dark: { 'R': '#330000', 'W': '#333333', 'B': '#111111', ' ': null }
        },
        sword: {
            classic: { 'W': '#00FFFF', 'B': '#0000FF', ' ': null },
            dark: { 'W': '#006666', 'B': '#000066', ' ': null }
        },
        shield: {
            classic: { 'W': '#FFFF00', 'B': '#000000', ' ': null },
            dark: { 'W': '#666600', 'B': '#111111', ' ': null }
        }
    };

    /* ----------  GESTIÓN DE JUGADORES SIMPLIFICADA (COPIADA DEL OTRO SCRIPT)  ---------- */
    class PlayerManager {
        constructor() {
            this.validPlayers = [];
            this.updateInterval = null;
        }

        updatePlayerOptions() {
            const playerSelect = document.getElementById('player-selector');
            if (!playerSelect) return;

            // Guardar la selección actual antes de limpiar
            const currentSelection = playerSelect.value;

            // Clear existing options
            playerSelect.innerHTML = '';

            // Try multiple selectors for better compatibility
            const playerElements = document.querySelectorAll('.spawnedavatar[data-playerid], .playerlist-row[data-playerid]');
            const validPlayers = [];

            playerElements.forEach(el => {
                const playerId = el.dataset.playerid;

                // Skip if no player ID or if it's the current player
                if (!playerId || playerId === '0' || el.dataset.self === 'true') {
                    return;
                }

                // Try different ways to get player name
                let playerName = '';

                // Method 1: Check for nickname in avatar
                const nicknameEl = el.querySelector('.nickname, .playerlist-name a, .player-name');
                if (nicknameEl) {
                    playerName = nicknameEl.textContent.trim();
                }

                // Method 2: Check parent elements
                if (!playerName) {
                    const parentRow = el.closest('.playerlist-row');
                    if (parentRow) {
                        const nameEl = parentRow.querySelector('.playerlist-name a, .player-name');
                        if (nameEl) {
                            playerName = nameEl.textContent.trim();
                        }
                    }
                }

                // Method 3: Use player ID as fallback
                if (!playerName) {
                    playerName = `Player ${playerId}`;
                }

                // Avoid duplicates
                if (!validPlayers.some(p => p.id === playerId)) {
                    validPlayers.push({
                        id: playerId,
                        name: playerName
                    });
                }
            });

            console.log('🎯 [PIXEL COMPANIONS] Players found:', validPlayers); // Debug log

            // Actualizar la lista de jugadores válidos
            this.validPlayers = validPlayers;

            if (validPlayers.length === 0) {
                const opt = document.createElement('option');
                opt.value = '';
                opt.textContent = '❌ No players available';
                opt.disabled = true;
                playerSelect.appendChild(opt);

                const startBtn = document.getElementById('start-system-btn');
                if (startBtn) startBtn.disabled = true;

                console.log('🎯 [PIXEL COMPANIONS] No hay jugadores disponibles');
            } else {
                // Opción para todos los jugadores
                const allOpt = document.createElement('option');
                allOpt.value = 'all';
                allOpt.textContent = `🌍 All Players (${validPlayers.length})`;
                playerSelect.appendChild(allOpt);

                // Poblar la lista con los jugadores válidos
                validPlayers.forEach(player => {
                    const opt = document.createElement('option');
                    opt.value = player.id;
                    opt.textContent = `🎯 ${player.name}`;
                    opt.dataset.playerName = player.name; // Guardar nombre para referencia
                    playerSelect.appendChild(opt);
                });

                // Intentar mantener la selección anterior
                const stillExists = currentSelection === 'all' || validPlayers.some(p => p.id === currentSelection);

                if (currentSelection && stillExists) {
                    // El jugador previamente seleccionado todavía existe, mantener selección
                    playerSelect.value = currentSelection;

                    // Actualizar nombre seleccionado
                    if (currentSelection === 'all') {
                        selectedPlayerName = 'Todos los jugadores';
                    } else {
                        const selectedPlayer = validPlayers.find(p => p.id === currentSelection);
                        selectedPlayerName = selectedPlayer ? selectedPlayer.name : null;
                    }

                    console.log('🎯 [PIXEL COMPANIONS] Manteniendo selección:', selectedPlayerName);
                } else if (currentSelection && !stillExists) {
                    // El jugador previamente seleccionado ya no existe
                    console.log('⚠️ [PIXEL COMPANIONS] El jugador seleccionado salió de la sala');
                    // Seleccionar "All Players" por defecto
                    playerSelect.value = 'all';
                    selectedPlayerId = 'all';
                    selectedPlayerName = 'Todos los jugadores';
                } else {
                    // Primera vez o sin selección previa
                    playerSelect.value = 'all';
                    selectedPlayerId = 'all';
                    selectedPlayerName = 'Todos los jugadores';
                }

                const startBtn = document.getElementById('start-system-btn');
                if (startBtn) startBtn.disabled = false;

                console.log(`🎯 [PIXEL COMPANIONS] Lista actualizada: ${validPlayers.length} jugadores`);
                console.log('👥 [PIXEL COMPANIONS] Nombres:', validPlayers.map(p => p.name).join(', '));
            }

            // Actualizar variables globales
            selectedPlayerId = playerSelect.value;
        }

        startAutoUpdate() {
            if (this.updateInterval) return;

            this.updateInterval = setInterval(() => {
                this.updatePlayerOptions();
            }, 2000);

            // Actualizar inmediatamente
            this.updatePlayerOptions();
            console.log('🔄 [PIXEL COMPANIONS] Auto-actualización de jugadores iniciada');
        }

        stopAutoUpdate() {
            if (this.updateInterval) {
                clearInterval(this.updateInterval);
                this.updateInterval = null;
                console.log('⏹️ [PIXEL COMPANIONS] Auto-actualización de jugadores detenida');
            }
        }
    }

    /* ----------  SISTEMA DE DIBUJO OPTIMIZADO  ---------- */
    function enqueueDrawCommand(x1, y1, x2, y2, color, thickness) {
        if (!drawariaCanvas || !drawariaSocket || !systemActive) return;

        const normX1 = (x1 / drawariaCanvas.width).toFixed(4);
        const normY1 = (y1 / drawariaCanvas.height).toFixed(4);
        const normX2 = (x2 / drawariaCanvas.width).toFixed(4);
        const normY2 = (y2 / drawariaCanvas.height).toFixed(4);

        const cmd = `42["drawcmd",0,[${normX1},${normY1},${normX2},${normY2},false,${-Math.abs(thickness)},"${color}",0,0,{}]]`;
        commandQueue.push(cmd);

        if (drawariaCtx) {
            drawariaCtx.strokeStyle = color;
            drawariaCtx.lineWidth = thickness;
            drawariaCtx.lineCap = 'round';
            drawariaCtx.beginPath();
            drawariaCtx.moveTo(x1, y1);
            drawariaCtx.lineTo(x2, y2);
            drawariaCtx.stroke();
        }
    }

    /* ----------  SISTEMA PRINCIPAL MEJORADO  ---------- */
    class EnhancedPixelCompanionSystem {
        constructor() {
            this.initialized = false;
            this.lives = 3;
            this.lastPlayerPositions = new Map();
            this.playerManager = new PlayerManager();

            this.MOVEMENT_THRESHOLD = 4;
            this.UPDATE_INTERVAL = 80;
            this.lastUpdateTime = 0;
            this.COLLISION_COOLDOWN = 3000;
            this.lastCollisionTime = 0;

            this.companionStates = new Map();
            this.animationState = {
                damageSequence: false,
                swordAttack: false,
                shieldDefend: false
            };

            this.cachedPatterns = this.preOptimizePatterns();
            this.init();
        }

        init() {
            const checkGameReady = () => {
                const gameCanvas = document.getElementById('canvas');
                if (gameCanvas) {
                    this.canvasElement = gameCanvas;
                    drawariaCanvas = gameCanvas;
                    this.canvasContext = gameCanvas.getContext('2d');
                    drawariaCtx = gameCanvas.getContext('2d');

                    this.initialized = true;
                    this.createControlInterface();
                    console.log('✅ [PIXEL COMPANIONS] Sistema inicializado correctamente');
                } else {
                    setTimeout(checkGameReady, 100);
                }
            };
            checkGameReady();
        }

        preOptimizePatterns() {
            const optimized = {};
            Object.keys(pixelPatterns).forEach(patternName => {
                optimized[patternName] = this.optimizePatternToLines(pixelPatterns[patternName]);
            });
            return optimized;
        }

        optimizePatternToLines(pattern) {
            const lines = [];
            for (let row = 0; row < pattern.length; row++) {
                let currentLine = null;
                for (let col = 0; col < pattern[row].length; col++) {
                    const char = pattern[row][col];
                    if (char !== ' ') {
                        if (!currentLine || currentLine.char !== char) {
                            if (currentLine) lines.push(currentLine);
                            currentLine = { char, startCol: col, endCol: col, row };
                        } else {
                            currentLine.endCol = col;
                        }
                    } else {
                        if (currentLine) {
                            lines.push(currentLine);
                            currentLine = null;
                        }
                    }
                }
                if (currentLine) lines.push(currentLine);
            }
            return lines;
        }

                getTargetPlayerCoords(playerId = null) {
            if (!playerId || playerId === 'all') {
                const allPlayers = [];
                const avatars = document.querySelectorAll('.spawnedavatar[data-playerid]:not([data-playerid="0"]):not(.self)');

                avatars.forEach(avatar => {
                    if (!this.canvasElement) return;

                    const cRect = this.canvasElement.getBoundingClientRect();
                    const aRect = avatar.getBoundingClientRect();

                    if (aRect.width > 0 && aRect.height > 0) {
                        allPlayers.push({
                            id: avatar.dataset.playerid || `player_${allPlayers.length}`,
                            x: Math.round((aRect.left - cRect.left) + (aRect.width / 2)),
                            y: Math.round((aRect.top - cRect.top) + (aRect.height / 2)),
                            width: aRect.width,
                            height: aRect.height
                        });
                    }
                });

                return allPlayers.length > 0 ? allPlayers : null;
            }

            const targetPlayers = [];
            const avatars = document.querySelectorAll(`.spawnedavatar[data-playerid="${playerId}"]`);

            avatars.forEach(avatar => {
                if (!this.canvasElement) return;

                const cRect = this.canvasElement.getBoundingClientRect();
                const aRect = avatar.getBoundingClientRect();

                if (aRect.width > 0 && aRect.height > 0) {
                    targetPlayers.push({
                        id: playerId,
                        x: Math.round((aRect.left - cRect.left) + (aRect.width / 2)),
                        y: Math.round((aRect.top - cRect.top) + (aRect.height / 2)),
                        width: aRect.width,
                        height: aRect.height
                    });
                }
            });

            return targetPlayers.length > 0 ? targetPlayers : null;
        }

        detectCollisionWithOtherPlayers() {
            if (selectedPlayerId === 'all') return false;

            const myPos = this.getTargetPlayerCoords(selectedPlayerId);
            if (!myPos || myPos.length === 0) return false;

            const now = Date.now();
            if (now - this.lastCollisionTime < this.COLLISION_COOLDOWN) {
                return false;
            }

            const otherPlayers = document.querySelectorAll('.spawnedavatar.spawnedavatar-otherplayer');
            const collisionDistance = 45;

            for (let otherPlayer of otherPlayers) {
                if (!this.canvasElement) continue;

                const cRect = this.canvasElement.getBoundingClientRect();
                const otherRect = otherPlayer.getBoundingClientRect();

                const otherX = (otherRect.left - cRect.left) + (otherRect.width / 2);
                const otherY = (otherRect.top - cRect.top) + (otherRect.height / 2);

                const distance = Math.sqrt(
                    Math.pow(myPos.x - otherX, 2) + Math.pow(myPos.y - otherY, 2)
                );

                if (distance < collisionDistance) {
                    this.lastCollisionTime = now;
                    return true;
                }
            }
            return false;
        }

        drawOptimizedPixelArt(patternName, colorScheme, pixelSize, centerX, centerY, rotation = 0, eraseMode = false) {
            const lines = this.cachedPatterns[patternName];
            if (!lines) return;

            let colors;
            if (eraseMode) {
                colors = Object.keys(specificColorSchemes[patternName][colorScheme] || {})
                    .reduce((acc, key) => {
                        acc[key] = key === ' ' ? null : '#FFFFFF';
                        return acc;
                    }, {});
            } else {
                colors = specificColorSchemes[patternName] ?
                         specificColorSchemes[patternName][colorScheme] :
                         specificColorSchemes.heart[colorScheme];
            }

            const patternCenter = Math.floor(pixelPatterns[patternName].length / 2);

            lines.forEach(line => {
                if (!colors[line.char]) return;

                const startX = centerX + (line.startCol - patternCenter) * pixelSize;
                const endX = centerX + (line.endCol - patternCenter) * pixelSize + pixelSize;
                const y = centerY + (line.row - patternCenter) * pixelSize;

                enqueueDrawCommand(startX, y, endX, y, colors[line.char], pixelSize * 1.2);
            });
        }

        async executeDamageSequence() {
            if (this.animationState.damageSequence || this.lives <= 0) return;

            this.animationState.damageSequence = true;
            console.log(`💔 [PIXEL COMPANIONS] ¡Daño recibido! Vidas restantes: ${this.lives - 1}`);

            const heartsToDeactivate = [2, 1, 0];

            for (let i = 0; i < Math.min(heartsToDeactivate.length, this.lives); i++) {
                const heartIndex = heartsToDeactivate[i];
                if (this.companions && this.companions.hearts[heartIndex]) {
                    this.companions.hearts[heartIndex].active = false;
                    this.companions.hearts[heartIndex].needsRedraw = true;
                }

                await new Promise(r => setTimeout(r, 800));
                if (i >= this.lives - 1) break;
            }

            this.lives--;

            if (this.lives <= 0) {
                console.log('💀 [PIXEL COMPANIONS] ¡Sin vidas! Reiniciando sistema...');

                await new Promise(r => setTimeout(r, 2000));

                this.lives = 3;
                if (this.companions) {
                    this.companions.hearts.forEach(heart => {
                        heart.active = true;
                        heart.needsRedraw = true;
                    });
                }
                console.log('🔄 [PIXEL COMPANIONS] Sistema reiniciado con 3 vidas');
            } else {
                await new Promise(r => setTimeout(r, 500));
                if (this.companions) {
                    this.companions.hearts.forEach(heart => {
                        heart.active = true;
                        heart.needsRedraw = true;
                    });
                }
            }

            this.animationState.damageSequence = false;
        }

        async executeSwordAttack() {
            if (this.animationState.swordAttack) return;

            this.animationState.swordAttack = true;
            console.log('⚔️ [PIXEL COMPANIONS] ¡Ejecutando ataque con espada!');

            await new Promise(r => setTimeout(r, 600));

            if (this.companions && this.companions.sword) {
                this.companions.sword.rotation = Math.PI / 3;
                this.companions.sword.needsRedraw = true;
            }

            await new Promise(r => setTimeout(r, 500));

            if (this.companions && this.companions.sword) {
                this.companions.sword.rotation = 0;
                this.companions.sword.needsRedraw = true;
            }

            await new Promise(r => setTimeout(r, 500));

            this.animationState.swordAttack = false;
            console.log('⚔️ [PIXEL COMPANIONS] Ataque con espada completado');
        }

        async executeShieldDefense() {
            if (this.animationState.shieldDefend) return;

            this.animationState.shieldDefend = true;
            console.log('🛡️ [PIXEL COMPANIONS] ¡Activando defensa con escudo!');

            await new Promise(r => setTimeout(r, 400));

            if (this.companions && this.companions.shield) {
                this.companions.shield.defending = true;
                this.companions.shield.needsRedraw = true;
            }

            await new Promise(r => setTimeout(r, 800));

            if (this.companions && this.companions.shield) {
                this.companions.shield.defending = false;
                this.companions.shield.needsRedraw = true;
            }

            this.animationState.shieldDefend = false;
            console.log('🛡️ [PIXEL COMPANIONS] Defensa con escudo completada');
        }

        // NEW: Clean Canvas functionality
        async cleanCanvas() {
            if (!drawariaCanvas) return;

            console.log('🧹 [PIXEL COMPANIONS] Limpiando canvas...');

            // Draw a giant white rectangle over entire canvas
            const canvasWidth = drawariaCanvas.width;
            const canvasHeight = drawariaCanvas.height;

            // Send multiple white rectangles to ensure complete coverage
            for (let y = 0; y < canvasHeight; y += 100) {
                for (let x = 0; x < canvasWidth; x += 100) {
                    const width = Math.min(100, canvasWidth - x);
                    const height = Math.min(100, canvasHeight - y);
                    enqueueDrawCommand(x, y, x + width, y + height, '#FFFFFF', Math.max(width, height));
                    await sleep(5); // Menor delay para una limpieza más rápida
                }
            }

            // Clear local canvas
            if (drawariaCtx) {
                drawariaCtx.clearRect(0, 0, canvasWidth, canvasHeight);
            }

            console.log('🧹 [PIXEL COMPANIONS] Canvas limpiado completamente!');
        }

        updateCompanions() {
            if (!systemActive || !this.initialized) return;

            const now = Date.now();
            if (now - this.lastUpdateTime < this.UPDATE_INTERVAL) return;

            const targetPlayers = this.getTargetPlayerCoords(selectedPlayerId);
            if (!targetPlayers) return;

            if (selectedPlayerId !== 'all') {
                const collision = this.detectCollisionWithOtherPlayers();
                if (collision && !this.animationState.damageSequence) {
                    this.executeDamageSequence();
                    this.executeSwordAttack();
                    this.executeShieldDefense();
                }
            }

            targetPlayers.forEach(player => {
                this.updateCompanionForPlayer(player);
            });

            this.lastUpdateTime = now;
        }

        updateCompanionForPlayer(player) {
            const playerId = player.id;

            if (!this.companionStates.has(playerId)) {
                this.companionStates.set(playerId, {
                    hearts: Array(3).fill().map(() => ({ active: true, lastX: -9999, lastY: -9999, needsRedraw: true })),
                    sword: { rotation: 0, lastX: -9999, lastY: -9999, needsRedraw: true },
                    shield: { rotation: 0, lastX: -9999, lastY: -9999, needsRedraw: true }
                });
            }

            const state = this.companionStates.get(playerId);
            const lastPos = this.lastPlayerPositions.get(playerId) || { x: 0, y: 0 };

            const deltaX = Math.abs(player.x - lastPos.x);
            const deltaY = Math.abs(player.y - lastPos.y);
            const significantMovement = deltaX > this.MOVEMENT_THRESHOLD || deltaY > this.MOVEMENT_THRESHOLD;

            if (activeComponents.hearts) {
                for (let i = 0; i < 3; i++) {
                    const heartX = player.x + (i - 1) * 32;
                    const heartY = player.y - player.height / 2 - 25;

                    if (significantMovement || state.hearts[i].needsRedraw) {
                        if (state.hearts[i].lastX !== -9999) {
                            this.drawOptimizedPixelArt('heart', 'classic', 3,
                                state.hearts[i].lastX, state.hearts[i].lastY, 0, true);
                        }

                        const scheme = state.hearts[i].active ? 'classic' : 'dark';
                        this.drawOptimizedPixelArt('heart', scheme, 3, heartX, heartY, 0, false);

                        state.hearts[i].lastX = heartX;
                        state.hearts[i].lastY = heartY;
                        state.hearts[i].needsRedraw = false;
                    }
                }
            }

            if (activeComponents.sword) {
                const swordX = player.x + player.width / 2 + 30;
                const swordY = player.y;

                if (significantMovement || state.sword.needsRedraw) {
                    if (state.sword.lastX !== -9999) {
                        this.drawOptimizedPixelArt('sword', 'classic', 5,
                            state.sword.lastX, state.sword.lastY, 0, true);
                    }

                    this.drawOptimizedPixelArt('sword', 'classic', 5, swordX, swordY, state.sword.rotation, false);

                    state.sword.lastX = swordX;
                    state.sword.lastY = swordY;
                    state.sword.needsRedraw = false;
                }
            }

            if (activeComponents.shield) {
                const shieldX = player.x - player.width / 2 - 30;
                const shieldY = player.y;

                if (significantMovement || state.shield.needsRedraw) {
                    if (state.shield.lastX !== -9999) {
                        this.drawOptimizedPixelArt('shield', 'classic', 5,
                            state.shield.lastX, state.shield.lastY, 0, true);
                    }

                    this.drawOptimizedPixelArt('shield', 'classic', 5, shieldX, shieldY, 0, false);

                    state.shield.lastX = shieldX;
                    state.shield.lastY = shieldY;
                    state.shield.needsRedraw = false;
                }
            }

            if (significantMovement) {
                this.lastPlayerPositions.set(playerId, { x: player.x, y: player.y });
            }
        }

        startSystem() {
            if (!this.initialized) {
                console.log('❌ [PIXEL COMPANIONS] Sistema no inicializado. Esperando canvas...');
                return;
            }

            if (!selectedPlayerId) {
                console.log('❌ [PIXEL COMPANIONS] No hay jugador seleccionado');
                return;
            }

            systemActive = true;
            this.playerManager.startAutoUpdate();

            this.companions = {
                hearts: Array(3).fill().map(() => ({ active: true, lastX: -9999, lastY: -9999, needsRedraw: true })),
                sword: { rotation: 0, lastX: -9999, lastY: -9999, needsRedraw: true },
                shield: { rotation: 0, lastX: -9999, lastY: -9999, needsRedraw: true }
            };

            const updateLoop = () => {
                if (systemActive && this.initialized) {
                    this.updateCompanions();
                    this.updateStatusDisplay();
                }
                if (systemActive) {
                    requestAnimationFrame(updateLoop);
                }
            };
            updateLoop();

            console.log('🎮 [PIXEL COMPANIONS] Sistema iniciado exitosamente');
            console.log(`🎯 [PIXEL COMPANIONS] Target: ${selectedPlayerName || 'Jugador desconocido'}`);
            console.log(`⚙️ [PIXEL COMPANIONS] Componentes activos: ${Object.entries(activeComponents).filter(([,v]) => v).map(([k]) => k).join(', ')}`);
        }

        async stopSystem() {
            console.log('⏹️ [PIXEL COMPANIONS] Deteniendo sistema...');

            systemActive = false;
            this.playerManager.stopAutoUpdate();

            // Limpiar el canvas antes de resetear estados
            await this.cleanCanvas();

            // Resetear la cola de comandos
            commandQueue.length = 0;
            console.log('🧹 [PIXEL COMPANIONS] Cola de comandos reseteada (Queue: 0)');

            // Limpiar estados
            this.companionStates.clear();
            this.lastPlayerPositions.clear();

            // Resetear animaciones
            this.animationState = {
                damageSequence: false,
                swordAttack: false,
                shieldDefend: false
            };

                        // Resetear vidas
            this.lives = 3;

            console.log('⏹️ [PIXEL COMPANIONS] Sistema detenido completamente');
            console.log('🧹 [PIXEL COMPANIONS] Canvas limpiado y cola reseteada');
        }

        createControlInterface() {
            const existingPanel = document.getElementById('pixel-companions-control');
            if (existingPanel) existingPanel.remove();

            const controlPanel = document.createElement('div');
            controlPanel.id = 'pixel-companions-control';
            controlPanel.style.cssText = `
                position: fixed; top: 20px; right: 20px; z-index: 9999;
                background: linear-gradient(135deg, #1a1a2e, #16213e);
                color: white; padding: 20px; border-radius: 15px;
                font-family: 'Segoe UI', Arial, sans-serif;
                border: 2px solid #4fd1c7; min-width: 320px;
                box-shadow: 0 0 30px rgba(79,209,199,0.4);
                font-size: 14px;
            `;

            controlPanel.innerHTML = `
                <div style="text-align: center; font-weight: bold; color: #4fd1c7; margin-bottom: 15px;">
                    🎮 PIXEL COMPANIONS v3.4 - SIMPLE METHOD
                </div>

                <div style="margin-bottom: 15px;">
                    <label style="display: block; margin-bottom: 5px; color: #FFD700;">🎯 Target Player:</label>
                    <select id="player-selector" style="width: 100%; padding: 8px; border-radius: 5px; background: #2d2d2d; color: white; border: 1px solid #4fd1c7;">
                        <option value="">🔍 Scanning players...</option>
                    </select>
                </div>

                <div style="margin-bottom: 15px;">
                    <label style="display: block; margin-bottom: 8px; color: #FFD700;">⚙️ Active Components:</label>
                    <div style="display: flex; gap: 10px; flex-wrap: wrap;">
                        <label style="display: flex; align-items: center; gap: 5px; cursor: pointer;">
                            <input type="checkbox" id="hearts-toggle" checked style="accent-color: #FF0000;">
                            <span>💖 Hearts</span>
                        </label>
                        <label style="display: flex; align-items: center; gap: 5px; cursor: pointer;">
                            <input type="checkbox" id="sword-toggle" checked style="accent-color: #00FFFF;">
                            <span>⚔️ Sword</span>
                        </label>
                        <label style="display: flex; align-items: center; gap: 5px; cursor: pointer;">
                            <input type="checkbox" id="shield-toggle" checked style="accent-color: #FFFF00;">
                            <span>🛡️ Shield</span>
                        </label>
                    </div>
                </div>

                <div style="display: flex; gap: 10px; margin-bottom: 15px;">
                    <button id="start-system-btn" style="flex: 1; padding: 10px; background: linear-gradient(135deg, #00FF00, #32CD32); color: white; border: none; border-radius: 8px; font-weight: bold; cursor: pointer;" disabled>
                        ▶️ START
                    </button>
                    <button id="stop-system-btn" style="flex: 1; padding: 10px; background: linear-gradient(135deg, #FF4444, #CC0000); color: white; border: none; border-radius: 8px; font-weight: bold; cursor: pointer;" disabled>
                        ⏹️ STOP
                    </button>
                </div>

                <div id="system-status" style="text-align: center; padding: 10px; background: #333; border-radius: 5px; margin-bottom: 10px;">
                    ⏸️ System: <span style="color: #FF6B6B;">STOPPED</span> | Ready to start
                </div>

                <div id="companion-stats" style="font-size: 12px; color: #888;">
                    📊 Players tracked: 0 | Queue: 0 | Console Mode: ON
                </div>

                <div style="font-size: 11px; color: #666; margin-top: 10px; text-align: center;">
                    📝 Console logs (F12) | 🔧 Simple & Reliable Player Detection
                </div>
            `;

            document.body.appendChild(controlPanel);
            this.setupEventListeners();
        }

        setupEventListeners() {
            const playerSelect = document.getElementById('player-selector');
            const heartsToggle = document.getElementById('hearts-toggle');
            const swordToggle = document.getElementById('sword-toggle');
            const shieldToggle = document.getElementById('shield-toggle');
            const startBtn = document.getElementById('start-system-btn');
            const stopBtn = document.getElementById('stop-system-btn');

            playerSelect?.addEventListener('change', (e) => {
                selectedPlayerId = e.target.value;

                if (selectedPlayerId === 'all') {
                    selectedPlayerName = 'Todos los jugadores';
                } else if (selectedPlayerId) {
                    const selectedOption = e.target.options[e.target.selectedIndex];
                    selectedPlayerName = selectedOption.dataset.playerName ||
                                       selectedOption.textContent.replace('🎯 ', '') ||
                                       `Jugador ${selectedPlayerId}`;
                } else {
                    selectedPlayerName = null;
                }

                console.log(`🎯 [PIXEL COMPANIONS] Target cambiado a: ${selectedPlayerName || 'Ninguno'}`);

                if (startBtn) startBtn.disabled = !selectedPlayerId;
            });

            heartsToggle?.addEventListener('change', (e) => {
                activeComponents.hearts = e.target.checked;
                console.log(`💖 [PIXEL COMPANIONS] Corazones: ${e.target.checked ? 'Activados' : 'Desactivados'}`);
            });

            swordToggle?.addEventListener('change', (e) => {
                activeComponents.sword = e.target.checked;
                console.log(`⚔️ [PIXEL COMPANIONS] Espada: ${e.target.checked ? 'Activada' : 'Desactivada'}`);
            });

            shieldToggle?.addEventListener('change', (e) => {
                activeComponents.shield = e.target.checked;
                console.log(`🛡️ [PIXEL COMPANIONS] Escudo: ${e.target.checked ? 'Activado' : 'Desactivado'}`);
            });

            startBtn?.addEventListener('click', () => {
                if (!selectedPlayerId) {
                    console.log('🚫 [PIXEL COMPANIONS] Error: No hay jugador seleccionado');
                    return;
                }

                this.startSystem();
                startBtn.disabled = true;
                if (stopBtn) stopBtn.disabled = false;
            });

            stopBtn?.addEventListener('click', async () => {
                // Deshabilitar botón mientras se ejecuta la limpieza
                stopBtn.disabled = true;
                stopBtn.textContent = '🧹 CLEANING...';

                await this.stopSystem();

                // Restaurar botón y habilitar start
                stopBtn.textContent = '⏹️ STOP';
                if (startBtn) startBtn.disabled = false;
                stopBtn.disabled = true;
            });

            // Inicializar actualización de jugadores con delay
            setTimeout(() => {
                this.playerManager.startAutoUpdate();
            }, 1000);
        }

                updateStatusDisplay() {
            const statusDiv = document.getElementById('system-status');
            const statsDiv = document.getElementById('companion-stats');

            if (statusDiv) {
                const status = systemActive ?
                    `▶️ System: <span style="color: #00FF00;">ACTIVE</span> | Target: ${selectedPlayerName || 'Unknown'}` :
                    `⏸️ System: <span style="color: #FF6B6B;">STOPPED</span> | Ready to start`;
                statusDiv.innerHTML = status;
            }

            if (statsDiv) {
                const componentsList = Object.entries(activeComponents)
                    .filter(([, active]) => active)
                    .map(([name]) => name.charAt(0).toUpperCase() + name.slice(1))
                    .join(', ') || 'None';

                statsDiv.textContent = `📊 Players tracked: ${this.playerManager.validPlayers.length} | Queue: ${commandQueue.length} | Components: ${componentsList}`;
            }
        }
    }

    /* ----------  INICIALIZACIÓN  ---------- */
    let enhancedCompanionSystem = null;

    const initEnhancedSystem = () => {
        if (!enhancedCompanionSystem) {
            console.log('🚀 [PIXEL COMPANIONS] Inicializando Enhanced Pixel Companions System v3.4 (SIMPLE METHOD)...');
            enhancedCompanionSystem = new EnhancedPixelCompanionSystem();

            setTimeout(() => {
                console.log('');
                console.log('✅ [PIXEL COMPANIONS] ENHANCED PIXEL COMPANIONS v3.4 LOADED! (SIMPLE METHOD)');
                console.log('🔧 [PIXEL COMPANIONS] COPIADO: Método simple y confiable del otro script');
                console.log('👥 [PIXEL COMPANIONS] Player Detection: 3 métodos simples (nickname → parent → fallback)');
                console.log('🎯 [PIXEL COMPANIONS] Player Selector: Nombres únicos y sin duplicados');
                console.log('⚙️ [PIXEL COMPANIONS] Component Control: Toggle Hearts/Sword/Shield');
                console.log('🎮 [PIXEL COMPANIONS] System Control: Botones Start/Stop');
                console.log('📊 [PIXEL COMPANIONS] Live Stats: Monitoreo en tiempo real');
                console.log('💖 [PIXEL COMPANIONS] Hearts (Rojo) | ⚔️ Sword (Aqua+Azul) | 🛡️ Shield (Amarillo)');
                console.log('📝 [PIXEL COMPANIONS] Debug logs: "Players found" en consola');
                console.log('🎛️ [PIXEL COMPANIONS] Panel de control en la esquina superior derecha');
                console.log('🧹 [PIXEL COMPANIONS] NEW: Canvas cleaning & Queue reset al presionar STOP');
                console.log('');
            }, 1000);
        }
    };

    // Inicialización cuando DOM esté listo
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initEnhancedSystem);
    } else {
        setTimeout(initEnhancedSystem, 500);
    }

    // Fallback de inicialización
    setTimeout(initEnhancedSystem, 2000);

    console.log('🌟 [PIXEL COMPANIONS] Enhanced Drawaria Pixel Companions v3.4 (SIMPLE METHOD) loaded! 🌟');
    console.log('🧹 [PIXEL COMPANIONS] NEW FEATURES: Canvas cleaning + Queue reset on STOP');

})();