UNPKG

@nxg-org/mineflayer-physics-util

Version:

Provides functionality for more accurate entity and projectile tracking.

194 lines (165 loc) 6.27 kB
import { pathfinder, goals } from "mineflayer-pathfinder"; import { Bot, createBot } from "mineflayer"; const physicsInject = require("mineflayer/lib/plugins/physics"); import loader, { BotcraftPhysics, EntityPhysics, EntityState, EPhysicsCtx } from "../src/index"; import { PlayerState } from "../src/physics/states"; const { Physics } = require("prismarine-physics"); const rl = require("readline").createInterface({ input: process.stdin, output: process.stdout, }); let bot1: Bot; function buildBot() { console.log("hey!"); const bot = createBot({ host: process.argv[2] || 'localhost', port: Number(process.argv[3]), username: "testingbot", version: process.argv[4], }); bot.on('login', () => { bot.chat("Hello! I am a testing bot!"); }) bot.once("spawn", async () => { bot.loadPlugin(loader); bot.loadPlugin(pathfinder); await bot.waitForTicks(20); (bot as any).physics.yawSpeed = 50; (bot as any).physics.pitchSpeed = 50; setupNewPhysics(bot); // setupNewPhysics(bot); }); let wasOnGround = false; const printNextPos = false; bot.on("move", (pos) => { // console.log(pos); if (bot.entity.onGround && !wasOnGround) { // bot.chat("Hit the ground! " + bot.entity.position.toString()); } wasOnGround = bot.entity.onGround; }); // print whenever another player hits the ground const lastPositions: Record<string, boolean> = {}; bot.on("entityMoved", (entity) => { if (entity.username && entity.username !== bot.username) { // check by seeing is y value is an integer if (Math.floor(entity.position.y) === entity.position.y && !lastPositions[entity.username]) { // check if in liquid const block = bot.blockAt(entity.position); if (block && (block.type === bot.registry.blocksByName.water.id || block.type === bot.registry.blocksByName.lava.id)) return; bot.chat(`${entity.username} hit the ground! ${entity.position.toString()}`); lastPositions[entity.username] = true; } else if (Math.floor(entity.position.y) !== entity.position.y) { lastPositions[entity.username] = false; } } }); let usingNew = false; let oldSimulate: any = null; let state: PlayerState | null = null; function setupNewPhysics(bot: Bot) { if (usingNew) return; usingNew = true; oldSimulate = (bot.physics as any).simulatePlayer; const val = new BotcraftPhysics(bot.registry); (EntityState.prototype as any).apply = function (this: EntityState, bot: Bot) { console.log(this.control, this.isUsingItem); this.applyToBot(bot); }; const ctx = EPhysicsCtx.FROM_BOT(val, bot); state = ctx.state as PlayerState; // EntityPhysics.prototype.simulate = function (ctx, world) { // bot.physics.simulatePlayer(ctx.state, world); // } (bot.physics as any).autojumpCooldown = 0; // (bot.physics).jumpTicks = 0; (bot.physics as any).simulatePlayer = (...args: any[]) => { state!.update(bot); ctx.state.jumpTicks = 0; // allow immediate jumping return val.simulate(ctx, bot.world); }; } bot.on("chat", async (user, message) => { const [cmd, ...args] = message.split(" "); const author = bot.nearestEntity((e) => e.username === user); switch (cmd) { case "using": bot.chat(`Using new physics: ${usingNew}`); break; case "lookatme": if (!author) return bot.chat("I can't see you!"); bot.lookAt(author.position.offset(0, author.height, 0)); break; case "status": const str0 = `pos: ${bot.entity.position.toString()}, vel: ${bot.entity.velocity.toString()}, yaw: ${bot.entity.yaw}, pitch: ${bot.entity.pitch}`; bot.chat(str0); const str = `onGround: ${bot.entity.onGround}, hCol: ${(bot.entity as any).isCollidedHorizontally}, vCol: ${ (bot.entity as any).isCollidedVertically }, inWater: ${(bot.entity as any).isInWater}, inLava: ${(bot.entity as any).isInLava}`; bot.chat(str); if (state != null) { const str1 = `crouching: ${state.crouching}, sprinting: ${state.sprinting}`; bot.chat(str1); } break; case "use": if (bot.usingHeldItem) bot.deactivateItem(); else bot.activateItem(); break; case "useoff": bot.deactivateItem(); bot.activateItem(true); break; case "control": if (args[0] === "clear") return bot.clearControlStates(); if (args.length === 1) return bot.setControlState(args[0] as any, !bot.getControlState(args[0] as any)); bot.setControlState(args[0] as any, args[1] === "true"); break; case "sim": // turn all but the mentioned ones off const [time, ...controls] = args; bot.clearControlStates(); for (const control of controls) { bot.setControlState(control as any, true); } for (let i = 0; i <= Number(time); i++) { console.log(bot.entity.position, bot.entity.velocity, i); await bot.waitForTicks(1); } bot.clearControlStates(); break; case "reset": usingNew = false; bot.quit(); await new Promise((res) => setTimeout(res, 3000)); bot1 = buildBot(); break; case "new": setupNewPhysics(bot); bot.chat("Switched to new physics!"); break; case "jump": bot.setControlState("jump", true); break; case "come": if (!author) return bot.chat(`Cannot see ${user}!`); const goal0 = new goals.GoalNear(author.position.x, author.position.y, author.position.z, 3); bot.pathfinder.setGoal(goal0); break; case "goto": if (!author) return bot.chat(`Cannot see ${user}!`); const goal1 = new goals.GoalNear(Number(args[0]), Number(args[1]), Number(args[2]), 3); bot.pathfinder.setGoal(goal1); break; case "stop": bot.deactivateItem(); bot.pathfinder.stop(); bot.clearControlStates(); bot.chat("Stopped!"); break; } }); rl.on("line", (line: any) => bot.chat(line)); return bot; } bot1 = buildBot();