@nxg-org/mineflayer-physics-util
Version:
Provides functionality for more accurate entity and projectile tracking.
467 lines (466 loc) • 20.8 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.ControlStateHandler = exports.PlayerState = exports.EntityDimensions = void 0;
exports.convInpToAxes = convInpToAxes;
const mineflayer_util_plugin_1 = require("@nxg-org/mineflayer-util-plugin");
const nbt = __importStar(require("prismarine-nbt"));
const vec3_1 = require("vec3");
const physicsUtils_1 = require("../../util/physicsUtils");
const playerControls_1 = require("../player/playerControls");
Object.defineProperty(exports, "ControlStateHandler", { enumerable: true, get: function () { return playerControls_1.ControlStateHandler; } });
const poses_1 = require("./poses");
const _1 = require(".");
function convInpToAxes(player) {
return {
forward: player.control.forward - player.control.back,
strafe: player.control.left - player.control.right,
};
}
const defaultMoves = playerControls_1.ControlStateHandler.DEFAULT();
//Utility class that wraps PlayerPoses.
class EntityDimensions {
constructor(width, height, fixed) {
this.width = width;
this.height = height;
this.fixed = fixed;
}
static scalable(f, f2) {
return new EntityDimensions(f, f2, false);
}
static fixed(f, f2) {
return new EntityDimensions(f, f2, true);
}
makeBoundingBox(vec3) {
return this.makeBoundingBoxCoords(vec3.x, vec3.y, vec3.z);
}
makeBoundingBoxCoords(d, d2, d3) {
const f = this.width / 2.0;
const f2 = this.height;
return new mineflayer_util_plugin_1.AABB(d - f, d2, d3 - f, d + f, d2 + f2, d3 + f);
}
scale(f) {
return this.scaleRaw(f, f);
}
scaleRaw(f, f2) {
if (this.fixed || (f == 1.0 && f2 == 1.0)) {
return this;
}
return EntityDimensions.scalable(this.width * f, this.height * f2);
}
toString() {
return "EntityDimensions w=" + this.width + ", h=" + this.height + ", fixed=" + this.fixed;
}
}
exports.EntityDimensions = EntityDimensions;
/**
* Looking at this code, it's too specified towards players.
*
* I will eventually split this code into PlayerState and bot.entityState, where bot.entityState contains fewer controls.
*/
class PlayerState {
get sprinting() {
return this._sprinting;
}
set sprinting(value) {
// console.trace('set sprinting', value)
this._sprinting = value;
}
get onGroundWithoutSupportingBlock() {
return this.onGround && !this.supportingBlockPos;
}
get height() {
return poses_1.playerPoseCtx[this.pose].height;
}
get eyeHeight() {
switch (this.pose) {
case poses_1.PlayerPoses.STANDING:
return 1.62;
case poses_1.PlayerPoses.SNEAKING:
return 1.27;
case poses_1.PlayerPoses.DYING:
case poses_1.PlayerPoses.SLEEPING:
case poses_1.PlayerPoses.SWIMMING:
case poses_1.PlayerPoses.FALL_FLYING:
case poses_1.PlayerPoses.SPIN_ATTACK:
return 0.4;
default:
return 1.62;
}
}
get halfWidth() {
return poses_1.playerPoseCtx[this.pose].width / 2;
}
constructor(ctx, bot, control) {
this.age = 0;
this.onGround = false;
this.onClimbable = false;
this.isInWater = false;
this.isUnderWater = false;
this.isInLava = false;
this.isUnderLava = false;
this.isInWeb = false;
this.elytraFlying = false;
this.elytraEquipped = false;
this.fireworkRocketDuration = 0;
this.isCollidedHorizontally = false;
this.isCollidedHorizontallyMinor = false;
this.isCollidedVertically = false;
this.supportingBlockPos = null;
this.stuckSpeedMultiplier = new vec3_1.Vec3(0, 0, 0);
this.jumpTicks = 0;
this.jumpQueued = false;
this.sprintTriggerTime = 0;
this.flyJumpTriggerTime = 0;
this.sneakCollision = false;
this.attributes = {};
this.yaw = 0;
this.pitch = 0;
this.control = defaultMoves;
this.prevControl = defaultMoves;
this.heading = { forward: 0, strafe: 0 };
this.prevHeading = { forward: 0, strafe: 0 };
this.isUsingItem = false;
this.isUsingMainHand = false;
this.isUsingOffHand = false;
this.jumpBoost = 0;
this.speed = 0;
this.slowness = 0;
this.dolphinsGrace = 0;
this.slowFalling = 0;
this.levitation = 0;
this.blindness = 0;
this.depthStrider = 0;
this.swiftSneak = 0;
this.soulSpeed = 0;
this.effects = [];
this.pose = poses_1.PlayerPoses.STANDING;
this.gameMode = "survival";
this.food = 0;
// the below fields are abilities mineflayer is supposed to store.
/**
* TODO: proper impl.
*/
this.mayFly = false;
/**
* TODO: proper impl.
*/
this.flying = false;
/**
* TODO: proper impl.
*/
this.swimming = false;
/**
* TODO: proper impl.
*/
this._sprinting = false;
/**
* TODO: proper impl.
*/
this.crouching = false;
/**
* TODO: proper impl.
*/
this.fallFlying = false;
/**
* TODO: proper impl.
*/
this.flySpeed = 0;
this.supportFeature = (0, physicsUtils_1.makeSupportFeature)(ctx.data);
this.ctx = ctx;
this.bot = bot;
this.pos = bot.entity.position.clone();
this.vel = bot.entity.velocity.clone();
this.statusEffectNames = (0, physicsUtils_1.getStatusEffectNamesForVersion)(this.supportFeature);
this.update(bot, playerControls_1.ControlStateHandler.COPY_BOT(bot));
}
update(bot, control) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
// const bot.entity = bot instanceof bot.entity ? bot : bot.entity;
// Input / Outputs
this.pos.set(bot.entity.position.x, bot.entity.position.y, bot.entity.position.z);
this.vel.set(bot.entity.velocity.x, bot.entity.velocity.y, bot.entity.velocity.z);
this.supportingBlockPos = (_a = bot.entity.supportingBlockPos) !== null && _a !== void 0 ? _a : null;
this.onGround = bot.entity.onGround;
this.onClimbable = bot.entity.onClimbable;
this.isInWater = bot.entity.isInWater;
this.isUnderWater = bot.entity.isUnderWater;
this.isInLava = bot.entity.isInLava;
this.isUnderLava = bot.entity.isUnderLava;
this.isInWeb = bot.entity.isInWeb;
this.elytraFlying = bot.entity.elytraFlying;
this.elytraEquipped = ((_b = bot.inventory.slots[bot.getEquipmentDestSlot('torso')]) === null || _b === void 0 ? void 0 : _b.name) === 'elytra';
this.fireworkRocketDuration = bot.fireworkRocketDuration;
this.isCollidedHorizontally = bot.entity.isCollidedHorizontally;
this.isCollidedHorizontallyMinor = bot.entity.isCollidedHorizontallyMinor;
this.isCollidedVertically = bot.entity.isCollidedVertically;
// dunno what to do about these, ngl.
this.jumpTicks = (_c = bot.jumpTicks) !== null && _c !== void 0 ? _c : 0;
this.jumpQueued = (_d = bot.jumpQueued) !== null && _d !== void 0 ? _d : false;
this.flyJumpTriggerTime = (_e = bot.flyJumpTriggerTime) !== null && _e !== void 0 ? _e : 0;
this.sprintTriggerTime = (_f = bot.sprintTriggerTime) !== null && _f !== void 0 ? _f : 0;
// Input only (not modified)
this.attributes = bot.entity.attributes;
this.yaw = bot.entity.yaw;
this.pitch = bot.entity.pitch;
this.control = control !== null && control !== void 0 ? control : playerControls_1.ControlStateHandler.COPY_BOT(bot); // prevControl only updated internally.
this.isUsingItem = bot.usingHeldItem; /* || isEntityUsingItem(bot.entity, this.ctx.supportFeature); */
this.isUsingMainHand = !(0, physicsUtils_1.whichHandIsEntityUsingBoolean)(bot.entity, this.ctx.supportFeature) && this.isUsingItem;
this.isUsingOffHand = (0, physicsUtils_1.whichHandIsEntityUsingBoolean)(bot.entity, this.ctx.supportFeature) && this.isUsingItem;
// effects
this.effects = bot.entity.effects;
this.jumpBoost = this.ctx.getEffectLevel(physicsUtils_1.CheapEffects.JUMP_BOOST, this.effects);
this.speed = this.ctx.getEffectLevel(physicsUtils_1.CheapEffects.SPEED, this.effects);
this.slowness = this.ctx.getEffectLevel(physicsUtils_1.CheapEffects.SLOWNESS, this.effects);
this.dolphinsGrace = this.ctx.getEffectLevel(physicsUtils_1.CheapEffects.DOLPHINS_GRACE, this.effects);
this.slowFalling = this.ctx.getEffectLevel(physicsUtils_1.CheapEffects.SLOW_FALLING, this.effects);
this.levitation = this.ctx.getEffectLevel(physicsUtils_1.CheapEffects.LEVITATION, this.effects);
// armour enchantments
//const boots = bot.inventory.slots[8];
const boots = bot.entity.equipment[5];
if (boots && boots.nbt) {
const simplifiedNbt = nbt.simplify(boots.nbt);
const enchantments = (_h = (_g = simplifiedNbt.Enchantments) !== null && _g !== void 0 ? _g : simplifiedNbt.ench) !== null && _h !== void 0 ? _h : [];
this.depthStrider = this.ctx.getEnchantmentLevel(physicsUtils_1.CheapEnchantments.DEPTH_STRIDER, enchantments);
this.soulSpeed = this.ctx.getEnchantmentLevel(physicsUtils_1.CheapEnchantments.SOUL_SPEED, enchantments);
}
else {
this.depthStrider = 0;
this.soulSpeed = 0;
}
const leggings = bot.entity.equipment[3];
if (leggings && leggings.nbt) {
const simplifiedNbt = nbt.simplify(leggings.nbt);
const enchantments = (_k = (_j = simplifiedNbt.Enchantments) !== null && _j !== void 0 ? _j : simplifiedNbt.ench) !== null && _k !== void 0 ? _k : [];
this.swiftSneak = this.ctx.getEnchantmentLevel(physicsUtils_1.CheapEnchantments.SWIFT_SNEAK, enchantments);
}
else {
this.swiftSneak = 0;
}
this.pose = (0, _1.getPose)(bot.entity);
this.gameMode = bot.game.gameMode;
this.food = bot.food;
// TODO:
this.swimming = (_l = bot.entity.swimming) !== null && _l !== void 0 ? _l : false;
this.sprinting = (_m = bot.entity.sprinting) !== null && _m !== void 0 ? _m : false;
this.crouching = (_o = bot.entity.crouching) !== null && _o !== void 0 ? _o : false;
this.fallFlying = (_p = bot.entity.fallFlying) !== null && _p !== void 0 ? _p : false;
switch (bot.game.gameMode) {
case "creative":
this.flySpeed = 0.05;
this.mayFly = true;
break;
case "spectator":
this.flySpeed = 0.1;
this.mayFly = true;
break;
case "survival":
case "adventure":
this.flySpeed = 0;
this.mayFly = bot.entity.canFly;
break;
default:
throw new Error("Unknown game mode: " + bot.game.gameMode);
}
this.flying = !!bot.entity.flying && this.mayFly;
return this;
}
apply(bot) {
var _a, _b, _c, _d, _e;
// const bot.entity = bot instanceof bot.entity ? bot : bot.entity;
bot.entity.position.set(this.pos.x, this.pos.y, this.pos.z);
bot.entity.velocity.set(this.vel.x, this.vel.y, this.vel.z);
bot.entity.onGround = this.onGround;
bot.entity.onClimbable = this.onClimbable;
bot.entity.isInWater = this.isInWater;
bot.entity.isUnderWater = this.isUnderWater;
bot.entity.isInLava = this.isInLava;
bot.entity.isUnderLava = this.isUnderLava;
bot.entity.isInWeb = this.isInWeb;
bot.entity.elytraFlying = this.elytraFlying;
bot.entity.elytraEquipped = this.elytraEquipped;
bot.fireworkRocketDuration = this.fireworkRocketDuration;
bot.entity.isCollidedHorizontally = this.isCollidedHorizontally;
bot.entity.isCollidedHorizontallyMinor = this.isCollidedHorizontallyMinor;
bot.entity.isCollidedVertically = this.isCollidedVertically;
bot.entity.supportingBlockPos = this.supportingBlockPos;
// dunno what to do about these, ngl.
bot.jumpTicks = this.jumpTicks;
bot.jumpQueued = this.jumpQueued;
bot.flyJumpTriggerTime = this.flyJumpTriggerTime;
bot.sprintTriggerTime = this.sprintTriggerTime;
bot.entity.yaw = this.yaw;
bot.entity.pitch = this.pitch;
Object.assign(bot.entity, this.pose);
bot.game.gameMode = this.gameMode; // this should never actually be in charge.
bot.food = this.food; // this should also never actually be in charge.
bot.entity.flying = (_a = this.flying) !== null && _a !== void 0 ? _a : false;
bot.entity.swimming = (_b = this.swimming) !== null && _b !== void 0 ? _b : false;
bot.entity.sprinting = (_c = this.sprinting) !== null && _c !== void 0 ? _c : false;
bot.entity.crouching = (_d = this.crouching) !== null && _d !== void 0 ? _d : false;
bot.entity.fallFlying = (_e = this.fallFlying) !== null && _e !== void 0 ? _e : false;
bot.entity.attributes = this.attributes;
this.control.applyControls(bot);
bot.entity.prevControl = this.prevControl;
}
clone() {
var _a, _b, _c, _d;
const tmp = new PlayerState(this.ctx, this.bot, this.control);
tmp.pos.set(this.pos.x, this.pos.y, this.pos.z);
tmp.vel.set(this.vel.x, this.vel.y, this.vel.z);
tmp.onGround = this.onGround;
tmp.onClimbable = this.onClimbable;
tmp.isInWater = this.isInWater;
tmp.isUnderWater = this.isUnderWater;
tmp.isInLava = this.isInLava;
tmp.isUnderLava = this.isUnderLava;
tmp.isInWeb = this.isInWeb;
tmp.elytraFlying = this.elytraFlying;
tmp.elytraEquipped = this.elytraEquipped;
tmp.fireworkRocketDuration = this.fireworkRocketDuration;
tmp.isCollidedHorizontally = this.isCollidedHorizontally;
tmp.isCollidedHorizontallyMinor = this.isCollidedHorizontallyMinor;
tmp.isCollidedVertically = this.isCollidedVertically;
tmp.supportingBlockPos = this.supportingBlockPos;
tmp.sneakCollision = false; //TODO
//not sure what to do here, ngl.
tmp.jumpTicks = (_a = this.jumpTicks) !== null && _a !== void 0 ? _a : 0;
tmp.jumpQueued = (_b = this.jumpQueued) !== null && _b !== void 0 ? _b : false;
tmp.flyJumpTriggerTime = (_c = this.flyJumpTriggerTime) !== null && _c !== void 0 ? _c : 0;
tmp.sprintTriggerTime = (_d = this.sprintTriggerTime) !== null && _d !== void 0 ? _d : 0;
// Input only (not modified)
tmp.attributes = this.attributes;
tmp.yaw = this.yaw;
tmp.pitch = this.pitch;
tmp.control = this.control.clone();
tmp.prevControl = this.prevControl.clone();
tmp.isUsingItem = this.isUsingItem;
tmp.isUsingMainHand = this.isUsingMainHand;
tmp.isUsingOffHand = this.isUsingOffHand;
// effects
tmp.effects = this.effects;
tmp.statusEffectNames = this.statusEffectNames;
tmp.jumpBoost = this.jumpBoost;
tmp.speed = this.speed;
tmp.slowness = this.slowness;
tmp.dolphinsGrace = this.dolphinsGrace;
tmp.slowFalling = this.slowFalling;
tmp.levitation = this.levitation;
tmp.blindness = this.blindness;
tmp.soulSpeed = this.soulSpeed;
tmp.swiftSneak = this.swiftSneak;
tmp.depthStrider = this.depthStrider;
tmp.pose = this.pose;
tmp.gameMode = this.gameMode;
tmp.flying = this.flying;
tmp.swimming = this.swimming;
tmp.sprinting = this.sprinting;
tmp.crouching = this.crouching;
tmp.fallFlying = this.fallFlying;
tmp.food = this.food;
return tmp;
}
merge(other) {
var _a, _b, _c, _d;
this.pos.set(other.pos.x, other.pos.y, other.pos.z);
this.vel.set(other.vel.x, other.vel.y, other.vel.z);
this.onGround = other.onGround;
this.onClimbable = other.onClimbable;
this.isInWater = other.isInWater;
this.isUnderWater = other.isUnderWater;
this.isInLava = other.isInLava;
this.isUnderLava = other.isUnderLava;
this.isInWeb = other.isInWeb;
this.elytraFlying = other.elytraFlying;
this.elytraEquipped = other.elytraEquipped;
this.fireworkRocketDuration = other.fireworkRocketDuration;
this.isCollidedHorizontally = other.isCollidedHorizontally;
this.isCollidedHorizontallyMinor = other.isCollidedHorizontallyMinor;
this.isCollidedVertically = other.isCollidedVertically;
this.supportingBlockPos = other.supportingBlockPos;
this.sneakCollision = false; //TODO
//not sure what to do here, ngl.
this.jumpTicks = (_a = other.jumpTicks) !== null && _a !== void 0 ? _a : 0;
this.jumpQueued = (_b = other.jumpQueued) !== null && _b !== void 0 ? _b : false;
this.flyJumpTriggerTime = (_c = other.flyJumpTriggerTime) !== null && _c !== void 0 ? _c : 0;
this.sprintTriggerTime = (_d = other.sprintTriggerTime) !== null && _d !== void 0 ? _d : 0;
// Input only (not modified)
this.attributes = other.attributes;
this.yaw = other.yaw;
this.pitch = other.pitch;
this.control = other.control.clone();
this.prevControl = other.prevControl.clone();
this.isUsingItem = other.isUsingItem;
this.isUsingMainHand = other.isUsingMainHand;
this.isUsingOffHand = other.isUsingOffHand;
// effects
this.effects = other.effects;
this.statusEffectNames = other.statusEffectNames;
this.jumpBoost = other.jumpBoost;
this.speed = other.speed;
this.slowness = other.slowness;
this.dolphinsGrace = other.dolphinsGrace;
this.slowFalling = other.slowFalling;
this.swiftSneak = other.swiftSneak;
this.soulSpeed = other.soulSpeed;
this.levitation = other.levitation;
this.depthStrider = other.depthStrider;
this.pose = other.pose;
this.gameMode = other.gameMode;
this.flying = other.flying;
this.swimming = other.swimming;
this.sprinting = other.sprinting;
this.crouching = other.crouching;
this.food = other.food;
return this;
}
getBB() {
const w = this.halfWidth;
return new mineflayer_util_plugin_1.AABB(this.pos.x - w, this.pos.y, this.pos.z - w, this.pos.x + w, this.pos.y + this.height, this.pos.z + w);
}
lookAt(vec3) {
const dx = vec3.x - this.pos.x;
const dy = vec3.y - this.pos.y;
const dz = vec3.z - this.pos.z;
this.yaw = Math.atan2(dz, dx) * 180 / Math.PI - 90;
this.pitch = -Math.atan2(dy, Math.sqrt(dx * dx + dz * dz)) * 180 / Math.PI;
console.log(this.yaw, this.pitch);
}
look(yaw, pitch) {
this.yaw = yaw;
this.pitch = pitch;
}
}
exports.PlayerState = PlayerState;