fix(lite): align long walks with browser client

This commit is contained in:
max bittker committed 2026-08-08 23:51:27 -04:00
1 parent 933fe0dbe0
commit 6fd02c9fb5
3 files changed
+39 -9

No files matched your search

+13 -3
View File
@@ -632,11 +632,21 @@ export class LiteClient {
/** Send a MOVE_GAMECLICK with a client-computed path. See movement.ts. */
walkTo(worldX: number, worldZ: number, running = false): boolean {
const dest = this.toSceneTile(worldX, worldZ);
if (!dest || !this.localPlayer) {
if (!this.localPlayer) {
return false;
}
return findPathToTile(this, dest.x, dest.z, running);
// Match Client.walkTo: a long-distance BotActions route can hand the
// client a global waypoint beyond its current 104x104 build area. Walk
// to the corresponding scene edge; crossing it causes REBUILD_NORMAL,
// after which BotActions observes progress and dispatches the next leg.
// Keeping the one-tile border excluded also matches the browser's
// collision bounds (tiles 0 and 103 are the blocked border ring).
const minBound = 1;
const maxBound = BuildArea.SIZE - 2;
const destX = Math.max(minBound, Math.min(maxBound, worldX - this.mapBuildBaseX));
const destZ = Math.max(minBound, Math.min(maxBound, worldZ - this.mapBuildBaseZ));
return findPathToTile(this, destX, destZ, running);
}
// ------------------------------------------------------ outgoing plumbing
@@ -19,6 +19,7 @@ import { beforeAll, describe, expect, test } from 'bun:test';
import './dom-shim.js';
import CollisionMap from '#/dash3d/CollisionMap.js';
import { ClientProt } from '#/io/ClientProt.js';
import Packet from '#/io/Packet.js';
import { ServerProt } from '#/io/ServerProt.js';
@@ -251,4 +252,28 @@ describe('outgoing action encoding', () => {
expect(r.g2()).toBe(9);
expect(r.g2()).toBe(INV_COMPONENT);
});
test('long walks clamp to the current scene edge like the browser client', () => {
if (!available) {
return;
}
const c = makeClient('bota');
c.mapBuildBaseX = 3200;
c.mapBuildBaseZ = 3200;
c.collision[0] = new CollisionMap();
c.localPlayer!.routeX[0] = 50;
c.localPlayer!.routeZ[0] = 50;
const start = c.out.pos;
expect(c.walkTo(4000, 3250, true)).toBe(true);
const r = new Capture(c.out, start);
expect(r.g1()).toBe(ClientProt.MOVE_GAMECLICK);
expect(r.g1()).toBe(5); // one turn: run flag + absolute x/z
expect(r.g1()).toBe(1); // running
expect(r.g2()).toBe(3302); // baseX + build-area max interior tile
expect(r.g2()).toBe(3250);
expect(r.at).toBe(c.out.pos);
});
});
+1 -6
View File
@@ -12,7 +12,6 @@
import { startSession, type LiteSession } from './session.js';
import { type ActionResult } from '#/bot/ActionExecutor.js';
import { formatWorldStateForAgent } from '#/bot/formatters.js';
import { BotActionQueue, type QueuedBotAction } from '#/bot/ActionQueue.js';
import type { BotAction } from '#/bot/types.js';
import type { LiteClient } from './LiteClient.js';
@@ -223,11 +222,7 @@ class LiteGatewayRunner {
if (!this.wsConnected) return;
const state = this.client.collectBotState(this.serverTick);
if (!state) return;
this.send({
type: 'state',
state,
formattedState: formatWorldStateForAgent(state, 'SDK Control')
});
this.send({ type: 'state', state });
}
}