blockmine 1.25.0 → 1.27.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.
Files changed (165) hide show
  1. package/CHANGELOG.md +46 -1
  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/scripts/postinstall.js +38 -0
  147. package/backend/package-lock.json +0 -6801
  148. package/backend/src/core/node-registries/actions.js +0 -202
  149. package/backend/src/core/node-registries/arrays.js +0 -155
  150. package/backend/src/core/node-registries/bot.js +0 -23
  151. package/backend/src/core/node-registries/container.js +0 -162
  152. package/backend/src/core/node-registries/data.js +0 -290
  153. package/backend/src/core/node-registries/debug.js +0 -26
  154. package/backend/src/core/node-registries/events.js +0 -201
  155. package/backend/src/core/node-registries/flow.js +0 -139
  156. package/backend/src/core/node-registries/furnace.js +0 -143
  157. package/backend/src/core/node-registries/logic.js +0 -62
  158. package/backend/src/core/node-registries/math.js +0 -42
  159. package/backend/src/core/node-registries/navigation.js +0 -111
  160. package/backend/src/core/node-registries/objects.js +0 -98
  161. package/backend/src/core/node-registries/strings.js +0 -187
  162. package/backend/src/core/node-registries/time.js +0 -113
  163. package/backend/src/core/node-registries/type.js +0 -25
  164. package/backend/src/core/node-registries/users.js +0 -79
  165. package/frontend/dist/assets/index-SfhKxI4-.css +0 -32
@@ -0,0 +1,151 @@
1
+ const { GRAPH_TYPES } = require('../../core/constants/graphTypes');
2
+
3
+ const flowNodes = [
4
+ {
5
+ type: 'flow:branch',
6
+ label: '↔️ Ветвление (Branch)',
7
+ category: 'Поток',
8
+ description: 'if/else логика',
9
+ graphType: GRAPH_TYPES.ALL,
10
+ executor: require('../../core/nodes/flow/branch').execute,
11
+ computeInputs: (data) => [
12
+ { id: 'exec', name: 'Выполнить', type: 'Exec', required: true },
13
+ { id: 'condition', name: 'Условие', type: 'Boolean', required: true }
14
+ ],
15
+ computeOutputs: (data) => [
16
+ { id: 'exec_true', name: 'True', type: 'Exec' },
17
+ { id: 'exec_false', name: 'False', type: 'Exec' }
18
+ ],
19
+ defaultData: {},
20
+ theme: { headerColor: '#10b981', accentColor: '#34d399' }
21
+ },
22
+ {
23
+ type: 'flow:sequence',
24
+ label: '⛓️ Последовательность',
25
+ category: 'Поток',
26
+ description: 'Выполняет действия по очереди',
27
+ graphType: GRAPH_TYPES.ALL,
28
+ executor: require('../../core/nodes/flow/sequence').execute,
29
+ computeInputs: (data) => [
30
+ { id: 'exec', name: 'Выполнить', type: 'Exec', required: true }
31
+ ],
32
+ computeOutputs: (data) => [
33
+ { id: 'exec_0', name: '0', type: 'Exec' },
34
+ { id: 'exec_1', name: '1', type: 'Exec' }
35
+ ],
36
+ defaultData: {},
37
+ theme: { headerColor: '#10b981', accentColor: '#34d399' }
38
+ },
39
+ {
40
+ type: 'flow:for_each',
41
+ label: '🔁 Перебор (for)',
42
+ category: 'Поток',
43
+ description: 'Выполняет "Тело цикла" для каждого элемента в "Массиве".',
44
+ graphType: GRAPH_TYPES.ALL,
45
+ executor: require('../../core/nodes/flow/for_each').execute,
46
+ computeInputs: (data) => [
47
+ { id: 'exec', name: 'Выполнить', type: 'Exec', required: true },
48
+ { id: 'array', name: 'Массив', type: 'Array', required: true }
49
+ ],
50
+ computeOutputs: (data) => [
51
+ { id: 'loop_body', name: 'Тело цикла', type: 'Exec' },
52
+ { id: 'element', name: 'Элемент', type: 'Any' },
53
+ { id: 'index', name: 'Индекс', type: 'Number' },
54
+ { id: 'completed', name: 'Завершено', type: 'Exec' }
55
+ ],
56
+ defaultData: {},
57
+ theme: { headerColor: '#10b981', accentColor: '#34d399' }
58
+ },
59
+ {
60
+ type: 'flow:while',
61
+ label: '🔁 Цикл While',
62
+ category: 'Поток',
63
+ description: 'Выполняет "Тело цикла" пока условие истинно.',
64
+ graphType: GRAPH_TYPES.ALL,
65
+ executor: require('../../core/nodes/flow/while').execute,
66
+ evaluator: require('../../core/nodes/flow/while').evaluate,
67
+ computeInputs: (data) => [
68
+ { id: 'exec', name: 'Выполнить', type: 'Exec', required: true },
69
+ { id: 'condition', name: 'Условие', type: 'Boolean', required: true }
70
+ ],
71
+ computeOutputs: (data) => [
72
+ { id: 'loop_body', name: 'Тело цикла', type: 'Exec' },
73
+ { id: 'iteration', name: 'Итерация', type: 'Number' },
74
+ { id: 'completed', name: 'Завершено', type: 'Exec' }
75
+ ],
76
+ defaultData: {},
77
+ theme: { headerColor: '#10b981', accentColor: '#34d399' }
78
+ },
79
+ {
80
+ type: 'flow:break',
81
+ label: '🛑 Break (выйти из цикла)',
82
+ category: 'Поток',
83
+ description: 'Немедленно прерывает выполнение цикла и передает управление на его выход Завершено.',
84
+ graphType: GRAPH_TYPES.ALL,
85
+ executor: require('../../core/nodes/flow/break').execute,
86
+ computeInputs: (data) => [
87
+ { id: 'exec', name: 'Выполнить', type: 'Exec', required: true }
88
+ ],
89
+ computeOutputs: (data) => [],
90
+ defaultData: {},
91
+ theme: { headerColor: '#10b981', accentColor: '#34d399' }
92
+ },
93
+ {
94
+ type: 'flow:delay',
95
+ label: '⏱️ Задержка',
96
+ category: 'Поток',
97
+ description: 'Ожидает указанное количество миллисекунд, затем продолжает выполнение.',
98
+ graphType: GRAPH_TYPES.ALL,
99
+ executor: require('../../core/nodes/flow/delay').execute,
100
+ computeInputs: (data) => [
101
+ { id: 'exec', name: 'Выполнить', type: 'Exec', required: true },
102
+ { id: 'delay', name: 'Задержка (мс)', type: 'Number', required: false, inlineField: true, placeholder: '1000' }
103
+ ],
104
+ computeOutputs: (data) => [
105
+ { id: 'exec', name: 'Далее', type: 'Exec' }
106
+ ],
107
+ defaultData: { delay: 1000 },
108
+ theme: { headerColor: '#10b981', accentColor: '#34d399' }
109
+ },
110
+ {
111
+ type: 'flow:switch',
112
+ label: '🔀 Switch',
113
+ category: 'Поток',
114
+ description: 'Выполняет разные действия в зависимости от значения.',
115
+ graphType: GRAPH_TYPES.ALL,
116
+ dynamicPins: true,
117
+ executor: require('../../core/nodes/flow/switch').execute,
118
+ computeInputs: (data) => [
119
+ { id: 'exec', name: 'Выполнить', type: 'Exec', required: true },
120
+ { id: 'value', name: 'Значение', type: 'Wildcard', required: true }
121
+ ],
122
+ computeOutputs: (data) => [
123
+ { id: 'default', name: 'Default', type: 'Exec' }
124
+ ],
125
+ defaultData: {},
126
+ theme: { headerColor: '#10b981', accentColor: '#34d399' }
127
+ },
128
+ {
129
+ type: 'flow:timer',
130
+ label: '⏲️ Таймер',
131
+ category: 'Поток',
132
+ description: 'Выполняет тело цикла каждые N секунд. Можно прервать через Break.',
133
+ graphType: GRAPH_TYPES.ALL,
134
+ executor: require('../../core/nodes/flow/timer').execute,
135
+ evaluator: require('../../core/nodes/flow/timer').evaluate,
136
+ computeInputs: (data) => [
137
+ { id: 'exec', name: 'Выполнить', type: 'Exec', required: true },
138
+ { id: 'interval', name: 'Интервал (сек)', type: 'Number', required: false, inlineField: true, placeholder: '1' },
139
+ { id: 'max_ticks', name: 'Макс. тиков (0 = ∞)', type: 'Number', required: false, inlineField: true, placeholder: '0' }
140
+ ],
141
+ computeOutputs: (data) => [
142
+ { id: 'loop_body', name: 'Тело цикла', type: 'Exec' },
143
+ { id: 'tick', name: 'Тик', type: 'Number' },
144
+ { id: 'completed', name: 'Завершено', type: 'Exec' }
145
+ ],
146
+ defaultData: { interval: 1, max_ticks: 0 },
147
+ theme: { headerColor: '#10b981', accentColor: '#34d399' }
148
+ },
149
+ ];
150
+
151
+ module.exports = flowNodes;
@@ -0,0 +1,123 @@
1
+ const { GRAPH_TYPES } = require('../../core/constants/graphTypes');
2
+
3
+ const furnaceNodes = [
4
+ {
5
+ type: 'furnace:open',
6
+ label: '🔥 Печка: открыть',
7
+ category: 'Печка',
8
+ description: 'Открывает печку (обычную, плавильную, коптильню) по координатам.',
9
+ graphType: GRAPH_TYPES.ALL,
10
+ executor: require('../../core/nodes/furnace/open').execute,
11
+ evaluator: require('../../core/nodes/furnace/open').evaluate,
12
+ computeInputs: (data) => [
13
+ { id: 'exec', name: 'Выполнить', type: 'Exec' },
14
+ { id: 'x', name: 'X', type: 'Number', required: false, inlineField: true, placeholder: '0' },
15
+ { id: 'y', name: 'Y', type: 'Number', required: false, inlineField: true, placeholder: '64' },
16
+ { id: 'z', name: 'Z', type: 'Number', required: false, inlineField: true, placeholder: '0' }
17
+ ],
18
+ computeOutputs: (data) => [
19
+ { id: 'exec', name: 'Открыта', type: 'Exec' },
20
+ { id: 'exec_failed', name: 'Ошибка', type: 'Exec' },
21
+ { id: 'furnace', name: 'Печка', type: 'Object' },
22
+ { id: 'success', name: 'Успех?', type: 'Boolean' }
23
+ ],
24
+ defaultData: { x: 0, y: 64, z: 0 },
25
+ theme: { headerColor: '#ef4444', accentColor: '#f87171' }
26
+ },
27
+ {
28
+ type: 'furnace:close',
29
+ label: '🔥 Печка: закрыть',
30
+ category: 'Печка',
31
+ description: 'Закрывает открытую печку.',
32
+ graphType: GRAPH_TYPES.ALL,
33
+ executor: require('../../core/nodes/furnace/close').execute,
34
+ computeInputs: () => [{ id: 'exec', name: 'Выполнить', type: 'Exec' }],
35
+ computeOutputs: () => [{ id: 'exec', name: 'Далее', type: 'Exec' }],
36
+ defaultData: {},
37
+ theme: { headerColor: '#ef4444', accentColor: '#f87171' }
38
+ },
39
+ {
40
+ type: 'furnace:put_input',
41
+ label: '🔥 Печка: положить для плавки',
42
+ category: 'Печка',
43
+ description: 'Кладёт предмет в слот плавки печки.',
44
+ graphType: GRAPH_TYPES.ALL,
45
+ executor: require('../../core/nodes/furnace/put_input').execute,
46
+ evaluator: require('../../core/nodes/furnace/put_input').evaluate,
47
+ computeInputs: (data) => [
48
+ { id: 'exec', name: 'Выполнить', type: 'Exec' },
49
+ { id: 'itemName', name: 'Предмет', type: 'String', required: true, inlineField: true, placeholder: 'iron_ore...' },
50
+ { id: 'count', name: 'Кол-во', type: 'Number', required: false, inlineField: true, placeholder: 'Все' }
51
+ ],
52
+ computeOutputs: (data) => [
53
+ { id: 'exec', name: 'Положено', type: 'Exec' },
54
+ { id: 'exec_failed', name: 'Ошибка', type: 'Exec' },
55
+ { id: 'success', name: 'Успех?', type: 'Boolean' }
56
+ ],
57
+ defaultData: { itemName: '', count: null },
58
+ theme: { headerColor: '#ef4444', accentColor: '#f87171' }
59
+ },
60
+ {
61
+ type: 'furnace:put_fuel',
62
+ label: '🔥 Печка: положить топливо',
63
+ category: 'Печка',
64
+ description: 'Кладёт топливо в слот топлива печки.',
65
+ graphType: GRAPH_TYPES.ALL,
66
+ executor: require('../../core/nodes/furnace/put_fuel').execute,
67
+ evaluator: require('../../core/nodes/furnace/put_fuel').evaluate,
68
+ computeInputs: (data) => [
69
+ { id: 'exec', name: 'Выполнить', type: 'Exec' },
70
+ { id: 'itemName', name: 'Топливо', type: 'String', required: true, inlineField: true, placeholder: 'coal...' },
71
+ { id: 'count', name: 'Кол-во', type: 'Number', required: false, inlineField: true, placeholder: 'Все' }
72
+ ],
73
+ computeOutputs: (data) => [
74
+ { id: 'exec', name: 'Положено', type: 'Exec' },
75
+ { id: 'exec_failed', name: 'Ошибка', type: 'Exec' },
76
+ { id: 'success', name: 'Успех?', type: 'Boolean' }
77
+ ],
78
+ defaultData: { itemName: '', count: null },
79
+ theme: { headerColor: '#ef4444', accentColor: '#f87171' }
80
+ },
81
+ {
82
+ type: 'furnace:take_output',
83
+ label: '🔥 Печка: забрать результат',
84
+ category: 'Печка',
85
+ description: 'Забирает готовый предмет из слота результата печки.',
86
+ graphType: GRAPH_TYPES.ALL,
87
+ executor: require('../../core/nodes/furnace/take_output').execute,
88
+ evaluator: require('../../core/nodes/furnace/take_output').evaluate,
89
+ computeInputs: (data) => [
90
+ { id: 'exec', name: 'Выполнить', type: 'Exec' }
91
+ ],
92
+ computeOutputs: (data) => [
93
+ { id: 'exec', name: 'Забрано', type: 'Exec' },
94
+ { id: 'exec_failed', name: 'Пусто/Ошибка', type: 'Exec' },
95
+ { id: 'item', name: 'Предмет', type: 'Object' },
96
+ { id: 'count', name: 'Кол-во', type: 'Number' },
97
+ { id: 'success', name: 'Успех?', type: 'Boolean' }
98
+ ],
99
+ defaultData: {},
100
+ theme: { headerColor: '#ef4444', accentColor: '#f87171' }
101
+ },
102
+ {
103
+ type: 'furnace:get_status',
104
+ label: '🔥 Печка: статус',
105
+ category: 'Печка',
106
+ description: 'Получает текущий статус печки (топливо, прогресс, предметы).',
107
+ graphType: GRAPH_TYPES.ALL,
108
+ evaluator: require('../../core/nodes/furnace/get_status').evaluate,
109
+ computeInputs: () => [],
110
+ computeOutputs: () => [
111
+ { id: 'inputItem', name: 'Плавится', type: 'Object' },
112
+ { id: 'fuelItem', name: 'Топливо', type: 'Object' },
113
+ { id: 'outputItem', name: 'Результат', type: 'Object' },
114
+ { id: 'fuel', name: 'Топливо %', type: 'Number' },
115
+ { id: 'progress', name: 'Прогресс %', type: 'Number' },
116
+ { id: 'isBurning', name: 'Горит?', type: 'Boolean' }
117
+ ],
118
+ defaultData: {},
119
+ theme: { headerColor: '#ef4444', accentColor: '#f87171' }
120
+ }
121
+ ];
122
+
123
+ module.exports = furnaceNodes;
@@ -0,0 +1,108 @@
1
+ const path = require('path');
2
+ const fs = require('fs');
3
+
4
+ const { NodeDefinition } = require('../../core/NodeDefinition');
5
+ const { GRAPH_TYPES } = require('../../core/constants/graphTypes');
6
+
7
+ function registerAllNodes(registry) {
8
+ const registriesDir = path.join(__dirname);
9
+
10
+ try {
11
+ const files = fs.readdirSync(registriesDir)
12
+ .filter(file => file.endsWith('.js') && file !== 'index.js' && file !== 'registerAllNodes.js');
13
+
14
+ for (const file of files) {
15
+ try {
16
+ const modulePath = path.join(registriesDir, file);
17
+ const registryModule = require(modulePath);
18
+
19
+ if (typeof registryModule.registerNodes === 'function') {
20
+ registryModule.registerNodes(registry);
21
+ } else if (Array.isArray(registryModule)) {
22
+ for (const def of registryModule) {
23
+ registry.registerNodeType(def);
24
+ }
25
+ }
26
+ } catch (error) {
27
+ console.error(`[Node Registries] Error loading ${file}:`, error.message);
28
+ }
29
+ }
30
+ } catch (error) {
31
+ console.error('[Node Registries] Error reading directory:', error.message);
32
+ }
33
+ }
34
+
35
+ function createNodeDefinitions() {
36
+ const nodes = {};
37
+ const registriesDir = __dirname;
38
+
39
+ try {
40
+ const files = fs.readdirSync(registriesDir)
41
+ .filter(file => file.endsWith('.js') && file !== 'index.js' && file !== 'registerAllNodes.js');
42
+
43
+ for (const file of files) {
44
+ try {
45
+ const modulePath = path.join(registriesDir, file);
46
+ const registryModule = require(modulePath);
47
+
48
+ if (Array.isArray(registryModule)) {
49
+ for (const def of registryModule) {
50
+ if (def instanceof NodeDefinition || (def.type && def.label)) {
51
+ nodes[def.type] = def instanceof NodeDefinition ? def.toJSON() : def;
52
+ }
53
+ }
54
+ }
55
+ } catch (error) {
56
+ console.error(`[Node Registries] Error creating definitions from ${file}:`, error.message);
57
+ }
58
+ }
59
+ } catch (error) {
60
+ console.error('[Node Registries] Error reading directory:', error.message);
61
+ }
62
+
63
+ return nodes;
64
+ }
65
+
66
+ function getNodesByCategory(grouped = true) {
67
+ const allNodes = createNodeDefinitions();
68
+ const byCategory = {};
69
+
70
+ for (const [type, node] of Object.entries(allNodes)) {
71
+ const category = node.category || 'Other';
72
+
73
+ if (!byCategory[category]) {
74
+ byCategory[category] = [];
75
+ }
76
+
77
+ byCategory[category].push({
78
+ ...node,
79
+ type
80
+ });
81
+ }
82
+
83
+ if (grouped) {
84
+ return byCategory;
85
+ }
86
+
87
+ return Object.values(byCategory).flat();
88
+ }
89
+
90
+ function getNodeDefinition(type) {
91
+ const allNodes = createNodeDefinitions();
92
+ return allNodes[type] || null;
93
+ }
94
+
95
+ function getAllNodeTypes() {
96
+ const allNodes = createNodeDefinitions();
97
+ return Object.keys(allNodes);
98
+ }
99
+
100
+ module.exports = {
101
+ registerAllNodes,
102
+ createNodeDefinitions,
103
+ getNodesByCategory,
104
+ getNodeDefinition,
105
+ getAllNodeTypes,
106
+ NodeDefinition,
107
+ GRAPH_TYPES
108
+ };
@@ -1,25 +1,20 @@
1
- const { GRAPH_TYPES } = require('../constants/graphTypes');
1
+ const { GRAPH_TYPES } = require('../../core/constants/graphTypes');
2
2
 
3
- /**
4
- * Регистрация нод категории "Инвентарь"
5
- */
6
3
  function registerNodes(registry) {
7
- // ========== DATA NODES ==========
8
-
9
4
  registry.registerNodeType({
10
5
  type: 'inventory:get_all',
11
6
  label: '📦 Весь инвентарь',
12
7
  category: 'Инвентарь',
13
8
  description: 'Возвращает весь инвентарь бота как массив предметов.',
14
9
  graphType: GRAPH_TYPES.ALL,
15
- evaluator: require('../nodes/inventory/get_all').evaluate,
16
- pins: {
17
- inputs: [],
18
- outputs: [
19
- { id: 'items', name: 'Предметы', type: 'Array' },
20
- { id: 'count', name: 'Кол-во слотов', type: 'Number' }
21
- ]
22
- }
10
+ evaluator: require('../../core/nodes/inventory/get_all').evaluate,
11
+ computeInputs: () => [],
12
+ computeOutputs: () => [
13
+ { id: 'items', name: 'Предметы', type: 'Array' },
14
+ { id: 'count', name: 'Кол-во слотов', type: 'Number' }
15
+ ],
16
+ defaultData: {},
17
+ theme: { headerColor: '#f59e0b', accentColor: '#fbbf24' }
23
18
  });
24
19
 
25
20
  registry.registerNodeType({
@@ -28,17 +23,17 @@ function registerNodes(registry) {
28
23
  category: 'Инвентарь',
29
24
  description: 'Ищет предмет в инвентаре по имени.',
30
25
  graphType: GRAPH_TYPES.ALL,
31
- evaluator: require('../nodes/inventory/find_item').evaluate,
32
- pins: {
33
- inputs: [
34
- { id: 'itemName', name: 'Имя предмета', type: 'String', required: true }
35
- ],
36
- outputs: [
37
- { id: 'item', name: 'Предмет', type: 'Object' },
38
- { id: 'found', name: 'Найден?', type: 'Boolean' },
39
- { id: 'slot', name: 'Слот', type: 'Number' }
40
- ]
41
- }
26
+ evaluator: require('../../core/nodes/inventory/find_item').evaluate,
27
+ computeInputs: (data) => [
28
+ { id: 'itemName', name: 'Имя предмета', type: 'String', required: true, inlineField: true, placeholder: 'diamond...' }
29
+ ],
30
+ computeOutputs: () => [
31
+ { id: 'item', name: 'Предмет', type: 'Object' },
32
+ { id: 'found', name: 'Найден?', type: 'Boolean' },
33
+ { id: 'slot', name: 'Слот', type: 'Number' }
34
+ ],
35
+ defaultData: { itemName: '' },
36
+ theme: { headerColor: '#f59e0b', accentColor: '#fbbf24' }
42
37
  });
43
38
 
44
39
  registry.registerNodeType({
@@ -47,15 +42,15 @@ function registerNodes(registry) {
47
42
  category: 'Инвентарь',
48
43
  description: 'Подсчитывает общее количество предмета в инвентаре.',
49
44
  graphType: GRAPH_TYPES.ALL,
50
- evaluator: require('../nodes/inventory/count_item').evaluate,
51
- pins: {
52
- inputs: [
53
- { id: 'itemName', name: 'Имя предмета', type: 'String', required: true }
54
- ],
55
- outputs: [
56
- { id: 'count', name: 'Количество', type: 'Number' }
57
- ]
58
- }
45
+ evaluator: require('../../core/nodes/inventory/count_item').evaluate,
46
+ computeInputs: (data) => [
47
+ { id: 'itemName', name: 'Имя предмета', type: 'String', required: true, inlineField: true, placeholder: 'diamond...' }
48
+ ],
49
+ computeOutputs: () => [
50
+ { id: 'count', name: 'Количество', type: 'Number' }
51
+ ],
52
+ defaultData: { itemName: '' },
53
+ theme: { headerColor: '#f59e0b', accentColor: '#fbbf24' }
59
54
  });
60
55
 
61
56
  registry.registerNodeType({
@@ -64,17 +59,17 @@ function registerNodes(registry) {
64
59
  category: 'Инвентарь',
65
60
  description: 'Проверяет наличие предмета в инвентаре.',
66
61
  graphType: GRAPH_TYPES.ALL,
67
- evaluator: require('../nodes/inventory/has_item').evaluate,
68
- pins: {
69
- inputs: [
70
- { id: 'itemName', name: 'Имя предмета', type: 'String', required: true },
71
- { id: 'minCount', name: 'Мин. кол-во', type: 'Number', required: false }
72
- ],
73
- outputs: [
74
- { id: 'hasItem', name: 'Есть?', type: 'Boolean' },
75
- { id: 'actualCount', name: 'Фактически', type: 'Number' }
76
- ]
77
- }
62
+ evaluator: require('../../core/nodes/inventory/has_item').evaluate,
63
+ computeInputs: (data) => [
64
+ { id: 'itemName', name: 'Имя предмета', type: 'String', required: true, inlineField: true, placeholder: 'diamond...' },
65
+ { id: 'minCount', name: 'Мин. кол-во', type: 'Number', required: false, inlineField: true, placeholder: '1' }
66
+ ],
67
+ computeOutputs: () => [
68
+ { id: 'hasItem', name: 'Есть?', type: 'Boolean' },
69
+ { id: 'actualCount', name: 'Фактически', type: 'Number' }
70
+ ],
71
+ defaultData: { itemName: '', minCount: 1 },
72
+ theme: { headerColor: '#f59e0b', accentColor: '#fbbf24' }
78
73
  });
79
74
 
80
75
  registry.registerNodeType({
@@ -83,16 +78,16 @@ function registerNodes(registry) {
83
78
  category: 'Инвентарь',
84
79
  description: 'Получает предмет в указанном слоте инвентаря.',
85
80
  graphType: GRAPH_TYPES.ALL,
86
- evaluator: require('../nodes/inventory/get_slot').evaluate,
87
- pins: {
88
- inputs: [
89
- { id: 'slotNumber', name: 'Номер слота', type: 'Number', required: true }
90
- ],
91
- outputs: [
92
- { id: 'item', name: 'Предмет', type: 'Object' },
93
- { id: 'isEmpty', name: 'Пусто?', type: 'Boolean' }
94
- ]
95
- }
81
+ evaluator: require('../../core/nodes/inventory/get_slot').evaluate,
82
+ computeInputs: (data) => [
83
+ { id: 'slotNumber', name: 'Номер слота', type: 'Number', required: true, inlineField: true, placeholder: '0' }
84
+ ],
85
+ computeOutputs: () => [
86
+ { id: 'item', name: 'Предмет', type: 'Object' },
87
+ { id: 'isEmpty', name: 'Пусто?', type: 'Boolean' }
88
+ ],
89
+ defaultData: { slotNumber: 0 },
90
+ theme: { headerColor: '#f59e0b', accentColor: '#fbbf24' }
96
91
  });
97
92
 
98
93
  registry.registerNodeType({
@@ -101,40 +96,39 @@ function registerNodes(registry) {
101
96
  category: 'Инвентарь',
102
97
  description: 'Получает предмет который бот держит в руке.',
103
98
  graphType: GRAPH_TYPES.ALL,
104
- evaluator: require('../nodes/inventory/get_held_item').evaluate,
105
- pins: {
106
- inputs: [
107
- { id: 'hand', name: 'Рука', type: 'String', required: false }
108
- ],
109
- outputs: [
110
- { id: 'item', name: 'Предмет', type: 'Object' },
111
- { id: 'name', name: 'Имя', type: 'String' },
112
- { id: 'count', name: 'Количество', type: 'Number' },
113
- { id: 'hasItem', name: 'Есть предмет?', type: 'Boolean' }
114
- ]
115
- }
99
+ evaluator: require('../../core/nodes/inventory/get_held_item').evaluate,
100
+ computeInputs: (data) => [
101
+ { id: 'hand', name: 'Рука', type: 'String', required: false, inlineField: true, placeholder: 'mainhand' }
102
+ ],
103
+ computeOutputs: () => [
104
+ { id: 'item', name: 'Предмет', type: 'Object' },
105
+ { id: 'name', name: 'Имя', type: 'String' },
106
+ { id: 'count', name: 'Количество', type: 'Number' },
107
+ { id: 'hasItem', name: 'Есть предмет?', type: 'Boolean' }
108
+ ],
109
+ defaultData: { hand: 'mainhand' },
110
+ theme: { headerColor: '#f59e0b', accentColor: '#fbbf24' }
116
111
  });
117
112
 
118
- // ========== ACTION NODES ==========
119
-
120
113
  registry.registerNodeType({
121
114
  type: 'inventory:equip',
122
115
  label: '⚔️ Экипировать',
123
116
  category: 'Инвентарь',
124
117
  description: 'Экипирует предмет в руку или слот брони.',
125
118
  graphType: GRAPH_TYPES.ALL,
126
- evaluator: require('../nodes/inventory/equip').evaluate,
127
- pins: {
128
- inputs: [
129
- { id: 'exec', name: 'Выполнить', type: 'Exec' },
130
- { id: 'itemName', name: 'Предмет', type: 'String', required: true },
131
- { id: 'destination', name: 'Куда', type: 'String', required: false }
132
- ],
133
- outputs: [
134
- { id: 'exec', name: 'Выполнено', type: 'Exec' },
135
- { id: 'success', name: 'Успех?', type: 'Boolean' }
136
- ]
137
- }
119
+ executor: require('../../core/nodes/inventory/equip').execute,
120
+ evaluator: require('../../core/nodes/inventory/equip').evaluate,
121
+ computeInputs: (data) => [
122
+ { id: 'exec', name: 'Выполнить', type: 'Exec' },
123
+ { id: 'itemName', name: 'Предмет', type: 'String', required: true, inlineField: true, placeholder: 'diamond_sword...' },
124
+ { id: 'destination', name: 'Куда', type: 'String', required: false, inlineField: true, placeholder: 'hand' }
125
+ ],
126
+ computeOutputs: () => [
127
+ { id: 'exec', name: 'Выполнено', type: 'Exec' },
128
+ { id: 'success', name: 'Успех?', type: 'Boolean' }
129
+ ],
130
+ defaultData: { itemName: '', destination: 'hand' },
131
+ theme: { headerColor: '#f59e0b', accentColor: '#fbbf24' }
138
132
  });
139
133
 
140
134
  registry.registerNodeType({
@@ -143,19 +137,20 @@ function registerNodes(registry) {
143
137
  category: 'Инвентарь',
144
138
  description: 'Выбрасывает предмет из инвентаря.',
145
139
  graphType: GRAPH_TYPES.ALL,
146
- evaluator: require('../nodes/inventory/drop').evaluate,
147
- pins: {
148
- inputs: [
149
- { id: 'exec', name: 'Выполнить', type: 'Exec' },
150
- { id: 'itemName', name: 'Предмет', type: 'String', required: true },
151
- { id: 'count', name: 'Количество', type: 'Number', required: false },
152
- { id: 'dropAll', name: 'Выбросить все?', type: 'Boolean', required: false }
153
- ],
154
- outputs: [
155
- { id: 'exec', name: 'Выполнено', type: 'Exec' },
156
- { id: 'dropped', name: 'Выброшено', type: 'Number' }
157
- ]
158
- }
140
+ executor: require('../../core/nodes/inventory/drop').execute,
141
+ evaluator: require('../../core/nodes/inventory/drop').evaluate,
142
+ computeInputs: (data) => [
143
+ { id: 'exec', name: 'Выполнить', type: 'Exec' },
144
+ { id: 'itemName', name: 'Предмет', type: 'String', required: true, inlineField: true, placeholder: 'dirt...' },
145
+ { id: 'count', name: 'Количество', type: 'Number', required: false, inlineField: true, placeholder: 'все' },
146
+ { id: 'dropAll', name: 'Выбросить все?', type: 'Boolean', required: false, inlineField: true }
147
+ ],
148
+ computeOutputs: () => [
149
+ { id: 'exec', name: 'Выполнено', type: 'Exec' },
150
+ { id: 'dropped', name: 'Выброшено', type: 'Number' }
151
+ ],
152
+ defaultData: { itemName: '', count: null, dropAll: false },
153
+ theme: { headerColor: '#f59e0b', accentColor: '#fbbf24' }
159
154
  });
160
155
 
161
156
  registry.registerNodeType({
@@ -164,18 +159,19 @@ function registerNodes(registry) {
164
159
  category: 'Инвентарь',
165
160
  description: 'Выбирает слот хотбара (0-8).',
166
161
  graphType: GRAPH_TYPES.ALL,
167
- evaluator: require('../nodes/inventory/select_slot').evaluate,
168
- pins: {
169
- inputs: [
170
- { id: 'exec', name: 'Выполнить', type: 'Exec' },
171
- { id: 'slot', name: 'Слот', type: 'Number', required: true }
172
- ],
173
- outputs: [
174
- { id: 'exec', name: 'Выполнено', type: 'Exec' },
175
- { id: 'item', name: 'Предмет', type: 'Object' }
176
- ]
177
- }
162
+ executor: require('../../core/nodes/inventory/select_slot').execute,
163
+ evaluator: require('../../core/nodes/inventory/select_slot').evaluate,
164
+ computeInputs: (data) => [
165
+ { id: 'exec', name: 'Выполнить', type: 'Exec' },
166
+ { id: 'slot', name: 'Слот', type: 'Number', required: true, inlineField: true, placeholder: '0-8' }
167
+ ],
168
+ computeOutputs: () => [
169
+ { id: 'exec', name: 'Выполнено', type: 'Exec' },
170
+ { id: 'item', name: 'Предмет', type: 'Object' }
171
+ ],
172
+ defaultData: { slot: 0 },
173
+ theme: { headerColor: '#f59e0b', accentColor: '#fbbf24' }
178
174
  });
179
175
  }
180
176
 
181
- module.exports = { registerNodes };
177
+ module.exports = { registerNodes };