feat: enhance AFK retry mechanism with GUI interaction and window handling
This commit is contained in:
parent
95a74d7a34
commit
d26de80759
116
afk.js
116
afk.js
@ -1,4 +1,5 @@
|
|||||||
const mineflayer = require("mineflayer");
|
const mineflayer = require("mineflayer");
|
||||||
|
const gui = require("mineflayer-gui");
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
|
|
||||||
@ -33,8 +34,6 @@ const LOG_FILE = path.join(
|
|||||||
const TELEPORT_DETECT_REGEX = /you teleported to\b/i;
|
const TELEPORT_DETECT_REGEX = /you teleported to\b/i;
|
||||||
const AFK_INITIAL_CHECK_DELAY_MS = 5000;
|
const AFK_INITIAL_CHECK_DELAY_MS = 5000;
|
||||||
const AFK_POST_COMMAND_CHECK_DELAY_MS = 7000;
|
const AFK_POST_COMMAND_CHECK_DELAY_MS = 7000;
|
||||||
const AFK_MIN_NUMBER = 1;
|
|
||||||
const AFK_MAX_NUMBER = 50;
|
|
||||||
|
|
||||||
let hasDetectedTeleport = false;
|
let hasDetectedTeleport = false;
|
||||||
let afkRetryTimer = null;
|
let afkRetryTimer = null;
|
||||||
@ -47,8 +46,79 @@ function log(message) {
|
|||||||
fs.appendFileSync(LOG_FILE, logMessage + "\n");
|
fs.appendFileSync(LOG_FILE, logMessage + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRandomIntInclusive(min, max) {
|
function sleep(ms) {
|
||||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
}
|
||||||
|
|
||||||
|
function waitForWindowOpen(timeoutMs = 5000) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
if (bot.currentWindow) {
|
||||||
|
resolve(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const originalHandler = bot.listenerCount("windowOpen");
|
||||||
|
const onWindowOpen = () => {
|
||||||
|
clearTimeout(timer);
|
||||||
|
bot.removeListener("windowOpen", onWindowOpen);
|
||||||
|
resolve(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
bot.removeListener("windowOpen", onWindowOpen);
|
||||||
|
resolve(false);
|
||||||
|
}, timeoutMs);
|
||||||
|
|
||||||
|
bot.on("windowOpen", onWindowOpen);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeCurrentWindow() {
|
||||||
|
if (!bot.currentWindow) return;
|
||||||
|
if (typeof bot.closeWindow === "function") {
|
||||||
|
bot.closeWindow(bot.currentWindow);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (typeof bot.currentWindow.close === "function") {
|
||||||
|
bot.currentWindow.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function findWindowSlotByCandidates(candidates) {
|
||||||
|
if (!bot.currentWindow || !Array.isArray(bot.currentWindow.slots))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
const normalizedCandidates = candidates.map((c) =>
|
||||||
|
String(c || "")
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/[_\s]+/g, "")
|
||||||
|
.trim(),
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const item of bot.currentWindow.slots) {
|
||||||
|
if (!item) continue;
|
||||||
|
|
||||||
|
const itemName = String(item.name || "")
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/[_\s]+/g, "");
|
||||||
|
const displayName = String(item.displayName || "")
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/[_\s]+/g, "");
|
||||||
|
const nbtName = String(item.customName || "")
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/[_\s]+/g, "");
|
||||||
|
|
||||||
|
const matched = normalizedCandidates.some(
|
||||||
|
(candidate) =>
|
||||||
|
itemName.includes(candidate) ||
|
||||||
|
displayName.includes(candidate) ||
|
||||||
|
nbtName.includes(candidate),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (matched) return item.slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearAfkRetryTimer() {
|
function clearAfkRetryTimer() {
|
||||||
@ -61,13 +131,38 @@ function clearAfkRetryTimer() {
|
|||||||
function scheduleAfkRetryCheck(delayMs) {
|
function scheduleAfkRetryCheck(delayMs) {
|
||||||
clearAfkRetryTimer();
|
clearAfkRetryTimer();
|
||||||
|
|
||||||
afkRetryTimer = setTimeout(() => {
|
afkRetryTimer = setTimeout(async () => {
|
||||||
if (hasDetectedTeleport) return;
|
if (hasDetectedTeleport) return;
|
||||||
|
|
||||||
const randomNumber = getRandomIntInclusive(AFK_MIN_NUMBER, AFK_MAX_NUMBER);
|
log(`No teleport detected after ${delayMs}ms; sending /afk command`);
|
||||||
const command = `/afk ${randomNumber}`;
|
bot.chat("/afk");
|
||||||
log(`No teleport detected after ${delayMs}ms; sending: ${command}`);
|
|
||||||
bot.chat(command);
|
await sleep(500);
|
||||||
|
const opened = await waitForWindowOpen(5000);
|
||||||
|
if (!opened || !bot.currentWindow) {
|
||||||
|
log("AFk GUI did not open");
|
||||||
|
scheduleAfkRetryCheck(AFK_POST_COMMAND_CHECK_DELAY_MS);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log("AFk GUI opened, clicking amethyst block");
|
||||||
|
const amethystCandidates = ["Amethyst Block", "amethyst_block", "Amethyst"];
|
||||||
|
const slot = findWindowSlotByCandidates(amethystCandidates);
|
||||||
|
if (slot === null) {
|
||||||
|
log("Amethyst block not found in AFk GUI");
|
||||||
|
closeCurrentWindow();
|
||||||
|
scheduleAfkRetryCheck(AFK_POST_COMMAND_CHECK_DELAY_MS);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await bot.clickWindow(slot, 0, 0);
|
||||||
|
log("Clicked amethyst block");
|
||||||
|
} catch (err) {
|
||||||
|
log(`Failed to click amethyst block: ${err.message}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
closeCurrentWindow();
|
||||||
|
|
||||||
// Teleport feedback can lag a few seconds after issuing /afk.
|
// Teleport feedback can lag a few seconds after issuing /afk.
|
||||||
scheduleAfkRetryCheck(AFK_POST_COMMAND_CHECK_DELAY_MS);
|
scheduleAfkRetryCheck(AFK_POST_COMMAND_CHECK_DELAY_MS);
|
||||||
@ -133,10 +228,13 @@ bot.on("login", () => {
|
|||||||
|
|
||||||
bot.on("spawn", () => {
|
bot.on("spawn", () => {
|
||||||
log("Bot spawned");
|
log("Bot spawned");
|
||||||
|
|
||||||
|
log(`Bot username: ${bot.username}`);
|
||||||
if (hasDetectedTeleport) {
|
if (hasDetectedTeleport) {
|
||||||
log("Teleport already confirmed before spawn; skipping AFK retry schedule");
|
log("Teleport already confirmed before spawn; skipping AFK retry schedule");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
scheduleAfkRetryCheck(AFK_INITIAL_CHECK_DELAY_MS);
|
scheduleAfkRetryCheck(AFK_INITIAL_CHECK_DELAY_MS);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user