Minefun FPS & CPS Counter, Key Display,CPS Graph,Reload & FPS Alert & Crosshair

minefun.ioでFPSとCPS、過去5秒のCPS線グラフ、押されているキー表示、リロード、FPS低下アラート、照準を追加

目前为 2025-04-13 提交的版本。查看 最新版本

// ==UserScript==
// @name         Minefun FPS & CPS Counter, Key Display,CPS Graph,Reload & FPS Alert & Crosshair
// @namespace    https://minefun.io/
// @license MIT
// @icon         data:image/webp;base64,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
// @version      1.9.9
// @description  minefun.ioでFPSとCPS、過去5秒のCPS線グラフ、押されているキー表示、リロード、FPS低下アラート、照準を追加
// @match        *://minefun.io/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // スタイル定義
    const styles = `
        #mfCounterContainer {
            position: fixed;
            top: 10px;
            left: 10px;
            background-color: rgba(30, 30, 30, 0.8);
            color: #eee;
            padding: 10px;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            font-size: 14px;
            z-index: 1000;
            cursor: grab;
            border-radius: 5px;
            box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3);
            display: flex;
            flex-direction: column;
            align-items: flex-start;
            gap: 8px;
            display: none; /* 初期状態は非表示 */
        }
        #mfCounterText {
            white-space: pre-line;
        }
        #mfKeyDisplay {
            display: flex;
            gap: 5px;
            margin-top: 5px;
        }
        .key-icon {
            background-color: #444;
            color: #eee;
            padding: 5px;
            border-radius: 3px;
            font-size: 12px;
            min-width: 20px;
            text-align: center;
        }
        #mfImageContainer {
            position: relative;
            width: 40px;
            height: 40px;
            border-radius: 50%;
            overflow: hidden;
            border: 1px solid #555;
            display: flex;
            justify-content: center;
            align-items: center;
        }
        #mfImage {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }
        #mfReloadButton {
            background-color: #555;
            color: #eee;
            border: none;
            padding: 6px 10px;
            border-radius: 5px;
            font-size: 12px;
            cursor: pointer;
            transition: background-color 0.3s ease;
            margin-top: 5px;
        }
        #mfReloadButton:hover {
            background-color: #777;
        }
        #mfFpsAlert {
            background-color: rgba(255, 0, 0, 0.7);
            color: white;
            padding: 5px;
            border-radius: 5px;
            font-size: 12px;
            margin-top: 5px;
            display: none;
        }
        .switch-container {
            display: flex;
            align-items: center;
            gap: 8px;
            margin-top: 5px;
        }
        .switch {
            position: relative;
            display: inline-block;
            width: 40px;
            height: 20px;
        }
        .switch input {
            opacity: 0;
            width: 0;
            height: 0;
        }
        .slider {
            position: absolute;
            cursor: pointer;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background-color: #ccc;
            transition: .4s;
            border-radius: 20px;
        }
        .slider:before {
            position: absolute;
            content: "";
            height: 16px;
            width: 16px;
            left: 2px;
            bottom: 2px;
            background-color: white;
            transition: .4s;
            border-radius: 50%;
        }
        input:checked + .slider {
            background-color: #2196F3;
        }
        input:focus + .slider {
            box-shadow: 0 0 1px #2196F3;
        }
        input:checked + .slider:before {
            transform: translateX(20px);
        }
        .switch-label {
            font-size: 12px;
            color: #ccc;
        }
        #mfCrosshair {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            width: 20px;
            height: 20px;
            border: 1px solid rgba(255, 255, 255, 0.5);
            border-radius: 50%;
            z-index: 9999;
            display: none; /* 初期状態は非表示 */
            pointer-events: none; /* クリックを透過 */
        }
        #mfCrosshair:before, #mfCrosshair:after {
            content: '';
            position: absolute;
            background-color: rgba(255, 255, 255, 0.5);
        }
        #mfCrosshair:before {
            left: 50%;
            top: 2px;
            bottom: 2px;
            width: 1px;
            transform: translateX(-50%);
        }
        #mfCrosshair:after {
            top: 50%;
            left: 2px;
            right: 2px;
            height: 1px;
            transform: translateY(-50%);
        }
        #mfCpsGraph {
            width: 100px;
            height: 30px;
            margin-top: 5px;
            border: 1px solid #555;
            border-radius: 3px;
            background-color: #333;
        }
    `;

    const styleSheet = document.createElement("style");
    styleSheet.type = "text/css";
    styleSheet.innerText = styles;
    document.head.appendChild(styleSheet);

    // コンテナ要素の作成
    const counterContainer = document.createElement('div');
    counterContainer.id = 'mfCounterContainer';
    document.body.appendChild(counterContainer);

    // テキスト要素の作成
    const textElement = document.createElement('span');
    textElement.id = 'mfCounterText';
    counterContainer.appendChild(textElement);

    // キー表示コンテナの作成
    const keyDisplayContainer = document.createElement('div');
    keyDisplayContainer.id = 'mfKeyDisplay';
    counterContainer.appendChild(keyDisplayContainer);

    // CPSグラフ表示用のキャンバス要素を作成
    const cpsGraphCanvas = document.createElement('canvas');
    cpsGraphCanvas.id = 'mfCpsGraph';
    counterContainer.appendChild(cpsGraphCanvas);
    const cpsGraphCtx = cpsGraphCanvas.getContext('2d');
    const cpsHistory = [];
    const maxCpsHistoryLength = 5; // 過去5秒

    // 画像要素の作成
    const imageContainer = document.createElement('div');
    imageContainer.id = 'mfImageContainer';
    counterContainer.appendChild(imageContainer);

    const imageElement = document.createElement('img');
    imageElement.id = 'mfImage';
    imageElement.src = 'https://cdn.minefun.io/users/67629a12aa9a815752742647/27EY08XPCCCXH.webp';
    imageContainer.appendChild(imageElement);

    // スーパーリロードボタンの作成
    const reloadButton = document.createElement('button');
    reloadButton.id = 'mfReloadButton';
    reloadButton.textContent = 'Reload';
    reloadButton.addEventListener('click', () => {
        window.location.reload(true); // 強制リロード
    });
    counterContainer.appendChild(reloadButton);

    // FPS低下アラート表示要素
    const fpsAlertElement = document.createElement('div');
    fpsAlertElement.id = 'mfFpsAlert';
    fpsAlertElement.style.display = 'none'; // 初期状態は非表示
    counterContainer.appendChild(fpsAlertElement);

    // 照準表示のコンテナ
    const crosshairSwitchContainer = document.createElement('div');
    crosshairSwitchContainer.classList.add('switch-container');
    counterContainer.appendChild(crosshairSwitchContainer);

    // 照準表示のトグルスイッチ
    const crosshairLabel = document.createElement('label');
    crosshairLabel.classList.add('switch');
    crosshairSwitchContainer.appendChild(crosshairLabel);

    const crosshairToggle = document.createElement('input');
    crosshairToggle.type = 'checkbox';
    crosshairLabel.appendChild(crosshairToggle);

    const crosshairSlider = document.createElement('span');
    crosshairSlider.classList.add('slider');
    crosshairLabel.appendChild(crosshairSlider);

    const crosshairSwitchLabel = document.createElement('span');
    crosshairSwitchLabel.classList.add('switch-label');
    crosshairSwitchLabel.textContent = 'Crosshair';
    crosshairSwitchContainer.appendChild(crosshairSwitchLabel);

    // 照準要素の作成
    const crosshairElement = document.createElement('div');
    crosshairElement.id = 'mfCrosshair';
    document.body.appendChild(crosshairElement);

    // 表示/非表示切り替えフラグ
    let isCounterVisible = false;

    // FPS計測
    let fps = 0;
    let lastFPSTime = performance.now();
    let frameCount = 0;

    function updateFPS(currentTime) {
        frameCount++;
        const deltaTime = currentTime - lastFPSTime;

        if (deltaTime >= 100) {
            fps = Math.round((frameCount * 1000) / deltaTime * 10) / 10;
            frameCount = 0;
            lastFPSTime = currentTime;

            // FPS低下アラートの表示/非表示
            if (fps < 30) {
                fpsAlertElement.textContent = `FPSが${fps}です`;
                fpsAlertElement.style.display = 'block';
            } else {
                fpsAlertElement.style.display = 'none';
            }
        }

        requestAnimationFrame(updateFPS);
    }

    requestAnimationFrame(updateFPS);

    // CPS計測と履歴の更新
    let cps = 0;
    let clickCount = 0;
    let lastCPSTime = performance.now();

    document.addEventListener('mousedown', () => {
        clickCount++;
    });

    function updateCPS() {
        const currentTime = performance.now();
        const deltaTime = currentTime - lastCPSTime;

        if (deltaTime >= 1000) {
            cps = clickCount;
            clickCount = 0;
            lastCPSTime = currentTime;

            cpsHistory.push(cps);
            if (cpsHistory.length > maxCpsHistoryLength) {
                cpsHistory.shift(); // 古いデータを削除
            }
        }
        requestAnimationFrame(updateCPS);
    }

    requestAnimationFrame(updateCPS);

    // CPSグラフの描画 (線グラフ)
    function drawCpsGraph() {
        cpsGraphCtx.clearRect(0, 0, cpsGraphCanvas.width, cpsGraphCanvas.height);
        if (cpsHistory.length > 1) {
            cpsGraphCtx.strokeStyle = '#00ff00'; // 線の色
            cpsGraphCtx.lineWidth = 2;
            cpsGraphCtx.beginPath();

            const maxCps = Math.max(...cpsHistory, 1); // 最小値を1として0除算を防ぐ
            const xIncrement = cpsGraphCanvas.width / (cpsHistory.length - 1);

            cpsHistory.forEach((cpsValue, index) => {
                const x = index * xIncrement;
                const y = cpsGraphCanvas.height - (cpsValue / maxCps) * cpsGraphCanvas.height;

                if (index === 0) {
                    cpsGraphCtx.moveTo(x, y);
                } else {
                    cpsGraphCtx.lineTo(x, y);
                }
            });

            cpsGraphCtx.stroke();
        }
        requestAnimationFrame(drawCpsGraph);
    }

    requestAnimationFrame(drawCpsGraph);

    // 押されているキーの表示 (アイコン)
    const pressedKeys = new Set();
    const keyIconMap = {
        'w': 'W', 'a': 'A', 's': 'S', 'd': 'D',
        ' ': 'Space', 'shift': 'Shift', 'ctrl': 'Ctrl', 'alt': 'Alt',
        'tab': 'Tab', 'capslock': 'Caps', 'enter': 'Enter',
        'arrowup': '↑', 'arrowdown': '↓', 'arrowleft': '←', 'arrowright': '→',
        'escape': 'Esc',
        '1': '1', '2': '2', '3': '3', '4': '4', '5': '5', '6': '6', '7': '7', '8': '8', '9': '9', '0': '0',
        '`': '`', '-': '-', '=': '=', '[': '[', ']': ']', '\\': '\\',
        ';': ';', '\'': '\'', ',': ',', '.': '.', '/': '/',
        'f1': 'F1', 'f2': 'F2', 'f3': 'F3', 'f4': 'F4', 'f5': 'F5', 'f6': 'F6',
        'f7': 'F7', 'f8': 'F8', 'f9': 'F9', 'f10': 'F10', 'f11': 'F11', 'f12': 'F12'
        // 必要に応じて他のキーも追加
    };

    document.addEventListener('keydown', (event) => {
        pressedKeys.add(event.key.toLowerCase());
        updateKeyDisplay();
        // '/'キーが押されたら表示/非表示を切り替える
        if (event.key === '/') {
            isCounterVisible = !isCounterVisible;
            counterContainer.style.display = isCounterVisible ? 'block' : 'none';
        }
    });

    document.addEventListener('keyup', (event) => {
        pressedKeys.delete(event.key.toLowerCase());
        updateKeyDisplay();
    });

    function updateKeyDisplay() {
        keyDisplayContainer.innerHTML = ''; // Clear previous icons
        pressedKeys.forEach(key => {
            const iconText = keyIconMap[key] || key.toUpperCase(); // マップにない場合は大文字で表示
            const keyIcon = document.createElement('div');
            keyIcon.classList.add('key-icon');
            keyIcon.textContent = iconText;
            keyDisplayContainer.appendChild(keyIcon);
        });
    }

    // 表示の更新
    function updateDisplay() {
        textElement.textContent = `FPS: ${fps}\nCPS: ${cps}\nBy kutu524_`;
        requestAnimationFrame(updateDisplay);
    }

    requestAnimationFrame(updateDisplay);

    // ドラッグ機能
    let isDragging = false;
    let offsetX, offsetY;

    counterContainer.addEventListener('mousedown', (e) => {
        isDragging = true;
        counterContainer.style.cursor = 'grabbing';
        offsetX = e.clientX - counterContainer.getBoundingClientRect().left;
        offsetY = e.clientY - counterContainer.getBoundingClientRect().top;
    });

    document.addEventListener('mouseup', () => {
        isDragging = false;
        counterContainer.style.cursor = 'grab';
    });

    document.addEventListener('mousemove', (e) => {
        if (!isDragging) return;

        counterContainer.style.left = e.clientX - offsetX + 'px';
        counterContainer.style.top = e.clientY - offsetY + 'px';
    });

    // 照準の表示/非表示を切り替え
    crosshairToggle.addEventListener('change', function() {
        crosshairElement.style.display = this.checked ? 'block' : 'none';
    });

    // '/'キーでの表示/非表示切り替え
    document.addEventListener('keydown', (event) => {
        if (event.key === '/') {
            isCounterVisible = !isCounterVisible;
            counterContainer.style.display = isCounterVisible ? 'block' : 'none';
        }
    });

})();