Greasy Fork is available in English.

TV Block ESP

Please dont report

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         TV Block ESP
// @namespace    *://minefun.io/*
// @version      2.5.0
// @author       TVhackgaming
// @description  Please dont report
// @match        *://minefun.io/*
// @grant        none
// @license      MIT
// ==/UserScript==

/* eslint-disable */
(function () {
    'use strict';

    var ALL_IDS = [ 1067, 572, 580, 840, 503, 1063, 571, 581, 616, 830];

    var ACTIVE_IDS    = ALL_IDS.slice();
    var SEARCH_RADIUS = 5;
    var MAX_RADIUS    = 16;
    var FOV_Y         = 70;
    var BATCH_SIZE    = 5;
    var STEPS_FRAME   = 80;

    var targetBlocks = [];
    var allBlocks    = [];
    var espOn        = true;
    var camera       = null;
    var scanState    = null;
    var lastURL      = location.href;
    var checkTick    = 0;
    var ui, listEl, statusEl;

    // ID colors
    var ID_COLORS = {
        1067:   '#f70a41',  // Infernal Shard
        572:    '#575403',   // gold block
        580:    '#03574e',   // diamond block
        840: '#64B5F6',   // furnace
        503: '#fefcff',   // Private block
        1063: '#230a40',   // Screaming Obsidian
        571: '#ffff05',   // gold
        581: '#80DEEA',   // diamond
        616: '#050505',   // coal
        830: '#e8e8e8'    // iron
    };
    function colorFor(id){ return ID_COLORS[id] || '#ffffff'; }

    var cvs = document.createElement('canvas');
    cvs.style.cssText = 'position:fixed;top:0;left:0;width:100vw;height:100vh;pointer-events:none;z-index:2147483646';
    document.body.appendChild(cvs);
    var ctx = cvs.getContext('2d');
    function resize(){ cvs.width=innerWidth; cvs.height=innerHeight; }
    resize(); window.addEventListener('resize', resize);

    function getO() {
        try {
            var r   = app._vnode.component.appContext.provides;
            var sym = Object.getOwnPropertySymbols(r).find(function(s){ return r[s] && r[s]._s; });
            if (!sym) return null;
            var o = r[sym]._s.get('gameState');
            if (!o || !o.gameWorld || !o.gameWorld.chunkManager || !o.gameWorld.player) return null;
            return o;
        } catch(e) { return null; }
    }

    function findCamera(o) {
        if (camera) { try{ if(camera.matrixWorldInverse) return camera; }catch(e){} camera=null; }
        try {
            var sys=o.gameWorld.systemsManager.activeSystems;
            for(var i=0;i<sys.length;i++){
                var s=sys[i]; if(!s) continue;
                var ks=Object.getOwnPropertyNames(s);
                for(var j=0;j<ks.length;j++){
                    try{
                        var v=s[ks[j]]; if(!v||typeof v!=='object') continue;
                        if(v.isPerspectiveCamera||v.isCamera){camera=v;return v;}
                        var ks2=Object.getOwnPropertyNames(v);
                        for(var n=0;n<ks2.length;n++){try{var v2=v[ks2[n]];if(v2&&(v2.isPerspectiveCamera||v2.isCamera)){camera=v2;return v2;}}catch(e){}}
                    }catch(e){}
                }
            }
        }catch(e){}
        return null;
    }

    function worldToScreen(pp, rot, bx, by, bz) {
        if (camera&&camera.projectionMatrix&&camera.matrixWorldInverse) {
            try {
                var mv=camera.matrixWorldInverse.elements, p=camera.projectionMatrix.elements;
                var vx=mv[0]*bx+mv[4]*by+mv[8]*bz+mv[12], vy=mv[1]*bx+mv[5]*by+mv[9]*bz+mv[13];
                var vz=mv[2]*bx+mv[6]*by+mv[10]*bz+mv[14], vw=mv[3]*bx+mv[7]*by+mv[11]*bz+mv[15];
                var cx=p[0]*vx+p[4]*vy+p[8]*vz+p[12]*vw, cy=p[1]*vx+p[5]*vy+p[9]*vz+p[13]*vw;
                var cz=p[2]*vx+p[6]*vy+p[10]*vz+p[14]*vw, cw=p[3]*vx+p[7]*vy+p[11]*vz+p[15]*vw;
                if(cw<=0||cz/cw>1) return null;
                return{x:((cx/cw)*0.5+0.5)*cvs.width, y:(-(cy/cw)*0.5+0.5)*cvs.height};
            }catch(e){camera=null;}
        }
        var dx=bx-pp[0],dy=by-pp[1]-1.6,dz=bz-pp[2];
        var bYaw=Math.atan2(dx,dz)+Math.PI;
        var pYaw=((rot.y%(2*Math.PI))+2*Math.PI)%(2*Math.PI);
        var yd=bYaw-pYaw;
        while(yd>Math.PI)yd-=2*Math.PI;
        while(yd<-Math.PI)yd+=2*Math.PI;
        if(Math.abs(yd)>Math.PI*0.65) return null;
        var h=Math.sqrt(dx*dx+dz*dz),pd=Math.atan2(dy,h)-rot.x;
        var W=cvs.width,H=cvs.height,fvY=FOV_Y*Math.PI/180,fvX=2*Math.atan(Math.tan(fvY/2)*W/H);
        return{x:W/2+(yd/(fvX/2))*(W/2), y:H/2-(pd/(fvY/2))*(H/2)};
    }

    function clampR(r){r=parseInt(r)||5;if(r<1)r=1;if(r>MAX_RADIUS)r=MAX_RADIUS;return r;}

    // huh
    function makeIdSet(){ var s={}; for(var i=0;i<ACTIVE_IDS.length;i++) s[ACTIVE_IDS[i]]=true; return s; }

    function startScan(o) {
        if (scanState) return;
        var R=clampR(SEARCH_RADIUS);
        var pos=Array.from(o.gameWorld.player.position);
        var sx=pos[0]>>4, sy=pos[1]>>4, sz=pos[2]>>4;
        scanState={
            cm:o.gameWorld.chunkManager,
            idSet: makeIdSet(),
            found:[], a:-R,l:-R,m:-R,R:R,
            cx:sx,cy:sy,cz:sz,
            pp:pos, total:Math.pow(2*R+1,3), done:0
        };
    }

    function forceScan(){
        scanState=null; targetBlocks=[]; allBlocks=[];
        var o=getO(); if(o) startScan(o);
    }

    function tickScan(){
        if(!scanState) return;
        var st=scanState, R=st.R, steps=0;
        while(steps<STEPS_FRAME){
            var cx=st.cx+st.a, cy=st.cy+st.l, cz=st.cz+st.m;
            try{
                var arr=st.cm.getChunkArray(cx,cy,cz);
                if(arr){
                    for(var g=0;g<arr.length;g++){
                        var bid=arr[g];
                        if(!st.idSet[bid]) continue;
                        var bx=(cx<<4)+(g&15), by=(cy<<4)+((g>>4)&15), bz=(cz<<4)+(g>>8);
                        try{if(st.cm.getBlock(bx,by,bz)===bid)st.found.push({bx:bx,by:by,bz:bz,id:bid});}catch(e){}
                    }
                }
            }catch(e){}
            st.done++; st.m++;
            if(st.m>R){st.m=-R;st.l++;}
            if(st.l>R){st.l=-R;st.a++;}
            if(st.a>R){
                allBlocks=st.found;
                var pp=st.pp; scanState=null;

                targetBlocks=allBlocks
                    .map(function(b){return{b:b,d:Math.hypot(b.bx-pp[0],b.by-pp[1],b.bz-pp[2])};})
                    .sort(function(a,z){return a.d-z.d;})
                    .slice(0,BATCH_SIZE).map(function(x){return x.b;});
                return;
            }
            steps++;
        }
        if(statusEl){var pct=Math.round(st.done/st.total*100);statusEl.textContent='Escaneando... '+pct+'%';}
    }

    function blockExists(o,b){
        try{return o.gameWorld.chunkManager.getBlock(b.bx,b.by,b.bz)===b.id;}catch(e){return false;}
    }

    function renderLoop(){
        ctx.clearRect(0,0,cvs.width,cvs.height);
        tickScan();
        var o=getO();
        if(o){
            if(!camera)findCamera(o);
            if(camera){try{camera.updateMatrixWorld(true);}catch(e){camera=null;}}

            checkTick++;
            if(checkTick>=45){
                checkTick=0;
                if(!scanState){
                    var alive=targetBlocks.filter(function(b){return blockExists(o,b);});
                    if(alive.length<targetBlocks.length) startScan(o);
                }
            }

            if(espOn&&targetBlocks.length){
                var pp=Array.from(o.gameWorld.player.position);
                var rot=o.gameWorld.player.rotation;
                for(var i=0;i<targetBlocks.length;i++){
                    var b=targetBlocks[i];
                    var sc=worldToScreen(pp,rot,b.bx+0.5,b.by+0.5,b.bz+0.5);
                    if(!sc||sc.x<-80||sc.x>cvs.width+80||sc.y<-80||sc.y>cvs.height+80)continue;
                    var d=Math.hypot(b.bx-pp[0],b.by-pp[1],b.bz-pp[2]);
                    var sz=Math.max(8,Math.min(52,400/d)), hw=sz/2;
                    var col=colorFor(b.id);
                    ctx.save();ctx.shadowColor=col;ctx.shadowBlur=18;ctx.strokeStyle=col;ctx.lineWidth=2.5;
                    ctx.strokeRect(sc.x-hw,sc.y-hw,sz,sz);
                    ctx.fillStyle=col.slice(0,7)+'22';ctx.fillRect(sc.x-hw,sc.y-hw,sz,sz);
                    ctx.restore();
                    ctx.save();ctx.font='bold 10px monospace';ctx.textAlign='center';
                    ctx.strokeStyle='rgba(0,0,0,0.9)';ctx.lineWidth=3;
                    ctx.strokeText(b.id+' '+d.toFixed(0)+'m',sc.x,sc.y-hw-3);
                    ctx.fillStyle='#fff';ctx.fillText(b.id+' '+d.toFixed(0)+'m',sc.x,sc.y-hw-3);
                    ctx.restore();
                }
            }

            if(!scanState){
                var pp2=Array.from(o.gameWorld.player.position);
                var camL=camera?'cam exacta':'angular FOV:'+FOV_Y;
                if(statusEl)statusEl.textContent=targetBlocks.length+'/5 activos | '+allBlocks.length+' total | '+camL;
                if(listEl){
                    listEl.textContent=targetBlocks.length===0?'none nearby':
                        targetBlocks.map(function(b){
                            return{b:b,d:Math.hypot(b.bx-pp2[0],b.by-pp2[1],b.bz-pp2[2])};
                        }).sort(function(a,z){return a.d-z.d;})
                        .map(function(x){
                            return '['+x.b.id+'] '+x.b.bx+','+x.b.by+','+x.b.bz+'  '+x.d.toFixed(1)+'m';
                        }).join('\n');
                }
            }
        }else{
            if(targetBlocks.length>0){targetBlocks=[];allBlocks=[];camera=null;scanState=null;
                if(listEl)listEl.textContent='';if(statusEl)statusEl.textContent='Esperando partida...';}
        }
        if(location.href!==lastURL){lastURL=location.href;targetBlocks=[];allBlocks=[];camera=null;scanState=null;
            if(statusEl)statusEl.textContent='Cargando nueva partida...';}
        requestAnimationFrame(renderLoop);
    }

    function createUI(){
        ui=document.createElement('div');
        // RED AND BLACK
        ui.style.cssText='position:fixed;top:80px;left:80px;width:280px;background:#0d0d0d;color:#e0e0e0;font:11px system-ui,sans-serif;border:1.5px solid #ff1e1e;border-radius:6px;box-shadow:0 0 15px rgba(255,30,30,0.3);z-index:2147483647;user-select:none;display:flex;flex-direction:column;';

        var cbHtml='';
        for(var i=0;i<ALL_IDS.length;i++){
            var id=ALL_IDS[i], col=colorFor(id);
            cbHtml+='<label style="display:inline-flex;align-items:center;gap:2px;margin:2px;cursor:pointer;font-size:10px">'
                +'<input type="checkbox" class="bfcb" data-id="'+id+'" checked '
                +'style="accent-color:'+col+'"> '
                +'<span style="color:'+col+'">'+id+'</span></label>';
        }

        ui.innerHTML='<div class="bfh" style="padding:6px 8px;cursor:move;display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid #ff1e1e;font-weight:700;background:#140505;color:#ff4d4d"><span>Block Finder</span><button id="bfesp" style="background:#b71c1c;border:1px solid #ff5252;color:#fff;border-radius:3px;padding:2px 7px;cursor:pointer;font-size:10px">ESP ON</button></div>'
            +'<div style="padding:4px 8px;border-bottom:1px solid #260a0a">'+cbHtml+'</div>'
            +'<div style="padding:4px 8px;border-bottom:1px solid #260a0a;display:flex;gap:4px;align-items:center">'
            +'<label style="font-size:10px;color:#ccc">R(chunks):<input id="bfr" type="number" min="1" max="'+MAX_RADIUS+'" value="'+SEARCH_RADIUS+'" style="width:30px;background:#1a1a1a;border:1px solid #ff1e1e;color:#fff;border-radius:3px;padding:2px 3px;text-align:center"></label>'
            +'<label style="font-size:10px;color:#ccc">FOV:<input id="bffov" type="number" value="'+FOV_Y+'" style="width:34px;background:#1a1a1a;border:1px solid #ff1e1e;color:#fff;border-radius:3px;padding:2px 3px;text-align:center"></label>'
            +'<button id="bfscan" style="background:#81c784;border:none;color:#000;font-weight:bold;border-radius:3px;padding:2px 6px;cursor:pointer;font-size:10px">Scan</button>'
            +'</div>'
            +'<div id="bfst" style="padding:2px 8px;font-size:10px;color:#ff6666;border-bottom:1px solid #260a0a">Esperando partida...</div>'
            +'<div id="bflist" style="max-height:180px;overflow:auto;padding:4px 8px 8px;font-family:monospace;white-space:pre;font-size:11px;color:#ffb3b3"></div>'
            // THANH NẮM KÉO PHÍA DƯỚI (DRAG BAR BOTTOM)
            +'<div class="bfb-drag" style="padding:6px;cursor:move;background:#140505;border-top:1px solid #ff1e1e;display:flex;justify-content:center;align-items:center;border-radius:0 0 4px 4px;">'
            +'<div style="width:40px;height:4px;background:#ff4d4d;border-radius:2px;box-shadow:0 0 5px rgba(255,77,77,0.5);"></div>'
            +'</div>';

        document.body.appendChild(ui);
        listEl=ui.querySelector('#bflist');statusEl=ui.querySelector('#bfst');

        function readActive(){
            ACTIVE_IDS=[];
            var cbs=ui.querySelectorAll('.bfcb');
            for(var i=0;i<cbs.length;i++) if(cbs[i].checked) ACTIVE_IDS.push(parseInt(cbs[i].dataset.id));
        }

        ui.querySelectorAll('.bfcb').forEach(function(cb){
            cb.addEventListener('change',function(){ readActive(); forceScan(); });
        });

        ui.querySelector('#bfscan').onclick=function(){
            SEARCH_RADIUS=clampR(ui.querySelector('#bfr').value);
            ui.querySelector('#bfr').value=SEARCH_RADIUS;
            FOV_Y=parseInt(ui.querySelector('#bffov').value)||70;
            readActive(); forceScan();
        };
        ui.querySelector('#bfr').addEventListener('change',function(){SEARCH_RADIUS=clampR(this.value);this.value=SEARCH_RADIUS;});
        ui.querySelector('#bffov').addEventListener('change',function(){FOV_Y=parseInt(this.value)||70;});
        ui.querySelector('#bfesp').onclick=function(){
            espOn=!espOn;
            this.textContent=espOn?'ESP ON':'ESP OFF';
            this.style.background=espOn?'#b71c1c':'#333';
            this.style.borderColor=espOn?'#ff5252':'#555';
        };

        // 6TOUCH & MOUSE7
        var drag=false, ox=0, oy=0;

        function startDrag(clientX, clientY) {
            drag = true;
            ox = clientX - ui.offsetLeft;
            oy = clientY - ui.offsetTop;
        }

        function doDrag(clientX, clientY) {
            if (drag) {
                ui.style.left = (clientX - ox) + 'px';
                ui.style.top = (clientY - oy) + 'px';
            }
        }

        function stopDrag() {
            drag = false;
        }

        var dragElements = [ui.querySelector('.bfh'), ui.querySelector('.bfb-drag')];
        dragElements.forEach(function(el) {
            // Chuột (Mouse)
            el.addEventListener('mousedown', function(e){ startDrag(e.clientX, e.clientY); });

            // Màn hình cảm ứng Mobile (Touch)
            el.addEventListener('touchstart', function(e){
                if (e.touches.length === 1) {
                    startDrag(e.touches[0].clientX, e.touches[0].clientY);
                }
            }, { passive: true });
        });

        document.addEventListener('mousemove', function(e){ doDrag(e.clientX, e.clientY); });
        document.addEventListener('mouseup', stopDrag);

        document.addEventListener('touchmove', function(e){
            if (drag && e.touches.length === 1) {
                doDrag(e.touches[0].clientX, e.touches[0].clientY);
            }
        }, { passive: true });
        document.addEventListener('touchend', stopDrag);
    }

    function tryInit(){
        var o=getO();if(!o){setTimeout(tryInit,1000);return;}
        createUI();findCamera(o);startScan(o);renderLoop();
    }
    setTimeout(tryInit,2000);
})();