Skip to content

Commit

Permalink
1.2.0: Switched from Buffer to Uint8Array, changed argument names, mu…
Browse files Browse the repository at this point in the history
…ltiple changes

- ⚙️ Changed `disableSrv` and `disableJSONParse` to `SRVLookup` and `JSONParse` respectively, changing their default values to true.
- ⚙️ Changed all `Buffer`s to `Uint8Array`s, improving compatibility throughout runtimes.
- ⚙️ Bumped the default protocol version from `764` (1.20.2) to `767` (1.21.1)
- 🛠️ Added hard limit on port property
- 🛠️ Changed uncompiled `.js` imports to `.ts`, making it work with Deno.
- 🛠️ Added jsr.json file
- 🛠️ Fixed SRV lookups not being prevented when port wasn't set 25565/was an IP
- ➖ Removed (previously dysfunctional) soft block on localhost addresses when looking up SRV. Code will initiate a SRV lookup with any local address, has to be disabled with `SRVLookup`,
  • Loading branch information
woodendoors7 committed Nov 25, 2024
1 parent 5b9eb5a commit 18b5daa
Show file tree
Hide file tree
Showing 11 changed files with 167 additions and 106 deletions.
16 changes: 16 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: Publish

on:
push:
branches:
- main

jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write # The OIDC ID token is used for authentication with JSR.
steps:
- uses: actions/checkout@v4
- run: npx jsr publish
10 changes: 6 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@

<h2>v1.2.0</h2>

[NPM](https://www.npmjs.com/package/minecraftstatuspinger/v/1.2.0)
<sup>[NPM](https://www.npmjs.com/package/minecraftstatuspinger/v/1.2.0) | [JSR](https://jsr.io/@minecraft/minecraftstatuspinger@1.2.0)</sup>

- ⚙️ Changed `disableSrv` and `disableJSONParse` to `SRVLookup` and `JSONParse` respectively, changing their default values to true.
- ⚙️ Changed all `Buffer`s to `Uint8Array`s, improving compatibility throughout runtimes.
- ⚙️ Bumped the default protocol version from `764` (1.20.2) to `767` (1.21.1)
- 🛠️ Added hard limit on port property
- 🛠️ Changed uncompiled `.js` imports to `.ts`, making it work with Deno.
- 🛠️ Added jsr.json file
- 🛠️ Fixed SRV lookups not being prevented when port wasn't set 25565/was an IP
- ➖ Removed (previously disfunctional) soft block on localhost addresses when looking up SRV. Code will initiate a SRV lookup with any localhost address, unless disabled with `SRVLookup`.
- ➖ Removed (previously dysfunctional) soft block on localhost addresses when looking up SRV. Code will initiate a SRV lookup with any local address, has to be disabled with `SRVLookup`.

<h2>v1.1.5</h2>

[NPM](https://www.npmjs.com/package/minecraftstatuspinger/v/1.1.5)
<sup>[NPM](https://www.npmjs.com/package/minecraftstatuspinger/v/1.1.5) | [JSR](https://jsr.io/@minecraft/minecraftstatuspinger@1.1.5)</sup>

- 🛠️ Fixed latency being returned as `null` instead of zero.

Expand Down Expand Up @@ -53,4 +55,4 @@
- 🟢 Added lookup option `disableJSONParse` to completely skip parsing JSON.
- ⚙️ Renamed primary lookup option `hostname` to `host`, `hostname` stays as an alias.

[all versions](https://www.npmjs.com/package/minecraftstatuspinger?activeTab=versions)
All versions: [NPM](https://www.npmjs.com/package/minecraftstatuspinger?activeTab=versions) | [JSR](https://jsr.io/@minecraft/minecraftstatuspinger/versions)
26 changes: 19 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
[![GitHub Link badge](https://badgen.net/badge/icon/GitHub?icon=github&label&color=010409)](https://github.com/woodendoors7/minecraftstatuspinger)
[![NPM link badge](https://badgen.net/badge/icon/NPM?icon=JS&label&color=a00a0b)](https://www.npmjs.com/package/minecraftstatuspinger)
[![JSR link badge](https://badgen.net/badge/color/JSR/?label=&color=d2a404)](https://jsr.io/@minecraft/minecraftstatuspinger)
[![Web link badge](https://badgen.net/badge/icon/Web?icon=JS&label)](https://pinger.floppa.hair)






<div align="center">
Expand All @@ -7,6 +15,13 @@

<hr>


![NPM Version](https://badgen.net/npm/v/minecraftstatuspinger)
![TS Types](https://badgen.net/npm/types/minecraftstatuspinger)
![License](https://badgen.net/npm/license/minecraftstatuspinger)
![NPM Downloads](https://badgen.net/npm/dy/minecraftstatuspinger/?color=00a600)
![Maintained?](https://badgen.net/static/Maintained%3F/Yes/00a600)

### What can this be used for?

- Getting server **Latency (ping)**
Expand Down Expand Up @@ -34,8 +49,6 @@ let result = await mc.lookup({ host: "mc.hypixel.net" })
console.log(result);
```



<details>
<summary><h3>Advanced Example</h3></summary>
<br>
Expand All @@ -47,7 +60,7 @@ let result = await mc.lookup({
host: "mc.hypixel.net",
port: 25565,
ping: true,
protocolVersion: 764,
protocolVersion: 767,
timeout: 10000,
throwOnParseError: true,
SRVLookup: true,
Expand All @@ -57,7 +70,6 @@ let result = await mc.lookup({
console.log(result);
```


</details>

## Docs
Expand All @@ -74,8 +86,8 @@ console.log(result);
> How long until an error is thrown if the transaction still hasn't finished. Default is 10 seconds.
* <b>`ping?:`</b> boolean <i>`default: true`</i>
> Whether to send a payload at the end to measure the server latency. If false, the `latency` field will be null.
* <b>`protocolVersion?:`</b> number <i>`default: 764`</i>
> Protocol version to send to the server to simulate different Minecraft client versions. Here, you can see the [Protocol Version Numbers](https://wiki.vg/Protocol_version_numbers). The current default protocol version is for 1.20.2 (764) and will be irregularly updated to newer versions.
* <b>`protocolVersion?:`</b> number <i>`default: 767`</i>
> Protocol version to send to the server to simulate different Minecraft client versions. Here, you can see the [Protocol Version Numbers](https://wiki.vg/Protocol_version_numbers). The current default protocol version is for 1.21.1 (767) and will be irregularly updated to newer versions.
* <b>`throwOnParseError?:`</b> boolean <i>`default: true`</i>
> Whether to throw an error if the status packet fails to parse the status field. The `statusRaw` field is always included.
* <b>`SRVLookup?:`</b> boolean <i>`default: true`</i>
Expand Down Expand Up @@ -109,7 +121,7 @@ console.log(result);
### Changelog

**[View Changelog](https://pinger.floppa.hair/changelog/)**,
Latest version: <b><i><code>v1.1.5</code></i></b>
Latest version: <b><i><code>v1.2.0</code></i></b>



Expand Down
5 changes: 0 additions & 5 deletions deno.json

This file was deleted.

3 changes: 2 additions & 1 deletion jsr.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"name": "@minecraft/minecraftstatuspinger",
"version": "1.2.0",
"exports": "./src/index.ts"
"exports": "./src/index.ts",
"compilerOptions":{"strictNullChecks": false}
}
51 changes: 0 additions & 51 deletions src/better-varint.ts

This file was deleted.

11 changes: 8 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,37 +28,42 @@ async function lookup(options?: ServerStatusOptions): Promise<ServerStatus> {
return new Promise<ServerStatus>(async (resolve, reject) => {

let hostname = options.host || options.hostname;
if (!hostname) return reject(new Error("No hostname was provided!"))
if (!hostname) return reject(new Error("No hostname was provided!"));

let port = options.port != null ? options.port : 25565;
if(port < 0 || port > 65535) return reject(new Error("Port number must be between 0 and 25565!"));

let timeout = options.timeout != null ? options.timeout : 10000;
let ping = options.ping != null ? options.ping : true;
let protocolVersion = options.protocolVersion != null ? options.protocolVersion : 767;
let throwOnParseError = options.throwOnParseError != null ? options.throwOnParseError : true;
let SRVLookup = options.SRVLookup != null ? options.SRVLookup : true;
let JSONParse = options.JSONParse != null ? options.JSONParse : true;
console.log(port)
if (SRVLookup) ({ hostname, port } = await processSRV(hostname, port))
// Default port of 25565, default timeout of 10 seconds.
// Ping is sent by default.

let portal = net.createConnection({ port: port, host: hostname, lookup: customLookup }, async () => {
// Send first the handshake, and then the status request to the server.
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) => {
portal.on("data", async (_chunk) => {

/*
Pass every new chunk of data sent from the server into the pipeline,
and also pass the packet object in, which holds the current state of the request.
The pipeline returns the packet object, with changes made from processing the data chunk.
*/

let chunk = new Uint8Array(<any>_chunk);
packet = await packetDec.packetPipeline(chunk, packet)
if (packet.Error) {
clearTimeout(timeoutFunc)
Expand Down
10 changes: 5 additions & 5 deletions src/packetDecoder.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import varint from "./better-varint.ts"
import varint from "./utils-varint.ts"
import { Packet } from "./types.ts";


async function packetPipeline(chunk: Buffer, packet: Packet) {
async function packetPipeline(chunk: Uint8Array, packet: Packet) {
// Wait for and Collect all the data coming from the server.
if (packet.status.pingSent) return await craftLatency(packet);

packet.dataBuffer = await Buffer.concat([
packet.dataBuffer = await varint.concatUI8([
packet.dataBuffer,
chunk
])

if (Buffer.byteLength(packet.dataBuffer) > 102400) {
if (packet.dataBuffer.length > 102400) {
packet.Error = new Error("Maximum buffer size of 100 Kilobytes reached.\nThe status packet should be smaller than 20 Kilobytes.")
return packet;
}
Expand Down Expand Up @@ -41,7 +41,7 @@ async function craftData(packet: 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.crafted.data = new TextDecoder().decode(packet.fieldsBuffer);
packet.status.handshakeBaked = true;
return packet;
}
Expand Down
49 changes: 21 additions & 28 deletions src/packetGenerator.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,38 @@
import varint from "./better-varint.ts"
import varint from "./utils-varint.ts"


async function craftHandshake(hostname: String, port: number, protocolVersion: number) {
async function craftHandshake(hostname: string, port: number, protocolVersion: number) {
let packetBody = await craftHandshakeBody(hostname, port, protocolVersion);

// Field 1: Length of the entire object, (VarInt)
// Field 2: PacketID, (VarInt)
// Field 3: The body of the request
const packetID = 0;

let packetLengthBuffer = Buffer.from(varint.encode(varint.encodingLength(packetID) + packetBody.length));
let packetIDBuffer = Buffer.from(varint.encode(packetID));
let packetLengthBuffer = varint.encode(varint.encodingLength(packetID) + packetBody.length);
let packetIDBuffer = varint.encode(packetID);

let craftedHandshake = Buffer.concat([
let craftedHandshake = varint.concatUI8([
packetLengthBuffer,
packetIDBuffer,
packetBody,
packetBody
])

return craftedHandshake
}

async function craftHandshakeBody(hostname: String, port: number, protocolVersion: number) {
async function craftHandshakeBody(hostname: string, port: number, protocolVersion: number) {
// Field 1: The Protocol Version, (VarInt)
// Field 2: The hostname of the server, (String) prefixed with it's length (VarInt)
// Field 3: The port of the server, (UInt16)
// Field 4: Next expected state, whether to get the status (1) or login (2), (VarInt)
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([
let protocolVersionBuffer = varint.encode(protocolVersion);
let hostnamePrefixBuffer = varint.encode(hostname.length);
let hostnameBuffer = new TextEncoder().encode(hostname);
let portBuffer = varint.craftUInt16BE(port);
let nextStateBuffer = varint.encode(1)

let packetBody = varint.concatUI8([
protocolVersionBuffer,
hostnamePrefixBuffer,
hostnameBuffer,
Expand All @@ -46,10 +45,10 @@ async function craftHandshakeBody(hostname: String, port: number, protocolVersio

async function craftEmptyPacket(packetID: number) {

let packetLengthBuffer = Buffer.from(varint.encode(varint.encodingLength(packetID)));
let packetIDBuffer = Buffer.from(varint.encode(packetID));
let packetLengthBuffer = varint.encode(varint.encodingLength(packetID));
let packetIDBuffer = varint.encode(packetID);

let craftedPacket = Buffer.concat([
let craftedPacket = varint.concatUI8([
packetLengthBuffer,
packetIDBuffer
])
Expand All @@ -66,12 +65,12 @@ async function craftPingPacket() {
// The time of when the ping request was sent is stored in a variable.
const packetID = 1;

let longBuffer = await makeLongBuffer(Date.now())
let longBuffer = varint.craftInt64BE(BigInt(Date.now()));

let packetLengthBuffer = Buffer.from(varint.encode(varint.encodingLength(packetID) + longBuffer.length));
let packetIDBuffer = Buffer.from(varint.encode(packetID));
let packetLengthBuffer = varint.encode(varint.encodingLength(packetID) + longBuffer.length);
let packetIDBuffer = varint.encode(packetID);

let craftedPacket = Buffer.concat([
let craftedPacket = varint.concatUI8([
packetLengthBuffer,
packetIDBuffer,
longBuffer
Expand All @@ -81,11 +80,5 @@ async function craftPingPacket() {
}


async function makeLongBuffer(longNumber: number) {
let buf = Buffer.allocUnsafe(8);
buf.writeBigInt64BE(BigInt(longNumber))

return buf;
}

export default { craftHandshake, craftEmptyPacket, craftPingPacket }
4 changes: 2 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ export class Packet {
fullLength: null,
metaLength: null,
}
dataBuffer = Buffer.alloc(0);
fieldsBuffer = Buffer.alloc(0);
dataBuffer: Uint8Array;
fieldsBuffer: Uint8Array;
crafted: PacketCrafted = {
data: null,
latency: null,
Expand Down
Loading

0 comments on commit 18b5daa

Please sign in to comment.