[plugin/control] add .ladderAscend()

This commit is contained in:
方而静 2023-11-01 13:32:05 +08:00
parent 4651ebc5c8
commit f6aa131caa
Signed by: szTom
GPG Key ID: 072D999D60C6473C
2 changed files with 81 additions and 8 deletions

View File

@ -72,10 +72,10 @@ async function main() {
return bot.players[args.owner];
};
context.debug = debug;
context.sc = {};
context.sc.pos = () => bot.entity.position;
context.sc.debug_enable = (module) => debug.enable(module);
context.sc.debug_disable = (module) => debug.disable(module);
context.sc.debug_mfc = () => debug.enable('mineflayer-control');
context.sc.q = () => bot.quit();
context.sc.sleep = asyncSleep;
}

View File

@ -1,6 +1,7 @@
import debug from 'debug';
import { Queue, Task, isIterable } from 'compass-utils';
import { Vec3 } from 'vec3';
import assert from 'node:assert/strict';
const logger = debug('mineflayer-control');
// yaw = axis * Math.PI / 2
@ -27,10 +28,12 @@ export const AXIS_UNIT = {
3: new Vec3(1, 0, 0),
};
AXIS_UNIT['-Z'] = AXIS_UNIT['NORTH'] = AXIS_UNIT[0];
AXIS_UNIT['-X'] = AXIS_UNIT['WEST'] = AXIS_UNIT[1];
AXIS_UNIT['+Z'] = AXIS_UNIT['SOUTH'] = AXIS_UNIT[2];
AXIS_UNIT['+X'] = AXIS_UNIT['EAST'] = AXIS_UNIT[3];
export const AXIS_NAME = {
0: '-Z',
1: '-X',
2: '+Z',
3: '+X',
};
export const MOVE_LEVEL = {
WALK: 1,
@ -96,6 +99,10 @@ export class MovePathBlockedError extends Error {
async function moveAxisTask(bot, task, axis_raw, target_raw, level) {
const axis = AXIS[axis_raw];
assert.equal(typeof axis, 'number', 'axis');
assert.ok(0 <= axis && axis <= 3, 'axis');
assert.equal(typeof level, 'number', 'level');
assert.ok(target instanceof Vec3, 'target');
const stable_axis = "xz"[axis % 2];
const target = target_raw.clone();
adjustXZ(target);
@ -166,7 +173,7 @@ async function moveAxisTask(bot, task, axis_raw, target_raw, level) {
let pos5t = pos_queue.front();
if (pos.distanceSquared(pos5t) < Number.EPSILON) {
logger('moveAxisTask() position changed too little.');
logger(`moveAxisTask() position 5 ticks ago: ${pos5t}.`);
logger(`moveAxisTask() position ${TRACK_TICKS} ticks ago: ${pos5t}.`);
logger(`moveAxisTask() position now: ${pos}.`);
throw new MovePathBlockedError();
}
@ -175,7 +182,7 @@ async function moveAxisTask(bot, task, axis_raw, target_raw, level) {
delta.update(target.minus(pos));
remaining_dis = delta.dot(AXIS_UNIT[axis]);
if (Math.abs(remaining_dis) <= 0.5) {
logger('moveAxisTask() very close to target now.');
logger(`moveAxisTask() very close! remain: ${remaining_dis}.`);
pos.x = target.x;
pos.z = target.z;
bot.entity.velocity.x = 0;
@ -192,6 +199,58 @@ async function moveAxisTask(bot, task, axis_raw, target_raw, level) {
task._ready(time_used);
}
async function ladderAscendTask(bot, task, target_y) {
assert.equal(typeof target_y, 'number', 'target_y');
bot.control.adjustXZ();
const start_pos = bot.entity.position.clone();
logger(`ladderAscendTask() initial position: ${start_pos}.`);
logger(`ladderAscendTask() target y: ${target_y}.`);
if (start_pos.y > target_y) {
throw new Error('Invalid Argument: target_y is smaller than current y.');
}
let controls = new ControlState('jump');
controls.apply(bot);
logger('ladderAscendTask() started.');
const TRACK_TICKS = 10;
let time_used = 0, last_y = start_pos.y;
do {
await bot.waitForTicks(1);
task._interuptableHere();
time_used += 1;
const pos = bot.entity.position;
if (pos.xzDistanceTo(start_pos) > 1) { throw new MoveInterferedError(); }
bot.control.adjustXZ();
if (Math.abs(pos.y - target_y) < 0.2) {
logger('ladderAscendTask() reached.');
bot.clearControlStates();
pos.y = target_y;
break;
}
if (pos.y - target_y > 0.4) {
logger('ladderAscendTask() went past target.');
throw new MoveInterferedError();
}
if (time_used % TRACK_TICKS == 0) {
let now_y = pos.y;
if (Math.abs(now_y - last_y) < 0.3) {
logger(`ladderAscendTask() move too little in past ${TRACK_TICKS} ticks!`);
logger(`ladderAscendTask() now pos.y=${now_y}`);
logger(`ladderAscendTask() ${TRACK_TICKS} ticks ago pos.y=${last_y}`);
throw new MovePathBlockedError();
}
last_y = now_y;
}
} while (true);
task._ready(time_used);
}
export default function inject(bot) {
bot.control = {};
bot.control.getState = () => { return ControlState.from(bot.controlState); };
@ -268,4 +327,18 @@ export default function inject(bot) {
await bot.waitForTicks(1);
bot.setControlState('jump', false);
};
bot.control.ladderAscend = (target_y) => {
let task = new Task();
queueMicrotask(async () => {
try {
task._start();
await ladderAscendTask(bot, task, target_y);
} catch(err) {
bot.clearControlStates();
task._fail(err);
}
});
return task;
};
}