@nxg-org/mineflayer-tracker
Version:
Provides functionality for more accurate entity and projectile tracking.
174 lines (173 loc) • 9.41 kB
JavaScript
"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.ProjectileTracker = void 0;
const mineflayer_trajectories_1 = require("@nxg-org/mineflayer-trajectories");
const normalizeName = (name) => name === null || name === void 0 ? void 0 : name.toLowerCase();
const knownProjectiles = new Set(Object.keys(mineflayer_trajectories_1.projectileGravity).map((name) => name.toLowerCase()));
const knownWeapons = new Set(Object.keys(mineflayer_trajectories_1.trajectoryInfo).map((name) => name.toLowerCase()));
const damagingProjectiles = new Set(["arrow", "firework_rocket", "trident", "fireball"]);
const hasKnownProjectileName = (name) => { var _a; return knownProjectiles.has((_a = normalizeName(name)) !== null && _a !== void 0 ? _a : ""); };
const hasKnownWeaponName = (name) => { var _a; return knownWeapons.has((_a = normalizeName(name)) !== null && _a !== void 0 ? _a : ""); };
const isDamagingProjectileName = (name) => { var _a; return damagingProjectiles.has((_a = normalizeName(name)) !== null && _a !== void 0 ? _a : ""); };
const isAimingMobName = (name) => {
const normalizedName = normalizeName(name);
return normalizedName === "skeleton" || normalizedName === "piglin";
};
const isBowName = (name) => { var _a, _b; return (_b = (_a = normalizeName(name)) === null || _a === void 0 ? void 0 : _a.includes("bow")) !== null && _b !== void 0 ? _b : false; };
class ProjectileTracker {
constructor(bot) {
this.bot = bot;
this.projectilesChecked = false;
this.entitiesChecked = false;
this.$isAimedAt = null;
this.$projectileAtMe = null;
this.detectIncomingProjectiles = false;
this.detectAimingEntities = false;
this.perTickHandler = () => __awaiter(this, void 0, void 0, function* () {
this.projectilesChecked = false;
this.entitiesChecked = false;
});
this.intercepter = new mineflayer_trajectories_1.InterceptFunctions(bot);
this.bot.on("physicsTick", this.perTickHandler);
}
get isAimedAt() {
if (this.entitiesChecked)
return this.$isAimedAt;
else {
this.$isAimedAt = this.getHighestPriorityEntity();
this.entitiesChecked = true;
return this.$isAimedAt;
}
}
get projectileAtMe() {
if (this.projectilesChecked)
return this.$projectileAtMe;
else {
this.$projectileAtMe = this.getHighestPriorityProjectile();
this.projectilesChecked = true;
return this.$projectileAtMe;
}
}
getIncomingArrow() {
var _a;
const arrowInfos = this.getIncomingArrows();
return ((_a = arrowInfos.sort((a, b) => a.entity.position.distanceTo(this.bot.entity.position) - b.entity.position.distanceTo(this.bot.entity.position))[0]) !== null && _a !== void 0 ? _a : null);
}
getIncomingArrows() {
const hittingArrows = [];
const aabbComponents = { position: this.bot.entity.position, height: this.bot.entity.height + 0.18, width: 0.6 };
for (const entity of Object.values(this.bot.entities).filter((e) => { var _a; return (_a = normalizeName(e.name)) === null || _a === void 0 ? void 0 : _a.includes("arrow"); })) {
// assuming stopped.
const init = mineflayer_trajectories_1.ShotFactory.fromEntity(entity, this.intercepter);
const info = init.hitsEntity(aabbComponents);
if (!!info)
hittingArrows.push({ entity, shotInfo: info.shotInfo });
}
return hittingArrows;
}
getIncomingProjectiles() {
const hittingArrows = [];
const aabbComponents = { position: this.bot.entity.position, height: this.bot.entity.height + 0.18, width: 0.6 };
for (const entity of Object.values(this.bot.entities).filter((e) => hasKnownProjectileName(e.name))) {
// assuming stopped.
const init = mineflayer_trajectories_1.ShotFactory.fromEntity(entity, this.intercepter);
const info = init.hitsEntity(aabbComponents);
if (!!info && info.shotInfo.nearestDistance === 0)
hittingArrows.push({ entity, shotInfo: info.shotInfo });
}
return hittingArrows;
}
getHighestPriorityProjectile(doesDamage = true) {
var _a, _b;
const projs = this.getIncomingProjectiles();
if (doesDamage) {
return ((_a = projs
.filter((p) => isDamagingProjectileName(p.entity.name))
.sort((a, b) => a.entity.position.distanceTo(this.bot.entity.position) - b.entity.position.distanceTo(this.bot.entity.position))[0]) !== null && _a !== void 0 ? _a : null);
}
else {
return ((_b = projs.sort((a, b) => a.entity.position.distanceTo(this.bot.entity.position) - b.entity.position.distanceTo(this.bot.entity.position))[0]) !== null && _b !== void 0 ? _b : null);
}
}
allProjectileInfo() {
const hittingArrows = [];
const entities = Object.values(this.bot.entities);
for (const entity of Object.values(this.bot.entities).filter((e) => hasKnownProjectileName(e.name))) {
// assuming stopped.
const init = mineflayer_trajectories_1.ShotFactory.fromEntity(entity, this.intercepter);
const info = init.calcToIntercept(true, entities);
hittingArrows.push({ entity, info });
}
return hittingArrows;
}
getMobsAimingAtBot() {
const hittingArrows = [];
const aabbComponents = { position: this.bot.entity.position, height: this.bot.entity.height + 0.18, width: 0.6 };
for (const entity of Object.values(this.bot.entities).filter((e) => { var _a; return isAimingMobName(e.name) && isBowName((_a = e.heldItem) === null || _a === void 0 ? void 0 : _a.name); })) {
const init = mineflayer_trajectories_1.ShotFactory.fromMob(entity, this.intercepter);
const info = init.hitsEntity(aabbComponents);
if (!!info)
hittingArrows.push({ entity, shotInfo: info.shotInfo });
}
return hittingArrows;
}
//TODO: Make aim dynamic by reading heldItem metadata.
getPlayersAimingAtBot() {
var _a;
const hittingArrows = [];
const aabbComponents = { position: this.bot.entity.position, height: this.bot.entity.height + 0.18, width: 0.6 };
for (const entity of Object.values(this.bot.entities).filter((e) => e.type === "player" && e !== this.bot.entity)) {
if (hasKnownWeaponName((_a = entity.heldItem) === null || _a === void 0 ? void 0 : _a.name)) {
const init = mineflayer_trajectories_1.ShotFactory.fromPlayer(entity, this.intercepter);
const info = init.hitsEntity(aabbComponents);
if (!!info)
hittingArrows.push({ entity, shotInfo: info.shotInfo });
}
}
return hittingArrows;
}
getAimingEntities() {
return this.getMobsAimingAtBot().concat(this.getPlayersAimingAtBot());
}
getHighestPriorityEntity() {
var _a;
return (_a = this.getAimingEntities().sort((a, b) => a.shotInfo.totalTicks - b.shotInfo.totalTicks)[0]) !== null && _a !== void 0 ? _a : null;
}
getShotDestination(entity) {
var _a, _b, _c;
if (hasKnownWeaponName((_b = (_a = entity.heldItem) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : (_c = entity.equipment[1]) === null || _c === void 0 ? void 0 : _c.name)) {
let shot;
switch (entity.type) {
case "player":
shot = mineflayer_trajectories_1.ShotFactory.fromPlayer(entity, this.intercepter);
break;
case "mob":
shot = mineflayer_trajectories_1.ShotFactory.fromMob(entity, this.intercepter);
break;
default:
throw `Invalid entity type: ${entity.type}`;
}
const info = shot.hitsEntities(true, ...Object.values(this.bot.entities).filter((e) => (e.type === "player" || e.type === "mob") && entity !== e));
return info;
}
return null;
}
getProjectileDestination(entity) {
if (hasKnownProjectileName(entity.name)) {
let shot = mineflayer_trajectories_1.ShotFactory.fromEntity(entity, this.intercepter);
const info = shot.hitsEntities(true, ...Object.values(this.bot.entities).filter((e) => e.type === "player" || e.type === "mob"));
return info;
}
return null;
}
}
exports.ProjectileTracker = ProjectileTracker;