Agar.io---Chat, Minimap, Bar Remover, Custom Skins, Skin Maker (Drag&Drop + Layout) [Updated]

Removes #agar-io_970x90, improves drag & drop styling, places Turn Skin On/Off under the skin URL.

目前為 2025-02-21 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Agar.io---Chat, Minimap, Bar Remover, Custom Skins, Skin Maker (Drag&Drop + Layout) [Updated]
// @namespace    All in one mod, doesnt add cheats.
// @version      1.0
// @description  Removes #agar-io_970x90, improves drag & drop styling, places Turn Skin On/Off under the skin URL.
// @author       𝓝𝑒ⓦ 𝓙ⓐ¢𝓀🕹️
// @match        https://agar.io/*
// @grant        none
// @run-at       document-idle
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';
    document.documentElement.removeAttribute('style');
    //------------------------------------------------------------------
    // 0) REMOVE #agar-io_970x90 DIV
    //------------------------------------------------------------------
    const adDiv = document.querySelector('#agar-io_970x90');
    if (adDiv) {
        adDiv.remove();
    }

    //------------------------------------------------------------------
    // AUDIO: Default OFF
    //------------------------------------------------------------------
    let musicOn = false;
    const messageSound = new Audio('https://jimboy3100.github.io/notification_01.mp3');
    const openSound    = new Audio('https://jimboy3100.github.io/sounds/notification-open.mp3');

    //------------------------------------------------------------------
    // GLOBAL STYLES
    //------------------------------------------------------------------
    const style = document.createElement('style');
    style.textContent = `
      /* --- COMMON BUTTON / CONTAINER STYLES --- */
      .styled-button, .toggle-button, .send-button, .resize-handle, .info-box, .status-indicator {
        background-color: #54c800;
        color: white;
        padding: 8px 16px;
        border: none;
        cursor: pointer;
        border-radius: 4px;
      }
      .styled-button:hover,
      .toggle-button:hover,
      .send-button:hover,
      .info-box:hover {
        background-color: #3d8b00;
      }
      .styled-button:active,
      .toggle-button:active,
      .send-button:active {
        background-color: #296600;
      }

      /* --- CHAT DRAGGABLE BOX --- */
      .draggable {
        position: fixed;
        bottom: 0;
        left: 0;
        width: 25%;
        height: 400px;
        background-color: rgba(0,0,0,.2);
        display: flex;
        flex-direction: column;
        overflow: hidden;
        cursor: move;
        z-index: 9999;
      }

      /* --- RESIZE HANDLE --- */
      .resize-handle {
        position: absolute;
        bottom: 0;
        right: 0;
        width: 10px;
        height: 10px;
        background-color: #ccc;
        cursor: nwse-resize;
      }

      /* --- CLOSE BUTTON & STATUS --- */
      .close-button, .status-indicator {
        position: absolute;
        right: 0;
        padding: 2px 5px;
        cursor: pointer;
        color: white;
      }
      .close-button {
        top: 0;
        background-color: red;
      }
      .status-indicator {
        bottom: 0;
        left: 1px;
        width: 25%;
        text-align: center;
      }

      /* --- MESSAGES --- */
      #messageContainer {
        display: flex;
        flex-wrap: wrap;
        background: rgba(0,0,0,.3);
        padding: 8px;
      }
      #messageArea {
        flex-grow: 1;
        overflow: auto;
        margin: 5px;
        padding: 5px;
        background: rgba(0,0,0,.1);
        color: white;
      }
      .chat-message {
        padding: 5px;
        border-bottom: 1px solid #ccc;
        display: flex;
        align-items: center;
      }

      /* --- INPUTS --- */
      #avatarInputContainer {
        width: 100%;
        margin-bottom: 5px;
        padding: 5px;
      }
      #avatarInputContainer label {
        color: white;
        background: transparent;
        font-size: 14px;
      }
      #avatarInput {
        color: white;
        width: 80%;
        background: rgba(255,255,255,0.1);
        margin-left: 4px;
        border: 1px solid #666;
        border-radius: 3px;
      }
      #inputArea {
        width: 75%;
        flex-grow: 1;
        padding: 8px;
        border-radius: 4px;
        background: rgba(0,0,0,.1);
        color: white;
        margin-right: 5px;
      }

      /* --- TOAST --- */
      .toast {
        position: fixed;
        bottom: 10%;
        left: 50%;
        transform: translateX(-50%);
        background-color: #333;
        color: white;
        padding: 10px;
        border-radius: 5px;
        text-align: center;
        z-index: 1000;
        display: none;
      }

      /* --- TOASTER (FOR COPY IP, ETC.) --- */
      .toaster {
        visibility: hidden;
        min-width: 250px;
        margin-left: -125px;
        background-color: #333;
        color: #fff;
        text-align: center;
        border-radius: 2px;
        padding: 16px;
        position: fixed;
        z-index: 1001;
        left: 50%;
        bottom: 30px;
        font-size: 17px;
        transition: visibility 0.5s, opacity 0.5s ease-out;
      }
      .toaster.show {
        visibility: visible;
        opacity: 1;
      }

      /* --- FUN STUFF POPUP --- */
      #funStuffPopup {
        display: none;
        position: fixed;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 80%;
        height: 80%;
        background-color: white;
        border: 2px solid #54c800;
        z-index: 10000;
        resize: both;
        overflow: auto;
      }
      #funStuffPopup iframe {
        width: 100%;
        height: 100%;
      }
      #funStuffPopupClose {
        position: absolute;
        top: 10px;
        right: 10px;
        background-color: red;
        color: white;
        border: none;
        padding: 5px 10px;
        cursor: pointer;
      }

      /* --- NEW RIGHT PANEL FOR BIG BOXES & TOGGLES --- */
      #rightPanel {
        position: fixed;
        top: 80px;
        right: 10px;
        width: 200px;
        background: rgba(0,0,0,0.2);
        border: 1px solid #54c800;
        border-radius: 4px;
        padding: 10px;
        z-index: 9999;
        display: flex;
        flex-direction: column;
        align-items: stretch;
        gap: 8px;
      }
      #rightPanel button {
        margin: 0;
        width: 100%;
      }
      #gameIPBox {
        background-color: #0077ff;
        text-align: center;
        cursor: pointer;
        padding: 8px 0;
        border-radius: 4px;
        color: white;
        font-weight: bold;
      }

      /* --- DRAG & DROP AREA FOR IMAGE UPLOAD (IMPROVED LOOK) --- */
      .drop-zone {
        position: relative;
        margin-top: 10px;
        padding: 15px;
        border: 2px dashed #54c800;
        border-radius: 5px;
        text-align: center;
        color: #fff;
        font-weight: bold;
        transition: background-color 0.2s;
        background-color: rgba(0, 0, 0, 0.4);
      }
      .drop-zone.dragover {
        background-color: rgba(84, 200, 0, 0.3);
      }
    `;
    document.head.appendChild(style);

    //------------------------------------------------------------------
    // LOCALSTORAGE HELPERS
    //------------------------------------------------------------------
    function getUsernameFromStorage() {
        const settingsJson = localStorage.getItem("settings");
        if (settingsJson) {
            try {
                const settings = JSON.parse(settingsJson);
                return settings.lastNick || '';
            } catch (e) {
                console.error("Error parsing settings from local storage:", e);
                return '';
            }
        }
        return '';
    }
    function getAvatarURL() {
        return localStorage.getItem('avatarURL') || '';
    }
    function setAvatarURL(url) {
        localStorage.setItem('avatarURL', url);
    }

    //------------------------------------------------------------------
    // TOAST / TOASTER
    //------------------------------------------------------------------
    function showToast(htmlMessage, duration) {
        const toast = document.createElement('div');
        toast.className = 'toast';
        toast.innerHTML = htmlMessage;
        document.body.appendChild(toast);

        toast.style.display = 'block';
        setTimeout(() => {
            if (document.body.contains(toast)) {
                document.body.removeChild(toast);
            }
        }, duration);
    }
    function showToaster(message) {
        const toaster = document.createElement('div');
        toaster.className = 'toaster';
        toaster.textContent = message;
        document.body.appendChild(toaster);
        setTimeout(() => {
            toaster.classList.add('show');
            setTimeout(() => {
                toaster.classList.remove('show');
                setTimeout(() => {
                    document.body.removeChild(toaster);
                }, 500);
            }, 2000);
        }, 10);
    }

    //------------------------------------------------------------------
    // MAIN CHAT CONTAINER
    //------------------------------------------------------------------
    const chatDiv = document.createElement('div');
    chatDiv.className = 'draggable';
    document.body.appendChild(chatDiv);

    // Status indicator
    const statusIndicator = document.createElement('div');
    statusIndicator.className = 'status-indicator';
    statusIndicator.textContent = 'Connecting...';
    chatDiv.appendChild(statusIndicator);

    // The container that holds avatar input + chat input + send button
    const messageContainer = document.createElement('div');
    messageContainer.id = 'messageContainer';
    chatDiv.appendChild(messageContainer);

    // Avatar input container
    const avatarInputContainer = document.createElement('div');
    avatarInputContainer.id = "avatarInputContainer";
    const avatarInputLabel = document.createElement('label');
    avatarInputLabel.textContent = "Avatar URL:";
    avatarInputContainer.appendChild(avatarInputLabel);

    const avatarInput = document.createElement('input');
    avatarInput.type = 'text';
    avatarInput.id = 'avatarInput';
    avatarInput.placeholder = "Enter Image URL";
    avatarInput.value = getAvatarURL();
    avatarInputContainer.appendChild(avatarInput);

    messageContainer.appendChild(avatarInputContainer);

    // Chat text input
    const inputArea = document.createElement('input');
    inputArea.id = 'inputArea';
    inputArea.placeholder = 'Enter your message';
    messageContainer.appendChild(inputArea);

    // Send button
    const sendButton = document.createElement('button');
    sendButton.textContent = "Send";
    sendButton.className = "send-button";
    messageContainer.appendChild(sendButton);

    // Message display area
    const messageArea = document.createElement('div');
    messageArea.id = "messageArea";
    chatDiv.appendChild(messageArea);

    //------------------------------------------------------------------
    // CHAT WEBSOCKET LOGIC
    //------------------------------------------------------------------
    let socket;
    function connectWebSocket() {
        socket = new WebSocket("wss://newjackchat2.glitch.me");

        socket.onopen = function() {
            console.log("Connected to the chat server.");
            statusIndicator.textContent = 'Connected';
            statusIndicator.style.backgroundColor = '#00C851';
        };
        socket.onmessage = function(event) {
            const data = JSON.parse(event.data);
            displayMessage(data.name, data.text, data.avatar || '');
            if (musicOn) messageSound.play();
        };
        socket.onclose = function() {
            console.log("WebSocket closed. Attempting to reconnect...");
            statusIndicator.textContent = 'Disconnected - Reconnecting...';
            statusIndicator.style.backgroundColor = '#ffbb33';
            setTimeout(connectWebSocket, 5000);
        };
        socket.onerror = function(error) {
            console.error("WebSocket Error:", error);
            statusIndicator.textContent = 'Connection Error';
            statusIndicator.style.backgroundColor = '#ff4444';
        };
    }
    connectWebSocket();

    function sendMessage() {
        const avatarURL = avatarInput.value.trim() || getAvatarURL();
        setAvatarURL(avatarURL); // store the avatar in localStorage
        const message = {
            name: getUsernameFromStorage().trim() || "Anonymous",
            text: inputArea.value.trim(),
            avatar: avatarURL
        };
        if (message.text) {
            socket.send(JSON.stringify(message));
            inputArea.value = "";
            simulateButtonClick();
        }
    }
    function simulateButtonClick() {
        sendButton.classList.add("active");
        setTimeout(() => {
            sendButton.classList.remove("active");
        }, 100);
    }

    sendButton.addEventListener("click", sendMessage);
    inputArea.addEventListener("keypress", function(event) {
        if (event.key === "Enter" && !event.shiftKey) {
            event.preventDefault();
            sendMessage();
        }
    });
    inputArea.addEventListener("keydown", function(event) {
        if (event.key === " ") {
            event.stopPropagation(); // prevent space from affecting gameplay
        }
    });

    //------------------------------------------------------------------
    // DISPLAY MESSAGES
    //------------------------------------------------------------------
    function displayMessage(name, text, avatar) {
        const messageElement = document.createElement("div");
        messageElement.className = "chat-message";

        const avatarImg = document.createElement("img");
        avatarImg.src = avatar || getAvatarURL();
        avatarImg.style.width = "30px";
        avatarImg.style.height = "30px";
        avatarImg.style.marginRight = "10px";
        avatarImg.style.verticalAlign = "middle";
        avatarImg.onerror = function() {
            avatarImg.src = getAvatarURL(); // fallback
        };

        const now = new Date();
        const hours = now.getHours().toString().padStart(2, "0");
        const minutes = now.getMinutes().toString().padStart(2, "0");
        const formattedTime = `${hours}:${minutes}`;

        const timestampSpan = document.createElement("span");
        timestampSpan.style.cssText = "color: #888; margin-right: 10px;";
        timestampSpan.textContent = formattedTime;

        const usernameSpan = document.createElement("span");
        usernameSpan.style.cssText = "font-weight: bold; margin-right: 5px;";
        usernameSpan.textContent = name + ":";

        messageElement.appendChild(avatarImg);
        messageElement.appendChild(timestampSpan);
        messageElement.appendChild(usernameSpan);

        // If text is an image link, display image
        if (/\.(jpeg|jpg|gif|png|svg|webp)$/i.test(text)) {
            const image = document.createElement("img");
            image.src = text;
            image.style.maxWidth = "75px";
            image.style.maxHeight = "75px";
            image.alt = "Sent image";
            image.onerror = function() {
                image.parentNode.removeChild(image);
                const errorText = document.createElement("span");
                errorText.textContent = " [Invalid image URL]";
                messageElement.appendChild(errorText);
            };
            messageElement.appendChild(image);
        } else {
            const messageText = document.createElement("span");
            messageText.textContent = text;
            messageElement.appendChild(messageText);
        }

        messageArea.appendChild(messageElement);

        // Remove after 60 seconds
        setTimeout(() => {
            if (messageArea.contains(messageElement)) {
                messageArea.removeChild(messageElement);
            }
        }, 60000);
    }

    //------------------------------------------------------------------
    // SHOW / HIDE CHAT + RIGHT PANEL
    //------------------------------------------------------------------
    document.addEventListener("auxclick", function (e) {
        // Double-click middle mouse to show chat & right panel
        if (e.button === 1 && e.detail === 2) {
            chatDiv.style.display = "flex";
            rightPanel.style.display = "flex";
        }
    });

    //------------------------------------------------------------------
    // CHAT DRAGGING
    //------------------------------------------------------------------
    function makeDraggable(element) {
        let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
        element.onmousedown = function (e) {
            // if user clicks close btn or an input or send button, don't drag
            if (
                e.target.classList.contains("close-button") ||
                e.target.tagName === "INPUT" ||
                e.target === sendButton
            ) {
                return;
            }
            e.preventDefault();
            pos3 = e.clientX;
            pos4 = e.clientY;
            document.onmouseup = closeDragElement;
            document.onmousemove = elementDrag;
        };
        function elementDrag(e) {
            e.preventDefault();
            pos1 = pos3 - e.clientX;
            pos2 = pos4 - e.clientY;
            pos3 = e.clientX;
            pos4 = e.clientY;
            element.style.top = element.offsetTop - pos2 + "px";
            element.style.left = element.offsetLeft - pos1 + "px";
        }
        function closeDragElement() {
            document.onmouseup = null;
            document.onmousemove = null;
        }
    }
    makeDraggable(chatDiv);

    //------------------------------------------------------------------
    // RESIZE HANDLE
    //------------------------------------------------------------------
    const resizeHandle = document.createElement("div");
    resizeHandle.className = "resize-handle";
    resizeHandle.textContent = "↗️";
    resizeHandle.style.color = "white";
    resizeHandle.style.backgroundColor = "#00d3ff";
    resizeHandle.style.display = "inline-block";
    resizeHandle.style.padding = "5px";
    resizeHandle.style.fontSize = "12px";
    resizeHandle.style.borderRadius = "50%";
    resizeHandle.style.cursor = "ns-resize";
    chatDiv.appendChild(resizeHandle);

    let startX, startY, startWidth, startHeight;
    resizeHandle.addEventListener("mousedown", function (e) {
        e.preventDefault();
        startX = e.clientX;
        startY = e.clientY;
        startWidth = parseInt(window.getComputedStyle(chatDiv).width, 10);
        startHeight = parseInt(window.getComputedStyle(chatDiv).height, 10);
        document.documentElement.addEventListener("mousemove", doDrag, false);
        document.documentElement.addEventListener("mouseup", stopDrag, false);
    });
    function doDrag(e) {
        chatDiv.style.width  = `${startWidth  + e.clientX - startX}px`;
        chatDiv.style.height = `${startHeight + e.clientY - startY}px`;
    }
    function stopDrag() {
        document.documentElement.removeEventListener("mousemove", doDrag, false);
        document.documentElement.removeEventListener("mouseup", stopDrag, false);
    }

    //------------------------------------------------------------------
    // CLOSE BUTTON
    //------------------------------------------------------------------
    const closeButton = document.createElement('div');
    closeButton.textContent = 'x';
    closeButton.className = 'close-button';
    closeButton.onclick = () => {
        // Hide both chat & right panel
        chatDiv.style.display = 'none';
        rightPanel.style.display = 'none';
        showToast(`
          <center>
            Special thanks to<br>
            <a href="https://imsolo.pro/" target="_blank"><img src="https://i.ibb.co/vC3f6M7f/K361z2W.png"></a>
            ImSolo.Pro & LegendsMod
            <a href="https://jimboy3100.github.io/" target="_blank">
              <img src="https://jimboy3100.github.io/banners/icon32croped.ico.gif" class="icon-link">
            </a><br><br>
            Double click middle mouse button to bring chat back up
          </center>
        `, 3000);
    };
    chatDiv.appendChild(closeButton);

    //------------------------------------------------------------------
    // MINIMAP AUTO-ACTIVATE
    //------------------------------------------------------------------
    window.addEventListener("load", function () {
      // 5 seconds after load, activate minimap
      setTimeout(function () {
        if (window.core && typeof core.setMinimap === 'function') {
          core.setMinimap(1);
          console.log("Minimap activated.");
          // 5 seconds after that, enable players on minimap
          setTimeout(function () {
            if (typeof core.playersMinimap === 'function') {
              core.playersMinimap(1);
              console.log("Player indicators on minimap activated.");
            }
          }, 5000);
        }
      }, 5000);
    });

    //------------------------------------------------------------------
    // CREATE RIGHT PANEL
    //------------------------------------------------------------------
    const rightPanel = document.createElement('div');
    rightPanel.id = 'rightPanel';
    document.body.appendChild(rightPanel);

    // 1) Music toggle (default OFF)
    const musicToggleButton = document.createElement('button');
    musicToggleButton.className = 'toggle-button';
    musicToggleButton.textContent = 'Sounds: OFF';
    musicToggleButton.onclick = () => {
        musicOn = !musicOn;
        musicToggleButton.textContent = musicOn ? 'Sounds: ON' : 'Sounds: OFF';
        if (musicOn) openSound.play();
    };
    rightPanel.appendChild(musicToggleButton);

    // 2) Minimap toggle
    let minimapOn = true;
    const minimapToggleButton = document.createElement('button');
    minimapToggleButton.className = 'toggle-button';
    minimapToggleButton.textContent = 'Minimap: ON';
    minimapToggleButton.onclick = () => {
        minimapOn = !minimapOn;
        minimapToggleButton.textContent = minimapOn ? 'Minimap: ON' : 'Minimap: OFF';
        if (window.core && typeof core.setMinimap === 'function') {
            core.setMinimap(minimapOn ? 1 : 0);
        }
    };
    rightPanel.appendChild(minimapToggleButton);

    // 3) Game IP Box
    const gameIPBox = document.createElement('div');
    gameIPBox.id = 'gameIPBox';
    gameIPBox.textContent = 'Your game IP: Not available';
    rightPanel.appendChild(gameIPBox);

    function updateGameIP() {
        if (typeof MC === "object" && typeof MC.getHost === "function") {
            const fullHost = MC.getHost() || 'live-arena-undefined.agar.io';
            const gameIP = fullHost.replace(/^live-arena-/, '').replace(/\.agar\.io$/, '');
            gameIPBox.textContent = `Your game IP: ${gameIP}`;
        } else {
            gameIPBox.textContent = 'Your game IP: Not available';
        }
    }
    setInterval(updateGameIP, 3000);

    // Click to copy IP
    gameIPBox.addEventListener('click', () => {
        if (gameIPBox.textContent.includes('Your game IP:')) {
            const gameIP = gameIPBox.textContent.replace('Your game IP: ', '');
            navigator.clipboard.writeText(gameIP).then(() => {
                showToaster('Game IP copied to clipboard!');
            }).catch(err => {
                console.error('Failed to copy text: ', err);
            });
        }
    });

    // 4) Fun stuff button
    const funStuffButton = document.createElement('button');
    funStuffButton.id = 'funStuffButton';
    funStuffButton.className = 'styled-button';
    funStuffButton.textContent = 'Agar.io Fun Stuff';
    funStuffButton.addEventListener('click', () => {
        document.getElementById('funStuffPopup').style.display = 'block';
    });
    rightPanel.appendChild(funStuffButton);

    //------------------------------------------------------------------
    // FUN STUFF POPUP
    //------------------------------------------------------------------
    const popupDiv = document.createElement('div');
    popupDiv.id = 'funStuffPopup';
    popupDiv.innerHTML = `
        <button id="funStuffPopupClose">Close 🕹️</button>
        <iframe src="https://newjackchat2.glitch.me/emojis.html"></iframe>
    `;
    document.body.appendChild(popupDiv);

    document.getElementById('funStuffPopupClose').addEventListener('click', () => {
        popupDiv.style.display = 'none';
    });

    //------------------------------------------------------------------
    // RUSSIA -> UKRAINE REPLACE
    //------------------------------------------------------------------
    (function () {
        function replaceText() {
            const options = document.querySelectorAll('option[value="RU-Russia"]');
            options.forEach(option => {
                const text = option.textContent;
                if (text.includes("Russia")) {
                    option.textContent = text.replace("Russia", "Ukraine");
                }
            });
        }
        replaceText();
        const observer = new MutationObserver(replaceText);
        observer.observe(document.body, { childList: true, subtree: true });
    })();

    //------------------------------------------------------------------
    // ACID MODE CHECKBOX
    //------------------------------------------------------------------
    (function() {
        function addAcidModeCheckbox() {
            if (document.querySelector('#acidMode')) return;
            const optionsDiv = document.querySelector('.options');
            if (!optionsDiv) return;

            const acidModeDiv = document.createElement('div');
            acidModeDiv.className = 'checkbox checkbox-info checkbox-circle option';

            const acidModeCheckbox = document.createElement('input');
            acidModeCheckbox.type = 'checkbox';
            acidModeCheckbox.id = 'acidMode';
            acidModeCheckbox.className = 'styled';

            const acidModeLabel = document.createElement('label');
            acidModeLabel.setAttribute('for', 'acidMode');
            acidModeLabel.textContent = 'Acid Mode';

            acidModeDiv.appendChild(acidModeCheckbox);
            acidModeDiv.appendChild(acidModeLabel);
            optionsDiv.appendChild(acidModeDiv);

            function applyShading(isChecked) {
                if (isChecked) {
                    acidModeLabel.style.backgroundColor = '#4CAF50';
                    acidModeLabel.style.color = '#FFFFFF';
                } else {
                    acidModeLabel.style.backgroundColor = '';
                    acidModeLabel.style.color = '';
                }
            }

            const savedState = localStorage.getItem('acidModeEnabled') === 'true';
            acidModeCheckbox.checked = savedState;
            applyShading(savedState);

            acidModeCheckbox.addEventListener('change', function() {
                const isChecked = acidModeCheckbox.checked;
                localStorage.setItem('acidModeEnabled', isChecked);
                if (window.core && typeof window.core.setAcid === 'function') {
                    window.core.setAcid(isChecked);
                    console.log('Acid mode set to:', isChecked);
                }
                applyShading(isChecked);
            });
        }

        const observer = new MutationObserver(function(mutations) {
            mutations.forEach(function(mutation) {
                if (mutation.type === 'childList' || mutation.type === 'subtree') {
                    addAcidModeCheckbox();
                }
            });
        });
        observer.observe(document.body, { childList: true, subtree: true });
        addAcidModeCheckbox();
    })();

    //------------------------------------------------------------------
    // DRAG-AND-DROP IMAGE UPLOAD (IMPROVED LOOK)
    //------------------------------------------------------------------
    function createUploadArea() {
        // Container with "Upload Image" button and drop zone
        const container = document.createElement('div');
        container.style.position = "relative";
        container.style.display = "inline-block";

        // Drop zone area
        const dropZone = document.createElement("div");
        dropZone.className = "drop-zone";
        dropZone.textContent = "Drag & Drop or Click 'Upload Image' above";
        dropZone.style.display = "none"; // will show on button click

        // File input
        const fileInput = document.createElement("input");
        fileInput.type = "file";
        fileInput.accept = "image/*";
        fileInput.id = "customImageUpload";
        // We'll hide the file input behind the zone if we want:
        fileInput.style.width = "100%";
        fileInput.style.height = "100%";
        fileInput.style.opacity = "0";
        fileInput.style.position = "absolute";
        fileInput.style.left = "0";
        fileInput.style.top = "0";
        fileInput.style.zIndex = "1";
        fileInput.style.cursor = "pointer";

        // Upload button
        const uploadButton = document.createElement("button");
        uploadButton.textContent = "Upload or drop an image here";
        uploadButton.style.color = "#fff";
        uploadButton.style.backgroundColor = "#54c800";
        uploadButton.style.border = "1px solid black";
        uploadButton.style.padding = "5px 10px";
        uploadButton.style.cursor = "pointer";

        // Clicking the upload button triggers the file input
        uploadButton.addEventListener("click", (e) => {
            e.stopPropagation();
            dropZone.style.display = "block"; // show the drop zone on click
            fileInput.click();
        });

        // Show/hide drop zone on fileInput click
        fileInput.addEventListener("click", () => {
            dropZone.style.display = "block";
        });

        // Handle file input "change" event
        fileInput.addEventListener("change", (e) => {
            if (e.target.files && e.target.files[0]) {
                handleFile(e.target.files[0]);
            }
        });

        // DRAG & DROP events
        dropZone.addEventListener("dragover", (e) => {
            e.preventDefault();
            dropZone.classList.add("dragover");
        });
        dropZone.addEventListener("dragleave", () => {
            dropZone.classList.remove("dragover");
        });
        dropZone.addEventListener("drop", (e) => {
            e.preventDefault();
            dropZone.classList.remove("dragover");
            if (e.dataTransfer.files && e.dataTransfer.files[0]) {
                handleFile(e.dataTransfer.files[0]);
            }
        });

        // Build the container
        container.appendChild(fileInput);
        container.appendChild(uploadButton);
        container.appendChild(dropZone);
        return container;
    }

    function handleFile(file) {
        if (!file) return;
        if (file.type.startsWith("image/")) {
            const reader = new FileReader();
            reader.onloadend = function() {
                const base64 = reader.result;
                drawImage(base64);
            };
            reader.readAsDataURL(file);
        } else {
            console.log("Invalid file type or no file dropped.");
        }
    }

    function drawImage(base64) {
        // The code below draws the image to #skin-editor-canvas (if that exists),
        // or do anything else you'd like with the base64
        const canvas = document.getElementById("skin-editor-canvas");
        if (!canvas) {
            console.log("No skin-editor-canvas found, but here's your base64:\n", base64);
            return;
        }
        const context = canvas.getContext("2d");
        const image = new Image();
        image.onload = function () {
            canvas.width = 512;
            canvas.height = 512;
            context.drawImage(image, 0, 0, 512, 512);
            context.save();
        };
        image.src = base64;
    }

    //------------------------------------------------------------------
    // ADD SKIN FIELD RIGHT BELOW AVATAR URL
    //------------------------------------------------------------------
    function addCustomSkinField() {
        // We'll place it inside #avatarInputContainer, right below the Avatar URL input
        const container = document.getElementById('avatarInputContainer');
        if (!container) return;

        const wrapper = document.createElement('div');
        wrapper.style.marginTop = '6px';

        const urlInput = document.createElement('input');
        urlInput.placeholder = 'Enter skin URL or leave blank';
        urlInput.style.marginRight = '5px';
        urlInput.style.width = '70%';
        urlInput.style.border = '1px solid #666';
        urlInput.style.background = 'rgba(255,255,255,0.1)';
        urlInput.style.color = '#fff';
        urlInput.style.borderRadius = '3px';

        const loadButton = createButton('Turn Skin on', '#54c800', '#347f01', () => {
            let skinURL = urlInput.value;
            if (!skinURL) {
                skinURL = 'default_skin_url';
                console.log('No URL provided. Using default skin.');
            }
            console.log(`Setting skin to ${skinURL}`);
            try {
                core.registerSkin(null, "%SubscribeToBeeChasnyAgario", skinURL, 2, null);
                core.loadSkin("%SubscribeToBeeChasnyAgario");
            } catch (e) {
                console.error("Error loading the skin:", e);
            }
        });
        const unloadButton = createButton('Turn Skin off', '#c85400', '#7f3401', () => {
            try {
                if (typeof core.unregisterSkin === "function") {
                    core.unregisterSkin("%SubscribeToBeeChasnyAgario");
                } else {
                    console.error("unregisterSkin function is not available. Resetting manually...");
                }
                urlInput.value = '';
                console.log("Skin reset or unloaded.");
            } catch (e) {
                console.error("Error attempting to unload the skin:", e);
            }
        });

        wrapper.appendChild(urlInput);
        wrapper.appendChild(loadButton);
        wrapper.appendChild(unloadButton);
        container.appendChild(wrapper);
    }
    function createButton(text, bgColor, hoverColor, action) {
        const button = document.createElement('button');
        button.style.backgroundColor = bgColor;
        button.style.color = "#FFFFFF";
        button.style.border = "none";
        button.style.padding = "5px 10px";
        button.style.cursor = "pointer";
        button.style.marginLeft = "5px";
        button.innerText = text;
        button.onmouseover = function() {
            this.style.backgroundColor = hoverColor;
        };
        button.onmouseout = function() {
            this.style.backgroundColor = bgColor;
        };
        button.addEventListener('click', action);
        return button;
    }

    //------------------------------------------------------------------
    // INSERT DRAG & DROP UPLOAD AREA INTO .right-tools (optional)
    //------------------------------------------------------------------
    function observeTargetContainer() {
        const observer = new MutationObserver((mutationsList) => {
            for (let mutation of mutationsList) {
                if (mutation.type === 'childList') {
                    const target = document.querySelector(".right-tools");
                    if (target && !target.querySelector("#customImageUpload")) {
                        const uploadArea = createUploadArea();
                        const newDiv = document.createElement("div");
                        newDiv.style.marginTop = "50px";
                        newDiv.appendChild(uploadArea);

                        if (target.querySelector(".save")) {
                            target.querySelector(".save").appendChild(newDiv);
                        } else {
                            target.appendChild(newDiv);
                        }
                    }
                }
            }
        });
        observer.observe(document.body, { childList: true, subtree: true });
    }

    //------------------------------------------------------------------
    // ACTIVATE EVERYTHING
    //------------------------------------------------------------------
    addCustomSkinField();   // Adds "Turn Skin on/off" right under the avatar URL
    observeTargetContainer(); // Adds drag/drop in the .right-tools panel (if present)

})();
(function () {
    'use strict';

// --- Remove the default agar.io background image ---
const originalDrawImage = CanvasRenderingContext2D.prototype.drawImage;
CanvasRenderingContext2D.prototype.drawImage = function (img) {
    // Skip drawing the default background
    if (img && img.src === "https://agar.io/img/background.png") {
        return;
    }
    originalDrawImage.apply(this, arguments);
};

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址