UNPKG

@nxg-org/mineflayer-physics-util

Version:

Provides functionality for more accurate entity and projectile tracking.

287 lines (286 loc) 14.4 kB
"use strict"; 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; }