Sleazy Fork is available in English.

Minefun Ultimate Hub V2

Bàn phím ảo + Cài đặt liền khối, đa ngôn ngữ, tự động nhặt đồ, lưu mọi thiết lập.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Minefun Ultimate Hub V2
// @namespace    http://tampermonkey.net/
// @version      2.0
// @description  Bàn phím ảo + Cài đặt liền khối, đa ngôn ngữ, tự động nhặt đồ, lưu mọi thiết lập.
// @author       Bạn
// @match        *://*.minefun.io/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // ==========================================
    // 1. DỮ LIỆU TỪ ĐIỂN & LƯU TRỮ (LOCALSTORAGE)
    // ==========================================
    const langDict = {
        VN: {
            title: "🎮 BÀN PHÍM MINEFUN",
            btnLang: "VN ⇆ EN",
            btnSet: "⚙️ CÀI ĐẶT",
            xhTitle: "🎯 Tâm Nhắm",
            colorTitle: "🎨 Màu Sắc",
            xhEffTitle: "✨ Hiệu Ứng Tâm",
            kbEffTitle: "⌨️ Hiệu Ứng Phím",
            eff1: "Tĩnh ⏹️", eff2: "Xoay 🔄", eff3: "Nhịp tim 💓", eff4: "Cầu vồng 🌈", 
            eff5: "Lắc 📳", eff6: "Sáng 🌟", eff7: "Nháy ⚡", eff8: "Lật 🔂",
            kb1: "Sáng Viền 🔲", kb2: "Thở 💨", kb3: "Viền Hồng 🌸", 
            kb4: "Nổi Lên 👆", kb5: "V. Cầu vồng 🌈", kb6: "T. Phản 🌗"
        },
        EN: {
            title: "🎮 MINEFUN KEYBOARD",
            btnLang: "EN ⇆ VN",
            btnSet: "⚙️ SETTINGS",
            xhTitle: "🎯 Crosshairs",
            colorTitle: "🎨 Colors",
            xhEffTitle: "✨ XH Effect",
            kbEffTitle: "⌨️ KB Effect",
            eff1: "Static ⏹️", eff2: "Spin 🔄", eff3: "Pulse 💓", eff4: "Rainbow 🌈", 
            eff5: "Shake 📳", eff6: "Glow 🌟", eff7: "Blink ⚡", eff8: "Flip 🔂",
            kb1: "Glow Box 🔲", kb2: "Breathe 💨", kb3: "Pink Box 🌸", 
            kb4: "Pop-up 👆", kb5: "RGB Box 🌈", kb6: "Contrast 🌗"
        }
    };

    // Tải cấu hình đã lưu hoặc dùng mặc định
    let cfg = JSON.parse(localStorage.getItem('minefun_hub_cfg')) || {
        lang: 'VN', x: 20, y: 20, xh: '+', xhColor: '#00FFFF', xhEff: 1, kbEff: 1, setOpen: false
    };

    const saveCfg = () => { localStorage.setItem('minefun_hub_cfg', JSON.stringify(cfg)); };

    // ==========================================
    // 2. CSS TỐI ƯU NHỎ GỌN & BẮT MẮT
    // ==========================================
    const style = document.createElement('style');
    style.innerHTML = `
        @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@500;700&display=swap');
        
        .no-block-game { pointer-events: none; }
        .allow-click { pointer-events: auto; }

        /* Container Chính - Ghép cả bàn phím & cài đặt */
        #hub-container {
            position: fixed; background: rgba(15, 15, 25, 0.9);
            border: 1px solid #444; border-radius: 8px;
            padding: 8px; width: 300px; z-index: 10000;
            user-select: none; font-family: 'Roboto', sans-serif;
            box-shadow: 0 4px 15px rgba(0,0,0,0.8);
            cursor: grab; /* Kéo được ở mọi nơi */
        }
        #hub-container:active { cursor: grabbing; }

        /* Header & Nút Bấm */
        #hub-header {
            display: flex; justify-content: space-between; align-items: center;
            border-bottom: 1px solid #333; padding-bottom: 5px; margin-bottom: 8px;
        }
        .hub-title { color: #fff; font-size: 10px; font-weight: bold; pointer-events: none; }
        .head-btn {
            background: #222; border: 1px solid #555; color: #fff;
            font-size: 9px; padding: 3px 6px; border-radius: 3px; cursor: pointer;
        }
        .head-btn:hover { background: #444; }

        /* Bàn Phím */
        .vk-row { display: flex; justify-content: center; gap: 3px; margin-bottom: 3px; }
        .vk-key {
            background: linear-gradient(135deg, #1e1e2f, #3a3a5c);
            color: #fff; font-size: 9px; font-weight: bold;
            width: 22px; height: 22px;
            display: flex; justify-content: center; align-items: center;
            border-radius: 4px; border: 1px solid #111; cursor: default;
            transition: transform 0.05s, background 0.1s;
        }
        .vk-key.wide { width: 42px; }
        .vk-key.active { background: #fff !important; color: #000 !important; transform: scale(0.9); box-shadow: 0 0 8px #fff; }

        /* Cài đặt (Ẩn/Hiện mượt mà) */
        #settings-area {
            display: ${cfg.setOpen ? 'block' : 'none'};
            margin-top: 10px; border-top: 1px dashed #555; padding-top: 5px;
            max-height: 250px; overflow-y: auto; cursor: default;
        }
        /* Tùy chỉnh thanh cuộn cho gọn */
        #settings-area::-webkit-scrollbar { width: 4px; }
        #settings-area::-webkit-scrollbar-thumb { background: #666; border-radius: 2px; }

        .set-group { margin-bottom: 8px; }
        .set-title { font-size: 9px; color: #0ff; margin-bottom: 4px; font-weight: bold; }
        .grid-xh { display: grid; grid-template-columns: repeat(10, 1fr); gap: 2px; }
        .grid-color { display: grid; grid-template-columns: repeat(10, 1fr); gap: 2px; }
        .grid-eff { display: grid; grid-template-columns: repeat(3, 1fr); gap: 3px; }
        
        .grid-btn {
            background: #2a2a35; border: 1px solid #444; color: #ccc;
            font-size: 9px; padding: 4px 0; border-radius: 3px; cursor: pointer; text-align: center;
        }
        .grid-btn:hover { background: #555; color: #fff; }
        .grid-btn.active-btn { background: #0ff; color: #000; border-color: #fff; font-weight: bold; }
        
        /* Tâm Nhắm Game */
        #custom-crosshair {
            position: fixed; top: 50%; left: 50%;
            transform: translate(-50%, -50%);
            font-size: 24px; pointer-events: none; z-index: 9999;
            text-shadow: 0 0 2px #000;
        }

        /* Hiệu ứng Tâm Nhắm & Bàn Phím (Giữ nguyên logic cũ) */
        .xh-eff-1 { } 
        .xh-eff-2 { animation: xhSpin 2s linear infinite; }
        .xh-eff-3 { animation: xhPulse 1s infinite; }
        .xh-eff-4 { animation: xhRainbow 3s linear infinite; }
        .xh-eff-5 { animation: xhShake 0.3s infinite; }
        .xh-eff-6 { text-shadow: 0 0 10px currentColor; }
        .xh-eff-7 { animation: xhBlink 0.5s step-end infinite; }
        .xh-eff-8 { animation: xhFlip 2s infinite; }

        .kb-eff-1 { box-shadow: 0 0 8px #0ff; }
        .kb-eff-2 { animation: kbBreathe 2s infinite; }
        .kb-eff-3 { border-color: #ff69b4; box-shadow: 0 0 5px #ff69b4; }
        .kb-eff-4 .vk-key { box-shadow: 0 2px 0 #0ff; }
        .kb-eff-4 .vk-key:active, .kb-eff-4 .vk-key.active { transform: translateY(2px); box-shadow: none; }
        .kb-eff-5 { animation: kbRainbowBorder 3s linear infinite; }
        .kb-eff-6 { filter: contrast(1.3); }

        @keyframes xhSpin { 100% { transform: translate(-50%, -50%) rotate(360deg); } }
        @keyframes xhPulse { 0%, 100% { transform: translate(-50%, -50%) scale(1); } 50% { transform: translate(-50%, -50%) scale(1.5); } }
        @keyframes xhRainbow { 100% { filter: hue-rotate(360deg); } }
        @keyframes xhShake { 0%, 100% { margin-left: 0; } 25% { margin-left: -2px; } 75% { margin-left: 2px; } }
        @keyframes xhBlink { 50% { opacity: 0; } }
        @keyframes xhFlip { 50% { transform: translate(-50%, -50%) rotateY(180deg); } }
        @keyframes kbBreathe { 0%, 100% { box-shadow: 0 0 2px #fff; } 50% { box-shadow: 0 0 15px #0ff; } }
        @keyframes kbRainbowBorder { 100% { filter: hue-rotate(360deg); } }
    `;
    document.head.appendChild(style);

    // ==========================================
    // 3. TẠO HTML GIAO DIỆN CHÍNH
    // ==========================================
    const keysRow1 = ['1','2','3','4','5','6','7','8','9'];
    const keysRow2 = ['W','Q','R','T','P','A','S','D','X','C','M','Shift'];
    const keysRow3 = ['Enter','Bksp','!','@','#','$','%','^','&','*','(',')','_','+','{','}','|',':','"','<','>','?'];
    
    const crosshairs = ['+','x','o','O','•','✛','✜','✚','✙','⌖','⯐','⯏','⯎','⯌','⯍','⯨','⯩','⯪','⯫','⭖','⭗','⭘','⭙','⭚','⭛','⭜','⭝','❖','⊕','🖕'];
    const colors = ['#FF0000','#00FF00','#0000FF','#FFFF00','#00FFFF','#FF00FF','#FFFFFF','#000000','#FF8C00','#8A2BE2','#00FF7F','#FF1493','#1E90FF','#FFD700','#32CD32','#8B008B','#FF4500','#00CED1','#9400D3','#ADFF2F'];

    const renderRow = (arr) => `<div class="vk-row">` + arr.map(k => `<div class="vk-key allow-click ${(k.length>1)?'wide':''}" data-key="${(k==='Bksp'?'BACKSPACE':k).toUpperCase()}">${k}</div>`).join('') + `</div>`;

    document.body.insertAdjacentHTML('beforeend', `
        <div id="hub-container" class="allow-click" style="left:${cfg.x}px; top:${cfg.y}px;">
            <div id="hub-header">
                <div class="hub-title" id="t-title">🎮 BÀN PHÍM MINEFUN</div>
                <div>
                    <button class="head-btn" id="btn-lang">VN ⇆ EN</button>
                    <button class="head-btn" id="btn-toggle-set">⚙️ CÀI ĐẶT</button>
                </div>
            </div>
            
            <div id="keyboard-area">
                ${renderRow(keysRow1)}
                ${renderRow(keysRow2)}
                ${renderRow(keysRow3)}
            </div>

            <div id="settings-area">
                <div class="set-group">
                    <div class="set-title" id="t-xh">🎯 Tâm Nhắm</div>
                    <div class="grid-xh">
                        ${crosshairs.map(c => `<div class="grid-btn allow-click xh-btn" data-val="${c}">${c}</div>`).join('')}
                    </div>
                </div>
                <div class="set-group">
                    <div class="set-title" id="t-color">🎨 Màu Sắc</div>
                    <div class="grid-color">
                        ${colors.map(c => `<div class="grid-btn allow-click color-btn" style="background:${c}; height:12px;" data-val="${c}"></div>`).join('')}
                    </div>
                </div>
                <div class="set-group">
                    <div class="set-title" id="t-xh-eff">✨ Hiệu Ứng Tâm</div>
                    <div class="grid-eff" id="xh-eff-list"></div>
                </div>
                <div class="set-group">
                    <div class="set-title" id="t-kb-eff">⌨️ Hiệu Ứng Phím</div>
                    <div class="grid-eff" id="kb-eff-list"></div>
                </div>
            </div>
        </div>
        <div id="custom-crosshair">${cfg.xh}</div>
    `);

    const hub = document.getElementById('hub-container');
    const xhEl = document.getElementById('custom-crosshair');
    const setArea = document.getElementById('settings-area');

    // ==========================================
    // 4. KÉO THẢ TỰ DO (Kéo ở mọi nơi trên bảng)
    // ==========================================
    let isDragging = false, offX, offY;
    hub.addEventListener('mousedown', (e) => {
        // Không kéo khi ấn vào các nút/chữ có tính tương tác
        if (e.target.closest('.vk-key') || e.target.closest('.head-btn') || e.target.closest('.grid-btn') || e.target.closest('#settings-area')) return;
        isDragging = true;
        offX = e.clientX - hub.offsetLeft;
        offY = e.clientY - hub.offsetTop;
    });
    document.addEventListener('mousemove', (e) => {
        if (!isDragging) return;
        hub.style.left = (e.clientX - offX) + 'px';
        hub.style.top = (e.clientY - offY) + 'px';
    });
    document.addEventListener('mouseup', () => {
        if (isDragging) {
            isDragging = false;
            cfg.x = parseInt(hub.style.left); cfg.y = parseInt(hub.style.top);
            saveCfg();
        }
    });

    // ==========================================
    // 5. NGÔN NGỮ & RENDER NÚT HIỆU ỨNG (CÓ EMOJI)
    // ==========================================
    const renderLang = () => {
        const t = langDict[cfg.lang];
        document.getElementById('t-title').innerText = t.title;
        document.getElementById('btn-lang').innerText = t.btnLang;
        document.getElementById('btn-toggle-set').innerText = t.btnSet;
        document.getElementById('t-xh').innerText = t.xhTitle;
        document.getElementById('t-color').innerText = t.colorTitle;
        document.getElementById('t-xh-eff').innerText = t.xhEffTitle;
        document.getElementById('t-kb-eff').innerText = t.kbEffTitle;

        document.getElementById('xh-eff-list').innerHTML = [1,2,3,4,5,6,7,8].map(i => 
            `<div class="grid-btn allow-click xhe-btn ${cfg.xhEff===i?'active-btn':''}" data-val="${i}">${t['eff'+i]}</div>`
        ).join('');

        document.getElementById('kb-eff-list').innerHTML = [1,2,3,4,5,6].map(i => 
            `<div class="grid-btn allow-click kbe-btn ${cfg.kbEff===i?'active-btn':''}" data-val="${i}">${t['kb'+i]}</div>`
        ).join('');
        
        bindEffectEvents(); // Gắn lại sự kiện click cho các nút vừa tạo
    };

    document.getElementById('btn-lang').addEventListener('click', () => {
        cfg.lang = cfg.lang === 'VN' ? 'EN' : 'VN';
        saveCfg(); renderLang();
    });

    document.getElementById('btn-toggle-set').addEventListener('click', () => {
        cfg.setOpen = !cfg.setOpen;
        setArea.style.display = cfg.setOpen ? 'block' : 'none';
        saveCfg();
    });

    // ==========================================
    // 6. ÁP DỤNG CÀI ĐẶT & SỰ KIỆN CLICK SETTINGS
    // ==========================================
    const applyAllCfg = () => {
        xhEl.innerText = cfg.xh;
        xhEl.style.color = cfg.xhColor;
        xhEl.className = `xh-eff-${cfg.xhEff}`;
        hub.className = `allow-click kb-eff-${cfg.kbEff}`;
    };

    // Chọn Tâm Nhắm
    document.querySelectorAll('.xh-btn').forEach(btn => {
        btn.addEventListener('click', (e) => {
            cfg.xh = e.target.getAttribute('data-val');
            saveCfg(); applyAllCfg();
        });
    });

    // Chọn Màu
    document.querySelectorAll('.color-btn').forEach(btn => {
        btn.addEventListener('click', (e) => {
            cfg.xhColor = e.target.getAttribute('data-val');
            saveCfg(); applyAllCfg();
        });
    });

    // Chọn Hiệu ứng (Dùng function gắn sự kiện vì HTML được render lại khi đổi ngôn ngữ)
    function bindEffectEvents() {
        document.querySelectorAll('.xhe-btn').forEach(btn => {
            btn.addEventListener('click', (e) => {
                cfg.xhEff = parseInt(e.target.getAttribute('data-val'));
                saveCfg(); applyAllCfg(); renderLang(); // Cập nhật nút màu sáng (active)
            });
        });
        document.querySelectorAll('.kbe-btn').forEach(btn => {
            btn.addEventListener('click', (e) => {
                cfg.kbEff = parseInt(e.target.getAttribute('data-val'));
                saveCfg(); applyAllCfg(); renderLang();
            });
        });
    }

    // Khởi chạy ngay khi load
    renderLang();
    applyAllCfg();

    // ==========================================
    // 7. NHÁY TRẮNG BÀN PHÍM VÀ AUTO LOOT
    // ==========================================
    const allVkKeys = document.querySelectorAll('.vk-key');
    document.addEventListener('keydown', (e) => {
        let keyName = e.key.toUpperCase();
        allVkKeys.forEach(vk => {
            if (vk.getAttribute('data-key') === keyName || (e.code === 'Space' && vk.getAttribute('data-key') === 'SPACE')) {
                vk.classList.add('active');
            }
        });
    });
    document.addEventListener('keyup', (e) => {
        let keyName = e.key.toUpperCase();
        allVkKeys.forEach(vk => {
            if (vk.getAttribute('data-key') === keyName) {
                vk.classList.remove('active');
            }
        });
    });

    // Auto Loot 
    document.addEventListener('click', (e) => {
        let t = e.target;
        if (t.className && typeof t.className === 'string' && (t.className.toLowerCase().includes('item') || t.className.toLowerCase().includes('loot'))) {
            let bp = document.querySelector('.backpack, #backpack, [class*="inventory"]');
            if (bp) {
                bp.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, cancelable: true, view: window }));
                t.style.display = 'none';
            }
        }
    });

})();