Minefun Simple Virtual Keyboard

Hiển thị duy nhất cụm phím ảo điều khiển di chuyển (WASD + Space) trên màn hình minefun.io. Ấn phím [ . ] để mở menu cài đặt màu sắc và vị trí.

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램을 설치해야 합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==UserScript==
// @name         Minefun Simple Virtual Keyboard
// @namespace    http://tampermonkey.net
// @version      1.1
// @description  Hiển thị duy nhất cụm phím ảo điều khiển di chuyển (WASD + Space) trên màn hình minefun.io. Ấn phím [ . ] để mở menu cài đặt màu sắc và vị trí.
// @author       AI Assistant
// @match        https://minefun.io*
// @license      MIT
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // --- 1. TẠO GIAO DIỆN BÀN PHÍM ẢO DI CHUYỂN ---
    const kbContainer = document.createElement('div');
    kbContainer.id = 'virtual-keyboard';
    kbContainer.style.cssText = `
        position: fixed;
        bottom: 30px;
        left: 50%;
        transform: translateX(-50%);
        background: rgba(0, 0, 0, 0.7);
        padding: 12px;
        border-radius: 10px;
        z-index: 99999;
        display: flex;
        flex-direction: column;
        gap: 6px;
        user-select: none;
        box-shadow: 0 4px 15px rgba(0,0,0,0.5);
    `;

    // Cấu trúc chỉ gồm cụm phím di chuyển cơ bản
    const rows = [
        ['W'],
        ['A', 'S', 'D'],
        ['Space']
    ];

    rows.forEach(rowKeys => {
        const rowDiv = document.createElement('div');
        rowDiv.style.cssText = 'display: flex; justify-content: center; gap: 6px;';
        
        rowKeys.forEach(key => {
            const keyBtn = document.createElement('div');
            keyBtn.innerText = key === 'Space' ? 'SPACE' : key;
            keyBtn.className = 'kb-key';
            keyBtn.dataset.key = key.toLowerCase();
            
            // Kiểu dáng tối giản cho phím ảo
            keyBtn.style.cssText = `
                width: ${key === 'Space' ? '150px' : '45px'};
                height: 45px;
                background: #2a2a2a;
                color: #ffffff;
                display: flex;
                align-items: center;
                justify-content: center;
                font-weight: bold;
                font-size: 14px;
                border-radius: 6px;
                border: 1px solid #444;
                font-family: 'Segoe UI', Arial, sans-serif;
                transition: background 0.1s, transform 0.1s, opacity 0.1s;
            `;
            rowDiv.appendChild(keyBtn);
        });
        kbContainer.appendChild(rowDiv);
    });
    document.body.appendChild(kbContainer);


    // --- 2. MENU ĐIỀU CHỈNH (ẨN/HIỆN BẰNG PHÍM DẤU CHẤM) ---
    const menu = document.createElement('div');
    menu.style.cssText = `
        position: fixed;
        top: 25%;
        left: 50%;
        transform: translate(-50%, -25%);
        background: #1e1e1e;
        color: #fff;
        padding: 20px;
        border-radius: 12px;
        border: 1px solid #444;
        z-index: 100000;
        display: none;
        flex-direction: column;
        gap: 15px;
        font-family: 'Segoe UI', Arial, sans-serif;
        box-shadow: 0 10px 25px rgba(0,0,0,0.7);
        width: 240px;
    `;
    menu.innerHTML = `
        <h4 style="margin: 0 0 5px 0; text-align: center; font-size: 16px; color: #4caf50;">Cài Đặt Bàn Phím Vỏ</h4>
        
        <label style="display: flex; justify-content: space-between; align-items: center; font-size: 14px;">
            Màu nút:
            <input type="color" id="key-color-picker" value="#2a2a2a" style="border:none; background:none; cursor:pointer;">
        </label>
        
        <label style="display: flex; justify-content: space-between; align-items: center; font-size: 14px;">
            Màu chữ:
            <input type="color" id="text-color-picker" value="#ffffff" style="border:none; background:none; cursor:pointer;">
        </label>

        <div style="border-top: 1px solid #333; padding-top: 10px;">
            <p style="margin: 0 0 8px 0; font-size: 13px; color: #aaa;">Di chuyển vị trí:</p>
            <div style="display: flex; gap: 4px; justify-content: space-between;">
                <button id="move-left" style="flex:1; padding: 6px; background:#333; color:#fff; border:1px solid #555; border-radius:4px; cursor:pointer;">Trái</button>
                <button id="move-right" style="flex:1; padding: 6px; background:#333; color:#fff; border:1px solid #555; border-radius:4px; cursor:pointer;">Phải</button>
                <button id="move-up" style="flex:1; padding: 6px; background:#333; color:#fff; border:1px solid #555; border-radius:4px; cursor:pointer;">Lên</button>
                <button id="move-down" style="flex:1; padding: 6px; background:#333; color:#fff; border:1px solid #555; border-radius:4px; cursor:pointer;">Xuống</button>
            </div>
        </div>
        <p style="margin: 5px 0 0 0; font-size: 11px; color: #777; text-align: center;">Ấn phím [ . ] để đóng menu này</p>
    `;
    document.body.appendChild(menu);


    // --- 3. LOGIC HOẠT ĐỘNG ---

    // Nhấn phím "." để mở menu
    window.addEventListener('keydown', (e) => {
        if (e.key === '.') {
            if (document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA') return;
            e.preventDefault();
            menu.style.display = menu.style.display === 'none' ? 'flex' : 'none';
        }
    });

    // Đồng bộ sáng/tối khi bạn bấm phím thật
    const toggleHighlight = (keyStr, isPressed) => {
        let targetKey = keyStr.toLowerCase();
        if (targetKey === ' ') targetKey = 'space';
        
        const keyVisual = kbContainer.querySelector(`.kb-key[data-key="${targetKey}"]`);
        if (keyVisual) {
            keyVisual.style.opacity = isPressed ? '0.5' : '1';
            keyVisual.style.transform = isPressed ? 'scale(0.92)' : 'scale(1)';
        }
    };
    window.addEventListener('keydown', (e) => toggleHighlight(e.key, true));
    window.addEventListener('keyup', (e) => toggleHighlight(e.key, false));

    // Đổi màu sắc từ Menu
    menu.querySelector('#key-color-picker').addEventListener('input', (e) => {
        kbContainer.querySelectorAll('.kb-key').forEach(k => k.style.background = e.target.value);
    });
    menu.querySelector('#text-color-picker').addEventListener('input', (e) => {
        kbContainer.querySelectorAll('.kb-key').forEach(k => k.style.color = e.target.value);
    });

    // Di chuyển cụm phím ảo độc lập bằng nút trong menu
    let currentLeft = window.innerWidth / 2;
    let currentBottom = 30;
    kbContainer.style.transform = 'none';
    kbContainer.style.left = `${currentLeft - 85}px`;

    const moveStep = 25; 
    menu.querySelector('#move-left').addEventListener('click', () => { currentLeft -= moveStep; kbContainer.style.left = `${currentLeft}px`; });
    menu.querySelector('#move-right').addEventListener('click', () => { currentLeft += moveStep; kbContainer.style.left = `${currentLeft}px`; });
    menu.querySelector('#move-up').addEventListener('click', () => { currentBottom += moveStep; kbContainer.style.bottom = `${currentBottom}px`; });
    menu.querySelector('#move-down').addEventListener('click', () => { currentBottom -= moveStep; kbContainer.style.bottom = `${currentBottom}px`; });

})();