PrismarineJS / mineflayer

Create Minecraft bots with a powerful, stable, and high level JavaScript API.
https://prismarinejs.github.io/mineflayer/
MIT License
5.11k stars 921 forks source link

Clicking on item in chest gui #2726

Open brnfhz opened 2 years ago

brnfhz commented 2 years ago

Versions

Detailed description of a problem

I was trying to click on a specific item, I didn't get any error, but nothing happend, the what should've happened when it clicked on it didn't happen.

What did you try yet?

bot.clickWindow(1, 1, 0)

Your current code


bot.chat('The command that opens the gui')
bot.clickWindow(1, 1, 0)

Expected behavior

Clicking on that item going to a specific server.

amoraschi commented 2 years ago

Maybe you should wait for the window to open with the windowOpen event

brnfhz commented 2 years ago

Maybe you should wait for the window to open with the windowOpen event

I tried it with bot.on but it still doesn't work, it may be because the slot is wrong but I don't know how the slots are counted, I am trying to click the second item in the second row (downwards), I tried to press the 11th slot. And I'm not sure if the clickwindow uses left click with 1 as the second argument

amoraschi commented 2 years ago

You should locate the item you want to click and pass item.slot to clickWindow

brnfhz commented 2 years ago

You should locate the item you want to click and pass item.slot to windowOpen

Can you please elaborate?

amoraschi commented 2 years ago

Get the Item you want to click in the window, then pass item.slot (a property of the Item) to the method bot.clickWindow (my bad I wrote "windowOpen", I meant "clickWindow")

brnfhz commented 2 years ago

I found the item with console.log and found that the slot is 11 (if there's a better way to find it tell me please), and it still didn't work, the current lines are bot.on("windowOpen", window => { bot.clickWindow(11, 0, 0) })

ufgf commented 2 years ago

Try something like this (you can remove await's if you want code to run more synced):

bot.setQuickBarSlot(0);
bot.activateItem();
await bot.waitForTicks(20);

while (bot.currentWindow == null) {
  bot.setQuickBarSlot(0);
  bot.activateItem();
  await bot.waitForTicks(10);
}

attempts_waiting_compass = 0;

if (bot.currentWindow != null) {
  while (bot.game.levelType == "flat") { // delete this if you don't have a lobby (or something else) that has a world type: flat (or something else)
    attempts_waiting_compass += 1;
    if (attempts_waiting_compass <= 5) {
      bot.clickWindow(11, 0, 0);
      console.log("[init] clicked for connection, " + attempts_waiting_compass + " attempt");
      if (bot.currentWindow == null) break;
      await bot.waitForTicks(20);
    } else {
      console.log("[init] item does not respond 5 times, reconnecting...");
      bot.end("reconnect-needed");  // or just bot.end(); if you don't want auto-reconnecting at all
      break;
    }
  }
}

Also, if you are interested in the question of auto-reconnection, I decided to implement it this way:

const mineflayer = require("mineflayer");
const options = {
  host: ...,
  port: ...,
  username: ...,
  version: ...
};

// ...

var bot = mineflayer.createBot(options);

// ...

function relog() {
  console.log("[init] attempting to reconnect...");
  bot.removeAllListeners();
  bot.end();

  bot = mineflayer.createBot(options);
  themain(); // call main function, where all bot.on(), bot.once() and etc is
}

// ...

// function themain() {
  bot.on("end", (reason) => {
    if (reason.includes("socketClosed")) {
      console.log("[bot] disconnected: socketClosed");
      setTimeout(relog, 5000);
    } else if (reason.includes("reconnect-needed")) {
      console.log("[bot] disconnected (recon requested)");
      setTimeout(relog, 5000);
    } else {
      console.log("[bot] disconnected: " + reason);
      setTimeout(relog, 5000);
    }
  });
// ...
// }
brnfhz commented 2 years ago

Try something like this (you can remove await's if you want code to run more synced):

bot.setQuickBarSlot(0);
bot.activateItem();
await bot.waitForTicks(20);

while (bot.currentWindow == null) {
  bot.setQuickBarSlot(0);
  bot.activateItem();
  await bot.waitForTicks(10);
}

attempts_waiting_compass = 0;

if (bot.currentWindow != null) {
  while (bot.game.levelType == "flat") { // delete this if you don't have a lobby (or something else) that has a world type: flat (or something else)
    attempts_waiting_compass += 1;
    if (attempts_waiting_compass <= 5) {
      bot.clickWindow(11, 0, 0);
      console.log("[init] clicked for connection, " + attempts_waiting_compass + " attempt");
      if (bot.currentWindow == null) break;
      await bot.waitForTicks(20);
    } else {
      console.log("[init] item does not respond 5 times, reconnecting...");
      bot.end("reconnect-needed");  // or just bot.end(); if you don't want auto-reconnecting at all
      break;
    }
  }
}

Also, if you are interested in the question of auto-reconnection, I decided to implement it this way:

const mineflayer = require("mineflayer");
const options = {
  host: ...,
  port: ...,
  username: ...,
  version: ...
};

// ...

var bot = mineflayer.createBot(options);

// ...

function relog() {
  console.log("[init] attempting to reconnect...");
  bot.removeAllListeners();
  bot.end();

  bot = mineflayer.createBot(options);
  themain(); // call main function, where all bot.on(), bot.once() and etc is
}

// ...

// function themain() {
  bot.on("end", (reason) => {
    if (reason.includes("socketClosed")) {
      console.log("[bot] disconnected: socketClosed");
      setTimeout(relog, 5000);
    } else if (reason.includes("reconnect-needed")) {
      console.log("[bot] disconnected (recon requested)");
      setTimeout(relog, 5000);
    } else {
      console.log("[bot] disconnected: " + reason);
      setTimeout(relog, 5000);
    }
  });
// ...
// }

Thanks for the reply, I tried that, but it didn't work, at bot.end("reconnect-needed"); it waited a couple of seconds and the process stopped. Btw I am not trying to press something with the compass but the menu thats opened when /smp is entered in hypixel, so I changed it to bot.chat("/smp")