@baipiaodajun/mcbots 1.2.1 → 1.2.2

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 (2) hide show
  1. package/package.json +1 -1
  2. package/server.js +117 -72
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@baipiaodajun/mcbots",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "description": "Minecraft bot and status dashboard for multi-server management",
5
5
  "main": "server.js",
6
6
  "scripts": {
package/server.js CHANGED
@@ -10,6 +10,13 @@ const fs = require('fs');
10
10
  const PORT = process.env.SERVER_PORT || process.env.PORT || 3000 ;
11
11
  const CHAT = process.env.CHAT || false ;
12
12
  const MOVE = process.env.MOVE || false ;
13
+ //debug模式,只有开启时才会有很多日志。
14
+ const DEBUG = (process.env.DEBUG || '').toLowerCase() === 'true';
15
+ function debugPrint(...args) {
16
+ if (DEBUG) {
17
+ console.log(...args);
18
+ }
19
+ }
13
20
  // Minecraft服务器配置
14
21
  const SERVERS = [
15
22
  {
@@ -124,7 +131,7 @@ const BOT_CONFIG = {
124
131
 
125
132
  const SERVER_CONFIG = {
126
133
  statusCheckInterval: 30000,
127
- maxFailedAttempts: 3,
134
+ maxFailedAttempts: 1,
128
135
  resetTimeout: 30000
129
136
  };
130
137
 
@@ -207,6 +214,7 @@ class MinecraftBotManager {
207
214
  this.version = version || "1.20.1";
208
215
  this.currentBots = 0;
209
216
  this.activeBots = new Map();
217
+ this.pendingReconnect = new Set(); // 等待重连的机器人名字(已断开但优先重用名字)
210
218
  this.failedAttempts = 0;
211
219
  this.lastUpdate = Date.now();
212
220
  this.status = 'initializing';
@@ -300,16 +308,52 @@ class MinecraftBotManager {
300
308
  this.notice=true;
301
309
  }
302
310
  }
311
+ async handleBottimeout(bot,botName){
312
+ this.timeout = setTimeout(() => {
313
+ debugPrint(`[${this.host}:${this.port}] ${botName} 连接超时,强制终止`);
314
+
315
+ // 第一步:尝试正常结束(推荐方式)
316
+ if (typeof bot.end === 'function') {
317
+ try {
318
+ bot.end();
319
+ debugPrint(`[${this.host}:${this.port}] ${botName} 调用 bot.end() 成功`);
320
+ return; // 如果正常结束,就不需要进一步操作
321
+ } catch (err) {
322
+ debugPrint(`[${this.host}:${this.port}] ${botName} bot.end() 抛出异常:`, err.message);
323
+ // 继续尝试强杀底层 socket
324
+ }
325
+ }
326
+
327
+ // 第二步:bot.end 失败或不存在,强制关闭底层 client socket
328
+ if (bot._client?.socket) {
329
+ try {
330
+ bot._client.socket.destroy(); // 最彻底:直接 destroy socket
331
+ debugPrint(`[${this.host}:${this.port}] ${botName} 强制 destroy 底层 socket`);
332
+ } catch (err) {
333
+ debugPrint(`[${this.host}:${this.port}] ${botName} destroy socket 失败:`, err.message);
334
+ }
335
+ } else if (bot._client?.end) {
336
+ try {
337
+ bot._client.end();
338
+ debugPrint(`[${this.host}:${this.port}] ${botName} 调用 bot._client.end()`);
339
+ } catch (err) {
340
+ debugPrint(`[${this.host}:${this.port}] ${botName} bot._client.end() 失败:`, err.message);
341
+ }
342
+ } else {
343
+ debugPrint(`[${this.host}:${this.port}] ${botName} 无可用 client socket,无法强制关闭`);
344
+ }
345
+
346
+ // 可选:触发断开处理(确保进入重连逻辑)
347
+ this.handleBotDisconnect(botName);
348
+
349
+ }, BOT_CONFIG.connectTimeout);
350
+ }
303
351
  // 创建Minecraft机器人
304
352
  async createBot(botName) {
305
353
  if (this.currentBots >= this.maxBots) {
306
354
  console.log(`[${this.host}:${this.port}] 已达到最大机器人限制: ${this.maxBots}`);
307
355
  return null;
308
356
  }
309
- await this.testmc();
310
- if (!this.reachable) {
311
- return null;
312
- }
313
357
  if(!botName){
314
358
  botName = this.generateBotName();
315
359
  }
@@ -324,12 +368,7 @@ class MinecraftBotManager {
324
368
  auth: 'offline'
325
369
  });
326
370
 
327
- this.timeout = setTimeout(() => {
328
- console.error(`[${this.host}:${this.port}] ${botName}连接超时,放弃等待`);
329
- if (typeof bot.end === 'function') {
330
- bot.end();
331
- }
332
- }, BOT_CONFIG.connectTimeout);
371
+ this.handleBottimeout(bot,botName);
333
372
 
334
373
  // 设置机器人事件处理
335
374
  this.setupBotEvents(bot, botName);
@@ -340,7 +379,7 @@ class MinecraftBotManager {
340
379
  this.updateStatus();
341
380
  return bot;
342
381
  } catch (error) {
343
- console.log(`[${this.host}:${this.port}] 创建机器人 ${botName} 失败:`, error.message);
382
+ debugPrint(`[${this.host}:${this.port}] 创建机器人 ${botName} 失败:`, error.message);
344
383
  this.handleBotFailure(botName);
345
384
  return null;
346
385
  }
@@ -354,19 +393,20 @@ class MinecraftBotManager {
354
393
  clearTimeout(this.timeout);
355
394
  this.timeout = null;
356
395
  }
396
+ this.failedAttempts = 0;
397
+ this.pendingReconnect.delete(botName);
357
398
  this.updateStatus();
358
399
  });
359
400
 
360
401
  bot.on('spawn', () => {
361
- console.log(`[${this.host}:${this.port}] 机器人 ${botName} 生成在世界中`);
362
-
402
+ debugPrint(`[${this.host}:${this.port}] 机器人 ${botName} 生成在世界中`);
363
403
  // 机器人基础行为
364
404
  this.setupBotBehavior(bot, botName);
365
405
  });
366
406
 
367
407
  bot.on('message', (message) => {
368
408
  const text = message.toString();
369
- console.log(`[${this.host}:${this.port}] ${botName} 收到消息: ${text}`);
409
+ debugPrint(`[${this.host}:${this.port}] ${botName} 收到消息: ${text}`);
370
410
  });
371
411
 
372
412
  bot.on('error', (error) => {
@@ -380,7 +420,7 @@ class MinecraftBotManager {
380
420
 
381
421
  bot.on('end', (reason) => {
382
422
  console.log(`[${this.host}:${this.port}] 机器人 ${botName} 断开连接:`, reason);
383
- console.log(`[${this.host}:${this.port}] ${botName}:失败次数${this.failedAttempts}`);
423
+ // console.log(`[${this.host}:${this.port}] ${botName}:失败次数${this.failedAttempts}`);
384
424
  this.handleBotDisconnect(botName);
385
425
  });
386
426
 
@@ -419,27 +459,21 @@ class MinecraftBotManager {
419
459
  }
420
460
  }
421
461
 
422
- // 处理机器人断开连接 - 增强版本
423
462
  handleBotDisconnect(botName) {
424
463
  if (this.activeBots.has(botName)) {
425
- console.log(`[${this.host}:${this.port}] 从活跃列表中移除机器人: ${botName}`);
464
+ debugPrint(`[${this.host}:${this.port}] 从活跃列表中移除机器人: ${botName}`);
426
465
  this.activeBots.delete(botName);
427
466
  this.currentBots = Math.max(0, this.currentBots - 1);
428
467
  this.updateStatus();
429
-
430
- // 记录断开连接时间,用于调试
431
- console.log(`[${this.host}:${this.port}] 当前活跃机器人数量: ${this.currentBots}, 目标: ${this.minBots}`);
432
-
433
- if(this.failedAttempts > SERVER_CONFIG.maxFailedAttempts){
434
- console.log(`[${this.host}:${this.port}] 机器人 ${botName} 重连次数太多,跳过`);
435
- return;
436
- }
437
- // 延迟重连,避免频繁重连
468
+ this.pendingReconnect.add(botName);
469
+ debugPrint(`[${this.host}:${this.port}] 当前活跃机器人数量: ${this.currentBots}, 目标: ${this.minBots}`);
470
+
438
471
  setTimeout(() => {
439
472
  this.reconnect(botName);
440
473
  }, BOT_CONFIG.reconnectDelay);
474
+
441
475
  } else {
442
- console.log(`[${this.host}:${this.port}] 机器人 ${botName} 不在活跃列表中,无需处理`);
476
+ debugPrint(`[${this.host}:${this.port}] 机器人 ${botName} 不在活跃列表中,无需处理`);
443
477
  }
444
478
  }
445
479
 
@@ -447,62 +481,63 @@ class MinecraftBotManager {
447
481
  handleBotFailure(botName) {
448
482
  this.failedAttempts++;
449
483
  this.updateStatus();
450
- if (this.failedAttempts >= SERVER_CONFIG.maxFailedAttempts) {
451
- console.log(`[${this.host}:${this.port}] 失败次数过多,${SERVER_CONFIG.resetTimeout / 1000}秒后再次尝试`);
452
- setTimeout(() => {
453
- this.failedAttempts = 0;
454
- this.reconnect(botName);
455
- }, SERVER_CONFIG.resetTimeout);
456
- return;
457
- }
458
- setTimeout(() => {
459
- this.reconnect(botName);
460
- }, BOT_CONFIG.reconnectDelay);
484
+ this.reconnect(botName);
461
485
  }
462
486
 
463
487
  // 维护机器人数目 - 增强版本
464
- maintainBots() {
465
- const neededBots = this.minBots - this.currentBots;
466
-
467
- // console.log(`[${this.host}:${this.port}] 当前机器人: ${this.currentBots}, 需要: ${neededBots}, 失败次数: ${this.failedAttempts}`);
468
- if (neededBots > 0 && this.failedAttempts < SERVER_CONFIG.maxFailedAttempts) {
469
- if (this.notice) {
470
- console.log(`[${this.host}:${this.port}] 需要启动 ${neededBots} 个机器人`);
471
- this.notice=false;
472
- }
473
- for (let i = 0; i < neededBots; i++) {
474
- setTimeout(() => {
475
- this.createBot();
476
- }, i * 8000); // 每隔8秒启动一个
488
+ async maintainBots() {
489
+ const neededBots = this.minBots -this.currentBots;
490
+ try {
491
+ debugPrint(`[${this.host}:${this.port}] 当前机器人: ${this.currentBots}, 需要: ${neededBots}, 失败次数: ${this.failedAttempts}`);
492
+ await this.testmc();
493
+ if (!this.reachable) {
494
+ return null;
477
495
  }
478
- }
479
- // else if (neededBots > 0) {
480
- // console.log(`[${this.host}:${this.port}] 由于失败次数过多,暂停创建新机器人`);
481
- // }
482
- this.updateStatus();
496
+ if (neededBots > 0 && this.failedAttempts < SERVER_CONFIG.maxFailedAttempts) {
497
+ if (this.notice) {
498
+ console.log(`[${this.host}:${this.port}] 需要启动 ${neededBots} 个机器人`);
499
+ this.notice=false;
500
+ }
501
+ for (let i = 0; i < neededBots; i++) {
502
+ setTimeout(() => {
503
+ this.createBot();
504
+ }, i * 8000); // 每隔8秒启动一个
505
+ }
506
+ }
507
+ this.updateStatus();
508
+ }
509
+ catch (err) {
510
+ console.error(`[${this.host}:${this.port}] maintainBots 异常:`, err);
511
+ }
483
512
  }
484
- reconnect(botName){
485
- if (this.failedAttempts < SERVER_CONFIG.maxFailedAttempts) {
486
- console.log(`[${this.host}:${this.port}] 第${this.failedAttempts}次重连 ${botName} 机器人`);
487
- this.failedAttempts++;
488
- setTimeout(() => {
489
- this.createBot(botName);
490
- }, 5000);
491
- } else{
492
- // 如果还没有设置过 resetTimer,就设置一次
513
+
514
+ reconnect(botName) {
515
+ if (this.failedAttempts >= SERVER_CONFIG.maxFailedAttempts) {
493
516
  if (!this.resetTimer) {
494
517
  this.resetTimer = setTimeout(() => {
495
518
  this.failedAttempts = 0;
496
- this.resetTimer = null; // 清理标记,允许下次再设置
497
- console.log(
498
- `[${this.host}:${this.port}] 失败次数已重置,可以重新尝试创建机器人`
499
- );
519
+ this.resetTimer = null;
520
+ debugPrint(`[${this.host}:${this.port}] 冷却期结束,恢复维护`);
521
+ this.maintainBots();
500
522
  }, SERVER_CONFIG.resetTimeout);
523
+ debugPrint(`[${this.host}:${this.port}] 失败过多,进入冷却 ${ SERVER_CONFIG.resetTimeout/ 1000}s`);
501
524
  }
502
- console.log(`[${this.host}:${this.port}] 由于失败次数过多,暂停创建新机器人`);
525
+ return;
503
526
  }
504
- this.updateStatus();
527
+
528
+ this.failedAttempts++;
529
+
530
+ // 如果传入 botName(来自断开重连),且它还在待重连名单中 → 优先用原名字
531
+ if (botName && this.pendingReconnect.has(botName)) {
532
+ debugPrint(`[${this.host}:${this.port}] 第 ${this.failedAttempts} 次尝试重连原机器人: ${botName}`);
533
+ this.createBot(botName); // 传名字,保持固定
534
+ return;
535
+ }
536
+ // 否则(新补人或名字已被放弃)→ 不传名字,生成新的
537
+ debugPrint(`[${this.host}:${this.port}] 第 ${this.failedAttempts} 次连接失败,触发维护补人`);
538
+ this.maintainBots();
505
539
  }
540
+
506
541
  // 更新状态
507
542
  updateStatus() {
508
543
  const serverInfo = globalServerStatus.servers.get(`${this.host}:${this.port}`);
@@ -1638,6 +1673,16 @@ function shutdown() {
1638
1673
 
1639
1674
  // 启动
1640
1675
  if (require.main === module) {
1676
+ process.on('unhandledRejection', (reason, promise) => {
1677
+ console.error('未处理的 Promise Rejection:', reason);
1678
+ // 不退出进程,但至少能看到问题
1679
+ });
1680
+
1681
+ process.on('uncaughtException', (error) => {
1682
+ console.error('未捕获的异常:', error);
1683
+ // process.exit(1);
1684
+ });
1685
+
1641
1686
  initialize().catch(error => {
1642
1687
  console.error('初始化失败:', error);
1643
1688
  process.exit(1);