From 6baa1888910146a471e4c83f0915a942f713d494 Mon Sep 17 00:00:00 2001 From: RainbowBird Date: Wed, 8 Jan 2025 23:28:21 +0800 Subject: [PATCH] feat(skill): combat --- services/minecraft/src/skills/combat.ts | 50 ++++++++++++------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/services/minecraft/src/skills/combat.ts b/services/minecraft/src/skills/combat.ts index 9946efd78..2ae048487 100644 --- a/services/minecraft/src/skills/combat.ts +++ b/services/minecraft/src/skills/combat.ts @@ -1,24 +1,30 @@ import type { Entity } from 'prismarine-entity' +import type { Item } from 'prismarine-item' import type { SkillContext } from './base' +import pathfinderModel from 'mineflayer-pathfinder' import * as world from '../composables/world' import * as mc from '../utils/mcdata' import { log } from './base' -/** - * Equip the item with highest attack damage - */ +const { goals } = pathfinderModel + +interface WeaponItem extends Item { + attackDamage: number +} + async function equipHighestAttack(ctx: SkillContext): Promise { const { bot } = ctx const weapons = bot.inventory.items().filter(item => item.name.includes('sword') || (item.name.includes('axe') && !item.name.includes('pickaxe')), - ) + ) as WeaponItem[] if (weapons.length === 0) { const tools = bot.inventory.items().filter(item => item.name.includes('pickaxe') || item.name.includes('shovel'), - ) + ) as WeaponItem[] + if (tools.length === 0) return @@ -35,16 +41,13 @@ async function equipHighestAttack(ctx: SkillContext): Promise { await bot.equip(weapon, 'hand') } -/** - * Attack the nearest mob of the given type - */ export async function attackNearest( ctx: SkillContext, mobType: string, kill = true, ): Promise { - const { bot } = ctx - const mob = world.getNearbyEntities(bot, 24).find(entity => entity.name === mobType) + const worldCtx = world.createWorldContext(ctx.botCtx) + const mob = world.getNearbyEntities(worldCtx, 24).find(entity => entity.name === mobType) if (mob) { return await attackEntity(ctx, mob, kill) @@ -54,9 +57,6 @@ export async function attackNearest( return false } -/** - * Attack a specific entity - */ export async function attackEntity( ctx: SkillContext, entity: Entity, @@ -68,14 +68,16 @@ export async function attackEntity( if (!kill) { if (bot.entity.position.distanceTo(pos) > 5) { - await bot.pathfinder.goto(bot.pathfinder.goals.GoalNear(pos.x, pos.y, pos.z, 4)) + const goal = new goals.GoalNear(pos.x, pos.y, pos.z, 4) + await bot.pathfinder.goto(goal) } await bot.attack(entity) return true } bot.pvp.attack(entity) - while (world.getNearbyEntities(bot, 24).includes(entity)) { + const worldCtx = world.createWorldContext(ctx.botCtx) + while (world.getNearbyEntities(worldCtx, 24).includes(entity)) { await new Promise(resolve => setTimeout(resolve, 1000)) if (ctx.shouldInterrupt) { bot.pvp.stop() @@ -87,13 +89,11 @@ export async function attackEntity( return true } -/** - * Defend against nearby hostile mobs - */ export async function defendSelf(ctx: SkillContext, range = 9): Promise { const { bot } = ctx let attacked = false - let enemy = world.getNearestEntityWhere(bot, entity => mc.isHostile(entity), range) + const worldCtx = world.createWorldContext(ctx.botCtx) + let enemy = world.getNearestEntityWhere(worldCtx, entity => mc.isHostile(entity), range) while (enemy) { await equipHighestAttack(ctx) @@ -101,17 +101,17 @@ export async function defendSelf(ctx: SkillContext, range = 9): Promise if (bot.entity.position.distanceTo(enemy.position) >= 4 && enemy.name !== 'creeper' && enemy.name !== 'phantom') { try { - await bot.pathfinder.goto(bot.pathfinder.goals.GoalFollow(enemy, 3.5), true) + const goal = new goals.GoalFollow(enemy, 3.5) + await bot.pathfinder.goto(goal) } catch { /* might error if entity dies, ignore */ } } if (bot.entity.position.distanceTo(enemy.position) <= 2) { try { - const invertedGoal = bot.pathfinder.goals.GoalInvert( - bot.pathfinder.goals.GoalFollow(enemy, 2), - ) - await bot.pathfinder.goto(invertedGoal, true) + const followGoal = new goals.GoalFollow(enemy, 2) + const invertedGoal = new goals.GoalInvert(followGoal) + await bot.pathfinder.goto(invertedGoal) } catch { /* might error if entity dies, ignore */ } } @@ -119,7 +119,7 @@ export async function defendSelf(ctx: SkillContext, range = 9): Promise bot.pvp.attack(enemy) attacked = true await new Promise(resolve => setTimeout(resolve, 500)) - enemy = world.getNearestEntityWhere(bot, entity => mc.isHostile(entity), range) + enemy = world.getNearestEntityWhere(worldCtx, entity => mc.isHostile(entity), range) if (ctx.shouldInterrupt) { bot.pvp.stop()