From 0eb503cde8a21ddab3a153e476c7ffbeded28343 Mon Sep 17 00:00:00 2001 From: mmaheshwari2 Date: Thu, 23 Jan 2025 11:31:42 -0800 Subject: [PATCH 1/2] finished function to test the blueprint layout. now working on procedurally generating the blueprint --- test/test_blueprint_layout.js | 160 +++++++++++++++++++++++++++++++- test/test_generate_blueprint.js | 24 +++++ 2 files changed, 181 insertions(+), 3 deletions(-) create mode 100644 test/test_generate_blueprint.js diff --git a/test/test_blueprint_layout.js b/test/test_blueprint_layout.js index 050e5db..8dc31f1 100644 --- a/test/test_blueprint_layout.js +++ b/test/test_blueprint_layout.js @@ -1,3 +1,4 @@ +import mineflayer from "mineflayer"; const bot = mineflayer.createBot({ host: 'localhost', // Replace with your server IP or hostname @@ -6,6 +7,159 @@ const bot = mineflayer.createBot({ // password: 'your_bot_password' // Only if the server has online-mode=true }); -this.bot.on('spawn', async () => { - bot.chat("/setblock ~ ~ ~ stone"); -}); \ No newline at end of file +bot.on('spawn', async () => { + // generate a blueprint + const blueprint = { + "levels": [ + { + "level": 0, + "coordinates": [142, -60, -179], + "placement": [ + ["stone", "stone", "oak_door", "stone", "stone"], + ["stone", "air", "air", "air", "stone"], + ["stone", "air", "air", "air", "stone"], + ["stone", "stone", "stone", "stone", "stone"] + ] + }, + { + "level": 1, + "coordinates": [142, -59, -179], + "placement": [ + ["stone", "stone", "air", "stone", "stone"], + ["stone", "air", "air", "air", "stone"], + ["stone", "air", "air", "air", "stone"], + ["stone", "stone", "stone", "stone", "stone"] + ] + }, + { + "level": 2, + "coordinates": [142, -58, -179], + "placement": [ + ["stone", "stone", "stone", "stone", "stone"], + ["stone", "stone", "stone", "stone", "stone"], + ["stone", "stone", "stone", "stone", "stone"], + ["stone", "stone", "stone", "stone", "stone"], + ] + } + ] + }; + + // have andy build the blueprint automatically + const result = blueprintToCommands(blueprint); + // const result = clearHouse(blueprint) + const commands = result.commands; + const nearbyPosition = result.nearbyPosition; + for (const command of commands) { + bot.chat(command); + } + + console.log(commands.slice(-10)); + + // Print out the location nearby the blueprint + console.log(`tp ${nearbyPosition.x} ${nearbyPosition.y} ${nearbyPosition.z}`) + + +}); + + + + + +/** + * Takes in the blueprint, and then converts it into a set of /setblock commands for the bot to follow + * @Returns: An object containing the setblock commands as a list of strings, and a position nearby the blueprint but not in it + * @param blueprint + */ +function blueprintToCommands(blueprint) { + const commands = []; + + let minX = Infinity, maxX = -Infinity; + let minY = Infinity, maxY = -Infinity; + let minZ = Infinity, maxZ = -Infinity; + + for (const level of blueprint.levels) { + console.log(level.level) + const baseX = level.coordinates[0]; + const baseY = level.coordinates[1]; + const baseZ = level.coordinates[2]; + const placement = level.placement; + + // Update bounds + minX = Math.min(minX, baseX); + maxX = Math.max(maxX, baseX + placement[0].length - 1); + minY = Math.min(minY, baseY); + maxY = Math.max(maxY, baseY); + minZ = Math.min(minZ, baseZ); + maxZ = Math.max(maxZ, baseZ + placement.length - 1); + + // Loop through the 2D placement array + for (let z = 0; z < placement.length; z++) { + for (let x = 0; x < placement[z].length; x++) { + const blockType = placement[z][x]; + if (blockType) { + const setblockCommand = `/setblock ${baseX + x} ${baseY} ${baseZ + z} ${blockType}`; + commands.push(setblockCommand); + } + } + } + } + + // Calculate a position nearby the blueprint but not in it + const nearbyPosition = { + x: maxX + 5, // Move 5 blocks to the right + y: minY, // Stay on the lowest level of the blueprint + z: minZ // Stay aligned with the front of the blueprint + }; + + return { commands, nearbyPosition }; +} + + +/** + * Takes in a blueprint, and returns a set of commands to clear up the space. + * + */ +function clearHouse(blueprint) { + const commands = []; + + let minX = Infinity, maxX = -Infinity; + let minY = Infinity, maxY = -Infinity; + let minZ = Infinity, maxZ = -Infinity; + + for (const level of blueprint.levels) { + const baseX = level.coordinates[0]; + const baseY = level.coordinates[1]; + const baseZ = level.coordinates[2]; + const placement = level.placement; + + // Update bounds + minX = Math.min(minX, baseX); + maxX = Math.max(maxX, baseX + placement[0].length - 1); + minY = Math.min(minY, baseY); + maxY = Math.max(maxY, baseY); + minZ = Math.min(minZ, baseZ); + maxZ = Math.max(maxZ, baseZ + placement.length - 1); + + // Loop through the 2D placement array + for (let z = 0; z < placement.length; z++) { + for (let x = 0; x < placement[z].length; x++) { + const blockType = placement[z][x]; + if (blockType) { + const setblockCommand = `/setblock ${baseX + x} ${baseY} ${baseZ + z} air`; + commands.push(setblockCommand); + } + } + } + } + + // Calculate a position nearby the blueprint but not in it + const nearbyPosition = { + x: maxX + 5, // Move 5 blocks to the right + y: minY, // Stay on the lowest level of the blueprint + z: minZ // Stay aligned with the front of the blueprint + }; + + return { commands, nearbyPosition }; +} + + diff --git a/test/test_generate_blueprint.js b/test/test_generate_blueprint.js new file mode 100644 index 0000000..16b3f97 --- /dev/null +++ b/test/test_generate_blueprint.js @@ -0,0 +1,24 @@ + +/** Build house + * + * @param position coordinate that specify where the house should be built. come in as [x,y,z] + * @param windows an int that can be 0,1,2 for increasing frequencies of windows + * @param doors a boolean that has doors for room or no doors (if ur crazy ig) + */ +function buildHouse(position, windows, doors){ + // randomly initalize a space for a 3D matrix (make sure its big enough) + const minSize = 30; // Minimum size for width, length, height + const randomness = 20; // Maximum randomness to add + const width = Math.floor(Math.random() * (randomness + 1)) + minSize; + const length = Math.floor(Math.random() * (randomness + 1)) + minSize; + const height = Math.floor(Math.random() * (randomness + 1)) + minSize; + + + // slice up the space ensuring each compartment has at least 4x4x2 space. + + + // then, internally do things like windows / stairs / doors/ etc... +} + + + From dccb120f64d77fe6aa0b25cdb99c58f91280183a Mon Sep 17 00:00:00 2001 From: mmaheshwari2 Date: Thu, 23 Jan 2025 18:20:09 -0800 Subject: [PATCH 2/2] compartmentalized 3d matrix randomly --- test/test_generate_blueprint.js | 92 +++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/test/test_generate_blueprint.js b/test/test_generate_blueprint.js index 16b3f97..ed78fc3 100644 --- a/test/test_generate_blueprint.js +++ b/test/test_generate_blueprint.js @@ -15,6 +15,8 @@ function buildHouse(position, windows, doors){ // slice up the space ensuring each compartment has at least 4x4x2 space. + const resultMatrix = generateMatrix(width, length, height, 3); + console.log(resultMatrix) // then, internally do things like windows / stairs / doors/ etc... @@ -22,3 +24,93 @@ function buildHouse(position, windows, doors){ +//Todo: make robust. add stairs and windows and stuff +function generateMatrix(m, n, p, compartmentCount = 5) { + const matrix = Array.from({ length: m }, () => + Array.from({ length: n }, () => + Array(p).fill('air') + ) + ); + + // Mark borders + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + matrix[i][j][0] = matrix[i][j][p-1] = 'stone'; + matrix[i][0][j] = matrix[i][n-1][j] = 'stone'; + matrix[0][i][j] = matrix[m-1][i][j] = 'stone'; + } + } + + const usedSpaces = new Set(); + + for (let _ = 0; _ < compartmentCount; _++) { + const width = Math.floor(Math.random() * 6) + 3; + const height = Math.floor(Math.random() * 6) + 3; + const depth = Math.floor(Math.random() * 3) + 2; + + for (let attempt = 0; attempt < 50; attempt++) { + const x = Math.floor(Math.random() * (m - height - 1)) + 1; + const y = Math.floor(Math.random() * (n - width - 1)) + 1; + const z = Math.floor(Math.random() * (p - depth - 1)) + 1; + + const spaceAvailable = !Array.from({ length: height }).some((_, di) => + Array.from({ length: width }).some((_, dj) => + Array.from({ length: depth }).some((_, dk) => + usedSpaces.has(`${x+di},${y+dj},${z+dk}`) + ) + ) + ); + + if (spaceAvailable) { + for (let di = 0; di < height; di++) { + for (let dj = 0; dj < width; dj++) { + matrix[x+di][y+dj][z] = 'stone'; + matrix[x+di][y+dj][z+depth-1] = 'stone'; + usedSpaces.add(`${x+di},${y+dj},${z}`); + usedSpaces.add(`${x+di},${y+dj},${z+depth-1}`); + } + } + for (let di = 0; di < height; di++) { + for (let dk = 0; dk < depth; dk++) { + matrix[x+di][y][z+dk] = 'stone'; + matrix[x+di][y+width-1][z+dk] = 'stone'; + usedSpaces.add(`${x+di},${y},${z+dk}`); + usedSpaces.add(`${x+di},${y+width-1},${z+dk}`); + } + } + for (let dj = 0; dj < width; dj++) { + for (let dk = 0; dk < depth; dk++) { + matrix[x][y+dj][z+dk] = 'stone'; + matrix[x+height-1][y+dj][z+dk] = 'stone'; + usedSpaces.add(`${x},${y+dj},${z+dk}`); + usedSpaces.add(`${x+height-1},${y+dj},${z+dk}`); + } + } + break; + } + } + } + + return matrix; +} + + +function printMatrix(matrix) { + matrix.forEach(row => { + console.log(row.join(' ')); // Join elements of the row into a single string separated by spaces + }); +} + +const resultMatrix = generateMatrix(10, 10, 10, 3); +printMatrix(resultMatrix) + + + + + + + + +/** + * todo: Given a matrix, turn it into a blueprint + */ \ No newline at end of file