first cycle lab release
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env node
|
||||
// Small Minecraft status-protocol query, used to verify real network access.
|
||||
import net from 'node:net';
|
||||
const host=process.argv[2],port=Number(process.argv[3]??25565);
|
||||
if(!host||!Number.isInteger(port)||port<1||port>65535){console.error('Usage: node scripts/query-minecraft.mjs HOST [PORT]');process.exit(1);}
|
||||
const encode=value=>{const bytes=[];let number=value>>>0;do{let byte=number&127;number>>>=7;if(number)byte|=128;bytes.push(byte);}while(number);return Buffer.from(bytes);};
|
||||
const read=(buffer,offset=0)=>{let value=0,shift=0;for(let i=offset;i<buffer.length&&i<offset+5;i++){const byte=buffer[i];value|=(byte&127)<<shift;if(!(byte&128))return{value:value>>>0,end:i+1};shift+=7;}return null;};
|
||||
const address=Buffer.from(host),portBytes=Buffer.alloc(2);portBytes.writeUInt16BE(port);
|
||||
const handshake=Buffer.concat([encode(0),encode(-1),encode(address.length),address,portBytes,encode(1)]);
|
||||
const socket=net.createConnection({host,port});let data=Buffer.alloc(0),complete=false;
|
||||
socket.setTimeout(10000,()=>socket.destroy(new Error('Minecraft status timeout')));
|
||||
socket.on('connect',()=>socket.write(Buffer.concat([encode(handshake.length),handshake,Buffer.from([1,0])])));
|
||||
socket.on('data',chunk=>{
|
||||
data=Buffer.concat([data,chunk]);
|
||||
if(data.length>1024*1024){socket.destroy(new Error('Oversized status packet'));return;}
|
||||
const length=read(data);if(!length||data.length<length.end+length.value)return;
|
||||
try{
|
||||
const packet=read(data,length.end);if(!packet||packet.value!==0)throw new Error('Unexpected status packet');
|
||||
const text=read(data,packet.end);if(!text||text.end+text.value!==length.end+length.value)throw new Error('Invalid status JSON length');
|
||||
const status=JSON.parse(data.subarray(text.end,text.end+text.value).toString('utf8'));
|
||||
if(!status.version?.name||!status.players)throw new Error('Invalid Minecraft status response');
|
||||
complete=true;console.log(JSON.stringify({host,port,version:status.version,players:status.players,description:status.description},null,2));socket.end();
|
||||
}catch(error){socket.destroy(error);}
|
||||
});
|
||||
socket.on('error',error=>{console.error(error.message);process.exitCode=1;});
|
||||
socket.on('close',()=>{if(!complete&&!process.exitCode){console.error('Connection closed before Minecraft status');process.exitCode=1;}});
|
||||
Reference in New Issue
Block a user