BloxdAura

KillAura for bloxd.io

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         BloxdAura
// @namespace    bloxd-aura
// @version      1.0.0
// @description  KillAura for bloxd.io
// @author       pentest
// @match        https://*.bloxd.io/*
// @grant        none
// @run-at       document-idle
// ==/UserScript==

(function() {
    'use strict';

    let settings = {
        enabled: false,
        range: 6,
        attackSpeed: 150, // ms between attacks
        attackKey: 'R'    // toggle key
    };

    // UI
    let uiContainer = null;
    let statusDot = null;
    let toggleBtn = null;

    // Internal refs
    let gameAPI = null;
    let lastAttackTime = 0;
    let auraInterval = null;
    let targetScanInterval = null;
    let currentTarget = null;
    let initialized = false;

    // ─── Find game internals dynamically ────────────────────────────
    function findGameAPI() {
        // Try multiple paths to find the game's internal API
        // Using the bloxd global object that the game exposes
        if (window.bloxd && window.bloxd.noa) {
            let noa = window.bloxd.noa;
            // Check for entity system
            if (noa.entities) {
                return { noa, bloxd: window.bloxd };
            }
        }
        // Fallback: traverse game canvas
        if (window.gameInstance && window.gameInstance.noa) {
            return { noa: window.gameInstance.noa, bloxd: window.gameInstance };
        }
        return null;
    }

    // ─── Entity discovery ──────────────────────────────────────────
    function getOtherPlayers() {
        if (!gameAPI) return [];
        try {
            let players = [];
            let state = gameAPI.noa.entities.getState();
            if (!state) return [];

            let myId = gameAPI.bloxd.playerId || 1;

            for (let [eid, entity] of Object.entries(state)) {
                if (!entity || eid == myId) continue;
                
                // Check if it's a player (has position, is alive)
                if (entity.position && entity.breath !== undefined) {
                    players.push({
                        eid: parseInt(eid),
                        entity: entity,
                        pos: entity.position
                    });
                }
            }
            return players;
        } catch(e) {
            return [];
        }
    }

    function distanceTo(pos) {
        if (!gameAPI || !gameAPI.noa) return Infinity;
        try {
            let cam = gameAPI.noa.camera;
            if (!cam) return Infinity;
            let dx = pos[0] - cam[0],
                dy = pos[1] - cam[1],
                dz = pos[2] - cam[2];
            return Math.sqrt(dx*dx + dy*dy + dz*dz);
        } catch(e) {
            return Infinity;
        }
    }

    // ─── Attack ───────────────────────────────────────────────────
    function attackEntity(eid) {
        if (!gameAPI) return false;
        try {
            let noa = gameAPI.noa;
            
            // Method 1: Direct entity attack if available
            if (noa.entities && typeof noa.entities.doAttack === 'function') {
                noa.entities.doAttack(eid);
                return true;
            }
            
            // Method 2: Look for attack on the specific entity
            let state = noa.entities.getState();
            if (state && state[eid]) {
                let ent = state[eid];
                if (typeof ent.doAttack === 'function') {
                    ent.doAttack(eid);
                    return true;
                }
                // Check breakingItem chain
                if (ent.breakingItem && typeof ent.breakingItem.doAttack === 'function') {
                    ent.breakingItem.doAttack(eid);
                    return true;
                }
            }
            
            // Method 3: Try the game's internal attack method through the container
            if (noa.entities._eidData && noa.entities._eidData[eid]) {
                let data = noa.entities._eidData[eid];
                if (data.mesh && data.mesh.doAttack) {
                    data.mesh.doAttack(eid);
                    return true;
                }
            }

            // Method 4: Send through game container
            let ecs = noa.entities;
            if (ecs.attackEntity) {
                ecs.attackEntity(eid);
                return true;
            }

            return false;
        } catch(e) {
            return false;
        }
    }

    function findAndAttackBestTarget() {
        if (!gameAPI || !settings.enabled) return;
        
        let now = Date.now();
        if (now - lastAttackTime < settings.attackSpeed) return;

        let players = getOtherPlayers();
        if (!players.length) return;

        let best = null;
        let bestDist = settings.range;

        for (let p of players) {
            let d = distanceTo(p.pos);
            if (d < bestDist) {
                bestDist = d;
                best = p;
            }
        }

        if (best) {
            currentTarget = best;
            lastAttackTime = now;
            attackEntity(best.eid);
        } else {
            currentTarget = null;
        }
    }

    // ─── UI ────────────────────────────────────────────────────────
    function createUI() {
        if (uiContainer) return;

        uiContainer = document.createElement('div');
        uiContainer.id = 'bloxd-aura-ui';
        uiContainer.style.cssText = `
            position: fixed; top: 8px; right: 8px; z-index: 999999;
            font-family: 'Segoe UI', Arial, sans-serif;
            background: rgba(10,10,10,0.85);
            border: 1px solid rgba(255,255,255,0.1);
            border-radius: 8px;
            padding: 10px 14px;
            color: #eee;
            font-size: 13px;
            user-select: none;
            backdrop-filter: blur(4px);
            min-width: 160px;
            pointer-events: auto;
        `;

        // Header row
        let header = document.createElement('div');
        header.style.cssText = 'display:flex;align-items:center;gap:8px;margin-bottom:6px;font-weight:600;';

        statusDot = document.createElement('span');
        statusDot.style.cssText = `
            display:inline-block;width:10px;height:10px;border-radius:50%;
            background:#666;transition:background 0.2s;
        `;

        let title = document.createElement('span');
        title.textContent = 'Aura';

        let keyHint = document.createElement('span');
        keyHint.style.cssText = 'font-size:10px;color:#888;margin-left:auto;';
        keyHint.textContent = `[${settings.attackKey}]`;

        header.appendChild(statusDot);
        header.appendChild(title);
        header.appendChild(keyHint);

        // Info row
        let info = document.createElement('div');
        info.style.cssText = 'font-size:11px;color:#999;';
        info.textContent = '±' + settings.range + 'm';

        uiContainer.appendChild(header);
        uiContainer.appendChild(info);

        // Toggle on click
        uiContainer.addEventListener('click', function(e) {
            e.stopPropagation();
            toggle();
        });

        document.body.appendChild(uiContainer);
    }

    function updateUI() {
        if (!statusDot) return;
        if (settings.enabled) {
            statusDot.style.background = '#ff4444';
            statusDot.style.boxShadow = '0 0 6px #ff4444';
        } else {
            statusDot.style.background = '#666';
            statusDot.style.boxShadow = 'none';
        }
    }

    // ─── Control ───────────────────────────────────────────────────
    function enable() {
        settings.enabled = true;
        updateUI();
        
        if (targetScanInterval) clearInterval(targetScanInterval);
        if (auraInterval) clearInterval(auraInterval);

        // Scan for targets and attack on a timer
        auraInterval = setInterval(() => {
            findAndAttackBestTarget();
        }, Math.min(settings.attackSpeed, 100));
    }

    function disable() {
        settings.enabled = false;
        if (auraInterval) {
            clearInterval(auraInterval);
            auraInterval = null;
        }
        if (targetScanInterval) {
            clearInterval(targetScanInterval);
            targetScanInterval = null;
        }
        currentTarget = null;
        updateUI();
    }

    function toggle() {
        if (settings.enabled) {
            disable();
        } else {
            enable();
        }
    }

    // ─── Keybind ───────────────────────────────────────────────────
    function onKeyDown(e) {
        if (e.key.toUpperCase() === settings.attackKey && 
            !e.ctrlKey && !e.altKey && !e.metaKey &&
            !e.target.matches('input, textarea, [contenteditable]')) {
            e.preventDefault();
            toggle();
        }
    }

    // ─── Init ──────────────────────────────────────────────────────
    function init() {
        if (initialized) return;

        // Try to find game API immediately
        gameAPI = findGameAPI();

        if (!gameAPI) {
            // Wait for game to load — poll
            let attempts = 0;
            let h = setInterval(() => {
                attempts++;
                gameAPI = findGameAPI();
                if (gameAPI || attempts > 30) {
                    clearInterval(h);
                    if (gameAPI) {
                        initialized = true;
                        setup();
                    }
                }
            }, 500);
            return;
        }

        initialized = true;
        setup();
    }

    function setup() {
        createUI();
        updateUI();
        document.addEventListener('keydown', onKeyDown);
        console.log('[Aura] Ready — press ' + settings.attackKey + ' to toggle');
    }

    // Start
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }

    // Expose for debugging
    window.__aura = {
        toggle,
        enable,
        disable,
        getSettings: () => ({...settings}),
        setRange: (r) => { settings.range = Math.max(1, Math.min(20, r)); },
        setSpeed: (s) => { settings.attackSpeed = Math.max(50, Math.min(1000, s)); }
    };

})();