"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.retrieveTools = exports.standardToolFilter = void 0; const Tool_1 = require("./Tool"); const mineflayer_pathfinder_1 = require("mineflayer-pathfinder"); const util_1 = require("util"); const wait = (0, util_1.promisify)(setTimeout); /** * A standard tool filter that returns true for all tools and false * for everything else. * * @param item - The item to test against. */ function standardToolFilter(item) { if (item.name.includes('sword')) return true; if (item.name.includes('pickaxe')) return true; if (item.name.includes('shovel')) return true; if (item.name.includes('axe')) return true; if (item.name.includes('hoe')) return true; return false; } exports.standardToolFilter = standardToolFilter; /** * Moves from chest to chest in an effort to get at least one tool that meets the given requirements. * Throws an error in the callback if a tool cannot be retrieved. * * @param bot - The bot. * @param options - The options to use when collecting tools. * @param cb - The callback to execute when the function has completed. */ function retrieveTools(bot, options, cb) { return __awaiter(this, void 0, void 0, function* () { const chestLocations = [...options.chestLocations]; while (chestLocations.length > 0) { const chest = getClosestChest(bot, chestLocations); if (chest == null) { const err = (0, Tool_1.error)('NoChest', 'There are no chests with available tools in them!'); if ((cb != null) && typeof cb === 'function') cb(err); throw err; } chestLocations.splice(chestLocations.indexOf(chest), 1); try { console.info('Going to chest', chest); yield gotoChest(bot, chest); console.info('Pulling from chest', chest, options); const gotItem = yield pullFromChest(bot, chest, options); if (gotItem) { if (cb != null) cb(); return; } } catch (err) { if (cb != null) cb(err); throw err; } } }); } exports.retrieveTools = retrieveTools; /** * Moves the bot to the chest. * * @param bot - The bot to move. * @param location - The location to move to. * @param cb - The callback to run when finished. * @returns {Promise} */ function gotoChest(bot, location, cb) { return __awaiter(this, void 0, void 0, function* () { const pathfinder = bot.pathfinder; try { yield pathfinder.goto(new mineflayer_pathfinder_1.goals.GoalGetToBlock(location.x, location.y, location.z)); } catch (err) { if ((cb != null) && typeof cb === 'function') cb(err); throw err; } }); } /** * Pull items from a given chest * @param bot Bot * @param chestPos Chest Position * @param options Tool Retrieval Options {@link ToolRetrievalOptions} * @param cb Optional callback * @returns {Promise} */ function pullFromChest(bot, chestPos, options, cb) { var _a; return __awaiter(this, void 0, void 0, function* () { const chestBlock = bot.blockAt(chestPos); if (chestBlock == null) { const err = (0, Tool_1.error)('UnloadedChunk', 'Chest is located in an unloaded chunk!'); if ((cb != null) && typeof cb === 'function') cb(err, false); throw err; } try { const chest = yield bot.openChest(chestBlock); let itemsToPull = []; for (const item of chest.items()) { if (options.toolFilter(item)) { itemsToPull.push(item); } } if (itemsToPull.length === 0) { if ((cb != null) && typeof cb === 'function') cb(undefined, false); return false; } itemsToPull.sort((a, b) => options.toolCostFilter(a) - options.toolCostFilter(b)); const maxTools = (_a = options.maxTools) !== null && _a !== void 0 ? _a : 1; if (itemsToPull.length > maxTools) { itemsToPull = itemsToPull.slice(0, maxTools); } for (const item of itemsToPull) { yield chest.withdraw(item.type, item.metadata, item.count); } chest.close(); yield wait(200); // Wait for server to update inventory } catch (err) { if ((cb != null) && typeof cb === 'function') cb(err, true); throw err; } return true; }); } /** * Gets the location of the nearest chest. * * @param bot - The bot. * @param chestLocations - The list of all chest locations. * * @returns The nearest chest location, or null if the chest location * array is empty. */ function getClosestChest(bot, chestLocations) { let location = null; let distance = 0; for (const chestLocation of chestLocations) { const dist = bot.entity.position.distanceTo(chestLocation); if (location == null || dist < distance) { location = chestLocation; distance = dist; } } return location; }