@nxg-org/mineflayer-physics-util
Version:
Provides functionality for more accurate entity and projectile tracking.
287 lines (286 loc) • 14.4 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CheapEnchantments = exports.CheapEffects = exports.DefaultPlayer = void 0;
exports.makeSupportFeature = makeSupportFeature;
exports.applyMdToNewEntity = applyMdToNewEntity;
exports.isEntityUsingItem = isEntityUsingItem;
exports.whichHandIsEntityUsing = whichHandIsEntityUsing;
exports.whichHandIsEntityUsingBoolean = whichHandIsEntityUsingBoolean;
exports.isUsableElytraItem = isUsableElytraItem;
exports.getStatusEffectNamesForVersion = getStatusEffectNamesForVersion;
exports.getEnchantmentNamesForVersion = getEnchantmentNamesForVersion;
exports.getBetweenRectangle = getBetweenRectangle;
exports.getLookingVector = getLookingVector;
exports.convertPlayerState = convertPlayerState;
exports.applyToPlayerState = applyToPlayerState;
const mineflayer_util_plugin_1 = require("@nxg-org/mineflayer-util-plugin");
const features_json_1 = __importDefault(require("../physics/info/features.json"));
const states_1 = require("../physics/states");
const vec3_1 = require("vec3");
function makeSupportFeature(mcData) {
return (feature) => features_json_1.default.some(({ name, versions }) => name === feature && versions.includes(mcData.version.majorVersion));
}
exports.DefaultPlayer = {
displayName: "Player",
height: 1.8,
width: 0.6,
type: "player",
name: "player",
id: -1
};
function applyMdToNewEntity(ctx, entityType = exports.DefaultPlayer, options = {}) {
var _a, _b;
//entityType.category
// entityType.internalId
const tmp = new ctx.entityConstructor(-1);
tmp.displayName = entityType.displayName;
tmp.height = (_a = entityType.height) !== null && _a !== void 0 ? _a : 0;
tmp.width = (_b = entityType.width) !== null && _b !== void 0 ? _b : 0;
tmp.type = entityType.type;
tmp.name = entityType.name;
Object.assign(tmp, options);
return tmp;
}
var CheapEffects;
(function (CheapEffects) {
CheapEffects[CheapEffects["JUMP_BOOST"] = 0] = "JUMP_BOOST";
CheapEffects[CheapEffects["SPEED"] = 1] = "SPEED";
CheapEffects[CheapEffects["SLOWNESS"] = 2] = "SLOWNESS";
CheapEffects[CheapEffects["DOLPHINS_GRACE"] = 3] = "DOLPHINS_GRACE";
CheapEffects[CheapEffects["SLOW_FALLING"] = 4] = "SLOW_FALLING";
CheapEffects[CheapEffects["LEVITATION"] = 5] = "LEVITATION";
CheapEffects[CheapEffects["BLINDNESS"] = 6] = "BLINDNESS";
})(CheapEffects || (exports.CheapEffects = CheapEffects = {}));
var CheapEnchantments;
(function (CheapEnchantments) {
CheapEnchantments[CheapEnchantments["DEPTH_STRIDER"] = 0] = "DEPTH_STRIDER";
CheapEnchantments[CheapEnchantments["SWIFT_SNEAK"] = 1] = "SWIFT_SNEAK";
CheapEnchantments[CheapEnchantments["SOUL_SPEED"] = 2] = "SOUL_SPEED";
})(CheapEnchantments || (exports.CheapEnchantments = CheapEnchantments = {}));
function getMetadataIndex(supportFeature) {
return supportFeature("itemUsageMetadata6") ? 6 : 8;
}
function isEntityUsingItem(entity, supportFeature) {
return entity.metadata[getMetadataIndex(supportFeature)] > 1;
}
function whichHandIsEntityUsing(entity, supportFeature) {
return entity.metadata[getMetadataIndex(supportFeature)] > 2 ? "off-hand" : "hand";
}
function whichHandIsEntityUsingBoolean(entity, supportFeature) {
return entity.metadata[getMetadataIndex(supportFeature)] > 2;
}
function isUsableElytraItem(item) {
if (!item || item.name !== "elytra")
return false;
if (typeof item.durabilityUsed === "number" && typeof item.maxDurability === "number") {
return item.durabilityUsed < item.maxDurability - 1;
}
return true;
}
function getStatusEffectNamesForVersion(supportFeature) {
if (supportFeature("effectNamesAreRegistryNames")) {
// seems to not matter right now.
return {
jumpBoostEffectName: "JumpBoost",
speedEffectName: "Speed",
slownessEffectName: "Slowness",
dolphinsGraceEffectName: "DolphinsGrace",
slowFallingEffectName: "SlowFalling",
levitationEffectName: "Levitation",
blindnessEffectName: "Blindnesss"
};
}
else {
return {
jumpBoostEffectName: "JumpBoost",
speedEffectName: "Speed",
slownessEffectName: "Slowness",
dolphinsGraceEffectName: "DolphinsGrace",
slowFallingEffectName: "SlowFalling",
levitationEffectName: "Levitation",
blindnessEffectName: "Blindnesss"
};
}
}
// lol. In case of expansion, yk.
function getEnchantmentNamesForVersion(supportFeature) {
return {
depthStriderEnchantmentName: "depth_strider",
swiftSneakEnchantmentName: "swift_sneak",
soulSpeedEnchantmentName: "soul_speed"
};
}
function getBetweenRectangle(src, dest) {
const outerAABB = new mineflayer_util_plugin_1.AABB(Math.min(src.minX, dest.minX), Math.min(src.minY, dest.minY), Math.min(src.minZ, dest.minZ), Math.max(src.maxX, dest.maxX), Math.max(src.maxY, dest.maxY), Math.max(src.maxZ, dest.maxZ));
//Math.max() only good for length, otherwise leave because we want good shit.
const innerAABBWidth = outerAABB.maxX - outerAABB.minX - (src.maxX - src.minX) - (dest.maxX - dest.minX);
const innerAABBLength = outerAABB.maxZ - outerAABB.minZ - (src.maxZ - src.minZ) - (dest.maxZ - dest.minZ);
const innerAABBHeight = outerAABB.maxY - outerAABB.minY - (src.maxY - src.minY) - (dest.maxY - dest.minY);
//hm... could make a new AABB representing inner here.
const outerCenter = outerAABB.getCenter();
const wFlip = Math.sign(innerAABBWidth);
const hFlip = Math.sign(innerAABBHeight);
const lFlip = Math.sign(innerAABBLength);
const innerAABB = new mineflayer_util_plugin_1.AABB(outerCenter.x - (wFlip * innerAABBWidth) / 2, outerCenter.y - (hFlip * innerAABBHeight) / 2, outerCenter.z - (lFlip * innerAABBLength) / 2, outerCenter.x + (wFlip * innerAABBWidth) / 2, outerCenter.y + (hFlip * innerAABBHeight) / 2, outerCenter.z + (lFlip * innerAABBLength) / 2);
return innerAABB;
}
function getLookingVector(entity) {
// given a yaw pitch, we need the looking vector
// yaw is right handed rotation about y (up) starting from -z (north)
// pitch is -90 looking down, 90 looking up, 0 looking at horizon
// lets get its coordinate system.
// let x' = -z (north)
// let y' = -x (west)
// let z' = y (up)
// the non normalized looking vector in x', y', z' space is
// x' is cos(yaw)
// y' is sin(yaw)
// z' is tan(pitch)
// substituting back in x, y, z, we get the looking vector in the normal x, y, z space
// -z = cos(yaw) => z = -cos(yaw)
// -x = sin(yaw) => x = -sin(yaw)
// y = tan(pitch)
// normalizing the vectors, we divide each by |sqrt(x*x + y*y + z*z)|
// x*x + z*z = sin^2 + cos^2 = 1
// so |sqrt(xx+yy+zz)| = |sqrt(1+tan^2(pitch))|
// = |sqrt(1+sin^2(pitch)/cos^2(pitch))|
// = |sqrt((cos^2+sin^2)/cos^2(pitch))|
// = |sqrt(1/cos^2(pitch))|
// = |+/- 1/cos(pitch)|
// = 1/cos(pitch) since pitch in [-90, 90]
// the looking vector is therefore
// x = -sin(yaw) * cos(pitch)
// y = tan(pitch) * cos(pitch) = sin(pitch)
// z = -cos(yaw) * cos(pitch)
const yaw = entity.yaw;
const pitch = entity.pitch;
const sinYaw = Math.sin(yaw);
const cosYaw = Math.cos(yaw);
const sinPitch = Math.sin(pitch);
const cosPitch = Math.cos(pitch);
const lookX = -sinYaw * cosPitch;
const lookY = sinPitch;
const lookZ = -cosYaw * cosPitch;
const lookDir = new vec3_1.Vec3(lookX, lookY, lookZ);
return {
yaw,
pitch,
sinYaw,
cosYaw,
sinPitch,
cosPitch,
lookX,
lookY,
lookZ,
lookDir
};
}
/**
* Converts an old PlayerState object into the new PlayerState class format.
* * @param bot The current Mineflayer bot instance.
* @param oldState The old PlayerState object to migrate.
* @param ctx The IPhysics context required by the new PlayerState constructor.
* @returns A newly formatted PlayerState instance.
*/
function convertPlayerState(bot, oldState, ctx) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y;
// 1. Initialize the new state.
// This automatically runs update() and pulls the bot's current real state.
const newState = new states_1.PlayerState(ctx, bot);
// 2. Overwrite spatial and velocity data with the old simulated state
if (oldState.pos)
newState.pos.set(oldState.pos.x, oldState.pos.y, oldState.pos.z);
if (oldState.vel)
newState.vel.set(oldState.vel.x, oldState.vel.y, oldState.vel.z);
// 3. Map collision and environment flags
newState.onGround = (_a = oldState.onGround) !== null && _a !== void 0 ? _a : newState.onGround;
newState.isInWater = (_b = oldState.isInWater) !== null && _b !== void 0 ? _b : newState.isInWater;
newState.isInLava = (_c = oldState.isInLava) !== null && _c !== void 0 ? _c : newState.isInLava;
newState.isInWeb = (_d = oldState.isInWeb) !== null && _d !== void 0 ? _d : newState.isInWeb;
newState.isCollidedHorizontally = (_e = oldState.isCollidedHorizontally) !== null && _e !== void 0 ? _e : newState.isCollidedHorizontally;
newState.isCollidedVertically = (_f = oldState.isCollidedVertically) !== null && _f !== void 0 ? _f : newState.isCollidedVertically;
// 4. Map movement and action states
newState.fallFlying = (_h = (_g = oldState.fallFlying) !== null && _g !== void 0 ? _g : oldState.elytraFlying) !== null && _h !== void 0 ? _h : newState.fallFlying;
newState.validElytraEquipped = (_k = (_j = oldState.validElytraEquipped) !== null && _j !== void 0 ? _j : oldState.elytraEquipped) !== null && _k !== void 0 ? _k : newState.validElytraEquipped;
newState.jumpTicks = (_l = oldState.jumpTicks) !== null && _l !== void 0 ? _l : newState.jumpTicks;
newState.jumpQueued = (_m = oldState.jumpQueued) !== null && _m !== void 0 ? _m : newState.jumpQueued;
newState.fireworkRocketDuration = (_o = oldState.fireworkRocketDuration) !== null && _o !== void 0 ? _o : newState.fireworkRocketDuration;
newState.yaw = (_p = oldState.yaw) !== null && _p !== void 0 ? _p : newState.yaw;
newState.pitch = (_q = oldState.pitch) !== null && _q !== void 0 ? _q : newState.pitch;
// 5. Map Control State
// The old state uses a standard object for controls; the new uses ControlStateHandler.
if (oldState.control) {
// Create a fresh clone of the bot's current controls, then overwrite with simulated ones
newState.control = states_1.ControlStateHandler.COPY_BOT(bot);
Object.assign(newState.control, oldState.control);
}
// 6. Map Attributes, Effects, and Enchantments
newState.attributes = (_r = oldState.attributes) !== null && _r !== void 0 ? _r : newState.attributes;
newState.jumpBoost = (_s = oldState.jumpBoost) !== null && _s !== void 0 ? _s : newState.jumpBoost;
newState.speed = (_t = oldState.speed) !== null && _t !== void 0 ? _t : newState.speed;
newState.slowness = (_u = oldState.slowness) !== null && _u !== void 0 ? _u : newState.slowness;
newState.dolphinsGrace = (_v = oldState.dolphinsGrace) !== null && _v !== void 0 ? _v : newState.dolphinsGrace;
newState.slowFalling = (_w = oldState.slowFalling) !== null && _w !== void 0 ? _w : newState.slowFalling;
newState.levitation = (_x = oldState.levitation) !== null && _x !== void 0 ? _x : newState.levitation;
newState.depthStrider = (_y = oldState.depthStrider) !== null && _y !== void 0 ? _y : newState.depthStrider;
return newState;
}
/**
* Applies the values of the new PlayerState class back onto an old PlayerState object.
* This updates the oldState in-place.
* * @param newState The current, updated instance of the new PlayerState class.
* @param oldState The old PlayerState object to be overwritten.
*/
function applyToPlayerState(newState, oldState) {
// 1. Update Spatial and Velocity Data
// Using .set() preserves the original Vec3 object reference in the old state.
if (oldState.pos && newState.pos) {
oldState.pos.set(newState.pos.x, newState.pos.y, newState.pos.z);
}
if (oldState.vel && newState.vel) {
oldState.vel.set(newState.vel.x, newState.vel.y, newState.vel.z);
}
// 2. Map Environment & Collision Flags
oldState.onGround = newState.onGround;
oldState.isInWater = newState.isInWater;
oldState.isInLava = newState.isInLava;
oldState.isInWeb = newState.isInWeb;
oldState.isCollidedHorizontally = newState.isCollidedHorizontally;
oldState.isCollidedVertically = newState.isCollidedVertically;
// 3. Map Movement & Actions
oldState.fallFlying = newState.fallFlying;
oldState.elytraFlying = newState.fallFlying;
oldState.validElytraEquipped = newState.validElytraEquipped;
oldState.elytraEquipped = newState.validElytraEquipped;
oldState.jumpTicks = newState.jumpTicks;
oldState.jumpQueued = newState.jumpQueued;
oldState.fireworkRocketDuration = newState.fireworkRocketDuration;
oldState.yaw = newState.yaw;
oldState.pitch = newState.pitch;
// 4. Downgrade Control State
// Extracts standard booleans from the ControlStateHandler so the old state
// doesn't accidentally inherit class methods.
if (newState.control) {
oldState.control = {
forward: newState.control.forward,
back: newState.control.back,
left: newState.control.left,
right: newState.control.right,
jump: newState.control.jump,
sprint: newState.control.sprint,
sneak: newState.control.sneak
};
}
// 5. Map Attributes, Effects, and Enchantments
oldState.attributes = newState.attributes;
oldState.jumpBoost = newState.jumpBoost;
oldState.speed = newState.speed;
oldState.slowness = newState.slowness;
oldState.dolphinsGrace = newState.dolphinsGrace;
oldState.slowFalling = newState.slowFalling;
oldState.levitation = newState.levitation;
oldState.depthStrider = newState.depthStrider;
}