TT Session Stats

FPS, Ping, Time info

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

// ==UserScript==
// @name         TT Session Stats
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  FPS, Ping, Time info
// @author       Aurelion-X9
// @match        https://tanktrouble.com/*
// @match        https://*.tanktrouble.com/*
// @run-at       document-start
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    let pings = [];
    let start = Date.now();
    let lastF = performance.now();
    let fTimes = [];
    let curPing = 0;
    let lastServerId = null;

    const div = document.createElement('div');
    div.id = 'tt-stats';
    div.innerHTML = '<span id="sf">FPS:--</span> <span id="sp">Ping:...</span> <span id="st">Time:0:00:00</span>';
    div.style.cssText = 'position:fixed;bottom:8px;left:8px;z-index:2147483647;background:rgba(0,0,0,0.85);color:#fff;padding:6px 12px;border-radius:6px;font:12px monospace;display:flex;gap:12px;pointer-events:none;';

    function init() {
        if (document.body && !document.getElementById('tt-stats')) {
            document.body.appendChild(div);
        }
    }
    init();
    setTimeout(init, 50);
    setTimeout(init, 200);
    setTimeout(init, 500);
    setTimeout(init, 1000);

    // Get current selected server ID
    function getCurrentServerId() {
        try {
            if (typeof Cookies !== 'undefined') {
                return Cookies.get('multiplayerserverid');
            }
            if (typeof ClientManager !== 'undefined' && ClientManager.getSelectedServer) {
                return ClientManager.getSelectedServer();
            }
        } catch(e) {}
        return null;
    }

    // Use TT's actual server ping measurement
    function measurePing() {
        try {
            if (typeof ClientManager === 'undefined') return;
            
            // Method 1: Get stats for all servers, use current one
            if (ClientManager.getAvailableServerStats) {
                const currentServer = getCurrentServerId();
                
                ClientManager.getAvailableServerStats(function(success, serverId, latency, gameCount, playerCount, message) {
                    if (success && latency > 0) {
                        // If this is our current server, use it
                        if (currentServer && serverId === currentServer) {
                            pings.push(latency);
                            if (pings.length > 10) pings.shift();
                            curPing = median();
                            lastServerId = serverId;
                        } else if (!lastServerId) {
                            // Use first available server's ping if we don't have one
                            pings.push(latency);
                            if (pings.length > 10) pings.shift();
                            curPing = median();
                        }
                    }
                });
            }
            
            // Method 2: Check if ClientManager has direct latency property
            if (ClientManager._latency) {
                pings.push(ClientManager._latency);
                curPing = median();
            }
            if (ClientManager.latency) {
                pings.push(ClientManager.latency);
                curPing = median();
            }
            
        } catch(e) {}
    }

    // Also try to read ping from UI if available
    function getPingFromUI() {
        try {
            // Check settings dropdown for ping text
            const settingsSelect = document.querySelector('#settings select option:not([disabled])');
            if (settingsSelect) {
                const desc = settingsSelect.getAttribute('data-description');
                if (desc) {
                    const match = desc.match(/(\d+)\s*ms/);
                    if (match) return parseInt(match[1]);
                }
            }
        } catch(e) {}
        return 0;
    }

    function median() {
        if (!pings.length) return curPing;
        const s = pings.slice().sort((a,b) => a-b);
        return s[Math.floor(s.length / 2)];
    }

    function fps() {
        const now = performance.now();
        const d = now - lastF;
        lastF = now;
        if (d > 0 && d < 500) {
            fTimes.push(d);
            if (fTimes.length > 30) fTimes.shift();
        }
        requestAnimationFrame(fps);
    }

    function getFPS() {
        try {
            if (typeof GameManager !== 'undefined' && GameManager.getGame) {
                const g = GameManager.getGame();
                if (g && g.time && g.time.fps > 0) return Math.round(g.time.fps);
            }
        } catch(e) {}
        if (!fTimes.length) return 0;
        return Math.round(1000 / (fTimes.reduce((a,b) => a+b, 0) / fTimes.length));
    }

    function fmt(ms) {
        const s = Math.floor(ms/1000);
        return Math.floor(s/3600) + ':' + String(Math.floor((s%3600)/60)).padStart(2,'0') + ':' + String(s%60).padStart(2,'0');
    }

    // Wait for ClientManager to be ready
    function waitForClientManager(callback) {
        let attempts = 0;
        const check = setInterval(function() {
            attempts++;
            if (typeof ClientManager !== 'undefined') {
                clearInterval(check);
                callback();
            } else if (attempts > 50) {
                clearInterval(check);
            }
        }, 200);
    }

    waitForClientManager(function() {
        // Start tracking
        fps();
        
        // Measure ping
        measurePing();
        setInterval(measurePing, 2000);
        
        // Also check UI periodically
        setInterval(function() {
            if (curPing === 0) {
                const uiPing = getPingFromUI();
                if (uiPing > 0) {
                    curPing = uiPing;
                }
            }
        }, 1000);
        
        // Update display
        setInterval(function() {
            const f = document.getElementById('sf');
            const p = document.getElementById('sp');
            const t = document.getElementById('st');
            
            if (f) {
                const v = getFPS();
                f.textContent = 'FPS:' + (v || '--');
                f.style.color = v > 100 ? '#4CAF50' : v > 60 ? '#FFC107' : '#f44336';
            }
            if (p) {
                p.textContent = 'Ping:' + (curPing > 0 ? curPing + 'ms' : '...');
                p.style.color = curPing > 0 && curPing < 80 ? '#4CAF50' : curPing > 0 && curPing < 150 ? '#FFC107' : '#f44336';
            }
            if (t) t.textContent = 'Time:' + fmt(Date.now() - start);
        }, 100);
    });
})();