Minefun Advanced Auto-Scaffold Engine

Hệ thống Scaffold tự động bắt điểm, hook Three.js/WebSocket và dự đoán quỹ đạo di chuyển

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Minefun Advanced Auto-Scaffold Engine
// @namespace    http://tampermonkey.net/
// @version      2.5
// @description  Hệ thống Scaffold tự động bắt điểm, hook Three.js/WebSocket và dự đoán quỹ đạo di chuyển
// @match        https://minefun.io/*
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function () {
    'use strict';

    // ==========================================
    // 1. CẤU HÌNH & TRẠNG THÁI HỆ THỐNG
    // ==========================================
    const CONFIG = {
        enabled: true,
        toggleKey: 'KeyB',
        slotKey: '1',               // Ô chứa block trên Hotbar
        cps: 20,                    // Tốc độ đặt block tối đa (lần/giây)
        reachDistance: 4.5,         // Khoảng cách tầm với tối đa
        aheadPrediction: 0.8,       // Hệ số dự đoán bước đi phía trước
        downOffset: 1.1,            // Độ sâu phát hiện lỗ hổng dưới chân
        autoExpand: true,           // Tự mở rộng sàn nếu đang chạy nhanh
        debugHUD: true              // Hiển thị bảng thông số kỹ thuật trên màn hình
    };

    const EngineState = {
        scene: null,
        camera: null,
        player: null,
        world: null,
        webSocket: null,
        playerPos: { x: 0, y: 0, z: 0 },
        playerVel: { x: 0, y: 0, z: 0 },
        playerRotation: { yaw: 0, pitch: 0 },
        lastPlaceTime: 0,
        blocksPlaced: 0
    };

    // ==========================================
    // 2. HOOK WEBSOCKET & CORE THREE.JS
    // ==========================================
    const NativeWebSocket = window.WebSocket;
    window.WebSocket = function (...args) {
        const ws = new NativeWebSocket(...args);
        EngineState.webSocket = ws;

        const originalSend = ws.send;
        ws.send = function (data) {
            // Phân tích gói tin gửi lên server (Position / Rotation / Block Place)
            try {
                if (typeof data === 'string' && data.startsWith('{')) {
                    const parsed = JSON.parse(data);
                    if (parsed.type === 'move' || parsed.type === 'position') {
                        if (parsed.x !== undefined) EngineState.playerPos = { x: parsed.x, y: parsed.y, z: parsed.z };
                    }
                }
            } catch (e) {}
            return originalSend.apply(this, arguments);
        };

        ws.addEventListener('message', (event) => {
            // Phân tích gói tin server trả về để đồng bộ thế giới
            try {
                if (typeof event.data === 'string' && event.data.startsWith('{')) {
                    const parsed = JSON.parse(event.data);
                    if (parsed.type === 'init' || parsed.type === 'world') {
                        console.log('[Scaffold Engine] Đồng bộ dữ liệu Thế giới thành công!');
                    }
                }
            } catch (e) {}
        });

        return ws;
    };

    // Intercept Three.js Scene & Camera thông qua Prototype
    const originalAdd = Object.prototype.add;
    let sceneCaptured = false;

    Object.defineProperty(Object.prototype, 'isScene', {
        get() {
            if (this.type === 'Scene' && !sceneCaptured) {
                EngineState.scene = this;
                sceneCaptured = true;
                console.log('[Scaffold Engine] Captured Three.js Scene Context:', this);
            }
            return this._isScene;
        },
        set(v) { this._isScene = v; },
        configurable: true
    });

    // ==========================================
    // 3. TOÁN HỌC VECTOR & RAYCASTING
    // ==========================================
    class Vector3D {
        constructor(x = 0, y = 0, z = 0) {
            this.x = x;
            this.y = y;
            this.z = z;
        }

        add(v) { return new Vector3D(this.x + v.x, this.y + v.y, this.z + v.z); }
        sub(v) { return new Vector3D(this.x - v.x, this.y - v.y, this.z - v.z); }
        multiplyScalar(s) { return new Vector3D(this.x * s, this.y * s, this.z * s); }
        floor() { return new Vector3D(Math.floor(this.x), Math.floor(this.y), Math.floor(this.z)); }
        distanceTo(v) { return Math.sqrt((this.x - v.x) ** 2 + (this.y - v.y) ** 2 + (this.z - v.z) ** 2); }
    }

    function getLookingDirection(yaw, pitch) {
        const cosPitch = Math.cos(pitch);
        return new Vector3D(
            -Math.sin(yaw) * cosPitch,
            Math.sin(pitch),
            -Math.cos(yaw) * cosPitch
        );
    }

    // ==========================================
    // 4. BẮT ĐIỂM VÀ TÌM VỊ TRÍ ĐẶT BLOCK
    // ==========================================
    function scanForAirHole() {
        const rawPos = getPlayerPosition();
        if (!rawPos) return null;

        const vel = getPlayerVelocity();
        
        // Tính toán vị trí dự đoán tương lai dựa trên tốc độ di chuyển
        const predictedX = rawPos.x + vel.x * CONFIG.aheadPrediction;
        const predictedZ = rawPos.z + vel.z * CONFIG.aheadPrediction;
        const targetY = rawPos.y - CONFIG.downOffset;

        const checkPos = new Vector3D(predictedX, targetY, predictedZ).floor();

        // Kiểm tra xem vị trí mục tiêu có phải là không khí không
        if (isBlockEmpty(checkPos.x, checkPos.y, checkPos.z)) {
            // Tìm block hàng xóm gần nhất để tựa vào khi đặt
            const neighbor = findSolidNeighbor(checkPos);
            return {
                target: checkPos,
                neighbor: neighbor
            };
        }

        return null;
    }

    function isBlockEmpty(x, y, z) {
        // Trích xuất dữ liệu World từ Global hoặc Raycast qua Scene
        const world = EngineState.world || window.world || (window.game && window.game.world);
        if (world && typeof world.getBlock === 'function') {
            const block = world.getBlock(x, y, z);
            return !block || block === 0 || block.id === 0 || block.type === 'air';
        }

        // Phương án dự phòng Raycast thủ công qua Mesh trong Three.js
        if (EngineState.scene) {
            let foundSolid = false;
            EngineState.scene.traverse((obj) => {
                if (obj.isMesh && obj.position) {
                    const mx = Math.floor(obj.position.x);
                    const my = Math.floor(obj.position.y);
                    const mz = Math.floor(obj.position.z);
                    if (mx === x && my === y && mz === z) {
                        foundSolid = true;
                    }
                }
            });
            return !foundSolid;
        }

        return true;
    }

    function findSolidNeighbor(pos) {
        const offsets = [
            { x: 0, y: -1, z: 0, face: 'top' },
            { x: 1, y: 0, z: 0, face: 'west' },
            { x: -1, y: 0, z: 0, face: 'east' },
            { x: 0, y: 0, z: 1, face: 'north' },
            { x: 0, y: 0, z: -1, face: 'south' }
        ];

        for (const off of offsets) {
            const nx = pos.x + off.x;
            const ny = pos.y + off.y;
            const nz = pos.z + off.z;
            if (!isBlockEmpty(nx, ny, nz)) {
                return { x: nx, y: ny, z: nz, face: off.face };
            }
        }
        return null;
    }

    // ==========================================
    // 5. TRÍCH XUẤT THÔNG TIN PLAYER
    // ==========================================
    function getPlayerPosition() {
        if (EngineState.playerPos.x !== 0) return new Vector3D(EngineState.playerPos.x, EngineState.playerPos.y, EngineState.playerPos.z);
        
        const player = window.localPlayer || (window.game && window.game.player) || window.player;
        if (player && player.position) {
            return new Vector3D(player.position.x, player.position.y, player.position.z);
        }

        if (EngineState.scene) {
            // Tìm Camera trong Scene
            let camPos = null;
            EngineState.scene.traverse((child) => {
                if (child.isCamera || child.type === 'PerspectiveCamera') {
                    EngineState.camera = child;
                    camPos = child.position;
                }
            });
            if (camPos) return new Vector3D(camPos.x, camPos.y, camPos.z);
        }

        return null;
    }

    function getPlayerVelocity() {
        const player = window.localPlayer || (window.game && window.game.player) || window.player;
        if (player && player.velocity) {
            return new Vector3D(player.velocity.x, player.velocity.y, player.velocity.z);
        }
        return new Vector3D(EngineState.playerVel.x, EngineState.playerVel.y, EngineState.playerVel.z);
    }

    // ==========================================
    // 6. HỆ THỐNG THỰC THI THAO TÁC (INPUT SPOOFING)
    // ==========================================
    function executeBlockPlacement(holeData) {
        // Step 1: Chuyển Hotbar sang ô đặt Block
        selectHotbarSlot(CONFIG.slotKey);

        // Step 2: Đặt block trực tiếp qua gọi hàm nội bộ hoặc giả lập gói tin/chuột
        const game = window.game || window.Client;
        if (game && typeof game.placeBlock === 'function') {
            game.placeBlock(holeData.target.x, holeData.target.y, holeData.target.z);
            EngineState.blocksPlaced++;
            return;
        }

        // Gọi trực tiếp qua WebSocket nếu đã bắt được kết nối
        if (EngineState.webSocket && EngineState.webSocket.readyState === WebSocket.OPEN) {
            const packet = JSON.stringify({
                type: 'place',
                x: holeData.target.x,
                y: holeData.target.y,
                z: holeData.target.z,
                slot: parseInt(CONFIG.slotKey) - 1
            });
            EngineState.webSocket.send(packet);
            EngineState.blocksPlaced++;
        }

        // Giả lập sự kiện chuột phải chuẩn WebGL Canvas
        dispatchMouseEvents();
    }

    function selectHotbarSlot(slotChar) {
        const eventDown = new KeyboardEvent('keydown', {
            key: slotChar,
            code: `Digit${slotChar}`,
            keyCode: 48 + parseInt(slotChar),
            which: 48 + parseInt(slotChar),
            bubbles: true,
            cancelable: true
        });
        const eventUp = new KeyboardEvent('keyup', {
            key: slotChar,
            code: `Digit${slotChar}`,
            keyCode: 48 + parseInt(slotChar),
            which: 48 + parseInt(slotChar),
            bubbles: true,
            cancelable: true
        });

        window.dispatchEvent(eventDown);
        document.dispatchEvent(eventDown);
        setTimeout(() => {
            window.dispatchEvent(eventUp);
            document.dispatchEvent(eventUp);
        }, 5);
    }

    function dispatchMouseEvents() {
        const canvas = document.querySelector('canvas') || document.body;
        const rect = canvas.getBoundingClientRect();
        const cx = rect.left + rect.width / 2;
        const cy = rect.top + rect.height / 2;

        const mouseDown = new MouseEvent('mousedown', {
            button: 2, // Chuột phải
            buttons: 2,
            clientX: cx,
            clientY: cy,
            bubbles: true,
            cancelable: true
        });

        const mouseUp = new MouseEvent('mouseup', {
            button: 2,
            buttons: 0,
            clientX: cx,
            clientY: cy,
            bubbles: true,
            cancelable: true
        });

        canvas.dispatchEvent(mouseDown);
        setTimeout(() => canvas.dispatchEvent(mouseUp), 10);
    }

    // ==========================================
    // 7. GIAO DIỆN HIỂN THỊ TRẠNG THÁI (HUD OVERLAY)
    // ==========================================
    let hudElement = null;

    function createHUD() {
        if (!CONFIG.debugHUD || hudElement) return;

        hudElement = document.createElement('div');
        hudElement.style.position = 'fixed';
        hudElement.style.top = '15px';
        hudElement.style.left = '15px';
        hudElement.style.padding = '10px 14px';
        hudElement.style.backgroundColor = 'rgba(0, 0, 0, 0.75)';
        hudElement.style.color = '#00FFCC';
        hudElement.style.fontFamily = 'monospace';
        hudElement.style.fontSize = '12px';
        hudElement.style.borderRadius = '6px';
        hudElement.style.zIndex = '999999';
        hudElement.style.border = '1px solid #00FFCC';
        hudElement.style.pointerEvents = 'none';
        hudElement.style.boxShadow = '0 0 8px rgba(0,255,204,0.3)';
        document.body.appendChild(hudElement);
    }

    function updateHUD(targetInfo) {
        if (!hudElement) return;

        const pos = getPlayerPosition() || new Vector3D(0, 0, 0);
        hudElement.innerHTML = `
            <b style="color:#FFF;">[MINEFUN SCAFFOLD ENGINE]</b><br>
            Trạng thái: <span style="color:${CONFIG.enabled ? '#00FF00' : '#FF0000'}">${CONFIG.enabled ? 'ĐÃ BẬT [Phím B]' : 'ĐÃ TẮT [Phím B]'}</span><br>
            Vị trí Player: ${pos.x.toFixed(1)}, ${pos.y.toFixed(1)}, ${pos.z.toFixed(1)}<br>
            Lỗ hổng gần nhất: ${targetInfo ? `${targetInfo.target.x}, ${targetInfo.target.y}, ${targetInfo.target.z}` : 'Không phát hiện'}<br>
            Hotbar Slot: ${CONFIG.slotKey}<br>
            Blocks Đã Đặt: ${EngineState.blocksPlaced}
        `;
    }

    // ==========================================
    // 8. VÒNG LẶP CHÍNH (MAIN ENGINE LOOP)
    // ==========================================
    window.addEventListener('keydown', (e) => {
        if (e.code === CONFIG.toggleKey) {
            CONFIG.enabled = !CONFIG.enabled;
        }
    });

    function mainLoop() {
        requestAnimationFrame(mainLoop);

        if (CONFIG.debugHUD) createHUD();

        const holeData = scanForAirHole();
        updateHUD(holeData);

        if (!CONFIG.enabled) return;

        const now = Date.now();
        const minInterval = 1000 / CONFIG.cps;

        if (now - EngineState.lastPlaceTime < minInterval) return;

        if (holeData) {
            executeBlockPlacement(holeData);
            EngineState.lastPlaceTime = now;
        }
    }

    // Khởi chạy Engine khi trang tải xong
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', () => setTimeout(mainLoop, 1000));
    } else {
        setTimeout(mainLoop, 1000);
    }

})();