GarticFlix V1 Elite

Ultimate Gartic Experience

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name GarticFlix V1 Elite
// @namespace http://tampermonkey.net/
// @version v.11.0
// @description Ultimate Gartic Experience
// @author Akíra & ygn
// @match https://gartic.io/*
// @icon https://www.google.com/s2/favicons?domain=gartic.io
// @grant none
// ==/UserScript==

if (window.location.href.indexOf("?L") !== -1) {
    const styles = `
        @import url('https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700&display=swap');
        
        :root {
            --bg-primary: #0f172a;
            --bg-secondary: #1e293b;
            --accent: #6366f1;
            --accent-hover: #4f46e5;
            --text: #e2e8f0;
        }

        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Outfit', sans-serif;
        }

        @keyframes fadeIn {
            from { opacity: 0; transform: translateY(20px); }
            to { opacity: 1; transform: translateY(0); }
        }

        @keyframes shimmer {
            0% { background-position: -1000px 0; }
            100% { background-position: 1000px 0; }
        }

        @keyframes float {
            0% { transform: translateY(0px); }
            50% { transform: translateY(-10px); }
            100% { transform: translateY(0px); }
        }

        .container {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100vh;
            background: var(--bg-primary);
            color: var(--text);
            overflow-y: auto;
            z-index: 9999;
            padding: 20px;
        }

        .header {
            background: linear-gradient(135deg, var(--accent), var(--accent-hover));
            padding: 20px;
            border-radius: 15px;
            text-align: center;
            margin-bottom: 20px;
            position: relative;
            overflow: hidden;
            animation: float 6s ease-in-out infinite;
        }

        .header::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
            animation: shimmer 2s infinite;
        }

        .header h1 {
            font-size: 28px;
            font-weight: 700;
            color: white;
            text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
            margin: 0;
        }

        .controls {
            background: var(--bg-secondary);
            border-radius: 15px;
            padding: 20px;
            margin-bottom: 20px;
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 15px;
            animation: fadeIn 0.5s ease-out;
        }

        .control-input {
            width: 100%;
            padding: 12px;
            background: rgba(255,255,255,0.1);
            border: 2px solid var(--accent);
            border-radius: 10px;
            color: var(--text);
            font-size: 16px;
            transition: all 0.3s ease;
        }

        .control-input:focus {
            outline: none;
            border-color: var(--accent-hover);
            box-shadow: 0 0 15px rgba(99, 102, 241, 0.3);
        }

        .stats {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
            gap: 15px;
            margin-bottom: 20px;
        }

        .stat-card {
            background: var(--bg-secondary);
            padding: 15px;
            border-radius: 10px;
            text-align: center;
        }

        .stat-value {
            font-size: 24px;
            font-weight: 700;
            color: var(--accent);
        }

        .stat-label {
            font-size: 14px;
            opacity: 0.8;
            margin-top: 5px;
        }

        .rooms-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
            gap: 20px;
            animation: fadeIn 0.6s ease-out;
        }

        .room-card {
            background: var(--bg-secondary);
            border-radius: 15px;
            padding: 20px;
            transition: all 0.3s ease;
            position: relative;
            overflow: hidden;
        }

        .room-card:hover {
            transform: translateY(-5px);
            box-shadow: 0 10px 20px rgba(0,0,0,0.2);
        }

        .room-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 15px;
            padding-bottom: 10px;
            border-bottom: 1px solid rgba(99, 102, 241, 0.2);
        }

        .room-title {
            font-size: 18px;
            font-weight: 600;
            color: var(--accent);
        }

        .room-stats {
            font-size: 14px;
            opacity: 0.8;
        }

        .room-actions {
            display: flex;
            gap: 10px;
        }

        .btn {
            padding: 10px 20px;
            border-radius: 8px;
            font-weight: 500;
            cursor: pointer;
            transition: all 0.3s ease;
            border: none;
            flex: 1;
            font-size: 14px;
        }

        .btn-primary {
            background: var(--accent);
            color: white;
        }

        .btn-primary:hover {
            background: var(--accent-hover);
            transform: translateY(-2px);
        }

        .btn-secondary {
            background: transparent;
            border: 2px solid var(--accent);
            color: var(--accent);
        }

        .btn-secondary:hover {
            background: var(--accent);
            color: white;
        }

        .users-grid {
            display: none;
            grid-template-columns: repeat(auto-fill, minmax(60px, 1fr));
            gap: 10px;
            margin-top: 15px;
            padding: 15px;
            background: rgba(0,0,0,0.2);
            border-radius: 10px;
            animation: fadeIn 0.3s ease-out;
        }

        .user-avatar {
            width: 60px;
            height: 60px;
            border-radius: 50%;
            cursor: pointer;
            transition: all 0.3s ease;
            border: 2px solid var(--accent);
        }

        .user-avatar:hover {
            transform: scale(1.1);
            border-color: var(--accent-hover);
        }

        .nickname-tooltip {
            position: absolute;
            background: var(--accent);
            color: white;
            padding: 5px 10px;
            border-radius: 5px;
            font-size: 12px;
            z-index: 1000;
            pointer-events: none;
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        @media (max-width: 768px) {
            .controls {
                grid-template-columns: 1fr;
            }
            
            .rooms-grid {
                grid-template-columns: 1fr;
            }
        }
    `;

    document.head.innerHTML = `<style>${styles}</style>`;






















    const mainContainer = document.createElement("div");
    mainContainer.className = "container";
    mainContainer.innerHTML = `
        <div class="header">
            <h1>GarticFlix Elite</h1>
        </div>

        <div class="stats">
            <div class="stat-card">
                <div class="stat-value" id="totalRooms">0</div>
                <div class="stat-label">Aktif Odalar</div>
            </div>
            <div class="stat-card">
                <div class="stat-value" id="totalPlayers">0</div>
                <div class="stat-label">Toplam Oyuncu</div>
            </div>
            <div class="stat-card">
                <div class="stat-value" id="onlineUsers">0</div>
                <div class="stat-label">Çevrimiçi</div>
            </div>
        </div>

        <div class="controls">
            <input type="text" class="control-input" placeholder="Oda veya Oyuncu Ara..." onkeyup="window.filterRooms(this.value)">
            
            <select class="control-input theme-select" onchange="window.updateRooms()">
                <option value="">Tüm Temalar</option>
                <option value="1">Genel</option>
                <option value="28">Anime</option>
                <option value="30">Diğer</option>
                <option value="12">Oyunlar</option>
                <option value="24">Youtuber</option>
                <option value="11">LoL</option>
                <option value="2">Hayvanlar</option>
                <option value="31">Minecraft</option>
                <option value="4">Yiyecekler</option>
                <option value="9">Animasyon</option>
                <option value="35">Naruto</option>
                <option value="16">Bayraklar</option>
                <option value="10">Şarkılar</option>
                <option value="17">Futbol</option>
                <option value="26">Logo</option>
                <option value="5">Fiiller</option>
                <option value="33">FNAF</option>
                <option value="3">Nesneler</option>
                <option value="6">Ülkeler</option>
                <option value="7">Markalar</option>
                <option value="8">Filmler</option>
            </select>

            <select class="control-input lang-select" onchange="window.updateRooms()">
                <option value="8">Türkçe</option>
                <option value="2">English</option>
                <option value="3">Español</option>
                <option value="1">Português</option>
                <option value="7">Русский</option>
                <option value="13">Tiếng Việt</option>
                <option value="15">日本語</option>
                <option value="20">한국어</option>
                <option value="23">Azərbaycanca</option>
                <option value="45">Bahasa Indonesia</option>
                <option value="11">Čeština</option>
                <option value="14">Deutsch</option>
                <option value="4">Français</option>
                <option value="6">Italiano</option>
                <option value="44">Magyar</option>
                <option value="18">Nederlands</option>
                <option value="10">Polski</option>
                <option value="58">Română</option>
                <option value="22">Slovenčina</option>
                <option value="21">български език</option>
                <option value="40">עברית</option>
                <option value="19">العربية</option>
                <option value="34">فارسی</option>
                <option value="12">ภาษาไทย</option>
                <option value="16">中文 (简化字)</option>
                <option value="9">中文 (臺灣)</option>
                <option value="17">中文 (香港)</option>
            </select>
        </div>

        <div class="rooms-grid"></div>
    `;

    document.body.appendChild(mainContainer);

    let roomsData = [];
    let filteredRooms = [];

    function createRoomCard(room) {
        const card = document.createElement('div');
        card.className = 'room-card';
        card.innerHTML = `
            <div class="room-header">
                <div class="room-title">#${room.code}</div>
                <div class="room-stats">${room.quant}/${room.max} Oyuncu</div>
            </div>
            <div class="room-actions">
                <button class="btn btn-primary" onclick="window.joinRoom('${room.code}')">Katıl</button>
                <button class="btn btn-secondary" onclick="window.watchRoom('${room.code}')">İzle</button>
                <button class="btn btn-primary" onclick="window.showUsers('${room.code}')">Kullanıcılar</button>
            </div>
            <div class="users-grid" id="users-${room.code}"></div>
        `;
        return card;
    }

    window.filterRooms = (query) => {
        query = query.toLowerCase();
        filteredRooms = roomsData.filter(room => 
            room.code.toLowerCase().includes(query) ||
            (room.players && room.players.some(player => 
                player.nick.toLowerCase().includes(query)
            ))
        );
        updateRoomsDisplay();
    };

    window.updateRooms = () => {
        const theme = document.querySelector('.theme-select').value;
        const lang = document.querySelector('.lang-select').value;
        
        let url = `https://gartic.io/req/list?language[]=${lang}`;
        if (theme) url += `&subject[]=${theme}`;

        fetch(url)
            .then(response => response.json())
            .then(data => {
                roomsData = data;
                filteredRooms = data;
                updateRoomsDisplay();
                updateStats();
            });
    };

    function updateStats() {
        document.getElementById('totalRooms').textContent = roomsData.length;
        const totalPlayers = roomsData.reduce((acc, room) => acc + room.quant, 0);
        document.getElementById('totalPlayers').textContent = totalPlayers;
        document.getElementById('onlineUsers').textContent = totalPlayers + Math.floor(Math.random() * 100);
    }















    function updateRoomsDisplay() {
        const container = document.querySelector('.rooms-grid');
        container.innerHTML = '';
        filteredRooms.forEach(room => {
            container.appendChild(createRoomCard(room));
        });
    }

    window.joinRoom = (code) => {
        window.open(`https://gartic.io/${code}`, '_blank');
    };

    window.watchRoom = (code) => {
        window.open(`https://gartic.io/${code}/viewer`, '_blank');
    };

    window.showUsers = (roomCode) => {
        const usersGrid = document.getElementById(`users-${roomCode}`);
        const isVisible = usersGrid.style.display === 'grid';
        
        if (!isVisible) {
            usersGrid.style.display = 'grid';
            loadRoomUsers(roomCode);
        } else {
            usersGrid.style.display = 'none';
        }
    };

    function loadRoomUsers(roomCode) {
        const usersGrid = document.getElementById(`users-${roomCode}`);
        usersGrid.innerHTML = '';

        const servers = ['01', '02', '03', '04', '05', '06'];
        let connectedServer = false;

        function tryNextServer(index) {
            if (index >= servers.length || connectedServer) return;

            const ws = new WebSocket(`wss://server${servers[index]}.gartic.io/socket.io/?EIO=3&transport=websocket`);
            
            ws.onopen = () => {
                ws.send(`42[12,{"v":20000,"platform":0,"sala":"${roomCode.slice(-4)}"}]`);
            };

            ws.onmessage = (msg) => {
                if (msg.data.startsWith('42[5,')) {
                    try {
                        const data = JSON.parse(msg.data.slice(2));
                        if (data[0] === 5 && Array.isArray(data[5])) {
                            connectedServer = true;
                            displayUsers(data[5], usersGrid);
                            ws.close();
                        }
                    } catch (e) {
                        console.error('JSON parse error:', e);
                    }
                }
            };

            ws.onerror = () => {
                tryNextServer(index + 1);
            };

            ws.onclose = () => {
                if (!connectedServer) {
                    tryNextServer(index + 1);
                }
            };
        }

        tryNextServer(0);
    }

    function displayUsers(users, container) {
        users.forEach(user => {
            const userContainer = document.createElement('div');
            userContainer.style.position = 'relative';
            
            const avatar = document.createElement('img');
            avatar.className = 'user-avatar';
            avatar.src = user.foto || `https://gartic.io/static/images/avatar/svg/${user.avatar}.svg`;
            avatar.setAttribute('data-nick', user.nick);
            avatar.setAttribute('data-points', user.pontos || 0);
            
            avatar.addEventListener('mouseenter', showTooltip);
            avatar.addEventListener('mouseleave', hideTooltip);
            
            userContainer.appendChild(avatar);
            container.appendChild(userContainer);
        });
    }

    function showTooltip(event) {
        const avatar = event.target;
        const nick = avatar.getAttribute('data-nick');
        const points = avatar.getAttribute('data-points');

        const tooltip = document.createElement('div');
        tooltip.className = 'nickname-tooltip';
        tooltip.innerHTML = `
            <div>${nick}</div>
            <div style="font-size: 11px">${points} puan</div>
        `;

        const rect = avatar.getBoundingClientRect();
        tooltip.style.position = 'fixed';
        tooltip.style.left = `${rect.left + rect.width/2}px`;
        tooltip.style.top = `${rect.top - 10}px`;
        tooltip.style.transform = 'translate(-50%, -100%)';
        tooltip.style.opacity = '1';

        document.body.appendChild(tooltip);
        avatar.tooltip = tooltip;
    }

    function hideTooltip(event) {
        const tooltip = event.target.tooltip;
        if (tooltip) {
            tooltip.style.opacity = '0';
            setTimeout(() => tooltip.remove(), 200);
        }
    }

    
    window.updateRooms();
    setInterval(window.updateRooms, 5000);

    
    function handleResize() {
        const container = document.querySelector('.container');
        container.style.height = `${window.innerHeight}px`;
    }

    window.addEventListener('resize', handleResize);
    handleResize();

    
    let updateTimeout;
    window.filterRooms = (query) => {
        clearTimeout(updateTimeout);
        updateTimeout = setTimeout(() => {
            query = query.toLowerCase();
            filteredRooms = roomsData.filter(room => 
                room.code.toLowerCase().includes(query)
            );
            updateRoomsDisplay();
        }, 300);
    };
}