blockmine 1.25.0 → 1.27.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 (164) hide show
  1. package/CHANGELOG.md +46 -3
  2. package/backend/cli.js +1 -1
  3. package/backend/package.json +2 -2
  4. package/backend/prisma/migrations/20260328173000_add_plugin_source_ref/migration.sql +2 -0
  5. package/backend/prisma/migrations/migration_lock.toml +2 -2
  6. package/backend/prisma/schema.prisma +2 -0
  7. package/backend/src/api/routes/apiKeys.js +8 -0
  8. package/backend/src/api/routes/bots.js +258 -9
  9. package/backend/src/api/routes/eventGraphs.js +151 -1
  10. package/backend/src/api/routes/health.js +38 -0
  11. package/backend/src/api/routes/nodeRegistry.js +63 -0
  12. package/backend/src/api/routes/plugins.js +254 -29
  13. package/backend/src/container.js +11 -8
  14. package/backend/src/core/BotCommandLoader.js +161 -0
  15. package/backend/src/core/BotConnection.js +125 -0
  16. package/backend/src/core/BotEventHandlers.js +234 -0
  17. package/backend/src/core/BotIPCHandler.js +445 -0
  18. package/backend/src/core/BotManager.js +15 -7
  19. package/backend/src/core/BotProcess.js +75 -142
  20. package/backend/src/core/EventGraphManager.js +7 -3
  21. package/backend/src/core/GraphDebugHandler.js +229 -0
  22. package/backend/src/core/GraphDebugIPC.js +117 -0
  23. package/backend/src/core/GraphExecutionEngine.js +545 -978
  24. package/backend/src/core/GraphTraversal.js +80 -0
  25. package/backend/src/core/GraphValidation.js +73 -0
  26. package/backend/src/core/NodeDefinition.js +138 -0
  27. package/backend/src/core/NodeRegistry.js +153 -141
  28. package/backend/src/core/PluginManager.js +272 -31
  29. package/backend/src/core/RewindSignal.js +9 -0
  30. package/backend/src/core/config/ConfigValidator.js +72 -0
  31. package/backend/src/core/config/FeatureFlags.js +52 -0
  32. package/backend/src/core/config/__tests__/ConfigValidator.test.js +232 -0
  33. package/backend/src/core/domain/entities/Bot.js +39 -0
  34. package/backend/src/core/domain/entities/Command.js +41 -0
  35. package/backend/src/core/domain/entities/EventGraph.js +39 -0
  36. package/backend/src/core/domain/entities/Plugin.js +45 -0
  37. package/backend/src/core/domain/entities/User.js +40 -0
  38. package/backend/src/core/domain/services/DependencyResolver.js +168 -0
  39. package/backend/src/core/domain/services/GraphValidator.js +117 -0
  40. package/backend/src/core/domain/services/PermissionChecker.js +34 -0
  41. package/backend/src/core/domain/services/__tests__/DependencyResolver.test.js +126 -0
  42. package/backend/src/core/domain/valueObjects/BotConfig.js +27 -0
  43. package/backend/src/core/domain/valueObjects/DependencyGraph.js +86 -0
  44. package/backend/src/core/domain/valueObjects/PluginManifest.js +36 -0
  45. package/backend/src/core/errors/BaseError.js +29 -0
  46. package/backend/src/core/errors/ErrorHandler.js +81 -0
  47. package/backend/src/core/errors/__tests__/ErrorHandler.test.js +188 -0
  48. package/backend/src/core/errors/index.js +68 -0
  49. package/backend/src/core/infrastructure/BatchingUtility.js +66 -0
  50. package/backend/src/core/infrastructure/CircuitBreaker.js +103 -0
  51. package/backend/src/core/infrastructure/ConnectionPool.js +81 -0
  52. package/backend/src/core/infrastructure/RateLimiter.js +64 -0
  53. package/backend/src/core/infrastructure/__tests__/BatchingUtility.test.js +86 -0
  54. package/backend/src/core/infrastructure/__tests__/CircuitBreaker.test.js +156 -0
  55. package/backend/src/core/infrastructure/__tests__/ConnectionPool.test.js +146 -0
  56. package/backend/src/core/infrastructure/__tests__/RateLimiter.test.js +171 -0
  57. package/backend/src/core/ipc/botApiFactory.js +72 -0
  58. package/backend/src/core/ipc/ipcMessageTypes.js +115 -0
  59. package/backend/src/core/logging/AuditLogger.js +61 -0
  60. package/backend/src/core/logging/StructuredLogger.js +80 -0
  61. package/backend/src/core/logging/__tests__/StructuredLogger.test.js +213 -0
  62. package/backend/src/core/logging/index.js +7 -0
  63. package/backend/src/core/metrics/MetricsCollector.js +104 -0
  64. package/backend/src/core/metrics/__tests__/MetricsCollector.test.js +131 -0
  65. package/backend/src/core/node-registries/actionsNodes.js +191 -0
  66. package/backend/src/core/node-registries/arraysNodes.js +152 -0
  67. package/backend/src/core/node-registries/botNodes.js +48 -0
  68. package/backend/src/core/node-registries/containerNodes.js +141 -0
  69. package/backend/src/core/node-registries/dataNodes.js +284 -0
  70. package/backend/src/core/node-registries/debugNodes.js +23 -0
  71. package/backend/src/core/node-registries/eventsNodes.js +223 -0
  72. package/backend/src/core/node-registries/flowNodes.js +151 -0
  73. package/backend/src/core/node-registries/furnaceNodes.js +123 -0
  74. package/backend/src/core/node-registries/index.js +108 -0
  75. package/backend/src/core/node-registries/inventory.js +102 -106
  76. package/backend/src/core/node-registries/logicNodes.js +54 -0
  77. package/backend/src/core/node-registries/mathNodes.js +38 -0
  78. package/backend/src/core/node-registries/navigationNodes.js +109 -0
  79. package/backend/src/core/node-registries/objectsNodes.js +90 -0
  80. package/backend/src/core/node-registries/stringsNodes.js +165 -0
  81. package/backend/src/core/node-registries/timeNodes.js +105 -0
  82. package/backend/src/core/node-registries/typeNodes.js +22 -0
  83. package/backend/src/core/node-registries/usersNodes.js +126 -0
  84. package/backend/src/core/nodes/arrays/shuffle.js +14 -0
  85. package/backend/src/core/nodes/bot/get_name.js +8 -0
  86. package/backend/src/core/nodes/bot/stop_bot.js +5 -0
  87. package/backend/src/core/nodes/container/open.js +101 -111
  88. package/backend/src/core/nodes/data/store_read.js +26 -0
  89. package/backend/src/core/nodes/data/store_write.js +23 -0
  90. package/backend/src/core/nodes/event/call_event.js +31 -0
  91. package/backend/src/core/nodes/event/custom_event.js +8 -0
  92. package/backend/src/core/nodes/flow/timer.js +35 -0
  93. package/backend/src/core/nodes/inventory/drop.js +73 -65
  94. package/backend/src/core/nodes/inventory/equip.js +54 -45
  95. package/backend/src/core/nodes/inventory/select_slot.js +48 -46
  96. package/backend/src/core/nodes/navigation/follow.js +54 -51
  97. package/backend/src/core/nodes/navigation/go_to.js +41 -53
  98. package/backend/src/core/nodes/navigation/go_to_entity.js +65 -69
  99. package/backend/src/core/nodes/navigation/go_to_player.js +65 -70
  100. package/backend/src/core/nodes/navigation/stop.js +17 -26
  101. package/backend/src/core/nodes/users/add_to_group.js +24 -0
  102. package/backend/src/core/nodes/users/check_permission.js +26 -0
  103. package/backend/src/core/nodes/users/remove_from_group.js +24 -0
  104. package/backend/src/core/services/BotIPCMessageRouter.js +337 -0
  105. package/backend/src/core/services/BotLifecycleService.js +41 -632
  106. package/backend/src/core/services/CacheManager.js +83 -23
  107. package/backend/src/core/services/CrashRestartManager.js +42 -0
  108. package/backend/src/core/services/DebugSessionManager.js +114 -12
  109. package/backend/src/core/services/EventGraphService.js +69 -0
  110. package/backend/src/core/services/MinecraftBotManager.js +9 -1
  111. package/backend/src/core/services/PluginManagementService.js +84 -0
  112. package/backend/src/core/services/TestModeContext.js +65 -0
  113. package/backend/src/core/services/__tests__/CacheManager.test.js +168 -0
  114. package/backend/src/core/services.js +1 -11
  115. package/backend/src/core/validation/InputValidator.js +167 -0
  116. package/backend/src/core/validation/__tests__/InputValidator.test.js +296 -0
  117. package/backend/src/real-time/botApi/index.js +1 -1
  118. package/backend/src/real-time/socketHandler.js +26 -0
  119. package/backend/src/server.js +10 -5
  120. package/frontend/dist/assets/{browser-ponyfill-DN7pwmHT.js → browser-ponyfill-D8y0Ty7C.js} +1 -1
  121. package/frontend/dist/assets/index-CFJLS0dk.css +32 -0
  122. package/frontend/dist/assets/{index-LSy71uwm.js → index-D91UGNMG.js} +1880 -1881
  123. package/frontend/dist/index.html +2 -2
  124. package/frontend/dist/locales/en/bots.json +4 -1
  125. package/frontend/dist/locales/en/common.json +7 -1
  126. package/frontend/dist/locales/en/login.json +2 -0
  127. package/frontend/dist/locales/en/management.json +79 -1
  128. package/frontend/dist/locales/en/nodes.json +59 -4
  129. package/frontend/dist/locales/en/plugin-detail.json +24 -4
  130. package/frontend/dist/locales/en/plugins.json +226 -7
  131. package/frontend/dist/locales/en/setup.json +2 -0
  132. package/frontend/dist/locales/en/sidebar.json +171 -3
  133. package/frontend/dist/locales/en/visual-editor.json +230 -31
  134. package/frontend/dist/locales/ru/bots.json +4 -1
  135. package/frontend/dist/locales/ru/login.json +2 -0
  136. package/frontend/dist/locales/ru/management.json +79 -1
  137. package/frontend/dist/locales/ru/minecraft-viewer.json +3 -0
  138. package/frontend/dist/locales/ru/nodes.json +105 -51
  139. package/frontend/dist/locales/ru/plugins.json +103 -4
  140. package/frontend/dist/locales/ru/setup.json +2 -0
  141. package/frontend/dist/locales/ru/sidebar.json +171 -3
  142. package/frontend/dist/locales/ru/visual-editor.json +232 -33
  143. package/frontend/package.json +2 -0
  144. package/nul +12 -0
  145. package/package.json +3 -3
  146. package/backend/package-lock.json +0 -6801
  147. package/backend/src/core/node-registries/actions.js +0 -202
  148. package/backend/src/core/node-registries/arrays.js +0 -155
  149. package/backend/src/core/node-registries/bot.js +0 -23
  150. package/backend/src/core/node-registries/container.js +0 -162
  151. package/backend/src/core/node-registries/data.js +0 -290
  152. package/backend/src/core/node-registries/debug.js +0 -26
  153. package/backend/src/core/node-registries/events.js +0 -201
  154. package/backend/src/core/node-registries/flow.js +0 -139
  155. package/backend/src/core/node-registries/furnace.js +0 -143
  156. package/backend/src/core/node-registries/logic.js +0 -62
  157. package/backend/src/core/node-registries/math.js +0 -42
  158. package/backend/src/core/node-registries/navigation.js +0 -111
  159. package/backend/src/core/node-registries/objects.js +0 -98
  160. package/backend/src/core/node-registries/strings.js +0 -187
  161. package/backend/src/core/node-registries/time.js +0 -113
  162. package/backend/src/core/node-registries/type.js +0 -25
  163. package/backend/src/core/node-registries/users.js +0 -79
  164. package/frontend/dist/assets/index-SfhKxI4-.css +0 -32
@@ -1,45 +1,54 @@
1
- /**
2
- * inventory:equip - Экипировать предмет
3
- */
4
- async function evaluate(node, pinId, context, helpers) {
5
- const bot = context.bot;
6
- const itemName = await helpers.resolvePinValue(node, 'itemName');
7
- const destination = (await helpers.resolvePinValue(node, 'destination')) || 'hand';
8
-
9
- if (pinId === 'exec') {
10
- return true; // Exec output
11
- }
12
-
13
- if (!bot?.inventory || !itemName) {
14
- if (pinId === 'success') return false;
15
- return null;
16
- }
17
-
18
- try {
19
- // Ищем предмет в инвентаре
20
- const searchName = itemName.toLowerCase().replace('minecraft:', '');
21
- const item = bot.inventory.items().find(i =>
22
- i.name.toLowerCase().includes(searchName) ||
23
- i.displayName?.toLowerCase().includes(searchName)
24
- );
25
-
26
- if (!item) {
27
- if (pinId === 'success') return false;
28
- return null;
29
- }
30
-
31
- // Экипируем предмет
32
- await bot.equip(item, destination);
33
-
34
- if (pinId === 'success') {
35
- return true;
36
- }
37
- } catch (error) {
38
- console.error('[inventory:equip] Error:', error.message);
39
- if (pinId === 'success') return false;
40
- }
41
-
42
- return null;
43
- }
44
-
45
- module.exports = { evaluate };
1
+ async function execute(node, context, helpers) {
2
+ const { resolvePinValue, traverse, memo } = helpers;
3
+ const bot = context.bot;
4
+
5
+ if (!bot) {
6
+ memo.set(`${node.id}:success`, false);
7
+ await traverse(node, 'exec');
8
+ return;
9
+ }
10
+
11
+ const itemName = await resolvePinValue(node, 'itemName', node.data?.itemName);
12
+ const destination = await resolvePinValue(node, 'destination', node.data?.destination) || 'hand';
13
+
14
+ if (!itemName) {
15
+ memo.set(`${node.id}:success`, false);
16
+ await traverse(node, 'exec');
17
+ return;
18
+ }
19
+
20
+ try {
21
+ const searchName = itemName.toLowerCase().replace('minecraft:', '');
22
+ const item = bot.inventory.items().find(i =>
23
+ i.name.toLowerCase().includes(searchName) ||
24
+ i.displayName?.toLowerCase().includes(searchName)
25
+ );
26
+
27
+ if (!item) {
28
+ memo.set(`${node.id}:success`, false);
29
+ await traverse(node, 'exec');
30
+ return;
31
+ }
32
+
33
+ await bot.equip(item, destination);
34
+
35
+ memo.set(`${node.id}:success`, true);
36
+ await traverse(node, 'exec');
37
+ } catch (error) {
38
+ console.error('[inventory:equip] Error:', error.message);
39
+ memo.set(`${node.id}:success`, false);
40
+ await traverse(node, 'exec');
41
+ }
42
+ }
43
+
44
+ async function evaluate(node, pinId, context, helpers) {
45
+ const { memo } = helpers;
46
+
47
+ if (pinId === 'success') {
48
+ return memo.get(`${node.id}:success`) ?? false;
49
+ }
50
+
51
+ return null;
52
+ }
53
+
54
+ module.exports = { execute, evaluate };
@@ -1,46 +1,48 @@
1
- /**
2
- * inventory:select_slot - Выбрать слот хотбара
3
- */
4
- async function evaluate(node, pinId, context, helpers) {
5
- const bot = context.bot;
6
- const slot = await helpers.resolvePinValue(node, 'slot');
7
-
8
- if (pinId === 'exec') {
9
- return true; // Exec output
10
- }
11
-
12
- if (!bot?.inventory || slot === undefined || slot === null) {
13
- if (pinId === 'item') return null;
14
- return null;
15
- }
16
-
17
- try {
18
- // Валидация номера слота (0-8)
19
- const slotNumber = Math.max(0, Math.min(8, parseInt(slot)));
20
-
21
- // Устанавливаем выбранный слот
22
- bot.setQuickBarSlot(slotNumber);
23
-
24
- if (pinId === 'item') {
25
- // Возвращаем предмет в выбранном слоте
26
- const item = bot.inventory.slots[slotNumber + 36]; // Хотбар начинается с 36
27
- if (!item) return null;
28
-
29
- return {
30
- name: item.name,
31
- displayName: item.displayName,
32
- count: item.count,
33
- slot: item.slot,
34
- type: item.type,
35
- metadata: item.metadata
36
- };
37
- }
38
- } catch (error) {
39
- console.error('[inventory:select_slot] Error:', error.message);
40
- if (pinId === 'item') return null;
41
- }
42
-
43
- return null;
44
- }
45
-
46
- module.exports = { evaluate };
1
+ async function execute(node, context, helpers) {
2
+ const { resolvePinValue, traverse, memo } = helpers;
3
+ const bot = context.bot;
4
+
5
+ if (!bot) {
6
+ await traverse(node, 'exec');
7
+ return;
8
+ }
9
+
10
+ const slot = await resolvePinValue(node, 'slot', node.data?.slot);
11
+
12
+ if (slot === undefined || slot === null) {
13
+ await traverse(node, 'exec');
14
+ return;
15
+ }
16
+
17
+ try {
18
+ const slotNumber = Math.max(0, Math.min(8, parseInt(slot)));
19
+ bot.setQuickBarSlot(slotNumber);
20
+
21
+ const item = bot.inventory.slots[slotNumber + 36];
22
+ memo.set(`${node.id}:item`, item ? {
23
+ name: item.name,
24
+ displayName: item.displayName,
25
+ count: item.count,
26
+ slot: item.slot,
27
+ type: item.type,
28
+ metadata: item.metadata
29
+ } : null);
30
+
31
+ await traverse(node, 'exec');
32
+ } catch (error) {
33
+ console.error('[inventory:select_slot] Error:', error.message);
34
+ await traverse(node, 'exec');
35
+ }
36
+ }
37
+
38
+ async function evaluate(node, pinId, context, helpers) {
39
+ const { memo } = helpers;
40
+
41
+ if (pinId === 'item') {
42
+ return memo.get(`${node.id}:item`) ?? null;
43
+ }
44
+
45
+ return null;
46
+ }
47
+
48
+ module.exports = { execute, evaluate };
@@ -1,51 +1,54 @@
1
- const { goals } = require('mineflayer-pathfinder');
2
-
3
- /**
4
- * navigation:follow - Следовать за игроком
5
- */
6
- async function evaluate(node, pinId, context, helpers) {
7
- const bot = context.bot;
8
-
9
- if (pinId === 'exec') {
10
- return true;
11
- }
12
-
13
- if (!bot?.pathfinder) {
14
- if (pinId === 'following') return false;
15
- return null;
16
- }
17
-
18
- const target = await helpers.resolvePinValue(node, 'target');
19
- const range = (await helpers.resolvePinValue(node, 'range')) || 3;
20
-
21
- if (!target) {
22
- if (pinId === 'following') return false;
23
- return null;
24
- }
25
-
26
- try {
27
- const player = bot.players[target];
28
-
29
- if (!player?.entity) {
30
- console.error(`[navigation:follow] Player "${target}" not found or not visible`);
31
- if (pinId === 'following') return false;
32
- return null;
33
- }
34
-
35
- // Используем GoalFollow для непрерывного следования
36
- const goal = new goals.GoalFollow(player.entity, range);
37
- bot.pathfinder.setGoal(goal, true); // true = dynamic, обновляется при движении цели
38
-
39
- if (pinId === 'following') {
40
- return true;
41
- }
42
- } catch (error) {
43
- console.error('[navigation:follow] Error:', error.message);
44
-
45
- if (pinId === 'following') return false;
46
- }
47
-
48
- return null;
49
- }
50
-
51
- module.exports = { evaluate };
1
+ const { goals } = require('mineflayer-pathfinder');
2
+
3
+ async function execute(node, context, helpers) {
4
+ const { resolvePinValue, traverse, memo } = helpers;
5
+ const bot = context.bot;
6
+
7
+ if (!bot?.pathfinder) {
8
+ memo.set(`${node.id}:following`, false);
9
+ await traverse(node, 'exec');
10
+ return;
11
+ }
12
+
13
+ const target = await resolvePinValue(node, 'target', node.data?.target);
14
+ const range = await resolvePinValue(node, 'range', node.data?.range) ?? 3;
15
+
16
+ if (!target) {
17
+ memo.set(`${node.id}:following`, false);
18
+ await traverse(node, 'exec');
19
+ return;
20
+ }
21
+
22
+ try {
23
+ const player = bot.players[target];
24
+
25
+ if (!player?.entity) {
26
+ console.error(`[navigation:follow] Player "${target}" not found or not visible`);
27
+ memo.set(`${node.id}:following`, false);
28
+ await traverse(node, 'exec');
29
+ return;
30
+ }
31
+
32
+ const goal = new goals.GoalFollow(player.entity, Number(range));
33
+ bot.pathfinder.setGoal(goal, true);
34
+
35
+ memo.set(`${node.id}:following`, true);
36
+ await traverse(node, 'exec');
37
+ } catch (error) {
38
+ console.error('[navigation:follow] Error:', error.message);
39
+ memo.set(`${node.id}:following`, false);
40
+ await traverse(node, 'exec');
41
+ }
42
+ }
43
+
44
+ async function evaluate(node, pinId, context, helpers) {
45
+ const { memo } = helpers;
46
+
47
+ if (pinId === 'following') {
48
+ return memo.get(`${node.id}:following`) ?? false;
49
+ }
50
+
51
+ return null;
52
+ }
53
+
54
+ module.exports = { execute, evaluate };
@@ -1,53 +1,41 @@
1
- const { goals } = require('mineflayer-pathfinder');
2
-
3
- /**
4
- * navigation:go_to - Идти к указанным координатам
5
- */
6
- async function evaluate(node, pinId, context, helpers) {
7
- const bot = context.bot;
8
-
9
- if (pinId === 'exec' || pinId === 'exec_failed') {
10
- // Exec выходы обрабатываются движком
11
- return true;
12
- }
13
-
14
- if (!bot?.pathfinder) {
15
- if (pinId === 'success') return false;
16
- return null;
17
- }
18
-
19
- const x = await helpers.resolvePinValue(node, 'x');
20
- const y = await helpers.resolvePinValue(node, 'y');
21
- const z = await helpers.resolvePinValue(node, 'z');
22
- const range = (await helpers.resolvePinValue(node, 'range')) || 1;
23
-
24
- // Используем данные ноды если входы не подключены
25
- const targetX = x ?? node.data?.x ?? 0;
26
- const targetY = y ?? node.data?.y ?? 64;
27
- const targetZ = z ?? node.data?.z ?? 0;
28
-
29
- try {
30
- const goal = new goals.GoalNear(targetX, targetY, targetZ, range);
31
- await bot.pathfinder.goto(goal);
32
-
33
- if (pinId === 'success') {
34
- return true;
35
- }
36
-
37
- // Указываем движку какой exec выход активировать
38
- context._nextExecPin = 'exec';
39
- } catch (error) {
40
- console.error('[navigation:go_to] Error:', error.message);
41
-
42
- if (pinId === 'success') {
43
- return false;
44
- }
45
-
46
- // При ошибке активируем exec_failed
47
- context._nextExecPin = 'exec_failed';
48
- }
49
-
50
- return null;
51
- }
52
-
53
- module.exports = { evaluate };
1
+ const { goals } = require('mineflayer-pathfinder');
2
+
3
+ async function execute(node, context, helpers) {
4
+ const { resolvePinValue, traverse, memo } = helpers;
5
+ const bot = context.bot;
6
+
7
+ if (!bot?.pathfinder) {
8
+ memo.set(`${node.id}:success`, false);
9
+ await traverse(node, 'exec_failed');
10
+ return;
11
+ }
12
+
13
+ const x = await resolvePinValue(node, 'x', node.data?.x) ?? 0;
14
+ const y = await resolvePinValue(node, 'y', node.data?.y) ?? 64;
15
+ const z = await resolvePinValue(node, 'z', node.data?.z) ?? 0;
16
+ const range = await resolvePinValue(node, 'range', node.data?.range) ?? 1;
17
+
18
+ try {
19
+ const goal = new goals.GoalNear(Number(x), Number(y), Number(z), Number(range));
20
+ await bot.pathfinder.goto(goal);
21
+
22
+ memo.set(`${node.id}:success`, true);
23
+ await traverse(node, 'exec');
24
+ } catch (error) {
25
+ console.error('[navigation:go_to] Error:', error.message);
26
+ memo.set(`${node.id}:success`, false);
27
+ await traverse(node, 'exec_failed');
28
+ }
29
+ }
30
+
31
+ async function evaluate(node, pinId, context, helpers) {
32
+ const { memo } = helpers;
33
+
34
+ if (pinId === 'success') {
35
+ return memo.get(`${node.id}:success`) ?? false;
36
+ }
37
+
38
+ return null;
39
+ }
40
+
41
+ module.exports = { execute, evaluate };
@@ -1,69 +1,65 @@
1
- const { goals } = require('mineflayer-pathfinder');
2
-
3
- /**
4
- * navigation:go_to_entity - Идти к сущности
5
- */
6
- async function evaluate(node, pinId, context, helpers) {
7
- const bot = context.bot;
8
-
9
- if (pinId === 'exec' || pinId === 'exec_failed') {
10
- return true;
11
- }
12
-
13
- if (!bot?.pathfinder) {
14
- if (pinId === 'success') return false;
15
- return null;
16
- }
17
-
18
- const entityData = await helpers.resolvePinValue(node, 'entity');
19
- const range = (await helpers.resolvePinValue(node, 'range')) || 2;
20
-
21
- if (!entityData) {
22
- if (pinId === 'success') return false;
23
- context._nextExecPin = 'exec_failed';
24
- return null;
25
- }
26
-
27
- try {
28
- // entityData может быть объектом с id или position
29
- let targetPos;
30
-
31
- if (entityData.id !== undefined) {
32
- // Ищем актуальную сущность по id
33
- const entity = bot.entities[entityData.id];
34
- if (entity?.position) {
35
- targetPos = entity.position;
36
- }
37
- }
38
-
39
- if (!targetPos && entityData.position) {
40
- targetPos = entityData.position;
41
- }
42
-
43
- if (!targetPos) {
44
- console.error('[navigation:go_to_entity] Entity position not found');
45
- if (pinId === 'success') return false;
46
- context._nextExecPin = 'exec_failed';
47
- return null;
48
- }
49
-
50
- const goal = new goals.GoalNear(targetPos.x, targetPos.y, targetPos.z, range);
51
- await bot.pathfinder.goto(goal);
52
-
53
- if (pinId === 'success') {
54
- return true;
55
- }
56
-
57
- context._nextExecPin = 'exec';
58
- } catch (error) {
59
- console.error('[navigation:go_to_entity] Error:', error.message);
60
-
61
- if (pinId === 'success') return false;
62
-
63
- context._nextExecPin = 'exec_failed';
64
- }
65
-
66
- return null;
67
- }
68
-
69
- module.exports = { evaluate };
1
+ const { goals } = require('mineflayer-pathfinder');
2
+
3
+ async function execute(node, context, helpers) {
4
+ const { resolvePinValue, traverse, memo } = helpers;
5
+ const bot = context.bot;
6
+
7
+ if (!bot?.pathfinder) {
8
+ memo.set(`${node.id}:success`, false);
9
+ await traverse(node, 'exec_failed');
10
+ return;
11
+ }
12
+
13
+ const entityData = await resolvePinValue(node, 'entity', null);
14
+ const range = await resolvePinValue(node, 'range', node.data?.range) ?? 2;
15
+
16
+ if (!entityData) {
17
+ memo.set(`${node.id}:success`, false);
18
+ await traverse(node, 'exec_failed');
19
+ return;
20
+ }
21
+
22
+ try {
23
+ let targetPos;
24
+
25
+ if (entityData.id !== undefined) {
26
+ const entity = bot.entities[entityData.id];
27
+ if (entity?.position) {
28
+ targetPos = entity.position;
29
+ }
30
+ }
31
+
32
+ if (!targetPos && entityData.position) {
33
+ targetPos = entityData.position;
34
+ }
35
+
36
+ if (!targetPos) {
37
+ console.error('[navigation:go_to_entity] Entity position not found');
38
+ memo.set(`${node.id}:success`, false);
39
+ await traverse(node, 'exec_failed');
40
+ return;
41
+ }
42
+
43
+ const goal = new goals.GoalNear(targetPos.x, targetPos.y, targetPos.z, Number(range));
44
+ await bot.pathfinder.goto(goal);
45
+
46
+ memo.set(`${node.id}:success`, true);
47
+ await traverse(node, 'exec');
48
+ } catch (error) {
49
+ console.error('[navigation:go_to_entity] Error:', error.message);
50
+ memo.set(`${node.id}:success`, false);
51
+ await traverse(node, 'exec_failed');
52
+ }
53
+ }
54
+
55
+ async function evaluate(node, pinId, context, helpers) {
56
+ const { memo } = helpers;
57
+
58
+ if (pinId === 'success') {
59
+ return memo.get(`${node.id}:success`) ?? false;
60
+ }
61
+
62
+ return null;
63
+ }
64
+
65
+ module.exports = { execute, evaluate };