@hytaleone/query 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 HytaleOne
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # @hytaleone/query
2
+
3
+ Query Hytale servers using the UDP query protocol.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @hytaleone/query
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import { query } from '@hytaleone/query';
15
+
16
+ // Basic query
17
+ const info = await query('play.example.com', 5520);
18
+ console.log(`${info.serverName}: ${info.currentPlayers}/${info.maxPlayers}`);
19
+
20
+ // Full query - includes players and plugins
21
+ const full = await query('play.example.com', 5520, { full: true });
22
+ console.log('Players:', full.players.map(p => p.name).join(', '));
23
+ console.log('Plugins:', full.plugins.map(p => p.id).join(', '));
24
+ ```
25
+
26
+ ## API
27
+
28
+ ### query(host, port?, options?)
29
+
30
+ Query a server for information.
31
+
32
+ ```typescript
33
+ const info = await query('localhost', 5520, {
34
+ timeout: 5000,
35
+ full: true
36
+ });
37
+ ```
38
+
39
+ **Options:**
40
+ - `timeout` - Query timeout in milliseconds (default: 5000)
41
+ - `full` - Include players and plugins (default: false)
42
+
43
+ **Returns `ServerInfo`:**
44
+ - `serverName` - Server display name
45
+ - `motd` - Message of the day
46
+ - `currentPlayers` - Current player count
47
+ - `maxPlayers` - Maximum player capacity
48
+ - `hostPort` - Server port
49
+ - `version` - Server version
50
+ - `protocolVersion` - Protocol version number
51
+ - `protocolHash` - Protocol hash
52
+
53
+ **With `full: true`, also returns:**
54
+ - `players` - Array of `{ name, uuid }`
55
+ - `plugins` - Array of `{ id, version, enabled }`
56
+
57
+ ## Requirements
58
+
59
+ - Node.js >= 18
60
+ - Server must have the [HytaleOne Query Plugin](https://github.com/hytaleone/hytale-one-query-plugin) installed
61
+
62
+ ## License
63
+
64
+ MIT
65
+
66
+ ---
67
+
68
+ **[hytale.one](https://hytale.one/)** - Discover Hytale Servers
package/dist/index.cjs ADDED
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ query: () => query
34
+ });
35
+ module.exports = __toCommonJS(index_exports);
36
+
37
+ // src/query.ts
38
+ var import_node_dgram = __toESM(require("dgram"), 1);
39
+
40
+ // src/protocol.ts
41
+ var REQUEST_MAGIC = Buffer.from("HYQUERY\0", "ascii");
42
+ var RESPONSE_MAGIC = Buffer.from("HYREPLY\0", "ascii");
43
+ var TYPE_BASIC = 0;
44
+ var TYPE_FULL = 1;
45
+ function buildRequest(type) {
46
+ const buf = Buffer.alloc(REQUEST_MAGIC.length + 1);
47
+ REQUEST_MAGIC.copy(buf, 0);
48
+ buf[REQUEST_MAGIC.length] = type;
49
+ return buf;
50
+ }
51
+ var BufferReader = class {
52
+ constructor(buf) {
53
+ this.buf = buf;
54
+ }
55
+ offset = 0;
56
+ readBytes(length) {
57
+ const slice = this.buf.subarray(this.offset, this.offset + length);
58
+ this.offset += length;
59
+ return slice;
60
+ }
61
+ readUInt16LE() {
62
+ const value = this.buf.readUInt16LE(this.offset);
63
+ this.offset += 2;
64
+ return value;
65
+ }
66
+ readInt32LE() {
67
+ const value = this.buf.readInt32LE(this.offset);
68
+ this.offset += 4;
69
+ return value;
70
+ }
71
+ readBigInt64BE() {
72
+ const value = this.buf.readBigInt64BE(this.offset);
73
+ this.offset += 8;
74
+ return value;
75
+ }
76
+ readBoolean() {
77
+ return this.buf[this.offset++] !== 0;
78
+ }
79
+ readString() {
80
+ const length = this.readUInt16LE();
81
+ const bytes = this.readBytes(length);
82
+ return bytes.toString("utf8");
83
+ }
84
+ readUUID() {
85
+ const msb = this.readBigInt64BE();
86
+ const lsb = this.readBigInt64BE();
87
+ return formatUUID(msb, lsb);
88
+ }
89
+ get remaining() {
90
+ return this.buf.length - this.offset;
91
+ }
92
+ };
93
+ function formatUUID(msb, lsb) {
94
+ const toHex = (n) => {
95
+ if (n < 0n) {
96
+ n = BigInt.asUintN(64, n);
97
+ }
98
+ return n.toString(16).padStart(16, "0");
99
+ };
100
+ const hex = toHex(msb) + toHex(lsb);
101
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
102
+ }
103
+ function validateResponse(buf) {
104
+ if (buf.length < RESPONSE_MAGIC.length + 1) {
105
+ return false;
106
+ }
107
+ return buf.subarray(0, RESPONSE_MAGIC.length).equals(RESPONSE_MAGIC);
108
+ }
109
+ function parseBasicResponse(buf) {
110
+ if (!validateResponse(buf)) {
111
+ throw new Error("Invalid response: magic mismatch");
112
+ }
113
+ const reader = new BufferReader(buf);
114
+ reader.readBytes(RESPONSE_MAGIC.length);
115
+ reader.readBytes(1);
116
+ return {
117
+ serverName: reader.readString(),
118
+ motd: reader.readString(),
119
+ currentPlayers: reader.readInt32LE(),
120
+ maxPlayers: reader.readInt32LE(),
121
+ hostPort: reader.readUInt16LE(),
122
+ version: reader.readString(),
123
+ protocolVersion: reader.readInt32LE(),
124
+ protocolHash: reader.readString()
125
+ };
126
+ }
127
+ function parseFullResponse(buf) {
128
+ if (!validateResponse(buf)) {
129
+ throw new Error("Invalid response: magic mismatch");
130
+ }
131
+ const reader = new BufferReader(buf);
132
+ reader.readBytes(RESPONSE_MAGIC.length);
133
+ reader.readBytes(1);
134
+ const serverName = reader.readString();
135
+ const motd = reader.readString();
136
+ const currentPlayers = reader.readInt32LE();
137
+ const maxPlayers = reader.readInt32LE();
138
+ const hostPort = reader.readUInt16LE();
139
+ const version = reader.readString();
140
+ const protocolVersion = reader.readInt32LE();
141
+ const protocolHash = reader.readString();
142
+ const playerCount = reader.readInt32LE();
143
+ const players = [];
144
+ for (let i = 0; i < playerCount; i++) {
145
+ players.push({
146
+ name: reader.readString(),
147
+ uuid: reader.readUUID()
148
+ });
149
+ }
150
+ const pluginCount = reader.readInt32LE();
151
+ const plugins = [];
152
+ for (let i = 0; i < pluginCount; i++) {
153
+ plugins.push({
154
+ id: reader.readString(),
155
+ version: reader.readString(),
156
+ enabled: reader.readBoolean()
157
+ });
158
+ }
159
+ return {
160
+ serverName,
161
+ motd,
162
+ currentPlayers,
163
+ maxPlayers,
164
+ hostPort,
165
+ version,
166
+ protocolVersion,
167
+ protocolHash,
168
+ players,
169
+ plugins
170
+ };
171
+ }
172
+
173
+ // src/query.ts
174
+ var DEFAULT_TIMEOUT = 5e3;
175
+ function sendQuery(host, port, type, timeout) {
176
+ return new Promise((resolve, reject) => {
177
+ const socket = import_node_dgram.default.createSocket("udp4");
178
+ let timeoutHandle;
179
+ const cleanup = () => {
180
+ clearTimeout(timeoutHandle);
181
+ socket.close();
182
+ };
183
+ socket.on("message", (msg) => {
184
+ cleanup();
185
+ resolve(msg);
186
+ });
187
+ socket.on("error", (err) => {
188
+ cleanup();
189
+ reject(err);
190
+ });
191
+ timeoutHandle = setTimeout(() => {
192
+ cleanup();
193
+ reject(new Error(`Query timeout after ${timeout}ms`));
194
+ }, timeout);
195
+ const request = buildRequest(type);
196
+ socket.send(request, port, host, (err) => {
197
+ if (err) {
198
+ cleanup();
199
+ reject(err);
200
+ }
201
+ });
202
+ });
203
+ }
204
+ async function query(host, port = 5520, options = {}) {
205
+ const timeout = options.timeout ?? DEFAULT_TIMEOUT;
206
+ const type = options.full ? TYPE_FULL : TYPE_BASIC;
207
+ const response = await sendQuery(host, port, type, timeout);
208
+ if (options.full) {
209
+ return parseFullResponse(response);
210
+ }
211
+ return parseBasicResponse(response);
212
+ }
213
+ // Annotate the CommonJS export names for ESM import in node:
214
+ 0 && (module.exports = {
215
+ query
216
+ });
217
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/query.ts","../src/protocol.ts"],"sourcesContent":["export { query } from './query.js';\nexport type {\n ServerInfo,\n ServerInfoFull,\n Player,\n Plugin,\n QueryOptions,\n} from './types.js';\n","import dgram from 'node:dgram';\nimport {\n buildRequest,\n parseBasicResponse,\n parseFullResponse,\n TYPE_BASIC,\n TYPE_FULL,\n} from './protocol.js';\nimport type { QueryOptions, ServerInfo, ServerInfoFull } from './types.js';\n\nconst DEFAULT_TIMEOUT = 5000;\n\n/**\n * Send a UDP query and wait for response.\n */\nfunction sendQuery(\n host: string,\n port: number,\n type: number,\n timeout: number\n): Promise<Buffer> {\n return new Promise((resolve, reject) => {\n const socket = dgram.createSocket('udp4');\n let timeoutHandle: NodeJS.Timeout;\n\n const cleanup = () => {\n clearTimeout(timeoutHandle);\n socket.close();\n };\n\n socket.on('message', (msg) => {\n cleanup();\n resolve(msg);\n });\n\n socket.on('error', (err) => {\n cleanup();\n reject(err);\n });\n\n timeoutHandle = setTimeout(() => {\n cleanup();\n reject(new Error(`Query timeout after ${timeout}ms`));\n }, timeout);\n\n const request = buildRequest(type);\n socket.send(request, port, host, (err) => {\n if (err) {\n cleanup();\n reject(err);\n }\n });\n });\n}\n\n/**\n * Query a Hytale server for information.\n *\n * @param host - Server hostname or IP address\n * @param port - Server port (default: 5520)\n * @param options - Query options\n * @returns Server information (full if options.full is true)\n *\n * @example\n * ```typescript\n * // Basic query\n * const info = await query('play.example.com', 5520);\n * console.log(`${info.serverName}: ${info.currentPlayers}/${info.maxPlayers}`);\n *\n * // Full query (includes players + plugins)\n * const full = await query('play.example.com', 5520, { full: true });\n * console.log('Players:', full.players.map(p => p.name).join(', '));\n * ```\n */\nexport async function query(\n host: string,\n port?: number,\n options?: QueryOptions & { full?: false }\n): Promise<ServerInfo>;\nexport async function query(\n host: string,\n port: number,\n options: QueryOptions & { full: true }\n): Promise<ServerInfoFull>;\nexport async function query(\n host: string,\n port = 5520,\n options: QueryOptions & { full?: boolean } = {}\n): Promise<ServerInfo | ServerInfoFull> {\n const timeout = options.timeout ?? DEFAULT_TIMEOUT;\n const type = options.full ? TYPE_FULL : TYPE_BASIC;\n const response = await sendQuery(host, port, type, timeout);\n\n if (options.full) {\n return parseFullResponse(response);\n }\n return parseBasicResponse(response);\n}\n","import type { Player, Plugin, ServerInfo, ServerInfoFull } from './types.js';\n\n// Protocol constants\nexport const REQUEST_MAGIC = Buffer.from('HYQUERY\\0', 'ascii');\nexport const RESPONSE_MAGIC = Buffer.from('HYREPLY\\0', 'ascii');\nexport const TYPE_BASIC = 0x00;\nexport const TYPE_FULL = 0x01;\n\n/**\n * Build a query request packet.\n */\nexport function buildRequest(type: number): Buffer {\n const buf = Buffer.alloc(REQUEST_MAGIC.length + 1);\n REQUEST_MAGIC.copy(buf, 0);\n buf[REQUEST_MAGIC.length] = type;\n return buf;\n}\n\n/**\n * Buffer reader helper for parsing responses.\n */\nclass BufferReader {\n private offset = 0;\n\n constructor(private buf: Buffer) {}\n\n readBytes(length: number): Buffer {\n const slice = this.buf.subarray(this.offset, this.offset + length);\n this.offset += length;\n return slice;\n }\n\n readUInt16LE(): number {\n const value = this.buf.readUInt16LE(this.offset);\n this.offset += 2;\n return value;\n }\n\n readInt32LE(): number {\n const value = this.buf.readInt32LE(this.offset);\n this.offset += 4;\n return value;\n }\n\n readBigInt64BE(): bigint {\n const value = this.buf.readBigInt64BE(this.offset);\n this.offset += 8;\n return value;\n }\n\n readBoolean(): boolean {\n return this.buf[this.offset++] !== 0;\n }\n\n readString(): string {\n const length = this.readUInt16LE();\n const bytes = this.readBytes(length);\n return bytes.toString('utf8');\n }\n\n readUUID(): string {\n const msb = this.readBigInt64BE();\n const lsb = this.readBigInt64BE();\n return formatUUID(msb, lsb);\n }\n\n get remaining(): number {\n return this.buf.length - this.offset;\n }\n}\n\n/**\n * Format UUID from most/least significant bits.\n */\nfunction formatUUID(msb: bigint, lsb: bigint): string {\n const toHex = (n: bigint): string => {\n if (n < 0n) {\n n = BigInt.asUintN(64, n);\n }\n return n.toString(16).padStart(16, '0');\n };\n\n const hex = toHex(msb) + toHex(lsb);\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n\n/**\n * Validate response magic bytes.\n */\nexport function validateResponse(buf: Buffer): boolean {\n if (buf.length < RESPONSE_MAGIC.length + 1) {\n return false;\n }\n return buf.subarray(0, RESPONSE_MAGIC.length).equals(RESPONSE_MAGIC);\n}\n\n/**\n * Parse a basic query response.\n */\nexport function parseBasicResponse(buf: Buffer): ServerInfo {\n if (!validateResponse(buf)) {\n throw new Error('Invalid response: magic mismatch');\n }\n\n const reader = new BufferReader(buf);\n\n // Skip magic\n reader.readBytes(RESPONSE_MAGIC.length);\n\n // Skip type\n reader.readBytes(1);\n\n return {\n serverName: reader.readString(),\n motd: reader.readString(),\n currentPlayers: reader.readInt32LE(),\n maxPlayers: reader.readInt32LE(),\n hostPort: reader.readUInt16LE(),\n version: reader.readString(),\n protocolVersion: reader.readInt32LE(),\n protocolHash: reader.readString(),\n };\n}\n\n/**\n * Parse a full query response.\n */\nexport function parseFullResponse(buf: Buffer): ServerInfoFull {\n if (!validateResponse(buf)) {\n throw new Error('Invalid response: magic mismatch');\n }\n\n const reader = new BufferReader(buf);\n\n // Skip magic\n reader.readBytes(RESPONSE_MAGIC.length);\n\n // Skip type\n reader.readBytes(1);\n\n // Base info\n const serverName = reader.readString();\n const motd = reader.readString();\n const currentPlayers = reader.readInt32LE();\n const maxPlayers = reader.readInt32LE();\n const hostPort = reader.readUInt16LE();\n const version = reader.readString();\n const protocolVersion = reader.readInt32LE();\n const protocolHash = reader.readString();\n\n // Player list\n const playerCount = reader.readInt32LE();\n const players: Player[] = [];\n for (let i = 0; i < playerCount; i++) {\n players.push({\n name: reader.readString(),\n uuid: reader.readUUID(),\n });\n }\n\n // Plugin list\n const pluginCount = reader.readInt32LE();\n const plugins: Plugin[] = [];\n for (let i = 0; i < pluginCount; i++) {\n plugins.push({\n id: reader.readString(),\n version: reader.readString(),\n enabled: reader.readBoolean(),\n });\n }\n\n return {\n serverName,\n motd,\n currentPlayers,\n maxPlayers,\n hostPort,\n version,\n protocolVersion,\n protocolHash,\n players,\n plugins,\n };\n}\n"],"mappings":"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","names":["dgram"]}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Basic server information returned by a basic query.
3
+ */
4
+ interface ServerInfo {
5
+ /** Server display name */
6
+ serverName: string;
7
+ /** Message of the day */
8
+ motd: string;
9
+ /** Current number of players online */
10
+ currentPlayers: number;
11
+ /** Maximum player capacity */
12
+ maxPlayers: number;
13
+ /** Server port */
14
+ hostPort: number;
15
+ /** Server version string */
16
+ version: string;
17
+ /** Protocol version number */
18
+ protocolVersion: number;
19
+ /** Protocol hash string */
20
+ protocolHash: string;
21
+ }
22
+ /**
23
+ * Player information included in full query response.
24
+ */
25
+ interface Player {
26
+ /** Player username */
27
+ name: string;
28
+ /** Player UUID in standard format */
29
+ uuid: string;
30
+ }
31
+ /**
32
+ * Plugin information included in full query response.
33
+ */
34
+ interface Plugin {
35
+ /** Plugin identifier (e.g. "HytaleOne:Query") */
36
+ id: string;
37
+ /** Plugin version string */
38
+ version: string;
39
+ /** Whether the plugin is enabled */
40
+ enabled: boolean;
41
+ }
42
+ /**
43
+ * Full server information including player and plugin lists.
44
+ */
45
+ interface ServerInfoFull extends ServerInfo {
46
+ /** List of online players */
47
+ players: Player[];
48
+ /** List of installed plugins */
49
+ plugins: Plugin[];
50
+ }
51
+ /**
52
+ * Options for query function.
53
+ */
54
+ interface QueryOptions {
55
+ /** Timeout in milliseconds (default: 5000) */
56
+ timeout?: number;
57
+ /** Request full info including players and plugins (default: false) */
58
+ full?: boolean;
59
+ }
60
+
61
+ /**
62
+ * Query a Hytale server for information.
63
+ *
64
+ * @param host - Server hostname or IP address
65
+ * @param port - Server port (default: 5520)
66
+ * @param options - Query options
67
+ * @returns Server information (full if options.full is true)
68
+ *
69
+ * @example
70
+ * ```typescript
71
+ * // Basic query
72
+ * const info = await query('play.example.com', 5520);
73
+ * console.log(`${info.serverName}: ${info.currentPlayers}/${info.maxPlayers}`);
74
+ *
75
+ * // Full query (includes players + plugins)
76
+ * const full = await query('play.example.com', 5520, { full: true });
77
+ * console.log('Players:', full.players.map(p => p.name).join(', '));
78
+ * ```
79
+ */
80
+ declare function query(host: string, port?: number, options?: QueryOptions & {
81
+ full?: false;
82
+ }): Promise<ServerInfo>;
83
+ declare function query(host: string, port: number, options: QueryOptions & {
84
+ full: true;
85
+ }): Promise<ServerInfoFull>;
86
+
87
+ export { type Player, type Plugin, type QueryOptions, type ServerInfo, type ServerInfoFull, query };
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Basic server information returned by a basic query.
3
+ */
4
+ interface ServerInfo {
5
+ /** Server display name */
6
+ serverName: string;
7
+ /** Message of the day */
8
+ motd: string;
9
+ /** Current number of players online */
10
+ currentPlayers: number;
11
+ /** Maximum player capacity */
12
+ maxPlayers: number;
13
+ /** Server port */
14
+ hostPort: number;
15
+ /** Server version string */
16
+ version: string;
17
+ /** Protocol version number */
18
+ protocolVersion: number;
19
+ /** Protocol hash string */
20
+ protocolHash: string;
21
+ }
22
+ /**
23
+ * Player information included in full query response.
24
+ */
25
+ interface Player {
26
+ /** Player username */
27
+ name: string;
28
+ /** Player UUID in standard format */
29
+ uuid: string;
30
+ }
31
+ /**
32
+ * Plugin information included in full query response.
33
+ */
34
+ interface Plugin {
35
+ /** Plugin identifier (e.g. "HytaleOne:Query") */
36
+ id: string;
37
+ /** Plugin version string */
38
+ version: string;
39
+ /** Whether the plugin is enabled */
40
+ enabled: boolean;
41
+ }
42
+ /**
43
+ * Full server information including player and plugin lists.
44
+ */
45
+ interface ServerInfoFull extends ServerInfo {
46
+ /** List of online players */
47
+ players: Player[];
48
+ /** List of installed plugins */
49
+ plugins: Plugin[];
50
+ }
51
+ /**
52
+ * Options for query function.
53
+ */
54
+ interface QueryOptions {
55
+ /** Timeout in milliseconds (default: 5000) */
56
+ timeout?: number;
57
+ /** Request full info including players and plugins (default: false) */
58
+ full?: boolean;
59
+ }
60
+
61
+ /**
62
+ * Query a Hytale server for information.
63
+ *
64
+ * @param host - Server hostname or IP address
65
+ * @param port - Server port (default: 5520)
66
+ * @param options - Query options
67
+ * @returns Server information (full if options.full is true)
68
+ *
69
+ * @example
70
+ * ```typescript
71
+ * // Basic query
72
+ * const info = await query('play.example.com', 5520);
73
+ * console.log(`${info.serverName}: ${info.currentPlayers}/${info.maxPlayers}`);
74
+ *
75
+ * // Full query (includes players + plugins)
76
+ * const full = await query('play.example.com', 5520, { full: true });
77
+ * console.log('Players:', full.players.map(p => p.name).join(', '));
78
+ * ```
79
+ */
80
+ declare function query(host: string, port?: number, options?: QueryOptions & {
81
+ full?: false;
82
+ }): Promise<ServerInfo>;
83
+ declare function query(host: string, port: number, options: QueryOptions & {
84
+ full: true;
85
+ }): Promise<ServerInfoFull>;
86
+
87
+ export { type Player, type Plugin, type QueryOptions, type ServerInfo, type ServerInfoFull, query };
package/dist/index.js ADDED
@@ -0,0 +1,180 @@
1
+ // src/query.ts
2
+ import dgram from "dgram";
3
+
4
+ // src/protocol.ts
5
+ var REQUEST_MAGIC = Buffer.from("HYQUERY\0", "ascii");
6
+ var RESPONSE_MAGIC = Buffer.from("HYREPLY\0", "ascii");
7
+ var TYPE_BASIC = 0;
8
+ var TYPE_FULL = 1;
9
+ function buildRequest(type) {
10
+ const buf = Buffer.alloc(REQUEST_MAGIC.length + 1);
11
+ REQUEST_MAGIC.copy(buf, 0);
12
+ buf[REQUEST_MAGIC.length] = type;
13
+ return buf;
14
+ }
15
+ var BufferReader = class {
16
+ constructor(buf) {
17
+ this.buf = buf;
18
+ }
19
+ offset = 0;
20
+ readBytes(length) {
21
+ const slice = this.buf.subarray(this.offset, this.offset + length);
22
+ this.offset += length;
23
+ return slice;
24
+ }
25
+ readUInt16LE() {
26
+ const value = this.buf.readUInt16LE(this.offset);
27
+ this.offset += 2;
28
+ return value;
29
+ }
30
+ readInt32LE() {
31
+ const value = this.buf.readInt32LE(this.offset);
32
+ this.offset += 4;
33
+ return value;
34
+ }
35
+ readBigInt64BE() {
36
+ const value = this.buf.readBigInt64BE(this.offset);
37
+ this.offset += 8;
38
+ return value;
39
+ }
40
+ readBoolean() {
41
+ return this.buf[this.offset++] !== 0;
42
+ }
43
+ readString() {
44
+ const length = this.readUInt16LE();
45
+ const bytes = this.readBytes(length);
46
+ return bytes.toString("utf8");
47
+ }
48
+ readUUID() {
49
+ const msb = this.readBigInt64BE();
50
+ const lsb = this.readBigInt64BE();
51
+ return formatUUID(msb, lsb);
52
+ }
53
+ get remaining() {
54
+ return this.buf.length - this.offset;
55
+ }
56
+ };
57
+ function formatUUID(msb, lsb) {
58
+ const toHex = (n) => {
59
+ if (n < 0n) {
60
+ n = BigInt.asUintN(64, n);
61
+ }
62
+ return n.toString(16).padStart(16, "0");
63
+ };
64
+ const hex = toHex(msb) + toHex(lsb);
65
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
66
+ }
67
+ function validateResponse(buf) {
68
+ if (buf.length < RESPONSE_MAGIC.length + 1) {
69
+ return false;
70
+ }
71
+ return buf.subarray(0, RESPONSE_MAGIC.length).equals(RESPONSE_MAGIC);
72
+ }
73
+ function parseBasicResponse(buf) {
74
+ if (!validateResponse(buf)) {
75
+ throw new Error("Invalid response: magic mismatch");
76
+ }
77
+ const reader = new BufferReader(buf);
78
+ reader.readBytes(RESPONSE_MAGIC.length);
79
+ reader.readBytes(1);
80
+ return {
81
+ serverName: reader.readString(),
82
+ motd: reader.readString(),
83
+ currentPlayers: reader.readInt32LE(),
84
+ maxPlayers: reader.readInt32LE(),
85
+ hostPort: reader.readUInt16LE(),
86
+ version: reader.readString(),
87
+ protocolVersion: reader.readInt32LE(),
88
+ protocolHash: reader.readString()
89
+ };
90
+ }
91
+ function parseFullResponse(buf) {
92
+ if (!validateResponse(buf)) {
93
+ throw new Error("Invalid response: magic mismatch");
94
+ }
95
+ const reader = new BufferReader(buf);
96
+ reader.readBytes(RESPONSE_MAGIC.length);
97
+ reader.readBytes(1);
98
+ const serverName = reader.readString();
99
+ const motd = reader.readString();
100
+ const currentPlayers = reader.readInt32LE();
101
+ const maxPlayers = reader.readInt32LE();
102
+ const hostPort = reader.readUInt16LE();
103
+ const version = reader.readString();
104
+ const protocolVersion = reader.readInt32LE();
105
+ const protocolHash = reader.readString();
106
+ const playerCount = reader.readInt32LE();
107
+ const players = [];
108
+ for (let i = 0; i < playerCount; i++) {
109
+ players.push({
110
+ name: reader.readString(),
111
+ uuid: reader.readUUID()
112
+ });
113
+ }
114
+ const pluginCount = reader.readInt32LE();
115
+ const plugins = [];
116
+ for (let i = 0; i < pluginCount; i++) {
117
+ plugins.push({
118
+ id: reader.readString(),
119
+ version: reader.readString(),
120
+ enabled: reader.readBoolean()
121
+ });
122
+ }
123
+ return {
124
+ serverName,
125
+ motd,
126
+ currentPlayers,
127
+ maxPlayers,
128
+ hostPort,
129
+ version,
130
+ protocolVersion,
131
+ protocolHash,
132
+ players,
133
+ plugins
134
+ };
135
+ }
136
+
137
+ // src/query.ts
138
+ var DEFAULT_TIMEOUT = 5e3;
139
+ function sendQuery(host, port, type, timeout) {
140
+ return new Promise((resolve, reject) => {
141
+ const socket = dgram.createSocket("udp4");
142
+ let timeoutHandle;
143
+ const cleanup = () => {
144
+ clearTimeout(timeoutHandle);
145
+ socket.close();
146
+ };
147
+ socket.on("message", (msg) => {
148
+ cleanup();
149
+ resolve(msg);
150
+ });
151
+ socket.on("error", (err) => {
152
+ cleanup();
153
+ reject(err);
154
+ });
155
+ timeoutHandle = setTimeout(() => {
156
+ cleanup();
157
+ reject(new Error(`Query timeout after ${timeout}ms`));
158
+ }, timeout);
159
+ const request = buildRequest(type);
160
+ socket.send(request, port, host, (err) => {
161
+ if (err) {
162
+ cleanup();
163
+ reject(err);
164
+ }
165
+ });
166
+ });
167
+ }
168
+ async function query(host, port = 5520, options = {}) {
169
+ const timeout = options.timeout ?? DEFAULT_TIMEOUT;
170
+ const type = options.full ? TYPE_FULL : TYPE_BASIC;
171
+ const response = await sendQuery(host, port, type, timeout);
172
+ if (options.full) {
173
+ return parseFullResponse(response);
174
+ }
175
+ return parseBasicResponse(response);
176
+ }
177
+ export {
178
+ query
179
+ };
180
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/query.ts","../src/protocol.ts"],"sourcesContent":["import dgram from 'node:dgram';\nimport {\n buildRequest,\n parseBasicResponse,\n parseFullResponse,\n TYPE_BASIC,\n TYPE_FULL,\n} from './protocol.js';\nimport type { QueryOptions, ServerInfo, ServerInfoFull } from './types.js';\n\nconst DEFAULT_TIMEOUT = 5000;\n\n/**\n * Send a UDP query and wait for response.\n */\nfunction sendQuery(\n host: string,\n port: number,\n type: number,\n timeout: number\n): Promise<Buffer> {\n return new Promise((resolve, reject) => {\n const socket = dgram.createSocket('udp4');\n let timeoutHandle: NodeJS.Timeout;\n\n const cleanup = () => {\n clearTimeout(timeoutHandle);\n socket.close();\n };\n\n socket.on('message', (msg) => {\n cleanup();\n resolve(msg);\n });\n\n socket.on('error', (err) => {\n cleanup();\n reject(err);\n });\n\n timeoutHandle = setTimeout(() => {\n cleanup();\n reject(new Error(`Query timeout after ${timeout}ms`));\n }, timeout);\n\n const request = buildRequest(type);\n socket.send(request, port, host, (err) => {\n if (err) {\n cleanup();\n reject(err);\n }\n });\n });\n}\n\n/**\n * Query a Hytale server for information.\n *\n * @param host - Server hostname or IP address\n * @param port - Server port (default: 5520)\n * @param options - Query options\n * @returns Server information (full if options.full is true)\n *\n * @example\n * ```typescript\n * // Basic query\n * const info = await query('play.example.com', 5520);\n * console.log(`${info.serverName}: ${info.currentPlayers}/${info.maxPlayers}`);\n *\n * // Full query (includes players + plugins)\n * const full = await query('play.example.com', 5520, { full: true });\n * console.log('Players:', full.players.map(p => p.name).join(', '));\n * ```\n */\nexport async function query(\n host: string,\n port?: number,\n options?: QueryOptions & { full?: false }\n): Promise<ServerInfo>;\nexport async function query(\n host: string,\n port: number,\n options: QueryOptions & { full: true }\n): Promise<ServerInfoFull>;\nexport async function query(\n host: string,\n port = 5520,\n options: QueryOptions & { full?: boolean } = {}\n): Promise<ServerInfo | ServerInfoFull> {\n const timeout = options.timeout ?? DEFAULT_TIMEOUT;\n const type = options.full ? TYPE_FULL : TYPE_BASIC;\n const response = await sendQuery(host, port, type, timeout);\n\n if (options.full) {\n return parseFullResponse(response);\n }\n return parseBasicResponse(response);\n}\n","import type { Player, Plugin, ServerInfo, ServerInfoFull } from './types.js';\n\n// Protocol constants\nexport const REQUEST_MAGIC = Buffer.from('HYQUERY\\0', 'ascii');\nexport const RESPONSE_MAGIC = Buffer.from('HYREPLY\\0', 'ascii');\nexport const TYPE_BASIC = 0x00;\nexport const TYPE_FULL = 0x01;\n\n/**\n * Build a query request packet.\n */\nexport function buildRequest(type: number): Buffer {\n const buf = Buffer.alloc(REQUEST_MAGIC.length + 1);\n REQUEST_MAGIC.copy(buf, 0);\n buf[REQUEST_MAGIC.length] = type;\n return buf;\n}\n\n/**\n * Buffer reader helper for parsing responses.\n */\nclass BufferReader {\n private offset = 0;\n\n constructor(private buf: Buffer) {}\n\n readBytes(length: number): Buffer {\n const slice = this.buf.subarray(this.offset, this.offset + length);\n this.offset += length;\n return slice;\n }\n\n readUInt16LE(): number {\n const value = this.buf.readUInt16LE(this.offset);\n this.offset += 2;\n return value;\n }\n\n readInt32LE(): number {\n const value = this.buf.readInt32LE(this.offset);\n this.offset += 4;\n return value;\n }\n\n readBigInt64BE(): bigint {\n const value = this.buf.readBigInt64BE(this.offset);\n this.offset += 8;\n return value;\n }\n\n readBoolean(): boolean {\n return this.buf[this.offset++] !== 0;\n }\n\n readString(): string {\n const length = this.readUInt16LE();\n const bytes = this.readBytes(length);\n return bytes.toString('utf8');\n }\n\n readUUID(): string {\n const msb = this.readBigInt64BE();\n const lsb = this.readBigInt64BE();\n return formatUUID(msb, lsb);\n }\n\n get remaining(): number {\n return this.buf.length - this.offset;\n }\n}\n\n/**\n * Format UUID from most/least significant bits.\n */\nfunction formatUUID(msb: bigint, lsb: bigint): string {\n const toHex = (n: bigint): string => {\n if (n < 0n) {\n n = BigInt.asUintN(64, n);\n }\n return n.toString(16).padStart(16, '0');\n };\n\n const hex = toHex(msb) + toHex(lsb);\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n\n/**\n * Validate response magic bytes.\n */\nexport function validateResponse(buf: Buffer): boolean {\n if (buf.length < RESPONSE_MAGIC.length + 1) {\n return false;\n }\n return buf.subarray(0, RESPONSE_MAGIC.length).equals(RESPONSE_MAGIC);\n}\n\n/**\n * Parse a basic query response.\n */\nexport function parseBasicResponse(buf: Buffer): ServerInfo {\n if (!validateResponse(buf)) {\n throw new Error('Invalid response: magic mismatch');\n }\n\n const reader = new BufferReader(buf);\n\n // Skip magic\n reader.readBytes(RESPONSE_MAGIC.length);\n\n // Skip type\n reader.readBytes(1);\n\n return {\n serverName: reader.readString(),\n motd: reader.readString(),\n currentPlayers: reader.readInt32LE(),\n maxPlayers: reader.readInt32LE(),\n hostPort: reader.readUInt16LE(),\n version: reader.readString(),\n protocolVersion: reader.readInt32LE(),\n protocolHash: reader.readString(),\n };\n}\n\n/**\n * Parse a full query response.\n */\nexport function parseFullResponse(buf: Buffer): ServerInfoFull {\n if (!validateResponse(buf)) {\n throw new Error('Invalid response: magic mismatch');\n }\n\n const reader = new BufferReader(buf);\n\n // Skip magic\n reader.readBytes(RESPONSE_MAGIC.length);\n\n // Skip type\n reader.readBytes(1);\n\n // Base info\n const serverName = reader.readString();\n const motd = reader.readString();\n const currentPlayers = reader.readInt32LE();\n const maxPlayers = reader.readInt32LE();\n const hostPort = reader.readUInt16LE();\n const version = reader.readString();\n const protocolVersion = reader.readInt32LE();\n const protocolHash = reader.readString();\n\n // Player list\n const playerCount = reader.readInt32LE();\n const players: Player[] = [];\n for (let i = 0; i < playerCount; i++) {\n players.push({\n name: reader.readString(),\n uuid: reader.readUUID(),\n });\n }\n\n // Plugin list\n const pluginCount = reader.readInt32LE();\n const plugins: Plugin[] = [];\n for (let i = 0; i < pluginCount; i++) {\n plugins.push({\n id: reader.readString(),\n version: reader.readString(),\n enabled: reader.readBoolean(),\n });\n }\n\n return {\n serverName,\n motd,\n currentPlayers,\n maxPlayers,\n hostPort,\n version,\n protocolVersion,\n protocolHash,\n players,\n plugins,\n };\n}\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@hytaleone/query",
3
+ "version": "1.0.0",
4
+ "description": "Query Hytale servers using the UDP query protocol",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
19
+ }
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "scripts": {
25
+ "build": "tsup",
26
+ "prepublishOnly": "npm run build"
27
+ },
28
+ "keywords": [
29
+ "hytale",
30
+ "query",
31
+ "server",
32
+ "udp",
33
+ "status",
34
+ "ping"
35
+ ],
36
+ "author": "HytaleOne",
37
+ "license": "MIT",
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "https://github.com/HytaleOne/query-js"
41
+ },
42
+ "homepage": "https://hytale.one",
43
+ "engines": {
44
+ "node": ">=18"
45
+ },
46
+ "devDependencies": {
47
+ "@types/node": "^22.0.0",
48
+ "tsup": "^8.0.0",
49
+ "typescript": "^5.0.0"
50
+ }
51
+ }