Greasy Fork is available in English.
Please dont report
// ==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);
})();