Greasy Fork

.io & Agar.io Clone Bots - 2022

The best open sourced & proxyless bots for .io & agar.io clone games.

目前为 2022-01-08 提交的版本。查看 最新版本

// ==UserScript==
// @name         .io & Agar.io Clone Bots - 2022
// @namespace    https://greasyfork.org/en/scripts/433283-io-agar-io-clone-bots-2022
// @version      23.5
// @description  The best open sourced & proxyless bots for .io & agar.io clone games.
// @author       Tatsuya
// @match        *.cubedot.kr/*
// @match        *.agar.cc/*
// @match        *.aquar.io/*
// @match        *.oceanar.io/*
// @match        *.agar.rip/*
// @match        *.agario.network/*
// @match        *.agario.work/*
// @match        *.agario.zafer2.com/*
// @match        *.agarabi.net/*
// @match        *.agario.boston/*
// @match        *.agar.chat/*
// @match        *.agario.nl/*
// @match        *.agariomoddedserver.com/*
// @match        *.agario.in/*
// @match        *.agario.id/*
// @match        *.agariomodded.com/*
// @match        *.bestagario.org/*
// @match        *.agariohub.cc/*
// @match        *.agar.team/*
// @match        *.agarprivateservers.org/*
// @match        *.agarprivateservers.net/*
// @match        *.agarprivateserver.com/*
// @match        *.agario.cc/*
// @match        *.easyagario.icu/*
// @run-at       document-start
// @icon         https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTJNVczs2oU6qdgJBw2ZSSe4ibVAGjaZMgWosjYzjXZU1B6Lp9MHoQ27ARzAtofWYHxz3U&usqp=CAU
// @grant        none
// ==/UserScript==

class Client {
    constructor() {
        this.BotAmount = 60;
        this.spawned = 0; this.serverIP = ''; this.positioning = { 'x': 0, 'y': 0}; this.movebuf = null; this.countInt = null; this.started = false; this.bots = []; this.gui = new GUI(this.startBots.bind(this), this.stopBots.bind(this), this.split.bind(this), this.eject.bind(this), this.InitMsg.bind(this));
        this.setup();
    }

    setup() { alert("Thanks for using the bots. Make sure to join my discord for any updates. These bots are up to date as of Jan 1, 2022. More games coming soon, make sure to check the greasyfork page for more updates."); for(let i = 0; i < this.BotAmount; i++) {this.bots.push(new Bot())}; this.UpdateCount(); this.HookMouse()};

    HookMouse() { this.countInt = setInterval(() => {this.bots.forEach(bot => {bot.sendmouse(this.movebuf)})}, 50)};

    UpdateCount() { this.countInt = setInterval(() => {this.gui.updateCount(this.spawned, this.BotAmount)}, 1000)}

    split() {this.bots.forEach((bot, i) => {bot.split()})}

    eject() {this.bots.forEach((bot, i) => {bot.eject()})}

    InitMsg() {};

    startBots() { if (this.started || !this.serverIP) return; if (this.serverIP == undefined) return; this.bots.forEach((bot, i) => { bot.connect(this.serverIP)}); this.started = true };

    stopBots() { if(!this.started) return; this.bots.forEach((bot, i) => { bot.close() }); this.started = false };
}

class GUI {
    constructor(start, stop, split, eject, spamMSG) {
        this.IDs = {
            'startButton': 'startbtn',
            'stopButton': 'stopbtn',
            'botCount': 'botAmount',
            'DiscordURL': 'discord'
        };
        this.injected = false;
        this.startBots = start; this.stopBots = stop; this.splitBots = split; this.ejectBots = eject; this.spamChat = spamMSG;
        this.inject(); this.setupKeys();
    }
    inject() {
        this.uiCode =
        `
        <div div="" id="mainUI" style='margin-left: 10px; top: 50%; transform: translateY(-50%); position: absolute; border: 2px solid rgb(255, 255, 255); border-radius: 2px;
        text-align: center; z-index: 999999; background-color: rgba(0, 0, 0, 0.7); font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;' > <h4 style="color: rgb(255,255,255); margin: 4px;">.io Bots!</h4>
        <div div = ""; id = "discord" style="color: white; margin: 1px; font-size: 12px; cursor: pointer; ">discord.gg/bAstbAfem9</div>
        <div><p div="" id="botAmount" style="color: rgb(50, 255, 88);">0 / 0</p></div> <div style="margin: 5px;">
        <button div="" id="startbtn" style="background-color: rgb(50, 255, 88); color: white; border: rgb(56, 211, 84); padding: 5px; border-radius: 2px;" >
        Start Bots</button ><button div="" id="stopbtn" style="margin-left: 3px; background-color: rgb(255, 66, 66); color: white; border: rgb(199, 52, 52); padding: 5px; border-radius: 2px;" > Stop Bots </button>
        </div> </div>
        `
        this.append(this.uiCode);
    }
    append(html) {
        const BOTUI = document.createElement('div'); BOTUI.innerHTML = html; document.body.appendChild(BOTUI);
        this.injected = true;
        document.getElementById(this.IDs.startButton).onclick = this.startBots;
        document.getElementById(this.IDs.stopButton).onclick = this.stopBots;
        document.getElementById(this.IDs.DiscordURL).onclick =() => {window.location.href = 'https://discord.gg/bAstbAfem9'};
    }
    setupKeys() {
        window.addEventListener('keypress', (event) => {
            switch(event.key) {
                case 'q':
                    this.splitBots();
                    break;
                case 'w':
                    this.ejectBots();
                    break;
                case 'z':
                    this.spamChat();
                    break;
            }
        });
    }
    updateCount(spawned, max) { document.getElementById(this.IDs.botCount).innerText = spawned + " / " + max };
}

window.addEventListener('load', () => {
    const client = new Client();
    WebSocket.prototype.realSend = WebSocket.prototype.send;
    WebSocket.prototype.send = function(pkt) {
        this.realSend(pkt);
            if (typeof pkt == 'string') return;
            if (this.url.includes('localhost')) return;
            if (pkt instanceof ArrayBuffer) pkt = new DataView(pkt);
            else if (pkt instanceof DataView) pkt = pkt;
            else pkt = new DataView(pkt.buffer);
        switch(pkt.getUint8(0, true)) {
            case 16:
                client.positioning.x = pkt.getFloat64(1, true);
                client.positioning.y = pkt.getFloat64(9, true);
                break;
            case 5:
            case 14:
            case 146:
                client.movebuf = pkt.buffer;
                break;
        }
        client.serverIP = this.url;
    }
    Hooks.run(client);
});

var Hooks = {
    Client: 'function'
};

Hooks.run = (func) => {
    Hooks.Client = func;
}

class Bot {
    constructor() {
        this.server = '';
        this.origin = /(\w+)\:\/\/(\w+.\w+)/gi.exec(window.location.origin)[2];
        this.ws = null;
        this.started = false;
        this.protoV = 0x5;
        this.protoK = 0x75BCD15;
        this.Essentials = {
            botNames: ["Free Bots!", "discord.gg/bAstbAfem9", "rb.gy/kafgsw"],
            botAppearance: 255,
            botSkins: ['26', '30', '32', '40', '60', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20','21', '22', '23'],

            respawnDelay: 3000,
            moveDelay: 150,

            getBotName() { return this.botNames[Math.floor(Math.random() * this.botNames.length)] },
            getBotSkin() { return this.botSkins[Math.floor(Math.random() * this.botSkins.length)] }
        };
        this.botName = this.Essentials.getBotName();

        this.SkinName = `{${this.Essentials.getBotSkin()}}` + this.botName;

    }

    setupDependencies(url, wss) {

        if (url == "oceanar.io" || url == "aquar.io") {
            this.init = this.Proto5.bind(this);
            this.spawnop = 0;
        } else {
            this.init = this.Proto5.bind(this);
            this.spawnop = 1;
        }

        this.ws = new WebSocket(wss);
        this.ws.binaryType = "arraybuffer";
        this.ws.onopen = this.onopen.bind(this);
        this.ws.onclose = this.onclose.bind(this);
	}

    connect(wss) {

        this.server = wss;
        this.setupDependencies(this.origin, this.server);

    }

    Proto5() {
        if (this.spawnop == 0) {
            this.spawn();
            this.ping();
        } else if (this.spawnop == 1) {

        let init = this.Buffer(0x5);
        init.setUint8(
            0x0, 0xfe
        )
        init.setUint32(
            0x1, this.protoV
        );
        this.send(init);

        init = this.Buffer(0x5);

        init.setUint8(
            0x0, 0xff
        )
        init.setUint32(
            0x1, this.protoK
        );
        this.send(init);

        this.spawn();
        }

        this.spawnInt = setInterval(() => {this.spawn()}, this.Essentials.respawnDelay);
        this.mouseInt = setInterval(() => {this.sendmouse()}, this.Essentials.moveDelay);
    }

    onopen() {
        Hooks.Client.spawned++
        this.init();
    }

    spawn() {
        if (this.spawnop == 0) {

            let spawnBuf = this.Buffer(52);
            spawnBuf.setUint8(0, 22);
            var o = 0;
            for(; o < 25; ++o) {
                spawnBuf.setUint16(1 + 2 * o, o < this.botName.length ? this.botName.charCodeAt(o) : 0, true);
            }
            spawnBuf.setUint8(51, this.Essentials.botAppearance)
            this.send(spawnBuf);

        } else if (this.spawnop == 1) {

            var spawnbuf = this.Buffer(1 + 2 * this.SkinName.length);
            spawnbuf.setUint8(0, 192);
            for(var i = 0; i < this.SkinName.length; ++i) {
                spawnbuf.setUint16(1 + 2 * i, this.SkinName.charCodeAt(i), true);
            };
            this.send(spawnbuf);

        }
    }

    split() {
        if (this.spawnop == 0) {
            return;
        } else if (this.spawnop == 1) {
            this.send(new Uint8Array([17]));
        }
    }

    eject() {
        if (this.spawnop == 0) {
            return;
        } else if (this.spawnop == 1) {
            this.send(new Uint8Array([21]));
        }
    }

    sendmouse() {
        if (this.spawnop == 0) {
            this.send(Hooks.Client.movebuf);
        } else if (this.spawnop == 1) {
            let movebuf = this.Buffer(0x15);
            movebuf.setUint8(
                0x0, 0x10
            )
            movebuf.setFloat64(
                0x1, Hooks.Client.positioning.x, true
            )
            movebuf.setFloat64(
                0x9, Hooks.Client.positioning.y, true
            )
            movebuf.setUint32(
                0x11, 0x0, true
            );
            this.send(movebuf);
        }
    }

    sendchat(msg) {
        if (this.spawnop == 0) {
            return;
        } else if (this.spawnop == 1) {
        }
    }

    ping() {
        let ParseTime = 268435455 & Date.now();
        let oneByte = this.Buffer(0x5);
        oneByte.setUint8(0x0, 0x1);
        oneByte.setUint32(0x1, ParseTime);
        this.send(oneByte);
    }

    Buffer(buf) { return new DataView(new ArrayBuffer(!buf ? 1 : buf))};

    get open() {return this.ws && this.ws.readyState === WebSocket.OPEN};

    send(data) {if(this.open) {this.ws.send(data)}};

    close() { if(this.ws) this.ws.close(); this.onclose(); Hooks.Client.spawned-- };

    onclose() { clearInterval(this.spawnInt); clearInterval(this.mouseInt); clearInterval(this.sprkcore);setTimeout(() => {this.connect()}, 5000)};
}