bonktools 2.0.0 โ 2.3.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/README.md +191 -480
- package/package.json +45 -63
- package/src/index.js +23 -0
- package/dist/connection/BonkConnection.d.ts +0 -173
- package/dist/connection/BonkConnection.js +0 -482
- package/dist/connection/PacketBuilder.d.ts +0 -13
- package/dist/connection/PacketBuilder.js +0 -25
- package/dist/connection/PacketParser.d.ts +0 -14
- package/dist/connection/PacketParser.js +0 -26
- package/dist/connection/types.d.ts +0 -0
- package/dist/connection/types.js +0 -1
- package/dist/game/GameLoop.d.ts +0 -0
- package/dist/game/GameLoop.js +0 -1
- package/dist/index.d.ts +0 -48
- package/dist/index.js +0 -73
- package/dist/simulator/GameState.d.ts +0 -0
- package/dist/simulator/GameState.js +0 -1
- package/dist/simulator/PhysicsWorld.d.ts +0 -0
- package/dist/simulator/PhysicsWorld.js +0 -1
- package/dist/types/events.d.ts +0 -0
- package/dist/types/events.js +0 -1
- package/dist/types/index.d.ts +0 -0
- package/dist/types/index.js +0 -1
- package/dist/utils/constants.d.ts +0 -175
- package/dist/utils/constants.js +0 -187
- package/dist/utils/logger.d.ts +0 -31
- package/dist/utils/logger.js +0 -133
- package/dist/utils/validation.d.ts +0 -5
- package/dist/utils/validation.js +0 -28
package/README.md
CHANGED
|
@@ -1,551 +1,262 @@
|
|
|
1
|
-
#
|
|
1
|
+
# BonkBot.js
|
|
2
2
|
|
|
3
|
-
[
|
|
4
|
-
[](https://www.typescriptlang.org/)
|
|
5
|
-
[](https://opensource.org/licenses/MIT)
|
|
3
|
+
BonkBot is a JavaScript library for creating bots for the web game [Bonk.io](https://bonk.io). It provides an easy way to create custom bots that can automate various actions within the game. With BonkBot, you can interact with the game's websocket protocol easily, chat with other players, and perform actions such as joining and leaving rooms.
|
|
6
4
|
|
|
7
|
-
|
|
5
|
+
### V4 Alpha, report any issues/bugs in the issues tab
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
### Newer NodeJS versions may encounter issues, node 18 and 16 are confirmed working
|
|
10
8
|
|
|
11
|
-
##
|
|
9
|
+
## Installation
|
|
12
10
|
|
|
13
|
-
|
|
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
|
|
22
|
-
|
|
23
|
-
## ๐ฆ Installation
|
|
11
|
+
To install BonkBot, you will need [Node.js](https://nodejs.org/en/download/) installed on your system. Then, run the following command in your terminal:
|
|
24
12
|
|
|
25
13
|
```bash
|
|
26
|
-
npm install
|
|
14
|
+
npm install bonkbot
|
|
27
15
|
```
|
|
28
16
|
|
|
29
|
-
##
|
|
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
|
-
});
|
|
17
|
+
## Features
|
|
44
18
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
19
|
+
- Connect to existing rooms or create new ones
|
|
20
|
+
- Automatically determine the optimal server using the game's API
|
|
21
|
+
- Send and receive chat messages
|
|
22
|
+
- Track players joining and leaving
|
|
23
|
+
- Manage teams and game settings
|
|
24
|
+
- Handle game events
|
|
25
|
+
- Comprehensive error handling
|
|
26
|
+
- Detailed logging
|
|
48
27
|
|
|
49
|
-
|
|
50
|
-
await bot.joinRoomByUrl('https://bonk.io/123456');
|
|
28
|
+
# Support
|
|
51
29
|
|
|
52
|
-
|
|
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
|
-
```
|
|
30
|
+
[Discord Server](https://discord.gg/USJQjwD7AY)
|
|
60
31
|
|
|
61
|
-
|
|
32
|
+
## Basic Usage
|
|
62
33
|
|
|
63
|
-
```
|
|
64
|
-
|
|
34
|
+
```javascript
|
|
35
|
+
const { createBot, LOG_LEVELS } = require('bonkbot');
|
|
65
36
|
|
|
37
|
+
// Create a bot instance
|
|
66
38
|
const bot = createBot({
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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');
|
|
39
|
+
account: {
|
|
40
|
+
username: 'BotName',
|
|
41
|
+
guest: true, // Use guest account
|
|
42
|
+
},
|
|
43
|
+
logLevel: LOG_LEVELS.WARN, // Set log level (DEBUG, INFO, WARN, ERROR, NONE)
|
|
239
44
|
});
|
|
240
45
|
|
|
241
|
-
|
|
242
|
-
|
|
46
|
+
// Initialize and handle events
|
|
47
|
+
bot.events.on('ready', async () => {
|
|
48
|
+
await bot.connect();
|
|
243
49
|
});
|
|
244
50
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
});
|
|
51
|
+
// Handle chat messages
|
|
52
|
+
bot.events.on('CHAT_MESSAGE', (message) => {
|
|
53
|
+
console.log(`${message.player.username}: ${message.message}`);
|
|
248
54
|
|
|
249
|
-
|
|
250
|
-
|
|
55
|
+
// Respond to !ping command
|
|
56
|
+
if (message.message === '!ping') {
|
|
57
|
+
bot.chat('Pong!');
|
|
58
|
+
}
|
|
251
59
|
});
|
|
252
|
-
```
|
|
253
60
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
```typescript
|
|
257
|
-
bot.on('roomCreated', (room) => {
|
|
258
|
-
console.log('Room created:', room.shareLink);
|
|
61
|
+
bot.events.on('PACKET', (packet) => {
|
|
62
|
+
bot.autoHandlePacket(packet);
|
|
259
63
|
});
|
|
260
64
|
|
|
261
|
-
bot.
|
|
262
|
-
console.log('Joined room:', room.name);
|
|
263
|
-
});
|
|
65
|
+
bot.init();
|
|
264
66
|
```
|
|
265
67
|
|
|
266
|
-
|
|
68
|
+
## Authentication Examples
|
|
267
69
|
|
|
268
|
-
|
|
269
|
-
bot.on('playerJoin', (player) => {
|
|
270
|
-
console.log(`${player.username} joined`);
|
|
271
|
-
});
|
|
70
|
+
### Automatic Server Detection
|
|
272
71
|
|
|
273
|
-
bot
|
|
274
|
-
console.log(`${player.username} left`);
|
|
275
|
-
});
|
|
72
|
+
By default, BonkBot will automatically determine the optimal server to connect to by querying the game's API. This ensures your bot connects to the most appropriate server based on the current game infrastructure.
|
|
276
73
|
|
|
277
|
-
|
|
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
|
-
});
|
|
74
|
+
If you want to override this behavior and connect to a specific server, you can provide the `server` option when creating the bot:
|
|
288
75
|
|
|
289
|
-
|
|
290
|
-
|
|
76
|
+
```javascript
|
|
77
|
+
const bot = createBot({
|
|
78
|
+
// ... other options
|
|
79
|
+
server: 'b2ny1', // Force connection to a specific server
|
|
291
80
|
});
|
|
292
81
|
```
|
|
293
82
|
|
|
294
|
-
###
|
|
295
|
-
|
|
296
|
-
```typescript
|
|
297
|
-
bot.on('gameStart', () => {
|
|
298
|
-
console.log('Game started!');
|
|
299
|
-
});
|
|
83
|
+
### Guest Account
|
|
300
84
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
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}...`);
|
|
85
|
+
```javascript
|
|
86
|
+
const bot = createBot({
|
|
87
|
+
account: {
|
|
88
|
+
username: 'BotName',
|
|
89
|
+
guest: true,
|
|
90
|
+
},
|
|
91
|
+
logLevel: LOG_LEVELS.WARN,
|
|
319
92
|
});
|
|
320
93
|
```
|
|
321
94
|
|
|
322
|
-
###
|
|
95
|
+
### User Account
|
|
323
96
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
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`);
|
|
97
|
+
```javascript
|
|
98
|
+
const bot = createBot({
|
|
99
|
+
account: {
|
|
100
|
+
username: 'YourUsername',
|
|
101
|
+
password: 'YourPassword',
|
|
102
|
+
guest: false,
|
|
103
|
+
},
|
|
104
|
+
logLevel: LOG_LEVELS.WARN,
|
|
339
105
|
});
|
|
340
106
|
```
|
|
341
107
|
|
|
342
|
-
|
|
108
|
+
## Connection Flow and Examples
|
|
343
109
|
|
|
344
|
-
|
|
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
|
-
```
|
|
110
|
+
The connection flow typically follows this sequence:
|
|
354
111
|
|
|
355
|
-
|
|
112
|
+
1. Bot initialization (`bot.init()`)
|
|
113
|
+
2. Ready event fires when login completes
|
|
114
|
+
3. Connect to game server (`bot.connect()`)
|
|
115
|
+
4. Find or create room
|
|
116
|
+
5. Join room or create room
|
|
117
|
+
6. Handle game events
|
|
356
118
|
|
|
357
|
-
|
|
358
|
-
bot.on('hostTransfer', (oldHost, newHost) => {
|
|
359
|
-
console.log(`Host transferred from ${oldHost.username} to ${newHost.username}`);
|
|
360
|
-
});
|
|
119
|
+
### Joining a Room by Name
|
|
361
120
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
121
|
+
```javascript
|
|
122
|
+
bot.events.on('ready', async () => {
|
|
123
|
+
try {
|
|
124
|
+
// Find room by name
|
|
125
|
+
const roomInfo = await bot.getAddressFromRoomName('roomName');
|
|
126
|
+
console.log(`Found room: ${roomInfo.roomname}`);
|
|
365
127
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
128
|
+
// Set address and connect
|
|
129
|
+
bot.setAddress(roomInfo);
|
|
130
|
+
await bot.connect();
|
|
369
131
|
|
|
370
|
-
|
|
371
|
-
|
|
132
|
+
// Join with optional password
|
|
133
|
+
await bot.joinRoom({
|
|
134
|
+
password: 'optional-password',
|
|
135
|
+
});
|
|
136
|
+
} catch (error) {
|
|
137
|
+
console.error('Failed to join room:', error);
|
|
138
|
+
}
|
|
372
139
|
});
|
|
373
140
|
```
|
|
374
141
|
|
|
375
|
-
###
|
|
142
|
+
### Joining a Room by Link
|
|
376
143
|
|
|
377
|
-
```
|
|
378
|
-
bot.on('
|
|
379
|
-
|
|
380
|
-
|
|
144
|
+
```javascript
|
|
145
|
+
bot.events.on('ready', async () => {
|
|
146
|
+
try {
|
|
147
|
+
// Get room info from share link
|
|
148
|
+
const roomInfo = await bot.getAddressFromUrl('https://bonk.io/123abc');
|
|
149
|
+
console.log(`Found room: ${roomInfo.roomname}`);
|
|
381
150
|
|
|
382
|
-
|
|
383
|
-
|
|
151
|
+
// Connect to room
|
|
152
|
+
bot.setAddress(roomInfo);
|
|
153
|
+
await bot.connect();
|
|
154
|
+
await bot.joinRoom();
|
|
155
|
+
} catch (error) {
|
|
156
|
+
console.error('Failed to join room:', error);
|
|
157
|
+
}
|
|
384
158
|
});
|
|
385
159
|
```
|
|
386
160
|
|
|
387
|
-
|
|
161
|
+
### Creating a Room
|
|
388
162
|
|
|
389
|
-
|
|
163
|
+
```javascript
|
|
164
|
+
bot.events.on('ready', async () => {
|
|
165
|
+
try {
|
|
166
|
+
// Connect to server first
|
|
167
|
+
await bot.connect();
|
|
390
168
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
mode: 'arrows'
|
|
169
|
+
// Then create room
|
|
170
|
+
bot.createRoom({
|
|
171
|
+
roomname: 'BonkBot Room',
|
|
172
|
+
maxplayers: 10,
|
|
173
|
+
roompassword: '',
|
|
174
|
+
hidden: true,
|
|
175
|
+
});
|
|
176
|
+
} catch (error) {
|
|
177
|
+
console.error('Failed to create room:', error);
|
|
178
|
+
}
|
|
402
179
|
});
|
|
403
180
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
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
|
-
}
|
|
181
|
+
// Get share link when room is created
|
|
182
|
+
bot.events.on('ROOM_SHARE_LINK', (data) => {
|
|
183
|
+
console.log(`Room created! URL: ${data.url}`);
|
|
433
184
|
});
|
|
434
185
|
```
|
|
435
186
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
}
|
|
462
|
-
}
|
|
187
|
+
## Available Events
|
|
188
|
+
|
|
189
|
+
| Event | Description | Returns |
|
|
190
|
+
| ------------------ | --------------------------- | ------------------------- |
|
|
191
|
+
| `ready` | Bot is ready to connect | - |
|
|
192
|
+
| `connect` | Connected to server | - |
|
|
193
|
+
| `PACKET` | Any packet received | `{type, ...data}` |
|
|
194
|
+
| `JOIN` | Joined a room | `{game, room, players}` |
|
|
195
|
+
| `PLAYER_JOIN` | Player joined room | `{player, id}` |
|
|
196
|
+
| `PLAYER_LEAVE` | Player left room | `{player, id}` |
|
|
197
|
+
| `CHAT_MESSAGE` | Chat message received | `{player, message}` |
|
|
198
|
+
| `TEAM_CHANGE` | Player changed team | `{player, team}` |
|
|
199
|
+
| `HOST_TRANSFER` | Host was transferred | `{oldHost, newHost}` |
|
|
200
|
+
| `READY_CHANGE` | Player ready status changed | `{player, ready}` |
|
|
201
|
+
| `GAME_START` | Game started | - |
|
|
202
|
+
| `GAME_END` | Game ended | - |
|
|
203
|
+
| `COUNTDOWN` | Game countdown | `{countdown}` |
|
|
204
|
+
| `MAP_SWITCH` | Map was switched | `{map}` |
|
|
205
|
+
| `MAP_SUGGEST` | Map was suggested | `{title, author, player}` |
|
|
206
|
+
| `CHANGE_ROUNDS` | Round count changed | `{rounds}` |
|
|
207
|
+
| `GAMEMODE_CHANGE` | Game mode changed | `{mode, engine}` |
|
|
208
|
+
| `ROOM_SHARE_LINK` | Room link created | `{url}` |
|
|
209
|
+
| `PLAYER_KICK` | Player was kicked | `player` |
|
|
210
|
+
| `PLAYER_TABBED` | Player tabbed in/out | `{player, tabbed}` |
|
|
211
|
+
| `PLAYER_INPUT` | Player input received | `{player, movement}` |
|
|
212
|
+
| `TEAMLOCK_TOGGLE` | Teams locked/unlocked | `{teamsLocked}` |
|
|
213
|
+
| `ROOM_NAME_UPDATE` | Room name changed | `{name}` |
|
|
214
|
+
| `ROOM_ADDRESS` | Room address updated | `{address}` |
|
|
215
|
+
| `BALANCE_SET` | Player balance changed | `{player, balance}` |
|
|
216
|
+
| `disconnect` | Disconnected from server | - |
|
|
217
|
+
|
|
218
|
+
## Common Methods
|
|
219
|
+
|
|
220
|
+
```javascript
|
|
221
|
+
// Chat message
|
|
222
|
+
bot.chat('Hello world');
|
|
223
|
+
|
|
224
|
+
// Get all players
|
|
225
|
+
const players = bot.getAllPlayers();
|
|
226
|
+
|
|
227
|
+
// Get host
|
|
228
|
+
const host = bot.getHost();
|
|
229
|
+
|
|
230
|
+
// Get room share link
|
|
231
|
+
const shareLink = bot.getShareLink();
|
|
232
|
+
|
|
233
|
+
// Set player ready status
|
|
234
|
+
bot.ready(true);
|
|
235
|
+
|
|
236
|
+
// Join a team (0-5)
|
|
237
|
+
bot.joinTeam(2); // 0=spectator, 1=FFA, 2=red, 3=blue...
|
|
238
|
+
|
|
239
|
+
// Give host to player
|
|
240
|
+
bot.giveHost(playerId);
|
|
241
|
+
|
|
242
|
+
// Kick a player
|
|
243
|
+
bot.kickPlayer(playerId);
|
|
244
|
+
|
|
245
|
+
// Leave the room
|
|
246
|
+
bot.leaveGame();
|
|
463
247
|
```
|
|
464
248
|
|
|
465
|
-
##
|
|
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
|
|
249
|
+
## Examples
|
|
538
250
|
|
|
539
|
-
|
|
251
|
+
Check out the `examples` directory for more examples:
|
|
540
252
|
|
|
541
|
-
-
|
|
542
|
-
-
|
|
253
|
+
- `simple-bot.js`: A basic bot that connects to a room and responds to chat commands
|
|
254
|
+
- `host-bot.js`: A bot that creates and hosts a room
|
|
543
255
|
|
|
544
|
-
|
|
256
|
+
## Contributing
|
|
545
257
|
|
|
546
|
-
|
|
258
|
+
Contributions are always welcome! If you find a bug or have a feature request, please open an issue on the project's GitHub page.
|
|
547
259
|
|
|
260
|
+
## License
|
|
548
261
|
|
|
549
|
-
[
|
|
550
|
-
[](https://github.com/brenoluizdev/bonktools/blob/main/LICENSE)
|
|
551
|
-
[](https://github.com/brenoluizdev/bonktools)
|
|
262
|
+
BonkBot is open-source software licensed under the [GPL-3.0 License](https://www.gnu.org/licenses/gpl-3.0.en.html).
|