fix(minecraft): use correct id for blocksearch and some improvements
This commit is contained in:
@@ -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?
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user