Онлайн игра бот производительности - PullRequest
0 голосов
/ 07 июня 2019

Я создаю бота для динамической онлайн-игры. В этом случае динамический означает, что игра героя может перемещаться, и фон меняется при движении. Глобальные переменные, такие как monsters, также изменяют динамику при движении.

Мой бот использует кукловода. Так как мне нужен этот объект монстров, у меня есть функция, которая получает этих монстров из контекста страницы каждые 2 - 3 секунды (рандомизирует для обнаружения).

Это решение далеко от совершенства. Два основных недостатка:

  • Мой бот убивает монстра, и я хочу перейти к следующему, он все еще видит этого монстра, который был убит, потому что следующее обновление, например, через 1500 мс с того времени.
  • Производительность получения монстров плохая.

Чтобы решить первый, я мог просто выполнить функцию, которая загружает монстров каждый раз после убийства одного. С другой стороны, второй даунсайд будет еще сильнее, потому что я сделаю гораздо больше, получая монстра, который уже медленный.

Все это касается второй проблемы - производительности. Вы можете спросить, откуда мне знать, что производительность плохая?

Когда герой движется, он относительно плавный, но когда загружаются монстры, я вижу микро-лаг, как часть остановки второго героя. Это действительно может быть 100 мс лага, но я могу видеть это человеческим глазом, и если я буду выполнять получение монстра чаще, это лаг будет становиться сильнее (чтобы быть ясным - лаг не будет длиннее, но чаще).

Загрузка объекта из глобального окна занимает много времени. Причина в том, что разработчики игр разработали его так, чтобы monsters находились внутри большого объекта npc, который содержит все, что находится на приборной панели, и содержит даже пустые элементы, поэтому общее количество этого npc объекта находится между 100k-200k элементами. Я делаю много фильтров, чтобы получить окончательные данные монстров, которые меня волнуют.

Я покажу, как я на самом деле получаю этих монстров. Поэтому я выполняю 3 асинхронные функции:

const allNpc = await getAllNpc(page);
let monsters = await filterMonsters(page, allNpc, monstersToHunt);
monsters.hunt = await deleteAvoidedMonsters(page, monsters.hunt, monstersToOmit);

Первый getAllNpc просто получить весь объект NPC (этот большой, который я упоминал выше)

return await page.evaluate(() => {
    if(window.g) return g.npc;
});

вторая функция фильтра реальных монстров и монстров, которых я хочу убить из NPC:

return new Promise((resolve, reject) => {
    const validNpc = allNpc.filter(el => !!el);
    const allMonsters = validNpc.filter(e => e.lvl !== 0);

    const names = new Set(monstersNames);
    const huntMonsters = validNpc
        .filter(it => names.has(it.nick))
        .map(({ nick, x, y, grp, id }) => ({ nick, x, y, grp, id }));

    resolve({all: allMonsters, hunt: huntMonsters});
});

Я использую Set здесь, чтобы избавиться от алгоритмов O (n) / O (n ^ 2), и я думаю, что это быстрее всего я могу достичь с помощью JavaScript. Третья функция такая же, как эта, но дополнительно фильтрует специальных монстров, которых я хочу избежать.

Теперь мои вопросы:

  • есть ли способ получить этот объект на каждом этом объекте, и только этот объект изменяется? Я знаю, что в кукловоде есть функция, которая может наблюдать за изменениями DOM, но есть ли что-то, чтобы наблюдать глобальный объект окна?
  • Могу ли я сделать что-нибудь еще, чтобы ускорить его? Я читал о worker_threads в NodeJS, может ли это помочь избавиться от этой микро-задержки или чего-то еще? Кластеризация?
...