bonktools 1.0.2 โ†’ 2.0.1

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/README.md CHANGED
@@ -1,18 +1,24 @@
1
- # ๐Ÿค– BonkTools
1
+ # ๐ŸŽฎ BonkTools v2.0
2
2
 
3
- A powerful **Node.js + TypeScript** library to create **automated bots for [Bonk.io](https://bonk.io)** โ€” with full event handling, room control, chat management, and in-game automation.
3
+ [![npm version](https://img.shields.io/npm/v/bonktools.svg)](https://www.npmjs.com/package/bonktools)
4
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.3-blue.svg)](https://www.typescriptlang.org/)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
6
 
5
- ---
7
+ > Advanced Bonk.io bot library with physics simulation and game state management
6
8
 
7
- ## ๐Ÿš€ Features
9
+ BonkTools is a powerful TypeScript library for creating automated bots for Bonk.io. Unlike other libraries, BonkTools includes a **Box2D physics simulator** that allows you to detect game events like player deaths, round endings, and collisions in real-time.
8
10
 
9
- โœ… Automatic connection to Bonk.io servers
10
- โœ… Supports chat, players, teams, and game state
11
- โœ… Fully typed with **TypeScript**
12
- โœ… Clean, modular structure
13
- โœ… Detailed debug logs (`[DEBUG] [BONKTOOLS] ...`)
11
+ ## โœจ Features
14
12
 
15
- ---
13
+ - ๐Ÿ”Œ **WebSocket Connection Management** - Stable connection with automatic reconnection
14
+ - โšก **Box2D Physics Simulation** - Replicate game physics locally to detect events
15
+ - ๐ŸŽฏ **Game State Tracking** - Full awareness of game state (rounds, scores, players)
16
+ - ๐ŸŽญ **Event-Driven Architecture** - React to any game event with TypeScript events
17
+ - ๐Ÿ› ๏ธ **Room Management** - Create, join, and manage rooms programmatically
18
+ - ๐Ÿ‘ฅ **Player Management** - Track all players, their states, and positions
19
+ - ๐ŸŽช **Host Controls** - Start/stop games, kick players, change settings
20
+ - ๐Ÿ“ **TypeScript Native** - Full type safety and IntelliSense support
21
+ - ๐Ÿงช **Tested & Reliable** - Built on proven Bonkbot foundation
16
22
 
17
23
  ## ๐Ÿ“ฆ Installation
18
24
 
@@ -20,6 +26,526 @@ A powerful **Node.js + TypeScript** library to create **automated bots for [Bonk
20
26
  npm install bonktools
21
27
  ```
22
28
 
29
+ ## ๐Ÿš€ Quick Start
30
+
31
+ ### Simple Bot Example
32
+
33
+ ```typescript
34
+ import { createBot } from 'bonktools';
35
+
36
+ // Create bot
37
+ const bot = createBot({
38
+ account: {
39
+ username: 'MyBot',
40
+ guest: true
41
+ },
42
+ logLevel: 'info'
43
+ });
44
+
45
+ // Initialize and connect
46
+ await bot.init();
47
+ await bot.connect();
48
+
49
+ // Join a room
50
+ await bot.joinRoomByUrl('https://bonk.io/123456');
51
+
52
+ // Send a message
53
+ await bot.chat('Hello from BonkTools! ๐ŸŽฎ');
54
+
55
+ // Listen for events
56
+ bot.on('chatMessage', (player, message) => {
57
+ console.log(`${player.username}: ${message}`);
58
+ });
59
+ ```
60
+
61
+ ### Host Bot Example
62
+
63
+ ```typescript
64
+ import { createBot } from 'bonktools';
65
+
66
+ const bot = createBot({
67
+ account: {
68
+ username: 'HostBot',
69
+ guest: true
70
+ }
71
+ });
72
+
73
+ await bot.init();
74
+ await bot.connect();
75
+
76
+ // Create a room
77
+ const room = await bot.createRoom({
78
+ roomName: 'My Tournament Room',
79
+ maxPlayers: 4,
80
+ mode: 'classic'
81
+ });
82
+
83
+ console.log('Room created:', room.shareLink);
84
+
85
+ // Detect when round ends (using physics simulation!)
86
+ bot.on('roundEnd', ({ winner, scores }) => {
87
+ console.log(`Winner: ${winner.username}`);
88
+ console.log('Scores:', scores);
89
+
90
+ // Auto-restart in 3 seconds
91
+ setTimeout(() => bot.startGame(), 3000);
92
+ });
93
+
94
+ // Detect player deaths
95
+ bot.on('playerDeath', (player, position) => {
96
+ console.log(`${player.username} died at (${position.x}, ${position.y})`);
97
+ });
98
+
99
+ // Start when all ready
100
+ bot.on('allPlayersReady', () => {
101
+ bot.startGame();
102
+ });
103
+ ```
104
+
105
+ ## ๐Ÿ“š API Reference
106
+
107
+ ### Core Methods
108
+
109
+ #### `init(): Promise<BonkTools>`
110
+ Initialize the bot (get auth token, server info)
111
+
112
+ #### `connect(): Promise<BonkTools>`
113
+ Connect to Bonk.io server
114
+
115
+ #### `disconnect(): void`
116
+ Disconnect from server
117
+
118
+ ### Room Management
119
+
120
+ #### `createRoom(options: RoomOptions): Promise<RoomInfo>`
121
+ Create a new room
122
+
123
+ ```typescript
124
+ const room = await bot.createRoom({
125
+ roomName: 'My Room',
126
+ maxPlayers: 4,
127
+ password: 'secret',
128
+ mode: 'classic',
129
+ hidden: false
130
+ });
131
+ ```
132
+
133
+ #### `joinRoom(address: string, password?: string): Promise<void>`
134
+ Join room by address code
135
+
136
+ ```typescript
137
+ await bot.joinRoom('123456', 'password');
138
+ ```
139
+
140
+ #### `joinRoomByUrl(url: string): Promise<void>`
141
+ Join room by full URL
142
+
143
+ ```typescript
144
+ await bot.joinRoomByUrl('https://bonk.io/123456');
145
+ ```
146
+
147
+ #### `leaveRoom(): Promise<void>`
148
+ Leave current room
149
+
150
+ ### Game Control
151
+
152
+ #### `startGame(): Promise<void>`
153
+ Start the game (host only)
154
+
155
+ #### `stopGame(): Promise<void>`
156
+ Stop/abort current game (host only)
157
+
158
+ #### `setRounds(rounds: number): Promise<void>`
159
+ Set number of rounds to win (1-999)
160
+
161
+ ```typescript
162
+ await bot.setRounds(5);
163
+ ```
164
+
165
+ #### `setReady(ready: boolean): Promise<void>`
166
+ Set bot ready status
167
+
168
+ ```typescript
169
+ await bot.setReady(true);
170
+ ```
171
+
172
+ ### Player Management
173
+
174
+ #### `getPlayer(id: number): PlayerData | null`
175
+ Get player by ID
176
+
177
+ #### `getPlayerByUsername(username: string, guest?: boolean): PlayerData | null`
178
+ Get player by username
179
+
180
+ #### `getAllPlayers(): PlayerData[]`
181
+ Get all players in room
182
+
183
+ #### `getHost(): PlayerData | null`
184
+ Get current host player
185
+
186
+ #### `isHost(): boolean`
187
+ Check if bot is host
188
+
189
+ #### `kickPlayer(playerId: number): Promise<void>`
190
+ Kick a player (host only)
191
+
192
+ #### `giveHost(playerId: number): Promise<void>`
193
+ Transfer host to another player (host only)
194
+
195
+ #### `joinTeam(team: number): Promise<void>`
196
+ Join a team (0=spectate, 1=FFA, 2-6=teams)
197
+
198
+ #### `lockTeams(locked: boolean): Promise<void>`
199
+ Lock/unlock teams (host only)
200
+
201
+ ### Chat
202
+
203
+ #### `chat(message: string): Promise<void>`
204
+ Send a chat message (max 200 chars)
205
+
206
+ ```typescript
207
+ await bot.chat('Hello everyone! ๐Ÿ‘‹');
208
+ ```
209
+
210
+ ### Utility
211
+
212
+ #### `getShareLink(): string | null`
213
+ Get room share link
214
+
215
+ #### `getRoomInfo(): RoomInfo`
216
+ Get current room information
217
+
218
+ #### `getMyId(): number`
219
+ Get bot's player ID
220
+
221
+ #### `isReady(): boolean`
222
+ Check if bot is initialized
223
+
224
+ #### `isConnected(): boolean`
225
+ Check if bot is connected
226
+
227
+ #### `getGameState(): any`
228
+ Get current game state (if physics is running)
229
+
230
+ ## ๐ŸŽญ Events
231
+
232
+ BonkTools uses TypeScript's EventEmitter for type-safe events:
233
+
234
+ ### Connection Events
235
+
236
+ ```typescript
237
+ bot.on('ready', () => {
238
+ console.log('Bot initialized');
239
+ });
240
+
241
+ bot.on('connect', () => {
242
+ console.log('Connected to server');
243
+ });
244
+
245
+ bot.on('disconnect', (reason) => {
246
+ console.log('Disconnected:', reason);
247
+ });
248
+
249
+ bot.on('error', (error) => {
250
+ console.error('Error:', error);
251
+ });
252
+ ```
253
+
254
+ ### Room Events
255
+
256
+ ```typescript
257
+ bot.on('roomCreated', (room) => {
258
+ console.log('Room created:', room.shareLink);
259
+ });
260
+
261
+ bot.on('roomJoined', ({ game, room, players }) => {
262
+ console.log('Joined room:', room.name);
263
+ });
264
+ ```
265
+
266
+ ### Player Events
267
+
268
+ ```typescript
269
+ bot.on('playerJoin', (player) => {
270
+ console.log(`${player.username} joined`);
271
+ });
272
+
273
+ bot.on('playerLeave', (player) => {
274
+ console.log(`${player.username} left`);
275
+ });
276
+
277
+ bot.on('playerReady', (player, ready) => {
278
+ console.log(`${player.username} is ${ready ? 'ready' : 'not ready'}`);
279
+ });
280
+
281
+ bot.on('allPlayersReady', () => {
282
+ console.log('All players ready!');
283
+ });
284
+
285
+ bot.on('playerTeamChange', (player, team) => {
286
+ console.log(`${player.username} joined team ${team}`);
287
+ });
288
+
289
+ bot.on('playerKick', (player) => {
290
+ console.log(`${player.username} was kicked`);
291
+ });
292
+ ```
293
+
294
+ ### Game Events
295
+
296
+ ```typescript
297
+ bot.on('gameStart', () => {
298
+ console.log('Game started!');
299
+ });
300
+
301
+ bot.on('gameEnd', (result) => {
302
+ console.log('Game ended!');
303
+ console.log('Champion:', result.champion?.username);
304
+ });
305
+
306
+ bot.on('roundStart', (roundNumber) => {
307
+ console.log(`Round ${roundNumber} started`);
308
+ });
309
+
310
+ bot.on('roundEnd', (result) => {
311
+ console.log('Round ended!');
312
+ console.log('Winner:', result.winner?.username);
313
+ console.log('Scores:', result.scores);
314
+ console.log('Duration:', result.duration);
315
+ });
316
+
317
+ bot.on('countdown', (seconds) => {
318
+ console.log(`Starting in ${seconds}...`);
319
+ });
320
+ ```
321
+
322
+ ### Physics Events (โšก New!)
323
+
324
+ These events are powered by the Box2D physics simulator:
325
+
326
+ ```typescript
327
+ bot.on('playerDeath', (player, position) => {
328
+ console.log(`${player.username} died at (${position.x}, ${position.y})`);
329
+ });
330
+
331
+ bot.on('collision', (event) => {
332
+ console.log('Collision detected:', event.type);
333
+ console.log('Player:', event.playerId);
334
+ console.log('Position:', event.position);
335
+ });
336
+
337
+ bot.on('playerOutOfBounds', (player) => {
338
+ console.log(`${player.username} went out of bounds`);
339
+ });
340
+ ```
341
+
342
+ ### Chat Events
343
+
344
+ ```typescript
345
+ bot.on('chatMessage', (player, message) => {
346
+ console.log(`${player.username}: ${message}`);
347
+
348
+ // Respond to commands
349
+ if (message === '!help') {
350
+ bot.chat('Available commands: !help, !placar');
351
+ }
352
+ });
353
+ ```
354
+
355
+ ### Host Events
356
+
357
+ ```typescript
358
+ bot.on('hostTransfer', (oldHost, newHost) => {
359
+ console.log(`Host transferred from ${oldHost.username} to ${newHost.username}`);
360
+ });
361
+
362
+ bot.on('teamLockToggle', (locked) => {
363
+ console.log(`Teams ${locked ? 'locked' : 'unlocked'}`);
364
+ });
365
+
366
+ bot.on('roundsChange', (rounds) => {
367
+ console.log(`Rounds changed to ${rounds}`);
368
+ });
369
+
370
+ bot.on('gamemodeChange', (mode, engine) => {
371
+ console.log(`Mode changed to ${mode} (${engine})`);
372
+ });
373
+ ```
374
+
375
+ ### Map Events
376
+
377
+ ```typescript
378
+ bot.on('mapSwitch', (map) => {
379
+ console.log('Map changed:', map.m.n); // map name
380
+ });
381
+
382
+ bot.on('mapSuggest', ({ title, author, player }) => {
383
+ console.log(`${player.username} suggested map: ${title} by ${author}`);
384
+ });
385
+ ```
386
+
387
+ ## ๐ŸŽฏ Advanced Usage
388
+
389
+ ### Tournament Bot
390
+
391
+ ```typescript
392
+ import { createBot } from 'bonktools';
393
+
394
+ const bot = createBot({ /* ... */ });
395
+ await bot.init();
396
+ await bot.connect();
397
+
398
+ const room = await bot.createRoom({
399
+ roomName: '๐Ÿ† Tournament - Round 1',
400
+ maxPlayers: 8,
401
+ mode: 'arrows'
402
+ });
403
+
404
+ const scores = new Map<string, number>();
405
+ let matchCount = 0;
406
+ const maxMatches = 10;
407
+
408
+ bot.on('roundEnd', ({ winner }) => {
409
+ if (winner) {
410
+ scores.set(winner.username, (scores.get(winner.username) || 0) + 1);
411
+ }
412
+
413
+ matchCount++;
414
+
415
+ if (matchCount >= maxMatches) {
416
+ // Tournament ended
417
+ const champion = Array.from(scores.entries())
418
+ .sort((a, b) => b[1] - a[1])[0];
419
+
420
+ bot.chat(`๐Ÿ† Tournament Champion: ${champion[0]}!`);
421
+
422
+ // Show leaderboard
423
+ const leaderboard = Array.from(scores.entries())
424
+ .sort((a, b) => b[1] - a[1])
425
+ .map(([name, score], i) => `${i+1}. ${name}: ${score}`)
426
+ .join(' | ');
427
+
428
+ bot.chat(`๐Ÿ“Š Final: ${leaderboard}`);
429
+ } else {
430
+ // Next match
431
+ setTimeout(() => bot.startGame(), 5000);
432
+ }
433
+ });
434
+ ```
435
+
436
+ ### Custom Command System
437
+
438
+ ```typescript
439
+ const commands = {
440
+ '!help': () => bot.chat('Commands: !help, !score, !stats'),
441
+
442
+ '!score': () => {
443
+ const players = bot.getAllPlayers();
444
+ const scoreText = players
445
+ .map(p => `${p.username}: ${p.balance}`)
446
+ .join(' | ');
447
+ bot.chat(`๐Ÿ“Š ${scoreText}`);
448
+ },
449
+
450
+ '!stats': () => {
451
+ const players = bot.getAllPlayers();
452
+ bot.chat(`๐Ÿ‘ฅ Players: ${players.length}`);
453
+ bot.chat(`๐ŸŽฎ Round: ${currentRound}/${maxRounds}`);
454
+ }
455
+ };
456
+
457
+ bot.on('chatMessage', (player, message) => {
458
+ const command = commands[message.toLowerCase()];
459
+ if (command) {
460
+ command();
461
+ }
462
+ });
463
+ ```
464
+
465
+ ## ๐Ÿ”ง Configuration
466
+
467
+ ### BonkToolsOptions
468
+
469
+ ```typescript
470
+ interface BonkToolsOptions {
471
+ account: {
472
+ username: string;
473
+ password?: string; // For non-guest accounts
474
+ guest?: boolean; // Default: true
475
+ };
476
+ server?: string; // Default: auto-detect best server
477
+ avatar?: Avatar; // Custom avatar
478
+ logLevel?: LogLevel; // 'debug' | 'info' | 'warn' | 'error' | 'none'
479
+ protocolVersion?: number; // Default: 49
480
+ peerID?: string; // Custom peer ID (auto-generated if not provided)
481
+ }
482
+ ```
483
+
484
+ ### RoomOptions
485
+
486
+ ```typescript
487
+ interface RoomOptions {
488
+ roomName?: string;
489
+ maxPlayers?: number; // 1-8
490
+ password?: string;
491
+ hidden?: boolean;
492
+ quick?: boolean;
493
+ mode?: 'classic' | 'arrows' | 'grapple' | 'death arrows' | 'simple' | 'vtol';
494
+ minLevel?: number; // 0-999
495
+ maxLevel?: number; // 0-999
496
+ }
497
+ ```
498
+
499
+ ## ๐Ÿ—๏ธ Architecture
500
+
501
+ BonkTools is built on a modular architecture:
502
+
503
+ ```
504
+ BonkTools (Main API)
505
+ โ”œโ”€โ”€ BonkConnection (WebSocket layer)
506
+ โ”‚ โ”œโ”€โ”€ PacketParser
507
+ โ”‚ โ””โ”€โ”€ PacketBuilder
508
+ โ”œโ”€โ”€ PhysicsWorld (Box2D simulation)
509
+ โ”‚ โ”œโ”€โ”€ GameState
510
+ โ”‚ โ”œโ”€โ”€ CollisionDetector
511
+ โ”‚ โ””โ”€โ”€ InputProcessor
512
+ โ”œโ”€โ”€ GameLoop (60 FPS game loop)
513
+ โ”œโ”€โ”€ RoomManager
514
+ โ””โ”€โ”€ PlayerManager
515
+ ```
516
+
517
+ The key innovation is the **PhysicsWorld** module, which:
518
+ 1. Receives player inputs from the server
519
+ 2. Simulates the game physics using Box2D
520
+ 3. Detects collisions, deaths, and round endings
521
+ 4. Emits events for your bot to react to
522
+
523
+ This allows BonkTools to have awareness of the game state that's impossible with just WebSocket packets alone.
524
+
525
+ ## ๐Ÿค Contributing
526
+
527
+ Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) first.
528
+
529
+ ## ๐Ÿ“ License
530
+
531
+ MIT ยฉ OBL
532
+
533
+ ## ๐Ÿ™ Acknowledgments
534
+
535
+ - Built on [Bonkbot](https://github.com/PixelMelt/BonkBot) by PixelMelt
536
+ - Physics powered by [Box2D](https://box2d.org/)
537
+ - Inspired by the Brazilian Bonk.io community
538
+
539
+ ## ๐Ÿ“ž Support
540
+
541
+ - GitHub Issues: [github.com/brenoluizdev/bonktools/issues](https://github.com/brenoluizdev/bonktools/issues)
542
+ - Discord: [Join our Discord](https://discord.gg/dBVmaySqEk)
543
+
544
+ ---
545
+
546
+ Made with โค๏ธ for the Bonk.io community
547
+
548
+
23
549
  [![npm version](https://img.shields.io/npm/v/bonktools.svg?color=blue)](https://www.npmjs.com/package/bonktools)
24
550
  [![license](https://img.shields.io/github/license/brenoluizdev/bonktools.svg)](https://github.com/brenoluizdev/bonktools/blob/main/LICENSE)
25
551
  [![GitHub Repo stars](https://img.shields.io/github/stars/brenoluizdev/bonktools?style=social)](https://github.com/brenoluizdev/bonktools)