FPS and Ping Counter (optimized for menu click)

Better FPS unlocker and counter with improved UI

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください。
// ==UserScript==
// @name         FPS and Ping Counter (optimized for menu click)
// @namespace    http://tampermonkey.net/
// @version      4.0
// @description  Better FPS unlocker and counter with improved UI
// @author       kyu
// @match        *://*/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    var bsLink = document.createElement('link');
    bsLink.rel = 'stylesheet';
    bsLink.href = 'https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css';
    document.head.appendChild(bsLink);

    var faLink = document.createElement('link');
    faLink.rel = 'stylesheet';
    faLink.href = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css';
    document.head.appendChild(faLink);

    if (typeof jQuery === 'undefined') {
        var jqScript = document.createElement('script');
        jqScript.src = 'https://code.jquery.com/jquery-3.6.0.min.js';
        jqScript.onload = function() {
            loadjQueryUI();
        };
        document.head.appendChild(jqScript);
    } else {
        loadjQueryUI();
    }

    function loadjQueryUI() {
        if (typeof jQuery.ui === 'undefined') {
            var uiScript = document.createElement('script');
            uiScript.src = 'https://code.jquery.com/ui/1.12.1/jquery-ui.min.js';
            uiScript.onload = startScript;
            document.head.appendChild(uiScript);
        } else {
            startScript();
        }
    }

    function startScript() {
        var style = document.createElement('style');
        style.textContent = `
            .fps-ping-container {
                position: fixed;
                top: 10px;
                right: 10px;
                background: rgba(0, 0, 0, 0.8);
                color: white;
                padding: 5px 10px;
                font-size: 12px;
                border-radius: 5px;
                z-index: 9999;
            }
            .fps-ping-container .fps-ping {
                margin-bottom: 5px;
                padding: 5px;
                border-radius: 5px;
                background-color: rgba(255, 255, 255, 0.2);
            }
            .menu-button {
                position: fixed;
                top: 10px;
                left: 10px;
                background-color: rgba(255, 255, 255, 0.8);
                color: black;
                padding: 5px 10px;
                font-size: 12px;
                border-radius: 5px;
                box-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
                z-index: 9999;
                cursor: pointer;
            }
            .menu {
                position: fixed;
                top: 50px; /* Default position */
                left: 50px; /* Default position */
                width: 300px;
                background-color: rgba(0, 0, 0, 0.8);
                color: white;
                font-size: 16px;
                z-index: 9998;
                display: none;
                overflow: auto;
                padding: 20px;
            }
            .menu label {
                margin-left: 10px;
                font-size: 14px;
                color: white;
                display: block;
                margin-bottom: 10px;
            }
            .menu input[type="checkbox"] {
                margin-right: 5px;
            }
        `;
        document.head.appendChild(style);

        var fpsPingContainer = document.createElement('div');
        fpsPingContainer.className = 'fps-ping-container';

        var fpsIcon = document.createElement('i');
        fpsIcon.className = 'fas fa-clock';
        fpsPingContainer.appendChild(fpsIcon);

        var fpsCounter = document.createElement('span');
        fpsCounter.className = 'fps-ping';
        fpsCounter.textContent = ' FPS: 0';
        fpsPingContainer.appendChild(fpsCounter);

        var pingIcon = document.createElement('i');
        pingIcon.className = 'fas fa-signal';
        fpsPingContainer.appendChild(pingIcon);

        var pingCounter = document.createElement('span');
        pingCounter.className = 'fps-ping';
        pingCounter.textContent = ' Ping: 0ms';
        fpsPingContainer.appendChild(pingCounter);

        document.body.appendChild(fpsPingContainer);

        var menuButton = document.createElement('button');
        menuButton.className = 'menu-button';
        menuButton.textContent = 'Menu';
        document.body.appendChild(menuButton);

        var menu = document.createElement('div');
        menu.className = 'menu';

        var checkbox = document.createElement('input');
        checkbox.type = 'checkbox';
        checkbox.checked = true;

        var label = document.createElement('label');
        label.textContent = 'Enable counters';
        label.appendChild(checkbox);
        menu.appendChild(label);

        var optimizationCheckbox = document.createElement('input');
        optimizationCheckbox.type = 'checkbox';
        optimizationCheckbox.checked = false;

        var optimizationLabel = document.createElement('label');
        optimizationLabel.textContent = 'Optimize';
        optimizationLabel.appendChild(optimizationCheckbox);
        menu.appendChild(optimizationLabel);

        document.body.appendChild(menu);

        menuButton.addEventListener('click', function() {
            if ($(menu).is(':hidden')) {
                $('body').css('overflow', 'hidden');
                $(menu).fadeIn();
            } else {
                $('body').css('overflow', 'auto');
                $(menu).fadeOut();
            }
        });

        checkbox.addEventListener('change', function() {
            fpsPingContainer.style.display = checkbox.checked ? 'block' : 'none';
        });

        optimizationCheckbox.addEventListener('change', function() {
            if (optimizationCheckbox.checked) {
                window.optimizeInterval = setInterval(optimizePage, 1000);
            } else {
                clearInterval(window.optimizeInterval);
                resetPage();
            }
        });

        function optimizePage() {
            var images = document.querySelectorAll('img');
            images.forEach(function(image) {
                image.style.visibility = 'hidden';
            });
            var scripts = document.querySelectorAll('script');
            scripts.forEach(function(script) {
                script.remove();
            });
        }

        function resetPage() {
            var images = document.querySelectorAll('img');
            images.forEach(function(image) {
                image.style.visibility = 'visible';
            });
            var scripts = document.querySelectorAll('script');
            scripts.forEach(function(script) {
                // Reinsert scripts if needed
            });
        }

        var fpsSamples = [];
        var pingSamples = [];
        var lastFrameTime = performance.now();

        function updateFPS() {
            requestAnimationFrame(function() {
                var currentFrameTime = performance.now();
                var elapsed = currentFrameTime - lastFrameTime;
                var fps = Math.round(1000 / elapsed);
                fpsSamples.push(fps);
                if (fpsSamples.length > 60) {
                    fpsSamples.shift();
                }
                var averageFPS = Math.round(fpsSamples.reduce((a, b) => a + b, 0) / fpsSamples.length);
                fpsCounter.textContent = ' FPS: ' + averageFPS;
                lastFrameTime = currentFrameTime;
                updateFPS();
            });
        }

        function updatePing() {
            fetch(location.href, { method: 'HEAD' })
                .then(function(response) {
                    var responseTime = performance.now();
                    var ping = Math.round(responseTime - lastFrameTime);
                    pingSamples.push(ping);
                    if (pingSamples.length > 10) {
                        pingSamples.shift();
                    }
                    var averagePing = Math.round(pingSamples.reduce((a, b) => a + b, 0) / pingSamples.length);
                    pingCounter.textContent = ' Ping: ' + averagePing + 'ms';
                    lastFrameTime = responseTime;
                })
                .catch(function(error) {
                    console.error('Ping measurement failed:', error);
                });
        }

        updateFPS();
        setInterval(updatePing, 1000);
    }
})();