Skip to content

Resource Pack accetpion issue #3860

@kontoepickratatujszczur-cmd

Description

  • The FAQ doesn't contain a resolution to my issue

Versions

  • mineflayer: 1.21.4
  • server: paper
  • node: 22.17.1

Detailed description of a problem

So i tied many times to fix the issue that i cannot install resource pack im trying to make a bot that go to afk automatically

What did you try yet?

I tried my own resource pack download system
and the original ones like this:
bot.on('resourcePackSend', (url, hash) => {
console.log('Resource pack received:', url);
bot.acceptResourcePack(); // Automatically accept the resource pack
})

// ============================================================
// botManager.js – Zarządzanie instancjami botów Minecraft
// ============================================================

const mineflayer = require('mineflayer');
const { pathfinder, Movements, goals } = require('mineflayer-pathfinder');
const config = require('./config');

// ── Mapa botów: nick → { bot, state } ───────────────────────
const bots = new Map();

// ── Pomocnik: opóźnienie ─────────────────────────────────────
const sleep = (ms) => new Promise(r => setTimeout(r, ms));

// ── Pomocnik: bezpieczny chat ────────────────────────────────
async function safeChat(bot, message) {
await sleep(config.delays.chatAction);
try { bot.chat(message); } catch (_) {}
}

// ============================================================
// HANDLER RESOURCE PACK
// ============================================================
function attachResourcePackHandler(bot) {

// ── select_known_packs (faza konfiguracji, MC 1.21+) ─────
bot._client.on('select_known_packs', (data) => {
console.log([${bot.username}] [PACKS] select_known_packs (${(data.packs || []).length} packs));
try {
bot._client.write('select_known_packs', { packs: data.packs || [] });
console.log([${bot.username}] [PACKS] Odpowiedź wysłana ✓);
} catch (e) {
console.error([${bot.username}] [PACKS] Błąd:, e.message);
}
});

// ── MC 1.20.3–1.21.x: add_resource_pack ──────────────────
bot._client.on('add_resource_pack', (data) => {
console.log([${bot.username}] [RP] add_resource_pack uuid=${data.uuid});

const uuid = typeof data.uuid === 'string'
  ? data.uuid
  : (data.uuid?.toString?.() ?? '');

const sendStatus = (result) => {
  try {
    bot._client.write('resource_pack_receive', { uuid, result });
  } catch (e) {
    console.error(`[${bot.username}] [RP] write error (result=${result}):`, e.message);
  }
};

// result 3 = accepted, result 0 = successfully loaded
sendStatus(3);
setTimeout(() => sendStatus(0), 1000);

console.log(`[${bot.username}] [RP] Odpowiedź wysłana ✓`);

});

// ── MC 1.8–1.20.2: stary event ───────────────────────────
bot._client.on('resource_pack_send', (data) => {
console.log([${bot.username}] [RP] resource_pack_send hash=${data.hash});
try {
bot._client.write('resource_pack_receive', { hash: data.hash, result: 3 });
setTimeout(() => {
try {
bot.client.write('resource_pack_receive', { hash: data.hash, result: 0 });
} catch (
) {}
}, 1000);
console.log([${bot.username}] [RP] Odpowiedź wysłana ✓);
} catch (e) {
console.error([${bot.username}] [RP] Błąd:, e.message);
}
});
}

// ============================================================
// PATHFINDER
// ============================================================
async function goToWaypoint(bot) {
try {
const { x, y, z } = config.waypoint;
const mcData = require('minecraft-data')(bot.version);
const movements = new Movements(bot, mcData);
movements.canDig = false;
movements.allowFreeMotion = true;
bot.pathfinder.setMovements(movements);
bot.pathfinder.setGoal(new goals.GoalNear(x, y, z, 2));
console.log([${bot.username}] Idę do waypointa (${x}, ${y}, ${z}));
} catch (err) {
console.error([${bot.username}] Błąd pathfindera:, err.message);
}
}

// ── Losowe ruchy kamerą ──────────────────────────────────────
function startCameraWiggle(bot) {
const wiggle = () => {
if (!bot || bot.ended) return;
try {
bot.look(
bot.entity.yaw + (Math.random() - 0.5) * 0.3,
bot.entity.pitch + (Math.random() - 0.5) * 0.2,
false
);
} catch (_) {}
setTimeout(wiggle, 8000 + Math.random() * 7000);
};
setTimeout(wiggle, 5000);
}

// ============================================================
// TWORZENIE BOTA
// ============================================================
function createBot(nick, ip, port, mode, discordChannel) {
// Zamknij starą instancję
if (bots.has(nick)) {
const old = bots.get(nick);
try { old.bot.quit(); } catch (_) {}
bots.delete(nick);
}

let bot;
try {
bot = mineflayer.createBot({
host: ip,
port: port || 25565,
username: nick,
version: config.mcVersion,
auth: 'offline',
checkTimeoutInterval: 30000,
hideErrors: false,
});
} catch (err) {
console.error([${nick}] Nie udało się utworzyć bota:, err.message);
return null;
}

const state = {
nick,
ip,
port: port || 25565,
mode,
online: false,
loggedIn: false,
loginSent: false,
resumed: false,
discordChannel,
reconnectTimer: null,
};

bots.set(nick, { bot, state });
bot.loadPlugin(pathfinder);

// Pakiety resource pack ZAWSZE przed innymi eventami
attachResourcePackHandler(bot);

// ── Wyślij /login ────────────────────────────────────────
async function sendLogin() {
if (state.loginSent || state.loggedIn || bot.ended) return;
state.loginSent = true;
await sleep(500);
console.log([${nick}] >>> /login ${config.botPassword});
try {
bot.chat(/login ${config.botPassword});
} catch (e) {
console.error([${nick}] Błąd /login:, e.message);
state.loginSent = false;
}
}

// ── Wyślij /register ─────────────────────────────────────
async function sendRegister(code) {
if (state.loginSent || state.loggedIn || bot.ended) return;
state.loginSent = true;
await sleep(500);
const cmd = code
? /register ${config.botPassword} ${config.botPassword} ${code}
: /register ${config.botPassword} ${config.botPassword};
console.log([${nick}] >>> ${cmd});
try {
bot.chat(cmd);
} catch (e) {
console.error([${nick}] Błąd /register:, e.message);
state.loginSent = false;
}
}

// ── spawn ─────────────────────────────────────────────────
bot.once('spawn', () => {
state.online = true;
console.log([${nick}] Połączony – tryb: ${mode});

if (mode === 'login') {
  setTimeout(() => {
    if (!state.loginSent && !state.loggedIn) {
      console.log(`[${nick}] Fallback /login (serwer milczał 6s)`);
      sendLogin();
    }
  }, 6000);
}

});

// ── Wiadomości z chatu ────────────────────────────────────
bot.on('message', async (jsonMsg) => {
const text = jsonMsg.toString();
const lower = text.toLowerCase();
console.log([${nick}] CHAT: ${text});

// ── Trigger /login ───────────────────────────────────
if (mode === 'login' && !state.loginSent && !state.loggedIn) {
  if (
    lower.includes('/login') ||
    lower.includes('zaloguj') ||
    lower.includes('wpisz hasło') ||
    lower.includes('please login') ||
    lower.includes('use /login') ||
    lower.includes('musisz się zalogować')
  ) {
    console.log(`[${nick}] Serwer poprosił o /login`);
    await sendLogin();
  }
}

// ── Trigger /register ────────────────────────────────
if (mode === 'register' && !state.loginSent && !state.loggedIn) {
  const codeMatch = text.match(/\b(\d{6,8})\b/);

  if (
    lower.includes('/register') ||
    lower.includes('zarejestruj') ||
    lower.includes('please register') ||
    lower.includes('use /register')
  ) {
    console.log(`[${nick}] Serwer poprosił o /register`);
    await sendRegister(codeMatch ? codeMatch[1] : null);
  } else if (codeMatch && !state.loginSent) {
    console.log(`[${nick}] Znaleziono kod: ${codeMatch[1]}`);
    await sendRegister(codeMatch[1]);
  }
}

// ── Detekcja udanego logowania ────────────────────────
if (!state.loggedIn && (
  lower.includes('zalogowany')           ||
  lower.includes('zalogowano')           ||
  lower.includes('zarejestrowany')       ||
  lower.includes('zarejestrowano')       ||
  lower.includes('logged in')            ||
  lower.includes('welcome back')         ||
  lower.includes('successfully logged')  ||
  lower.includes('pomyślnie zalogowano') ||
  lower.includes('dobrego grania')       ||
  lower.includes('miłej gry')
)) {
  state.loggedIn = true;
  console.log(`[${nick}] ✓ Zalogowany`);
  await sleep(config.delays.afterLogin);
  startCameraWiggle(bot);
  await goToWaypoint(bot);
}

});

// ── windowOpen – obsługa GUI ──────────────────────────────
bot.on('windowOpen', async (window) => {
console.log([${nick}] GUI otwarte: "${window.title}");
const title = (window.title || '').toLowerCase();

if (title.includes('regulamin') || title.includes('rules') || title.includes('terms')) {
  console.log(`[${nick}] GUI regulaminu – klikam slot 11`);
  await sleep(600);
  try { bot.clickWindow(11, 0, 0); } catch (_) {}
}

if (title.includes('afk')) {
  console.log(`[${nick}] GUI AFK – klikam slot 13`);
  await sleep(600);
  try { bot.clickWindow(13, 0, 0); } catch (_) {}
}

});

// ── kicked ────────────────────────────────────────────────
bot.on('kicked', (reason) => {
state.online = false;
state.loggedIn = false;
console.log([${nick}] Wyrzucony: ${JSON.stringify(reason)});
scheduleReconnect(nick, state, discordChannel);
});

// ── error ─────────────────────────────────────────────────
bot.on('error', (err) => {
if (['ECONNRESET', 'ECONNREFUSED', 'ETIMEDOUT'].includes(err.code)) {
console.log([${nick}] Połączenie zresetowane (${err.code}));
} else {
console.error([${nick}] Błąd: ${err.message});
}
});

// ── end ───────────────────────────────────────────────────
bot.on('end', (reason) => {
state.online = false;
state.loggedIn = false;
bot.ended = true;
console.log([${nick}] Rozłączony (${reason || 'brak powodu'}));
if (state.reconnectTimer !== 'MANUAL') {
scheduleReconnect(nick, state, discordChannel);
}
});

// ── goal_reached ──────────────────────────────────────────
bot.on('goal_reached', () => {
console.log([${nick}] ✓ Dotarłem do celu);
});

return bot;
}

// ── Auto-reconnect ───────────────────────────────────────────
function scheduleReconnect(nick, state, discordChannel) {
if (state.reconnectTimer) return;
state.reconnectTimer = setTimeout(() => {
state.reconnectTimer = null;
console.log([${nick}] Auto-reconnect...);
createBot(nick, state.ip, state.port, state.mode, discordChannel);
}, config.delays.reconnect);
}

// ── Publiczne API ────────────────────────────────────────────

async function connectAll(ip, port, mode, discordChannel) {
let [host, p] = ip.includes(':') ? ip.split(':') : [ip, port];
p = parseInt(p) || 25565;
for (const nick of config.botNicks) {
createBot(nick, host, p, mode, discordChannel);
await sleep(20000);
}
}

function disconnectBot(nick) {
if (nick) {
const entry = bots.get(nick);
if (entry) {
clearTimeout(entry.state.reconnectTimer);
entry.state.reconnectTimer = 'MANUAL';
try { entry.bot.quit('disconnect'); } catch () {}
bots.delete(nick);
}
} else {
for (const [, entry] of bots.entries()) {
clearTimeout(entry.state.reconnectTimer);
entry.state.reconnectTimer = 'MANUAL';
try { entry.bot.quit('disconnect all'); } catch (
) {}
}
bots.clear();
}
}

async function reconnectAll(discordChannel) {
const snapshot = [...bots.entries()];
for (const [nick, { state }] of snapshot) {
disconnectBot(nick);
await sleep(300);
createBot(nick, state.ip, state.port, state.mode, discordChannel);
await sleep(800);
}
}

function getBots() { return bots; }

function resumeAll() {
for (const [nick, { bot, state }] of bots.entries()) {
if (!state.online || bot.ended) return;
state.resumed = true;
console.log([${nick}] RESUME – akceptuję regulamin + idę do waypointa);

if (bot.currentWindow) {
  const title = (bot.currentWindow.title || '').toLowerCase();
  if (title.includes('regulamin') || title.includes('rules')) {
    sleep(400).then(() => { try { bot.clickWindow(11, 0, 0); } catch (_) {} });
  }
}

bot.once('windowOpen', async (window) => {
  const title = (window.title || '').toLowerCase();
  if (title.includes('regulamin') || title.includes('rules') || title.includes('terms')) {
    console.log(`[${nick}] RESUME GUI – klikam slot 11`);
    await sleep(500);
    try { bot.clickWindow(11, 0, 0); } catch (_) {}
    await sleep(1000);
    goToWaypoint(bot);
  }
});

sleep(1500).then(() => goToWaypoint(bot));

}
}

module.exports = {
connectAll,
disconnectBot,
reconnectAll,
getBots,
resumeAll,
goToWaypoint,
safeChat,
sleep,
};

Expected behavior

Then it should install resource pack after !connect anarchia.gg so firstly log in then accept resource pack

here are some logs tho:
[NurekKosmitaxz3] CHAT: Zostałeś pomyślnie zalogowany!
[NurekKosmitaxz3] ✓ Zalogowany
[NurekKosmitaxz3] CHAT: Trwa inicjalizacja do serwera...
[NurekKosmitaxz3] CHAT: Trwa inicjalizacja do serwera...
[NurekKosmitaxz3] CHAT: Trwa inicjalizacja do serwera...
[NurekKosmitaxz3] CHAT: Trwa inicjalizacja do serwera...
[NurekKosmitaxz3] CHAT: Trwa inicjalizacja do serwera...
[NurekKosmitaxz3] CHAT: Trwa inicjalizacja do serwera...
[NurekKosmitaxz3] CHAT: Trwa inicjalizacja do serwera...
[NurekKosmitaxz3] [RP] add_resource_pack uuid=b40fe165-b06d-4b2b-be03-8021c6f89fa9
[NurekKosmitaxz3] [RP] Odpowiedź wysłana ✓
[NurekKosmitaxz6] Auto-reconnect...
[NurekKosmitaxz3] CHAT: Aby zagrać na serwerze ANARCHIA.GG musisz pobrać nasze serwerowe zasoby!
[undefined] [PACKS] select_known_packs (1 packs)
[undefined] [PACKS] Odpowiedź wysłana ✓
[NurekKosmitaxz6] CHAT: Zaloguj się komendą /login <hasło>
[NurekKosmitaxz6] Serwer poprosił o /login
[NurekKosmitaxz2] Auto-reconnect...
[undefined] [PACKS] select_known_packs (1 packs)
[undefined] [PACKS] Odpowiedź wysłana ✓
[NurekKosmitaxz3] CHAT: Czekamy na odpowiedź o pomyślnym pobraniu zasobów serwera!
[NurekKosmitaxz3] CHAT: Czekamy na odpowiedź o pomyślnym pobraniu zasobów serwera!
[NurekKosmitaxz3] CHAT: Czekamy na odpowiedź o pomyślnym pobraniu zasobów serwera!
[NurekKosmitaxz3] CHAT: Czekamy na odpowiedź o pomyślnym pobraniu zasobów serwera!

Metadata

Metadata

Assignees

No one assigned

    Labels

    Stage1just created by someone new to the project, we don't know yet if it deserves an implementation / a fpossible bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions