From 0990557f8135381cf1d20cebb99c745227a170ba Mon Sep 17 00:00:00 2001 From: XaXayo12 <257781493+XaXayo12@users.noreply.github.com> Date: Fri, 19 Jun 2026 17:57:46 +0200 Subject: [PATCH] fix(costs): price horizontal water moves at the water cost (not land + flat add) Review catch (chatgpt-codex): Forward/Diagonal seeded the move with travelCost() at land speed and then added a flat liquidCost. With sprinting on (the default) a one-block water move came to ~8.02 ticks instead of the 9.09 water cost, and the flat add did not scale, so diagonal water moves were undercharged even more. Paths could prefer water because it was priced too cheaply. travelCost(blocks, inLiquid) now returns WALK_ONE_IN_WATER_COST * blocks when in liquid (you swim, can't sprint/walk), which is correct and scales with distance. Forward and Diagonal pass inLiquid and no longer add the flat liquidCost. The vertical providers (jump/drop/up/down) are unchanged. --- src/mineflayer-specific/movements/movement.ts | 9 ++++++--- .../movements/movementProviders.ts | 14 ++++++++------ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/mineflayer-specific/movements/movement.ts b/src/mineflayer-specific/movements/movement.ts index c7d471a..95eb82c 100644 --- a/src/mineflayer-specific/movements/movement.ts +++ b/src/mineflayer-specific/movements/movement.ts @@ -259,10 +259,13 @@ export abstract class Movement { /** * Ticks to travel `blocks` blocks of flat ground. * - * The bot sprints when allowed (the fastest way to move), otherwise it walks. - * Pass `1` for one straight block, `Math.SQRT2` for one diagonal block, etc. + * On land the bot sprints when allowed (the fastest way to move), otherwise it + * walks. In water it can do neither, so it is priced at the (much slower) swim + * speed, which is why callers pass `inLiquid`. Pass `1` for one straight block, + * `Math.SQRT2` for one diagonal block, etc. */ - travelCost (blocks: number): number { + travelCost (blocks: number, inLiquid = false): number { + if (inLiquid) return blocks * WALK_ONE_IN_WATER_COST return blocks * (this.settings.allowSprinting ? SPRINT_ONE_BLOCK_COST : WALK_ONE_BLOCK_COST) } diff --git a/src/mineflayer-specific/movements/movementProviders.ts b/src/mineflayer-specific/movements/movementProviders.ts index cd7eaef..95db898 100644 --- a/src/mineflayer-specific/movements/movementProviders.ts +++ b/src/mineflayer-specific/movements/movementProviders.ts @@ -48,9 +48,10 @@ export class Forward extends MovementProvider { getMoveForward (start: Move, dir: Vec3, neighbors: Move[]): void { const pos = start.cachedVec - let cost = this.travelCost(1) // sprint/walk one block forward - - if (this.getBlockInfo(pos, 0, 0, 0).liquid) cost += this.settings.liquidCost + // In water the bot swims (no sprint/walk), so price the block at the water + // cost itself rather than land speed + a flat add (which undercharged it). + const inLiquid = this.getBlockInfo(pos, 0, 0, 0).liquid + let cost = this.travelCost(1, inLiquid) const blockC = this.getBlockInfo(pos, dir.x, 0, dir.z) if (blockC.isInvalid) return // out of range. @@ -100,7 +101,10 @@ export class Diagonal extends MovementProvider { } getMoveDiagonal (node: Move, dir: Vec3, neighbors: Move[], goal: goals.Goal): void { - let cost = this.travelCost(Math.SQRT2) // one diagonal block is sqrt(2) blocks of travel + // In water the bot swims (no sprint/walk); price the diagonal at the water + // cost, which also scales with the sqrt(2) distance (a flat add did not). + const inLiquid = this.getBlockInfo(node, 0, 0, 0).liquid + let cost = this.travelCost(Math.SQRT2, inLiquid) const block0 = this.getBlockInfo(node, dir.x, 0, dir.z) @@ -108,8 +112,6 @@ export class Diagonal extends MovementProvider { if (!block0.walkthrough) return - if (this.getBlockInfo(node, 0, 0, 0).liquid) cost += this.settings.liquidCost - const toBreak: BreakHandler[] = [] const toPlace: PlaceHandler[] = [] const block00 = this.getBlockInfo(node, 0, 0, 0)