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.
Files changed (104) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +174 -0
  3. package/bin/specprotocol.js +136 -0
  4. package/dist/auth/microsoft.d.ts +23 -0
  5. package/dist/auth/microsoft.d.ts.map +1 -0
  6. package/dist/auth/microsoft.js +167 -0
  7. package/dist/auth/microsoft.js.map +1 -0
  8. package/dist/auth/offline.d.ts +20 -0
  9. package/dist/auth/offline.d.ts.map +1 -0
  10. package/dist/auth/offline.js +67 -0
  11. package/dist/auth/offline.js.map +1 -0
  12. package/dist/bot.d.ts +190 -0
  13. package/dist/bot.d.ts.map +1 -0
  14. package/dist/bot.js +624 -0
  15. package/dist/bot.js.map +1 -0
  16. package/dist/entity/entity.d.ts +71 -0
  17. package/dist/entity/entity.d.ts.map +1 -0
  18. package/dist/entity/entity.js +157 -0
  19. package/dist/entity/entity.js.map +1 -0
  20. package/dist/index.d.ts +36 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +73 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/plugins/built-in/chat.d.ts +19 -0
  25. package/dist/plugins/built-in/chat.d.ts.map +1 -0
  26. package/dist/plugins/built-in/chat.js +62 -0
  27. package/dist/plugins/built-in/chat.js.map +1 -0
  28. package/dist/plugins/built-in/combat.d.ts +20 -0
  29. package/dist/plugins/built-in/combat.d.ts.map +1 -0
  30. package/dist/plugins/built-in/combat.js +42 -0
  31. package/dist/plugins/built-in/combat.js.map +1 -0
  32. package/dist/plugins/plugin-manager.d.ts +49 -0
  33. package/dist/plugins/plugin-manager.d.ts.map +1 -0
  34. package/dist/plugins/plugin-manager.js +76 -0
  35. package/dist/plugins/plugin-manager.js.map +1 -0
  36. package/dist/protocol/compression.d.ts +23 -0
  37. package/dist/protocol/compression.d.ts.map +1 -0
  38. package/dist/protocol/compression.js +85 -0
  39. package/dist/protocol/compression.js.map +1 -0
  40. package/dist/protocol/connection.d.ts +73 -0
  41. package/dist/protocol/connection.d.ts.map +1 -0
  42. package/dist/protocol/connection.js +212 -0
  43. package/dist/protocol/connection.js.map +1 -0
  44. package/dist/protocol/encryption.d.ts +29 -0
  45. package/dist/protocol/encryption.d.ts.map +1 -0
  46. package/dist/protocol/encryption.js +116 -0
  47. package/dist/protocol/encryption.js.map +1 -0
  48. package/dist/protocol/packet.d.ts +75 -0
  49. package/dist/protocol/packet.d.ts.map +1 -0
  50. package/dist/protocol/packet.js +140 -0
  51. package/dist/protocol/packet.js.map +1 -0
  52. package/dist/protocol/states/handshake.d.ts +19 -0
  53. package/dist/protocol/states/handshake.d.ts.map +1 -0
  54. package/dist/protocol/states/handshake.js +32 -0
  55. package/dist/protocol/states/handshake.js.map +1 -0
  56. package/dist/protocol/states/login.d.ts +77 -0
  57. package/dist/protocol/states/login.d.ts.map +1 -0
  58. package/dist/protocol/states/login.js +125 -0
  59. package/dist/protocol/states/login.js.map +1 -0
  60. package/dist/protocol/states/play.d.ts +187 -0
  61. package/dist/protocol/states/play.d.ts.map +1 -0
  62. package/dist/protocol/states/play.js +316 -0
  63. package/dist/protocol/states/play.js.map +1 -0
  64. package/dist/protocol/types.d.ts +210 -0
  65. package/dist/protocol/types.d.ts.map +1 -0
  66. package/dist/protocol/types.js +495 -0
  67. package/dist/protocol/types.js.map +1 -0
  68. package/dist/types.d.ts +36 -0
  69. package/dist/types.d.ts.map +1 -0
  70. package/dist/types.js +6 -0
  71. package/dist/types.js.map +1 -0
  72. package/dist/utils/events.d.ts +23 -0
  73. package/dist/utils/events.d.ts.map +1 -0
  74. package/dist/utils/events.js +44 -0
  75. package/dist/utils/events.js.map +1 -0
  76. package/dist/utils/logger.d.ts +19 -0
  77. package/dist/utils/logger.d.ts.map +1 -0
  78. package/dist/utils/logger.js +47 -0
  79. package/dist/utils/logger.js.map +1 -0
  80. package/dist/utils/vec3.d.ts +25 -0
  81. package/dist/utils/vec3.d.ts.map +1 -0
  82. package/dist/utils/vec3.js +66 -0
  83. package/dist/utils/vec3.js.map +1 -0
  84. package/dist/world/block.d.ts +39 -0
  85. package/dist/world/block.d.ts.map +1 -0
  86. package/dist/world/block.js +84 -0
  87. package/dist/world/block.js.map +1 -0
  88. package/dist/world/world.d.ts +55 -0
  89. package/dist/world/world.d.ts.map +1 -0
  90. package/dist/world/world.js +95 -0
  91. package/dist/world/world.js.map +1 -0
  92. package/docs/README.md +29 -0
  93. package/docs/api/auth.md +210 -0
  94. package/docs/api/bot.md +137 -0
  95. package/docs/api/events.md +166 -0
  96. package/docs/api/plugins.md +207 -0
  97. package/docs/api/protocol.md +129 -0
  98. package/docs/api/world.md +138 -0
  99. package/docs/first-bot.md +114 -0
  100. package/docs/getting-started.md +103 -0
  101. package/docs/guides/architecture.md +122 -0
  102. package/docs/guides/custom-plugins.md +211 -0
  103. package/docs/guides/raw-packets.md +80 -0
  104. package/package.json +55 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026
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,174 @@
1
+ # SpecProtocol
2
+
3
+ A **Minecraft bot framework** built from scratch in TypeScript — a Mineflayer alternative with full protocol support for **Java Edition 1.21.4** (Protocol 769).
4
+
5
+ ```bash
6
+ npm install specprotocol
7
+ ```
8
+
9
+ ## ✨ Features
10
+
11
+ - 🔌 **From-scratch protocol** — No dependency on `node-minecraft-protocol`
12
+ - 🔐 **Auth support** — Offline (cracked) & Microsoft (Device Code Flow)
13
+ - 🗜️ **Compression & Encryption** — Zlib + AES/CFB8 fully implemented
14
+ - 🌍 **World management** — Chunk sections, block access by coordinates
15
+ - 👾 **Entity tracking** — Spawn, remove, find nearest, spatial queries
16
+ - 🧩 **Plugin system** — Built-in chat & combat + custom plugin API
17
+ - 📦 **TypeScript-first** — Full type safety with typed events
18
+
19
+ ## 🚀 Quick Start
20
+
21
+ ```typescript
22
+ import { createBot } from 'specprotocol';
23
+
24
+ const bot = await createBot({
25
+ host: 'localhost',
26
+ port: 25565,
27
+ username: 'MyBot',
28
+ auth: 'offline', // or 'microsoft'
29
+ });
30
+
31
+ bot.on('spawn', () => {
32
+ console.log(`Spawned at ${bot.position}`);
33
+ bot.chat('Hello from SpecProtocol! 🤖');
34
+ });
35
+
36
+ bot.on('chat', (message) => {
37
+ console.log(`Chat: ${message}`);
38
+ });
39
+
40
+ bot.on('health', (health, food) => {
41
+ console.log(`Health: ${health}/20 | Food: ${food}/20`);
42
+ });
43
+ ```
44
+
45
+ ## 📖 API
46
+
47
+ ### `createBot(options)`
48
+
49
+ | Option | Type | Default | Description |
50
+ |--------|------|---------|-------------|
51
+ | `host` | `string` | required | Server hostname |
52
+ | `port` | `number` | `25565` | Server port |
53
+ | `username` | `string` | required | Bot username |
54
+ | `auth` | `'offline' \| 'microsoft'` | `'offline'` | Authentication mode |
55
+ | `viewDistance` | `number` | `10` | Requested view distance |
56
+ | `logLevel` | `LogLevel` | `INFO` | Logging verbosity |
57
+ | `plugins` | `Plugin[]` | `[]` | Custom plugins to load |
58
+
59
+ ### Bot Events
60
+
61
+ | Event | Payload | Description |
62
+ |-------|---------|-------------|
63
+ | `spawn` | — | Bot spawned in world |
64
+ | `chat` | `(message, isOverlay)` | Chat message received |
65
+ | `health` | `(health, food, saturation)` | Health updated |
66
+ | `death` | — | Bot died |
67
+ | `position` | `(Vec3)` | Position updated by server |
68
+ | `kicked` | `(reason)` | Kicked from server |
69
+ | `entitySpawn` | `(Entity)` | Entity spawned nearby |
70
+ | `entityRemove` | `(entityId)` | Entity removed |
71
+ | `blockUpdate` | `(x, y, z, stateId)` | Block changed |
72
+ | `error` | `(Error)` | Connection error |
73
+ | `end` | — | Disconnected |
74
+
75
+ ### Bot Methods
76
+
77
+ ```typescript
78
+ bot.chat('Hello!') // Send chat message
79
+ bot.attack(entity) // Attack an entity
80
+ bot.setPosition(x, y, z) // Move to position
81
+ bot.lookAt(new Vec3(x, y, z)) // Look at coordinates
82
+ bot.dig(x, y, z) // Break a block
83
+ bot.setHeldItem(slot) // Select hotbar slot (0-8)
84
+ bot.disconnect() // Disconnect from server
85
+ ```
86
+
87
+ ## 🧩 Custom Plugins
88
+
89
+ ```typescript
90
+ import { createBot, type Plugin, type BotAPI } from 'specprotocol';
91
+
92
+ class MyPlugin implements Plugin {
93
+ name = 'my-plugin';
94
+
95
+ initialize(bot: BotAPI): void {
96
+ bot.on('spawn', () => {
97
+ console.log('Bot spawned!');
98
+ });
99
+ }
100
+
101
+ destroy(): void {
102
+ // Cleanup
103
+ }
104
+ }
105
+
106
+ const bot = await createBot({
107
+ host: 'localhost',
108
+ username: 'Bot',
109
+ plugins: [new MyPlugin()],
110
+ });
111
+ ```
112
+
113
+ ## 🛠️ Low-Level Access
114
+
115
+ ```typescript
116
+ import { Connection, BufferReader, BufferWriter, PROTOCOL_VERSION } from 'specprotocol';
117
+
118
+ // Direct packet access
119
+ bot.on('rawPacket', (packet) => {
120
+ console.log(`Packet 0x${packet.id.toString(16)}: ${packet.data.length} bytes`);
121
+ });
122
+
123
+ // Send raw packets
124
+ const writer = new BufferWriter();
125
+ writer.writeVarInt(42);
126
+ writer.writeString('hello');
127
+ bot.sendPacket(0x06, writer.toBuffer());
128
+ ```
129
+
130
+ ## 📂 Architecture
131
+
132
+ ```
133
+ specprotocol/
134
+ ├── src/
135
+ │ ├── index.ts # Public API exports
136
+ │ ├── bot.ts # Main Bot orchestrator
137
+ │ ├── types.ts # Shared types (BotAPI)
138
+ │ ├── auth/
139
+ │ │ ├── offline.ts # Offline auth & UUID generation
140
+ │ │ └── microsoft.ts # Microsoft OAuth (Device Code Flow)
141
+ │ ├── protocol/
142
+ │ │ ├── types.ts # VarInt, VarLong, BufferReader/Writer
143
+ │ │ ├── packet.ts # Packet framing, splitting, registry
144
+ │ │ ├── connection.ts # TCP connection manager
145
+ │ │ ├── compression.ts # Zlib compression
146
+ │ │ ├── encryption.ts # AES/CFB8 encryption
147
+ │ │ └── states/
148
+ │ │ ├── handshake.ts
149
+ │ │ ├── login.ts
150
+ │ │ └── play.ts
151
+ │ ├── entity/
152
+ │ │ └── entity.ts # Entity, PlayerEntity, EntityManager
153
+ │ ├── world/
154
+ │ │ ├── block.ts # ChunkSection, ChunkColumn
155
+ │ │ └── world.ts # World manager
156
+ │ ├── plugins/
157
+ │ │ ├── plugin-manager.ts
158
+ │ │ └── built-in/
159
+ │ │ ├── chat.ts
160
+ │ │ └── combat.ts
161
+ │ └── utils/
162
+ │ ├── vec3.ts # 3D vector class
163
+ │ ├── logger.ts # Leveled logger
164
+ │ └── events.ts # Typed event emitter
165
+ ```
166
+
167
+ ## ⚙️ Requirements
168
+
169
+ - **Node.js** ≥ 18
170
+ - **Minecraft Java Edition** 1.21.4 (Protocol 769)
171
+
172
+ ## 📄 License
173
+
174
+ MIT
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * SpecProtocol CLI — Start a bot directly from the terminal.
5
+ *
6
+ * After `npm install specprotocol`, just run:
7
+ * specprotocol
8
+ *
9
+ * Or with arguments:
10
+ * specprotocol --host localhost --port 25565 --username MyBot
11
+ */
12
+
13
+ const { createBot } = require('../dist/index.js');
14
+ const readline = require('readline');
15
+
16
+ const args = process.argv.slice(2);
17
+
18
+ function getArg(name) {
19
+ const idx = args.indexOf(`--${name}`);
20
+ if (idx !== -1 && args[idx + 1]) return args[idx + 1];
21
+ return null;
22
+ }
23
+
24
+ function ask(question) {
25
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
26
+ return new Promise((resolve) => {
27
+ rl.question(question, (answer) => {
28
+ rl.close();
29
+ resolve(answer);
30
+ });
31
+ });
32
+ }
33
+
34
+ async function main() {
35
+ console.log('');
36
+ console.log(' ╔═══════════════════════════════════╗');
37
+ console.log(' ║ 🎮 SpecProtocol v1.0 ║');
38
+ console.log(' ║ Minecraft Bot Framework (1.21.4) ║');
39
+ console.log(' ╚═══════════════════════════════════╝');
40
+ console.log('');
41
+
42
+ // Get config from args or ask interactively
43
+ const host = getArg('host') || await ask(' Sunucu adresi (localhost): ') || 'localhost';
44
+ const port = parseInt(getArg('port') || await ask(' Port (25565): ') || '25565');
45
+ const username = getArg('username') || await ask(' Bot adı (SpecBot): ') || 'SpecBot';
46
+ const auth = getArg('auth') || 'offline';
47
+
48
+ console.log('');
49
+ console.log(` → ${host}:${port} adresine "${username}" olarak bağlanılıyor...`);
50
+ console.log('');
51
+
52
+ try {
53
+ const bot = await createBot({
54
+ host,
55
+ port,
56
+ username,
57
+ auth,
58
+ });
59
+
60
+ bot.on('spawn', () => {
61
+ console.log(` ✅ Dünyada doğuldu! Pozisyon: ${bot.position}`);
62
+ console.log('');
63
+ console.log(' Komutlar:');
64
+ console.log(' say <mesaj> — Chat mesajı gönder');
65
+ console.log(' pos — Pozisyonu göster');
66
+ console.log(' health — Sağlık bilgisi');
67
+ console.log(' quit — Çıkış');
68
+ console.log('');
69
+ startRepl(bot);
70
+ });
71
+
72
+ bot.on('chat', (message, isOverlay) => {
73
+ if (!isOverlay) {
74
+ console.log(` 💬 ${message}`);
75
+ }
76
+ });
77
+
78
+ bot.on('health', (health, food) => {
79
+ if (health <= 0) console.log(' 💀 Bot öldü!');
80
+ });
81
+
82
+ bot.on('kicked', (reason) => {
83
+ console.log(` 🚫 Sunucudan atıldı: ${reason}`);
84
+ process.exit(1);
85
+ });
86
+
87
+ bot.on('error', (err) => {
88
+ console.error(` ❌ Hata: ${err.message}`);
89
+ });
90
+
91
+ bot.on('end', () => {
92
+ console.log(' 🔌 Bağlantı kesildi');
93
+ process.exit(0);
94
+ });
95
+
96
+ } catch (err) {
97
+ console.error(` ❌ Bağlantı kurulamadı: ${err.message}`);
98
+ process.exit(1);
99
+ }
100
+ }
101
+
102
+ function startRepl(bot) {
103
+ const rl = readline.createInterface({
104
+ input: process.stdin,
105
+ output: process.stdout,
106
+ prompt: ' > ',
107
+ });
108
+
109
+ rl.prompt();
110
+
111
+ rl.on('line', (line) => {
112
+ const input = line.trim();
113
+
114
+ if (input.startsWith('say ')) {
115
+ bot.chat(input.substring(4));
116
+ } else if (input === 'pos') {
117
+ console.log(` 📍 ${bot.position}`);
118
+ } else if (input === 'health') {
119
+ console.log(` ❤️ Can: ${bot.health}/20 | 🍖 Açlık: ${bot.food}/20`);
120
+ } else if (input === 'quit' || input === 'exit') {
121
+ bot.disconnect();
122
+ process.exit(0);
123
+ } else if (input) {
124
+ console.log(' Bilinmeyen komut. Komutlar: say, pos, health, quit');
125
+ }
126
+
127
+ rl.prompt();
128
+ });
129
+
130
+ rl.on('close', () => {
131
+ bot.disconnect();
132
+ process.exit(0);
133
+ });
134
+ }
135
+
136
+ main();
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Microsoft Authentication for Minecraft Java Edition.
3
+ *
4
+ * Auth chain: Microsoft OAuth2 → Xbox Live → XSTS → Minecraft Services
5
+ *
6
+ * This implements the Device Code Flow (user opens a browser to authenticate).
7
+ */
8
+ export interface MicrosoftAuthResult {
9
+ accessToken: string;
10
+ username: string;
11
+ uuid: string;
12
+ }
13
+ /**
14
+ * Authenticate using Microsoft Device Code Flow.
15
+ * Returns a callback with the device code info, and a promise that resolves to the auth result.
16
+ */
17
+ export declare function authenticateMicrosoft(onDeviceCode: (userCode: string, verificationUri: string) => void): Promise<MicrosoftAuthResult>;
18
+ /**
19
+ * Join a server (session server authentication).
20
+ * Called after encrypting the shared secret, before sending Encryption Response.
21
+ */
22
+ export declare function joinServer(accessToken: string, selectedProfile: string, serverHash: string): Promise<void>;
23
+ //# sourceMappingURL=microsoft.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"microsoft.d.ts","sourceRoot":"","sources":["../../src/auth/microsoft.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,mBAAmB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CAChB;AAwCD;;;GAGG;AACH,wBAAsB,qBAAqB,CACvC,YAAY,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,KAAK,IAAI,GAClE,OAAO,CAAC,mBAAmB,CAAC,CA0B9B;AA6HD;;;GAGG;AACH,wBAAsB,UAAU,CAC5B,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,EACvB,UAAU,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CAef"}
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ /**
3
+ * Microsoft Authentication for Minecraft Java Edition.
4
+ *
5
+ * Auth chain: Microsoft OAuth2 → Xbox Live → XSTS → Minecraft Services
6
+ *
7
+ * This implements the Device Code Flow (user opens a browser to authenticate).
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.authenticateMicrosoft = authenticateMicrosoft;
11
+ exports.joinServer = joinServer;
12
+ // Microsoft Azure App Client ID for Minecraft
13
+ const CLIENT_ID = '00000000402b5328';
14
+ const AUTHORITY = 'https://login.live.com';
15
+ /**
16
+ * Authenticate using Microsoft Device Code Flow.
17
+ * Returns a callback with the device code info, and a promise that resolves to the auth result.
18
+ */
19
+ async function authenticateMicrosoft(onDeviceCode) {
20
+ // Step 1: Get Device Code
21
+ const deviceCode = await requestDeviceCode();
22
+ onDeviceCode(deviceCode.user_code, deviceCode.verification_uri);
23
+ // Step 2: Poll for Microsoft Token
24
+ const msToken = await pollForToken(deviceCode);
25
+ // Step 3: Xbox Live Auth
26
+ const xboxToken = await authenticateXboxLive(msToken.access_token);
27
+ // Step 4: XSTS Token
28
+ const xstsToken = await authenticateXSTS(xboxToken.Token);
29
+ // Step 5: Minecraft Auth
30
+ const uhs = xstsToken.DisplayClaims.xui[0].uhs;
31
+ const mcAuth = await authenticateMinecraft(uhs, xstsToken.Token);
32
+ // Step 6: Get Minecraft Profile
33
+ const profile = await getMinecraftProfile(mcAuth.access_token);
34
+ return {
35
+ accessToken: mcAuth.access_token,
36
+ username: profile.name,
37
+ uuid: formatUUID(profile.id),
38
+ };
39
+ }
40
+ async function requestDeviceCode() {
41
+ const response = await fetch(`${AUTHORITY}/oauth20_connect.srf`, {
42
+ method: 'POST',
43
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
44
+ body: new URLSearchParams({
45
+ client_id: CLIENT_ID,
46
+ scope: 'XboxLive.signin offline_access',
47
+ response_type: 'device_code',
48
+ }),
49
+ });
50
+ if (!response.ok)
51
+ throw new Error(`Device code request failed: ${response.status}`);
52
+ return response.json();
53
+ }
54
+ async function pollForToken(deviceCode) {
55
+ const intervalMs = (deviceCode.interval || 5) * 1000;
56
+ const expiresAt = Date.now() + deviceCode.expires_in * 1000;
57
+ while (Date.now() < expiresAt) {
58
+ await sleep(intervalMs);
59
+ const response = await fetch(`${AUTHORITY}/oauth20_token.srf`, {
60
+ method: 'POST',
61
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
62
+ body: new URLSearchParams({
63
+ client_id: CLIENT_ID,
64
+ grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
65
+ device_code: deviceCode.device_code,
66
+ }),
67
+ });
68
+ const data = await response.json();
69
+ if (data.error === 'authorization_pending') {
70
+ continue;
71
+ }
72
+ if (data.error) {
73
+ throw new Error(`Token polling error: ${data.error} — ${data.error_description}`);
74
+ }
75
+ return data;
76
+ }
77
+ throw new Error('Device code expired');
78
+ }
79
+ async function authenticateXboxLive(msAccessToken) {
80
+ const response = await fetch('https://user.auth.xboxlive.com/user/authenticate', {
81
+ method: 'POST',
82
+ headers: {
83
+ 'Content-Type': 'application/json',
84
+ 'Accept': 'application/json',
85
+ },
86
+ body: JSON.stringify({
87
+ Properties: {
88
+ AuthMethod: 'RPS',
89
+ SiteName: 'user.auth.xboxlive.com',
90
+ RpsTicket: `d=${msAccessToken}`,
91
+ },
92
+ RelyingParty: 'http://auth.xboxlive.com',
93
+ TokenType: 'JWT',
94
+ }),
95
+ });
96
+ if (!response.ok)
97
+ throw new Error(`Xbox Live auth failed: ${response.status}`);
98
+ return response.json();
99
+ }
100
+ async function authenticateXSTS(xboxToken) {
101
+ const response = await fetch('https://xsts.auth.xboxlive.com/xsts/authorize', {
102
+ method: 'POST',
103
+ headers: {
104
+ 'Content-Type': 'application/json',
105
+ 'Accept': 'application/json',
106
+ },
107
+ body: JSON.stringify({
108
+ Properties: {
109
+ SandboxId: 'RETAIL',
110
+ UserTokens: [xboxToken],
111
+ },
112
+ RelyingParty: 'rp://api.minecraftservices.com/',
113
+ TokenType: 'JWT',
114
+ }),
115
+ });
116
+ if (!response.ok)
117
+ throw new Error(`XSTS auth failed: ${response.status}`);
118
+ return response.json();
119
+ }
120
+ async function authenticateMinecraft(uhs, xstsToken) {
121
+ const response = await fetch('https://api.minecraftservices.com/authentication/login_with_xbox', {
122
+ method: 'POST',
123
+ headers: { 'Content-Type': 'application/json' },
124
+ body: JSON.stringify({
125
+ identityToken: `XBL3.0 x=${uhs};${xstsToken}`,
126
+ }),
127
+ });
128
+ if (!response.ok)
129
+ throw new Error(`Minecraft auth failed: ${response.status}`);
130
+ return response.json();
131
+ }
132
+ async function getMinecraftProfile(accessToken) {
133
+ const response = await fetch('https://api.minecraftservices.com/minecraft/profile', {
134
+ headers: {
135
+ Authorization: `Bearer ${accessToken}`,
136
+ },
137
+ });
138
+ if (!response.ok)
139
+ throw new Error(`Failed to get Minecraft profile: ${response.status}`);
140
+ return response.json();
141
+ }
142
+ function formatUUID(hex) {
143
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
144
+ }
145
+ function sleep(ms) {
146
+ return new Promise(resolve => setTimeout(resolve, ms));
147
+ }
148
+ /**
149
+ * Join a server (session server authentication).
150
+ * Called after encrypting the shared secret, before sending Encryption Response.
151
+ */
152
+ async function joinServer(accessToken, selectedProfile, serverHash) {
153
+ const response = await fetch('https://sessionserver.mojang.com/session/minecraft/join', {
154
+ method: 'POST',
155
+ headers: { 'Content-Type': 'application/json' },
156
+ body: JSON.stringify({
157
+ accessToken,
158
+ selectedProfile: selectedProfile.replace(/-/g, ''),
159
+ serverId: serverHash,
160
+ }),
161
+ });
162
+ if (response.status !== 204 && !response.ok) {
163
+ const errorText = await response.text();
164
+ throw new Error(`Failed to join server session: ${response.status} — ${errorText}`);
165
+ }
166
+ }
167
+ //# sourceMappingURL=microsoft.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"microsoft.js","sourceRoot":"","sources":["../../src/auth/microsoft.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Offline Authentication — for cracked/offline mode servers.
3
+ *
4
+ * In offline mode, no external auth is needed.
5
+ * The client just provides a username and generates an offline UUID.
6
+ */
7
+ export interface OfflineProfile {
8
+ username: string;
9
+ uuid: string;
10
+ }
11
+ /**
12
+ * Generate an offline UUID from a username.
13
+ * Minecraft uses "OfflinePlayer:<username>" hashed with MD5, then sets version/variant bits.
14
+ */
15
+ export declare function offlineUUID(username: string): string;
16
+ /**
17
+ * Create an offline profile from a username.
18
+ */
19
+ export declare function createOfflineProfile(username: string): OfflineProfile;
20
+ //# sourceMappingURL=offline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"offline.d.ts","sourceRoot":"","sources":["../../src/auth/offline.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,WAAW,cAAc;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAUpD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,CAKrE"}
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ /**
3
+ * Offline Authentication — for cracked/offline mode servers.
4
+ *
5
+ * In offline mode, no external auth is needed.
6
+ * The client just provides a username and generates an offline UUID.
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.offlineUUID = offlineUUID;
43
+ exports.createOfflineProfile = createOfflineProfile;
44
+ const crypto = __importStar(require("crypto"));
45
+ /**
46
+ * Generate an offline UUID from a username.
47
+ * Minecraft uses "OfflinePlayer:<username>" hashed with MD5, then sets version/variant bits.
48
+ */
49
+ function offlineUUID(username) {
50
+ const md5 = crypto.createHash('md5').update(`OfflinePlayer:${username}`).digest();
51
+ // Set version to 3 (name-based MD5)
52
+ md5[6] = (md5[6] & 0x0F) | 0x30;
53
+ // Set variant to IETF
54
+ md5[8] = (md5[8] & 0x3F) | 0x80;
55
+ const hex = md5.toString('hex');
56
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
57
+ }
58
+ /**
59
+ * Create an offline profile from a username.
60
+ */
61
+ function createOfflineProfile(username) {
62
+ return {
63
+ username,
64
+ uuid: offlineUUID(username),
65
+ };
66
+ }
67
+ //# sourceMappingURL=offline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"offline.js","sourceRoot":"","sources":["../../src/auth/offline.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAaH,kCAUC;AAKD,oDAKC;AA/BD,+CAAiC;AAOjC;;;GAGG;AACH,SAAgB,WAAW,CAAC,QAAgB;IACxC,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,iBAAiB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;IAElF,oCAAoC;IACpC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IACjC,sBAAsB;IACtB,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAEjC,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChC,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;AAC/G,CAAC;AAED;;GAEG;AACH,SAAgB,oBAAoB,CAAC,QAAgB;IACjD,OAAO;QACH,QAAQ;QACR,IAAI,EAAE,WAAW,CAAC,QAAQ,CAAC;KAC9B,CAAC;AACN,CAAC"}