Emulation's Slither Client

Enhanced Slither.io mod with new features, fixed bot AI, professional UI, and immersive loading screen.

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Emulation's Slither Client
// @namespace    http://slither.com/io
// @version      2.6
// @description  Enhanced Slither.io mod with new features, fixed bot AI, professional UI, and immersive loading screen.
// @author       Emulation12
// @match        http://slither.com/io
// @grant        none
// @license      MIT
// ==/UserScript==  */

/* Utility Functions */
const savePreference = (key, value) => localStorage.setItem(key, JSON.stringify(value));
const loadPreference = (key, def) => JSON.parse(localStorage.getItem(key)) ?? def;

/* State Variables */
let IsBotActive = loadPreference('IsBotActive', true);
let isSpeedBoost = loadPreference('isSpeedBoost', false);
let showEnemyLines = loadPreference('showEnemyLines', true);
let showDangerBar = loadPreference('showDangerBar', true);
let showPlayerGlow = loadPreference('showPlayerGlow', false);
let autoRespawn = loadPreference('autoRespawn', false);
let aggressiveMode = loadPreference('aggressiveMode', false);
let defensiveMode = loadPreference('defensiveMode', false);
let speedModulation = loadPreference('speedModulation', false);
let autoZoom = loadPreference('autoZoom', false);
let enemyTrap = loadPreference('enemyTrap', false);
let showSpeedCooldown = loadPreference('showSpeedCooldown', true);
let showScoreTracker = loadPreference('showScoreTracker', true);
let customColors = loadPreference('customColors', false);
let autoDodge = loadPreference('autoDodge', false);
let menuVisible = false;
let favoriteMods = loadPreference('favoriteMods', []);
let activeTab = 'favorites-tab';
let isMinimized = false;
let targetFood = null;
let targetFoodTimestamp = 0;
let blacklistedFoods = {};
let criticDanger = false;
let lastSpeedBoost = 0;
let speedBoostCooldown = 3000; // 3 seconds cooldown
window.zoomMultiplier = loadPreference('zoomMultiplier', 1.0);
let customLineColor = loadPreference('customLineColor', '#ff0000');
let customMinimapColor = loadPreference('customMinimapColor', '#00ff88');

/* Mod Configuration */
const mods = [
    { id: 'bot', name: 'Bot', category: 'Bot', state: () => IsBotActive, toggle: (state) => { IsBotActive = state; state ? startFoodBot() : stopFoodBot(); savePreference('IsBotActive', state); } },
    { id: 'speedBoost', name: 'Speed Boost', category: 'Bot', state: () => isSpeedBoost, toggle: (state) => { if (Date.now() - lastSpeedBoost > speedBoostCooldown) { isSpeedBoost = state; window.setAcceleration?.(state ? 1 : 0); if (state) lastSpeedBoost = Date.now(); savePreference('isSpeedBoost', state); } } },
    { id: 'autoRespawn', name: 'Auto Respawn', category: 'Bot', state: () => autoRespawn, toggle: (state) => { autoRespawn = state; savePreference('autoRespawn', state); } },
    { id: 'aggressiveMode', name: 'Aggressive Mode', category: 'Bot', state: () => aggressiveMode, toggle: (state) => { aggressiveMode = state; defensiveMode = state ? false : defensiveMode; savePreference('aggressiveMode', state); savePreference('defensiveMode', defensiveMode); refreshTabs(); } },
    { id: 'defensiveMode', name: 'Defensive Mode', category: 'Bot', state: () => defensiveMode, toggle: (state) => { defensiveMode = state; aggressiveMode = state ? false : aggressiveMode; savePreference('defensiveMode', state); savePreference('aggressiveMode', aggressiveMode); refreshTabs(); } },
    { id: 'speedModulation', name: 'Speed Modulation', category: 'Bot', state: () => speedModulation, toggle: (state) => { speedModulation = state; savePreference('speedModulation', state); } },
    { id: 'autoZoom', name: 'Auto Zoom', category: 'Bot', state: () => autoZoom, toggle: (state) => { autoZoom = state; savePreference('autoZoom', state); } },
    { id: 'enemyTrap', name: 'Enemy Trap', category: 'Bot', state: () => enemyTrap, toggle: (state) => { enemyTrap = state; savePreference('enemyTrap', state); } },
    { id: 'autoDodge', name: 'Auto Dodge', category: 'Bot', state: () => autoDodge, toggle: (state) => { autoDodge = state; savePreference('autoDodge', state); } },
    { id: 'enemyLines', name: 'Enemy Lines', category: 'Visuals', state: () => showEnemyLines, toggle: (state) => { showEnemyLines = state; savePreference('showEnemyLines', state); } },
    { id: 'dangerBar', name: 'Danger Bar', category: 'Visuals', state: () => showDangerBar, toggle: (state) => { showDangerBar = state; savePreference('showDangerBar', state); } },
    { id: 'playerGlow', name: 'Player Glow', category: 'Visuals', state: () => showPlayerGlow, toggle: (state) => { showPlayerGlow = state; savePreference('showPlayerGlow', state); } },
    { id: 'showSpeedCooldown', name: 'Speed Cooldown', category: 'Visuals', state: () => showSpeedCooldown, toggle: (state) => { showSpeedCooldown = state; savePreference('showSpeedCooldown', state); } },
    { id: 'showScoreTracker', name: 'Score Tracker', category: 'Visuals', state: () => showScoreTracker, toggle: (state) => { showScoreTracker = state; savePreference('showScoreTracker', state); } },
    { id: 'customColors', name: 'Custom Colors', category: 'Visuals', state: () => customColors, toggle: (state) => { customColors = state; savePreference('customColors', state); } }
];

/* SVG Icons */
const icons = {
    Favorites: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/></svg>`,
    Bot: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 15v5m-3-8h6m-8-4h10a2 2 0 012 2v6a2 2 0 01-2 2H7a2 2 0 01-2-2v-6a2 2 0 012-2zm-3 4h2m14 0h2"/></svg>`,
    Visuals: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>`,
    FavoriteOn: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"/></svg>`,
    FavoriteOff: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"/></svg>`
};

/* Zoom Control */
window.updateZoom = () => { window.gsc = window.zoomMultiplier; };
window.adjustZoom = (amount) => {
    window.zoomMultiplier = Math.max(0.2, Math.min(3.0, window.zoomMultiplier + amount));
    window.updateZoom();
    savePreference('zoomMultiplier', window.zoomMultiplier);
};
window.recursiveZoomUpdate = () => {
    window.updateZoom();
    requestAnimationFrame(window.recursiveZoomUpdate);
};
window.recursiveZoomUpdate();

/* Mouse Position */
window.mousePos = { x: 0, y: 0 };
document.addEventListener('mousemove', (e) => { window.mousePos = { x: e.clientX, y: e.clientY }; });
window.botTargetPos = null;

/* Loading Screen */
(function setupLoadingScreen() {
    const style = document.createElement('style');
    style.textContent = `
        @keyframes glitch { 0% { transform: translate(0); } 20% { transform: translate(-2px, 2px); } 40% { transform: translate(-2px, -2px); } 60% { transform: translate(2px, 2px); } 80% { transform: translate(2px, -2px); } 100% { transform: translate(0); } }
        @keyframes matrix { 0% { opacity: 0; transform: translateY(20px); } 50% { opacity: 1; } 100% { opacity: 0; transform: translateY(-20px); } }
        #bot-loading-screen { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: #000; z-index: 10001; display: flex; flex-direction: column; align-items: center; justify-content: center; font-family: 'Courier New', monospace; color: #00ff88; overflow: hidden; }
        #bot-loading-canvas { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
        #bot-loading-content { z-index: 1; text-align: center; }
        #bot-loading-text { font-size: 24px; margin-bottom: 20px; animation: glitch 0.5s infinite alternate; }
        #bot-loading-bar { width: 300px; height: 20px; background: #222; border: 2px solid #00ff88; border-radius: 5px; overflow: hidden; }
        #bot-loading-fill { height: 100%; background: linear-gradient(90deg, #00ff88, #00cc66); width: 0%; transition: width 0.5s ease; }
    `;
    document.head.appendChild(style);

    const loadingScreen = document.createElement('div');
    loadingScreen.id = 'bot-loading-screen';
    document.body.appendChild(loadingScreen);

    const canvas = document.createElement('canvas');
    canvas.id = 'bot-loading-canvas';
    loadingScreen.appendChild(canvas);
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    window.addEventListener('resize', () => { canvas.width = window.innerWidth; canvas.height = window.innerHeight; });

    const content = document.createElement('div');
    content.id = 'bot-loading-content';
    loadingScreen.appendChild(content);

    const loadingText = document.createElement('div');
    loadingText.id = 'bot-loading-text';
    loadingText.textContent = 'Initializing Slither Client...';
    content.appendChild(loadingText);

    const loadingBar = document.createElement('div');
    loadingBar.id = 'bot-loading-bar';
    const loadingFill = document.createElement('div');
    loadingFill.id = 'bot-loading-fill';
    loadingBar.appendChild(loadingFill);
    content.appendChild(loadingBar);

    const ctx = canvas.getContext('2d');
    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#$%^&*';
    const fontSize = 14;
    const columns = Math.floor(canvas.width / fontSize);
    const drops = Array(columns).fill(0);

    function drawMatrix() {
        ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ctx.fillStyle = '#00ff88';
        ctx.font = `${fontSize}px 'Courier New'`;
        drops.forEach((y, i) => {
            const text = chars.charAt(Math.floor(Math.random() * chars.length));
            ctx.fillText(text, i * fontSize, y * fontSize);
            if (y * fontSize > canvas.height && Math.random() > 0.975) drops[i] = 0;
            drops[i]++;
        });
    }

    const particles = Array(100).fill().map(() => ({
        x: Math.random() * canvas.width,
        y: Math.random() * canvas.height,
        vx: (Math.random() - 0.5) * 2,
        vy: (Math.random() - 0.5) * 2,
        size: Math.random() * 3 + 1
    }));

    function drawParticles() {
        ctx.fillStyle = 'rgba(0, 255, 136, 0.5)';
        particles.forEach(p => {
            ctx.beginPath();
            ctx.arc(p.x, p.y, p.size, 0, 2 * Math.PI);
            ctx.fill();
            p.x += p.vx;
            p.y += p.vy;
            if (p.x < 0 || p.x > canvas.width) p.vx *= -1;
            if (p.y < 0 || p.y > canvas.height) p.vy *= -1;
        });
    }

    function animateLoading() {
        drawMatrix();
        drawParticles();
        requestAnimationFrame(animateLoading);
    }
    animateLoading();

    const components = [
        { name: 'Core Systems', duration: 600 },
        { name: 'Bot AI', duration: 500 },
        { name: 'Visuals', duration: 400 },
        { name: 'UI', duration: 500 }
    ];

    let index = 0, progress = 0;
    function loadNextComponent() {
        if (index >= components.length) {
            loadingScreen.style.display = 'none';
            initializeUI();
            return;
        }
        loadingText.textContent = `[${index + 1}/${components.length}] Loading ${components[index].name}...`;
        progress += 100 / components.length;
        loadingFill.style.width = `${progress}%`;
        setTimeout(loadNextComponent, components[index].duration);
        index++;
    }
    loadNextComponent();
})();

/* Mod Menu UI */
function initializeUI() {
    const style = document.createElement('style');
    style.textContent = `
        #bot-overlay-container { position: fixed; top: 50px; left: 50px; background: linear-gradient(135deg, #1a1a1a, #2d2d2d); border-radius: 12px; z-index: 10000; font-family: 'Roboto', Arial, sans-serif; color: #e0e0e0; box-shadow: 0 8px 30px rgba(0, 0, 0, 0.7); width: 320px; height: 450px; resize: both; min-width: 280px; min-height: 350px; max-width: 600px; max-height: 700px; overflow: hidden; }
        #bot-overlay-container.minimized { width: 60px; height: 40px; overflow: hidden; }
        #bot-header { background: #111; padding: 10px; font-size: 16px; font-weight: bold; text-align: center; cursor: move; border-bottom: 1px solid #444; display: flex; justify-content: space-between; align-items: center; }
        #bot-sidebar { width: 50px; background: #222; height: 100%; float: left; border-right: 1px solid #444; }
        #bot-sidebar.collapsed { width: 0; overflow: hidden; }
        #bot-content-container { width: calc(100% - 50px); height: 100%; float: left; padding: 10px; overflow-y: auto; background: #1a1a1a; }
        #bot-content-container::-webkit-scrollbar { width: 6px; }
        #bot-content-container::-webkit-scrollbar-track { background: #333; }
        #bot-content-container::-webkit-scrollbar-thumb { background: #00ff88; border-radius: 3px; }
        .tab-button { width: 100%; padding: 10px; background: #222; color: #e0e0e0; border: none; text-align: center; font-size: 13px; cursor: pointer; transition: all 0.3s ease; display: flex; align-items: center; justify-content: center; }
        .tab-button:hover { background: #2a2a2a; }
        .tab-button.active { background: #333; color: #00ff88; }
        .mod-container { display: flex; align-items: center; margin: 5px 0; }
        .mod-button { flex: 1; padding: 6px; background: #ff4d4d; color: #000; border: none; border-radius: 4px; cursor: pointer; transition: all 0.2s ease; font-size: 13px; }
        .mod-button.on { background: #00ff88; }
        .mod-button:hover { filter: brightness(1.2); }
        .favorite-button { padding: 6px; background: #444; color: #e0e0e0; border: none; border-radius: 4px; margin-left: 5px; cursor: pointer; transition: all 0.2s ease; }
        .favorite-button.on { background: #ffd700; color: #000; }
        #bot-search-bar { width: 100%; padding: 6px; margin-bottom: 8px; background: #333; border: 1px solid #444; color: #e0e0e0; border-radius: 4px; font-size: 13px; }
        #bot-danger-bar { position: fixed; top: 50%; right: 10px; width: 15px; height: 150px; background: #333; border-radius: 8px; z-index: 9999; overflow: hidden; transform: translateY(-50%); box-shadow: 0 4px 10px rgba(0, 0, 0, 0.5); }
        #bot-danger-fill { width: 100%; height: 0%; background: green; transition: height 0.3s ease, background 0.3s ease; }
        #bot-speed-cooldown { position: fixed; bottom: 20px; left: 20px; width: 100px; height: 10px; background: #333; border-radius: 5px; z-index: 9999; overflow: hidden; }
        #bot-speed-cooldown-fill { height: 100%; background: #00ff88; width: 0%; transition: width 0.3s ease; }
        #bot-color-picker { margin: 10px 0; }
    `;
    document.head.appendChild(style);

    const tailwindLink = document.createElement('link');
    tailwindLink.href = 'https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css';
    tailwindLink.rel = 'stylesheet';
    document.head.appendChild(tailwindLink);

    const fontLink = document.createElement('link');
    fontLink.href = 'https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap';
    fontLink.rel = 'stylesheet';
    document.head.appendChild(fontLink);

    const overlayContainer = document.createElement('div');
    overlayContainer.id = 'bot-overlay-container';
    document.body.appendChild(overlayContainer);

    let isDragging = false, xOffset = loadPreference('menuX', 50), yOffset = loadPreference('menuY', 50);
    overlayContainer.style.left = `${xOffset}px`;
    overlayContainer.style.top = `${yOffset}px`;

    const header = document.createElement('div');
    header.id = 'bot-header';
    header.innerHTML = `<span>Slither Client</span><span id="active-tab" class="text-sm text-gray-400">Favorites</span><button id="minimize-btn" class="text-gray-400 hover:text-gray-100">${isMinimized ? '+' : '-'}</button>`;
    overlayContainer.appendChild(header);

    header.addEventListener('mousedown', (e) => {
        isDragging = true;
        xOffset = e.clientX - parseFloat(overlayContainer.style.left);
        yOffset = e.clientY - parseFloat(overlayContainer.style.top);
    });

    document.addEventListener('mousemove', (e) => {
        if (isDragging) {
            e.preventDefault();
            overlayContainer.style.left = `${e.clientX - xOffset}px`;
            overlayContainer.style.top = `${e.clientY - yOffset}px`;
            savePreference('menuX', e.clientX - xOffset);
            savePreference('menuY', e.clientY - yOffset);
        }
    });

    document.addEventListener('mouseup', () => { isDragging = false; });

    const sidebar = document.createElement('div');
    sidebar.id = 'bot-sidebar';
    overlayContainer.appendChild(sidebar);

    const contentContainer = document.createElement('div');
    contentContainer.id = 'bot-content-container';
    overlayContainer.appendChild(contentContainer);

    const tabs = [
        { id: 'favorites-tab', name: 'Favorites', icon: icons.Favorites },
        { id: 'bot-tab', name: 'Bot', icon: icons.Bot },
        { id: 'visuals-tab', name: 'Visuals', icon: icons.Visuals }
    ];

    tabs.forEach(tab => {
        const tabButton = document.createElement('button');
        tabButton.innerHTML = `${tab.icon} ${tab.name}`;
        tabButton.className = `tab-button ${tab.id === activeTab ? 'active' : ''}`;
        tabButton.onclick = () => {
            activeTab = tab.id;
            document.getElementById('active-tab').textContent = tab.name;
            tabs.forEach(t => {
                document.getElementById(t.id).style.display = t.id === tab.id ? 'block' : 'none';
                sidebar.querySelectorAll('.tab-button').forEach(btn => {
                    btn.className = `tab-button ${btn.innerText.includes(t.name) && t.id === tab.id ? 'active' : ''}`;
                });
            });
            refreshTabs();
        };
        sidebar.appendChild(tabButton);

        const tabContent = document.createElement('div');
        tabContent.id = tab.id;
        tabContent.style.display = tab.id === activeTab ? 'block' : 'none';
        contentContainer.appendChild(tabContent);
    });

    const searchBar = document.createElement('input');
    searchBar.id = 'bot-search-bar';
    searchBar.type = 'text';
    searchBar.placeholder = 'Search mods...';
    contentContainer.appendChild(searchBar);

    searchBar.oninput = () => {
        const query = searchBar.value.toLowerCase();
        mods.forEach(mod => {
            const modElement = document.getElementById(`mod-${mod.id}`);
            if (modElement) modElement.style.display = mod.name.toLowerCase().includes(query) ? 'flex' : 'none';
        });
    };

    if (customColors) {
        const colorPicker = document.createElement('div');
        colorPicker.id = 'bot-color-picker';
        colorPicker.innerHTML = `
            <label class="block text-sm mb-1">Line Color: <input type="color" id="line-color" value="${customLineColor}"></label>
            <label class="block text-sm mb-1">Minimap Color: <input type="color" id="minimap-color" value="${customMinimapColor}"></label>
        `;
        contentContainer.appendChild(colorPicker);

        document.getElementById('line-color').addEventListener('input', (e) => {
            customLineColor = e.target.value;
            savePreference('customLineColor', customLineColor);
        });
        document.getElementById('minimap-color').addEventListener('input', (e) => {
            customMinimapColor = e.target.value;
            savePreference('customMinimapColor', customMinimapColor);
        });
    }

    const minimizeBtn = header.querySelector('#minimize-btn');
    minimizeBtn.onclick = () => {
        isMinimized = !isMinimized;
        overlayContainer.className = isMinimized ? 'minimized' : '';
        minimizeBtn.textContent = isMinimized ? '+' : '-';
        contentContainer.style.display = isMinimized ? 'none' : 'block';
        sidebar.className = `bg-gray-800 ${isMinimized ? 'collapsed' : ''}`;
    };

    function refreshTabs() {
        const favoritesTab = document.getElementById('favorites-tab');
        const botTab = document.getElementById('bot-tab');
        const visualsTab = document.getElementById('visuals-tab');

        favoritesTab.innerHTML = botTab.innerHTML = visualsTab.innerHTML = '';

        const filteredMods = favoriteMods.length > 0 ? mods.filter(mod => favoriteMods.includes(mod.id)) : [];
        if (filteredMods.length === 0 && activeTab === 'favorites-tab') {
            favoritesTab.innerHTML = '<div class="text-gray-500 text-center p-5">No favorite mods yet.</div>';
        } else {
            filteredMods.forEach(mod => favoritesTab.appendChild(createModToggle(mod)));
        }

        mods.filter(m => m.category === 'Bot').forEach(mod => botTab.appendChild(createModToggle(mod)));
        mods.filter(m => m.category === 'Visuals').forEach(mod => visualsTab.appendChild(createModToggle(mod)));
    }

    function createModToggle(mod) {
        const container = document.createElement('div');
        container.id = `mod-${mod.id}`;
        container.className = 'mod-container';

        const button = document.createElement('button');
        button.textContent = `${mod.name}: ${mod.state() ? 'ON' : 'OFF'}`;
        button.className = `mod-button ${mod.state() ? 'on' : ''}`;
        button.onclick = () => {
            const newState = !mod.state();
            mod.toggle(newState);
            button.textContent = `${mod.name}: ${newState ? 'ON' : 'OFF'}`;
            button.className = `mod-button ${newState ? 'on' : ''}`;
            document.querySelectorAll(`#mod-${mod.id} .mod-button`).forEach(btn => {
                btn.textContent = `${mod.name}: ${newState ? 'ON' : 'OFF'}`;
                btn.className = `mod-button ${newState ? 'on' : ''}`;
            });
        };

        const favoriteButton = document.createElement('button');
        favoriteButton.innerHTML = favoriteMods.includes(mod.id) ? icons.FavoriteOn : icons.FavoriteOff;
        favoriteButton.className = `favorite-button ${favoriteMods.includes(mod.id) ? 'on' : ''}`;
        favoriteButton.onclick = () => {
            favoriteMods = favoriteMods.includes(mod.id) ? favoriteMods.filter(id => id !== mod.id) : [...favoriteMods, mod.id];
            savePreference('favoriteMods', favoriteMods);
            favoriteButton.innerHTML = favoriteMods.includes(mod.id) ? icons.FavoriteOn : icons.FavoriteOff;
            favoriteButton.className = `favorite-button ${favoriteMods.includes(mod.id) ? 'on' : ''}`;
            refreshTabs();
        };

        container.appendChild(button);
        container.appendChild(favoriteButton);
        return container;
    }

    const dangerBar = document.createElement('div');
    dangerBar.id = 'bot-danger-bar';
    dangerBar.innerHTML = '<div id="bot-danger-fill"></div>';
    document.body.appendChild(dangerBar);

    const speedCooldown = document.createElement('div');
    speedCooldown.id = 'bot-speed-cooldown';
    speedCooldown.innerHTML = '<div id="bot-speed-cooldown-fill"></div>';
    document.body.appendChild(speedCooldown);

    document.addEventListener('keydown', (e) => {
        if (e.key === ';') {
            menuVisible = !menuVisible;
            overlayContainer.style.display = menuVisible && !isMinimized ? 'block' : 'none';
        }
    });

    refreshTabs();
}

/* Minimap and Visuals */
(function setupMinimap() {
    const minimap = document.createElement('canvas');
    minimap.id = 'bot-minimap';
    minimap.width = 200;
    minimap.height = 200;
    minimap.style.cssText = `position: fixed; bottom: 10px; right: 40px; z-index: 9999; border: 2px solid ${customColors ? customMinimapColor : '#00ff88'}; border-radius: 8px; background: rgba(0, 0, 0, 0.6); box-shadow: 0 4px 10px rgba(0, 0, 0, 0.5);`;
    document.body.appendChild(minimap);

    function updateMinimap() {
        const ctx = minimap.getContext('2d');
        ctx.clearRect(0, 0, minimap.width, minimap.height);
        ctx.fillStyle = 'rgba(0, 0, 0, 0.6)';
        ctx.fillRect(0, 0, minimap.width, minimap.height);

        if (window.slither?.xx !== undefined) {
            const scale = 0.015, centerX = minimap.width / 2, centerY = minimap.height / 2;

            ctx.fillStyle = customColors ? customMinimapColor : 'green';
            ctx.beginPath();
            ctx.arc(centerX, centerY, 6, 0, 2 * Math.PI);
            ctx.fill();
            if (showPlayerGlow) {
                ctx.shadowBlur = 15;
                ctx.shadowColor = customColors ? customMinimapColor : 'green';
                ctx.fill();
                ctx.shadowBlur = 0;
            }

            if (Array.isArray(window.slithers)) {
                window.slithers.forEach(e => {
                    if (!e || e.xx === window.slither.xx || typeof e.xx !== 'number') return;
                    const dx = (e.xx - window.slither.xx) * scale;
                    const dy = (e.yy - window.slither.yy) * scale;
                    if (Math.abs(dx) < centerX && Math.abs(dy) < centerY) {
                        ctx.fillStyle = 'red';
                        ctx.beginPath();
                        ctx.arc(centerX + dx, centerY + dy, 4, 0, 2 * Math.PI);
                        ctx.fill();
                    }
                });
            }

            if (Array.isArray(window.foods)) {
                window.foods.forEach(f => {
                    if (!f || typeof f.xx !== 'number') return;
                    const dx = (f.xx - window.slither.xx) * scale;
                    const dy = (f.yy - window.slither.yy) * scale;
                    if (Math.abs(dx) < centerX && Math.abs(dy) < centerY) {
                        ctx.fillStyle = 'cyan';
                        ctx.beginPath();
                        ctx.arc(centerX + dx, centerY + dy, 3, 0, 2 * Math.PI);
                        ctx.fill();
                    }
                });
            }

            if (showScoreTracker && window.slither?.l) {
                ctx.fillStyle = '#fff';
                ctx.font = '12px Roboto';
                ctx.fillText(`Score: ${Math.floor(window.slither.l)}`, 10, 20);
                ctx.fillText(`Rank: ${window.rank || 'N/A'}`, 10, 35);
            }
        }
        requestAnimationFrame(updateMinimap);
    }
    updateMinimap();
})();

/* World to Screen Conversion */
const worldToScreen = (xx, yy) => ({
    x: (xx - window.view_xx) * window.gsc + window.mww2,
    y: (yy - window.view_yy) * window.gsc + window.mhh2
});

/* Enemy Processing */
function getEnemyBodyPoints(enemy) {
    const points = [];
    if (enemy?.pts) {
        for (const segment of enemy.pts) {
            if (segment.fxs && segment.fys) {
                for (let i = 0; i < segment.fxs.length; i += Math.max(1, Math.floor(segment.fxs.length / 5))) {
                    const x = segment.xx + segment.fxs[i];
                    const y = segment.yy + segment.fys[i];
                    if (isFinite(x) && isFinite(y)) points.push({ xx: x, yy: y });
                }
            }
        }
    }
    return points;
}

function DangerColor(start, end) {
    const dist = Math.hypot(end.x - start.x, end.y - start.y);
    const dangerRatio = Math.max(0, Math.min(1, (700 - dist) / (700 - 300)));
    const r = Math.floor(255 * dangerRatio), g = Math.floor(255 * (1 - dangerRatio));
    return customColors ? customLineColor : `rgba(${r},${g},0,0.8)`;
}

/* Enemy Lines */
(function updateEnemyLines() {
    let canvas, ctx;
    function initCanvas() {
        canvas = document.createElement('canvas');
        canvas.id = 'bot-line-overlay';
        canvas.style.cssText = `position: fixed; top: 0; left: 0; pointer-events: none; z-index: 9998;`;
        document.body.appendChild(canvas);
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
        window.addEventListener('resize', () => {
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;
        });
        ctx = canvas.getContext('2d');
    }

    function update() {
        if (!canvas) initCanvas();
        ctx.clearRect(0, 0, canvas.width, canvas.height);

        if (showEnemyLines && window.slither?.xx !== undefined && Array.isArray(window.slithers)) {
            const selfScreen = worldToScreen(window.slither.xx, window.slither.yy);
            const enemies = window.slithers.filter(e => e && typeof e.xx === 'number' && e.xx !== window.slither.xx).slice(0, 5);
            enemies.forEach(enemy => {
                const bodyPoints = getEnemyBodyPoints(enemy);
                let minDist = Infinity, minPoint = null;
                bodyPoints.forEach(p => {
                    const screenPoint = worldToScreen(p.xx, p.yy);
                    const dist = Math.hypot(screenPoint.x - selfScreen.x, screenPoint.y - selfScreen.y);
                    if (dist < minDist && dist > 0) {
                        minDist = dist;
                        minPoint = screenPoint;
                    }
                });
                if (minPoint) {
                    ctx.beginPath();
                    ctx.moveTo(selfScreen.x, selfScreen.y);
                    ctx.lineTo(minPoint.x, minPoint.y);
                    ctx.strokeStyle = DangerColor(selfScreen, minPoint);
                    ctx.lineWidth = 3;
                    ctx.stroke();
                }
            });
        }
        requestAnimationFrame(update);
    }
    update();
})();

/* Speed Cooldown Indicator */
(function updateSpeedCooldown() {
    function update() {
        if (showSpeedCooldown) {
            const cooldownProgress = Math.min((Date.now() - lastSpeedBoost) / speedBoostCooldown, 1);
            const fill = document.getElementById('bot-speed-cooldown-fill');
            if (fill) fill.style.width = `${cooldownProgress * 100}%`;
        }
        requestAnimationFrame(update);
    }
    update();
})();

/* A* Pathfinding */
function aStarPathfinding(start, goal, obstacles) {
    const gridSize = 50, gridWidth = Math.ceil(10000 / gridSize), gridHeight = Math.ceil(10000 / gridSize);
    const openSet = new Set([`${Math.floor(start.x / gridSize)},${Math.floor(start.y / gridSize)}`]);
    const closedSet = new Set();
    const cameFrom = new Map();
    const gScore = new Map([[openSet.values().next().value, 0]]);
    const fScore = new Map([[openSet.values().next().value, Math.hypot(goal.x - start.x, goal.y - start.y)]]);

    function getNeighbors(node) {
        const [x, y] = node.split(',').map(Number);
        const directions = [[1,0],[-1,0],[0,1],[0,-1],[1,1],[1,-1],[-1,1],[-1,-1]];
        return directions.map(([dx, dy]) => ({ x: x + dx, y: y + dy }))
            .filter(n => n.x >= 0 && n.x < gridWidth && n.y >= 0 && n.y < gridHeight);
    }

    function isObstacle(node) {
        const nodeX = node.x * gridSize + gridSize / 2, nodeY = node.y * gridSize + gridSize / 2;
        return obstacles.some(o => Math.hypot(o.point.xx - nodeX, o.point.yy - nodeY) < 200);
    }

    while (openSet.size) {
        let current = [...openSet].reduce((a, b) => (fScore.get(a) || Infinity) < (fScore.get(b) || Infinity) ? a : b);
        const [cx, cy] = current.split(',').map(Number);
        const currentNode = { x: cx, y: cy };

        if (cx === Math.floor(goal.x / gridSize) && cy === Math.floor(goal.y / gridSize)) {
            const path = [];
            let curr = current;
            while (curr) {
                const [x, y] = curr.split(',').map(Number);
                path.unshift({ x: x * gridSize + gridSize / 2, y: y * gridSize + gridSize / 2 });
                curr = cameFrom.get(curr);
            }
            return path;
        }

        openSet.delete(current);
        closedSet.add(current);

        for (const neighbor of getNeighbors(current)) {
            const neighborStr = `${neighbor.x},${neighbor.y}`;
            if (closedSet.has(neighborStr) || isObstacle(neighbor)) continue;

            const tentativeG = (gScore.get(current) || 0) + Math.hypot((neighbor.x - cx) * gridSize, (neighbor.y - cy) * gridSize);
            if (!openSet.has(neighborStr)) openSet.add(neighborStr);
            else if (tentativeG >= (gScore.get(neighborStr) || Infinity)) continue;

            cameFrom.set(neighborStr, current);
            gScore.set(neighborStr, tentativeG);
            fScore.set(neighborStr, tentativeG + Math.hypot((neighbor.x - goal.x / gridSize) * gridSize, (neighbor.y - goal.y / gridSize) * gridSize));
        }
    }
    return [];
}

/* Bot Logic */
function moveMouseToward(worldX, worldY) {
    if (!window.slither?.xx) return;
    window.botTargetPos = { x: worldX, y: worldY };
    const screenX = (worldX - window.view_xx) * window.gsc + window.mww2;
    const screenY = (worldY - window.view_yy) * window.gsc + window.mhh2;
    if (Math.hypot(screenX - window.mousePos.x, screenY - window.mousePos.y) > 10) {
        window.dispatchEvent(new MouseEvent('mousemove', { clientX: screenX, clientY: screenY, bubbles: true }));
    }
}

let foodBotInterval = null;
function startFoodBot() {
    if (!foodBotInterval) foodBotInterval = setInterval(foodBotUpdate, loadPreference('botSpeed', 20));
}
function stopFoodBot() {
    if (foodBotInterval) {
        clearInterval(foodBotInterval);
        foodBotInterval = null;
    }
}

function foodBotUpdate() {
    if (!window.slither?.xx || !Array.isArray(window.foods)) return;
    const self = window.slither, now = Date.now();
    let dangerLevel = 0, enemyList = [];
    criticDanger = false;

    if (Array.isArray(window.slithers)) {
        window.slithers.forEach(enemy => {
            if (!enemy || enemy.xx === self.xx || typeof enemy.xx !== 'number') return;
            const bodyPoints = getEnemyBodyPoints(enemy);
            if (!bodyPoints.length) return;
            let bestPoint = null, bestDistance = Infinity, bestDx = 0, bestDy = 0;
            bodyPoints.forEach(p => {
                const dx = p.xx - self.xx, dy = p.yy - self.yy, d = Math.hypot(dx, dy);
                if (d < bestDistance) {
                    bestDistance = d;
                    bestPoint = p;
                    bestDx = dx;
                    bestDy = dy;
                }
            });
            if (bestPoint) {
                dangerLevel = Math.max(dangerLevel, bestDistance < 300 ? 1 - bestDistance / 300 : bestDistance < 700 ? 0.5 * (1 - (bestDistance - 300) / 400) : 0);
                if (bestDistance < 300) criticDanger = true;
                enemyList.push({ point: bestPoint, distance: bestDistance, dx: bestDx, dy: bestDy, size: enemy.l || 100, futurePoint: {
                    xx: bestPoint.xx + (enemy.spd || 0) * Math.cos(enemy.ang || 0) * 100,
                    yy: bestPoint.yy + (enemy.spd || 0) * Math.sin(enemy.ang || 0) * 100
                } });
            }
        });
    }

    if (showDangerBar) {
        const fill = document.getElementById('bot-danger-fill');
        if (fill) {
            fill.style.height = `${Math.min(dangerLevel * 100, 100)}%`;
            fill.style.background = `rgb(${Math.floor(255 * dangerLevel)},${Math.floor(255 * (1 - dangerLevel))},0)`;
        }
    }

    if (speedModulation && !isSpeedBoost && targetFood?.sz > 50 && dangerLevel < 0.5 && Date.now() - lastSpeedBoost > speedBoostCooldown) {
        window.setAcceleration?.(1);
        isSpeedBoost = true;
        lastSpeedBoost = Date.now();
        document.querySelectorAll('#mod-speedBoost .mod-button').forEach(btn => {
            btn.textContent = `Speed Boost: ON`;
            btn.className = 'mod-button on';
        });
    } else if (speedModulation && isSpeedBoost && (!targetFood || targetFood.sz <= 50 || dangerLevel >= 0.5)) {
        window.setAcceleration?.(0);
        isSpeedBoost = false;
        document.querySelectorAll('#mod-speedBoost .mod-button').forEach(btn => {
            btn.textContent = `Speed Boost: OFF`;
            btn.className = 'mod-button';
        });
    }

    if (autoZoom) {
        const baseZoom = 1.0, sizeFactor = window.slither?.l ? Math.min(0.5, 500 / window.slither.l) : 0;
        window.zoomMultiplier = Math.max(0.2, Math.min(3.0, baseZoom - sizeFactor + dangerLevel * 0.5));
        window.updateZoom();
        savePreference('zoomMultiplier', window.zoomMultiplier);
    }

    const foods = window.foods.filter(f => f && typeof f.xx === 'number' && !(blacklistedFoods[`${f.xx}_${f.yy}`] && now < blacklistedFoods[`${f.xx}_${f.yy}`]));
    let target = null;

    if (!enemyList.length) {
        target = chooseBestFood(foods);
    } else if (enemyList.some(e => e.distance < 300)) {
        if (autoDodge) {
            let avgX = 0, avgY = 0, totalWeight = 0;
            enemyList.filter(e => e.distance < 300).forEach(e => {
                const weight = 1 / (e.distance + 1e-5);
                avgX += (e.dx / e.distance) * weight;
                avgY += (e.dy / e.distance) * weight;
                totalWeight += weight;
            });
            if (totalWeight > 0) {
                avgX /= totalWeight;
                avgY /= totalWeight;
                const bestDir = { x: -avgX * 200, y: -avgY * 200 };
                if (criticDanger && Math.random() < 0.5) {
                    const angle = Date.now() / 1000 * Math.PI;
                    bestDir.x += Math.cos(angle) * 50;
                    bestDir.y += Math.sin(angle) * 50;
                }
                moveMouseToward(self.xx + bestDir.x, self.yy + bestDir.y);
                targetFood = null;
                return;
            }
        }
    } else if (!aggressiveMode) {
        const closest = enemyList.reduce((a, b) => a.distance < b.distance ? a : b);
        const vecX = self.xx - closest.futurePoint.xx, vecY = self.yy - closest.futurePoint.yy;
        const vecLength = Math.hypot(vecX, vecY);
        const normX = vecLength ? vecX / vecLength : 0, normY = vecLength ? vecY / vecLength : 0;
        const filteredFoods = foods.filter(f => (f.xx - self.xx) * normX + (f.yy - self.yy) * normY > 0);
        target = filteredFoods.length ? chooseBestFood(filteredFoods) : chooseBestFood(foods);
    } else if (enemyTrap && aggressiveMode) {
        const smallEnemies = enemyList.filter(e => e.size < (window.slither.l || 100) && e.distance < 500);
        if (smallEnemies.length) {
            const trapTarget = chooseBestFood(foods.filter(f => {
                return smallEnemies.some(e => Math.hypot(f.xx - e.point.xx, f.yy - e.point.yy) < 200);
            }));
            if (trapTarget) {
                const angle = Date.now() / 1000 * Math.PI;
                const orbitRadius = 100;
                target = {
                    xx: trapTarget.xx + Math.cos(angle) * orbitRadius,
                    yy: trapTarget.yy + Math.sin(angle) * orbitRadius,
                    sz: trapTarget.sz
                };
            } else {
                target = chooseBestFood(foods);
            }
        } else {
            target = chooseBestFood(foods);
        }
    } else {
        target = chooseBestFood(foods);
    }

    if (target && targetFood?.xx === target.xx && target.yy === targetFood.yy && now - targetFoodTimestamp >= 2000) {
        blacklistedFoods[`${targetFood.xx}_${targetFood.yy}`] = now + 2000;
        target = chooseBestFood(foods.filter(f => f.xx !== targetFood.xx || f.yy !== targetFood.yy));
        targetFoodTimestamp = now;
    } else if (target) {
        targetFoodTimestamp = now;
    }

    if (target) {
        const path = aStarPathfinding({ x: self.xx, y: self.yy }, { x: target.xx, y: target.yy }, enemyList);
        moveMouseToward(path[1]?.x || target.xx, path[1]?.y || target.yy);
        targetFood = target;
    }
}

function chooseBestFood(foods) {
    const maxDistance = aggressiveMode ? 1000 : 500;
    let bestTarget = null, bestScore = -Infinity;
    foods.forEach(f => {
        if (!f || typeof f.xx !== 'number') return;
        const dist = Math.hypot(f.xx - window.slither.xx, f.yy - window.slither.yy);
        if (dist > maxDistance) return;
        let dangerScore = 0;
        window.slithers?.forEach(e => {
            if (!e || e.xx === window.slither.xx) return;
            const dx = f.xx - e.xx, dy = f.yy - e.yy, d = Math.hypot(dx, dy);
            if (d < 300) dangerScore -= aggressiveMode ? 500 / (d + 1e-5) : 1000 / (d + 1e-5);
        });
        const score = (f.sz || 1) * (aggressiveMode ? 2 : 1) + dangerScore - dist / (defensiveMode ? 5 : 10);
        if (score > bestScore) {
            bestScore = score;
            bestTarget = f;
        }
    });
    return bestTarget;
}

/* Auto Respawn */
(function checkRespawn() {
    if (autoRespawn && window.dead_mtm && !window.playing) window.play_btn_click?.();
    requestAnimationFrame(checkRespawn);
})();

/* Key Bindings */
document.addEventListener('keydown', (e) => {
    switch (e.key.toLowerCase()) {
        case 't': window.adjustZoom(0.1); break;
        case 'r': window.adjustZoom(-0.1); break;
        case 'y': if (Date.now() - lastSpeedBoost > speedBoostCooldown) toggleSpeedBoost(); break;
    }
});

function toggleSpeedBoost() {
    isSpeedBoost = !isSpeedBoost;
    window.setAcceleration?.(isSpeedBoost ? 1 : 0);
    if (isSpeedBoost) lastSpeedBoost = Date.now();
    savePreference('isSpeedBoost', isSpeedBoost);
    document.querySelectorAll('#mod-speedBoost .mod-button').forEach(btn => {
        btn.textContent = `Speed Boost: ${isSpeedBoost ? 'ON' : 'OFF'}`;
        btn.className = `mod-button ${isSpeedBoost ? 'on' : ''}`;
    });
}

if (IsBotActive) startFoodBot();

document.addEventListener('DOMContentLoaded', () => setTimeout(initializeUI, 100));