[plugin/flyctl] add .ascend()
This commit is contained in:
parent
a6f5d0062a
commit
6df6dbcaf6
@ -57,6 +57,7 @@ async function main() {
|
|||||||
await waitEvent(bot, 'inject_allowed');
|
await waitEvent(bot, 'inject_allowed');
|
||||||
bot.loadPlugin((await import('mineflayer-event-promise')).default);
|
bot.loadPlugin((await import('mineflayer-event-promise')).default);
|
||||||
bot.loadPlugin((await import('mineflayer-control')).default);
|
bot.loadPlugin((await import('mineflayer-control')).default);
|
||||||
|
bot.loadPlugin((await import('mineflayer-fly-control')).default);
|
||||||
await bot.waitEvent('spawn');
|
await bot.waitEvent('spawn');
|
||||||
|
|
||||||
async function loadReplContextModules(context) {
|
async function loadReplContextModules(context) {
|
||||||
@ -76,8 +77,10 @@ async function main() {
|
|||||||
context.sc = {};
|
context.sc = {};
|
||||||
context.sc.pos = () => bot.entity.position;
|
context.sc.pos = () => bot.entity.position;
|
||||||
context.sc.debug_mfc = () => debug.enable('mineflayer-control');
|
context.sc.debug_mfc = () => debug.enable('mineflayer-control');
|
||||||
|
context.sc.debug_mff = () => debug.enable('mineflayer-fly-control');
|
||||||
context.sc.q = () => bot.quit();
|
context.sc.q = () => bot.quit();
|
||||||
context.sc.sleep = asyncSleep;
|
context.sc.sleep = asyncSleep;
|
||||||
|
context.sc.tossHeld = () => bot.tossStack(bot.heldItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!args.noRepl) {
|
if (!args.noRepl) {
|
||||||
@ -89,6 +92,8 @@ async function main() {
|
|||||||
terminal: true,
|
terminal: true,
|
||||||
ignoreUndefined: true,
|
ignoreUndefined: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
r.on('exit', () => bot.quit());
|
||||||
loadReplContextModules(r.context);
|
loadReplContextModules(r.context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,8 +14,7 @@
|
|||||||
"mineflayer-event-promise": "file:plugin/event-promise",
|
"mineflayer-event-promise": "file:plugin/event-promise",
|
||||||
"compass-utils": "file:utils",
|
"compass-utils": "file:utils",
|
||||||
"mineflayer-control": "file:plugin/control",
|
"mineflayer-control": "file:plugin/control",
|
||||||
"mineflayer-pathfinder": "^2.4.5",
|
"mineflayer-fly-control": "file:plugin/fly-control",
|
||||||
"prismarine-viewer": "^1.25.0",
|
|
||||||
"yargs": "^17.7.2"
|
"yargs": "^17.7.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
146
plugin/fly-control/index.mjs
Normal file
146
plugin/fly-control/index.mjs
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import debug from 'debug';
|
||||||
|
import { Task } from 'compass-utils';
|
||||||
|
const logger = debug('mineflayer-fly-control');
|
||||||
|
|
||||||
|
export class ElytraNotEquippedError extends Error {
|
||||||
|
constructor() { super('Elytra is not equipped!'); }
|
||||||
|
}
|
||||||
|
|
||||||
|
export class InsufficientRocketError extends Error {
|
||||||
|
constructor(flight_requirement, flight_actual) {
|
||||||
|
super(`Expected ${flight_requirement} flight in total, got ${flight_actual}`);
|
||||||
|
this.flight_requirement = flight_requirement;
|
||||||
|
this.flight_actual = flight_actual;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export class AlreadyElytraFlyingError extends Error {
|
||||||
|
constructor() { super('Already elytra flying!'); }
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fireworkFlight(firework_item) {
|
||||||
|
return firework_item?.nbt?.value?.Fireworks?.value?.Flight?.value ?? 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function takeOffTask(bot, task) {
|
||||||
|
if (bot.entity.elytraFlying) { throw new AlreadyElytraFlyingError(); }
|
||||||
|
if (bot.entity.onGround) {
|
||||||
|
await task._waitDependent(bot.control.jumpToHighest());
|
||||||
|
task._interuptableHere();
|
||||||
|
}
|
||||||
|
|
||||||
|
await bot.elytraFly();
|
||||||
|
task._interuptableHere();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ascendTask(bot, task, flight, gracefulMode) {
|
||||||
|
assert.ok(typeof flight == 'number');
|
||||||
|
bot.control.adjustXZ();
|
||||||
|
await bot.look(0, Math.PI / 2, true);
|
||||||
|
task._interuptableHere();
|
||||||
|
|
||||||
|
if (!bot.entity.elytraFlying) { await takeOffTask(bot, task); }
|
||||||
|
await bot.waitForTicks(1);
|
||||||
|
task._interuptableHere();
|
||||||
|
|
||||||
|
function gracefulModePredicate() {
|
||||||
|
return bot.entity.velocity.y >= 0.01;
|
||||||
|
}
|
||||||
|
|
||||||
|
function fastModePredicate() {
|
||||||
|
return bot.fireworkRocketDuration > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const predicate = gracefulMode ? gracefulModePredicate : fastModePredicate;
|
||||||
|
|
||||||
|
let flight_pre_rocket = fireworkFlight(bot.heldItem);
|
||||||
|
for (let i = 0; i < flight; i += flight_pre_rocket) {
|
||||||
|
bot.activateItem();
|
||||||
|
do {
|
||||||
|
await bot.waitForTicks(Math.max(1, bot.fireworkRocketDuration));
|
||||||
|
task._interuptableHere();
|
||||||
|
} while (predicate());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function inject(bot) {
|
||||||
|
const firework_id = bot.registry.itemsByName.firework_rocket.id;
|
||||||
|
const elytra_id = bot.registry.itemsByName.elytra.id;
|
||||||
|
const elytra_slot = bot.getEquipmentDestSlot('torso');
|
||||||
|
|
||||||
|
bot.flyctl = {};
|
||||||
|
bot.flyctl.skipValidation = false;
|
||||||
|
function beforeFlyValidation(flight_requirement = 0) {
|
||||||
|
assert.ok(typeof flight_requirement == 'number');
|
||||||
|
assert.ok(flight_requirement >= 0);
|
||||||
|
|
||||||
|
if (bot.flyctl.skipValidation) {
|
||||||
|
logger('beforeFlyValidation() skipped.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger(`beforeFlyValidation() elytra slot: ${elytra_slot}`);
|
||||||
|
let elytra_slot_item = bot.inventory.slots[elytra_slot]?.type;
|
||||||
|
if (elytra_slot_item != elytra_id) {
|
||||||
|
logger(`beforeFlyValidation() failed: elytra slot found ${elytra_slot_item}.`);
|
||||||
|
logger(`beforeFlyValidation() expected ${elytra_id}.`);
|
||||||
|
throw new ElytraNotEquippedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flight_requirement > 0) {
|
||||||
|
let rocket_item = bot.heldItem;
|
||||||
|
if (rocket_item?.type != firework_id) {
|
||||||
|
logger('beforeFlyValidation() failed: holding is not rocket.');
|
||||||
|
logger(`beforeFlyValidation() found ${rocket_item?.type} expected ${firework_id} .`);
|
||||||
|
throw new InsufficientRocketError(flight_requirement, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let flight_sum = rocket_item.count * fireworkFlight(rocket_item);
|
||||||
|
if (flight_sum < flight_requirement) {
|
||||||
|
throw new InsufficientRocketError(flight_requirement, flight_sum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger('beforeFlyValidation() passed.');
|
||||||
|
}
|
||||||
|
|
||||||
|
bot.flyctl.prepare = async () => {
|
||||||
|
await bot.equip(elytra_id, 'torso');
|
||||||
|
await bot.equip(firework_id);
|
||||||
|
};
|
||||||
|
|
||||||
|
bot.flyctl.ascend = async (flight = 1, gracefulMode = true) => {
|
||||||
|
let task = new Task();
|
||||||
|
queueMicrotask(async () => {
|
||||||
|
try {
|
||||||
|
beforeFlyValidation(flight);
|
||||||
|
task._ready(await ascendTask(bot, task, flight, gracefulMode));
|
||||||
|
} catch(err) {
|
||||||
|
task._fail(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return task;
|
||||||
|
};
|
||||||
|
|
||||||
|
bot.flyctl.gracefulAscend = (flight = 1) => {
|
||||||
|
return bot.flyctl.ascend(flight, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
bot.flyctl.fastAscend = (flight = 1) => {
|
||||||
|
return bot.flyctl.ascend(flight, false);
|
||||||
|
};
|
||||||
|
|
||||||
|
bot.flyctl.takeOff = () => {
|
||||||
|
let task = new Task();
|
||||||
|
queueMicrotask(async () => {
|
||||||
|
try {
|
||||||
|
beforeFlyValidation(flight);
|
||||||
|
task._ready(await takeOffTask(bot, task));
|
||||||
|
} catch(err) {
|
||||||
|
task._fail(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return task;
|
||||||
|
};
|
||||||
|
}
|
11
plugin/fly-control/package.json
Normal file
11
plugin/fly-control/package.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"name": "mineflayer-fly-control",
|
||||||
|
"description": "High-level & handy API for mineflayer bot elytra flying.",
|
||||||
|
"type": "module",
|
||||||
|
"main": "index.mjs",
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "^4.3.4",
|
||||||
|
"vec3": "^0.1.8",
|
||||||
|
"compass-utils": "file:../../utils"
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user