added trade
This commit is contained in:
parent
f71899e9c0
commit
16668c6714
@ -4,4 +4,5 @@ module.exports = {
|
||||
default: require('./default'),
|
||||
fun: require('./fun'),
|
||||
invite: require('./invite'),
|
||||
trade: require('./trade'),
|
||||
};
|
||||
|
412
nodejs/controller/commands/trade.js
Normal file
412
nodejs/controller/commands/trade.js
Normal file
@ -0,0 +1,412 @@
|
||||
'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: 1,
|
||||
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!`)
|
||||
}, 30000);
|
||||
|
||||
// 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;
|
||||
clearTimeout(timeoutCheck)
|
||||
|
||||
// Give MC a moment
|
||||
await sleep(1000);
|
||||
|
||||
let isPutAway = await this.putInChest(chestBlock)
|
||||
await this.whisper(from, `I put ${isPutAway ? 'all' : 'some'} items in your chest.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
|
||||
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 };*/
|
@ -14,19 +14,19 @@ for(let name in conf.mc.bots){
|
||||
let bot = new CJbot({name, host: conf.mc.host, ...conf.mc.bots[name]});
|
||||
CJbot.bots[name] = bot;
|
||||
|
||||
|
||||
for(let command of conf.mc.bots[name].commands || ['default']){
|
||||
|
||||
for(let [name, toAdd] of Object.entries(commands[command])){
|
||||
bot.addCommand(name, toAdd)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bot.on('onReady', async function(argument) {
|
||||
await sleep(1000);
|
||||
bot.bot.setControlState('jump', true);
|
||||
setTimeout(()=> bot.bot.setControlState('jump', false), 5000)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
(async ()=>{
|
||||
try{
|
||||
for(let name in CJbot.bots){
|
||||
@ -37,11 +37,8 @@ try{
|
||||
|
||||
await sleep(30000);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}catch(e){
|
||||
|
||||
console.log('!!!!!!!! error:', e)
|
||||
}})()
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
const {sleep} = require('../utils');
|
||||
const mineflayer = require('mineflayer');
|
||||
const Vec3 = require('vec3');
|
||||
const {sleep} = require('../utils');
|
||||
|
||||
|
||||
class CJbot{
|
||||
@ -111,7 +112,7 @@ class CJbot{
|
||||
// Call the internal listeners when the bot is ready
|
||||
for(let callback of this.listeners.onReady || []){
|
||||
console.log('calling listener', callback)
|
||||
await callback(this)
|
||||
await callback.call(this)
|
||||
}
|
||||
|
||||
this.isReady = true;
|
||||
@ -222,6 +223,14 @@ class CJbot{
|
||||
this.__doCommand(message.toString().split(' ')[0], '.invite');
|
||||
}
|
||||
|
||||
if(message.toString().includes(' wants to trade with you!')){
|
||||
// teleport invite
|
||||
|
||||
console.log('found Trade', message.toString().split(' ')[0])
|
||||
this.__doCommand(message.toString().split(' ')[0], '.trade');
|
||||
}
|
||||
|
||||
|
||||
if(message.toString().includes('You are combat tagged by')){
|
||||
try{
|
||||
this.combatTag = true;
|
||||
@ -316,6 +325,62 @@ class CJbot{
|
||||
|
||||
return this.bot.players;
|
||||
}
|
||||
|
||||
__blockOrVec(thing){
|
||||
if(thing instanceof Vec3.Vec3) return this.bot.blockAt(thing);
|
||||
if(thing.constructor && thing.constructor.name === 'Block') return thing;
|
||||
|
||||
throw new Error('Not supported block identifier');
|
||||
}
|
||||
|
||||
|
||||
async __nextContainerSlot(window, item) {
|
||||
let firstEmptySlot = false;
|
||||
|
||||
await window.containerItems();
|
||||
|
||||
for(let slot in window.slots.slice(0, window.inventoryStart)){
|
||||
if(window.slots[slot] === null ){
|
||||
if(!Number.isInteger(firstEmptySlot)) firstEmptySlot = Number(slot);
|
||||
continue;
|
||||
}
|
||||
if(item.type === window.slots[slot].type && window.slots[slot].count < window.slots[slot].stackSize){
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
|
||||
return firstEmptySlot;
|
||||
}
|
||||
|
||||
async putInChest(block, blockName, amount) {
|
||||
block = this.__blockOrVec(block);
|
||||
|
||||
this.bot.openContainer(block);
|
||||
let window = await this.once('windowOpen');
|
||||
|
||||
for(let item of window.slots.slice(window.inventoryStart).filter(function(item){
|
||||
if(!item) return false;
|
||||
if(blockName && blockName !== item.name) return false;
|
||||
return true;
|
||||
})){
|
||||
let currentSlot = Number(item.slot);
|
||||
if(!window.slots[currentSlot]) continue;
|
||||
|
||||
if(amount && !amount--) return;
|
||||
let chestSlot = await this.__nextContainerSlot(window, item);
|
||||
console.log('next slot', chestSlot);
|
||||
await this.bot.moveSlotItem(currentSlot, chestSlot)
|
||||
|
||||
let res = await this.putInChest(...arguments);
|
||||
if(res === false) return amount ? amount : false;
|
||||
}
|
||||
|
||||
await this.bot.closeWindow(window);
|
||||
|
||||
return amount ? amount : true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
module.exports = {CJbot};
|
||||
|
Loading…
x
Reference in New Issue
Block a user