docs: overhaul README and provide new usage examples

The README.md has been completely rewritten. Also the `example`
directory has been renamed to `examples` and its content
has been replaced with a more structured and practical set of scripts.
This commit is contained in:
2025-06-25 13:16:42 +03:00
parent 0bf30140b7
commit 7222eeae3c
7 changed files with 230 additions and 78 deletions

155
README.md
View File

@ -1,8 +1,19 @@
# mineping # mineping
This JavaScript library provides an implementation of the Minecraft server ping protocol. **It allows you to gather information about a Minecraft server**, such as the MOTD, current online players, server icon (Java Edition only), and more. [![npm version](https://img.shields.io/npm/v/@minescope/mineping.svg)](https://www.npmjs.com/package/@minescope/mineping)
Mirror on my [<img src="https://git.zeldon.ru/assets/img/logo.svg" align="center" width="20" height="20"/> Git](https://git.zeldon.ru/zeldon/mineping) A simple and efficient JavaScript library for pinging Minecraft servers. It supports both Java and Bedrock editions through a async/await-friendly API.
`@minescope/mineping` automatically resolves SRV records for Java servers and parses rich status data, including MOTD, player counts, version info, and server icons. Comes with full TypeScript support.
*Mirror on my [<img src="https://git.zeldon.ru/assets/img/logo.svg" align="center" width="20" height="20"/> Git](https://git.zeldon.ru/zeldon/mineping)*
## Features
- **Dual Protocol Support:** Ping both Java and Bedrock servers with a consistent API.
- **SRV Record Resolution:** Automatically resolves SRV records for Java Edition servers, so you don't have to worry about custom ports.
- **Rich Data:** Parses the full response from servers, including player samples, favicons, gamemodes, and more.
- **Lightweight:** Has only **one** runtime dependency — [debug](https://www.npmjs.com/package/debug) (used for tracing).
## Requirements ## Requirements
@ -12,22 +23,56 @@ Mirror on my [<img src="https://git.zeldon.ru/assets/img/logo.svg" align="center
To install `mineping`, simply run the following command: To install `mineping`, simply run the following command:
``` ```bash
npm i @minescope/mineping npm i @minescope/mineping
``` ```
> To install _beta_ version (if available), run: `npm i @minescope/mineping@next` ## API & Usage Examples
The library exports two main functions: `pingJava` and `pingBedrock`. Both are asynchronous and return a `Promise`.
### 1. Basic Server Ping
Java:
```js
import { pingJava } from "@minescope/mineping";
const data = await pingJava("0.0.0.0");
console.log(data)
```
```json
{
version: { name: '1.21.5', protocol: 770 },
enforcesSecureChat: true,
description: 1Welcome to §2My Minecraft Server!',
players: { max: 20, online: 0 }
}
```
Bedrock:
```js
import { pingBedrock } from "@minescope/mineping";
const data = await pingBedrock("0.0.0.0");
console.log(data)
```
```json
{
edition: 'MCPE',
name: 'Dedicated Server',
levelName: 'Bedrock level',
gamemode: 'Survival',
version: { protocol: 800, minecraft: '1.21.84' },
players: { online: 0, max: 10 },
port: { v4: 19132, v6: 19133 },
guid: 12143264093420916401n,
isNintendoLimited: false,
isEditorModeEnabled: false
}
```
## Loading and configuration the module ## Loading and configuration the module
### ES Modules (ESM)
If you are using ES Modules, you can import the library like this:
```js
import { pingJava, pingBedrock } from "@minescope/mineping";
```
### CommonJS ### CommonJS
`mineping` is an ESM-only module — you are not able to import it with `require()`. `mineping` is an ESM-only module — you are not able to import it with `require()`.
@ -40,34 +85,86 @@ const pingBedrock = (...args) =>
import("@minescope/mineping").then((module) => module.pingBedrock(...args)); import("@minescope/mineping").then((module) => module.pingBedrock(...args));
``` ```
## Usage ## Debugging
Ping a Java server with default options: `mineping` uses the [`debug`](https://www.npmjs.com/package/debug) library to provide detailed tracing information, which can be useful for diagnosing connection issues or understanding the library's internal workings.
```js To enable debug logs, set the `DEBUG` environment variable when running your script. The library uses two namespaces:
import { pingJava } from "@minescope/mineping";
const data = await pingJava("mc.hypixel.net"); - `mineping:java` for the Java Edition pinger.
console.log(data); - `mineping:bedrock` for the Bedrock Edition pinger.
### Examples
**Enable all `mineping` debug logs:**
You can use a wildcard (`*`) to enable all logs from this library.
```bash
DEBUG=mineping:* node your-script.js
``` ```
Ping a Bedrock server with custom options: <details>
<summary>Click to see output for <code>DEBUG="mineping:*" node examples/01-basic-ping.js</code></summary>
```js ```bash
import { pingBedrock } from "@minescope/mineping"; DEBUG="mineping:*" node examples/01-basic-ping.js
mineping:java pinging Java server hypixel.net with options: {} +0ms
mineping:java attempting SRV lookup for _minecraft._tcp.hypixel.net with 5000ms timeout +2ms
mineping:java SRV lookup successful, new target: mc.hypixel.net:25565 +2ms
mineping:java creating TCP connection to mc.hypixel.net:25565 +0ms
mineping:java socket connected to mc.hypixel.net:25565, sending packets... +182ms
mineping:java received 1440 bytes of data, total buffer size is now 1440 bytes +130ms
mineping:java packet incomplete, waiting for more data +0ms
mineping:java received 12960 bytes of data, total buffer size is now 14400 bytes +1ms
mineping:java packet incomplete, waiting for more data +0ms
mineping:java received 1601 bytes of data, total buffer size is now 16001 bytes +129ms
mineping:java received raw JSON response +0ms
mineping:java successfully parsed full response +0ms
mineping:java cleaning up resources for mc.hypixel.net:25565 +0ms
--- Java Server ---
{
version: { name: 'Requires MC 1.8 / 1.21', protocol: 47 },
players: { max: 200000, online: 28654, sample: [] },
description: ' §aHypixel Network §c[1.8-1.21]\n' +
' §6§lSB 0.23 §2§lFORAGING §8§l- §e§lSUMMER EVENT',
favicon: 'data:image/png;base64,iVBORw0K'... 5738 more characters
}
const data = await pingBedrock("mco.mineplex.com", { ====================
port: 19132,
timeout: 500, mineping:bedrock pinging Bedrock server geo.hivebedrock.network:19132 with 5000ms timeout +0ms
}); mineping:bedrock sending Unconnected Ping packet to geo.hivebedrock.network:19132 +1ms
console.log(data); mineping:bedrock packet: <Buffer 01 c0 01 00 00 00 00 00 00 00 ff ff 00 fe fe fe fe fd fd fd fd 12 34 56 78 19 20 9f 00 e6 ed ef 96> +0ms
mineping:bedrock received 124 bytes from geo.hivebedrock.network:19132 +104ms
mineping:bedrock received raw MOTD string: MCPE;BEDWARS + BUILD BATTLE;121;1.0;13074;100001;-4669279440237021648;Hive Games;Survival +0ms
mineping:bedrock cleaning up resources for geo.hivebedrock.network:19132 +0ms
--- Bedrock Server ---
{
edition: 'MCPE',
name: 'BEDWARS + BUILD BATTLE',
levelName: 'Hive Games',
gamemode: 'Survival',
version: { protocol: 121, minecraft: '1.0' },
players: { online: 13074, max: 100001 },
port: { v4: undefined, v6: undefined },
guid: -4669279440237021648n,
isNintendoLimited: undefined,
isEditorModeEnabled: undefined
}
``` ```
</details>
> More complex example can be found in the `example` folder! **_PowerShell_ uses different syntax to set environment variables:**
```powershell
$env:DEBUG="mineping:*";node your-script.js
```
## Acknowledgements ## Acknowledgements
Special thanks to the following projects: Special thanks to the following projects for inspiration and protocol details:
- [mcping](https://github.com/Scetch/mcping) crate for Rust - [mcping](https://github.com/Scetch/mcping) crate for Rust
- [mcping-js](https://github.com/Cryptkeeper/mcping-js) library for quering Minecraft Java Edition servers - [mcping-js](https://github.com/Cryptkeeper/mcping-js) library for querying Minecraft Java Edition servers
- The amazing community at [minecraft.wiki](https://minecraft.wiki/) for documenting the protocols.

View File

@ -1,20 +0,0 @@
import { pingBedrock } from '../index.js';
const hosts = [
'play.timecrack.net',
'geo.hivebedrock.network',
'oasys-pe.com',
'play.galaxite.net',
];
const pingPromises = hosts.map(host => pingBedrock(host));
const results = await Promise.allSettled(pingPromises);
for (let result of results) {
if (result.status === 'rejected') {
console.error(result.reason);
break;
}
console.log(result.value);
}

View File

@ -1,5 +0,0 @@
import { pingBedrock } from "../index.js";
const host = "0.0.0.0";
const motd = await pingBedrock(host);
console.log(motd);

19
examples/01-basic-ping.js Normal file
View File

@ -0,0 +1,19 @@
import { pingJava, pingBedrock } from "../index.js";
try {
const javaData = await pingJava("hypixel.net");
console.log("--- Java Server ---");
console.log(javaData);
} catch (error) {
console.error("Could not ping Java server:", error);
}
console.log("\n" + "=".repeat(20) + "\n");
try {
const motd = await pingBedrock("geo.hivebedrock.network");
console.log("--- Bedrock Server ---");
console.log(motd);
} catch (error) {
console.error("Could not ping Bedrock server:", error);
}

View File

@ -0,0 +1,14 @@
import { pingJava } from "../index.js";
const offlineServer = "this.server.does.not.exist";
const port = 12345;
console.log(`Pinging an offline server: ${offlineServer}:${port}`);
try {
// We set a short timeout to fail faster.
const data = await pingJava(offlineServer, { port, timeout: 500 });
console.log("Success!?", data);
} catch (error) {
console.error("Caught expected error:", error.message);
}

View File

@ -0,0 +1,47 @@
import { pingJava, pingBedrock } from "../index.js";
const servers = [
{ type: "Java", host: "mc.hypixel.net" },
{ type: "Java", host: "play.cubecraft.net" },
{ type: "Java", host: "an-offline-java-server.com" },
{ type: "Bedrock", host: "geo.hivebedrock.network" },
{ type: "Bedrock", host: "buzz.insanitycraft.net" },
{ type: "Bedrock", host: "an.offline.bedrock.server" },
];
console.log("Pinging all servers...");
// Create an array of ping promises
const pingPromises = servers.map((server) => {
if (server.type === "Java") {
return pingJava(server.host, { timeout: 3000 });
} else {
return pingBedrock(server.host, { timeout: 3000 });
}
});
// Wait for all pings to complete (or fail)
const results = await Promise.allSettled(pingPromises);
// Process and display results
const displayData = results.map((result, index) => {
const server = servers[index];
if (result.status === "fulfilled") {
const data = result.value;
return {
Server: `${server.type} - ${server.host}`,
Status: "✅ Online",
Players: `${data.players.online} / ${data.players.max}`,
Version: data.version.name ?? data.version.minecraft,
};
} else {
return {
Server: `${server.type} - ${server.host}`,
Status: "❌ Offline",
Players: "N/A",
Version: `Error: ${result.reason.message.slice(0, 30)}...`,
};
}
});
console.table(displayData);

View File

@ -86,31 +86,31 @@ function shouldShowHelp(args) {
function printHelp() { function printHelp() {
console.log(`node cli.js [..] console.log(`node cli.js [..]
A simple to use, efficient, and full-featured Minecraft server info parser! A simple to use, efficient, and full-featured Minecraft server info parser!
USAGE: USAGE:
node cli.js [OPTIONS] --host <HOST> --port <PORT> --timeout <TIMEOUT> node cli.js [OPTIONS] --host <HOST> --port <PORT> --timeout <TIMEOUT>
OPTIONS: OPTIONS:
-j Use for Minecraft Java Edition -j Use for Minecraft Java Edition
-b Use for Minecraft Bedrock Edition -b Use for Minecraft Bedrock Edition
-h, --help Show this help message -h, --help Show this help message
--host The server address (required) --host The server address (required)
--port The server port (default: ${JAVA_DEFAULT_PORT} for Java, ${BEDROCK_DEFAULT_PORT} for Bedrock) --port The server port (default: ${JAVA_DEFAULT_PORT} for Java, ${BEDROCK_DEFAULT_PORT} for Bedrock)
--timeout The socket timeout in milliseconds (default: ${DEFAULT_TIMEOUT}) --timeout The socket timeout in milliseconds (default: ${DEFAULT_TIMEOUT})
P.S. Don't use -j and -b at the same time!`); P.S. Don't use -j and -b at the same time!`);
} }
function printInterestingFacts() { function printInterestingFacts() {
console.log(`Some interesting facts about MOTDs on bedrock: console.log(`Some interesting facts about MOTDs on bedrock:
- so far they seem to exclusively use legacy color codes - so far they seem to exclusively use legacy color codes
- the random style has a special impl for periods, they turn into animated - the random style has a special impl for periods, they turn into animated
colons that warp up and down rapidly colons that warp up and down rapidly
- motd_2 is ignored? client displays "motd_1 - v{version}", where the - motd_2 is ignored? client displays "motd_1 - v{version}", where the
appended version text is considered part of motd_1 for color code processing appended version text is considered part of motd_1 for color code processing
- motd_2 seems to mainly be used to return the server software in use (e.g. PocketMine-MP)`); - motd_2 seems to mainly be used to return the server software in use (e.g. PocketMine-MP)`);
} }
function getDefaultPort(args) { function getDefaultPort(args) {
@ -120,7 +120,7 @@ function getDefaultPort(args) {
async function pingJavaServer(host, port, timeout) { async function pingJavaServer(host, port, timeout) {
const data = await pingJava(host, { port, timeout }); const data = await pingJava(host, { port, timeout });
console.log(`Host: ${host} console.log(`Host: ${host}
Version: ${data.version?.name} (protocol: ${data.version?.protocol}) Version: ${data.version.name} (protocol: ${data.version.protocol})
Players: ${data.players?.online}/${data.players?.max} Players: ${data.players?.online}/${data.players?.max}
Description: ${ Description: ${
typeof data.description === "string" typeof data.description === "string"
@ -133,8 +133,8 @@ async function pingBedrockServer(host, port, timeout) {
const data = await pingBedrock(host, { port, timeout }); const data = await pingBedrock(host, { port, timeout });
console.log(`Host: ${host} console.log(`Host: ${host}
Edition: ${data.edition} Edition: ${data.edition}
Version: ${data.version.minecraftVersion} (protocol: ${data.version.protocolVersion}) Version: ${data.version.minecraft} (protocol: ${data.version.protocol})
Players: ${data.players.online}/${data.players.max} Players: ${data.players.online}/${data.players.max}
Name: ${data.name} Name: ${data.name}
Gamemode: ${data.gameMode}`); Gamemode: ${data.gamemode}`);
} }