bonktools 1.0.1 → 2.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.
@@ -0,0 +1,173 @@
1
+ import { EventEmitter } from 'events';
2
+ export type Account = {
3
+ username: string;
4
+ password?: string;
5
+ guest: boolean;
6
+ };
7
+ export type RoomInfo = {
8
+ address: string | null;
9
+ name: string | null;
10
+ server: string;
11
+ bypass: string;
12
+ id: number | null;
13
+ dbid: number | null;
14
+ teamsLocked: boolean;
15
+ map: any;
16
+ inGame: boolean;
17
+ };
18
+ export type GameInfo = {
19
+ id: number | null;
20
+ host: number | null;
21
+ banned: boolean;
22
+ };
23
+ export type Player = {
24
+ id: number;
25
+ username: string;
26
+ guest: boolean;
27
+ peerID: string;
28
+ };
29
+ export type JoinOptions = {
30
+ password?: string;
31
+ peerID?: string;
32
+ };
33
+ export type CreateRoomOptions = {
34
+ roomname?: string;
35
+ maxplayers?: number;
36
+ password?: string;
37
+ };
38
+ /**
39
+ * Gerencia a conexão WebSocket com o servidor Bonk.io e o estado do jogo.
40
+ */
41
+ export declare class BonkConnection extends EventEmitter {
42
+ private socket;
43
+ private connected;
44
+ private keepAliveTimer;
45
+ private PROTOCOL_VERSION;
46
+ account: Account;
47
+ server: string;
48
+ room: RoomInfo;
49
+ game: GameInfo;
50
+ players: Map<number, Player>;
51
+ token: string | null;
52
+ peerID: string;
53
+ avatar: any;
54
+ location: any;
55
+ constructor(account: Account, server?: string);
56
+ /**
57
+ * Gera um ID de par (peerID) aleatório.
58
+ * @returns {string} O peerID gerado.
59
+ */
60
+ private generatePeerID;
61
+ /**
62
+ * Obtém o token de autenticação do usuário.
63
+ * (Implementação baseada no bonkbot original, usando axios)
64
+ * @param {string} username - Nome de usuário.
65
+ * @param {string} password - Senha.
66
+ * @returns {Promise<string>} O token de autenticação.
67
+ */
68
+ private getToken;
69
+ /**
70
+ * Obtém informações do servidor (localização, etc.).
71
+ * (Implementação baseada no bonkbot original)
72
+ * @returns {Promise<any>} Informações do servidor.
73
+ */
74
+ private getServerInfo;
75
+ /**
76
+ * Inicializa a conexão (autenticação, obtenção de info do servidor).
77
+ * @returns {Promise<BonkConnection>} Esta instância.
78
+ */
79
+ init(): Promise<BonkConnection>;
80
+ /**
81
+ * Inicia o temporizador de keep-alive.
82
+ */
83
+ private startKeepAlive;
84
+ /**
85
+ * Para o bot (limpa timers, etc.).
86
+ */
87
+ private stopBot;
88
+ /**
89
+ * Configura os ouvintes de eventos do Socket.IO.
90
+ */
91
+ private setupSocketEvents;
92
+ /**
93
+ * Conecta-se ao servidor Bonk.io.
94
+ * @returns {Promise<BonkConnection>} Esta instância.
95
+ */
96
+ connect(): Promise<BonkConnection>;
97
+ /**
98
+ * Desconecta do servidor.
99
+ */
100
+ disconnect(): void;
101
+ /**
102
+ * Envia uma mensagem (pacote) para o servidor.
103
+ * @param {number} type - Tipo da mensagem (CLIENT_MESSAGE_TYPES).
104
+ * @param {any} data - Dados da mensagem.
105
+ */
106
+ sendMessage(type: number, data: any): void;
107
+ /**
108
+ * Envia o pacote TIMESYNC (keep-alive).
109
+ */
110
+ private sendTimesync;
111
+ /**
112
+ * Envia uma mensagem de chat para a sala.
113
+ * @param {string} message - A mensagem a ser enviada.
114
+ */
115
+ sendChat(message: string): void;
116
+ /**
117
+ * Envia um comando de input do jogador (movimento).
118
+ * @param {number} input - O valor do input (ex: 1 para esquerda, 2 para direita, etc.).
119
+ * @param {number} frame - O frame atual do jogo.
120
+ * @param {number} sequence - O número de sequência do input.
121
+ */
122
+ sendInput(input: number, frame: number, sequence: number): void;
123
+ /**
124
+ * Envia o comando para iniciar o jogo.
125
+ */
126
+ startGame(): void;
127
+ /**
128
+ * Envia o comando para mudar de time.
129
+ * @param {number} team - O ID do time (1 a 5, ou 0 para espectador).
130
+ */
131
+ changeTeam(team: number): void;
132
+ /**
133
+ * Envia o comando para definir o status de pronto/não pronto.
134
+ * @param {boolean} ready - True para pronto, False para não pronto.
135
+ */
136
+ setReady(ready: boolean): void;
137
+ /**
138
+ * Envia o comando para chutar/banir um jogador.
139
+ * @param {number} id - O ID do jogador.
140
+ * @param {boolean} ban - Se deve banir (true) ou apenas chutar (false).
141
+ */
142
+ kickBanPlayer(id: number, ban?: boolean): void;
143
+ /**
144
+ * Cria uma nova sala.
145
+ * @param {CreateRoomOptions} options - Opções de criação de sala.
146
+ * @returns {Promise<RoomInfo>} Informações da sala criada.
147
+ */
148
+ createRoom(options?: CreateRoomOptions): Promise<RoomInfo>;
149
+ /**
150
+ * Entra em uma sala existente.
151
+ * @param {string} roomAddress - Endereço da sala (ex: '123456' ou '123456abcde').
152
+ * @param {JoinOptions} options - Opções de entrada.
153
+ * @returns {Promise<void>}
154
+ */
155
+ joinRoom(roomAddress: string, options?: JoinOptions): Promise<void>;
156
+ /**
157
+ * Define o endereço da sala.
158
+ * @param {any} addressInfo - Informações de endereço da sala.
159
+ */
160
+ private setAddress;
161
+ /**
162
+ * Obtém informações de endereço da sala a partir de uma URL/ID.
163
+ * (Implementação baseada no bonkbot original)
164
+ * @param {string} url - URL ou ID da sala.
165
+ * @returns {Promise<any>} Informações de endereço.
166
+ */
167
+ private getAddressFromUrl;
168
+ /**
169
+ * Manipula os pacotes recebidos do servidor.
170
+ * @param {any} packet - Pacote analisado.
171
+ */
172
+ private handlePacket;
173
+ }
@@ -0,0 +1,482 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.BonkConnection = void 0;
7
+ const socket_io_client_1 = __importDefault(require("socket.io-client"));
8
+ const events_1 = require("events");
9
+ const axios_1 = __importDefault(require("axios"));
10
+ const constants_1 = require("../utils/constants");
11
+ const validation_1 = require("../utils/validation");
12
+ const PacketBuilder_1 = require("./PacketBuilder");
13
+ const PacketParser_1 = require("./PacketParser");
14
+ /**
15
+ * Gerencia a conexão WebSocket com o servidor Bonk.io e o estado do jogo.
16
+ */
17
+ class BonkConnection extends events_1.EventEmitter {
18
+ constructor(account, server = constants_1.DEFAULT_SERVER) {
19
+ super();
20
+ this.socket = null;
21
+ this.connected = false;
22
+ this.keepAliveTimer = null;
23
+ this.PROTOCOL_VERSION = 7; // Versão do protocolo Bonk.io (pode precisar de atualização)
24
+ this.players = new Map();
25
+ this.token = null;
26
+ this.peerID = this.generatePeerID();
27
+ this.avatar = { layers: [], bc: 0 }; // Avatar padrão
28
+ this.location = {}; // Informações de localização (lat, long, country)
29
+ this.account = (0, validation_1.validateAccount)(account);
30
+ this.server = server;
31
+ this.room = {
32
+ address: null,
33
+ name: null,
34
+ server: this.server,
35
+ bypass: '',
36
+ id: null,
37
+ dbid: null,
38
+ teamsLocked: false,
39
+ map: null,
40
+ inGame: false,
41
+ };
42
+ this.game = {
43
+ id: null,
44
+ host: null,
45
+ banned: false,
46
+ };
47
+ }
48
+ /**
49
+ * Gera um ID de par (peerID) aleatório.
50
+ * @returns {string} O peerID gerado.
51
+ */
52
+ generatePeerID() {
53
+ // Implementação de geração de peerID (pode ser simplificada por enquanto)
54
+ return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
55
+ }
56
+ /**
57
+ * Obtém o token de autenticação do usuário.
58
+ * (Implementação baseada no bonkbot original, usando axios)
59
+ * @param {string} username - Nome de usuário.
60
+ * @param {string} password - Senha.
61
+ * @returns {Promise<string>} O token de autenticação.
62
+ */
63
+ async getToken(username, password) {
64
+ // TODO: Implementar a lógica de obtenção de token
65
+ // Por enquanto, retorna um token falso se não for convidado
66
+ if (!password) {
67
+ throw new Error('Password is required for non-guest accounts.');
68
+ }
69
+ // Lógica de requisição HTTP para login
70
+ // const response = await axios.post(API.LOGIN, { username, password });
71
+ // return response.data.token;
72
+ return 'FAKE_TOKEN_12345';
73
+ }
74
+ /**
75
+ * Obtém informações do servidor (localização, etc.).
76
+ * (Implementação baseada no bonkbot original)
77
+ * @returns {Promise<any>} Informações do servidor.
78
+ */
79
+ async getServerInfo() {
80
+ // TODO: Implementar a lógica de obtenção de informações do servidor
81
+ // Por enquanto, retorna um objeto mock
82
+ return {
83
+ server: constants_1.DEFAULT_SERVER,
84
+ lat: 0,
85
+ long: 0,
86
+ country: 'BR',
87
+ };
88
+ }
89
+ /**
90
+ * Inicializa a conexão (autenticação, obtenção de info do servidor).
91
+ * @returns {Promise<BonkConnection>} Esta instância.
92
+ */
93
+ async init() {
94
+ // Lógica de inicialização (getToken, getServerInfo)
95
+ if (!this.account.guest && !this.token) {
96
+ this.token = await this.getToken(this.account.username, this.account.password);
97
+ }
98
+ if (!this.server || this.server === constants_1.DEFAULT_SERVER) {
99
+ const serverInfo = await this.getServerInfo();
100
+ this.server = serverInfo.server;
101
+ this.location = serverInfo;
102
+ this.room.server = this.server;
103
+ }
104
+ this.emit('ready');
105
+ return this;
106
+ }
107
+ /**
108
+ * Inicia o temporizador de keep-alive.
109
+ */
110
+ startKeepAlive() {
111
+ this.keepAliveTimer = setInterval(() => {
112
+ if (this.connected && this.socket && this.socket.connected) {
113
+ this.sendTimesync();
114
+ }
115
+ else if (this.connected) {
116
+ this.stopBot();
117
+ this.emit('disconnect');
118
+ }
119
+ }, 5000);
120
+ }
121
+ /**
122
+ * Para o bot (limpa timers, etc.).
123
+ */
124
+ stopBot() {
125
+ if (this.keepAliveTimer) {
126
+ clearInterval(this.keepAliveTimer);
127
+ this.keepAliveTimer = null;
128
+ }
129
+ this.connected = false;
130
+ }
131
+ /**
132
+ * Configura os ouvintes de eventos do Socket.IO.
133
+ */
134
+ setupSocketEvents() {
135
+ if (!this.socket)
136
+ return;
137
+ // O Bonk.io usa o evento 'message' para a maioria dos pacotes
138
+ this.socket.on('message', (data) => {
139
+ const packet = PacketParser_1.PacketParser.parse(data);
140
+ this.handlePacket(packet);
141
+ });
142
+ // Evento de desconexão
143
+ this.socket.on('disconnect', (reason) => {
144
+ this.stopBot();
145
+ this.emit('disconnect', reason);
146
+ });
147
+ // Evento de erro
148
+ this.socket.on('error', (error) => {
149
+ this.emit('error', error);
150
+ });
151
+ }
152
+ /**
153
+ * Conecta-se ao servidor Bonk.io.
154
+ * @returns {Promise<BonkConnection>} Esta instância.
155
+ */
156
+ async connect() {
157
+ if (this.connected) {
158
+ this.disconnect();
159
+ }
160
+ // Desabilitar verificação de certificado TLS (necessário para bonk.io)
161
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
162
+ const socketAddr = `https://${this.server}.bonk.io`;
163
+ return new Promise((resolve, reject) => {
164
+ try {
165
+ const socketOptions = {
166
+ transports: ['websocket'],
167
+ reconnection: false,
168
+ timeout: 10000,
169
+ forceNew: true,
170
+ path: '/socket.io',
171
+ rejectUnauthorized: false // Necessário para bonk.io
172
+ };
173
+ this.socket = (0, socket_io_client_1.default)(socketAddr, socketOptions);
174
+ const timeout = setTimeout(() => {
175
+ if (!this.connected) {
176
+ reject(new Error(`Connection timeout to server: ${this.server}`));
177
+ this.stopBot();
178
+ }
179
+ }, 10000);
180
+ this.socket.on('connect', () => {
181
+ clearTimeout(timeout);
182
+ this.connected = true;
183
+ this.setupSocketEvents();
184
+ this.startKeepAlive();
185
+ this.emit('connect');
186
+ resolve(this);
187
+ });
188
+ this.socket.on('connect_error', (error) => {
189
+ if (!this.connected) {
190
+ clearTimeout(timeout);
191
+ reject(new Error(`Failed to connect to server: ${error.message}`));
192
+ }
193
+ this.emit('error', error);
194
+ });
195
+ this.socket.on('disconnect', (reason) => {
196
+ if (!this.connected) {
197
+ clearTimeout(timeout);
198
+ reject(new Error(`Connection closed before fully established: ${reason}`));
199
+ }
200
+ this.stopBot();
201
+ this.emit('disconnect', reason);
202
+ });
203
+ }
204
+ catch (error) {
205
+ reject(new Error(`Failed to create Socket.IO connection: ${error.message}`));
206
+ }
207
+ });
208
+ }
209
+ /**
210
+ * Desconecta do servidor.
211
+ */
212
+ disconnect() {
213
+ if (!this.connected)
214
+ return;
215
+ this.stopBot();
216
+ if (this.socket) {
217
+ this.socket.disconnect();
218
+ this.socket = null;
219
+ }
220
+ }
221
+ /**
222
+ * Envia uma mensagem (pacote) para o servidor.
223
+ * @param {number} type - Tipo da mensagem (CLIENT_MESSAGE_TYPES).
224
+ * @param {any} data - Dados da mensagem.
225
+ */
226
+ sendMessage(type, data) {
227
+ if (!this.socket || !this.connected) {
228
+ throw new Error('Not connected to server.');
229
+ }
230
+ const packet = PacketBuilder_1.PacketBuilder.build(type, data);
231
+ this.socket.emit('message', packet);
232
+ }
233
+ /**
234
+ * Envia o pacote TIMESYNC (keep-alive).
235
+ */
236
+ sendTimesync() {
237
+ this.sendMessage(constants_1.CLIENT_MESSAGE_TYPES.TIMESYNC, { time: Date.now() });
238
+ }
239
+ /**
240
+ * Envia uma mensagem de chat para a sala.
241
+ * @param {string} message - A mensagem a ser enviada.
242
+ */
243
+ sendChat(message) {
244
+ this.sendMessage(constants_1.CLIENT_MESSAGE_TYPES.CHAT_MESSAGE, { message });
245
+ }
246
+ /**
247
+ * Envia um comando de input do jogador (movimento).
248
+ * @param {number} input - O valor do input (ex: 1 para esquerda, 2 para direita, etc.).
249
+ * @param {number} frame - O frame atual do jogo.
250
+ * @param {number} sequence - O número de sequência do input.
251
+ */
252
+ sendInput(input, frame, sequence) {
253
+ this.sendMessage(constants_1.CLIENT_MESSAGE_TYPES.SEND_INPUTS, {
254
+ input,
255
+ frame,
256
+ sequence,
257
+ });
258
+ }
259
+ /**
260
+ * Envia o comando para iniciar o jogo.
261
+ */
262
+ startGame() {
263
+ this.sendMessage(constants_1.CLIENT_MESSAGE_TYPES.TRIGGER_START, {});
264
+ }
265
+ /**
266
+ * Envia o comando para mudar de time.
267
+ * @param {number} team - O ID do time (1 a 5, ou 0 para espectador).
268
+ */
269
+ changeTeam(team) {
270
+ this.sendMessage(constants_1.CLIENT_MESSAGE_TYPES.CHANGE_OWN_TEAM, { team });
271
+ }
272
+ /**
273
+ * Envia o comando para definir o status de pronto/não pronto.
274
+ * @param {boolean} ready - True para pronto, False para não pronto.
275
+ */
276
+ setReady(ready) {
277
+ this.sendMessage(constants_1.CLIENT_MESSAGE_TYPES.SET_READY, { ready });
278
+ }
279
+ /**
280
+ * Envia o comando para chutar/banir um jogador.
281
+ * @param {number} id - O ID do jogador.
282
+ * @param {boolean} ban - Se deve banir (true) ou apenas chutar (false).
283
+ */
284
+ kickBanPlayer(id, ban = false) {
285
+ this.sendMessage(constants_1.CLIENT_MESSAGE_TYPES.KICK_BAN_PLAYER, { id, ban });
286
+ }
287
+ // Outras funcionalidades podem ser adicionadas aqui, como:
288
+ // - setMap(mapData: any)
289
+ // - setGameMode(mode: string)
290
+ // - setRounds(rounds: number)
291
+ // - sendMapSuggest(mapID: number)
292
+ // - etc.
293
+ /**
294
+ * Cria uma nova sala.
295
+ * @param {CreateRoomOptions} options - Opções de criação de sala.
296
+ * @returns {Promise<RoomInfo>} Informações da sala criada.
297
+ */
298
+ async createRoom(options = {}) {
299
+ if (!this.connected) {
300
+ throw new Error('Not connected to server.');
301
+ }
302
+ // A validação será implementada em src/utils/validation.ts
303
+ // const validatedOptions = validateRoomOptions(options);
304
+ const validatedOptions = options; // Temporário
305
+ this.room.name = validatedOptions.roomname || `BonkBot Room ${Math.floor(Math.random() * 1000)}`;
306
+ this.room.server = this.server; // Garante que o servidor está correto
307
+ const createData = {
308
+ peerID: this.peerID,
309
+ roomName: this.room.name,
310
+ maxPlayers: validatedOptions.maxplayers || 8,
311
+ password: validatedOptions.password || '',
312
+ dbid: 11822936, // Valor padrão do bonkbot
313
+ guest: this.account.guest,
314
+ minLevel: 0,
315
+ maxLevel: 999,
316
+ latitude: this.location.lat || 0,
317
+ longitude: this.location.long || 0,
318
+ country: this.location.country || 'BR',
319
+ version: this.PROTOCOL_VERSION,
320
+ hidden: validatedOptions.hidden ? 1 : 0,
321
+ quick: validatedOptions.quick || false,
322
+ mode: validatedOptions.mode || 'custom',
323
+ token: this.token || '',
324
+ avatar: this.avatar,
325
+ };
326
+ if (this.account.guest) {
327
+ createData.guestName = this.account.username;
328
+ }
329
+ // O bonkbot original não espera uma resposta aqui, apenas envia a mensagem
330
+ this.sendMessage(constants_1.CLIENT_MESSAGE_TYPES.CREATE_ROOM, createData);
331
+ // O endereço da sala (roomID e bypass) é recebido posteriormente via pacote 'ROOM_SHARE_LINK'
332
+ // Por enquanto, retornamos o que sabemos
333
+ return this.room;
334
+ }
335
+ /**
336
+ * Entra em uma sala existente.
337
+ * @param {string} roomAddress - Endereço da sala (ex: '123456' ou '123456abcde').
338
+ * @param {JoinOptions} options - Opções de entrada.
339
+ * @returns {Promise<void>}
340
+ */
341
+ async joinRoom(roomAddress, options = {}) {
342
+ if (!this.connected) {
343
+ throw new Error('Not connected to server.');
344
+ }
345
+ // A validação será implementada em src/utils/validation.ts
346
+ // const validatedOptions = validateJoinOptions(options);
347
+ const validatedOptions = options; // Temporário
348
+ // 1. Obter endereço completo (server, bypass) se necessário
349
+ const addressInfo = await this.getAddressFromUrl(`https://bonk.io/game.html?${roomAddress}`);
350
+ if (!addressInfo || addressInfo.r !== 'success') {
351
+ throw new Error('Failed to get room address information.');
352
+ }
353
+ this.setAddress(addressInfo);
354
+ // 2. Enviar mensagem de JOIN_ROOM
355
+ const joinData = {
356
+ joinID: this.room.address,
357
+ roomPassword: validatedOptions.password || '',
358
+ guest: this.account.guest,
359
+ dbid: 2, // Valor padrão
360
+ version: this.PROTOCOL_VERSION,
361
+ peerID: validatedOptions.peerID || this.peerID,
362
+ bypass: this.room.bypass || '',
363
+ avatar: this.avatar
364
+ };
365
+ if (this.account.guest) {
366
+ joinData.guestName = this.account.username;
367
+ }
368
+ else {
369
+ joinData.token = this.token;
370
+ }
371
+ this.sendMessage(constants_1.CLIENT_MESSAGE_TYPES.JOIN_ROOM, joinData);
372
+ }
373
+ /**
374
+ * Define o endereço da sala.
375
+ * @param {any} addressInfo - Informações de endereço da sala.
376
+ */
377
+ setAddress(addressInfo) {
378
+ if (!addressInfo.address || !addressInfo.roomname || !addressInfo.server) {
379
+ throw new Error('Invalid room address information');
380
+ }
381
+ this.room.address = addressInfo.address;
382
+ this.room.name = addressInfo.roomname;
383
+ this.room.server = addressInfo.server;
384
+ this.room.bypass = addressInfo.bypass || '';
385
+ if (this.server !== addressInfo.server) {
386
+ this.server = addressInfo.server;
387
+ }
388
+ }
389
+ /**
390
+ * Obtém informações de endereço da sala a partir de uma URL/ID.
391
+ * (Implementação baseada no bonkbot original)
392
+ * @param {string} url - URL ou ID da sala.
393
+ * @returns {Promise<any>} Informações de endereço.
394
+ */
395
+ async getAddressFromUrl(url) {
396
+ // Lógica de regex para extrair ID e bypass
397
+ const regex = /\/(\d{6})([a-zA-Z0-9]{5})?$/;
398
+ const match = url.match(regex);
399
+ if (!match) {
400
+ return null;
401
+ }
402
+ const id = match[1];
403
+ const bypass = match[2] || '';
404
+ const data = new URLSearchParams();
405
+ data.append('joinID', id);
406
+ try {
407
+ // TODO: Implementar httpsAgent se necessário para ignorar certificados
408
+ const response = await axios_1.default.post(constants_1.API.AUTOJOIN, data.toString(), {
409
+ headers: {
410
+ 'Content-Type': 'application/x-www-form-urlencoded'
411
+ },
412
+ // httpsAgent: httpsAgent // Necessário importar e configurar
413
+ });
414
+ const result = response.data;
415
+ if (result.r === 'success') {
416
+ result.bypass = bypass;
417
+ }
418
+ return result;
419
+ }
420
+ catch (error) {
421
+ // console.error('Error getting join link:', error);
422
+ throw error;
423
+ }
424
+ }
425
+ /**
426
+ * Manipula os pacotes recebidos do servidor.
427
+ * @param {any} packet - Pacote analisado.
428
+ */
429
+ handlePacket(packet) {
430
+ // TODO: Implementar a lógica de autoHandlePacket do bonkbot
431
+ // Por enquanto, apenas emite o evento
432
+ this.emit('packet', packet);
433
+ switch (packet.type) {
434
+ case constants_1.SERVER_MESSAGE_TYPES.ROOM_SHARE_LINK:
435
+ // O servidor responde com o ID da sala e o bypass após a criação
436
+ this.room.dbid = packet.data.roomId;
437
+ this.room.bypass = packet.data.roomBypass;
438
+ this.emit('ROOM_SHARE_LINK', { roomId: this.room.dbid, bypass: this.room.bypass });
439
+ break;
440
+ case constants_1.SERVER_MESSAGE_TYPES.JOIN_ROOM:
441
+ // Lógica de JOIN_ROOM (configurar game.id, game.host, room.id, players)
442
+ this.game.id = packet.data.myid;
443
+ this.game.host = packet.data.hostid;
444
+ this.room.id = packet.data.roomid;
445
+ this.room.bypass = packet.data.roombypass;
446
+ this.room.teamsLocked = packet.data.teamsLocked;
447
+ // Adicionar jogadores (playerdata)
448
+ if (packet.data.playerdata && Array.isArray(packet.data.playerdata)) {
449
+ for (let i = 0; i < packet.data.playerdata.length; i++) {
450
+ const playerData = packet.data.playerdata[i];
451
+ if (playerData) {
452
+ // Mapear e adicionar jogador (simplificado)
453
+ this.players.set(i, {
454
+ id: i,
455
+ username: playerData.userName,
456
+ guest: playerData.guest,
457
+ peerID: playerData.peerID,
458
+ // ... outros campos
459
+ });
460
+ }
461
+ }
462
+ }
463
+ this.emit('JOIN', { game: this.game, room: this.room, players: this.players });
464
+ break;
465
+ case constants_1.SERVER_MESSAGE_TYPES.CHAT_MESSAGE:
466
+ // Lógica de CHAT_MESSAGE
467
+ const player = this.players.get(packet.id);
468
+ this.emit('CHAT_MESSAGE', { player, message: packet.message });
469
+ break;
470
+ case constants_1.SERVER_MESSAGE_TYPES.TIMESYNC:
471
+ // Lógica de TIMESYNC (opcional, apenas para rastrear latência)
472
+ // this.timeSync.last_sync = packet.time;
473
+ // this.timeSync.latency = Date.now() - this.timeSync.last_sync;
474
+ break;
475
+ // TODO: Adicionar outros casos importantes (PLAYER_JOIN, PLAYER_LEAVE, GAME_START, etc.)
476
+ default:
477
+ // console.log(`Unhandled packet type: ${packet.type}`);
478
+ break;
479
+ }
480
+ }
481
+ }
482
+ exports.BonkConnection = BonkConnection;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Classe utilitária para construir pacotes a serem enviados ao servidor Bonk.io.
3
+ * O Bonk.io usa o formato PSON (Protocol-Specific Object Notation) para a maioria dos pacotes.
4
+ */
5
+ export declare class PacketBuilder {
6
+ /**
7
+ * Constrói um pacote para envio.
8
+ * @param {number} type - O tipo de mensagem (do CLIENT_MESSAGE_TYPES).
9
+ * @param {any} data - Os dados a serem serializados.
10
+ * @returns {any} O pacote serializado (geralmente um array).
11
+ */
12
+ static build(type: number, data: any): any;
13
+ }
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ // src/connection/PacketBuilder.ts
3
+ // Lógica de serialização de pacotes (baseada no bonkbot original)
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.PacketBuilder = void 0;
6
+ /**
7
+ * Classe utilitária para construir pacotes a serem enviados ao servidor Bonk.io.
8
+ * O Bonk.io usa o formato PSON (Protocol-Specific Object Notation) para a maioria dos pacotes.
9
+ */
10
+ class PacketBuilder {
11
+ /**
12
+ * Constrói um pacote para envio.
13
+ * @param {number} type - O tipo de mensagem (do CLIENT_MESSAGE_TYPES).
14
+ * @param {any} data - Os dados a serem serializados.
15
+ * @returns {any} O pacote serializado (geralmente um array).
16
+ */
17
+ static build(type, data) {
18
+ // O bonkbot original usa um array onde o primeiro elemento é o tipo
19
+ // e o segundo é o objeto de dados. A serialização PSON é feita
20
+ // automaticamente pelo socket.io-client v2.x, que era a versão usada no bonkbot.
21
+ // Vamos manter essa estrutura.
22
+ return [type, data];
23
+ }
24
+ }
25
+ exports.PacketBuilder = PacketBuilder;