'use strict'; var net = require('node:net'); var node_dns = require('node:dns'); function _interopNamespaceDefault(e) { var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n.default = e; return Object.freeze(n); } var net__namespace = /*#__PURE__*/_interopNamespaceDefault(net); function encode(num) { const bytes = []; do { let byte = num & 127; num = num >> 7; if (num > 0) { byte |= 128; } bytes.push(byte); } while (num > 0); return Buffer.from(bytes); } function decode(varint, offset = 0) { let result = 0; let shift = 0; for (let i = offset; i < varint.length; i++) { const byte = varint[i]; result |= (byte & 127) << shift; if ((byte & 128) === 0) { break; } shift += 7; } return result; } function encodingLength(num, offset = 0) { let length = offset; do { length++; num = num >> 7; } while (num > 0); return length - offset; } var varint = { encode, decode, encodingLength }; async function craftHandshake(hostname, port, protocolVersion) { let packetBody = await craftHandshakeBody(hostname, port, protocolVersion); const packetID = 0; let packetLengthBuffer = Buffer.from(varint.encode(varint.encodingLength(packetID) + packetBody.length)); let packetIDBuffer = Buffer.from(varint.encode(packetID)); let craftedHandshake = Buffer.concat([ packetLengthBuffer, packetIDBuffer, packetBody ]); return craftedHandshake; } async function craftHandshakeBody(hostname, port, protocolVersion) { let protocolVersionBuffer = Buffer.from(varint.encode(protocolVersion)); let hostnamePrefixBuffer = Buffer.from(varint.encode(hostname.length)); let hostnameBuffer = Buffer.from(hostname, "utf8"); let portBuffer = Buffer.allocUnsafe(2); portBuffer.writeUInt16BE(port, 0); let nextStateBuffer = Buffer.from(varint.encode(1)); let packetBody = Buffer.concat([ protocolVersionBuffer, hostnamePrefixBuffer, hostnameBuffer, portBuffer, nextStateBuffer ]); return packetBody; } async function craftEmptyPacket(packetID) { let packetLengthBuffer = Buffer.from(varint.encode(varint.encodingLength(packetID))); let packetIDBuffer = Buffer.from(varint.encode(packetID)); let craftedPacket = Buffer.concat([ packetLengthBuffer, packetIDBuffer ]); return craftedPacket; } async function craftPingPacket() { const packetID = 1; let longBuffer = await makeLongBuffer(Date.now()); let packetLengthBuffer = Buffer.from(varint.encode(varint.encodingLength(packetID) + longBuffer.length)); let packetIDBuffer = Buffer.from(varint.encode(packetID)); let craftedPacket = Buffer.concat([ packetLengthBuffer, packetIDBuffer, longBuffer ]); return craftedPacket; } async function makeLongBuffer(longNumber) { let buf = Buffer.allocUnsafe(8); buf.writeBigInt64BE(BigInt(longNumber)); return buf; } var packetGen = { craftHandshake, craftEmptyPacket, craftPingPacket }; async function packetPipeline(chunk, packet) { if (packet.status.pingSent) return await craftLatency(packet); packet.dataBuffer = await Buffer.concat([ packet.dataBuffer, chunk ]); if (Buffer.byteLength(packet.dataBuffer) > 102400) { packet.Error = new Error("Maximum buffer size of 100 Kilobytes reached.\nThe status packet should be smaller than 20 Kilobytes."); return packet; } if (!packet.meta.packetInitialized) packet = await craftPacketMeta(packet); if (packet.dataBuffer.length != packet.meta.fullLength) return packet; if (!packet.meta.fieldsCrafted) packet = await craftData(packet); return packet; } async function craftLatency(packet) { packet.crafted.latency = Date.now() - packet.status.pingSentTime; packet.status.pingBaked = true; return packet; } async function craftData(packet) { packet.fieldsBuffer = packet.dataBuffer.slice(packet.meta.metaLength); let fieldLength = varint.decode(packet.fieldsBuffer); packet.fieldsBuffer = packet.fieldsBuffer.slice(varint.encodingLength(fieldLength)); packet.crafted.data = packet.fieldsBuffer.toString(); packet.status.handshakeBaked = true; return packet; } async function craftPacketMeta(packet) { packet.meta.dataLength = varint.decode(packet.dataBuffer); packet.meta.fullLength = varint.encodingLength(packet.meta.dataLength) + packet.meta.dataLength; packet.meta.packetID = varint.decode(packet.dataBuffer, varint.encodingLength(packet.meta.dataLength)); packet.meta.metaLength = varint.encodingLength(packet.meta.dataLength) + varint.encodingLength(packet.meta.packetID); packet.meta.metaCrafted = true; packet.meta.packetInitialized = true; if (packet.meta.dataLength == null || packet.meta.fullLength == null || packet.meta.packetID == null) packet.Error = new Error("Invalid packet was received."); return packet; } var packetDec = { packetPipeline }; class Packet { constructor() { this.status = { handshakeBaked: false, pingSent: false, pingBaked: false, pingSentTime: null }; this.meta = { packetInitialized: false, metaCrafted: false, fieldsCrafted: false, packetID: null, dataLength: null, fullLength: null, metaLength: null }; this.dataBuffer = Buffer.alloc(0); this.fieldsBuffer = Buffer.alloc(0); this.crafted = { data: null, latency: null }; this.Error = null; } } class ServerStatus { constructor(statusRaw, latency, throwOnParseError, disableJSONParse) { if (!disableJSONParse) { try { this.status = JSON.parse(statusRaw); } catch (err) { if (throwOnParseError) throw err; this.status = null; } } else this.status = null; this.statusRaw = statusRaw; if (latency != null) { this.latency = latency; } else this.latency = null; } } async function lookup(options) { return new Promise(async (resolve, reject) => { let hostname = options.host || options.hostname; if (!hostname) return reject(new Error("No hostname was provided!")); let port = options.port != null ? options.port : 25565; let timeout = options.timeout != null ? options.timeout : 1e4; let ping = options.ping != null ? options.ping : true; let protocolVersion = options.protocolVersion != null ? options.protocolVersion : 764; let throwOnParseError = options.throwOnParseError != null ? options.throwOnParseError : true; let disableSRV = options.disableSRV != null ? options.disableSRV : false; let disableJSONParse = options.disableJSONParse != null ? options.disableJSONParse : false; if (!disableSRV) ({ hostname, port } = await processSRV(hostname, port)); let portal = net__namespace.createConnection({ port, host: hostname, lookup: customLookup }, async () => { let handshake = await packetGen.craftHandshake(hostname, port, protocolVersion); let statusRequest = await packetGen.craftEmptyPacket(0); portal.write(handshake); portal.write(statusRequest); }); let packet = new Packet(); portal.on("data", async (chunk) => { packet = await packetDec.packetPipeline(chunk, packet); if (packet.Error) { clearTimeout(timeoutFunc); return reject(packet.Error); } if (packet.status.pingBaked || packet.status.handshakeBaked && !ping) { let serverStatus; try { serverStatus = new ServerStatus(packet.crafted.data, packet.crafted.latency, throwOnParseError, disableJSONParse); } catch (error) { clearTimeout(timeoutFunc); portal.destroy(); return reject(error); } clearTimeout(timeoutFunc); portal.destroy(); return resolve(serverStatus); } if (packet.status.handshakeBaked && !packet.status.pingSent) { let pingRequest = await packetGen.craftPingPacket(); packet.status.pingSentTime = Date.now(); packet.status.pingSent = true; await portal.write(pingRequest); } }); portal.once("error", (netError) => { clearTimeout(timeoutFunc); reject(netError); }); let timeoutFunc = setTimeout(() => { portal.destroy(); reject(new Error("Timed out.")); }, timeout); }); } async function setDnsServers(serverArray) { await node_dns.promises.setServers(serverArray); return true; } async function customLookup(hostname, options, callback) { let result = await node_dns.promises.lookup(hostname, options).catch((e) => { callback(e); }); if (!result) return; if (options?.all) callback(null, result); else callback(null, result.address, result.family); } async function processSRV(hostname, port) { if (hostname == "localhostname" && port != 25565 && net__namespace.isIP(hostname) != 0) return { hostname, port }; let result = await node_dns.promises.resolveSrv("_minecraft._tcp." + hostname).catch(() => { }); if (!result || result.length == 0 || !result[0].name || !result[0].port) return { hostname, port }; return { hostname: result[0].name, port: result[0].port }; } var index = { setDnsServers, lookup }; module.exports = index;