40 bot script (no vpn required)

simple moomoo.io script that allows you to use bots

// ==UserScript==
// @name        40 bot script (no vpn required)
// @ namespace  -
// @version     1.0.1
// @description simple moomoo.io script that allows you to use bots
// @author      me mega noob
// @match       *://sandbox.moomoo.io/*
// @require     https://greasyfork.org/scripts/423602-msgpack/code/msgpack.js
// @license     MIT
// @grant       none
// @namespace https://greasyfork.org/users/708575
// ==/UserScript==

/*

use the period button to musket sync

bots are made only for sandbox

chat "!spawn *amount*" to send X amount of bots (max of 38)

chat "!dc" to disconnect them all

*/

(function() {
    "use strict";

    var botNames = ["supaman", "megawashere", "welcome", "tomy", "nextvideo", "on moomoo", "cowgame"].map(e => e.slice(0, 15)); // custom bot names

    var projects = [];
    var socket = undefined;
    var wsAddress = "";

    class Bot {
        constructor(amount, ws) {
            this.socket = ws;
            this.amount = amount;

            this.socket.onopen = () => {
                this.requestBots(this.amount);
            };

            this.socket.onmessage = (msg) => {
                let message = JSON.parse(msg.data);
                if (message.type == "canSendNow") {
                    this.requestBots(this.amount);
                }
            };
        }
        async requestBots(amount) {
            let tokens = await this.getTokens(amount);

            this.send({
                type: "add",
                ip: wsAddress,
                tokens: tokens
            });
        }
        getTokens(amount) {
            const tokenPromises = [];
            for (let i = 0; i < amount; i++) {
                const tokenPromise = new Promise((resolve, reject) => {
                    window.grecaptcha.execute("6LfahtgjAAAAAF8SkpjyeYMcxMdxIaQeh-VoPATP", { action: "homepage" }).then((token) => {
                        resolve("re:" + encodeURIComponent(token));
                    }).catch(reject);
                });
                tokenPromises.push(tokenPromise);
            }
            return Promise.all(tokenPromises);
        }
        send(data) {
            if (this.socket.readyState == 1) {
                this.socket.send(JSON.stringify(data));
            }
        }
    }

    var botManager = new class {
        constructor() {
            this.projects = ["large-shadowed-hoof", "cooperative-vanilla-hydrofoil", "lowly-discovered-agenda", "balanced-instinctive-mantis", "splashy-dusty-snout", "field-vivacious-mangosteen", "locrian-buttery-fur", "abstracted-prong-cod", "just-arrow-spark"];
            this.bots = [];
        }
        spawn(amount, projectLink) {
            let ws = new WebSocket(`wss://${projectLink}.glitch.me/`);

            this.bots.push(new Bot(amount, ws));
        }
        destroy() {
            this.bots.forEach(bot => {
                bot.socket.close();
            });
        }
        update() {
            for (let i = 0; i < this.bots.length; i++) {
                let bot = this.bots[i];

                if (bot.socket.readyState == 1) {
                    bot.send({
                        type: "update",
                        msg: {
                            owner: {
                                x: player.x,
                                y: player.y,
                                team: player.team,
                                enemy: nearestEnemy
                            },
                            botNames: botNames // There are like 10000 more efficient ways to do this but i do not care
                        }
                    });
                }
            }
        }
    };

    var playerSID = null;
    var player = {
        x: 0,
        y: 0,
        team: null
    };
    var nearestEnemy = null;
    var allEnemies = [];

    function getDistance(...args) {
        return Math.hypot(args[0].y - args[1].y, args[0].x - args[1].x);
    }

    document.addEventListener("keydown", e => {
        if (e.key == ".") {
            for (let i = 0; i < botManager.bots.length; i++) {
                let bot = botManager.bots[i];
                if (bot.socket.readyState == 1) {
                    bot.send({
                        type: "sync"
                    });
                }
            }
        }
    });

    WebSocket.prototype.oldSend = WebSocket.prototype.send;
    WebSocket.prototype.send = function(msg) {
        if (!socket && this.url.includes("moomoo.io")) {
            socket = this;

            this.addEventListener("message", (msg) => {
                let data = new Uint8Array(msg.data);
                let parsed = window.msgpack.decode(data);
                let type = parsed[0];
                data = parsed[1];


                if (type == "C") { // setUpGame
                    playerSID = data[0];
                } else if (type == "a") { // updatePlayer
                    allEnemies = [];
                    nearestEnemy = null;

                    for (let i = 0; i < data[0].length;) {
                        let team = data[0][i + 7];
                        if (data[0][i] == playerSID) {
                            player.x = data[0][i + 1];
                            player.y = data[0][i + 2];
                            player.team = team;
                        } else if (!(data[0][i] == playerSID || (team && team == player.team))) {
                            allEnemies.push({ x: data[0][i + 1], y: data[0][i + 2] });
                        }
                        i += 13;
                    }

                    if (allEnemies.length) {
                        nearestEnemy = allEnemies.sort((a, b) => getDistance(a, player) - getDistance(b, player))[0];
                    }

                    botManager.update();
                }
            });

            wsAddress = this.url.split("/?token")[0];
        }
        if (socket == this) {
            let data = new Uint8Array(msg);
            let parsed = window.msgpack.decode(data);
            let type = parsed[0];
            data = parsed[1];

            if (type == "6") {
                let msg = data[0];
                if (msg.startsWith("!spawn ")) {
                    let request = Math.min(parseInt(msg.split("!spawn ")[1] || 0), 38);

                    for (let i = 0; i < botManager.projects.length; i++) {
                        if (request <= 0) break;
                        botManager.spawn(Math.min(request, 4), botManager.projects[i]);

                        request -= 4;
                    }
                } else if (msg == "!dc") {
                    botManager.destroy();
                }
            }
        }
        this.oldSend(msg);
    }
})();