import assert from 'node:assert/strict'; import {createRequire} from 'node:module'; import test from 'node:test'; import {tsImport} from 'tsx/esm/api'; const {init: DropAll} = await tsImport('../bot/function/item/drop_slot_all_item.ts', import.meta.url); const {init: DropNumber} = await tsImport('../bot/function/item/drop_slot_item_number.ts', import.meta.url); const {init: UseItem} = await tsImport('../bot/function/item/use_item.ts', import.meta.url); const require = createRequire(import.meta.url); const mf = createRequire(require.resolve('@wp2508/mineflayer')); const registry = mf('prismarine-registry')('1.21.4'); const windows = mf('prismarine-windows')(registry); const Item = mf('prismarine-item')(registry); function botFixture(container = false) { const inventory = windows.createWindow(0, 'minecraft:inventory', 'Inventory'); const currentWindow = container ? windows.createWindow(1, 'minecraft:generic_9x3', 'Chest') : null; const window = currentWindow ?? inventory; window.updateSlot(9, new Item(1, 5)); const clicks = []; return {inventory, currentWindow, clicks, async clickWindow(slot, mouseButton, mode) { clicks.push([slot, mouseButton, mode]); window.acceptClick({slot, mouseButton, mode, item: window.slots[slot]}, 0); }}; } test('drop functions use native drop clicks in inventory and container without closing', async () => { for (const container of [false, true]) { const bot = botFixture(container); const window = bot.currentWindow ?? bot.inventory; assert.equal(await new DropNumber().run(bot, [9, 2]), true); assert.equal(window.slots[9].count, 3); assert.deepEqual(bot.clicks, [[9, 0, 4], [9, 0, 4]]); assert.equal(await new DropAll().run(bot, [9]), true); assert.equal(window.slots[9], null); assert.deepEqual(bot.clicks.at(-1), [9, 1, 4]); assert.equal(await new DropAll().run(bot, [9]), false); } const bot = botFixture(); assert.equal(await new DropNumber().run(bot, [9, 100]), true); assert.equal(bot.clicks.length, 5); assert.equal(bot.inventory.slots[9], null); }); test('drop functions reject invalid inputs, cursor items, failures and changed windows', async () => { for (const [fn, valid, invalid] of [ [new DropAll(), [9], [[], [-1], [46], [1.5], [NaN], [9, 1]]], [new DropNumber(), [9, 2], [[], [9], [-1, 2], [9, 0], [9, -1], [9, 1.5], [9, Infinity]]], ]) { const bot = botFixture(); for (const args of invalid) assert.equal(await fn.run(bot, args), false); assert.equal(bot.clicks.length, 0); bot.inventory.selectedItem = new Item(2, 1); assert.equal(await fn.run(bot, valid), false); bot.inventory.selectedItem = null; bot.clickWindow = async () => { throw Error('rejected'); }; assert.equal(await fn.run(bot, valid), false); let calls = 0; bot.clickWindow = async () => { calls++; bot.currentWindow = {}; }; assert.equal(await fn.run(bot, valid), false); assert.equal(calls, 1); } const bot = botFixture(); bot.clickWindow = async () => {}; assert.equal(await new DropNumber().run(bot, [9, 2]), false); assert.equal(await new DropAll().run(bot, [9]), false); }); test('using an item selects the requested hand and rejects empty or unsupported hands', async () => { const bot = botFixture(); const used = []; bot.heldItem = new Item(1, 1); bot.inventory.slots[45] = new Item(2, 1); bot.supportFeature = () => false; bot.activateItem = hand => used.push(hand); const fn = new UseItem(); assert.equal(await fn.run(bot, [false]), true); assert.equal(await fn.run(bot, [true]), true); assert.deepEqual(used, [false, true]); for (const args of [[], [0], ['false'], [false, true]]) assert.equal(await fn.run(bot, args), false); bot.heldItem = null; assert.equal(await fn.run(bot, [false]), false); bot.supportFeature = () => true; assert.equal(await fn.run(bot, [true]), false); bot.supportFeature = () => false; bot.inventory.slots[45] = null; assert.equal(await fn.run(bot, [true]), false); bot.heldItem = new Item(1, 1); bot.activateItem = () => { throw Error('failed'); }; assert.equal(await fn.run(bot, [false]), false); assert.deepEqual(used, [false, true]); });