UNPKG

@nxg-org/mineflayer-custom-pvp

Version:

Intermediate functionality for bow and sword pvp.

302 lines (301 loc) 12 kB
"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.BowPVP = void 0; const perf_hooks_1 = require("perf_hooks"); const util_1 = require("util"); const shotPlanner_1 = require("./shotPlanner"); const vec3_1 = require("vec3"); const sleep = (0, util_1.promisify)(setTimeout); const emptyVec = new vec3_1.Vec3(0, 0, 0); class BowPVP { constructor(bot) { this.bot = bot; this.enabled = false; this.weapon = "bow"; this.useOffhand = false; this.target = null; this.shotInfo = null; this.shotInit = perf_hooks_1.performance.now(); this.shotCharging = false; this.crossbowLoading = false; this.waitTime = 1200; this.getShotInfo = () => __awaiter(this, void 0, void 0, function* () { if (!this.target) return; this.shotInfo = this.shotToEntity(this.target, this.bot.tracker.getEntitySpeed(this.target) || new vec3_1.Vec3(0, 0, 0)); }); this.chargeHandling = () => __awaiter(this, void 0, void 0, function* () { switch (this.weapon) { case "bow": case "trident": this.waitTime = 1200; break; case "snowball": case "egg": case "splash_potion": this.waitTime = 150; break; case "ender_pearl": this.waitTime = 1000; break; case "crossbow": case "crossbow_firework": const weaponHand = this.bot.util.inv.getHandWithItem(this.useOffhand); if (!weaponHand) return console.log("cant find a thing"); const isEnchanted = weaponHand.enchants.find((enchant) => enchant.name === "quick_charge"); this.waitTime = 1250 - (isEnchanted ? isEnchanted.lvl : 0) * 250; break; default: this.waitTime = 1200; } if (!this.shotCharging) { if (["bow", "crossbow", "crossbow_firework", "trident"].includes(this.weapon)) { this.bot.activateItem(this.useOffhand); } this.shotCharging = true; this.shotInit = perf_hooks_1.performance.now(); } if (this.shotInfo && this.shotInfo.hit) { this.bot.look(this.shotInfo.yaw, this.shotInfo.pitch, true); if (this.shotReady) { if (["bow", "trident"].includes(this.weapon)) { this.bot.deactivateItem(); this.shotCharging = false; } if (["snowball", "ender_pearl", "egg", "splash_potion"].includes(this.weapon)) { this.bot.swingArm(undefined); this.bot.activateItem(this.useOffhand); this.bot.deactivateItem(); this.shotCharging = false; } if (["crossbow_firework", "crossbow"].includes(this.weapon)) { this.shootCrossbow(); } } } }); this.planner = new shotPlanner_1.ShotPlanner(bot); this.bot.on("entityGone", (e) => { if (e === this.target) this.stop(); }); // this.intercepter = new InterceptEquations(bot); } get shotReady() { return perf_hooks_1.performance.now() - this.shotInit >= this.waitTime; } /** * * @param entity * @param velocity * @returns */ shotToEntity(entity, velocity) { if (!velocity) velocity = this.bot.tracker.getEntitySpeed(entity) || new vec3_1.Vec3(0, 0, 0); return this.planner.shotToEntity(entity, velocity); } /** * @function hasWeapon * @param {string} weapon * @returns */ hasWeapon(weapon) { weapon !== null && weapon !== void 0 ? weapon : (weapon = this.weapon); return !!this.bot.util.inv.getAllItems().find((item) => weapon && item.name.includes(weapon)); } /** * @function hasAmmo * @param {string} [weapon=this.weapon] Optional string name of a weapon. Defaults to this.weapon. * @returns {boolean} If the weapon has ammo or not. * * ### Usage: * ```ts * // Let us fire! * let doWeHaveAmmo = bot.bowpvp.hasAmmo(); * if (doWeHaveAmmo) { * ‍ console.log("cool.") * } else { * ‍ ocnsole.log("not cool.") * } * ``` */ hasAmmo(weapon) { weapon !== null && weapon !== void 0 ? weapon : (weapon = this.weapon); switch (weapon) { case "bow": return !!this.bot.inventory.items().find((item) => item.name.includes("arrow")); case "crossbow": return !!this.bot.inventory.items().find((item) => item.name.includes("arrow")); case "crossbow_firework": return !!this.bot.util.inv.getAllItems().find(item => item.name.includes("firework")); default: return !!this.bot.inventory.items().find((item) => weapon && item.name.includes(weapon)); } } /** * @function checkForWeapon * Checks to see if a weapon exists * @param {string} weapon A string name of a weapon to check for * @returns {Promise<boolean>} A promise with a boolean * * ### Usage: * ```ts // Check for our weapon let doWeHaveABow = await bot.bowpvp.checkForWeapon("bow"); if (doWeHaveABow) { ‍ console.log("We have a bow.") } else { ‍ console.log("God damnit") } ``` */ checkForWeapon(weapon) { return __awaiter(this, void 0, void 0, function* () { weapon !== null && weapon !== void 0 ? weapon : (weapon = this.weapon); const usedHand = this.bot.util.inv.getHandWithItem(this.useOffhand); if (!usedHand || !usedHand.name.includes(weapon)) { const foundItem = this.bot.util.inv.getAllItems().find((item) => item.name === weapon); if (!foundItem) return false; yield this.bot.util.inv.customEquip(foundItem, this.bot.util.inv.getHand(this.useOffhand)); } return true; }); } fireworkSetup() { return __awaiter(this, void 0, void 0, function* () { const weapon = this.bot.util.inv.getAllItems().find((item) => item.name.includes("crossbow")); if (!this.hasAmmo("crossbow_firework") || !weapon) return false; this.useOffhand = false; // if (!this.bot.util.inv.getHandWithItem(true)?.name.includes("firework")) { const ammo = this.bot.util.inv.getAllItems().find(item => item.name.includes("firework")); yield this.bot.util.inv.customEquip(ammo, this.bot.util.inv.getHand(!this.useOffhand)); yield this.bot.util.inv.customEquip(weapon, this.bot.util.inv.getHand(this.useOffhand)); return true; // } }); } /** * @function stop * @public * * ### Usage: * ```ts * // Stop with the bow! * bot.bowpvp.stop() * // That's better * ``` */ stop() { this.bot.removeListener("physicsTick", this.getShotInfo); this.bot.removeListener("physicsTick", this.chargeHandling); if (this.target) this.bot.tracker.stopTrackingEntity(this.target); if (this.shotCharging) { // if (this.shotInfo) this.bot.look(this.shotInfo.yaw, this.shotInfo.pitch, true); if (this.shotInfo) this.bot.look(this.shotInfo.yaw, this.shotInfo.pitch, true); this.bot.deactivateItem(); } this.target = null; this.shotCharging = false; this.enabled = false; } /** * Attacks a specified target with a specified weapon. * @function attack * @public * @param {Entity} target An Entity object. * @param {string} [weapon=this.weapon] An optional string name of an item featured in the bots inventory. * @return {Promise<void>} An empty promise * * ### Usage: * ```ts * // Get our target * target = bot.nearestEntity((e) => (e.username ?? e.name) === "test_player"); * // Start the attack! * bot.newbowpvp.attack(target, "bow"); * ``` */ attack(target, weapon) { return __awaiter(this, void 0, void 0, function* () { if (this.target === target) return; this.enabled = true; this.target = target; if (weapon === "crossbow_firework") { const isSetup = yield this.fireworkSetup(); if (!isSetup) return this.stop(); } else { const hasWeapon = yield this.checkForWeapon(weapon); if (!hasWeapon) return this.stop(); } if (weapon) this.weapon = weapon; this.planner.weapon = this.weapon; this.bot.tracker.trackEntity(target); this.bot.on("physicsTick", this.getShotInfo); this.bot.on("physicsTick", this.chargeHandling); }); } /** * * @param yaw * @param grade * @param weapon * @returns */ shootAt(yaw, grade, weapon) { return __awaiter(this, void 0, void 0, function* () { if (this.shotCharging) return; const hasWeapon = yield this.checkForWeapon(weapon); if (!hasWeapon) this.stop(); if (!yaw) yaw = this.bot.player.entity.yaw; if (!grade) grade = this.bot.player.entity.pitch; if (weapon) this.weapon = weapon; yield this.bot.look(yaw, grade, true); this.shotCharging = true; this.shotInit = perf_hooks_1.performance.now(); this.bot.activateItem(this.useOffhand); while (!this.shotReady) yield sleep(50); this.bot.deactivateItem(); this.shotCharging = false; }); } shootCrossbow() { // console.log(this.crossbowLoading, this.shotReady, performance.now() - this.shotInit) if (this.crossbowLoading) { this.bot.activateItem(this.useOffhand); this.bot.deactivateItem(); this.crossbowLoading = false; this.shotCharging = false; return; } if (!this.crossbowLoading && this.shotReady) { this.bot.deactivateItem(); this.crossbowLoading = true; } } } exports.BowPVP = BowPVP;