addon.js
// ==UserScript==
// @name         cytrus = kot
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://*.margonem.pl
// @grant        none
// ==/UserScript==
class Game {
    constructor(){
        this.ws = new WebSocket('ws://localhost:8080');
        g.delays.limit = 150;
        this.mobs = () => {
            return Object.values(g.npc).filter(npc => (npc.type == 2 || npc.type == 3) && !npc.hasOwnProperty('walkover'));
          }
        this.storage = JSON.parse(localStorage.getItem('mamon666')) || {
                position: { x: 0, y: 0 },
                ExpButton: false,
                TuniaButton: false,
                expMapy: "",
                selectedIndex: 0,
                minlvl: 1,
                maxlvl: 300,
                }
        };
    createMenu(){

const maindiv = document.createElement("div")
maindiv.id = 'main-div'
maindiv.style.cssText = `border-radius: 20px;border: 2px solid #0bff8b;background: linear-gradient(90deg, rgba(46,46,52,1) 0%, rgba(0,0,0,1) 35%, rgba(55,55,55,1) 100%);width: 416px;height: 320px;position: absolute;display: block;top: ${this.storage.position.x}px;left: ${this.storage.position.y}px;z-index: 999;`;

const title = document.createElement("div")
title.innerHTML = "<h2>nienawidze bociarzy</h2>"
title.id = 'main-title'

const content = document.createElement("div")
content.id = 'main-content'

const h1 = document.createElement('h');
h1.textContent = 'Exp';

const expButton = document.createElement('input');
expButton.type = 'checkbox';
expButton.id = 'ExpButton';
expButton.checked = this.storage.ExpButton;

const tuniaH1 = document.createElement('h');
tuniaH1.textContent = 'Tunia';

const tuniaButton = document.createElement('input');
tuniaButton.type = 'checkbox';
tuniaButton.id = 'TuniaButton';
tuniaButton.checked = this.storage.TuniaButton;

const gotomapsdiv = document.createElement('textarea');
gotomapsdiv.placeholder = 'Mapy do chodzenia..';
gotomapsdiv.id = 'gotomaps';

const lvlsdiv = document.createElement('span');

const lvlH1 = document.createElement('h');
lvlH1.textContent = 'Lvl:';

const minlvldiv = document.createElement('input');
minlvldiv.type = 'text';
minlvldiv.id = 'minlvl';

const hyphen = document.createElement('h');
hyphen.textContent = '-';

const maxlvldiv = document.createElement('input');
maxlvldiv.type = 'text';
maxlvldiv.id = 'maxlvl';

const selectsetup = document.createElement("select");
selectsetup.id = 'main-setups'
selectsetup.style = "margin-left: 10px;margin-top: -4px;color: rgb(75 255 0);border-width: 1px;border-style: solid;border-radius: 2px;border-color: rgb(0 255 119);background: rgba(0, 0, 0, 0.1);width: 268px;";

const save = document.createElement('button');
save.textContent = 'Zapisz';
save.id = 'save';

lvlsdiv.append(lvlH1, minlvldiv, hyphen, maxlvldiv, selectsetup);
content.append(h1, expButton, tuniaH1, tuniaButton, gotomapsdiv, lvlsdiv, save);
maindiv.append(title, content);
document.body.appendChild(maindiv);
this.loadSetups();
save.addEventListener('click', () => {
    this.saveSetup()
});

selectsetup.addEventListener("change",this.changeSetup)

expButton.addEventListener('change', () => {
    if(expButton.checked){
        this.storage.ExpButton = true;
        this.attackLoop()
    } else {
        this.storage.ExpButton = false;
        this.ws.send(JSON.stringify({type: 'stop'}))
    }
    localStorage.setItem('mamon666', JSON.stringify(this.storage));
});

tuniaButton.addEventListener('change', () => {
    TuniaButton.checked ? this.storage.TuniaButton = true : this.storage.TuniaButton = false;
    localStorage.setItem('mamon666', JSON.stringify(this.storage));
});

$("#main-div").draggable({
    scroll: !1,
    start: () => {
        g.mouseMove.enabled = !1
    },
    stop: (e, ui) => {
        g.mouseMove.enabled = !0;
        this.storage.position = {
            x: ui.position.top,
            y: ui.position.left
        }

        localStorage.setItem('mamon666', JSON.stringify(this.storage))
    }
})
minlvldiv.value = this.storage.minlvl
maxlvldiv.value = this.storage.maxlvl
gotomapsdiv.value = this.storage.expMapy
selectsetup.selectedIndex = this.storage.selectedIndex
$('<link rel="stylesheet" type="text/css" href="https://cytrusek7331.ct8.pl/bot/style.css"/>').appendTo('head');
    }
     saveSetup(){
        this.storage.minlvl = Number(document.querySelector("#minlvl").value);
        this.storage.maxlvl = Number(document.querySelector("#maxlvl").value);
        this.storage.expMapy = document.querySelector("#gotomaps").value;
        localStorage.setItem('mamon666', JSON.stringify(this.storage))
        message("Zapisano ustawienia!")
        }
        async loadSetups() {
            await fetch('https://cytruszef.ct8.pl/?setupy', {
                method: 'GET',
                headers: {
                    'Content-Type': 'application/json'
                }
            })
            .then(res => {
                if (!res.ok) {
                    throw new Error('Network response was not ok');
                }
                return res.json();
            })
            .then(v => {
                const setups = document.querySelector("#main-setups");
                for (let t = 0; t < v.length; t++) {
                    const i = document.createElement("option");
                    i.value = `${v[t].lvl};${v[t].value}`;
                    i.innerText = v[t].name;
                    setups.appendChild(i);
                }
            })
        console.log("Załadowano setupy!")
        };
        changeSetup = () => {
            const selectedSetup = document.querySelector("#main-setups").value.split(";")
            const lvls = selectedSetup[0].split("-")
            const minlvl = Number(lvls[0])
            const maxlvl = Number(lvls[1])
            this.storage.expMapy = selectedSetup[1]
            this.storage.minlvl = minlvl
            this.storage.maxlvl = maxlvl
            this.storage.selectedIndex = document.querySelector("#main-setups").selectedIndex
            localStorage.setItem('mamon666', JSON.stringify(this.storage))
            document.querySelector("#gotomaps").value = this.storage.expMapy
            document.querySelector("#minlvl").value = minlvl
            document.querySelector("#maxlvl").value = maxlvl
            document.querySelector("#main-setups").selectedIndex = this.storage.selectedIndex
          };
          async attackLoop() {
            let mob;
            const expMaps = this.storage.expMapy.split(',');
            
            while (this.storage.ExpButton) {
            mob = this.closestMob({ min: this.storage.minlvl, max: this.storage.maxlvl });
            
            if (!mob) {
            const currentMapIndex = expMaps.indexOf(mapid.toString()),
            nextMap = currentMapIndex !== -1 ? expMaps[currentMapIndex + 1] : (await this.getRoute(expMaps[0])).split(',')[1];
            await this.goToMap(Number(nextMap));
            } else {
            if (this.getDistanceToNpc(mob.x, mob.y) === 1) {
            window._g(`fight&a=attack&ff=1&id=-${mob.id}`);
            await new Promise(resolve => setTimeout(resolve, 500));
            } else {
            await this.goTo(mob.x, mob.y);
            await new Promise(resolve => setTimeout(resolve, Math.round(this.getDistanceToNpc(mob.x, mob.y)) * 300));
            }
            }
            }
            }
          
     getPath(x, y){
        return new AStar(map.col, map.x,map.y, {x: hero.x,y: hero.y}, {x: x,y: y},g.npccol).anotherFindPath();
    }
    goTo(x,y){
        const path = this.getPath(x,y)
        const message = {
            type: 'path',
            current: { x: hero.x, y: hero.y },
            path: path.map(point => ({
                x: point.x,
                y: point.y,
              })).reverse(),
          }
            this.ws.send(JSON.stringify(message))
    }
     async goToMap(id){
        let x = g.gwIds[id].split('.')[0];
        let y = g.gwIds[id].split('.')[1];
        if(map.id == id) return true;
        while(g.gwIds[id] && hero.x ==! x && hero.y !== y){
            this.goTo(x,y);
            await new Promise(resolve => setTimeout(resolve, this.getDistanceToNpc(x,y)*300));
        }
            _g("walk");
        }
    async getRoute(id){
        const a = await fetch(`https://cytruszef.ct8.pl?start=${map.id}&end=${id}`).then(res => res.json())
        return a.defaultPath
}

    closestMob(lvl={min,max}){
            let closestDist = 9999;
            let closestMonster;
            for (const npc of this.mobs()) {
              if(npc.lvl >= lvl.min&&npc.lvl <= lvl.max){
            const path = this.getPath(npc.x,npc.y)
              if (path == undefined || path.length == 0) continue;
              const pathLength = path.length;
              if (pathLength < closestDist) {
                closestDist = pathLength;
                closestMonster = npc;
              }
            }
          }
            return closestMonster;
    }
     getDistanceToNpc = (x,y) => {
        const path = this.getPath(x,y);
        return Array.isArray(path) ? path.length : void 0;
      }

    init(){
        g.loadQueue.push({fun:()=>{
            this.createMenu()
            this.ws.send(JSON.stringify({type: 'init'}))
        }})
        const e = () =>{
            if(g.init == 5) this.storage.ExpButton ? this.attackLoop() : null;
            else{
                setTimeout(e, 1000)
            }
        };
        e();
    }
}
const bot = new Game;
bot.init()


class AStar {
    constructor(collisionsString,width,height,start,end,additionalCollisions) {
        this.width = width;
        this.height = height;
        this.collisions = this.parseCollisions(collisionsString, width, height);
        this.additionalCollisions = additionalCollisions || {};
        this.start = this.collisions[start.x][start.y];
        this.end = this.collisions[end.x][end.y];
        this.start.beginning = true;
        this.start.g = 0;
        this.start.f = heuristic(this.start, this.end);
        this.end.target = true;
        this.end.g = 0;
        this.addNeighbours();
        this.openSet = [];
        this.closedSet = [];
        this.openSet.push(this.start);
    }
    parseCollisions(collisionsString, width, height) {
        const collisions = new Array(width);
        for (let w = 0; w < width; w++) {
            collisions[w] = new Array(height);
            for (let h = 0; h < height; h++) {
                collisions[w][h] = new Point(w,
                                             h,
                                             collisionsString.charAt(w + h * width) === "1"
                                            );
            }
        }
        return collisions;
    }
    addNeighbours() {
        for (let i = 0; i < this.width; i++) {
            for (let j = 0; j < this.height; j++) {
                this.addPointNeighbours(this.collisions[i][j]);
            }
        }
    }
    addPointNeighbours(point) {
        const x = point.x,
              y = point.y;
        const neighbours = [];
        if (x > 0) neighbours.push(this.collisions[x - 1][y]);
        if (y > 0) neighbours.push(this.collisions[x][y - 1]);
        if (x < this.width - 1) neighbours.push(this.collisions[x + 1][y]);
        if (y < this.height - 1) neighbours.push(this.collisions[x][y + 1]);
        point.neighbours = neighbours;
    }
    anotherFindPath() {
        while (this.openSet.length > 0) {
            let currentIndex = this.getLowestF();
            let current = this.openSet[currentIndex];
            if (current === this.end) return this.reconstructPath();
            else {
                this.openSet.splice(currentIndex, 1);
                this.closedSet.push(current);
                for (const neighbour of current.neighbours) {
                    if (this.closedSet.includes(neighbour)) continue;
                    else {
                        const tentative_score = current.g + 1;
                        let isBetter = false;
                        if (this.end == this.collisions[neighbour.x][neighbour.y] || (!this.openSet.includes(neighbour) && !neighbour.collision && !this.additionalCollisions[neighbour.x + 256 * neighbour.y])) {
                            this.openSet.push(neighbour);
                            neighbour.h = heuristic(neighbour, this.end);
                            isBetter = true;
                        } else if (tentative_score < neighbour.g && !neighbour.collision) {
                            isBetter = true;
                        }
                        if (isBetter) {
                            neighbour.previous = current;
                            neighbour.g = tentative_score;
                            neighbour.f = neighbour.g + neighbour.h;
                        }
                    }
                }
            }
        }
    }
    getLowestF() {
        let lowestFIndex = 0;
        for (let i = 0; i < this.openSet.length; i++) {
            if (this.openSet[i].f < this.openSet[lowestFIndex].f) lowestFIndex = i;
        }
        return lowestFIndex;
    }
    reconstructPath() {
        const path = [];
        let currentNode = this.end;
        while (currentNode !== this.start) {
            path.push(currentNode);
            currentNode = currentNode.previous;
        }
        return path;
    }
}
class Point {
    constructor(x, y, collision) {
        this.x = x;
        this.y = y;
        this.collision = collision;
        this.neighbours = [];
        this.target = false;
    }
}
function heuristic(p1, p2) {
    return Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y);
}



index.js
import puppeteer from 'puppeteer';
import {goTo} from './pathfinder/pathfinder.js'
import {WebSocketServer} from 'ws';
class Game {
  constructor() {}
    async initGame(){
    const wss = new WebSocketServer({
      port: 8080
    });
    const cookies = [{
      'name': 'intro',
      'value': '1',
      'domain': '.margonem.pl',
    }, {
      'name': 'interface',
      'value': 'si',
      'domain': '.margonem.pl'
    }, {
    'name': '__mExts',
    'value': 'd149364',
    'domain': '.margonem.pl'
    }]
    const browser = await puppeteer.launch({
      headless: false,
      args: ['--disable-extensions-except=C:/Users/cytrus/Desktop/main/margonem/botaddon/vpn','--window-size=500,300'],
    });
    const page = await browser.newPage();
    await page.setViewport({
      width: 1920,
      height: 1080,
      deviceScaleFactor: 1,
    });
    await page.evaluateOnNewDocument(() => {
      Object.defineProperty(navigator, 'webdriver', {
        get: () => false
      })
    });
    await page.setUserAgent('Mozilla/5.0 (Linux; Android 10; SM-T875) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.5671.215 Mobile Safari/537.36')
    await new Promise(resolve => setTimeout(resolve, 30000));
    await page.setCookie(...cookies);
    await page.goto('https://www.margonem.pl/',{timeout: 120000});
    await page.waitForSelector('input[name=login]',{timeout: 60000});
    await page.waitForSelector('input[name=password]',{timeout: 60000})
    await page.$eval('input[name=login]', el => el.value = 'CytruSek7331');
    await page.$eval('input[name=password]', el => el.value = 'eluwina123');
    const element2 = await page.waitForSelector("#js-login-btn > span", {timeout: 60000})
    await element2.click();
    await page.waitForNavigation({waitUntil: 'networkidle0',timeout: 80000})
    console.log('logged in')
    wss.on('connection', ws => {
      ws.on('message', async message => {
          message = JSON.parse(message)
          switch (message.type) {
              case 'path':
              await goTo(page,message.path,message.current)
              break;
              case 'stop':
              await goTo(page,message.path,message.current)
              break;
              case 'init':
              ws.send('init')
              break;
          }
      })
  })
  }
}
const game = new Game();
game.initGame()
pathfinder.js
export async function goTo(page, path, current = { x, y }) {
  console.log('trasa smieciu', path);
  for (let i = 0; i < path.length; i++) {
    const next = path[i];
    let direction;
    let steps = 0;

    if (next.x > current.x) {
      direction = 'KeyD';
      steps = next.x - current.x;
      current.x += steps;
    } else if (next.x < current.x) {
      direction = 'KeyA';
      steps = current.x - next.x;
      current.x -= steps;
    } else if (next.y > current.y) {
      direction = 'KeyS';
      steps = next.y - current.y;
      current.y += steps;
    } else if (next.y < current.y) {
      direction = 'KeyW';
      steps = current.y - next.y;
      current.y -= steps;
    }

    if (direction) {
      if (steps > 2) {
        await holdKey(page, direction, steps);
      } else {
        await moveHero(page, direction);
      }
    }
  }

  async function holdKey(page, direction, steps) {
    await page.focus('body');
    await page.keyboard.down(direction);
    await new Promise(resolve => setTimeout(resolve, 300 * (steps - 2)));
    await page.keyboard.up(direction);
    await new Promise(resolve => setTimeout(resolve, 200));
  }

  async function moveHero(page, direction) {
    await page.focus('body');
    await page.keyboard.down(direction);
    setTimeout(async () => {
      await page.keyboard.up(direction);
    }, 100);
    await new Promise(resolve => setTimeout(resolve, 250));
  }
}


Dlaczego moja przeglądarka po nacisnięciu przycisku do włączania bota i wybraniu zestawu gdzie ani nie ma moba na mapie, ani mapa nie jest expmaps odświeża stronę raz a po załadowaniu ponownym wysyła mnóstwo requestów przez getRoute i wyłącza przeglądarke z błędem:
export async function goTo(page, path, current = { x, y }) {
                                                   ^

ReferenceError: x is not defined