Bot Unable to Deposit Items into Trade GUI
- [x] The FAQ doesn't contain a resolution to my issue
Versions
- Mineflayer: 4.29.0
- Server: Paper 1.8.8
- Runtime: bun 1.2.15 | node 24.1.0
Detailed description of a problem
I am building a two-part middleman bot for a Minecraft server. A C# Discord bot handles user interactions and state, while a Mineflayer bot executes in-game actions like trading. With RabbitMQ to handle jobs for the Minecraft bot.
The core problem is that the Mineflayer bot is unable to deposit items into the server's trade window. The bot can successfully initiate a trade and open the trade GUI, but all attempts to move items from its inventory into the trade slots fail silently. This makes it impossible to complete the final step of a trade, where the bot gives items to the buyer.
What did you try yet?
The primary method I tried was using bot.clickWindow() to simulate a shift-click for every item in the bot's inventory. I looped through bot.inventory.items() and called await bot.clickWindow(item.slot, 0, 1) for each one.
When we just click on slot 0 to confirm the trade, that works fine and you see it updating on the other trades screen, but not when moving items.
This code executes without throwing any errors, but it has no effect. The items do not move, and the bot's inventory remains unchanged. I also tried adding small delays between clicks using bot.waitForTicks().
Your current code
const bot: Bot = createBot({
host: process.env.MC_HOST,
username: process.env.MC_USERNAME!,
password: process.env.MC_PASSWORD,
version: "1.8.9",
auth: "microsoft",
});
bot.on("windowOpen", async (window) => {
if (!isBusy || !currentTradeJob) return;
const isTradeWindow = window.title.includes("You");
if (!isTradeWindow) return;
console.log("[State] Trade window opened. Waiting for server to populate items...");
inventoryBeforeTrade = botInstance.inventory.items().map(item => ({ type: item.type, count: item.count }));
if (currentTradeJob.action === "SECURE_ITEMS_FROM_SELLER") {
console.log("[State] Action is SECURE_ITEMS. Accepting.");
await acceptTrade(botInstance);
} else if (currentTradeJob.action === "GIVE_ITEMS_TO_BUYER") {
console.log("[State] Action is GIVE_ITEMS. Depositing and accepting.");
await depositItemsForTrade(botInstance);
await acceptTrade(botInstance);
}
});
/**
* Deposits all tradeable items into the trade window by simulating a shift-click
* for each item.
* @param bot The Mineflayer bot instance.
*/
export async function depositItemsForTrade(bot: Bot): Promise<void> {
if (!bot.currentWindow) {
console.error("[Action] Cannot deposit items, no window is open.");
return;
}
console.log("[Action] Depositing all inventory items via shift-click...");
// Get a fresh list of items from the main inventory to deposit.
const itemsToDeposit = bot.inventory.items();
if (itemsToDeposit.length === 0) {
console.warn("[Action] Bot has no items to deposit.");
return;
}
for (const item of itemsToDeposit) {
try {
console.log(`[Action] Shift-clicking ${item.count}x ${item.name} from slot ${item.slot}...`);
// The '1' in the second argument signifies a shift-click.
await bot.clickWindow(item.slot, 0, 1);
// A small delay is still wise to prevent spamming the server.
await bot.waitForTicks(10);
} catch (err) {
console.error(`[Action] Failed to shift-click item ${item.name}. Aborting deposit.`, err);
break;
}
}
console.log("[Action] Finished depositing items.");
}
/**
* A helper function to accept a trade in the custom GUI.
* It directly clicks the known slot for the "Accept Trade" button.
* @param bot The Mineflayer bot instance.
*/
export async function acceptTrade(bot: Bot): Promise<void> {
if (!bot.currentWindow) {
console.error("[Action] Cannot accept trade, no window is open.");
return;
}
try {
const acceptSlot = 0;
console.log(`[Action] Clicking known 'Accept Trade' slot: ${acceptSlot}`);
await bot.clickWindow(acceptSlot, 0, 0);
} catch (err) {
console.error("[Action] An error occurred while trying to click the accept slot:", err);
}
}
Expected behavior
When await bot.clickWindow(item.slot, 0, 1) is called while a trade window is open, I expect the specified item to be moved from the bot's main inventory into an available slot in the trade window. The bot's internal inventory state (bot.inventory) should update to reflect that the item has been moved.
Additional context
This issue is occurring on a large, live production server (Minecadia), which almost certainly runs a custom trade GUI plugin.
The next step is to verify this using a packet inspector like prismarine-proxy. I am looking for guidance on how to approach debugging this kind of GUI.