mirror of
https://github.com/kolbytn/mindcraft.git
synced 2025-04-22 06:02:07 +02:00
Merge pull request #118 from kolbytn/sideplacement
Place block in creative + side placement
This commit is contained in:
commit
28a51682da
6 changed files with 76 additions and 14 deletions
|
@ -153,8 +153,8 @@
|
||||||
{"role": "assistant", "content": "I found an oak log and I am now standing next to it. What next?"}
|
{"role": "assistant", "content": "I found an oak log and I am now standing next to it. What next?"}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{"role": "user", "content": "234jeb: build a little tower"},
|
{"role": "user", "content": "234jeb: build a little tower with a torch on the side"},
|
||||||
{"role": "assistant", "content": "```let pos = bot.entity.position;\nfor (let i = 0; i < 5; i++) {\n await skills.placeBlock(bot, 'dirt', pos.x, pos.y + i, pos.z);\n}\n```"},
|
{"role": "assistant", "content": "```let pos = bot.entity.position;\nfor (let i = 0; i < 5; i++) {\n await skills.placeBlock(bot, 'dirt', pos.x, pos.y + i, pos.z);\n}\nawait skills.placeBlock(bot, 'torch', pos.x + 1, pos.y + 4, pos.z, 'side');\n```"},
|
||||||
{"role": "system", "content": "Successfully placed 5 dirt."},
|
{"role": "system", "content": "Successfully placed 5 dirt."},
|
||||||
{"role": "assistant", "content": "I built a little tower!"}
|
{"role": "assistant", "content": "I built a little tower!"}
|
||||||
],
|
],
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
"mineflayer-pvp": "^1.3.2",
|
"mineflayer-pvp": "^1.3.2",
|
||||||
"openai": "^4.4.0",
|
"openai": "^4.4.0",
|
||||||
"patch-package": "^8.0.0",
|
"patch-package": "^8.0.0",
|
||||||
|
"prismarine-item": "^1.14.0",
|
||||||
"replicate": "^0.29.4",
|
"replicate": "^0.29.4",
|
||||||
"vec3": "^0.1.10",
|
"vec3": "^0.1.10",
|
||||||
"yargs": "^17.7.2"
|
"yargs": "^17.7.2"
|
||||||
|
|
|
@ -14,7 +14,7 @@ async function autoLight(bot) {
|
||||||
if (world.shouldPlaceTorch(bot)) {
|
if (world.shouldPlaceTorch(bot)) {
|
||||||
try {
|
try {
|
||||||
const pos = world.getPosition(bot);
|
const pos = world.getPosition(bot);
|
||||||
return await placeBlock(bot, 'torch', pos.x, pos.y, pos.z, true);
|
return await placeBlock(bot, 'torch', pos.x, pos.y, pos.z, 'bottom', true);
|
||||||
} catch (err) {return false;}
|
} catch (err) {return false;}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -482,7 +482,7 @@ export async function breakBlockAt(bot, x, y, z) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function placeBlock(bot, blockType, x, y, z, no_cheat=false) {
|
export async function placeBlock(bot, blockType, x, y, z, placeOn='bottom', dontCheat=false) {
|
||||||
/**
|
/**
|
||||||
* Place the given block type at the given position. It will build off from any adjacent blocks. Will fail if there is a block in the way or nothing to build off of.
|
* Place the given block type at the given position. It will build off from any adjacent blocks. Will fail if there is a block in the way or nothing to build off of.
|
||||||
* @param {MinecraftBot} bot, reference to the minecraft bot.
|
* @param {MinecraftBot} bot, reference to the minecraft bot.
|
||||||
|
@ -490,31 +490,65 @@ export async function placeBlock(bot, blockType, x, y, z, no_cheat=false) {
|
||||||
* @param {number} x, the x coordinate of the block to place.
|
* @param {number} x, the x coordinate of the block to place.
|
||||||
* @param {number} y, the y coordinate of the block to place.
|
* @param {number} y, the y coordinate of the block to place.
|
||||||
* @param {number} z, the z coordinate of the block to place.
|
* @param {number} z, the z coordinate of the block to place.
|
||||||
* @param {boolean} no_cheat, overrides cheat mode to place the block normally. Defaults to false.
|
* @param {string} placeOn, the preferred side of the block to place on. Can be 'top', 'bottom', 'north', 'south', 'east', 'west', or 'side'. Defaults to bottom. Will place on first available side if not possible.
|
||||||
|
* @param {boolean} dontCheat, overrides cheat mode to place the block normally. Defaults to false.
|
||||||
* @returns {Promise<boolean>} true if the block was placed, false otherwise.
|
* @returns {Promise<boolean>} true if the block was placed, false otherwise.
|
||||||
* @example
|
* @example
|
||||||
* let position = world.getPosition(bot);
|
* let p = world.getPosition(bot);
|
||||||
* await skills.placeBlock(bot, "oak_log", position.x + 1, position.y - 1, position.x);
|
* await skills.placeBlock(bot, "oak_log", p.x + 2, p.y, p.x);
|
||||||
|
* await skills.placeBlock(bot, "torch", p.x + 1, p.y, p.x, 'side');
|
||||||
**/
|
**/
|
||||||
if (!mc.getBlockId(blockType)) {
|
if (!mc.getBlockId(blockType)) {
|
||||||
log(bot, `Invalid block type: ${blockType}.`);
|
log(bot, `Invalid block type: ${blockType}.`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bot.modes.isOn('cheat') && !no_cheat) {
|
const target_dest = new Vec3(Math.floor(x), Math.floor(y), Math.floor(z));
|
||||||
|
if (bot.modes.isOn('cheat') && !dontCheat) {
|
||||||
|
// invert the facing direction
|
||||||
|
let face = placeOn === 'north' ? 'south' : placeOn === 'south' ? 'north' : placeOn === 'east' ? 'west' : 'east';
|
||||||
|
if (blockType.includes('torch') && placeOn !== 'bottom') {
|
||||||
|
// insert wall_ before torch
|
||||||
|
blockType = blockType.replace('torch', 'wall_torch');
|
||||||
|
if (placeOn !== 'side' && placeOn !== 'top') {
|
||||||
|
blockType += `[facing=${face}]`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (blockType.includes('button') || blockType === 'lever') {
|
||||||
|
if (placeOn === 'top') {
|
||||||
|
blockType += `[face=ceiling]`;
|
||||||
|
}
|
||||||
|
else if (placeOn === 'bottom') {
|
||||||
|
blockType += `[face=floor]`;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
blockType += `[facing=${face}]`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (blockType === 'ladder' || blockType === 'repeater' || blockType === 'comparator') {
|
||||||
|
blockType += `[facing=${face}]`;
|
||||||
|
}
|
||||||
|
|
||||||
let msg = '/setblock ' + Math.floor(x) + ' ' + Math.floor(y) + ' ' + Math.floor(z) + ' ' + blockType;
|
let msg = '/setblock ' + Math.floor(x) + ' ' + Math.floor(y) + ' ' + Math.floor(z) + ' ' + blockType;
|
||||||
bot.chat(msg);
|
bot.chat(msg);
|
||||||
log(bot, `Used /setblock to place ${blockType} at ${x}, ${y}, ${z}.`);
|
if (blockType.includes('door'))
|
||||||
|
bot.chat('/setblock ' + Math.floor(x) + ' ' + Math.floor(y+1) + ' ' + Math.floor(z) + ' ' + blockType + '[half=upper]');
|
||||||
|
if (blockType.includes('bed'))
|
||||||
|
bot.chat('/setblock ' + Math.floor(x) + ' ' + Math.floor(y) + ' ' + Math.floor(z-1) + ' ' + blockType + '[part=head]');
|
||||||
|
log(bot, `Used /setblock to place ${blockType} at ${target_dest}.`);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let block = bot.inventory.items().find(item => item.name === blockType);
|
let block = bot.inventory.items().find(item => item.name === blockType);
|
||||||
|
if (!block && bot.game.gameMode === 'creative') {
|
||||||
|
await bot.creative.setInventorySlot(36, mc.makeItem(blockType, 1)); // 36 is first hotbar slot
|
||||||
|
block = bot.inventory.items().find(item => item.name === blockType);
|
||||||
|
}
|
||||||
if (!block) {
|
if (!block) {
|
||||||
log(bot, `Don't have any ${blockType} to place.`);
|
log(bot, `Don't have any ${blockType} to place.`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const target_dest = new Vec3(Math.floor(x), Math.floor(y), Math.floor(z));
|
|
||||||
const targetBlock = bot.blockAt(target_dest);
|
const targetBlock = bot.blockAt(target_dest);
|
||||||
if (targetBlock.name === blockType) {
|
if (targetBlock.name === blockType) {
|
||||||
log(bot, `${blockType} already at ${targetBlock.position}.`);
|
log(bot, `${blockType} already at ${targetBlock.position}.`);
|
||||||
|
@ -533,12 +567,32 @@ export async function placeBlock(bot, blockType, x, y, z, no_cheat=false) {
|
||||||
// get the buildoffblock and facevec based on whichever adjacent block is not empty
|
// get the buildoffblock and facevec based on whichever adjacent block is not empty
|
||||||
let buildOffBlock = null;
|
let buildOffBlock = null;
|
||||||
let faceVec = null;
|
let faceVec = null;
|
||||||
const dirs = [Vec3(0, -1, 0), Vec3(0, 1, 0), Vec3(1, 0, 0), Vec3(-1, 0, 0), Vec3(0, 0, 1), Vec3(0, 0, -1)];
|
const dir_map = {
|
||||||
|
'top': Vec3(0, 1, 0),
|
||||||
|
'bottom': Vec3(0, -1, 0),
|
||||||
|
'north': Vec3(0, 0, -1),
|
||||||
|
'south': Vec3(0, 0, 1),
|
||||||
|
'east': Vec3(1, 0, 0),
|
||||||
|
'west': Vec3(-1, 0, 0),
|
||||||
|
}
|
||||||
|
let dirs = [];
|
||||||
|
if (placeOn === 'side') {
|
||||||
|
dirs.push(dir_map['north'], dir_map['south'], dir_map['east'], dir_map['west']);
|
||||||
|
}
|
||||||
|
else if (dir_map[placeOn] !== undefined) {
|
||||||
|
dirs.push(dir_map[placeOn]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dirs.push(dir_map['bottom']);
|
||||||
|
log(bot, `Unknown placeOn value "${placeOn}". Defaulting to bottom.`);
|
||||||
|
}
|
||||||
|
dirs.push(...Object.values(dir_map).filter(d => !dirs.includes(d)));
|
||||||
|
|
||||||
for (let d of dirs) {
|
for (let d of dirs) {
|
||||||
const block = bot.blockAt(target_dest.plus(d));
|
const block = bot.blockAt(target_dest.plus(d));
|
||||||
if (!empty_blocks.includes(block.name)) {
|
if (!empty_blocks.includes(block.name)) {
|
||||||
buildOffBlock = block;
|
buildOffBlock = block;
|
||||||
faceVec = new Vec3(-d.x, -d.y, -d.z);
|
faceVec = new Vec3(-d.x, -d.y, -d.z); // invert
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -261,6 +261,8 @@ export function shouldPlaceTorch(bot) {
|
||||||
const pos = getPosition(bot);
|
const pos = getPosition(bot);
|
||||||
// TODO: check light level instead of nearby torches, block.light is broken
|
// TODO: check light level instead of nearby torches, block.light is broken
|
||||||
let nearest_torch = getNearestBlock(bot, 'torch', 6);
|
let nearest_torch = getNearestBlock(bot, 'torch', 6);
|
||||||
|
if (!nearest_torch)
|
||||||
|
nearest_torch = getNearestBlock(bot, 'wall_torch', 6);
|
||||||
if (!nearest_torch) {
|
if (!nearest_torch) {
|
||||||
const block = bot.blockAt(pos);
|
const block = bot.blockAt(pos);
|
||||||
let has_torch = bot.inventory.items().find(item => item.name === 'torch');
|
let has_torch = bot.inventory.items().find(item => item.name === 'torch');
|
||||||
|
|
|
@ -156,7 +156,7 @@ const modes = [
|
||||||
if (Date.now() - this.last_place < this.cooldown * 1000) return;
|
if (Date.now() - this.last_place < this.cooldown * 1000) return;
|
||||||
execute(this, agent, async () => {
|
execute(this, agent, async () => {
|
||||||
const pos = agent.bot.entity.position;
|
const pos = agent.bot.entity.position;
|
||||||
await skills.placeBlock(agent.bot, 'torch', pos.x, pos.y, pos.z, true);
|
await skills.placeBlock(agent.bot, 'torch', pos.x, pos.y, pos.z, 'bottom', true);
|
||||||
});
|
});
|
||||||
this.last_place = Date.now();
|
this.last_place = Date.now();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import minecraftData from 'minecraft-data';
|
import minecraftData from 'minecraft-data';
|
||||||
import settings from '../../settings.js';
|
import settings from '../../settings.js';
|
||||||
import { createBot } from 'mineflayer';
|
import { createBot } from 'mineflayer';
|
||||||
|
import prismarine_items from 'prismarine-item';
|
||||||
import { pathfinder } from 'mineflayer-pathfinder';
|
import { pathfinder } from 'mineflayer-pathfinder';
|
||||||
import { plugin as pvp } from 'mineflayer-pvp';
|
import { plugin as pvp } from 'mineflayer-pvp';
|
||||||
import { plugin as collectblock } from 'mineflayer-collectblock';
|
import { plugin as collectblock } from 'mineflayer-collectblock';
|
||||||
|
@ -10,7 +11,7 @@ const armorManager = plugin;
|
||||||
|
|
||||||
const mc_version = settings.minecraft_version;
|
const mc_version = settings.minecraft_version;
|
||||||
const mcdata = minecraftData(mc_version);
|
const mcdata = minecraftData(mc_version);
|
||||||
|
const Item = prismarine_items(mc_version);
|
||||||
|
|
||||||
export const WOOD_TYPES = ['oak', 'spruce', 'birch', 'jungle', 'acacia', 'dark_oak'];
|
export const WOOD_TYPES = ['oak', 'spruce', 'birch', 'jungle', 'acacia', 'dark_oak'];
|
||||||
export const MATCHING_WOOD_BLOCKS = [
|
export const MATCHING_WOOD_BLOCKS = [
|
||||||
|
@ -237,3 +238,7 @@ export function getBlockTool(blockName) {
|
||||||
}
|
}
|
||||||
return getItemName(Object.keys(block.harvestTools)[0]); // Double check first tool is always simplest
|
return getItemName(Object.keys(block.harvestTools)[0]); // Double check first tool is always simplest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function makeItem(name, amount=1) {
|
||||||
|
return new Item(getItemId(name), amount);
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue