[Old] Cellcraft.io & Agma.io Bots 2022

The best bots for popular agar.io clone games.

// ==UserScript==
// @name         [Old] Cellcraft.io & Agma.io Bots 2022
// @namespace    https://discord.com/invite/bAstbAfem9
// @version      1.0.0
// @description  The best bots for popular agar.io clone games.
// @author       Tatsuya & Enes
// @match        *.agma.io/*
// @match        *.cellcraft.io/*
// @run-at       document-start
// @icon         https://www.google.com/s2/favicons?sz=64&domain=cellcraft.io
// @grant        none
// ==/UserScript==
class Client {
    constructor() {
        this.bots = [];
        this.BotAmount = this.hookAmt;
        this.serverIP = '';
        this.positioning = {
            'x': 0,
            'y': 0
        };
        this.movebuf = null;
        this.started = false;
        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();
    }
    get hookAmt() {
        let url = /(\w+)\:\/\/(\w+.\w+)/gi.exec(window.location.origin)[2];
        if (url == "agma.io" || url == "cellcraft.io") {
            return 69;
        }
    }
    get AllowChat() {
        let url = /(\w+)\:\/\/(\w+.\w+)/gi.exec(window.location.origin)[2];
        if (url == "agma.io" || url == "cellcraft.io") {
            return true;
        }
    }
    get spawned() {
        return this.bots.filter(b => b.ws && b.ws.readyState === WebSocket.OPEN).length;
    }
    setup() {
        for (let i = 0; i < this.BotAmount; i++) {
            this.bots.push(new Bot())
        };
        this.UpdateCount();
        this.HookMouse();
    };
    HookMouse() {
        this.MouseInt = 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() {
        if (!this.started) return;
        if (!this.AllowChat) return this.gui.showPopUp("Chatspam is currently disabled for this site. Contact a developer for any questions or if you'd like for it to be enabled.");
        let msg = prompt("Enter the message you want to spam", "");
        this.bots.forEach((bot) => {
            if (msg) bot.sendChat(msg)
        })
    };
    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();
    }
    async inject() {
        this.uiCode = await this.getGUI();
        if (!this.uiCode) {
            return alert('Failed to load bot GUI. If this keeps happening, contact a developer.');
        }
        this.append(this.uiCode);
    }
    async getGUI() {
        const UI = await fetch('https://puzzling-tiny-fruit.glitch.me/');
        if (!UI.ok) {
            return console.log('[GUI STATUS]', UI);
        }
        return await UI.text();
    }
    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'
        };
        document.querySelector("#okbtn").onclick = () => {
            document.querySelector("#popup").style.display = "none";
            document.querySelector("#blackout").style.display = "none";
        };
        this.showPopUp("Thank you for using these bots. Contact Tatsuya in the Discord listed in order to unpatch the bots if they get patched. Agma.io is patched.");
    }
    setupKeys() {
        window.addEventListener('keypress', (event) => {
            switch (event.key) {
                case 'q':
                    this.splitBots();
                    break;
                case 'w':
                    this.ejectBots();
                    break;
                case 'c':
                    this.spamChat();
                    break;
            }
        });
    }
    updateCount(spawned, max) {
        document.getElementById(this.IDs.botCount).innerText = spawned + " / " + max
    };
    showPopUp(msg) {
        document.getElementById("msgpop").innerHTML = msg;
        document.querySelector("#popup").style.display = "block";
        document.querySelector("#blackout").style.display = "block";
    };
}
var HookClient = {
    Client: 'function'
};
HookClient.run = (func) => {
    HookClient.Client = func;
}
class DataFrameWriter {
    constructor() {
        this.bytes = [];
    }
    writeUint8(val) {
        this.bytes.push(val);
    }
    writeUint16(val) {
        this.bytes.push(val & 0xFF);
        this.bytes.push(val >> 8 & 0xFF);
    }
    writeUint32(val) {
        this.bytes.push(val & 0xFF);
        this.bytes.push(val >> 8 & 0xFF);
        this.bytes.push(val >> 16 & 0xFF);
        this.bytes.push(val >> 24 & 0xFF);
    }
    writeStringEx(str) {
        this.writeUint16(str.length);
        for (var i = 0; i < str.length; i++) {
            this.writeUint16(str.charCodeAt(i));
        }
    }
    writeBool(str) {
        this.writeUint8(str.length);
        for (var i = 0; i < str.length; i++) {
            this.writeUint8(str.charCodeAt(i));
        }
    }
    getBuffer() {
        return this.bytes;
    }
    getArrayBuffer() {
        return new Uint8Array(this.bytes).buffer;
    }
}
class Writer {
    constructor(a) {
        this.buffer = new DataView(new ArrayBuffer(a)), this.position = 0, this.littleEndian = true;
    }
    setString(c) {
        for (let a = 0; a < c.length; a++) this.setUint16(c.charCodeAt(a));
        return this;
    }
    setInt8(a) {
        return this.buffer.setInt8(this.position++, a), this;
    }
    setUint8(a) {
        return this.buffer.setUint8(this.position++, a), this;
    }
    setInt16(a) {
        return this.buffer.setInt16((this.position += 2) - 2, a, this.littleEndian), this;
    }
    setUint16(a) {
        return this.buffer.setUint16((this.position += 2) - 2, a, this.littleEndian), this;
    }
    setInt32(a) {
        return this.buffer.setInt32((this.position += 4) - 4, a, this.littleEndian), this;
    }
    setUint32(a) {
        return this.buffer.setUint32((this.position += 4) - 4, a, this.littleEndian), this;
    }
    setFloat32(a) {
        return this.buffer.setFloat32((this.position += 4) - 4, a, this.littleEndian), this;
    }
    setFloat64(a) {
        return this.buffer.setFloat64((this.position += 8) - 8, a, this.littleEndian), this;
    }
}
class Bot {
    constructor() {
        this.server = '';
        this.origin = /(\w+)\:\/\/(\w+.\w+)/gi.exec(window.location.origin)[2];
        this.ws = null;
        this.Essentials = {
            botNames: ["Xero-Bots"],
            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,
            response: 0,
            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;
    }
    async setupDependencies(url, wss) {
        if (url == "agma.io") {
            this.opcode = 0;
            this.Tags = {
                emgaa: 'Agma!',
                S_: 22421,
                j9: 50,
                M: 128,
                T_: 50,
                result: 0,
                A0: 33,
                Va(a, c, x, _) {
                    c + x > a.byteLength && (x = 0);
                    for (var e = 12345768 + _, t = 0; t < x; t++) e += a.getUint8(c + t) * (t + 2);
                    return e;
                },
                postAuth() {
                    return new Promise(async (resolve, reject) => {
                        window.jQuery.post("client.php", {
                            data: JSON.stringify({
                                cv: 4 * this.S_,
                                ch: this.j9,
                                ccv: this.S_,
                                vv: this.M
                            })
                        }, function(key) {
                            resolve(key);
                        });
                    });
                }
            };
            --this.Tags.T_;
            let key = await this.Tags.postAuth();
            this.Tags.result = key;
            var i = 0;
            for (; i < this.Tags.emgaa.length; i++) {
                this.Tags.T_ += this.Tags.emgaa.charCodeAt(i) * (1 - (!i || i % 2 ? 0 : 2)) - (i ? 0 : 1)
            }
        } else if (url == "cellcraft.io") {
            this.opcode = 1;
            this.Tags = {
                emgaa: 'Agma!',
                currentTime: -1,
                c: 54295,
                length: 5,
                to: 50,
                result: 0,
                formatTag: 22,
                oldNumThing: 118,
                toArray(data, offset, length, callback) {
                    if (offset + length > data.byteLength) {
                        length = 0;
                    }
                    var source = 12345678 + callback;
                    var i = 0;
                    for (; length > i; i++) {
                        source = source + data.getUint8(offset + i) * (i + 1);
                    }
                    return source;
                },
                postAuth() {
                    return new Promise(async (resolve, reject) => {
                        window.jQuery.post("client.php", {
                            data: JSON.stringify({
                                cv: 4 * this.c,
                                ch: this.to,
                                ccv: this.c,
                                vv: this.oldNumThing
                            })
                        }, function(key) {
                            resolve(key);
                        });
                    });
                }
            };
            --this.Tags.length;
            let key = await this.Tags.postAuth();
            this.Tags.result = key;
            i = 0;
            for (; i < this.Tags.emgaa.length; i++) {
                this.Tags.length = this.Tags.length += (this.Tags.emgaa.charCodeAt(i) * (1 - (!i || i % 2 ? 0 : 2)) - 1 * (i ? 0 : 1));
            }
        }
        this.ws = new WebSocket(wss);
        this.ws.binaryType = "arraybuffer";
        this.ws.onopen = this.onOpen.bind(this);
        this.ws.onclose = this.onClose.bind(this);
        this.ws.onmessage = this.onMessage.bind(this);
    }
    connect(wss) {
        this.server = wss;
        this.setupDependencies(this.origin, this.server);
    }
    onOpen() {
        if (this.opcode == 1) {
            const packet = this.Buffer(13);
            packet.setUint8(0, 245);
            packet.setUint16(1, this.Tags.formatTag, true);
            packet.setUint16(3, this.Tags.oldNumThing, true);
            packet.setUint32(5, this.Tags.c, true);
            packet.setUint32(9, this.Tags.toArray(packet, 0, 9, 245), true);
            this.send(packet);
            this.sprkcore = setInterval(() => {
                if (this.readyToSpawn) this.send([0x5f]);
            }, 18e3);
            this.spawnInt = setInterval(this.spawn.bind(this), 1000);
        } else if (this.opcode == 0) {
            const packet = new Writer(13);
            packet.setUint8(245);
            packet.setUint16(this.Tags.A0);
            packet.setUint16(this.Tags.M);
            packet.setUint32(this.Tags.S_);
            packet.setUint32(this.Tags.Va(packet.buffer, 0, 9, 245));
            this.send(packet);
            this.sprkcore = setInterval(() => {
                if (this.readyToSpawn) var singleByte = this.Buffer(1);
                singleByte.setUint8(0, 94);
                this.send(singleByte);
            }, 18e3);
            this.spawnInt = setInterval(this.spawn.bind(this), 5000);
        }
    }
    spawn() {
        if (this.opcode == 1 || this.opcode == 0) {
            if (!this.readyToSpawn) return;
            var es = [1];
            var _s = 0;
            var spawnBuf = this.Buffer(4 + 2 * es.length + 2 * this.botName.length);
            spawnBuf.setUint8(0, 1);
            for (var b = 4, x = 0; x < es.length; x++) spawnBuf.setUint16(b, 0, true);
            for (x = 0; x < this.botName.length; ++x) spawnBuf.setUint16(b + 2 * x, this.botName.charCodeAt(x), true);
            var singleByte = this.Buffer(1);
            singleByte.setUint8(0, 34);
            this.send(singleByte);
            this.send(spawnBuf);
            singleByte = this.Buffer(1);
            singleByte.setUint8(0, 34);
            this.send(singleByte);
        } else if (this.opcode == 2) {
            this.send(new Uint8Array([27]));
        }
    }
    onMessage(data) {
        if (this.opcode == 1) {
            var view = new DataView(data.data);
            var offset = 0;
            switch (240 == view.getUint8(offset) && (offset = offset + 5), view.getUint8(offset++)) {
                case 64:
                    offset = offset + 34;
                    var next = view.getUint32(offset, true);
                    offset = offset + 4;
                    var code = view.getUint32(offset, true);
                    if (next === code) {
                        if (70 > this.Tags.to) {
                            this.Tags.to = 100;
                            this.Tags.currentTime = next;
                            this.parse(0, 33000);
                        }
                    } else {
                        this.ws.close();
                        console.log("Err in 64!");
                    }
                    break;
                case 244:
                    this.readyToSpawn = true;
                    this.send(new Uint8Array([0x04, 0x07, 0x01]))
                    this.send(new Uint8Array([0x04, 0x08, 0x00]))
                    this.send(new Uint8Array([0x04, 0x03, 0x01]))
                    break;
            }
        } else if (this.opcode == 0) {
            view = new DataView(data.data);
            offset = 0;
            switch (240 == view.getUint8(offset) && (offset = offset + 5), view.getUint8(offset++)) {
                case 64:
                    offset = offset + 34;
                    next = view.getUint32(offset, true);
                    offset = offset + 4;
                    code = view.getUint32(offset, true);
                    if (next === code) {
                        if (70 > this.Tags.j9) {
                            this.Tags.j9 = 100;
                            this.Tags.M_ = next;
                            this.try64(0, 18208);
                        }
                    } else {
                        this.ws.close();
                        console.log("Err in 64!");
                    }
                    break;
                case 244:
                    this.readyToSpawn = true;
                    this.send(new Uint8Array([0x04, 0x07, 0x01]))
                    this.send(new Uint8Array([0x04, 0x08, 0x00]))
                    this.send(new Uint8Array([0x04, 0x03, 0x01]))
                    break;
            }
        }
    }
    try64(a, key) {
        const auth = new Writer(13);
        auth.setUint8(2 * (100 + 30) - (this.Tags.M_ - 5) % 10 - 5);
        auth.setUint32(~~(this.Tags.M_ / 1.81 + 100 / 2 - 2 * (a ? .5 : 1)) + (~~(~~(22.21 * (~~(this.Tags.M_ + 4.42 * this.Tags.S_ - 550) % --key -
            36360)) / 4.2)));
        auth.setUint32(this.increment2() + 171)
        auth.setUint32(this.Tags.Va(auth.buffer, 0, 9, 255) - 1)
        this.send(auth);
    }
    get C_() {
        var zafar = "~9B\\x$";
        return [
            zafar.charCodeAt(0), zafar.charCodeAt(1), zafar.charCodeAt(2) + 73, zafar.charCodeAt(3), zafar.charCodeAt(4) + 227, zafar.charCodeAt(5)
        ];
    }
    increment2() {
        for (var a = 0, c = 1; c < this.C_.length; c++) {
            a += ~~(this.Tags.M_ / this.C_[c] - this.C_[c] % 171);
        }
        return a;
    }
    get filenameFilter() {
        var o = '~9B\\x$';
        return [
            o.charCodeAt(0),
            o.charCodeAt(1),
            o.charCodeAt(2) + 73,
            o.charCodeAt(3),
            o.charCodeAt(4) + 227,
            o.charCodeAt(5),
        ];
    }
    increment() {
        var op = 0;
        var ii = 0;
        for (; ii < this.filenameFilter.length; ii++) {
            op = op + ~~(this.Tags.currentTime / this.filenameFilter[ii] - this.filenameFilter[ii] % 103);
        }
        return op;
    }
    parse(offset, key) {
        if (this.opcode == 1) {
            let auth = this.Buffer(13);
            auth.setUint8(0, 2 * (100 + 30) - (this.Tags.currentTime - 5) % 10 - 5);
            auth.setUint32(1, ~~(this.Tags.currentTime / 1.84 + 100 / 2 - 2 * (offset ? .5 : 1)) + ~~(~~(21.2 * (~~(this.Tags.currentTime + 4.42 * this.Tags
                .c + 555) % --key + 36360)) / 4.2), true);
            auth.setUint32(5, this.increment() + 103, true);
            auth.setUint32(9, this.Tags.toArray(auth, 0, 9, 255), true);
            this.send(auth);
        }
    }
    split() {
        if (this.opcode == 1 || this.opcode == 0) {
            this.send(new Uint8Array([0x11]))
        } else if (this.opcode == 2) {
            this.send(new Uint8Array([33, 0, 1]));
        }
    }
    eject() {
        if (this.opcode == 1 || this.opcode == 0) {
            this.send(new Uint8Array([0x24]))
        } else if (this.opcode == 2) {
            this.send(new Uint8Array([33, 1, 255]));
        }
    }
    sendmouse() {
        if (this.opcode == 1 || this.opcode == 0) {
            if (!this.readyToSpawn) return;
            this.send(HookClient.Client.movebuf);
        } else if (this.opcode == 2) {
            this.send(HookClient.Client.movebuf);
        }
    }
    sendChat(msg) {
        if (this.opcode == 1 || this.opcode == 0) {
            var b = this.Buffer(2 + 2 * msg.length),
                x = 0;
            b.setUint8(x++, 98)
            b.setUint8(x++, 1);
            for (var _ = 0; _ < msg.length; ++_) b.setUint16(x, msg.charCodeAt(_), true), x += 2;
            this.send(b);
        } else if (this.opcode == 2) {
            let writer = new DataFrameWriter();
            var f = 0;
            writer.writeUint8(98);
            writer.writeUint8(f ? 1 : 0);
            writer.writeStringEx(msg);
            this.send(writer.getArrayBuffer());
        }
    }
    GetUserID(length) {
        var result = [];
        var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
        var charactersLength = characters.length;
        for (var i = 0; i < length; i++) {
            result.push(characters.charAt(Math.floor(Math.random() * charactersLength)));
        }
        return result.join('');
    }
    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) {
            if (this.opcode == 1 || this.opcode == 0) {
                this.ws.send(data.buffer);
            } else {
                this.ws.send(data)
            }
        }
    };
    close() {
        if (this.ws) this.ws.close();
    };
    onClose() {
        clearInterval(this.spawnInt);
        clearInterval(this.mouseInt);
        clearInterval(this.sprkcore);
        if (!HookClient.Client.started) return;
        //setTimeout(this.connect(this.server), 5000);
    };
}
 
if (location.host.includes('agma.io') || location.host.includes('cellcraft.io')) {
    let client = null;
    window.WebSocket = class extends WebSocket {
        constructor() {
            let ws = super(...arguments);
            window.sockets?.push(this);
 
            setTimeout(() => {
                ws.onmessage = new Proxy(ws.onmessage, {
                    apply(target, thisArg, argArray) {
                        let data = argArray[0].data;
                        return target.apply(thisArg, argArray);
                    }
                });
            });
        }
    }
 
    WebSocket.prototype.send = new Proxy(WebSocket.prototype.send, {
        apply(target, thisArg, argArray) {
            var res = target.apply(thisArg, argArray);
            let pkt = argArray[0];
            if (!client) return;
            if (typeof pkt == 'string') return res;
            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 0:
                    switch (pkt.byteLength) {
                        case 9:
                            client.movebuf = pkt;
                            break;
                    }
                    break;
            }
            if (client.serverIP !== thisArg.url) {
                client.serverIP = thisArg.url;
            }
            return res;
        }
    });
    window.addEventListener('load', () => {
        client = new Client();
        HookClient.run(client);
    });
}