ngx-minecraft/mcroute.js
2025-06-22 02:37:03 +05:00

277 lines
11 KiB
JavaScript

var where_v = "";
function mcproto(s) {
var bufs=[];
var eating=null;
var eatpr=0;
var cond=null;
var rr=null;
var lasted = false;
async function read_b(count,b) {
var arred=count!=null;
count=count??1;
var out = [];
if(b==null) {
while (count>0) {
if(eating!=null&&eatpr>=eating.length) {
eating = null;
eatpr = 0;
}
if(eating==null) {
if(bufs.length == 0) {
if (lasted) {
throw "ran out of data";
}
await (new Promise((a,r)=>(cond=a,rr=r,[][[]])));
}
eating=bufs.shift();
if(eating==null ) throw "Wtf!"
}
out.push(eating[eatpr++]);count--;
}
} else {
while (count>0) {
b.i=b.i??0;
var cc = b.buf[b.i++];count--;
if(cc==null) {
throw new Error("ran out of data (buf)");
}
out.push(cc);
}
}
return arred?out:out[0];
}
s.on("upstream",function(b,opt){
if (b.length > 0) {
bufs.push(b);
if(cond!=null) cond();
}
lasted = lasted||opt.last;
if (b.length==0 && lasted) {
rr("unexpected end");
}
})
var unreg =_=> s.off("upstream");
async function readVarInt(b) {
var Int = 0;
var power = 0;
var rr;
while(1) {
rr=await read_b(null,b);
Int+=(rr&(0x80-1))<<power;
if(!(rr>>7)) {
break;
}
power+=7;
if(power>32)
throw "varInt too big!";
}
return Int|0;
}
async function readPacket(b) {
var len = await readVarInt(b);
if (len > 2097151) {
throw "packet too big!";
}
var pack = await read_b(len,b);
pack = {buf:pack};
try {
pack.type = await readVarInt(pack);
} catch(e) {
s.error("bad packet! "+JSON.stringify(pack));
throw e;
}
return pack;
}
async function readString(b) {
var len = await readVarInt(b);
var text = await read_b(len,b);
text = (new TextDecoder())
.decode(new Uint8Array(text));
return text;
}
async function readShort(b) {
var p = await read_b(2,b);
return (p[0]<<8)+p[1];
}
return {
read_b, unreg, readVarInt, readPacket, readString, readShort
};
}
function makeVarInt(Int) {
var rr;
var out=[];
while (1) {
rr = Int&(0x80-1);
Int>>=7;
if(Int>0) {
out.push(rr|0x80);
} else {
out.push(rr);
break;
}
}
return out;
}
function makePacket(type,pack) {
var pack1 = [];
var ll=makeVarInt(type);
memcpy(makeVarInt(ll.length+pack.length),pack1)
memcpy(ll,pack1);
memcpy(pack,pack1);
return pack1;
}
function makeString(desc) {
var pack = [];
var str=[];
memcpy((new TextEncoder())
.encode(desc),str);
memcpy(makeVarInt(str.length),pack);
memcpy(str,pack);
return pack;
}
function makeNBTString(desc) {
var pack = [];
var str=[];
memcpy((new TextEncoder())
.encode(desc),str);
memcpy([8,(str.length>>8)&0xff,str.length&0xff],pack);
return pack;
}
function wellcome(desc,s) {
return {"version":{"name":"nginx/"+s.variables.nginx_version,"protocol": 65535},"description":{"text":desc},"players":{"max":1000000,"online":-1},
"favicon": "data:image/png;base64,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",};
}
function memcpy(from,to) {
for(var i=0; i<from.length; i++) {
to.push(from[i]);
}
}
var hout;
var stt;
function handler_out() {
return hout;
}
function makeHandler(desc) {
return function(s) {
(async function(){
var pack = [];
memcpy(makeString(JSON.stringify(wellcome(desc,s))),pack);
pack = makePacket(0,pack);
hout = Buffer.from(new Uint8Array(pack)).toString('base64');
s.error(hout);
s.done();
})().catch(e=>{
s.error(e.stack);
s.deny();
return Promise.reject(e);
});
}
}
var err404 = makeHandler("404 Not Found")
var err503 = makeHandler("503 Bad Gateway")
function ponger(s) {
var mm=mcproto(s);
var read_b = mm.read_b;
var unreg = mm.unreg;
var readVarInt = mm.readVarInt;
var readPacket = mm.readPacket;
var readString = mm.readString;
var readShort = mm.readShort;
(async function() {
await readPacket(); // discard hello;
var pack = await readPacket();
if(pack.type != 1) {
throw "ponger wants a ping request!";
}
var data = await read_b(8,pack);
pack = makePacket(1,data);
hout = Buffer.from(new Uint8Array(pack)).toString('base64');
s.done();
})().catch(e=>{
s.error(e.stack);
unreg();
s.deny();
return Promise.reject(e);
});
}
function disconner(s) {
(async function() {
var pack = makePacket(0,makeString(JSON.stringify({text:"404 Not Found\n---------------\nnginx/"+s.variables.nginx_version})));
hout = Buffer.from(new Uint8Array(pack)).toString('base64');
s.done();
})().catch(e=>{
s.error(e.stack);
unreg();
s.deny();
return Promise.reject(e);
});
}
function unb64(s) {
s.on("downstream",function(b){
s.send(Buffer.from(b.toString(),'base64'));
})
}
function preread(s) {
var mm=mcproto(s);
var read_b = mm.read_b;
var unreg = mm.unreg;
var readVarInt = mm.readVarInt;
var readPacket = mm.readPacket;
var readString = mm.readString;
var readShort = mm.readShort;
(async function() {
//await readVarInt(); // we do not care about packet length somehow
// ^ we do actually
var pack = await readPacket();
if(pack.type != 0) {
throw "not minecraft...";
}
await readVarInt(pack); // we do not care what version this is
where_v = (await readString(pack))
.match(/([^\0]*)\0*/)[1]; // Forge Modloader support
var port = (await readShort(pack));
var nstate = (await readVarInt(pack));
if(nstate != 1) {
stt="disconnect";
} else {
pack = await readPacket();
if(pack.type == 1) {
stt="pinger";
} else if (pack.type == 0) {
stt = "status";
}
}
unreg();
s.error("YES minecraft! "+where_v+" from "+s.variables.remote_addr);
s.done();
})().catch(e=>{
s.error(e.stack);
unreg();
s.deny();
return Promise.reject(e);
});
}
function where() {
return where_v;
}
function status_type() {
return stt;
}
export default { preread, where, err404, err503, disconner, ponger, handler_out, status_type, unb64 };