mindcraft 0.1.4-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 (116) hide show
  1. package/FAQ.md +38 -0
  2. package/LICENSE +21 -0
  3. package/README.md +255 -0
  4. package/andy.json +6 -0
  5. package/bin/mindcraft.js +80 -0
  6. package/keys.example.json +19 -0
  7. package/main.js +80 -0
  8. package/package.json +78 -0
  9. package/patches/minecraft-data+3.97.0.patch +13 -0
  10. package/patches/mineflayer+4.33.0.patch +54 -0
  11. package/patches/mineflayer-pathfinder+2.4.5.patch +265 -0
  12. package/patches/mineflayer-pvp+1.3.2.patch +13 -0
  13. package/patches/prismarine-viewer+1.33.0.patch +13 -0
  14. package/patches/protodef+1.19.0.patch +15 -0
  15. package/profiles/andy-4-reasoning.json +14 -0
  16. package/profiles/andy-4.json +7 -0
  17. package/profiles/azure.json +19 -0
  18. package/profiles/claude.json +7 -0
  19. package/profiles/claude_thinker.json +15 -0
  20. package/profiles/deepseek.json +7 -0
  21. package/profiles/defaults/_default.json +256 -0
  22. package/profiles/defaults/assistant.json +14 -0
  23. package/profiles/defaults/creative.json +14 -0
  24. package/profiles/defaults/god_mode.json +14 -0
  25. package/profiles/defaults/survival.json +14 -0
  26. package/profiles/freeguy.json +7 -0
  27. package/profiles/gemini.json +9 -0
  28. package/profiles/gpt.json +12 -0
  29. package/profiles/grok.json +7 -0
  30. package/profiles/llama.json +10 -0
  31. package/profiles/mercury.json +9 -0
  32. package/profiles/mistral.json +5 -0
  33. package/profiles/qwen.json +17 -0
  34. package/profiles/tasks/construction_profile.json +42 -0
  35. package/profiles/tasks/cooking_profile.json +11 -0
  36. package/profiles/tasks/crafting_profile.json +71 -0
  37. package/profiles/vllm.json +10 -0
  38. package/settings.js +64 -0
  39. package/src/agent/action_manager.js +177 -0
  40. package/src/agent/agent.js +561 -0
  41. package/src/agent/coder.js +229 -0
  42. package/src/agent/commands/actions.js +504 -0
  43. package/src/agent/commands/index.js +259 -0
  44. package/src/agent/commands/queries.js +347 -0
  45. package/src/agent/connection_handler.js +96 -0
  46. package/src/agent/conversation.js +353 -0
  47. package/src/agent/history.js +122 -0
  48. package/src/agent/library/full_state.js +89 -0
  49. package/src/agent/library/index.js +23 -0
  50. package/src/agent/library/lockdown.js +32 -0
  51. package/src/agent/library/skill_library.js +93 -0
  52. package/src/agent/library/skills.js +2093 -0
  53. package/src/agent/library/world.js +431 -0
  54. package/src/agent/memory_bank.js +25 -0
  55. package/src/agent/mindserver_proxy.js +136 -0
  56. package/src/agent/modes.js +446 -0
  57. package/src/agent/npc/build_goal.js +80 -0
  58. package/src/agent/npc/construction/dirt_shelter.json +38 -0
  59. package/src/agent/npc/construction/large_house.json +230 -0
  60. package/src/agent/npc/construction/small_stone_house.json +42 -0
  61. package/src/agent/npc/construction/small_wood_house.json +42 -0
  62. package/src/agent/npc/controller.js +261 -0
  63. package/src/agent/npc/data.js +50 -0
  64. package/src/agent/npc/item_goal.js +355 -0
  65. package/src/agent/npc/utils.js +126 -0
  66. package/src/agent/self_prompter.js +146 -0
  67. package/src/agent/settings.js +7 -0
  68. package/src/agent/speak.js +150 -0
  69. package/src/agent/tasks/construction_tasks.js +1104 -0
  70. package/src/agent/tasks/cooking_tasks.js +358 -0
  71. package/src/agent/tasks/tasks.js +594 -0
  72. package/src/agent/templates/execTemplate.js +6 -0
  73. package/src/agent/templates/lintTemplate.js +10 -0
  74. package/src/agent/vision/browser_viewer.js +8 -0
  75. package/src/agent/vision/camera.js +78 -0
  76. package/src/agent/vision/vision_interpreter.js +82 -0
  77. package/src/mindcraft/index.js +28 -0
  78. package/src/mindcraft/mcserver.js +154 -0
  79. package/src/mindcraft/mindcraft.js +111 -0
  80. package/src/mindcraft/mindserver.js +328 -0
  81. package/src/mindcraft/public/index.html +1253 -0
  82. package/src/mindcraft/public/settings_spec.json +145 -0
  83. package/src/mindcraft/userconfig.js +72 -0
  84. package/src/mindcraft-py/example.py +27 -0
  85. package/src/mindcraft-py/init-mindcraft.js +24 -0
  86. package/src/mindcraft-py/mindcraft.py +99 -0
  87. package/src/models/_model_map.js +89 -0
  88. package/src/models/azure.js +32 -0
  89. package/src/models/cerebras.js +61 -0
  90. package/src/models/claude.js +87 -0
  91. package/src/models/deepseek.js +59 -0
  92. package/src/models/gemini.js +176 -0
  93. package/src/models/glhf.js +71 -0
  94. package/src/models/gpt.js +147 -0
  95. package/src/models/grok.js +82 -0
  96. package/src/models/groq.js +95 -0
  97. package/src/models/huggingface.js +86 -0
  98. package/src/models/hyperbolic.js +114 -0
  99. package/src/models/lmstudio.js +74 -0
  100. package/src/models/mercury.js +95 -0
  101. package/src/models/mistral.js +94 -0
  102. package/src/models/novita.js +71 -0
  103. package/src/models/ollama.js +115 -0
  104. package/src/models/openrouter.js +77 -0
  105. package/src/models/prompter.js +366 -0
  106. package/src/models/qwen.js +80 -0
  107. package/src/models/replicate.js +60 -0
  108. package/src/models/vllm.js +81 -0
  109. package/src/process/agent_process.js +84 -0
  110. package/src/process/init_agent.js +54 -0
  111. package/src/utils/examples.js +83 -0
  112. package/src/utils/keys.js +34 -0
  113. package/src/utils/math.js +13 -0
  114. package/src/utils/mcdata.js +572 -0
  115. package/src/utils/text.js +78 -0
  116. package/src/utils/translator.js +30 -0
@@ -0,0 +1,1104 @@
1
+ import {Vec3} from 'vec3';
2
+
3
+ export class ConstructionTaskValidator {
4
+ constructor(data, agent) {
5
+ this.blueprint = new Blueprint(data.blueprint);
6
+ this.agent = agent;
7
+ }
8
+ validate() {
9
+ try {
10
+ //todo: somehow make this more of a percentage or something
11
+ // console.log('Validating task...');
12
+ let valid = false;
13
+ let score = 0;
14
+ let result = this.blueprint.check(this.agent.bot);
15
+ if (result.mismatches.length === 0) {
16
+ valid = true;
17
+ console.log('Task is complete');
18
+ }
19
+ let total_blocks = result.mismatches.length + result.matches.length;
20
+ score = (result.matches.length / total_blocks) * 100;
21
+ console.log(`Task score: ${score}%`);
22
+ return {
23
+ "valid": valid,
24
+ "score": score
25
+ };
26
+ } catch (error) {
27
+ console.error('Error validating task:', error);
28
+ return {
29
+ "valid": false,
30
+ "score": 0
31
+ };
32
+ }
33
+ }
34
+ }
35
+
36
+ export function resetConstructionWorld(bot, blueprint) {
37
+ console.log('Resetting world...');
38
+ const starting_position = blueprint.levels[0].coordinates;
39
+ const length = blueprint.levels[0].placement.length + 5;
40
+ const height = blueprint.levels.length + 5;
41
+ const width = blueprint.levels[0].placement[0].length + 5;
42
+ const command = `/fill ${starting_position[0]} ${starting_position[1]} ${starting_position[2]} ${starting_position[0] + width} ${starting_position[1] + height} ${starting_position[2] + length} air`;
43
+ bot.chat(command);
44
+ console.log('World reset');
45
+ }
46
+
47
+ export function checkLevelBlueprint(agent, levelNum) {
48
+ const blueprint = agent.task.blueprint;
49
+ const bot = agent.bot;
50
+ const result = blueprint.checkLevel(bot, levelNum);
51
+ if (result.mismatches.length === 0) {
52
+ return `Level ${levelNum} is correct`;
53
+ } else {
54
+ let explanation = blueprint.explainLevelDifference(bot, levelNum);
55
+ return explanation;
56
+ }
57
+ }
58
+
59
+ export function checkBlueprint(agent) {
60
+ console.log('Checking blueprint...');
61
+ console.log(agent);
62
+ const blueprint = agent.task.blueprint;
63
+ const bot = agent.bot;
64
+ const result = blueprint.check(bot);
65
+ if (result.mismatches.length === 0) {
66
+ return "Blueprint is correct";
67
+ } else {
68
+ let explanation = blueprint.explainBlueprintDifference(bot);
69
+ return explanation;
70
+ }
71
+ }
72
+
73
+ export class Blueprint {
74
+ constructor(blueprint) {
75
+ this.data = blueprint;
76
+ }
77
+ explain() {
78
+ var explanation = "";
79
+
80
+ for (let item of this.data.levels) {
81
+ var coordinates = item.coordinates;
82
+ explanation += `Level ${item.level}: `;
83
+ explanation += `Start at coordinates X: ${coordinates[0]}, Y: ${coordinates[1]}, Z: ${coordinates[2]}`;
84
+ // let placement_string = this._getPlacementString(item.placement);
85
+ // explanation += `\n${placement_string}\n`;
86
+ }
87
+ return explanation;
88
+ }
89
+ _getPlacementString(placement) {
90
+ var placement_string = "[\n";
91
+ for (let row of placement) {
92
+ placement_string += "[";
93
+ for (let i = 0; i < row.length - 1; i++) {
94
+ let item = row[i];
95
+ placement_string += `${item}, `;
96
+ }
97
+ let final_item = row[row.length - 1];
98
+ placement_string += `${final_item}],\n`;
99
+ }
100
+ placement_string += "]";
101
+ return placement_string;
102
+ }
103
+ explainLevel(levelNum) {
104
+ const levelData = this.data.levels[levelNum];
105
+ var explanation = `Level ${levelData.level} `;
106
+ explanation += `starting at coordinates X: ${levelData.coordinates[0]}, Y: ${levelData.coordinates[1]}, Z: ${levelData.coordinates[2]}`;
107
+ let placement_string = this._getPlacementString(levelData.placement);
108
+ explanation += `\n${placement_string}\n`;
109
+ return explanation;
110
+ }
111
+ explainBlueprintDifference(bot) {
112
+ var explanation = "";
113
+ const levels = this.data.levels;
114
+ for (let i = 0; i < levels.length; i++) {
115
+ let level_explanation = this.explainLevelDifference(bot, i);
116
+ explanation += level_explanation + "\n";
117
+ }
118
+ return explanation;
119
+ }
120
+ explainLevelDifference(bot, levelNum) {
121
+ const results = this.checkLevel(bot, levelNum);
122
+ const mismatches = results.mismatches;
123
+ const levelData = this.data.levels[levelNum];
124
+
125
+ if (mismatches.length === 0) {
126
+ return `Level ${levelData.level} is complete`;
127
+ }
128
+ var explanation = `Level ${levelData.level} `;
129
+ // explanation += `at coordinates X: ${levelData.coordinates[0]}, Y: ${levelData.coordinates[1]}, Z: ${levelData.coordinates[2]}`;
130
+ explanation += " requires the following fixes:\n";
131
+ for (let item of mismatches) {
132
+ if (item.actual === 'air') {
133
+ explanation += `Place ${item.expected} at coordinates X: ${item.coordinates[0]}, Y: ${item.coordinates[1]}, Z: ${item.coordinates[2]}\n`;
134
+ } else if (item.expected === 'air') {
135
+ explanation += `Remove the ${item.actual} at coordinates X: ${item.coordinates[0]}, Y: ${item.coordinates[1]}, Z: ${item.coordinates[2]}\n`;
136
+ } else {
137
+ explanation += `Replace the ${item.actual} with a ${item.expected} at coordinates X: ${item.coordinates[0]}, Y: ${item.coordinates[1]}, Z: ${item.coordinates[2]} \n`;
138
+ }
139
+ }
140
+ return explanation;
141
+ }
142
+ check(bot) {
143
+ if (!bot || typeof bot !== 'object' || !bot.hasOwnProperty('blockAt')) {
144
+ throw new Error('Invalid bot object. Expected a mineflayer bot.');
145
+ }
146
+ const levels = this.data.levels;
147
+ const mismatches = [];
148
+ const matches = [];
149
+ for (let i = 0; i < levels.length; i++) {
150
+ const result = this.checkLevel(bot, i);
151
+ mismatches.push(...result.mismatches);
152
+ matches.push(...result.matches);
153
+ }
154
+ return {
155
+ "mismatches": mismatches,
156
+ "matches": matches
157
+ };
158
+ }
159
+ checkLevel(bot, levelNum) {
160
+ const levelData = this.data.levels[levelNum];
161
+ const startCoords = levelData.coordinates;
162
+ const placement = levelData.placement;
163
+ const mismatches = [];
164
+ const matches = [];
165
+
166
+ for (let zOffset = 0; zOffset < placement.length; zOffset++) {
167
+ const row = placement[zOffset];
168
+ for (let xOffset = 0; xOffset < row.length; xOffset++) {
169
+ const blockName = row[xOffset];
170
+
171
+ const x = startCoords[0] + xOffset;
172
+ const y = startCoords[1];
173
+ const z = startCoords[2] + zOffset;
174
+
175
+ try {
176
+ const blockAtLocation = bot.blockAt(new Vec3(x, y, z));
177
+ const actualBlockName = blockAtLocation ? bot.registry.blocks[blockAtLocation.type].name : "air";
178
+
179
+ // Skip if both expected and actual block are air
180
+ if (blockName === "air" && actualBlockName === "air") {
181
+ continue;
182
+ }
183
+
184
+ if (actualBlockName !== blockName) {
185
+ mismatches.push({
186
+ level: levelData.level,
187
+ coordinates: [x, y, z],
188
+ expected: blockName,
189
+ actual: actualBlockName
190
+ });
191
+ } else {
192
+ matches.push({
193
+ level: levelData.level,
194
+ coordinates: [x, y, z],
195
+ expected: blockName,
196
+ actual: actualBlockName
197
+ });
198
+ }
199
+ } catch (err) {
200
+ console.error(`Error getting block at (${x}, ${y}, ${z}):`, err);
201
+ return false; // Stop checking if there's an issue getting blocks
202
+ }
203
+ }
204
+ }
205
+ return {
206
+ "mismatches": mismatches,
207
+ "matches": matches
208
+ };
209
+ }
210
+
211
+ /**
212
+ * Takes in the blueprint, and then converts it into a set of /setblock commands for the bot to follow
213
+ * @Returns: An object containing the setblock commands as a list of strings, and a position nearby the blueprint but not in it
214
+ * @param blueprint
215
+ */
216
+ autoBuild() {
217
+ const commands = [];
218
+ let blueprint = this.data
219
+
220
+ let minX = Infinity, maxX = -Infinity;
221
+ let minY = Infinity, maxY = -Infinity;
222
+ let minZ = Infinity, maxZ = -Infinity;
223
+
224
+ for (const level of blueprint.levels) {
225
+ console.log(level.level)
226
+ const baseX = level.coordinates[0];
227
+ const baseY = level.coordinates[1];
228
+ const baseZ = level.coordinates[2];
229
+ const placement = level.placement;
230
+
231
+ // Update bounds
232
+ minX = Math.min(minX, baseX);
233
+ maxX = Math.max(maxX, baseX + placement[0].length - 1);
234
+ minY = Math.min(minY, baseY);
235
+ maxY = Math.max(maxY, baseY);
236
+ minZ = Math.min(minZ, baseZ);
237
+ maxZ = Math.max(maxZ, baseZ + placement.length - 1);
238
+
239
+ // Loop through the 2D placement array
240
+ for (let z = 0; z < placement.length; z++) {
241
+ for (let x = 0; x < placement[z].length; x++) {
242
+ const blockType = placement[z][x];
243
+ if (blockType) {
244
+ const setblockCommand = `/setblock ${baseX + x} ${baseY} ${baseZ + z} ${blockType}`;
245
+ commands.push(setblockCommand);
246
+ }
247
+ }
248
+ }
249
+ }
250
+
251
+ // Calculate a position nearby the blueprint but not in it
252
+ const nearbyPosition = {
253
+ x: maxX + 5, // Move 5 blocks to the right
254
+ y: minY, // Stay on the lowest level of the blueprint
255
+ z: minZ // Stay aligned with the front of the blueprint
256
+ };
257
+
258
+ return { commands, nearbyPosition };
259
+ }
260
+
261
+
262
+ /**
263
+ * Takes in a blueprint, and returns a set of commands to clear up the space.
264
+ *
265
+ */
266
+ autoDelete() {
267
+ console.log("auto delete called!")
268
+ const commands = [];
269
+ let blueprint = this.data
270
+
271
+ let minX = Infinity, maxX = -Infinity;
272
+ let minY = Infinity, maxY = -Infinity;
273
+ let minZ = Infinity, maxZ = -Infinity;
274
+
275
+ for (const level of blueprint.levels) {
276
+ const baseX = level.coordinates[0];
277
+ const baseY = level.coordinates[1];
278
+ const baseZ = level.coordinates[2];
279
+ const placement = level.placement;
280
+
281
+ // Update bounds
282
+ minX = Math.min(minX, baseX);
283
+ maxX = Math.max(maxX, baseX + placement[0].length - 1);
284
+ minY = Math.min(minY, baseY);
285
+ maxY = Math.max(maxY, baseY);
286
+ minZ = Math.min(minZ, baseZ);
287
+ maxZ = Math.max(maxZ, baseZ + placement.length - 1);
288
+
289
+ // Loop through the 2D placement array
290
+ for (let z = 0; z < placement.length; z++) {
291
+ for (let x = 0; x < placement[z].length; x++) {
292
+ const blockType = placement[z][x];
293
+ if (blockType) {
294
+ const setblockCommand = `/setblock ${baseX + x} ${baseY} ${baseZ + z} air`;
295
+ commands.push(setblockCommand);
296
+ }
297
+ }
298
+ }
299
+ }
300
+
301
+ // Calculate a position nearby the blueprint but not in it
302
+ const nearbyPosition = {
303
+ x: maxX + 5, // Move 5 blocks to the right
304
+ y: minY, // Stay on the lowest level of the blueprint
305
+ z: minZ // Stay aligned with the front of the blueprint
306
+ };
307
+
308
+ return { commands, nearbyPosition };
309
+ }
310
+ }
311
+
312
+
313
+ /**
314
+ * Systematically builds the houses by placing them next to the already existing rooms. Still uses randomness for what gets placed next.
315
+ * @param m width of the 3D space
316
+ * @param n height of the 3D space
317
+ * @param p depth of the 3D space
318
+ * @param rooms Number of rooms to attempt to generate
319
+ * @param minRoomWidth
320
+ * @param minRoomLength
321
+ * @param minRoomDepth
322
+ * @param roomVariance How much the room size will vary
323
+ * @param wrapping material of wrapping (air, glass, etc...) -> default is air
324
+ * @param carpetStyle 0,1,2 increasingly more complex
325
+ * @param windowStyle 0,1,2 increasingly more complex
326
+ * @param complexity 0,1,2,3,4 for increasingly complex materials for room generation
327
+ * @param startCoord an array of the x,y,z coordinates to create the blueprint. default = [148,-60,-170]
328
+ * @returns a blueprint object
329
+ */
330
+ export function proceduralGeneration(m = 20,
331
+ n = 20,
332
+ p = 20,
333
+ rooms = 8,
334
+ minRoomWidth = 5,
335
+ minRoomLength = 5,
336
+ minRoomDepth = 6,
337
+ roomVariance = 5,
338
+ wrapping = "air",
339
+ carpetStyle = 1,
340
+ windowStyle = 1,
341
+ complexity = 4,
342
+ startCoord = [148,-60,-170]) {
343
+ // Build 3D space
344
+ const matrix = Array.from({length: p}, () =>
345
+ Array.from({length: m}, () =>
346
+ Array(n).fill('air')
347
+ )
348
+ );
349
+
350
+ // todo: extrapolate into another param? then have set materials be dynamic?
351
+ let roomMaterials = ["stone", "terracotta", "quartz_block", "copper_block", "purpur_block"]
352
+
353
+ if (complexity < roomMaterials.length) {
354
+ roomMaterials = roomMaterials.slice(0, complexity + 1);
355
+ }
356
+
357
+ // Mark entire outer border with 'stone'
358
+ for (let z = 0; z < p; z++) {
359
+ for (let x = 0; x < m; x++) {
360
+ for (let y = 0; y < n; y++) {
361
+ if (
362
+ z === 0 || z === p - 1 || // Top and bottom faces
363
+ x === 0 || x === m - 1 || // Front and back faces
364
+ y === 0 || y === n - 1 // Left and right faces
365
+ ) {
366
+ matrix[z][x][y] = 'stone';
367
+ }
368
+ }
369
+ }
370
+ }
371
+
372
+ // Replace outer layer with wrap
373
+ for (let z = 0; z < p; z++) {
374
+ for (let x = 0; x < m; x++) {
375
+ for (let y = 0; y < n; y++) {
376
+ if (
377
+ (z === p - 1 || // Top face
378
+ x === 0 || x === m - 1 || // Front and back faces
379
+ y === 0 || y === n - 1) // Left and right faces
380
+ ) {
381
+ matrix[z][x][y] = wrapping;
382
+ }
383
+ }
384
+ }
385
+ }
386
+
387
+ let placedRooms = 0;
388
+ let lastRoom = null;
389
+
390
+ // Direction probabilities (e.g., 'above': 40%, 'left': 15%, etc.)
391
+ const directionChances = [
392
+ {direction: 'above', chance: 0.15},
393
+ {direction: 'left', chance: 0.15},
394
+ {direction: 'right', chance: 0.15},
395
+ {direction: 'forward', chance: 0.15},
396
+ {direction: 'backward', chance: 0.15},
397
+ ];
398
+
399
+ // Function to pick a random direction based on percentages
400
+ function getRandomDirection() {
401
+ const rand = Math.random();
402
+ let cumulative = 0;
403
+
404
+ for (const {direction, chance} of directionChances) {
405
+ cumulative += chance;
406
+ if (rand <= cumulative) return direction;
407
+ }
408
+ return directionChances[1].direction; // Fallback to the first direction
409
+ }
410
+
411
+ // Ensures no rooms overlap except at edges
412
+ function isSpaceValid(newX, newY, newZ, newLength, newWidth, newDepth) {
413
+ for (let di = 0; di < newDepth; di++) {
414
+ for (let dj = 0; dj < newLength; dj++) {
415
+ for (let dk = 0; dk < newWidth; dk++) {
416
+ const x = newX + dj;
417
+ const y = newY + dk;
418
+ const z = newZ + di;
419
+
420
+ // Skip checking the outermost borders of the new room (these can overlap with stone)
421
+ if (dj === 0 || dj === newLength - 1 ||
422
+ dk === 0 || dk === newWidth - 1 ||
423
+ di === 0 || di === newDepth - 1) {
424
+ continue;
425
+ }
426
+
427
+ // For non-border spaces, ensure they're air
428
+ if (matrix[z][x][y] !== 'air') {
429
+ return false;
430
+ }
431
+ }
432
+ }
433
+ }
434
+ return true;
435
+ }
436
+
437
+ function validateAndBuildBorder(matrix, newX, newY, newZ, newLength, newWidth, newDepth, m, n, p, material) {
438
+ // Allow rooms to use the matrix edges (note the <= instead of <)
439
+ if (
440
+ newX >= 0 && newX + newLength <= m &&
441
+ newY >= 0 && newY + newWidth <= n &&
442
+ newZ >= 0 && newZ + newDepth <= p &&
443
+ isSpaceValid(newX, newY, newZ, newLength, newWidth, newDepth)
444
+ ) {
445
+ // console.log(`Placing room at (${newX}, ${newY}, ${newZ}) with dimensions (${newLength}x${newWidth}x${newDepth})`);
446
+ for (let di = 0; di < newDepth; di++) {
447
+ for (let dj = 0; dj < newLength; dj++) {
448
+ for (let dk = 0; dk < newWidth; dk++) {
449
+ const x = newX + dj;
450
+ const y = newY + dk;
451
+ const z = newZ + di;
452
+
453
+ // If this is at a matrix border, don't modify it
454
+ if (z === 0) {
455
+ continue;
456
+ }
457
+ // if (x === 0 || x === m - 1 ||
458
+ // y === 0 || y === n - 1 ||
459
+ // z === 0 || z === p - 1) {
460
+ // continue;
461
+ // }
462
+
463
+ // For non-border spaces, check if this is a floor that should be shared
464
+ //was: === 'stone'
465
+ if (di === 0 && matrix[z - 1][x][y] !== 'air') {
466
+ // Skip creating floor if there's a ceiling below
467
+ matrix[z][x][y] = 'air';
468
+ } else if (di === 0 || di === newDepth - 1 ||
469
+ dj === 0 || dj === newLength - 1 ||
470
+ dk === 0 || dk === newWidth - 1) {
471
+ matrix[z][x][y] = material;
472
+ } else {
473
+ matrix[z][x][y] = 'air';
474
+ }
475
+
476
+
477
+ }
478
+ }
479
+ }
480
+ return true;
481
+ }
482
+ return false;
483
+ }
484
+
485
+ function addDoor(matrix, x, y, z, material) {
486
+ matrix[z][x][y] = material;
487
+
488
+ // Place the lower half of the door
489
+ // matrix[z + 1][x][y] = 'dark_oak_door[half=lower, hinge=left]';
490
+
491
+ matrix[z + 1][x][y] = 'dark_oak_door';
492
+
493
+
494
+ // Place the upper half of the door
495
+ // matrix[z + 2][x][y] = 'dark_oak_door[half=upper, hinge=left]';
496
+ matrix[z + 2][x][y] = 'dark_oak_door';
497
+
498
+ }
499
+
500
+
501
+ // Takes in a room and randomly converts some faces to be windows
502
+ function addWindowsAsSquares(matrix, x, y, z, newLength, newWidth, newDepth, material) {
503
+ // Matrix dimensions
504
+ const matrixDepth = matrix.length;
505
+ const matrixLength = matrix[0].length;
506
+ const matrixWidth = matrix[0][0].length;
507
+ const windowX = Math.ceil(minRoomWidth / 2)
508
+ const windowY = Math.ceil(minRoomLength / 2)
509
+ const windowZ = Math.ceil(minRoomDepth / 2)
510
+
511
+ // Helper function to check if coordinates are within bounds
512
+ function isInBounds(z, x, y) {
513
+ return z >= 0 && z < matrixDepth &&
514
+ x >= 0 && x < matrixLength &&
515
+ y >= 0 && y < matrixWidth;
516
+ }
517
+
518
+ // Front and back faces (z is constant)
519
+ if (Math.random() < 0.8) {
520
+ let centerX = x + Math.floor(newLength / 2 - windowX / 2);
521
+ let centerY = y + Math.floor(newWidth / 2 - windowY / 2);
522
+
523
+ for (let dx = 0; dx <= windowX; dx++) {
524
+ for (let dy = 0; dy <= windowY; dy++) {
525
+ let frontZ = z;
526
+ let backZ = z + newDepth - 1;
527
+
528
+ if (isInBounds(frontZ, centerX + dx, centerY + dy) &&
529
+ matrix[frontZ][centerX + dx][centerY + dy] === material) {
530
+ matrix[frontZ][centerX + dx][centerY + dy] = 'glass';
531
+ }
532
+ if (isInBounds(backZ, centerX + dx, centerY + dy) &&
533
+ matrix[backZ][centerX + dx][centerY + dy] === material) {
534
+ matrix[backZ][centerX + dx][centerY + dy] = 'glass';
535
+ }
536
+ }
537
+ }
538
+ }
539
+
540
+ // Left and right faces (x is constant)
541
+ if (Math.random() < 0.8) {
542
+ let centerZ = z + Math.floor(newDepth / 2 - windowZ / 2);
543
+ let centerY = y + Math.floor(newWidth / 2 - windowY / 2);
544
+
545
+ for (let dz = 0; dz <= windowZ; dz++) {
546
+ for (let dy = 0; dy <= windowY; dy++) {
547
+ let leftX = x;
548
+ let rightX = x + newLength - 1;
549
+
550
+ if (isInBounds(centerZ + dz, leftX, centerY + dy) &&
551
+ matrix[centerZ + dz][leftX][centerY + dy] === material) {
552
+ matrix[centerZ + dz][leftX][centerY + dy] = 'glass';
553
+ }
554
+ if (isInBounds(centerZ + dz, rightX, centerY + dy) &&
555
+ matrix[centerZ + dz][rightX][centerY + dy] === material) {
556
+ matrix[centerZ + dz][rightX][centerY + dy] = 'glass';
557
+ }
558
+ }
559
+ }
560
+ }
561
+
562
+ // Top and bottom faces (y is constant)
563
+ if (Math.random() < 0.8) {
564
+ let centerX = x + Math.floor(newLength / 2 - windowX / 2);
565
+ let centerZ = z + Math.floor(newDepth / 2 - windowZ / 2);
566
+
567
+ for (let dx = 0; dx <= windowX; dx++) {
568
+ for (let dz = 0; dz <= windowZ; dz++) {
569
+ let bottomY = y;
570
+ let topY = y + newWidth - 1;
571
+
572
+ if (isInBounds(centerZ + dz, centerX + dx, bottomY) &&
573
+ matrix[centerZ + dz][centerX + dx][bottomY] === material) {
574
+ matrix[centerZ + dz][centerX + dx][bottomY] = 'glass';
575
+ }
576
+ if (isInBounds(centerZ + dz, centerX + dx, topY) &&
577
+ matrix[centerZ + dz][centerX + dx][topY] === material) {
578
+ matrix[centerZ + dz][centerX + dx][topY] = 'glass';
579
+ }
580
+ }
581
+ }
582
+ }
583
+ }
584
+
585
+ function addWindowsAsPlane(matrix, x, y, z, newLength, newWidth, newDepth, material) {
586
+ // Ensure the new dimensions are within bounds
587
+ const maxX = matrix[0].length;
588
+ const maxY = matrix[0][0].length;
589
+ const maxZ = matrix.length;
590
+
591
+ // Each face has a 30% chance of becoming a window
592
+ if (Math.random() < 0.8) {
593
+ for (let dx = 0; dx < newLength; dx++) {
594
+ for (let dy = 0; dy < newWidth; dy++) {
595
+ let frontZ = z;
596
+ let backZ = z + newDepth - 1;
597
+
598
+ // Check bounds before modifying the matrix
599
+ if (frontZ >= 0 && frontZ < maxZ && x + dx >= 0 && x + dx < maxX && y + dy >= 0 && y + dy < maxY) {
600
+ if (matrix[frontZ][x + dx][y + dy] === material) {
601
+ matrix[frontZ][x + dx][y + dy] = 'glass';
602
+ }
603
+ }
604
+ if (backZ >= 0 && backZ < maxZ && x + dx >= 0 && x + dx < maxX && y + dy >= 0 && y + dy < maxY) {
605
+ if (matrix[backZ][x + dx][y + dy] === material) {
606
+ matrix[backZ][x + dx][y + dy] = 'glass';
607
+ }
608
+ }
609
+ }
610
+ }
611
+ }
612
+
613
+ if (Math.random() < 0.8) {
614
+ for (let dz = 0; dz < newDepth; dz++) {
615
+ for (let dy = 0; dy < newWidth; dy++) {
616
+ let leftX = x;
617
+ let rightX = x + newLength - 1;
618
+
619
+ // Check bounds before modifying the matrix
620
+ if (leftX >= 0 && leftX < maxX && z + dz >= 0 && z + dz < maxZ && y + dy >= 0 && y + dy < maxY) {
621
+ if (matrix[z + dz][leftX][y + dy] === material) {
622
+ matrix[z + dz][leftX][y + dy] = 'glass';
623
+ }
624
+ }
625
+ if (rightX >= 0 && rightX < maxX && z + dz >= 0 && z + dz < maxZ && y + dy >= 0 && y + dy < maxY) {
626
+ if (matrix[z + dz][rightX][y + dy] === material) {
627
+ matrix[z + dz][rightX][y + dy] = 'glass';
628
+ }
629
+ }
630
+ }
631
+ }
632
+ }
633
+ }
634
+
635
+
636
+ //still a little buggy
637
+ function addStairs(matrix, x, y, z, length, width, material) {
638
+ let currentZ = z;
639
+ let currentX = x + 1;
640
+ let currentY = y + 1;
641
+ let direction = 0;
642
+ let stepCount = 0;
643
+ const maxSteps = length * width; // Safety limit
644
+
645
+ while (currentZ >= 0 && currentX < x + length - 1 && currentY < y + width - 1 && stepCount < maxSteps) {
646
+ // Place stair block
647
+ matrix[currentZ][currentX][currentY] = material || 'stone';
648
+
649
+ // Clear 3 blocks above for headroom
650
+ for (let i = 1; i <= 3; i++) {
651
+ if (currentZ + i < matrix.length) {
652
+ matrix[currentZ + i][currentX][currentY] = 'air';
653
+ }
654
+ }
655
+
656
+ // Move to next position based on direction
657
+ if (direction === 0) {
658
+ currentX++;
659
+ if (currentX >= x + length - 1) {
660
+ currentX = x + length - 2;
661
+ direction = 1;
662
+ } else {
663
+ currentZ--;
664
+ }
665
+ } else {
666
+ currentY++;
667
+ if (currentY >= y + width - 1) {
668
+ currentY = y + width - 2;
669
+ direction = 0;
670
+ } else {
671
+ currentZ--;
672
+ }
673
+ }
674
+
675
+ stepCount++;
676
+ }
677
+ }
678
+
679
+ function addCarpet(probability, matrix, newX, newY, newZ, newLength, newWidth, material) {
680
+ let colors = ["blue", "cyan", "light_blue", "lime"];
681
+
682
+ // Iterate through the dimensions of the room
683
+ for (let dx = 1; dx < newLength - 1; dx++) {
684
+ for (let dy = 1; dy < newWidth - 1; dy++) {
685
+ let x = newX + dx;
686
+ let y = newY + dy;
687
+ let z = newZ; // Start at floor level
688
+
689
+ // Check if there is floor (not air)
690
+ if (matrix[z][x][y] === material) {
691
+ // Consider a random probability of adding a carpet
692
+ if (Math.random() < probability) {
693
+ // Choose a random color for the carpet
694
+ let randomColor = colors[Math.floor(Math.random() * colors.length)];
695
+ // Add carpet one z position above the floor with a random color
696
+ matrix[z + 1][x][y] = `${randomColor}_carpet`;
697
+ }
698
+ }
699
+ }
700
+ }
701
+ }
702
+
703
+ function addLadder(matrix, x, y, z) {
704
+ let currentZ = z + 1;
705
+
706
+ // turn the floor into air where person would go up
707
+ matrix[currentZ][x + 1][y] = 'air';
708
+
709
+ // Build the first 3 ladder segments from floor level downwards
710
+ for (let i = 0; i < 3; i++) {
711
+ // Place stone block behind ladder
712
+ matrix[currentZ][x - 1][y] = 'stone';
713
+ // Place ladder
714
+ matrix[currentZ][x][y] = 'ladder[facing=north]';
715
+ currentZ -= 1;
716
+ }
717
+
718
+ // Continue building ladder downwards until a floor is hit or we reach the bottom
719
+ while (currentZ >= 0 && matrix[currentZ][x][y] === 'air') {
720
+ // Place stone block behind ladder
721
+ matrix[currentZ][x - 1][y] = 'stone';
722
+ // Place ladder
723
+ matrix[currentZ][x][y] = 'ladder[facing=north]';
724
+
725
+ // Move down
726
+ currentZ--;
727
+ }
728
+ }
729
+
730
+
731
+ function embellishments(carpet, windowStyle, matrix, newX, newY, newZ, newLength, newWidth, newDepth, material) {
732
+
733
+
734
+ switch (windowStyle) {
735
+ case 0:
736
+ break;
737
+ case 1:
738
+ addWindowsAsSquares(matrix, newZ, newY, newZ, newLength, newWidth, newDepth, material)
739
+ break;
740
+ case 2:
741
+ addWindowsAsPlane(matrix, newZ, newY, newZ, newLength, newWidth, newDepth, material)
742
+ }
743
+
744
+
745
+ switch (carpet) {
746
+ case 0:
747
+ break;
748
+ case 1:
749
+ addCarpet(0.3, matrix, newX, newY, newZ, newLength, newWidth, material);
750
+ break;
751
+ case 2:
752
+ addCarpet(0.7, matrix, newX, newY, newZ, newLength, newWidth, material)
753
+ break;
754
+ }
755
+
756
+
757
+ }
758
+
759
+
760
+ // Places rooms until we can't, or we place all
761
+ // attempts random configurations of rooms in random directions.
762
+ while (placedRooms < rooms) {
763
+ let roomPlaced = false;
764
+
765
+ for (let attempt = 0; attempt < 150; attempt++) {
766
+
767
+ const material = roomMaterials[Math.floor(Math.random() * roomMaterials.length)];
768
+
769
+
770
+ // dimensions of room
771
+ const newLength = Math.max(minRoomLength, Math.floor(Math.random() * roomVariance) + minRoomLength);
772
+ const newWidth = Math.max(minRoomWidth, Math.floor(Math.random() * roomVariance) + minRoomWidth);
773
+ const newDepth = Math.max(minRoomDepth, Math.floor(Math.random() * Math.floor(roomVariance / 2)) + minRoomDepth);
774
+ let newX, newY, newZ;
775
+
776
+ // first room is special
777
+ if (placedRooms === 0) {
778
+ // First room placement
779
+ newX = Math.floor(Math.random() * (m - newLength - 1)) + 1;
780
+ newY = Math.floor(Math.random() * (n - newWidth - 1)) + 1;
781
+ newZ = 0; // Ground floor
782
+
783
+ if (validateAndBuildBorder(matrix, newX, newY, newZ, newLength, newWidth, newDepth, m, n, p, material)) {
784
+ lastRoom = {x: newX, y: newY, z: newZ, length: newLength, width: newWidth, depth: newDepth};
785
+ roomPlaced = true;
786
+ placedRooms++;
787
+
788
+ // Add doors to all four sides
789
+ // Left side
790
+ addDoor(matrix, newX, newY + Math.floor(newWidth / 2), newZ, material);
791
+ // Right side
792
+ addDoor(matrix, newX + newLength - 1, newY + Math.floor(newWidth / 2), newZ, material);
793
+ // Front side
794
+ addDoor(matrix, newX + Math.floor(newLength / 2), newY, newZ, material);
795
+ // Back side
796
+ addDoor(matrix, newX + Math.floor(newLength / 2), newY + newWidth - 1, newZ, material);
797
+
798
+ addCarpet(0.7, matrix, newX, newY, newZ, newLength, newWidth)
799
+ }
800
+
801
+ break;
802
+ } else {
803
+ const direction = getRandomDirection();
804
+
805
+ switch (direction) {
806
+ case 'above':
807
+ newX = lastRoom.x;
808
+ newY = lastRoom.y;
809
+ newZ = lastRoom.z + lastRoom.depth - 1;
810
+ if (validateAndBuildBorder(matrix, newX, newY, newZ, newLength, newWidth, newDepth, m, n, p, material)) {
811
+
812
+ embellishments(carpetStyle, windowStyle, matrix, newX, newY, newZ, newLength, newWidth, newDepth, material)
813
+
814
+ // addLadder(matrix, lastRoom.x + Math.floor(lastRoom.length / 2),
815
+ // lastRoom.y + Math.floor(lastRoom.width / 2),
816
+ // newZ); // Adding the ladder
817
+
818
+ addStairs(matrix, newX, newY, newZ, newLength, newWidth, material)
819
+
820
+
821
+ lastRoom = {x: newX, y: newY, z: newZ, length: newLength, width: newWidth, depth: newDepth};
822
+ roomPlaced = true;
823
+ placedRooms++;
824
+ break;
825
+ }
826
+ break;
827
+
828
+ case 'left':
829
+ newX = lastRoom.x - newLength + 1;
830
+ newY = lastRoom.y;
831
+ newZ = lastRoom.z;
832
+ if (validateAndBuildBorder(matrix, newX, newY, newZ, newLength, newWidth, newDepth, m, n, p, material)) {
833
+
834
+
835
+ embellishments(carpetStyle, windowStyle, matrix, newX, newY, newZ, newLength, newWidth, newDepth, material)
836
+
837
+
838
+ addDoor(matrix, lastRoom.x, lastRoom.y + Math.floor(lastRoom.width / 2), lastRoom.z, material);
839
+
840
+
841
+ lastRoom = {x: newX, y: newY, z: newZ, length: newLength, width: newWidth, depth: newDepth};
842
+ roomPlaced = true;
843
+ placedRooms++;
844
+ break;
845
+ }
846
+ break;
847
+
848
+ case 'right':
849
+ newX = lastRoom.x + lastRoom.length - 1;
850
+ newY = lastRoom.y;
851
+ newZ = lastRoom.z;
852
+ if (validateAndBuildBorder(matrix, newX, newY, newZ, newLength, newWidth, newDepth, m, n, p, material)) {
853
+
854
+ embellishments(carpetStyle, windowStyle, matrix, newX, newY, newZ, newLength, newWidth, newDepth, material)
855
+
856
+
857
+ addDoor(matrix, lastRoom.x + lastRoom.length - 1,
858
+ lastRoom.y + Math.floor(lastRoom.width / 2),
859
+ lastRoom.z, material);
860
+
861
+
862
+ lastRoom = {x: newX, y: newY, z: newZ, length: newLength, width: newWidth, depth: newDepth};
863
+ roomPlaced = true;
864
+ placedRooms++;
865
+ break;
866
+ }
867
+ break;
868
+
869
+ case 'forward':
870
+ newX = lastRoom.x;
871
+ newY = lastRoom.y + lastRoom.width - 1;
872
+ newZ = lastRoom.z;
873
+ if (validateAndBuildBorder(matrix, newX, newY, newZ, newLength, newWidth, newDepth, m, n, p, material)) {
874
+
875
+ embellishments(carpetStyle, windowStyle, matrix, newX, newY, newZ, newLength, newWidth, newDepth, material)
876
+
877
+
878
+ addDoor(matrix, lastRoom.x + Math.floor(lastRoom.length / 2),
879
+ lastRoom.y + lastRoom.width - 1,
880
+ lastRoom.z, material);
881
+
882
+
883
+ lastRoom = {x: newX, y: newY, z: newZ, length: newLength, width: newWidth, depth: newDepth};
884
+ roomPlaced = true;
885
+ placedRooms++;
886
+ break;
887
+ }
888
+ break;
889
+
890
+ case 'backward':
891
+ newX = lastRoom.x;
892
+ newY = lastRoom.y - newWidth + 1;
893
+ newZ = lastRoom.z;
894
+ if (validateAndBuildBorder(matrix, newX, newY, newZ, newLength, newWidth, newDepth, m, n, p, material)) {
895
+
896
+ embellishments(carpetStyle, windowStyle, matrix, newX, newY, newZ, newLength, newWidth, newDepth, material)
897
+
898
+
899
+ addDoor(matrix, lastRoom.x + Math.floor(lastRoom.length / 2),
900
+ lastRoom.y,
901
+ lastRoom.z, material);
902
+
903
+
904
+ lastRoom = {x: newX, y: newY, z: newZ, length: newLength, width: newWidth, depth: newDepth};
905
+ roomPlaced = true;
906
+ placedRooms++;
907
+ break;
908
+ }
909
+ break;
910
+ }
911
+
912
+ if (roomPlaced) {
913
+ break;
914
+ }
915
+ }
916
+ }
917
+
918
+ if (!roomPlaced) {
919
+ console.warn(`Could not place room ${placedRooms + 1}`);
920
+ break;
921
+ }
922
+ }
923
+
924
+ // uncomment to visualize blueprint output
925
+ // printMatrix(matrix)
926
+
927
+ return matrixToBlueprint(matrix, startCoord)
928
+ }
929
+
930
+
931
+
932
+
933
+ /**
934
+ * for cutesy output
935
+ * @param matrix
936
+ */
937
+ function printMatrix(matrix) {
938
+ matrix.forEach((layer, layerIndex) => {
939
+ console.log(`Layer ${layerIndex}:`);
940
+ layer.forEach(row => {
941
+ console.log(
942
+ row.map(cell => {
943
+ switch (cell) {
944
+ case 'stone': return '█'; // Wall
945
+ case 'air': return '.'; // Open space
946
+ case 'dark_oak_door[half=upper, hinge=left]': return 'D';
947
+ case 'dark_oak_door[half=lower, hinge=left]': return 'D';
948
+ case 'oak_stairs[facing=north]': return 'S'; // Stairs
949
+ case 'oak_stairs[facing=east]': return 'S'; // Stairs
950
+ case 'oak_stairs[facing=south]': return 'S'; // Stairs
951
+ case 'oak_stairs[facing=west]': return 'S'; // Stairs
952
+ case 'glass': return 'W'
953
+
954
+
955
+ default: return '?'; // Unknown or unmarked space
956
+ }
957
+ }).join(' ')
958
+ );
959
+ });
960
+ console.log('---');
961
+ });
962
+ }
963
+
964
+ /**
965
+ * Converts a 3D matrix into a Minecraft blueprint format
966
+ * @param {Array<Array<Array<string>>>} matrix - 3D matrix of block types
967
+ * @param {number[]} startCoord - Starting coordinates [x, y, z]
968
+ * @returns {Object} a Blueprint object in Minecraft format
969
+ */
970
+ function matrixToBlueprint(matrix, startCoord) {
971
+ // Validate inputs
972
+ if (!Array.isArray(matrix) || !Array.isArray(startCoord) || startCoord.length !== 3) {
973
+ console.log(matrix)
974
+ throw new Error('Invalid input format');
975
+ }
976
+
977
+ const [startX, startY, startZ] = startCoord;
978
+
979
+
980
+ // CONSIDER: using blueprint class here?
981
+ return {
982
+ levels: matrix.map((level, levelIndex) => ({
983
+ level: levelIndex,
984
+ coordinates: [
985
+ startX,
986
+ startY + levelIndex,
987
+ startZ
988
+ ],
989
+ placement: level.map(row =>
990
+ // Ensure each block is a string, default to 'air' if undefined
991
+ row.map(block => block?.toString() || 'air')
992
+ )
993
+ }))
994
+ };
995
+ }
996
+
997
+ async function getBlockName(bot, coordinate) {
998
+ const blockAtLocation = bot.blockAt(new Vec3(coordinate.x, coordinate.y, coordinate.z));
999
+ return blockAtLocation ? bot.registry.blocks[blockAtLocation.type].name : "air";
1000
+ }
1001
+
1002
+ /**
1003
+ * Converts a world location to a blueprint. takes some time to ensure that the chunks are loaded before conversion.
1004
+ * @param startCoord - [x,y,z] that signifies the start of the blueprint
1005
+ * @param y_amount - how many spaces you want to register from the start coordinate in the y dimension
1006
+ * @param x_amount - how many spaces in the x direction on minecraft
1007
+ * @param z_amount - how many spaces from the start coordinate in the z direction in minecraft
1008
+ * @param bot - the mineflayer agent (ex. andy)
1009
+ * @returns - a Blueprint object of the converted blueprint
1010
+ */
1011
+ export async function worldToBlueprint(startCoord, y_amount, x_amount, z_amount, bot) {
1012
+ await bot.waitForChunksToLoad();
1013
+
1014
+ const materials = {};
1015
+
1016
+ const levels = [];
1017
+ for (let y = 0; y < y_amount; y++) {
1018
+ const placement = [];
1019
+ const coordinates = [startCoord.x, startCoord.y + y, startCoord.z];
1020
+ for (let z = 0; z < z_amount; z++) {
1021
+ const row = [];
1022
+ for (let x = 0; x < x_amount; x++) {
1023
+ const worldCoord = {
1024
+ x: startCoord.x + x,
1025
+ y: startCoord.y + y,
1026
+ z: startCoord.z + z
1027
+ };
1028
+ await bot.waitForChunksToLoad(worldCoord);
1029
+ const blockName = await getBlockName(bot, worldCoord);
1030
+ row.push(blockName);
1031
+ if (blockName !== 'air') {
1032
+ materials[blockName] = (materials[blockName] || 0) + 1;
1033
+ }
1034
+ }
1035
+ placement.push(row);
1036
+ }
1037
+ levels.push({
1038
+ level: y,
1039
+ coordinates: coordinates,
1040
+ placement: placement
1041
+ })
1042
+ }
1043
+ console.log(levels);
1044
+ const blueprint_data = {
1045
+ materials: materials,
1046
+ levels: levels
1047
+ }
1048
+ return blueprint_data
1049
+ }
1050
+
1051
+ export function blueprintToTask(blueprint_data, num_agents) {
1052
+ let initialInventory = {}
1053
+ for (let j = 0; j < num_agents; j++) {
1054
+ initialInventory[JSON.stringify(j)] = {"diamond_pickaxe": 1, "diamond_axe": 1, "diamond_shovel": 1};
1055
+ }
1056
+
1057
+ let give_agent = 0;
1058
+ console.log("materials", blueprint_data.materials)
1059
+ for (const key of Object.keys(blueprint_data.materials)) {
1060
+ initialInventory[JSON.stringify(give_agent)][key] = blueprint_data.materials[key];
1061
+ give_agent = (give_agent + 1) % num_agents;
1062
+ }
1063
+
1064
+ const task = {
1065
+ type: "construction",
1066
+ goal: "Make a structure with the blueprint below",
1067
+ conversation: "Let's share materials and make a structure with the blueprint",
1068
+ agent_count: num_agents,
1069
+ blueprint: blueprint_data,
1070
+ initial_inventory: initialInventory,
1071
+ };
1072
+ return task;
1073
+ }
1074
+
1075
+ // testing code
1076
+
1077
+ // let blueprint = proceduralGeneration(20,10,20)
1078
+ // const b = new Blueprint(blueprint)
1079
+ // const result = b.autoBuild();
1080
+ // const commands = result.commands;
1081
+ // const nearbyPosition = result.nearbyPosition;
1082
+ //
1083
+ //
1084
+ // import {initBot} from "../../utils/mcdata.js";
1085
+ // let bot = initBot("andy");
1086
+
1087
+
1088
+ // example usage of world->blueprint function
1089
+
1090
+ // bot.once('spawn', async () => {
1091
+ // console.log("nearby position", nearbyPosition);
1092
+ // bot.chat(`/tp @andy ${nearbyPosition.x} ${nearbyPosition.y} ${nearbyPosition.z}`);
1093
+ // for (const command of commands) {
1094
+ // bot.chat(command);
1095
+ // }
1096
+ // const startCoord = {
1097
+ // x: 148,
1098
+ // y: -60,
1099
+ // z: -170
1100
+ // };
1101
+ // // [148,-60,-170] is default start for procedural generation
1102
+ //
1103
+ // const worldOutput = await worldToBlueprint(startCoord, 20,10,20, bot)
1104
+ // });