diff --git a/src/ThePathfinder.ts b/src/ThePathfinder.ts index 05055c9..d09e10d 100644 --- a/src/ThePathfinder.ts +++ b/src/ThePathfinder.ts @@ -27,6 +27,12 @@ import { StraightUp } from './mineflayer-specific/movements/movementProviders' + +import { + MovementAscend, + MovementDescend +} from './mineflayer-specific/movements/baritone/baritoneProviders' + import { ParkourForwardExecutor, ForwardDropDownExecutor, @@ -62,13 +68,15 @@ const EMPTY_VEC = new Vec3(0, 0, 0) * These are the default movement types and their respective executors. */ const DEFAULT_PROVIDER_EXECUTORS = [ - [Forward, NewForwardExecutor], - [ForwardJump, NewForwardJumpExecutor], - [ForwardDropDown, ForwardDropDownExecutor], - [Diagonal, NewForwardExecutor], - [StraightDown, StraightDownExecutor], - [StraightUp, StraightUpExecutor], - [ParkourForward, ParkourForwardExecutor] + // [Forward, NewForwardExecutor], + // [ForwardJump, NewForwardJumpExecutor], + // [ForwardDropDown, ForwardDropDownExecutor], + // [Diagonal, NewForwardExecutor], + // [StraightDown, StraightDownExecutor], + // [StraightUp, StraightUpExecutor], + // [ParkourForward, ParkourForwardExecutor] + [MovementAscend, StraightUpExecutor], + [MovementDescend, StraightDownExecutor] ] as Array<[BuildableMoveProvider, BuildableMoveExecutor]> /** @@ -579,9 +587,9 @@ export class ThePathfinder { } } - do { + outer0: do { let madeIt = false - do { + outer1: do { setupWait() console.log('reset I believe', doForever) @@ -592,7 +600,7 @@ export class ThePathfinder { if (res.result.status !== 'success') { if (res.result.status === 'noPath' || res.result.status === 'timeout' || res.result.status === 'canceled') { if (task !== null && res1 !== null) res1.path.length = 0 - break + break outer1 } if (res.result.status === 'partialSuccess') { @@ -665,16 +673,17 @@ export class ThePathfinder { } private async postProcess (pathInfo: Path): Promise { - const optimizer = new Optimizer(this.bot, this.world, this.optimizers) + return pathInfo + // const optimizer = new Optimizer(this.bot, this.world, this.optimizers) - optimizer.loadPath(pathInfo.path) + // optimizer.loadPath(pathInfo.path) - const res = await optimizer.compute() + // const res = await optimizer.compute() - const ret = { ...pathInfo } + // const ret = { ...pathInfo } - ret.path = res - return ret + // ret.path = res + // return ret } private check (): void { diff --git a/src/customHashmap/Int64Map/src/Int64Map.ts b/src/customHashmap/Int64Map/src/Int64Map.ts index 4e91506..5f729f2 100644 --- a/src/customHashmap/Int64Map/src/Int64Map.ts +++ b/src/customHashmap/Int64Map/src/Int64Map.ts @@ -1,15 +1,15 @@ type primitive = boolean | number | string | bigint | symbol | object | null -interface Node { +interface Node

{ intLow: number intHigh: number - value: primitive - next?: Node + value: P + next?: Node

} -interface Bucket { - head?: Node +interface Bucket

{ + head?: Node

} const DEFAULT_SIZE = 1024 @@ -17,9 +17,9 @@ const LOAD_FACTOR = 0.5 console.log('running with load factor', LOAD_FACTOR) -class Int64Map { +class Int64Map

{ constructor (initialSize = DEFAULT_SIZE) { - this.values = new Array(initialSize) + this.values = new Array>(initialSize) for (let i = 0; i < initialSize; i++) { this.values[i] = { } } @@ -27,7 +27,7 @@ class Int64Map { this.size = initialSize } - private readonly values: Bucket[] + private readonly values: Bucket

[] private readonly INTIAL_SIZE: number = DEFAULT_SIZE @@ -43,7 +43,7 @@ class Int64Map { return this.length } - get (intLow: number, intHigh: number): primitive { + get (intLow: number, intHigh: number): P | null { const index = intLow & (this.size - 1) const bucket = this.values[index] let node = bucket.head @@ -56,7 +56,7 @@ class Int64Map { return null } - set (intLow: number, intHigh: number, value: primitive): primitive { + set (intLow: number, intHigh: number, value: P): P | boolean { if (this.length > this.size * LOAD_FACTOR) { this.grow() } diff --git a/src/mineflayer-specific/move.ts b/src/mineflayer-specific/move.ts index 46e2bc1..51528a4 100644 --- a/src/mineflayer-specific/move.ts +++ b/src/mineflayer-specific/move.ts @@ -37,6 +37,9 @@ export class Move implements PathData { this.cachedVec = new Vec3(this.x, this.y, this.z) Object.freeze(this.cachedVec) + + Object.freeze(toBreak) + Object.freeze(toPlace) // this.x = x; // this.y = y; // this.z = z; diff --git a/src/mineflayer-specific/movements/baritone/baritoneProviders.ts b/src/mineflayer-specific/movements/baritone/baritoneProviders.ts index 854dd0d..18f5184 100644 --- a/src/mineflayer-specific/movements/baritone/baritoneProviders.ts +++ b/src/mineflayer-specific/movements/baritone/baritoneProviders.ts @@ -1,18 +1,26 @@ -import { Vec3 } from 'vec3' -import { Move } from '../../move' -import { MovementProvider } from '../movementProvider' -import { Goal } from '../../goals' -import { canUseFrostWalker, canWalkOn, canWalkThrough, findPlaceOpts, getMiningDurationTicks, isBottomSlab } from './movementHelper' -import { BreakHandler, PlaceHandler } from '../interactionUtils' -import { CENTER_AFTER_FALL_COST, COST_INF, FALL_N_BLOCKS_COST, JUMP_ONE_BLOCK_COST, WALK_OFF_BLOCK_COST, WALK_ONE_BLOCK_COST, WALK_ONE_OVER_SOUL_SAND_COST } from '../costs' -import { BlockInfo } from '../../world/cacheWorld' +import { Vec3 } from "vec3"; +import { Move } from "../../move"; +import { MovementProvider } from "../movementProvider"; +import { Goal } from "../../goals"; +import { canUseFrostWalker, canWalkOn, canWalkThrough, findPlaceOpts, getMiningDurationTicks, isBottomSlab, mustBeSolidToWalkOn } from "./movementHelper"; +import { BreakHandler, PlaceHandler } from "../interactionUtils"; +import { + CENTER_AFTER_FALL_COST, + COST_INF, + FALL_N_BLOCKS_COST, + JUMP_ONE_BLOCK_COST, + WALK_OFF_BLOCK_COST, + WALK_ONE_BLOCK_COST, + WALK_ONE_OVER_SOUL_SAND_COST, +} from "../costs"; +import { BlockInfo } from "../../world/cacheWorld"; export class IdleMovement extends MovementProvider { - movementDirs: Vec3[] = [] - provideMovements (start: Move, storage: Move[]): void {} - async performInit (thisMove: Move, currentIndex: number, path: Move[]): Promise {} - async performPerTick (thisMove: Move, tickCount: number, currentIndex: number, path: Move[]): Promise { - return true + movementDirs: Vec3[] = []; + provideMovements(start: Move, storage: Move[]): void {} + async performInit(thisMove: Move, currentIndex: number, path: Move[]): Promise {} + async performPerTick(thisMove: Move, tickCount: number, currentIndex: number, path: Move[]): Promise { + return true; } } @@ -20,138 +28,173 @@ export class IdleMovement extends MovementProvider { // https://github.com/cabaletta/baritone/blob/1.19.4/src/main/java/baritone/pathing/movement/movements/MovementAscend.java export class MovementAscend extends MovementProvider { - movementDirs = [new Vec3(0, 1, 0)] - provideMovements (start: Move, storage: Move[], goal: Goal, closed: Set): void { + movementDirs = [new Vec3(0, 1, 0), new Vec3(0, 1, 1), new Vec3(0, 1, -1), new Vec3(1, 1, 0), new Vec3(-1, 1, 0)]; + provideMovements(start: Move, storage: Move[], goal: Goal, closed: Set): void { for (const dir of this.movementDirs) { - const off = start.cachedVec.plus(dir) - if (closed.has(off.toString())) return - this.provideAscend(start, dir, storage, closed) + const off = start.cachedVec.plus(dir); + // if (closed.has(off.toString())) return + this.provideAscend(start, dir, storage, closed); } } - provideAscend (node: Move, dir: Vec3, storage: Move[], closed: Set): void { - const blPlace = this.getBlockInfo(node, dir.x, 0, dir.y) + provideAscend(node: Move, dir: Vec3, storage: Move[], closed: Set): void { + const blPlace = this.getBlockInfo(node, dir.x, 0, dir.z); - if (blPlace.isInvalid) return + if (blPlace.block?.name.startsWith("black")) console.log("sup bitch", node.exitPos, blPlace); + if (blPlace.isInvalid) return; // potentially get rid of these, as we don't actually need them for the time being. - const toPlace: PlaceHandler[] = [] - const toBreak: BreakHandler[] = [] + const toPlace: PlaceHandler[] = []; + const toBreak: BreakHandler[] = []; - let cost = 0 - if (!blPlace.physical) { + let cost = 0; + if (!blPlace.solidFull) { if (!blPlace.replaceable) { - if ((cost += this.safeOrBreak(blPlace, toBreak)) >= COST_INF) return + if ((cost += this.safeOrBreak(blPlace, toBreak)) >= COST_INF) return; } - if ((cost += this.safeOrPlace(blPlace, toPlace)) >= COST_INF) return - if (findPlaceOpts(this, node, blPlace.position) == null) return + if ((cost += this.safeOrPlace(blPlace, toPlace)) >= COST_INF) return; + if (findPlaceOpts(this, node, blPlace.position) == null) return; } - const srcUp1 = this.getBlockInfo(node, 0, 1, 0) - const srcUp2 = this.getBlockInfo(node, 0, 2, 0) - const srcUp3 = this.getBlockInfo(node, 0, 3, 0) + // console.log('made it here', node.exitPos) + + const srcUp1 = this.getBlockInfo(node, 0, 1, 0); + const srcUp2 = this.getBlockInfo(node, 0, 2, 0); + const srcUp3 = this.getBlockInfo(node, 0, 3, 0); // translate below to typescript // if (context.get(x, y + 3, z).getBlock() instanceof FallingBlock && (MovementHelper.canWalkThrough(context, x, y + 1, z) || !(srcUp2.getBlock() instanceof FallingBlock))) {//it would fall on us and possibly suffocate us if (srcUp3.canFall && (canWalkThrough(srcUp1) || !srcUp2.canFall)) { - return + console.log("end here"); + return; } - const srcDown1 = this.getBlockInfo(node, 0, -1, 0) - if (srcDown1.climbable) return + const srcDown1 = this.getBlockInfo(node, 0, -1, 0); + if (srcDown1.climbable) return; - const jumpFromBottomSlab = isBottomSlab(srcDown1) - const jumpToBottomSlab = isBottomSlab(blPlace) + const jumpFromBottomSlab = isBottomSlab(srcDown1); + const jumpToBottomSlab = isBottomSlab(blPlace); if (jumpFromBottomSlab && !jumpToBottomSlab) { - return + return; } - let walk = 0 + let walk = 0; if (jumpToBottomSlab) { if (jumpFromBottomSlab) { - walk = Math.max(JUMP_ONE_BLOCK_COST, WALK_ONE_BLOCK_COST) // we hit space immediately on entering this action - walk += this.settings.jumpCost + walk = Math.max(JUMP_ONE_BLOCK_COST, WALK_ONE_BLOCK_COST); // we hit space immediately on entering this action + walk += this.settings.jumpCost; } else { - walk = WALK_ONE_BLOCK_COST + walk = WALK_ONE_BLOCK_COST; } } else { // for speed // eslint-disable-next-line @typescript-eslint/no-non-null-assertion if (blPlace.block!.type === BlockInfo.soulsandId) { - walk = WALK_ONE_OVER_SOUL_SAND_COST + walk = WALK_ONE_OVER_SOUL_SAND_COST; } else { - walk = Math.max(JUMP_ONE_BLOCK_COST, WALK_ONE_BLOCK_COST) + walk = Math.max(JUMP_ONE_BLOCK_COST, WALK_ONE_BLOCK_COST); } - walk += this.settings.jumpCost + walk += this.settings.jumpCost; } - if ((cost += walk) >= COST_INF) return - if ((cost += getMiningDurationTicks(this, srcUp2)) >= COST_INF) return + if ((cost += walk) >= COST_INF) return; + if ((cost += getMiningDurationTicks(this, srcUp2, toBreak)) >= COST_INF) return; - const target1 = this.getBlockInfo(node, dir.x, 1, dir.z) - if ((cost += getMiningDurationTicks(this, target1)) >= COST_INF) return + const target1 = this.getBlockInfo(node, dir.x, 1, dir.z); + if ((cost += getMiningDurationTicks(this, target1, toBreak)) >= COST_INF) return; - const target2 = this.getBlockInfo(node, dir.x, 2, dir.z) - if ((cost += getMiningDurationTicks(this, target2)) >= COST_INF) return + const target2 = this.getBlockInfo(node, dir.x, 2, dir.z); + if ((cost += getMiningDurationTicks(this, target2, toBreak)) >= COST_INF) return; - cost += 1 + // cost += 1 + storage.push(Move.fromPrevious(cost, target1.position, node, this, toPlace, toBreak)); } } export class MovementDescend extends MovementProvider { - movementDirs = [new Vec3(0, -1, 0)] - provideMovements (start: Move, storage: Move[], goal: Goal, closed: Set): void { + movementDirs = [new Vec3(0, -1, 0)]//, new Vec3(0, -1, 1), new Vec3(0, -1, -1), new Vec3(1, -1, 0), new Vec3(-1, -1, 0)]; + provideMovements(start: Move, storage: Move[], goal: Goal, closed: Set): void { for (const dir of this.movementDirs) { - this.provideDescend(start, dir, storage, closed) + this.provideDescend(start, dir, storage, closed); } } - provideDescend (node: Move, dir: Vec3, storage: Move[], closed: Set): void { - const srcN1 = this.getBlockInfo(node, dir.x, -1, dir.z) - if (srcN1.climbable) return + provideDescend(node: Move, dir: Vec3, storage: Move[], closed: Set): void { + + const toBreak: BreakHandler[] = []; - const srcN2 = this.getBlockInfo(node, dir.x, -2, dir.z) + + const srcN1 = this.getBlockInfo(node, dir.x, -1, dir.z); + if (srcN1.climbable) return; + + const srcN2 = this.getBlockInfo(node, dir.x, -2, dir.z); if (!canWalkOn(srcN2)) { return // for now, do not calculate this movement as it will be handled by movementFall. // this.dynamicFallCosts(srcN2, cost); } if (canUseFrostWalker(this, srcN2)) { - return + return; } - let cost = 0 + let cost = 0; - const destN1 = this.getBlockInfo(node, dir.x, -1, dir.z) - if ((cost += getMiningDurationTicks(this, destN1)) >= COST_INF) return + const destN1 = this.getBlockInfo(node, dir.x, -1, dir.z); - const dest = this.getBlockInfo(node, dir.x, 0, dir.z) - if ((cost += getMiningDurationTicks(this, dest)) >= COST_INF) return + + if ((cost += getMiningDurationTicks(this, destN1, toBreak)) >= COST_INF) return; - const dest1 = this.getBlockInfo(node, dir.x, 1, dir.z) - if ((cost += getMiningDurationTicks(this, dest1, true)) >= COST_INF) return + const dest = this.getBlockInfo(node, dir.x, 0, dir.z); + if ((cost += getMiningDurationTicks(this, dest, toBreak)) >= COST_INF) return; + + const dest1 = this.getBlockInfo(node, dir.x, 1, dir.z); + if ((cost += getMiningDurationTicks(this, dest1, toBreak)) >= COST_INF) return; - let walk = WALK_OFF_BLOCK_COST + let walk = WALK_OFF_BLOCK_COST; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion if (srcN1.block!.type === BlockInfo.soulsandId) { - walk = WALK_ONE_OVER_SOUL_SAND_COST / WALK_ONE_BLOCK_COST + walk = WALK_ONE_OVER_SOUL_SAND_COST / WALK_ONE_BLOCK_COST; } - cost += walk - cost += Math.max(FALL_N_BLOCKS_COST[1], CENTER_AFTER_FALL_COST) + cost += walk; + cost += Math.max(FALL_N_BLOCKS_COST[1], CENTER_AFTER_FALL_COST); + storage.push(Move.fromPrevious(cost, destN1.position, node, this, [], toBreak)); } // TODO: implement mutables - dynamicFallCosts (info: BlockInfo, cost: number): void { - - } + dynamicFallCosts(info: BlockInfo, cost: number): void {} } export class MovementDiagonal extends MovementProvider { movementDirs = MovementProvider.diagonalDirs provideMovements (start: Move, storage: Move[], goal: Goal, closed: Set): void { + for (const dir of this.movementDirs) { + this.provideDiagonal(start, dir, storage, closed) + } + } + + provideDiagonal(node: Move, dir: Vec3, storage: Move[], closed: Set) { + const toBreak: BreakHandler[] = [] + const toPlace: PlaceHandler[] = [] + + const dest1 = this.getBlockInfo(node, dir.x, 1, dir.z) + if (!canWalkThrough(dest1)) return + + + const dest0 = this.getBlockInfo(node, dir.x, 0, dir.z) + + if (!canWalkThrough(dest0)) { + return // handle in a diagonal ascension movement + } + + // else + + const destWalkOn = this.getBlockInfo(node, dir.x, -1, dir.z) + const fromDown = this.getBlockInfo(node, 0, -1, 0) + const isStandingOnABlock = mustBeSolidToWalkOn(fromDown) + } } diff --git a/src/mineflayer-specific/movements/baritone/movementHelper.ts b/src/mineflayer-specific/movements/baritone/movementHelper.ts index 4a69ca9..59c2d26 100644 --- a/src/mineflayer-specific/movements/baritone/movementHelper.ts +++ b/src/mineflayer-specific/movements/baritone/movementHelper.ts @@ -2,6 +2,7 @@ import { Vec3 } from 'vec3' import { BlockInfo } from '../../world/cacheWorld' import { Movement } from '../movement' import { Vec3Properties } from '../../../types' +import { BreakHandler } from '../interactionUtils' export function canWalkOn (info: BlockInfo): boolean { if (info.block == null) return false @@ -22,9 +23,6 @@ const ALL_DIRS_BUT_UP = [ ] export function findPlaceOpts (move: Movement, orgPos: Vec3Properties, pos: Vec3Properties): BlockInfo | null { for (const dir of ALL_DIRS_BUT_UP) { - const nX = pos.x + dir.x - const nZ = pos.z + dir.z - if (nX === orgPos.x && nZ === orgPos.z) continue const info = move.getBlockInfo(pos, dir.x, dir.y, dir.z) if (canPlaceAgainst(info)) return info } @@ -40,17 +38,30 @@ export function isBottomSlab (info: BlockInfo): boolean { return info.dY === 0.5 } -export function getMiningDurationTicks (move: Movement, info: BlockInfo, includeFalling = false): number { - if (!includeFalling) return move.breakCost(info) +export function getMiningDurationTicks (move: Movement, info: BlockInfo, toBreak: BreakHandler[], includeFalling = false): number { + if (!includeFalling) return move.safeOrBreak(info, toBreak) const above = move.getBlockInfo(info.position, 0, 1, 0) - return move.breakCost(info) + getMiningDurationTicks(move, above, true) // recurse upwards. potentially slow. + return move.safeOrBreak(info, toBreak) + getMiningDurationTicks(move, above, toBreak, true) // recurse upwards. potentially slow. } -export function getMiningDurationTicksCoords (move: Movement, pos: Vec3, includeFalling = false): number { - return getMiningDurationTicks(move, move.getBlockInfoRaw(pos), includeFalling) +export function getMiningDurationTicksCoords (move: Movement, pos: Vec3, toBreak: BreakHandler[], includeFalling = false): number { + return getMiningDurationTicks(move, move.getBlockInfoRaw(pos), toBreak, includeFalling) } export function canUseFrostWalker (move: Movement, info: BlockInfo): boolean { return info.liquid && false // TODO: frostwalker. } + + +export function mustBeSolidToWalkOn(info: BlockInfo) { + if (!BlockInfo.initialized) throw new Error('BlockInfo not initialized') + + if (info.block == null) return false + + if (info.block.type === BlockInfo.registry.blocksByName.ladder.id) return false + if (info.block.type === BlockInfo.registry.blocksByName.vine.id) return false + + // TODO: check waterlogging + return true +} \ No newline at end of file diff --git a/src/mineflayer-specific/movements/movement.ts b/src/mineflayer-specific/movements/movement.ts index 9f97e2c..d5df46c 100644 --- a/src/mineflayer-specific/movements/movement.ts +++ b/src/mineflayer-specific/movements/movement.ts @@ -222,7 +222,9 @@ export abstract class Movement { // if (block.breakCost !== undefined) return block.breakCost // cache breaking cost. if (block.walkthrough) { - // if (!block.replaceable) toBreak.push(BreakHandler.fromVec(block.position, "solid")); + if (!block.replaceable) { + toBreak.push(BreakHandler.fromVec(block.position, "solid")); + } return 0 // TODO: block is a carpet or a climbable (BUG) } @@ -262,7 +264,9 @@ export abstract class Movement { if (this.currentMove.remainingBlocks <= 0) return COST_INF if (block.block === null) return COST_INF // Don't know its type, but that's only replaceables so just return. - if (block.solidFull) return 0 // block is already physical at location. + if (block.solidFull) { + return 0 // block is already physical at location. + } const cost = this.placeCost(block) diff --git a/src/mineflayer-specific/movements/movementProvider.ts b/src/mineflayer-specific/movements/movementProvider.ts index 1233c75..0e9bbed 100644 --- a/src/mineflayer-specific/movements/movementProvider.ts +++ b/src/mineflayer-specific/movements/movementProvider.ts @@ -60,25 +60,25 @@ export abstract class MovementProvider extends Movement { getBlockInfoRaw (yes: Vec3): BlockInfo { // - // let move: Move | undefined = this.currentMove - - // let i = 0 - // while (move !== undefined && i++ < 3) { // 5 levels - - // for (const m of move.toPlace) { - // if (m.x === yes.x && m.y === yes.y && m.z === yes.z) { - // return m.blockInfo - // } - // } + let move: Move | undefined = this.currentMove + + let i = 0 + while (move !== undefined && i++ < 5) { // 5 levels + + for (const m of move.toPlace) { + if (m.x === yes.x && m.y === yes.y && m.z === yes.z) { + return m.blockInfo + } + } - // for (const m of move.toBreak) { - // if (m.x === yes.x && m.y === yes.y && m.z === yes.z) { - // return m.blockInfo - // } - // } + for (const m of move.toBreak) { + if (m.x === yes.x && m.y === yes.y && m.z === yes.z) { + return m.blockInfo + } + } - // move = move.parent - // } + move = move.parent + } // if (i > 0) console.log('i', i) // const wantedDx = pos.x - this.orgPos.x + dx + this.halfway[0] diff --git a/src/mineflayer-specific/world/cacheWorld.ts b/src/mineflayer-specific/world/cacheWorld.ts index 8752604..89d4bc7 100644 --- a/src/mineflayer-specific/world/cacheWorld.ts +++ b/src/mineflayer-specific/world/cacheWorld.ts @@ -16,6 +16,9 @@ import pBlock from 'prismarine-block' export class BlockInfo { static initialized = false + static PBlock: BlockType + static registry: MCData + static readonly interactableBlocks = new Set() static readonly blocksCantBreak = new Set() static readonly blocksToAvoid = new Set() @@ -32,7 +35,7 @@ export class BlockInfo { static readonly mlgItems = new Set() static readonly INVALID: BlockInfo = new BlockInfo(false, false, false, false, false, false, false, 0, false, new Vec3(0, 0, 0), -1) - static PBlock: BlockType + static _waterBlock: Block static _solidBlock: Block @@ -84,6 +87,7 @@ export class BlockInfo { static init (registry: MCData): void { if (BlockInfo.initialized) return BlockInfo.initialized = true + BlockInfo.registry = registry BlockInfo.soulsandId = registry.blocksByName.soul_sand.id // might be broke, who knows @@ -234,7 +238,7 @@ export class BlockInfo { ) } else { return new BlockInfo( - false, + BlockInfo.replaceables.has(b.type), false, true, true,