forked from wmantly/mc-bot-town
fable
This commit is contained in:
@@ -162,12 +162,31 @@ module.exports = {
|
||||
return;
|
||||
}
|
||||
|
||||
let tradeResult = null;
|
||||
let pending = null;
|
||||
let itemsReceived = [];
|
||||
|
||||
try {
|
||||
storage._busy = true;
|
||||
const pending = storage.pendingWithdrawals.get(from);
|
||||
// The task we interrupted has exited (it released the lock);
|
||||
// reset the interrupt flag so our own work isn't flagged
|
||||
this.registerTask('Storage', 'trade', null);
|
||||
pending = storage.pendingWithdrawals.get(from);
|
||||
|
||||
// Set up listener BEFORE accepting to avoid race with window opening
|
||||
const windowPromise = this.once('windowOpen');
|
||||
await this.say('/trade accept');
|
||||
let window = await this.once('windowOpen');
|
||||
|
||||
// If no window ever opens (expired request, player left), bail
|
||||
// instead of holding the storage lock forever
|
||||
let window = await Promise.race([
|
||||
windowPromise,
|
||||
sleep(30000).then(() => null),
|
||||
]);
|
||||
if (!window) {
|
||||
this.whisper(from, 'Trade window never opened — send the trade request again.');
|
||||
return;
|
||||
}
|
||||
|
||||
// If there's a pending withdrawal, place items in bot's trade slots
|
||||
if (pending) {
|
||||
@@ -202,7 +221,8 @@ module.exports = {
|
||||
console.log(`Storage trade: Placed ${placed} stack(s) in trade window`);
|
||||
}
|
||||
|
||||
// Poll for customer confirmation (lime_dye at slot 53)
|
||||
// Poll for other party's lock indicator (slot 53 grey_dye → lime_dye)
|
||||
// Both parties must click green wool (slot 37) twice: 1st locks, 2nd finalizes
|
||||
let timeoutCheck = setTimeout(() => {
|
||||
this.bot.closeWindow(window);
|
||||
this.whisper(from, 'Trade timed out.');
|
||||
@@ -210,9 +230,25 @@ module.exports = {
|
||||
|
||||
let confirmationCheck = setInterval(async () => {
|
||||
try {
|
||||
// Never click a closed window — invalid window IDs
|
||||
// trip anti-cheat ("unusual packets")
|
||||
if (this.bot.currentWindow !== window) return;
|
||||
const indicator = window.slots[53];
|
||||
if (indicator && indicator.name === 'lime_dye') {
|
||||
this.bot.moveSlotItem(37, 37);
|
||||
clearInterval(confirmationCheck);
|
||||
|
||||
// Click 1: lock items — single left-click, not the
|
||||
// pickup+putdown pair moveSlotItem sends
|
||||
await this.bot.clickWindow(37, 0, 0);
|
||||
console.log('Storage trade: click 1 — items locked');
|
||||
|
||||
await sleep(1000); // Both now locked, brief pause
|
||||
|
||||
// Click 2: finalize (second confirmation)
|
||||
if (this.bot.currentWindow === window) {
|
||||
await this.bot.clickWindow(37, 0, 0);
|
||||
console.log('Storage trade: click 2 — final confirm');
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// window may have closed
|
||||
@@ -229,7 +265,7 @@ module.exports = {
|
||||
}
|
||||
clearTimeout(timeoutCheck);
|
||||
|
||||
let tradeResult = null;
|
||||
|
||||
|
||||
if (pending) {
|
||||
// Withdrawal complete — clear pending
|
||||
@@ -241,7 +277,7 @@ module.exports = {
|
||||
await sleep(500);
|
||||
|
||||
const hotbarNames = new Set((storage.config.hotbarItems || []).map(h => h.name));
|
||||
const itemsReceived = [];
|
||||
itemsReceived = [];
|
||||
for (const item of this.bot.inventory.items()) {
|
||||
if (hotbarNames.has(item.name)) continue;
|
||||
itemsReceived.push({ name: item.name, id: item.type, count: item.count, nbt: item.nbt });
|
||||
@@ -254,18 +290,35 @@ module.exports = {
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
this.clearTask();
|
||||
storage._busy = false;
|
||||
storage._releaseOperationLock();
|
||||
}
|
||||
|
||||
// Organize after lock is released (handleTrade runs under the lock)
|
||||
if (tradeResult && tradeResult.needsOrganize) {
|
||||
storage._busy = true;
|
||||
try {
|
||||
await storage.organizeLooseItems();
|
||||
await storage.organizeLooseItems(true);
|
||||
} catch (error) {
|
||||
console.error('Storage: Post-trade organize failed:', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Notify the AI face bot about this trade so it can respond naturally
|
||||
try {
|
||||
const { getInstance } = require('../ai/manager');
|
||||
const manager = getInstance();
|
||||
if (manager.isActive) {
|
||||
if (pending) {
|
||||
manager.notifySystemEvent(`${this.bot.entity.username} completed withdrawal: ${pending.count}x ${pending.itemName} for ${from}. Trade finished.`);
|
||||
} else if (itemsReceived && itemsReceived.length > 0) {
|
||||
const itemSummary = itemsReceived.slice(0, 5).map(i => `${i.count}x ${i.name}`).join(', ');
|
||||
const extra = itemsReceived.length > 5 ? ` +${itemsReceived.length - 5} more types` : '';
|
||||
manager.notifySystemEvent(`${this.bot.entity.username} received deposit from ${from}: ${itemSummary}${extra}. All items stored.`);
|
||||
}
|
||||
}
|
||||
} catch (e) { /* ignore */ }
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -55,8 +55,9 @@ module.exports = {
|
||||
}
|
||||
}
|
||||
|
||||
// Confirm and log trade
|
||||
this.bot.moveSlotItem(37, 37);
|
||||
// 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');
|
||||
@@ -91,16 +92,23 @@ module.exports = {
|
||||
|
||||
// If the process is taking to long, just stop
|
||||
let timeoutCheck = setTimeout(()=>{
|
||||
this.bot.closeWindow('window');
|
||||
this.bot.removeAllListeners('windowOpen');
|
||||
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 ()=>{
|
||||
if(window.containerItems().filter(item => item?.slot == 53)[0].name == 'lime_dye'){
|
||||
this.bot.moveSlotItem(37, 37);
|
||||
}
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user