46 lines
2.3 KiB
TypeScript
46 lines
2.3 KiB
TypeScript
import type {Bot} from '@wp2508/mineflayer';
|
|
import type {BaseFunction, FunctionArgument} from '../../../types/bot/function/function.ts';
|
|
import {Mutex} from 'async-mutex';
|
|
import {cancellation_generation} from '../cancellation.ts';
|
|
|
|
const locks = new WeakMap<Bot, Mutex>();
|
|
|
|
export class init implements BaseFunction<number[]> {
|
|
readonly name = 'slot_switch_slot';
|
|
readonly i18n = {
|
|
lang: 'zh-CN', name: '物品交换', description: '依次左键点击源槽位、目标槽位,并将鼠标剩余物品放回源槽位;同类物品按原生规则合并',
|
|
};
|
|
readonly args: FunctionArgument[] = [
|
|
{name: 'slot', type: 'number', i18n: {lang: 'zh-CN', name: '物品槽位', description: '第一个槽位编号'}},
|
|
{name: 'new_slot', type: 'number', i18n: {lang: 'zh-CN', name: '目标槽位', description: '第二个槽位编号'}},
|
|
];
|
|
|
|
async run(bot: Bot, args: number[]): Promise<boolean> {
|
|
if (!Array.isArray(args) || args.length !== 2 || !args.every(Number.isSafeInteger)) return false;
|
|
const window = bot.currentWindow ?? bot.inventory;
|
|
if (!window) return false;
|
|
const generation = cancellation_generation(bot);
|
|
const active = () => cancellation_generation(bot) === generation;
|
|
let lock = locks.get(bot);
|
|
if (!lock) locks.set(bot, lock = new Mutex());
|
|
return lock.runExclusive(async () => {
|
|
const [slot, new_slot] = args;
|
|
if (!active() || (bot.currentWindow ?? bot.inventory) !== window || window.selectedItem
|
|
|| slot === new_slot || args.some(value => value < 0 || value >= window.slots.length)) return false;
|
|
try {
|
|
await bot.clickWindow(slot, 0, 0);
|
|
if (!active() || (bot.currentWindow ?? bot.inventory) !== window) return false;
|
|
await bot.clickWindow(new_slot, 0, 0);
|
|
if (!active() || (bot.currentWindow ?? bot.inventory) !== window) return false;
|
|
// An empty cursor means a final click would pick the source item up again.
|
|
if (window.selectedItem) {
|
|
await bot.clickWindow(slot, 0, 0);
|
|
}
|
|
return active() && (bot.currentWindow ?? bot.inventory) === window && !window.selectedItem;
|
|
} catch {
|
|
return false;
|
|
}
|
|
});
|
|
}
|
|
}
|