specprotocol 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 +21 -0
- package/README.md +174 -0
- package/bin/specprotocol.js +136 -0
- package/dist/auth/microsoft.d.ts +23 -0
- package/dist/auth/microsoft.d.ts.map +1 -0
- package/dist/auth/microsoft.js +167 -0
- package/dist/auth/microsoft.js.map +1 -0
- package/dist/auth/offline.d.ts +20 -0
- package/dist/auth/offline.d.ts.map +1 -0
- package/dist/auth/offline.js +67 -0
- package/dist/auth/offline.js.map +1 -0
- package/dist/bot.d.ts +190 -0
- package/dist/bot.d.ts.map +1 -0
- package/dist/bot.js +624 -0
- package/dist/bot.js.map +1 -0
- package/dist/entity/entity.d.ts +71 -0
- package/dist/entity/entity.d.ts.map +1 -0
- package/dist/entity/entity.js +157 -0
- package/dist/entity/entity.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +73 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/built-in/chat.d.ts +19 -0
- package/dist/plugins/built-in/chat.d.ts.map +1 -0
- package/dist/plugins/built-in/chat.js +62 -0
- package/dist/plugins/built-in/chat.js.map +1 -0
- package/dist/plugins/built-in/combat.d.ts +20 -0
- package/dist/plugins/built-in/combat.d.ts.map +1 -0
- package/dist/plugins/built-in/combat.js +42 -0
- package/dist/plugins/built-in/combat.js.map +1 -0
- package/dist/plugins/plugin-manager.d.ts +49 -0
- package/dist/plugins/plugin-manager.d.ts.map +1 -0
- package/dist/plugins/plugin-manager.js +76 -0
- package/dist/plugins/plugin-manager.js.map +1 -0
- package/dist/protocol/compression.d.ts +23 -0
- package/dist/protocol/compression.d.ts.map +1 -0
- package/dist/protocol/compression.js +85 -0
- package/dist/protocol/compression.js.map +1 -0
- package/dist/protocol/connection.d.ts +73 -0
- package/dist/protocol/connection.d.ts.map +1 -0
- package/dist/protocol/connection.js +212 -0
- package/dist/protocol/connection.js.map +1 -0
- package/dist/protocol/encryption.d.ts +29 -0
- package/dist/protocol/encryption.d.ts.map +1 -0
- package/dist/protocol/encryption.js +116 -0
- package/dist/protocol/encryption.js.map +1 -0
- package/dist/protocol/packet.d.ts +75 -0
- package/dist/protocol/packet.d.ts.map +1 -0
- package/dist/protocol/packet.js +140 -0
- package/dist/protocol/packet.js.map +1 -0
- package/dist/protocol/states/handshake.d.ts +19 -0
- package/dist/protocol/states/handshake.d.ts.map +1 -0
- package/dist/protocol/states/handshake.js +32 -0
- package/dist/protocol/states/handshake.js.map +1 -0
- package/dist/protocol/states/login.d.ts +77 -0
- package/dist/protocol/states/login.d.ts.map +1 -0
- package/dist/protocol/states/login.js +125 -0
- package/dist/protocol/states/login.js.map +1 -0
- package/dist/protocol/states/play.d.ts +187 -0
- package/dist/protocol/states/play.d.ts.map +1 -0
- package/dist/protocol/states/play.js +316 -0
- package/dist/protocol/states/play.js.map +1 -0
- package/dist/protocol/types.d.ts +210 -0
- package/dist/protocol/types.d.ts.map +1 -0
- package/dist/protocol/types.js +495 -0
- package/dist/protocol/types.js.map +1 -0
- package/dist/types.d.ts +36 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/events.d.ts +23 -0
- package/dist/utils/events.d.ts.map +1 -0
- package/dist/utils/events.js +44 -0
- package/dist/utils/events.js.map +1 -0
- package/dist/utils/logger.d.ts +19 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +47 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/vec3.d.ts +25 -0
- package/dist/utils/vec3.d.ts.map +1 -0
- package/dist/utils/vec3.js +66 -0
- package/dist/utils/vec3.js.map +1 -0
- package/dist/world/block.d.ts +39 -0
- package/dist/world/block.d.ts.map +1 -0
- package/dist/world/block.js +84 -0
- package/dist/world/block.js.map +1 -0
- package/dist/world/world.d.ts +55 -0
- package/dist/world/world.d.ts.map +1 -0
- package/dist/world/world.js +95 -0
- package/dist/world/world.js.map +1 -0
- package/docs/README.md +29 -0
- package/docs/api/auth.md +210 -0
- package/docs/api/bot.md +137 -0
- package/docs/api/events.md +166 -0
- package/docs/api/plugins.md +207 -0
- package/docs/api/protocol.md +129 -0
- package/docs/api/world.md +138 -0
- package/docs/first-bot.md +114 -0
- package/docs/getting-started.md +103 -0
- package/docs/guides/architecture.md +122 -0
- package/docs/guides/custom-plugins.md +211 -0
- package/docs/guides/raw-packets.md +80 -0
- package/package.json +55 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zlib Compression/Decompression for Minecraft packet compression.
|
|
3
|
+
*
|
|
4
|
+
* Minecraft uses Zlib (deflate) for packet compression when enabled.
|
|
5
|
+
* Compression is enabled after Login Success with a threshold value.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Compress data using Zlib deflate.
|
|
9
|
+
*/
|
|
10
|
+
export declare function compressSync(data: Buffer): Buffer;
|
|
11
|
+
/**
|
|
12
|
+
* Decompress data using Zlib inflate.
|
|
13
|
+
*/
|
|
14
|
+
export declare function decompressSync(data: Buffer): Buffer;
|
|
15
|
+
/**
|
|
16
|
+
* Async compress.
|
|
17
|
+
*/
|
|
18
|
+
export declare function compress(data: Buffer): Promise<Buffer>;
|
|
19
|
+
/**
|
|
20
|
+
* Async decompress.
|
|
21
|
+
*/
|
|
22
|
+
export declare function decompress(data: Buffer): Promise<Buffer>;
|
|
23
|
+
//# sourceMappingURL=compression.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compression.d.ts","sourceRoot":"","sources":["../../src/protocol/compression.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAOtD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAOxD"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Zlib Compression/Decompression for Minecraft packet compression.
|
|
4
|
+
*
|
|
5
|
+
* Minecraft uses Zlib (deflate) for packet compression when enabled.
|
|
6
|
+
* Compression is enabled after Login Success with a threshold value.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.compressSync = compressSync;
|
|
43
|
+
exports.decompressSync = decompressSync;
|
|
44
|
+
exports.compress = compress;
|
|
45
|
+
exports.decompress = decompress;
|
|
46
|
+
const zlib = __importStar(require("zlib"));
|
|
47
|
+
/**
|
|
48
|
+
* Compress data using Zlib deflate.
|
|
49
|
+
*/
|
|
50
|
+
function compressSync(data) {
|
|
51
|
+
return zlib.deflateSync(data);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Decompress data using Zlib inflate.
|
|
55
|
+
*/
|
|
56
|
+
function decompressSync(data) {
|
|
57
|
+
return zlib.inflateSync(data);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Async compress.
|
|
61
|
+
*/
|
|
62
|
+
function compress(data) {
|
|
63
|
+
return new Promise((resolve, reject) => {
|
|
64
|
+
zlib.deflate(data, (err, result) => {
|
|
65
|
+
if (err)
|
|
66
|
+
reject(err);
|
|
67
|
+
else
|
|
68
|
+
resolve(result);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Async decompress.
|
|
74
|
+
*/
|
|
75
|
+
function decompress(data) {
|
|
76
|
+
return new Promise((resolve, reject) => {
|
|
77
|
+
zlib.inflate(data, (err, result) => {
|
|
78
|
+
if (err)
|
|
79
|
+
reject(err);
|
|
80
|
+
else
|
|
81
|
+
resolve(result);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=compression.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compression.js","sourceRoot":"","sources":["../../src/protocol/compression.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOH,oCAEC;AAKD,wCAEC;AAKD,4BAOC;AAKD,gCAOC;AAtCD,2CAA6B;AAE7B;;GAEG;AACH,SAAgB,YAAY,CAAC,IAAY;IACrC,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,SAAgB,cAAc,CAAC,IAAY;IACvC,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,SAAgB,QAAQ,CAAC,IAAY;IACjC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACnC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;YAC/B,IAAI,GAAG;gBAAE,MAAM,CAAC,GAAG,CAAC,CAAC;;gBAChB,OAAO,CAAC,MAAM,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;GAEG;AACH,SAAgB,UAAU,CAAC,IAAY;IACnC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACnC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;YAC/B,IAAI,GAAG;gBAAE,MAAM,CAAC,GAAG,CAAC,CAAC;;gBAChB,OAAO,CAAC,MAAM,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TCP Connection Manager for Minecraft protocol.
|
|
3
|
+
*
|
|
4
|
+
* Handles:
|
|
5
|
+
* - TCP socket connection
|
|
6
|
+
* - Packet framing (length-prefixed)
|
|
7
|
+
* - Optional compression (Zlib)
|
|
8
|
+
* - Optional encryption (AES/CFB8)
|
|
9
|
+
* - Event-based packet receiving
|
|
10
|
+
*/
|
|
11
|
+
import { TypedEventEmitter } from '../utils/events.js';
|
|
12
|
+
import { LogLevel } from '../utils/logger.js';
|
|
13
|
+
import { type RawPacket } from './packet.js';
|
|
14
|
+
export interface ConnectionEvents {
|
|
15
|
+
/** Fired when a raw packet is received */
|
|
16
|
+
'packet': (packet: RawPacket) => void;
|
|
17
|
+
/** Fired when connection is established */
|
|
18
|
+
'connect': () => void;
|
|
19
|
+
/** Fired on connection error */
|
|
20
|
+
'error': (error: Error) => void;
|
|
21
|
+
/** Fired when connection is closed */
|
|
22
|
+
'close': () => void;
|
|
23
|
+
}
|
|
24
|
+
export interface ConnectionOptions {
|
|
25
|
+
host: string;
|
|
26
|
+
port: number;
|
|
27
|
+
logLevel?: LogLevel;
|
|
28
|
+
}
|
|
29
|
+
export declare class Connection extends TypedEventEmitter<ConnectionEvents> {
|
|
30
|
+
private socket;
|
|
31
|
+
private splitter;
|
|
32
|
+
private logger;
|
|
33
|
+
/** Encryption state */
|
|
34
|
+
private cipher;
|
|
35
|
+
private decipher;
|
|
36
|
+
private encrypted;
|
|
37
|
+
/** Compression state */
|
|
38
|
+
private compressionThreshold;
|
|
39
|
+
private readonly host;
|
|
40
|
+
private readonly port;
|
|
41
|
+
private _connected;
|
|
42
|
+
constructor(options: ConnectionOptions);
|
|
43
|
+
get connected(): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Connect to the Minecraft server.
|
|
46
|
+
*/
|
|
47
|
+
connect(): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Handle incoming TCP data.
|
|
50
|
+
*/
|
|
51
|
+
private handleData;
|
|
52
|
+
/**
|
|
53
|
+
* Send a packet to the server.
|
|
54
|
+
*/
|
|
55
|
+
sendPacket(packetId: number, data: Buffer): void;
|
|
56
|
+
/**
|
|
57
|
+
* Enable compression with the given threshold.
|
|
58
|
+
*/
|
|
59
|
+
enableCompression(threshold: number): void;
|
|
60
|
+
/**
|
|
61
|
+
* Enable encryption with the given shared secret.
|
|
62
|
+
*/
|
|
63
|
+
enableEncryption(sharedSecret: Buffer): void;
|
|
64
|
+
/**
|
|
65
|
+
* Disconnect from the server.
|
|
66
|
+
*/
|
|
67
|
+
disconnect(): void;
|
|
68
|
+
/**
|
|
69
|
+
* Wait for a specific packet ID (convenience helper).
|
|
70
|
+
*/
|
|
71
|
+
waitForPacket(packetId: number, timeout?: number): Promise<RawPacket>;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=connection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/protocol/connection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAU,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAKH,KAAK,SAAS,EACjB,MAAM,aAAa,CAAC;AAKrB,MAAM,WAAW,gBAAgB;IAC7B,0CAA0C;IAC1C,QAAQ,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,CAAC;IACtC,2CAA2C;IAC3C,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,gCAAgC;IAChC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAChC,sCAAsC;IACtC,OAAO,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACvB;AAED,qBAAa,UAAW,SAAQ,iBAAiB,CAAC,gBAAgB,CAAC;IAC/D,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,QAAQ,CAAwB;IACxC,OAAO,CAAC,MAAM,CAAS;IAEvB,uBAAuB;IACvB,OAAO,CAAC,MAAM,CAAgD;IAC9D,OAAO,CAAC,QAAQ,CAAkD;IAClE,OAAO,CAAC,SAAS,CAAS;IAE1B,wBAAwB;IACxB,OAAO,CAAC,oBAAoB,CAAM;IAElC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,UAAU,CAAS;gBAEf,OAAO,EAAE,iBAAiB;IAOtC,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED;;OAEG;IACH,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAgCxB;;OAEG;IACH,OAAO,CAAC,UAAU;IAuClB;;OAEG;IACH,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAqBhD;;OAEG;IACH,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAK1C;;OAEG;IACH,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;IAO5C;;OAEG;IACH,UAAU,IAAI,IAAI;IAQlB;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,MAAc,GAAG,OAAO,CAAC,SAAS,CAAC;CAkB/E"}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* TCP Connection Manager for Minecraft protocol.
|
|
4
|
+
*
|
|
5
|
+
* Handles:
|
|
6
|
+
* - TCP socket connection
|
|
7
|
+
* - Packet framing (length-prefixed)
|
|
8
|
+
* - Optional compression (Zlib)
|
|
9
|
+
* - Optional encryption (AES/CFB8)
|
|
10
|
+
* - Event-based packet receiving
|
|
11
|
+
*/
|
|
12
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
15
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
16
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
17
|
+
}
|
|
18
|
+
Object.defineProperty(o, k2, desc);
|
|
19
|
+
}) : (function(o, m, k, k2) {
|
|
20
|
+
if (k2 === undefined) k2 = k;
|
|
21
|
+
o[k2] = m[k];
|
|
22
|
+
}));
|
|
23
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
24
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
25
|
+
}) : function(o, v) {
|
|
26
|
+
o["default"] = v;
|
|
27
|
+
});
|
|
28
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
29
|
+
var ownKeys = function(o) {
|
|
30
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
31
|
+
var ar = [];
|
|
32
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
33
|
+
return ar;
|
|
34
|
+
};
|
|
35
|
+
return ownKeys(o);
|
|
36
|
+
};
|
|
37
|
+
return function (mod) {
|
|
38
|
+
if (mod && mod.__esModule) return mod;
|
|
39
|
+
var result = {};
|
|
40
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
41
|
+
__setModuleDefault(result, mod);
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
44
|
+
})();
|
|
45
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
+
exports.Connection = void 0;
|
|
47
|
+
const net = __importStar(require("net"));
|
|
48
|
+
const events_js_1 = require("../utils/events.js");
|
|
49
|
+
const logger_js_1 = require("../utils/logger.js");
|
|
50
|
+
const packet_js_1 = require("./packet.js");
|
|
51
|
+
const types_js_1 = require("./types.js");
|
|
52
|
+
const encryption_js_1 = require("./encryption.js");
|
|
53
|
+
const compression_js_1 = require("./compression.js");
|
|
54
|
+
class Connection extends events_js_1.TypedEventEmitter {
|
|
55
|
+
socket = null;
|
|
56
|
+
splitter = new packet_js_1.PacketSplitter();
|
|
57
|
+
logger;
|
|
58
|
+
/** Encryption state */
|
|
59
|
+
cipher = null;
|
|
60
|
+
decipher = null;
|
|
61
|
+
encrypted = false;
|
|
62
|
+
/** Compression state */
|
|
63
|
+
compressionThreshold = -1;
|
|
64
|
+
host;
|
|
65
|
+
port;
|
|
66
|
+
_connected = false;
|
|
67
|
+
constructor(options) {
|
|
68
|
+
super();
|
|
69
|
+
this.host = options.host;
|
|
70
|
+
this.port = options.port;
|
|
71
|
+
this.logger = new logger_js_1.Logger('Connection', options.logLevel ?? logger_js_1.LogLevel.INFO);
|
|
72
|
+
}
|
|
73
|
+
get connected() {
|
|
74
|
+
return this._connected;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Connect to the Minecraft server.
|
|
78
|
+
*/
|
|
79
|
+
connect() {
|
|
80
|
+
return new Promise((resolve, reject) => {
|
|
81
|
+
this.socket = net.createConnection({
|
|
82
|
+
host: this.host,
|
|
83
|
+
port: this.port,
|
|
84
|
+
});
|
|
85
|
+
this.socket.once('connect', () => {
|
|
86
|
+
this._connected = true;
|
|
87
|
+
this.logger.info(`Connected to ${this.host}:${this.port}`);
|
|
88
|
+
this.emit('connect');
|
|
89
|
+
resolve();
|
|
90
|
+
});
|
|
91
|
+
this.socket.once('error', (err) => {
|
|
92
|
+
this.logger.error('Socket error:', err);
|
|
93
|
+
this.emit('error', err);
|
|
94
|
+
if (!this._connected)
|
|
95
|
+
reject(err);
|
|
96
|
+
});
|
|
97
|
+
this.socket.on('data', (data) => {
|
|
98
|
+
this.handleData(data);
|
|
99
|
+
});
|
|
100
|
+
this.socket.once('close', () => {
|
|
101
|
+
this._connected = false;
|
|
102
|
+
this.logger.info('Connection closed');
|
|
103
|
+
this.emit('close');
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Handle incoming TCP data.
|
|
109
|
+
*/
|
|
110
|
+
handleData(rawData) {
|
|
111
|
+
let data = rawData;
|
|
112
|
+
// Decrypt if encryption is enabled
|
|
113
|
+
if (this.encrypted && this.decipher) {
|
|
114
|
+
data = this.decipher.update(data);
|
|
115
|
+
}
|
|
116
|
+
// Split into packet frames
|
|
117
|
+
const frames = this.splitter.feed(data);
|
|
118
|
+
for (const frame of frames) {
|
|
119
|
+
try {
|
|
120
|
+
let packetPayload;
|
|
121
|
+
if (this.compressionThreshold >= 0) {
|
|
122
|
+
// Compression is enabled — read data length
|
|
123
|
+
const { value: dataLength, bytesRead } = (0, types_js_1.readVarInt)(frame, 0);
|
|
124
|
+
const compressedData = frame.subarray(bytesRead);
|
|
125
|
+
if (dataLength === 0) {
|
|
126
|
+
// Not compressed
|
|
127
|
+
packetPayload = compressedData;
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
// Decompress
|
|
131
|
+
packetPayload = (0, compression_js_1.decompressSync)(compressedData);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
packetPayload = frame;
|
|
136
|
+
}
|
|
137
|
+
const packet = (0, packet_js_1.parseRawPacket)(packetPayload);
|
|
138
|
+
this.emit('packet', packet);
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
this.logger.error('Failed to parse packet:', err);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Send a packet to the server.
|
|
147
|
+
*/
|
|
148
|
+
sendPacket(packetId, data) {
|
|
149
|
+
if (!this.socket || !this._connected) {
|
|
150
|
+
throw new Error('Not connected');
|
|
151
|
+
}
|
|
152
|
+
let frame;
|
|
153
|
+
if (this.compressionThreshold >= 0) {
|
|
154
|
+
frame = (0, packet_js_1.framePacketCompressed)(packetId, data, this.compressionThreshold, compression_js_1.compressSync);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
frame = (0, packet_js_1.framePacket)(packetId, data);
|
|
158
|
+
}
|
|
159
|
+
// Encrypt if encryption is enabled
|
|
160
|
+
if (this.encrypted && this.cipher) {
|
|
161
|
+
frame = this.cipher.update(frame);
|
|
162
|
+
}
|
|
163
|
+
this.socket.write(frame);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Enable compression with the given threshold.
|
|
167
|
+
*/
|
|
168
|
+
enableCompression(threshold) {
|
|
169
|
+
this.compressionThreshold = threshold;
|
|
170
|
+
this.logger.info(`Compression enabled with threshold: ${threshold}`);
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Enable encryption with the given shared secret.
|
|
174
|
+
*/
|
|
175
|
+
enableEncryption(sharedSecret) {
|
|
176
|
+
this.cipher = (0, encryption_js_1.createCipher)(sharedSecret);
|
|
177
|
+
this.decipher = (0, encryption_js_1.createDecipher)(sharedSecret);
|
|
178
|
+
this.encrypted = true;
|
|
179
|
+
this.logger.info('Encryption enabled');
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Disconnect from the server.
|
|
183
|
+
*/
|
|
184
|
+
disconnect() {
|
|
185
|
+
if (this.socket) {
|
|
186
|
+
this.socket.destroy();
|
|
187
|
+
this.socket = null;
|
|
188
|
+
this._connected = false;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Wait for a specific packet ID (convenience helper).
|
|
193
|
+
*/
|
|
194
|
+
waitForPacket(packetId, timeout = 10000) {
|
|
195
|
+
return new Promise((resolve, reject) => {
|
|
196
|
+
const timer = setTimeout(() => {
|
|
197
|
+
this.off('packet', handler);
|
|
198
|
+
reject(new Error(`Timeout waiting for packet 0x${packetId.toString(16)}`));
|
|
199
|
+
}, timeout);
|
|
200
|
+
const handler = (packet) => {
|
|
201
|
+
if (packet.id === packetId) {
|
|
202
|
+
clearTimeout(timer);
|
|
203
|
+
this.off('packet', handler);
|
|
204
|
+
resolve(packet);
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
this.on('packet', handler);
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
exports.Connection = Connection;
|
|
212
|
+
//# sourceMappingURL=connection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/protocol/connection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AES/CFB8 Encryption for Minecraft protocol.
|
|
3
|
+
*
|
|
4
|
+
* Minecraft uses AES/CFB8 encryption for all packets after the Encryption Response.
|
|
5
|
+
* Both the key and IV are the shared secret (16 bytes).
|
|
6
|
+
*/
|
|
7
|
+
import * as crypto from 'crypto';
|
|
8
|
+
/**
|
|
9
|
+
* Create a cipher transform for encrypting outgoing data.
|
|
10
|
+
*/
|
|
11
|
+
export declare function createCipher(sharedSecret: Buffer): crypto.Cipheriv;
|
|
12
|
+
/**
|
|
13
|
+
* Create a decipher transform for decrypting incoming data.
|
|
14
|
+
*/
|
|
15
|
+
export declare function createDecipher(sharedSecret: Buffer): crypto.Decipheriv;
|
|
16
|
+
/**
|
|
17
|
+
* Generate a random shared secret (16 bytes).
|
|
18
|
+
*/
|
|
19
|
+
export declare function generateSharedSecret(): Buffer;
|
|
20
|
+
/**
|
|
21
|
+
* Encrypt the shared secret with the server's public key (RSA PKCS1).
|
|
22
|
+
*/
|
|
23
|
+
export declare function encryptRSA(publicKeyDer: Buffer, data: Buffer): Buffer;
|
|
24
|
+
/**
|
|
25
|
+
* Compute the "server hash" for Minecraft authentication.
|
|
26
|
+
* Minecraft uses a non-standard hex digest (Notch's twos-complement hex).
|
|
27
|
+
*/
|
|
28
|
+
export declare function computeServerHash(serverId: string, sharedSecret: Buffer, publicKey: Buffer): string;
|
|
29
|
+
//# sourceMappingURL=encryption.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encryption.d.ts","sourceRoot":"","sources":["../../src/protocol/encryption.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAIjC;;GAEG;AACH,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,mBAEhD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,qBAElD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAcrE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAQnG"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* AES/CFB8 Encryption for Minecraft protocol.
|
|
4
|
+
*
|
|
5
|
+
* Minecraft uses AES/CFB8 encryption for all packets after the Encryption Response.
|
|
6
|
+
* Both the key and IV are the shared secret (16 bytes).
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.createCipher = createCipher;
|
|
43
|
+
exports.createDecipher = createDecipher;
|
|
44
|
+
exports.generateSharedSecret = generateSharedSecret;
|
|
45
|
+
exports.encryptRSA = encryptRSA;
|
|
46
|
+
exports.computeServerHash = computeServerHash;
|
|
47
|
+
const crypto = __importStar(require("crypto"));
|
|
48
|
+
const ALGORITHM = 'aes-128-cfb8';
|
|
49
|
+
/**
|
|
50
|
+
* Create a cipher transform for encrypting outgoing data.
|
|
51
|
+
*/
|
|
52
|
+
function createCipher(sharedSecret) {
|
|
53
|
+
return crypto.createCipheriv(ALGORITHM, sharedSecret, sharedSecret);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Create a decipher transform for decrypting incoming data.
|
|
57
|
+
*/
|
|
58
|
+
function createDecipher(sharedSecret) {
|
|
59
|
+
return crypto.createDecipheriv(ALGORITHM, sharedSecret, sharedSecret);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Generate a random shared secret (16 bytes).
|
|
63
|
+
*/
|
|
64
|
+
function generateSharedSecret() {
|
|
65
|
+
return crypto.randomBytes(16);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Encrypt the shared secret with the server's public key (RSA PKCS1).
|
|
69
|
+
*/
|
|
70
|
+
function encryptRSA(publicKeyDer, data) {
|
|
71
|
+
const publicKey = crypto.createPublicKey({
|
|
72
|
+
key: publicKeyDer,
|
|
73
|
+
format: 'der',
|
|
74
|
+
type: 'spki',
|
|
75
|
+
});
|
|
76
|
+
return crypto.publicEncrypt({
|
|
77
|
+
key: publicKey,
|
|
78
|
+
padding: crypto.constants.RSA_PKCS1_PADDING,
|
|
79
|
+
}, data);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Compute the "server hash" for Minecraft authentication.
|
|
83
|
+
* Minecraft uses a non-standard hex digest (Notch's twos-complement hex).
|
|
84
|
+
*/
|
|
85
|
+
function computeServerHash(serverId, sharedSecret, publicKey) {
|
|
86
|
+
const hash = crypto.createHash('sha1');
|
|
87
|
+
hash.update(serverId);
|
|
88
|
+
hash.update(sharedSecret);
|
|
89
|
+
hash.update(publicKey);
|
|
90
|
+
const digest = hash.digest();
|
|
91
|
+
return minecraftHexDigest(digest);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Minecraft's non-standard hex digest.
|
|
95
|
+
* If the most significant bit is set, the value is negative (two's complement).
|
|
96
|
+
*/
|
|
97
|
+
function minecraftHexDigest(buffer) {
|
|
98
|
+
const isNegative = (buffer[0] & 0x80) !== 0;
|
|
99
|
+
if (isNegative) {
|
|
100
|
+
// Two's complement
|
|
101
|
+
let carry = true;
|
|
102
|
+
const flipped = Buffer.alloc(buffer.length);
|
|
103
|
+
for (let i = buffer.length - 1; i >= 0; i--) {
|
|
104
|
+
let byte = ~buffer[i] & 0xFF;
|
|
105
|
+
if (carry) {
|
|
106
|
+
byte++;
|
|
107
|
+
carry = byte > 0xFF;
|
|
108
|
+
byte &= 0xFF;
|
|
109
|
+
}
|
|
110
|
+
flipped[i] = byte;
|
|
111
|
+
}
|
|
112
|
+
return '-' + flipped.toString('hex').replace(/^0+/, '');
|
|
113
|
+
}
|
|
114
|
+
return buffer.toString('hex').replace(/^0+/, '');
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=encryption.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encryption.js","sourceRoot":"","sources":["../../src/protocol/encryption.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AASH,oCAEC;AAKD,wCAEC;AAKD,oDAEC;AAKD,gCAcC;AAMD,8CAQC;AAxDD,+CAAiC;AAEjC,MAAM,SAAS,GAAG,cAAc,CAAC;AAEjC;;GAEG;AACH,SAAgB,YAAY,CAAC,YAAoB;IAC7C,OAAO,MAAM,CAAC,cAAc,CAAC,SAAS,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC;AACxE,CAAC;AAED;;GAEG;AACH,SAAgB,cAAc,CAAC,YAAoB;IAC/C,OAAO,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC;AAC1E,CAAC;AAED;;GAEG;AACH,SAAgB,oBAAoB;IAChC,OAAO,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,SAAgB,UAAU,CAAC,YAAoB,EAAE,IAAY;IACzD,MAAM,SAAS,GAAG,MAAM,CAAC,eAAe,CAAC;QACrC,GAAG,EAAE,YAAY;QACjB,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,MAAM;KACf,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,aAAa,CACvB;QACI,GAAG,EAAE,SAAS;QACd,OAAO,EAAE,MAAM,CAAC,SAAS,CAAC,iBAAiB;KAC9C,EACD,IAAI,CACP,CAAC;AACN,CAAC;AAED;;;GAGG;AACH,SAAgB,iBAAiB,CAAC,QAAgB,EAAE,YAAoB,EAAE,SAAiB;IACvF,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IACvC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACtB,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAC1B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACvB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;IAE7B,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC;AACtC,CAAC;AAED;;;GAGG;AACH,SAAS,kBAAkB,CAAC,MAAc;IACtC,MAAM,UAAU,GAAG,CAAC,MAAM,CAAC,CAAC,CAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;IAE7C,IAAI,UAAU,EAAE,CAAC;QACb,mBAAmB;QACnB,IAAI,KAAK,GAAG,IAAI,CAAC;QACjB,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5C,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC1C,IAAI,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAE,GAAG,IAAI,CAAC;YAC9B,IAAI,KAAK,EAAE,CAAC;gBACR,IAAI,EAAE,CAAC;gBACP,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC;gBACpB,IAAI,IAAI,IAAI,CAAC;YACjB,CAAC;YACD,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;QACtB,CAAC;QACD,OAAO,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACrD,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Packet definitions and serialization/deserialization.
|
|
3
|
+
*
|
|
4
|
+
* Each Minecraft packet has:
|
|
5
|
+
* - Length (VarInt) — total byte size of packetId + data
|
|
6
|
+
* - Packet ID (VarInt)
|
|
7
|
+
* - Data (varies per packet)
|
|
8
|
+
*/
|
|
9
|
+
import { BufferReader } from './types.js';
|
|
10
|
+
/** Protocol states */
|
|
11
|
+
export declare enum ProtocolState {
|
|
12
|
+
HANDSHAKING = 0,
|
|
13
|
+
STATUS = 1,
|
|
14
|
+
LOGIN = 2,
|
|
15
|
+
CONFIGURATION = 3,
|
|
16
|
+
PLAY = 4
|
|
17
|
+
}
|
|
18
|
+
/** Packet direction */
|
|
19
|
+
export declare enum PacketDirection {
|
|
20
|
+
SERVERBOUND = "serverbound",
|
|
21
|
+
CLIENTBOUND = "clientbound"
|
|
22
|
+
}
|
|
23
|
+
/** Raw packet structure */
|
|
24
|
+
export interface RawPacket {
|
|
25
|
+
id: number;
|
|
26
|
+
data: Buffer;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Frame a packet for sending over the wire.
|
|
30
|
+
* Format: [Length VarInt][Packet ID VarInt][Data]
|
|
31
|
+
*/
|
|
32
|
+
export declare function framePacket(packetId: number, data: Buffer): Buffer;
|
|
33
|
+
/**
|
|
34
|
+
* Frame a packet with compression.
|
|
35
|
+
* Format when compressed: [Packet Length][Data Length][Compressed(Packet ID + Data)]
|
|
36
|
+
* Format when uncompressed: [Packet Length][0][Packet ID + Data]
|
|
37
|
+
*/
|
|
38
|
+
export declare function framePacketCompressed(packetId: number, data: Buffer, threshold: number, compress: (data: Buffer) => Buffer): Buffer;
|
|
39
|
+
/**
|
|
40
|
+
* PacketSplitter — accumulates incoming TCP data and splits into individual packet frames.
|
|
41
|
+
* Handles the length-prefixed framing used by Minecraft protocol.
|
|
42
|
+
*/
|
|
43
|
+
export declare class PacketSplitter {
|
|
44
|
+
private buffer;
|
|
45
|
+
/**
|
|
46
|
+
* Feed raw TCP data into the splitter.
|
|
47
|
+
* Returns an array of complete packet buffers (each containing [Packet ID VarInt][Data]).
|
|
48
|
+
*/
|
|
49
|
+
feed(data: Buffer): Buffer[];
|
|
50
|
+
/** Reset the internal buffer */
|
|
51
|
+
reset(): void;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Parse a raw packet payload into id + data.
|
|
55
|
+
*/
|
|
56
|
+
export declare function parseRawPacket(payload: Buffer): RawPacket;
|
|
57
|
+
/**
|
|
58
|
+
* PacketRegistry — maps packet IDs to names and handlers.
|
|
59
|
+
*/
|
|
60
|
+
export type PacketHandler = (reader: BufferReader) => Record<string, unknown>;
|
|
61
|
+
export interface PacketDefinition {
|
|
62
|
+
name: string;
|
|
63
|
+
state: ProtocolState;
|
|
64
|
+
direction: PacketDirection;
|
|
65
|
+
id: number;
|
|
66
|
+
handler?: PacketHandler;
|
|
67
|
+
}
|
|
68
|
+
export declare class PacketRegistry {
|
|
69
|
+
private packets;
|
|
70
|
+
private makeKey;
|
|
71
|
+
register(def: PacketDefinition): void;
|
|
72
|
+
get(state: ProtocolState, direction: PacketDirection, id: number): PacketDefinition | undefined;
|
|
73
|
+
getByName(name: string): PacketDefinition | undefined;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=packet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packet.d.ts","sourceRoot":"","sources":["../../src/protocol/packet.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,YAAY,EAAqD,MAAM,YAAY,CAAC;AAE7F,sBAAsB;AACtB,oBAAY,aAAa;IACrB,WAAW,IAAI;IACf,MAAM,IAAI;IACV,KAAK,IAAI;IACT,aAAa,IAAI;IACjB,IAAI,IAAI;CACX;AAED,uBAAuB;AACvB,oBAAY,eAAe;IACvB,WAAW,gBAAgB;IAC3B,WAAW,gBAAgB;CAC9B;AAED,2BAA2B;AAC3B,MAAM,WAAW,SAAS;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAKlE;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,MAAM,CAmBnI;AAED;;;GAGG;AACH,qBAAa,cAAc;IACvB,OAAO,CAAC,MAAM,CAA2B;IAEzC;;;OAGG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE;IAoC5B,gCAAgC;IAChC,KAAK,IAAI,IAAI;CAGhB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAIzD;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,YAAY,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE9E,MAAM,WAAW,gBAAgB;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,aAAa,CAAC;IACrB,SAAS,EAAE,eAAe,CAAC;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,CAAC,EAAE,aAAa,CAAC;CAC3B;AAED,qBAAa,cAAc;IACvB,OAAO,CAAC,OAAO,CAAuC;IAEtD,OAAO,CAAC,OAAO;IAIf,QAAQ,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI;IAKrC,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAI/F,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;CAMxD"}
|