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(); export class init implements BaseFunction { public name = "slot_to_slot"; public i18n = { lang: "zh-CN", name: "物品移动", description: "将物品从一个槽位移动到另一个槽位, 目标槽位必须为空" } public 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 { if (!Array.isArray(args) || args.length !== 2 || !args.every(Number.isSafeInteger)) { return false; } const [slot, new_slot] = args; 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 () => { if (!active() || (bot.currentWindow ?? bot.inventory) !== window) return false; if ([slot, new_slot].some(value => value < 0 || value >= window.slots.length)) { return false; } if (slot === new_slot || !window.slots[slot] || window.slots[new_slot] || window.selectedItem) return false; try { await bot.clickWindow(slot, 0, 0); // Never apply the destination click to a replacement window. if (!active() || (bot.currentWindow ?? bot.inventory) !== window || window.slots[new_slot]) return false; await bot.clickWindow(new_slot, 0, 0); return active(); } catch { return false; } }); } }