TT Session Stats

FPS, Ping, Time info

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==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);
    });
})();