fix(minecraft): use correct id for blocksearch and some improvements

This commit is contained in:
Rin
2026-02-18 11:12:04 +08:00
committed by Neko Ayaka
parent f99b9d6aa4
commit de8b1994ed
4 changed files with 63 additions and 10 deletions
@@ -138,8 +138,8 @@ export const actionsList: Action[] = [
search_range: z.number().describe('The range to search for the block.').min(32).max(512),
}),
perform: mineflayer => async (block_type: string, range: number) => {
await skills.goToNearestBlock(mineflayer, block_type, 4, range)
return `Arrived at nearest [${block_type}]` // TODO more spacial context?
const block = await skills.goToNearestBlock(mineflayer, block_type, 4, range)
return `Arrived at nearest [${block.name}] at (${block.position.x}, ${block.position.y}, ${block.position.z})` // TODO more spacial context?
},
},
{
+4 -4
View File
@@ -1,3 +1,4 @@
import type { Block } from 'prismarine-block'
import type { Entity } from 'prismarine-entity'
import type { Mineflayer } from '../libs/mineflayer'
@@ -43,7 +44,7 @@ export async function goToNearestBlock(
blockType: string,
minDistance = 2,
range = 64,
): Promise<boolean> {
): Promise<Block> {
const MAX_RANGE = 512
if (range > MAX_RANGE) {
log(mineflayer, `Maximum search range capped at ${MAX_RANGE}.`)
@@ -52,13 +53,12 @@ export async function goToNearestBlock(
const block = getNearestBlock(mineflayer, blockType, range)
if (!block) {
log(mineflayer, `Could not find any ${blockType} in ${range} blocks.`)
return false
throw new Error(`Could not find any ${blockType} in ${range} blocks.`)
}
log(mineflayer, `Found ${blockType} at ${block.position}.`)
await goToPosition(mineflayer, block.position.x, block.position.y, block.position.z, minDistance)
return true
return block
}
export async function goToNearestEntity(
+18 -4
View File
@@ -58,11 +58,25 @@ export function getNearestFreeSpace(
}
export function getNearestBlocks(mineflayer: Mineflayer, blockTypes: string[] | string | null = null, distance: number = 16, count: number = 10000): Block[] {
const blockIds = blockTypes === null
? mc.getAllBlockIds(['air'])
: (Array.isArray(blockTypes) ? blockTypes : [blockTypes]).map(mc.getBlockId).filter((id): id is number => id !== null)
const blockNames = blockTypes === null
? mc.getAllBlocks(['air']).map(block => block.name)
: (Array.isArray(blockTypes) ? blockTypes : [blockTypes])
.map((name) => {
const id = mc.getBlockId(name)
if (id)
return name
const positions = mineflayer.bot.findBlocks({ matching: blockIds, maxDistance: distance, count })
const closest = mc.getClosestBlockName(name)
const suggestion = closest ? `; did you mean ${closest}?` : ''
throw new Error(`Unknown block type: ${name}${suggestion}`)
})
const blockNameSet = new Set(blockNames)
const positions = mineflayer.bot.findBlocks({
matching: block => block && blockNameSet.has(block.name),
maxDistance: distance,
count,
})
return positions
.map((pos) => {
+39
View File
@@ -99,6 +99,45 @@ export function getBlockName(blockId: number): string {
return block.name || ''
}
export function getClosestBlockName(input: string): string | null {
const names = Object.keys(gameData.blocksByName ?? {})
let best: { name: string | null, distance: number } = { name: null, distance: Number.POSITIVE_INFINITY }
for (const name of names) {
const distance = levenshteinDistance(input, name)
if (distance < best.distance) {
best = { name, distance }
if (distance === 0)
break
}
}
return best.name
}
function levenshteinDistance(a: string, b: string): number {
const matrix: number[][] = Array.from({ length: a.length + 1 }, () =>
Array.from({ length: b.length + 1 }, () => 0))
for (let i = 0; i <= a.length; i++)
matrix[i][0] = i
for (let j = 0; j <= b.length; j++)
matrix[0][j] = j
for (let i = 1; i <= a.length; i++) {
for (let j = 1; j <= b.length; j++) {
const cost = a[i - 1] === b[j - 1] ? 0 : 1
matrix[i][j] = Math.min(
matrix[i - 1][j] + 1,
matrix[i][j - 1] + 1,
matrix[i - 1][j - 1] + cost,
)
}
}
return matrix[a.length][b.length]
}
export function getAllItems(ignore: string[] = []): any[] {
const items: any[] = []
for (const itemId in gameData.items) {