GarticBetter

Gartic.io Better

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey, Greasemonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

You will need to install an extension such as Tampermonkey to install this script.

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्क्रिप्ट व्यवस्थापक एक्स्टेंशन इंस्टॉल करावे लागेल.

(माझ्याकडे आधीच युझर स्क्रिप्ट व्यवस्थापक आहे, मला इंस्टॉल करू द्या!)

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

(माझ्याकडे आधीच युझर स्टाईल व्यवस्थापक आहे, मला इंस्टॉल करू द्या!)

// ==UserScript==
// @name         GarticBetter
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Gartic.io Better
// @author       iQuez
// @homepageURL  https://discord.gg/2c4qhYudBP
// @license      MIT
// @match        *://gartic.io/*
// @icon         https://i.ibb.co/5WD8w1yK/Gartic-Better.png
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    let settings = JSON.parse(localStorage.getItem('iquez_settings') || JSON.stringify({
        borderColor: '#ff0000',
        nameColor: '#ffffff',
        chatColor: '#ff0000',
        enableBorder: true,
        enableNameColor: true,
        enableChatColor: true,
        enablePing: true,
        enableDarkMode: true
    }));

    let capturedAvatarUrl = '';

    const style = document.createElement('style');
    const updateStyles = () => {
        let baseCSS = `
            .scrollElements a { position: relative !important; padding-bottom: 35px !important; }

            .iquez-watch-btn {
                position: absolute; bottom: 8px; left: 8px; background-color: #0a5efb;
                color: white; border: none; border-radius: 5px; padding: 5px 0; font-weight: bold; font-size: 11px;
                cursor: pointer; box-shadow: 0 3px 0 #0742b8; transition: all 0.1s ease; text-transform: uppercase;
                width: calc(100% - 16px); display: block; text-align: center; z-index: 10;
            }

            #popUp.iquez-my-popup .content.profile .contentPopup .avatar,
            .home .anonymus .avatar,
            .logged .userLogged .avatar,
            .user.you .avatar {
                box-shadow: ${settings.enableBorder ? `0 0 0 4px ${settings.borderColor}` : 'none'} !important;
                border-radius: 50% !important;
                border-color: transparent !important;
            }

            .home .anonymus .avatar {
                overflow: visible !important;
            }

            .selectAvatar {
                z-index: 10 !important;
            }

            #popUp.iquez-my-popup .content.profile .contentPopup .avatar canvas,
            #popUp.iquez-my-popup .content.profile .contentPopup .avatar .av {
                width: 100% !important;
                height: 100% !important;
                border-radius: 50% !important;
                display: block !important;
            }

            .user.you .infosPlayer .nick,
            #popUp.iquez-my-popup .content.profile .contentPopup .nick,
            .home .anonymus .fieldset.nick input,
            header:not(.game) .userLogged .infos span,
            header:not(.game) .userLogged .infos strong,
            .scrollElements .iquez-my-msg strong {
                color: ${settings.enableNameColor ? settings.nameColor : ''} !important;
            }

            .textGame input[type="text"] {
                color: ${settings.enableChatColor ? settings.chatColor : ''} !important;
            }

            #iquez-settings-panel {
                position: fixed; top: 85px; left: 15px; width: 280px; background: #1a1a1a; color: white;
                z-index: 1000000; border-radius: 10px; padding: 15px; border: 2px solid #333;
                font-family: sans-serif; display: none; box-shadow: 0 5px 15px rgba(0,0,0,0.5);
                max-height: 80vh; overflow-y: auto;
            }
            #iquez-settings-panel::-webkit-scrollbar { width: 6px; }
            #iquez-settings-panel::-webkit-scrollbar-thumb { background: #444; border-radius: 3px; }

            .iquez-panel-title { font-weight: bold; margin-bottom: 15px; border-bottom: 1px solid #333; padding-bottom: 5px; text-align: center; font-size: 16px; letter-spacing: 1px; }
            .iquez-option { margin-bottom: 15px; display: flex; align-items: center; justify-content: space-between; font-size: 13px; }
            .iquez-controls { display: flex; align-items: center; gap: 12px; }
            .iquez-option input[type="color"] { border: none; width: 35px; height: 25px; cursor: pointer; background: none; padding: 0; border-radius: 4px; }
            .iquez-btn-save { width: 100%; background: #0a5efb; color: white; border: none; padding: 10px; border-radius: 5px; cursor: pointer; font-weight: bold; margin-top: 10px; box-shadow: 0 3px 0 #0742b8; transition: transform 0.1s; }
            .iquez-btn-save:active { transform: translateY(2px); box-shadow: none; }

            .iquez-watermark { position: fixed; top: 15px; left: 15px; z-index: 999999; font-family: sans-serif; text-shadow: 1px 1px 3px rgba(0,0,0,0.8); }
            .iquez-watermark .brand { color: red !important; font-size: 22px; font-weight: 900; }
            .iquez-watermark .author { color: white; font-size: 14px; font-weight: bold; display: inline-block;}
            #iquez-gear-icon { cursor: pointer; font-size: 18px; margin-left: 5px; display: inline-block; transition: transform 0.3s ease; vertical-align: middle; }
            #iquez-gear-icon:hover { transform: rotate(90deg); }

            #iquez-ping-display {
                position: fixed; top: 15px; right: 15px; z-index: 999999;
                background: rgba(0, 0, 0, 0.6); color: white; padding: 6px 12px;
                border-radius: 8px; font-family: sans-serif; font-size: 13px;
                font-weight: bold; text-shadow: 1px 1px 2px black;
                display: ${settings.enablePing ? 'flex' : 'none'};
                align-items: center; gap: 6px; box-shadow: 0 2px 5px rgba(0,0,0,0.3);
            }

            .iquez-switch { position: relative; display: inline-block; width: 36px; height: 20px; }
            .iquez-switch input { opacity: 0; width: 0; height: 0; }
            .iquez-slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #444; transition: .3s; border-radius: 20px; box-shadow: inset 0 0 5px rgba(0,0,0,0.5); }
            .iquez-slider:before { position: absolute; content: ""; height: 14px; width: 14px; left: 3px; bottom: 3px; background-color: white; transition: .3s; border-radius: 50%; box-shadow: 0 2px 4px rgba(0,0,0,0.3); }
            input:checked + .iquez-slider { background-color: #0a5efb; }
            input:checked + .iquez-slider:before { transform: translateX(16px); }

            #iquez-rejoin {
                width: 26px !important;
                height: 26px !important;
                background-color: transparent !important;
                background-image: url('https://i.ibb.co/vCWPFjVq/rejoin.png') !important;
                background-size: contain !important;
                background-repeat: no-repeat !important;
                background-position: center !important;
                border: none !important;
                cursor: pointer !important;
                padding: 0 !important;
                margin: 0 6px !important;
                display: inline-flex !important;
                align-items: center !important;
                justify-content: center !important;
                transition: transform 0.2s ease;
                position: relative;
            }
            #iquez-rejoin:hover {
                transform: scale(1.1);
            }
        `;

        if (settings.enableDarkMode) {
            baseCSS += `
                #background { background-color: transparent !important; }
                #fundo { opacity: 0 !important; }

                #background:before {
                    background-color: #252525 !important;
                    background-image: url(/static/images/new/textura.png) !important;
                    content: "" !important;
                    width: 200% !important;
                    display: block !important;
                    position: absolute !important;
                    z-index: 0 !important;
                    left: 50% !important;
                    top: 50% !important;
                    height: 200% !important;
                    transform: translate(-50%, -50%) rotate(345deg) !important;
                }

                #screens > div {
                    background-color: #252525 !important;
                    box-shadow: -2px 2px 4px 0 rgba(0, 0, 0, 0.3) !important;
                    border-radius: 10px !important;
                }

                .home .anonymus .fieldset.nick input,
                .home .logged .fieldset.nick input {
                    background-color: #252525 !important;
                }

                .home .lastRooms>div ul li:not(.emptyList):not(.empty) {
                    background-color: #252525 !important;
                    border: 5px solid #6f6f6f !important;
                }

                .home .lastRooms>div ul li:not(.emptyList):not(.empty).bgEmptyRoom {
                    background-color: #252525 !important;
                    border-color: #6f6f6f !important;
                }

                input[type=email], input[type=text] {
                    background-color: #252525 !important;
                }

                #screens .content.bg {
                    background-color: #252525 !important;
                    border: 1px solid #868d96 !important;
                }

                .rooms .scroll a:not(.emptyList):not(.loading) {
                    background-color: #252525 !important;
                    border: 7px solid #868d96 !important;
                }

                .rooms .scroll a:not(.emptyList):not(.loading).bgEmptyRoom {
                    background-color: #535353 !important;
                    border-color: #e4edef !important;
                }

                #screenRoom .ctt #interaction,
                #screenRoom.common .ctt #interaction {
                    background-color: #252525 !important;
                }

                #screenRoom .ctt #interaction #chat,
                #screenRoom.common .ctt #interaction #chat {
                    background-color: #252525 !important;
                }

                .textGame input[type="text"] {
                    background-color: #252525 !important;
                }

                #screenRoom .ctt .users-tools #users {
                    background-color: #252525 !important;
                    border: 1px solid #979797 !important;
                }

                #screenRoom .ctt .users-tools #users ul {
                    background-color: #252525 !important;
                }

                #popUp .content {
                    background-color: #252525 !important;
                    border: 1px solid #868d96 !important;
                }
            `;
        }

        style.innerHTML = baseCSS;
    };
    updateStyles();
    document.head.appendChild(style);

    function createMenu() {
        if (document.querySelector('.iquez-watermark')) return;
        const wm = document.createElement('div');
        wm.className = 'iquez-watermark';
        wm.innerHTML = `<div class="brand">GarticBetter</div><div class="author">by iQuez</div><div id="iquez-gear-icon">⚙️</div>`;
        document.body.appendChild(wm);

        const panel = document.createElement('div');
        panel.id = 'iquez-settings-panel';
        panel.innerHTML = `
            <div class="iquez-panel-title">GarticBetter Menü</div>

            <div class="iquez-option">
                <span>Karanlık Mod:</span>
                <label class="iquez-switch">
                    <input type="checkbox" id="iq-dark-t" ${settings.enableDarkMode ? 'checked' : ''}>
                    <span class="iquez-slider"></span>
                </label>
            </div>
            <hr style="border:0; border-top:1px solid #333; margin: 12px 0;">

            <div class="iquez-option">
                <span>Çerçeve Rengi:</span>
                <div class="iquez-controls">
                    <label class="iquez-switch">
                        <input type="checkbox" id="iq-border-t" ${settings.enableBorder ? 'checked' : ''}>
                        <span class="iquez-slider"></span>
                    </label>
                    <input type="color" id="iq-border-c" value="${settings.borderColor}">
                </div>
            </div>
            <hr style="border:0; border-top:1px solid #333; margin: 12px 0;">

            <div class="iquez-option">
                <span>İsim Rengi:</span>
                <div class="iquez-controls">
                    <label class="iquez-switch">
                        <input type="checkbox" id="iq-name-t" ${settings.enableNameColor ? 'checked' : ''}>
                        <span class="iquez-slider"></span>
                    </label>
                    <input type="color" id="iq-name-c" value="${settings.nameColor}">
                </div>
            </div>
            <hr style="border:0; border-top:1px solid #333; margin: 12px 0;">

            <div class="iquez-option">
                <span>Mesaj Rengi:</span>
                <div class="iquez-controls">
                    <label class="iquez-switch">
                        <input type="checkbox" id="iq-chat-t" ${settings.enableChatColor ? 'checked' : ''}>
                        <span class="iquez-slider"></span>
                    </label>
                    <input type="color" id="iq-chat-c" value="${settings.chatColor}">
                </div>
            </div>
            <hr style="border:0; border-top:1px solid #333; margin: 12px 0;">

            <div class="iquez-option">
                <span>Ping Göstergesi:</span>
                <label class="iquez-switch">
                    <input type="checkbox" id="iq-ping-t" ${settings.enablePing ? 'checked' : ''}>
                    <span class="iquez-slider"></span>
                </label>
            </div>
            <button class="iquez-btn-save" id="iq-save-btn">KAYDET</button>
        `;
        document.body.appendChild(panel);

        document.getElementById('iquez-gear-icon').onclick = () => {
            panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
        };

        document.getElementById('iq-save-btn').onclick = () => {
            settings.borderColor = document.getElementById('iq-border-c').value;
            settings.nameColor = document.getElementById('iq-name-c').value;
            settings.chatColor = document.getElementById('iq-chat-c').value;
            settings.enableBorder = document.getElementById('iq-border-t').checked;
            settings.enableNameColor = document.getElementById('iq-name-t').checked;
            settings.enableChatColor = document.getElementById('iq-chat-t').checked;
            settings.enablePing = document.getElementById('iq-ping-t').checked;
            settings.enableDarkMode = document.getElementById('iq-dark-t').checked;

            localStorage.setItem('iquez_settings', JSON.stringify(settings));
            updateStyles();
            panel.style.display = 'none';
        };
    }

    function createPingDisplay() {
        if (!document.getElementById('iquez-ping-display')) {
            const pingEl = document.createElement('div');
            pingEl.id = 'iquez-ping-display';
            pingEl.innerHTML = `<span style="color:#00ff00">●</span> 0 ms`;
            document.body.appendChild(pingEl);

            setInterval(() => {
                if (settings.enablePing) {
                    const start = Date.now();
                    fetch('/?t=' + start, { method: 'HEAD', cache: 'no-store' }).then(() => {
                        const ping = Date.now() - start;
                        let color = '#00ff00';
                        if (ping > 80) color = '#ffcc00';
                        if (ping > 150) color = '#ff3333';
                        document.getElementById('iquez-ping-display').innerHTML = `<span style="color:${color}">●</span> ${ping} ms`;
                    }).catch(() => {});
                }
            }, 2000);
        }
    }

    const originalDrawImage = CanvasRenderingContext2D.prototype.drawImage;
    CanvasRenderingContext2D.prototype.drawImage = function(...args) {
        const img = args[0];
        if (this.canvas && this.canvas.closest) {
            const isAvatarCanvas = this.canvas.closest('.avatar') || this.canvas.closest('#popUp');
            if (isAvatarCanvas && img && img.src && img.src.startsWith('http')) {
                capturedAvatarUrl = img.src;
            }
        }
        return originalDrawImage.apply(this, args);
    };

    function applyModifications() {
        const rejoinRoom = sessionStorage.getItem('iquez_rejoin_room');
        if (rejoinRoom) {
            const isHome = document.querySelector('.content.home') || window.location.pathname === '/';
            if (isHome) {
                sessionStorage.removeItem('iquez_rejoin_room');
                window.location.href = window.location.origin + rejoinRoom;
                return;
            }
        }

        createMenu();
        createPingDisplay();

        const exitBtn = document.getElementById('exit');
        if (exitBtn && !document.getElementById('iquez-rejoin')) {
            const rejoinBtn = document.createElement('button');
            rejoinBtn.id = 'iquez-rejoin';
            rejoinBtn.innerHTML = '<span class="tooltip">Yeniden Gir</span>';

            rejoinBtn.onclick = () => {
                const roomUrl = window.location.pathname;
                if (roomUrl && roomUrl !== '/') {
                    sessionStorage.setItem('iquez_rejoin_room', roomUrl);
                    exitBtn.click();

                    let attempts = 0;
                    const checkYes = setInterval(() => {
                        const yesBtn = document.querySelector('.ic-yes');
                        const popUp = document.getElementById('popUp');

                        if (yesBtn && popUp && window.getComputedStyle(popUp).display !== 'none') {
                            clearInterval(checkYes);
                            setTimeout(() => {
                                yesBtn.click();
                            }, 100);
                        }

                        if (++attempts > 100) clearInterval(checkYes);
                    }, 20);
                }
            };

            exitBtn.parentNode.insertBefore(rejoinBtn, exitBtn);
        }

        document.querySelectorAll('.scrollElements a:not(.has-watch-btn)').forEach(room => {
            room.classList.add('has-watch-btn');
            const watchBtn = document.createElement('div');
            watchBtn.className = 'iquez-watch-btn';
            watchBtn.innerHTML = '👁️ İZLE';
            watchBtn.onclick = (e) => {
                e.preventDefault(); e.stopPropagation();
                let url = room.getAttribute('href');
                window.open((url.startsWith('http') ? url : window.location.origin + url) + '/viewer', '_blank');
            };
            room.appendChild(watchBtn);
        });

        const popupButtons = document.querySelector('#popUp .content.profile .buttons');
        if (popupButtons && !popupButtons.classList.contains('has-pic-btn')) {
            popupButtons.classList.add('has-pic-btn');
            const picBtn = document.createElement('button');
            picBtn.className = 'btYellowBig iquez-profile-btn';
            picBtn.innerHTML = '<strong>PROFİL RESMİ</strong>';
            picBtn.onclick = () => { if (capturedAvatarUrl) window.open(capturedAvatarUrl, '_blank'); };
            popupButtons.appendChild(picBtn);
        }

        let myNick = (document.querySelector('.user.you .infosPlayer .nick') ||
                      document.querySelector('.logged .userLogged .infos .nick') ||
                      document.querySelector('.logged .userLogged .infos strong') ||
                      document.querySelector('header:not(.game) .userLogged .infos span'))?.innerText;

        const popup = document.querySelector('#popUp');
        if (popup && myNick) {
            const pNick = popup.querySelector('.content.profile .contentPopup .nick');
            if (pNick?.innerText.trim() === myNick.trim()) {
                popup.classList.add('iquez-my-popup');
            } else {
                popup.classList.remove('iquez-my-popup');
            }
        }

        if (myNick) {
            document.querySelectorAll('.scrollElements .msg:not(.iquez-processed)').forEach(msg => {
                msg.classList.add('iquez-processed');
                const strong = msg.querySelector('strong');
                if (strong && strong.innerText.replace(':', '').trim() === myNick.trim()) {
                    msg.classList.add('iquez-my-msg');
                    if (settings.enableChatColor) {
                        const target = msg.querySelector('span') || msg;
                        target.style.setProperty('color', settings.chatColor, 'important');
                    }
                }
            });
        }
    }

    const observer = new MutationObserver(() => applyModifications());
    observer.observe(document.body, { childList: true, subtree: true });
    applyModifications();
})();