feat(skill): inventory

This commit is contained in:
RainbowBird
2025-01-08 22:35:28 +08:00
parent dfd888b4b4
commit 252cc1e81a
+33 -62
View File
@@ -1,14 +1,13 @@
import type { Bot } from 'mineflayer'
import type { SkillContext } from './base'
import pathfinderModel from 'mineflayer-pathfinder'
import * as world from '../composables/world'
import { log } from './base'
import { goToPosition } from './movement'
/**
* Pick up nearby items
*/
const { goals } = pathfinderModel
export async function pickupNearbyItems(ctx: SkillContext): Promise<boolean> {
const { bot } = ctx
const distance = 8
const getNearestItem = (bot: Bot) =>
bot.nearestEntity(entity =>
@@ -16,15 +15,15 @@ export async function pickupNearbyItems(ctx: SkillContext): Promise<boolean> {
&& bot.entity.position.distanceTo(entity.position) < distance,
)
let nearestItem = getNearestItem(bot)
let nearestItem = getNearestItem(ctx.bot)
let pickedUp = 0
while (nearestItem) {
await bot.pathfinder.goto(bot.pathfinder.goals.GoalFollow(nearestItem, 0.8), true)
await ctx.bot.pathfinder.goto(new goals.GoalFollow(nearestItem, 0.8))
await new Promise(resolve => setTimeout(resolve, 200))
const prev = nearestItem
nearestItem = getNearestItem(bot)
nearestItem = getNearestItem(ctx.bot)
if (prev === nearestItem) {
break
}
@@ -35,55 +34,47 @@ export async function pickupNearbyItems(ctx: SkillContext): Promise<boolean> {
return true
}
/**
* Equip an item
*/
export async function equip(ctx: SkillContext, itemName: string): Promise<boolean> {
const { bot } = ctx
const item = bot.inventory.slots.find(slot => slot && slot.name === itemName)
const item = ctx.bot.inventory.slots.find(slot => slot && slot.name === itemName)
if (!item) {
log(ctx, `You do not have any ${itemName} to equip.`)
return false
}
if (itemName.includes('leggings')) {
await bot.equip(item, 'legs')
await ctx.bot.equip(item, 'legs')
}
else if (itemName.includes('boots')) {
await bot.equip(item, 'feet')
await ctx.bot.equip(item, 'feet')
}
else if (itemName.includes('helmet')) {
await bot.equip(item, 'head')
await ctx.bot.equip(item, 'head')
}
else if (itemName.includes('chestplate') || itemName.includes('elytra')) {
await bot.equip(item, 'torso')
await ctx.bot.equip(item, 'torso')
}
else if (itemName.includes('shield')) {
await bot.equip(item, 'off-hand')
await ctx.bot.equip(item, 'off-hand')
}
else {
await bot.equip(item, 'hand')
await ctx.bot.equip(item, 'hand')
}
log(ctx, `Equipped ${itemName}.`)
return true
}
/**
* Discard items
*/
export async function discard(ctx: SkillContext, itemName: string, num = -1): Promise<boolean> {
const { bot } = ctx
let discarded = 0
while (true) {
const item = bot.inventory.items().find(item => item.name === itemName)
const item = ctx.bot.inventory.items().find(item => item.name === itemName)
if (!item) {
break
}
const toDiscard = num === -1 ? item.count : Math.min(num - discarded, item.count)
await bot.toss(item.type, null, toDiscard)
await ctx.bot.toss(item.type, null, toDiscard)
discarded += toDiscard
if (num !== -1 && discarded >= num) {
@@ -100,18 +91,14 @@ export async function discard(ctx: SkillContext, itemName: string, num = -1): Pr
return true
}
/**
* Put items in a chest
*/
export async function putInChest(ctx: SkillContext, itemName: string, num = -1): Promise<boolean> {
const { bot } = ctx
const chest = world.getNearestBlock(bot, 'chest', 32)
const chest = world.getNearestBlock(world.createWorldContext(ctx.botCtx), 'chest', 32)
if (!chest) {
log(ctx, 'Could not find a chest nearby.')
return false
}
const item = bot.inventory.items().find(item => item.name === itemName)
const item = ctx.bot.inventory.items().find(item => item.name === itemName)
if (!item) {
log(ctx, `You do not have any ${itemName} to put in the chest.`)
return false
@@ -120,7 +107,7 @@ export async function putInChest(ctx: SkillContext, itemName: string, num = -1):
const toPut = num === -1 ? item.count : Math.min(num, item.count)
await goToPosition(ctx, chest.position.x, chest.position.y, chest.position.z, 2)
const chestContainer = await bot.openContainer(chest)
const chestContainer = await ctx.bot.openContainer(chest)
await chestContainer.deposit(item.type, null, toPut)
await chestContainer.close()
@@ -128,19 +115,15 @@ export async function putInChest(ctx: SkillContext, itemName: string, num = -1):
return true
}
/**
* Take items from a chest
*/
export async function takeFromChest(ctx: SkillContext, itemName: string, num = -1): Promise<boolean> {
const { bot } = ctx
const chest = world.getNearestBlock(bot, 'chest', 32)
const chest = world.getNearestBlock(world.createWorldContext(ctx.botCtx), 'chest', 32)
if (!chest) {
log(ctx, 'Could not find a chest nearby.')
return false
}
await goToPosition(ctx, chest.position.x, chest.position.y, chest.position.z, 2)
const chestContainer = await bot.openContainer(chest)
const chestContainer = await ctx.bot.openContainer(chest)
const item = chestContainer.containerItems().find(item => item.name === itemName)
if (!item) {
@@ -157,19 +140,15 @@ export async function takeFromChest(ctx: SkillContext, itemName: string, num = -
return true
}
/**
* View contents of a chest
*/
export async function viewChest(ctx: SkillContext): Promise<boolean> {
const { bot } = ctx
const chest = world.getNearestBlock(bot, 'chest', 32)
const chest = world.getNearestBlock(world.createWorldContext(ctx.botCtx), 'chest', 32)
if (!chest) {
log(ctx, 'Could not find a chest nearby.')
return false
}
await goToPosition(ctx, chest.position.x, chest.position.y, chest.position.z, 2)
const chestContainer = await bot.openContainer(chest)
const chestContainer = await ctx.bot.openContainer(chest)
const items = chestContainer.containerItems()
if (items.length === 0) {
@@ -186,16 +165,12 @@ export async function viewChest(ctx: SkillContext): Promise<boolean> {
return true
}
/**
* Consume (eat/drink) an item
*/
export async function consume(ctx: SkillContext, itemName = ''): Promise<boolean> {
const { bot } = ctx
let item
let name
if (itemName) {
item = bot.inventory.items().find(item => item.name === itemName)
item = ctx.bot.inventory.items().find(item => item.name === itemName)
name = itemName
}
@@ -204,23 +179,19 @@ export async function consume(ctx: SkillContext, itemName = ''): Promise<boolean
return false
}
await bot.equip(item, 'hand')
await bot.consume()
await ctx.bot.equip(item, 'hand')
await ctx.bot.consume()
log(ctx, `Consumed ${item.name}.`)
return true
}
/**
* Give items to a player
*/
export async function giveToPlayer(
ctx: SkillContext,
itemType: string,
username: string,
num = 1,
): Promise<boolean> {
const { bot } = ctx
const player = bot.players[username]?.entity
const player = ctx.bot.players[username]?.entity
if (!player) {
log(ctx, `Could not find ${username}.`)
return false
@@ -228,21 +199,21 @@ export async function giveToPlayer(
await goToPosition(ctx, player.position.x, player.position.y, player.position.z, 3)
if (bot.entity.position.y < player.position.y - 1) {
if (ctx.bot.entity.position.y < player.position.y - 1) {
await goToPosition(ctx, player.position.x, player.position.y, player.position.z, 1)
}
if (bot.entity.position.distanceTo(player.position) < 2) {
const goal = bot.pathfinder.goals.GoalNear(player.position.x, player.position.y, player.position.z, 2)
const invertedGoal = bot.pathfinder.goals.GoalInvert(goal)
await bot.pathfinder.goto(invertedGoal)
if (ctx.bot.entity.position.distanceTo(player.position) < 2) {
const goal = new goals.GoalNear(player.position.x, player.position.y, player.position.z, 2)
const invertedGoal = new goals.GoalInvert(goal)
await ctx.bot.pathfinder.goto(invertedGoal)
}
await bot.lookAt(player.position)
await ctx.bot.lookAt(player.position)
if (await discard(ctx, itemType, num)) {
let given = false
bot.once('playerCollect', (collector, collected) => {
ctx.bot.once('playerCollect', (collector, _collected) => {
if (collector.username === username) {
log(ctx, `${username} received ${itemType}.`)
given = true