mc_autobot/index.js
2023-03-26 17:02:24 +07:00

252 lines
7.9 KiB
JavaScript

import Config from "./config.js";
import mcdataLib from "minecraft-data";
import { createBot } from "mineflayer";
import { pathfinder, Movements, default as mpf } from "mineflayer-pathfinder";
const { GoalBlock, GoalNear } = mpf.goals;
import Vec3 from "vec3";
const bot = createBot(Config.mc.bot);
const mcData = mcdataLib(bot.version);
let upperLeft = null;
let bottomRight = null;
bot.loadPlugin(pathfinder);
const defaultMove = new Movements(bot, mcData);
bot.pathfinder.setMovements(defaultMove);
bot.once("spawn", () => {
console.log("[MC] Bot spawned!");
});
bot.on('chat', (username, message) => {
if (username === bot.username) return;
const cmd = message.split(" ", 2)[0];
switch (cmd) {
case "!help":
bot.chat("Prefix: !; Commands: help, check, holding, field-set, field, till, sow, reap, stop");
break;
case "!check":
checkBlockUnder();
break;
case "!holding":
bot.chat(`holding ${bot.heldItem}`);
console.log("holding: %s", bot.heldItem);
break;
case "!field-set":
let parts = message.split(" ");
let [x1, y1, z1, x2, y2, z2] = parts.slice(1);
upperLeft = new Vec3(~~x1, ~~y1, ~~z1);
bottomRight = new Vec3(~~x2, ~~y2, ~~z2);
bot.chat(`Set field rect to ${upperLeft} til ${bottomRight}`);
break;
case "!field":
findFieldBorders();
break;
case "!till":
startTilling();
break;
case "!sow":
startSowing();
break;
case "!reap":
startReaping();
break;
case "!stop":
bot.pathfinder.stop();
break;
default:
break;
}
});
bot.on('kicked', console.log);
bot.on('error', console.log);
const gotoUntill = async (dx, dy, dz, predicateOnBlock) => {
try {
let ul = bot.entity.position.offset(dx, dy, dz);
let targetBlock = bot.blockAt(ul);
while (predicateOnBlock(targetBlock)) {
await bot.pathfinder.goto(new GoalBlock(ul.x, ul.y, ul.z));
ul = bot.entity.position.offset(dx, dy, dz);
targetBlock = bot.blockAt(ul);
}
} catch (e) {
bot.chat(`Shit happened! ${e}`);
console.error(e);
}
}
const checkBlockUnder = async () => {
let targetBlock = bot.blockAt(bot.entity.position.offset(0, -1, 0));
bot.chat(`Block under: ${targetBlock}`)
}
const findFieldBorders = async () => {
try {
await gotoUntill(1, 0, 0, block => block.name === "air"); // go left
await gotoUntill(0, 0, 1, block => block.name === "air"); // go up
upperLeft = bot.entity.position;
await gotoUntill(-1, 0, 0, block => block.name === "air"); // go right
await gotoUntill(0, 0, -1, block => block.name === "air"); // go down
bottomRight = bot.entity.position;
bot.chat(`Done, ${upperLeft} to ${bottomRight}`);
} catch (e) {
bot.chat(`Shit happened! ${e}`);
console.error(e);
}
}
const isSowable = (block) => {
const blockAbove = bot.blockAt(block.position.offset(0, 1, 0));
return !blockAbove || blockAbove.name === mcData.blocksByName.air.name;
}
const findDrops = (dropItemId) => {
return Object.values(bot.entities).filter(entity => {
return entity.name === "item" && entity.metadata.length >= 8 && entity.metadata[8].itemId == dropItemId
}).map(item => {
return item.position;
});
}
const startTilling = async () => {
if (!upperLeft || !bottomRight) {
bot.chat("I dont know about field rect!");
return;
}
const diamond_hoe_id = mcData.itemsByName.diamond_hoe.id;
await bot.equip(diamond_hoe_id, "hand");
if (bot.heldItem === null || bot.heldItem.type !== diamond_hoe_id) {
bot.chat("No hoe in my inventory :(");
return;
}
let uy = ~~bot.entity.position.y;
let lx = Math.floor(Math.min(upperLeft.x, bottomRight.x));
let hx = Math.floor(Math.max(upperLeft.x, bottomRight.x));
let lz = Math.floor(Math.min(upperLeft.z, bottomRight.z));
let hz = Math.floor(Math.max(upperLeft.z, bottomRight.z));
bot.chat("Started tilling the field");
try {
for (let desiredX = lx; desiredX <= hx; desiredX++) {
for (let desiredZ = lz; desiredZ <= hz; desiredZ++) {
await bot.pathfinder.goto(new GoalBlock(desiredX, uy, desiredZ));
let targetBlock = bot.blockAt(new Vec3(desiredX, uy - 1, desiredZ));
await bot.activateBlock(targetBlock);
}
}
} catch (e) {
bot.chat(`Shit happened! ${e}`);
console.error(e);
}
bot.chat("Done, tilled the field");
}
const startSowing = async () => {
if (!upperLeft || !bottomRight) {
bot.chat("I dont know about field rect!");
return;
}
const carrot_id = mcData.itemsByName.carrot.id;
await bot.equip(carrot_id, "hand");
if (bot.heldItem === null || bot.heldItem.type !== carrot_id) {
bot.chat("No carrot in my inventory :(");
return;
}
let uy = ~~bot.entity.position.y;
let lx = Math.floor(Math.min(upperLeft.x, bottomRight.x));
let hx = Math.floor(Math.max(upperLeft.x, bottomRight.x));
let lz = Math.floor(Math.min(upperLeft.z, bottomRight.z));
let hz = Math.floor(Math.max(upperLeft.z, bottomRight.z));
bot.chat("Started sowing the field");
try {
for (let desiredX = lx; desiredX <= hx; desiredX++) {
for (let desiredZ = lz; desiredZ <= hz; desiredZ++) {
await bot.pathfinder.goto(new GoalNear(desiredX, uy, desiredZ, 2));
let targetBlock = bot.blockAt(new Vec3(desiredX, uy, desiredZ));
if (isSowable(targetBlock)) {
await bot.placeBlock(targetBlock, new Vec3(0, 1, 0))
}
}
}
} catch (e) {
bot.chat(`Shit happened! ${e}`);
console.error(e);
}
bot.chat("Done, sowed the field");
}
const startReaping = async () => {
if (!upperLeft || !bottomRight) {
bot.chat("I dont know about field rect!");
return;
}
const carrot_id = mcData.itemsByName.carrot.id;
const carrot_block_id = mcData.blocksByName.carrots.id;
let uy = ~~bot.entity.position.y;
let lx = Math.floor(Math.min(upperLeft.x, bottomRight.x));
let hx = Math.floor(Math.max(upperLeft.x, bottomRight.x));
let lz = Math.floor(Math.min(upperLeft.z, bottomRight.z));
let hz = Math.floor(Math.max(upperLeft.z, bottomRight.z));
bot.chat("Started reaping the field");
try {
for (let desiredX = lx; desiredX <= hx; desiredX++) {
for (let desiredZ = lz; desiredZ <= hz; desiredZ++) {
await bot.pathfinder.goto(new GoalNear(desiredX, uy, desiredZ, 2));
let targetBlock = bot.blockAt(new Vec3(desiredX, uy + 1, desiredZ));
if (targetBlock.type === carrot_block_id && targetBlock.metadata === 7) {
await bot.dig(targetBlock);
try {
await bot.equip(carrot_id, "hand");
if (bot.heldItem === null || bot.heldItem.type !== carrot_id) {
bot.chat("No carrot in my inventory :(");
return;
}
await bot.placeBlock(bot.blockAt(targetBlock.position.offset(0, -1, 0)), new Vec3(0, 1, 0))
} catch (e) {
console.error(e);
}
}
}
}
} catch (e) {
bot.chat(`Shit happened! ${e}`);
console.error(e);
}
for (let pos of findDrops(mcData.itemsByName.carrot.id)) {
await bot.pathfinder.goto(new GoalNear(pos.x, pos.y, pos.z, 1));
await bot.waitForTicks(5);
}
bot.chat("Done, reaped the field");
}