2023-06-06 12:50:53 -04:00

427 lines
17 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){
/*
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...`);
await this.say('/trade accept');
let window = await this.once('windowOpen');
// If the process is taking to long, just stop
let timeoutCheck = setTimeout(()=>{
this.bot.closeWindow('window');
this.bot.removeAllListeners('windowOpen');
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.
let confirmationCheck = setInterval(async ()=>{
if(window.containerItems().filter(item => item?.slot == 53)[0].name == 'lime_dye'){
this.bot.moveSlotItem(37, 37);
}
}, 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;
console.log('clearing timeout');
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);
}
}
}
/*
const { countCustomerPayment } = require('../parts/countCustomerPayment.js');
const { getCustomerItems } = require('../parts/getCustomerItems.js');
const { findContainerItem } = require('../parts/findContainerItem.js');
const { minecraftBot } = require('../../../modules/minecraftBot.js');
const mcData = require('minecraft-data')(minecraftBot.version);
const { once } = require('../../../functions/once.js');
const { timeOut } = require('../../../functions/timeOut.js');
const { toMinecraftChat } = require('../../../functions/toMinecraftChat.js');
const { findOrCreateBankItemWithRelation } = require('../../bank/parts/findOrCreateBankItemWithRelations.js');
const { toDiscordChat } = require('../../../functions/toDiscordChat.js');
let checkCustomerFirstConfirmInterval;
let checkCustomerSecondConfirmInterval;
let putItemInterval;
let firstTimeout;
let secondTimeout;
let windowOpened;
let timedOut;
let isFinished;
const firstTimeoutDelay = 30000;
const secondTimeoutDelay = 20000;
function CJTradeRequest(targetPlayer, itemToGive, itemToGiveAmount, itemToReceive, itemToReceiveAmount) {
windowOpened = false;
isFinished = false;
timedOut = false;
// Item that is not the currency.
let fullItemName = itemToGive.nameWithTradeName ?? itemToReceive.nameWithTradeName;
let itemAmount = itemToGive.nameWithTradeName ? itemToGiveAmount : itemToReceiveAmount;
let tradePromise = new Promise((resolve, reject) => {
console.log("trade request started");
minecraftBot.chat(`/trade ${targetPlayer}`);
minecraftBot.once('windowOpen', async (window) => {
windowOpened = true;
if (timedOut == true) {
return;
}
console.log("trade window opened");
// List of items in inventory
let windowInventoryItems = window.items();
function windowInventoryItemsCount() {
let inventoryItemCount = 0;
for (let item of windowInventoryItems) {
if (item.name == itemToGive.item_name) {
inventoryItemCount += parseInt(item.count);
}
}
return inventoryItemCount;
}
console.log("inventory item count: " + windowInventoryItemsCount());
// If itemToGive is diamond round down to whole number and pay difference in diamondBank
let roundingDifference = 0;
if (itemToGive.item_name == "diamond" && itemToGive.isToken == false) {
let itemToGiveAmountUnrounded = itemToGiveAmount;
itemToGiveAmount = Math.floor(itemToGiveAmount);
roundingDifference = itemToGiveAmountUnrounded - itemToGiveAmount;
}
let takeItemDelay = 50;
let i = 0;
let currentSlotAmount = 0;
let movedAmount = 0;
let itemToMove;
let amountLeft;
let putItemInTrade = async () => {
itemToMove = await findContainerItem(window.items(), itemToGive, itemToGive.itemEnchants);
// amountLeft is the amount of items left to move
amountLeft = itemToGiveAmount - movedAmount;
if (itemToMove !== null) {
// Move entire slot if is less than whats left
if (amountLeft >= itemToMove.count) {
amountToMove = itemToMove.count
console.log("amount to move is all items in inv slot, amount: ", amountToMove);
}
// Move only specific amount of slot if slot itemToMove count is more than whats left
else if (amountLeft < itemToMove.count) {
amountToMove = amountLeft;
console.log("amount to move is less than in the slot, amount: ", amountToMove);
}
// Move stack size if amountToMove is bigger than a stack
if (currentSlotAmount + amountToMove > itemToGive.stackSize) {
amountToMove = itemToGive.stackSize - currentSlotAmount;
console.log("total amount of slot will be more than stack size, updated amount: ", amountToMove);
}
}
if (itemToGiveAmount > movedAmount) {
itemSlot = itemToMove.slot;
let options = {
itemType: itemToGive.mcId,
destStart: botSlots[i],
// destEnd is until (excluding itself)
destEnd: botSlots[i] + 1,
sourceStart: itemSlot,
sourceEnd: itemSlot + 1,
count: amountToMove,
}
currentSlotAmount += amountToMove;
minecraftBot.transfer(options)
movedAmount = parseInt(movedAmount + amountToMove);
console.log(" amountToMove / movedAmount / total needed amount", amountToMove, movedAmount, amount);
console.log("current slot amount / stack size", currentSlotAmount, itemToGive.stackSize);
if (currentSlotAmount >= itemToGive.stackSize) {
console.log("1 slot up!");
i++;
currentSlotAmount = 0;
}
}
if (itemToGiveAmount == movedAmount) {
clearInterval(putItemInterval);
//do first confirm
setTimeout(() => {
minecraftBot.moveSlotItem(37, 37);
}, 70);
}
}
// Start putting items in trade window.
console.log("give token: ", itemToGive.isToken)
if (itemToGive.isToken == false) {
putItemInterval = setInterval(putItemInTrade, takeItemDelay);
}
// If token transaction do not put item in trade window and press first confirm.
else if (itemToGive.isToken == true) {
setTimeout(() => {
minecraftBot.moveSlotItem(37, 37);
}, 70);
}
let missingDiamonds = null;
let missingDiamondsRounded = null;
let windowItems;
let paymentCount;
let bankItem;
let validateTrade = async () => {
windowItems = window.containerItems();
paymentCount = await countCustomerPayment(windowItems, itemToReceive, itemToReceive.itemEnchants);
// Check if payment amount is less than required amount
if (paymentCount < itemToReceiveAmount) {
if (itemToReceive.item_name == "diamond") {
missingDiamonds = itemToReceiveAmount - paymentCount;
missingDiamondsRounded = Math.round(missingDiamonds * 100) / 100;
// Check if it has the missing diamonds in bank
bankItem = await findOrCreateBankItemWithRelation(targetPlayer)
if (bankItem.balance < missingDiamonds) {
toMinecraftChat(targetPlayer, "You did not pay enough, and not enough in bank!");
minecraftBot.closeWindow(window);
return reject("Not enough paid and not enough in bank.");
}
}
else {
toMinecraftChat(targetPlayer, "You did not pay enough of the item!");
minecraftBot.closeWindow(window);
return reject("not enough paid");
}
}
// Check for illegal items
for (let windowItem of windowItems) {
// Item is named with anvil and bigger stack size than 1
let itemNickJson = windowItem?.nbt?.value?.display?.value?.Name?.value
let itemNick = itemNickJson ? JSON.parse(itemNickJson).text : null;
if (itemNick) {
let itemStackSize = mcData.itemsByName[windowItem.name].stackSize;
if (itemStackSize > 1) {
toMinecraftChat(targetPlayer, "Only items with stack size of 1 may be named!");
minecraftBot.closeWindow(window);
return reject("named item");
}
}
// Item is is a map
if (windowItem.name == "filled_map") {
toMinecraftChat(targetPlayer, "You put an illegal piece of junk in trade window.");
minecraftBot.closeWindow(window);
return reject(`Illegal item "filled_map" in trade window.`);
}
}
}
let customerConfirmItem;
let checkCustomerFirstConfirm = async () => {
customerConfirmItem = window.containerItems().filter(item => item?.slot == 53);
if (window.findContainerItem("magenta_dye") !== null && customerConfirmItem[0]?.name == "magenta_dye") {
clearInterval(checkCustomerFirstConfirmInterval);
await validateTrade();
checkCustomerSecondConfirmInterval = setInterval(checkCustomerSecondConfirm, secondConfirmIntervalDelay);
}
}
let checkCustomerSecondConfirm = async () => {
console.log("checkCustomerSecondConfirm");
// Check if item in slot 54 is lime dye
customerConfirmItem = window.containerItems().filter(item => item?.slot == 53);
if (window.findContainerItem("lime_dye") != null && customerConfirmItem[0]?.name == "lime_dye") {
console.log("customer did second confirm");
clearInterval(checkCustomerSecondConfirmInterval);
await validateTrade();
bankItem = await findOrCreateBankItemWithRelation(targetPlayer)
// Buy:
if (itemToReceive.item_name == "diamond") {
if (bankItem.balance >= missingDiamonds && missingDiamonds != null) {
bankItem.balance -= missingDiamonds;
bankItem.save();
toMinecraftChat(targetPlayer, `You paid ${missingDiamondsRounded} diamonds from your bulba bank account!`);
toDiscordChat(`Paid ${missingDiamondsRounded} diamond token and ${itemToReceiveAmount - missingDiamonds} diamond.`);
}
// Add overpaid diamonds to bank
else if (paymentCount > itemToReceiveAmount) {
let overpaidDiamonds = paymentCount - itemToReceiveAmount;
let overpaidDiamondsRounded = Math.round(overpaidDiamonds * 100) / 100;
bankItem.balance += overpaidDiamonds;
bankItem.save();
toMinecraftChat(targetPlayer, `You overpaid ${overpaidDiamondsRounded} diamond. It has been added to your bulba bank account!`);
toDiscordChat(`Overpaid ${overpaidDiamondsRounded} diamond.`);
}
}
// Sell: Give all diamonds in tokens to customer
else if (itemToGive.item_name == "diamond" && itemToGive.isToken == true) {
console.log("Gave all currency/item in tokens to customer.");
bankItem.balance += itemToGiveAmount;
bankItem.save();
}
// Sell: Give rounding difference to customer
else if (itemToGive.item_name == "diamond" && roundingDifference > 0) {
console.log("Gave rounding difference to customer.");
bankItem.balance += roundingDifference;
bankItem.save();
}
console.log("payment: ", paymentCount);
let customerItems = getCustomerItems(windowItems);
minecraftBot.moveSlotItem(37, 37);
once('windowClose').then(() => {
return resolve(customerItems);
});
}
};
// Check for secondConfirm every 0.05 seconds until trade closes
let secondConfirmIntervalDelay = 50;
checkCustomerFirstConfirmInterval = setInterval(checkCustomerFirstConfirm, secondConfirmIntervalDelay);
// Delay because when trade succesfull it closes too
await once('windowClose');
await timeOut(1000);
return reject("Trade window closed.");
});
// 30 seconds timeout add 20 seconds if in trade window
firstTimeout = setTimeout(() => {
console.log("timeout!!");
if (isFinished == true) {
return;
}
else if (windowOpened == false) {
toMinecraftChat(targetPlayer, `Trade request timed out. If you only want to check the price please use "price ${fullItemName} ${itemAmount}" instead.`);
minecraftBot.removeAllListeners('windowOpen');
timedOut = true;
return reject("timed out");
}
else {
//if in trade window
secondTimeout = setTimeout(() => {
console.log("second timeout!!");
if (windowOpened == true && timedOut == false) {
toMinecraftChat(targetPlayer, "Trade request timed out.");
minecraftBot.removeAllListeners('windowOpen');
return reject("timed out in trade window");
}
}, secondTimeoutDelay);
}
}, firstTimeoutDelay);
});
tradePromise
.then(() => {
clearInterval(checkCustomerFirstConfirmInterval);
clearInterval(checkCustomerSecondConfirmInterval);
clearInterval(putItemInterval);
clearTimeout(firstTimeout);
clearTimeout(secondTimeout);
isFinished = true;
})
.catch((err) => {
clearInterval(checkCustomerFirstConfirmInterval);
clearInterval(checkCustomerSecondConfirmInterval);
clearInterval(putItemInterval);
clearTimeout(firstTimeout);
clearTimeout(secondTimeout);
isFinished = true;
});
return tradePromise;
}
module.exports = { CJTradeRequest };*/