Files
mc-bot-town/nodejs/controller/commands/trade.js
T
2026-07-12 17:26:59 -04:00

142 lines
3.9 KiB
JavaScript

'use strict';
const {sleep} = require('../../utils');
const botSlots = [0, 1, 2, 3, 9, 10, 11, 12, 18, 19, 20, 21];
const customerSlots = [5, 6, 7, 8, 14, 15, 16, 17, 23, 24, 25, 26];
function findChestBySign(bot, text){
let sign = bot.bot.findBlock({
useExtraInfo: true,
maxDistance: 32,
matching: (block)=> {
if(block.name.includes('sign') && block.signText.includes(text)){
return true;
}
}
});
return bot.bot.findBlock({
point: sign.position,
// maxDistance: 1,
useExtraInfo: true,
matching: block => block.name === 'chest'
});
}
module.exports = {
'.trade': {
desc: 'Bot will take trade requests',
async function(from){
// Check if bot has StoragePlugin
if (this.plunginsLoaded['Storage']) {
// Storage bot flow
if (this.plunginsLoaded['Ai']) {
this.plunginsLoaded['Ai']._expectingTradeWindow = true;
}
await this.say('/trade accept');
let window = await this.once('windowOpen');
// Collect items received from player
const itemsReceived = [];
const customerSlots = [5, 6, 7, 8, 14, 15, 16, 17, 23, 24, 25, 26];
for (const slotNum of customerSlots) {
const item = window.slots[slotNum];
if (item) {
itemsReceived.push({
name: item.name,
id: item.type,
count: item.count,
nbt: item.nbt
});
}
}
// Confirm and log trade — single left-click (moveSlotItem's
// pickup+putdown pair trips anti-cheat on cancelled GUI slots)
try { await this.bot.clickWindow(37, 0, 0); } catch (e) { /* ignore */ }
// Wait for trade to complete
await this.once('windowClose');
// Handle the trade items
if (itemsReceived.length > 0) {
await this.plunginsLoaded['Storage'].handleTrade(from, itemsReceived);
this.whisper(from, `Received ${itemsReceived.length} item type(s). Sorting into storage.`);
} else {
this.whisper(from, `No items received.`);
}
return;
}
// Original sign-based flow for non-storage bots
/*
todo
* Do... something if the users chest is full
*/
// Make the user has a chest then can add too.
let chestBlock = findChestBySign(this, from);
if(!chestBlock) return this.whisper(from, `You aren't allowed to trade with me...`);
if (this.plunginsLoaded['Ai']) {
this.plunginsLoaded['Ai']._expectingTradeWindow = true;
}
await this.say('/trade accept');
let window = await this.once('windowOpen');
// If the process is taking to long, just stop
let timeoutCheck = setTimeout(()=>{
try{ this.bot.closeWindow(window); }catch(e){ /* ignore */ }
this.whisper(from, `I have things to do, I cant wait on you all day!`)
}, 120000);
// Check to see if the remote user has agreed to the trade.
// Click once, only while the window is actually open — repeat
// clicks and clicks on closed windows trip anti-cheat.
let confirmed = false;
let confirmationCheck = setInterval(async ()=>{
try{
if(confirmed || this.bot.currentWindow !== window) return;
const indicator = window.slots[53];
if(indicator && indicator.name === 'lime_dye'){
confirmed = true;
await this.bot.clickWindow(37, 0, 0);
}
}catch(e){ /* window may have closed */ }
}, 500);
// Clean up when the trade is done
await this.once('windowClose');
clearInterval(confirmationCheck);
// If the trade took so long it timed out, just kill the whole thing.
if(timeoutCheck._destroyed) return;
clearTimeout(timeoutCheck)
// Give MC a moment
// await sleep(1000);
let goBack = await this.goToReturn({where: chestBlock, reTry: true})
let isPutAway = await this.dumpToChest(chestBlock)
await goBack();
await this.whisper(from, `I put ${isPutAway ? 'all' : 'some'} items in your chest.`);
}
},
'test': {
desc: 'go away',
allowed: ['useless666'],
async function(from){
let chestBlock = findChestBySign(this, from);
}
}
}