252 lines
7.9 KiB
JavaScript
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");
|
|
}
|