MrMenu

Best Manager bonk.io

目前为 2024-10-11 提交的版本。查看 最新版本

// ==UserScript==
// @name         MrMenu
// @version      1.31
// @description  Best Manager bonk.io
// @namespace    https://greasyfork.org/en/scripts/504571-mrmenu
// @author       MrBonkeiro
// @match        https://bonk.io/
// @match        https://bonk.io/*
// @match        https://bonkisback.io/*
// @match        https://multiplayer.gg/physics/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=bonk.io
// @grant        none
// @unwrap
// ==/UserScript==

class API {
    constructor() {
        this.plugins = {};
    }

    addHTML(htmlString, selector, beforeSelector = null) {
        const targetElement = document.querySelector(selector);
        if (!targetElement) { return; }

        const parser = new DOMParser();
        const doc = parser.parseFromString(htmlString, 'text/html');
        const newElements = Array.from(doc.body.childNodes);

        if (beforeSelector) {
            const beforeElement = document.querySelector(beforeSelector);
            if (!beforeElement) { return; }
            newElements.forEach(node => {
                beforeElement.parentNode.insertBefore(node, beforeElement);
            });
        } else {
            newElements.forEach(node => {
                targetElement.appendChild(node);
            });
        }
    }

    addCSS(ID, cssString, replace = false)
    {
        let styleElement = document.getElementById(ID);

        if (styleElement) {
            if (replace) {
                styleElement.innerHTML = cssString;
            } else {
                styleElement.innerHTML += `\n${cssString}`;
            }
        } else {
            styleElement = document.createElement('style');
            styleElement.id = ID;
            styleElement.innerHTML = cssString;
            document.head.appendChild(styleElement);
        }
    }

    callPluginFunction(pluginName, funcName, ...args) {
        if (this.plugins[pluginName] && typeof this.plugins[pluginName][funcName] === 'function') {
            return this.plugins[pluginName][funcName](...args);
        }
        console.error(`Function ${funcName} not found in plugin ${pluginName}.`);
    }

    addPlugin(pluginName, plugin) {
        this.plugins[pluginName] = plugin;
    }
}

class MrMenu {
    constructor()
    {
        this.plugins = {};
        this.api = new API();
    }

    addPlugin(pluginName, plugin) {
        if (this.plugins[pluginName]) {
            console.error(`Plugin ${pluginName} is already registered.`);
            return;
        }
        this.plugins[pluginName] = plugin;
        this.api.addPlugin(pluginName, plugin);
    }

    init() {
        for (const pluginName in this.plugins) {
            const plugin = this.plugins[pluginName];
            if (typeof plugin.init === 'function') {
                plugin.init(this.api);
            }
        }
    }
}

const MenuUI = {

    API: null,

    init(api)
    {
        API = api;
        api.addCSS(`MrMenuUI`, `.MrMenuUI { background-color: #1f1f1f; display: flex; position: absolute; top: 50%; left: 50%; width: 85%; height: 85%; transform: translate(-50%, -50%); user-select: none; box-sizing: border-box;}`);
        api.addCSS(`MrMenuUI`, `.MrMenuUI .sidebar { display: flex; flex-direction: column; width: 200px; border-right: 1px solid #2b2b2bcc; box-sizing: border-box; overflow-y: auto; overflow-x: hidden; }`);
        api.addCSS(`MrMenuUI`, `.MrMenuUI .sidebar::-webkit-scrollbar { width: 7px; }`);
        api.addCSS(`MrMenuUI`, `.MrMenuUI .sidebar::-webkit-scrollbar-track { background: #1f1f1f; }`);
        api.addCSS(`MrMenuUI`, `.MrMenuUI .sidebar::-webkit-scrollbar-thumb { background: #444444; border-radius: 4px; }`);
        api.addCSS(`MrMenuUI`, `.MrMenuUI .sidebar .title { display: flex; width: 200px; height: 50px!important; color: white; font-size: 13px; font-family: 'Be Vietnam Pro', sans-serif; font-size: 13px; text-align: center; align-items: center; justify-content: center; border-bottom: 1px solid #2b2b2bcc; }`);
        api.addCSS(`MrMenuUI`, `.MrMenuUI .sidebar button { margin: 7px 20px 2px 10px; padding: 10px 15px; width: 170px; border: none; outline: none; background-color: #1f1f1f; color: white; font-family: 'Be Vietnam Pro', sans-serif; font-size: 11px; text-align: left; }`);
        api.addCSS(`MrMenuUI`, `.MrMenuUI .sidebar button:hover { background-color: #3c3c3c; }`);
        api.addCSS(`MrMenuUI`, `.MrMenuUI .sidebar button.active { background-color: #1e73be; }`);
        api.addCSS(`MrMenuUI`, `.MrMenuUI div.content { display: flex; flex: 1; overflow-y: auto; overflow-x: hidden; }`);
        api.addCSS(`MrMenuUIPage`, `.MrMenuUI > div.content > div { height: 100%; overflow-y: auto; box-sizing: border-box; display: none; color: white; padding: 15px; font-family: 'Be Vietnam Pro', sans-serif; font-size: 11px; text-align: left; }`);
        api.addCSS(`MrMenuUIPage`, `.MrMenuUI > div.content > div > .row { display: flex; padding: 4px; margin: 5px 0; }`);
        api.addCSS(`MrMenuUIPage`, `div.MrMenuUI > div.content > div > div > button { background: #cccccc; height: 30px; width: 70px; border: none; border-radius: 4px; margin-right: 6px; }`);
        api.addCSS(`MrMenuUIPage`, `div.MrMenuUI > div.content > div > div > button:hover { background-color: #1c1c1c; border: 1px solid lightgrey; color: white}`);
        api.addCSS(`MrMenuUIPage`, `div.MrMenuUI > div.content > div > div > button.md { width: 150px;}`);
        api.addCSS(`MrMenuUIPage`, `div.MrMenuUI > div.content > div > div.row > button.active { background: #1e73be; color:white; }`);


        api.addHTML(`<div class="MrMenuUI"><div class="sidebar"><div class="title"><a>MrMenu by MrBonkeiro</a></div></div><div class="content"></div></div>`, '#bonkiocontainer');
        document.addEventListener('keydown', (event) => { if (event.key === 'Delete') { this.toggleMenu(); } });
        document.querySelector(`div#pretty_top_name`).addEventListener(`click`, () => { this.toggleMenu(); });

        /////////////////////////////////////////////////////////////////////////////////////////////

        this.addTab(`Host Manager`);

        this.addTabElement(`Host Manager`,`<div class="row"><label>Miscellaneous:</label></div> NO WORK`);
        this.addTabElement(`Host Manager`,`<div class="row"><button id="RestartRoom" class="md">Restart Room</button></div>`);
        this.addTabElement(`Host Manager`,`<div class="row"><label>Freejoin:</label></div>`);
        this.addTabElement(`Host Manager`,`<div class="row"><button id="FreejoinEnable">Enable</button><button id="FreejoinDisable" class="active">Disable</button></div>`);
        /////////////////////////////////////////////////////////////////////////////////////////////
        this.addTab(`Chat Custom`);
        this.addTabElement(`Chat Custom`,`<div class="row"><label>Miscellaneous:</label></div>`);

        this.addTab(`Bonk theme`);
        this.addTab(`Keypress Show`);

        /////////////////////////////////////////////////////////////////////////////////////////////
        this.addTab(`XP Involker`);
        this.addTabElement(`XP Involker`,`<div class="row"><label>XP:</label></div>`);
        this.addTabElement(`XP Involker`,`<div class="row"><button id="XPEnable">Enable</button><button id="XPDisable" class="active">Disable</button></div>`);

        this.addTabElement(`XP Involker`,`<div class="row"><label>Delay:</label></div>`);
        this.addTabElement(`XP Involker`,`<div class="row"><button id="XPDelay10s" class="btnXPDelay active">10s</button><button id="XPDelay15s" class="btnXPDelay">15s</button><button id="XPDelay30s" class="btnXPDelay">30s</button><button id="XPDelay60s" class="btnXPDelay">60s</button></div>`);

        this.addTab(`IP Logger`);
        this.addTab(`Settings`);

        /////////////////////////////////////////////////////////////////////////////
        this.addEvent(`button#RestartRoom`,`click`, () => { api.callPluginFunction('Actions', 'restartRoom'); });

        this.addEvent(`button#FreejoinEnable`,`click`, () => { document.querySelector(`button#FreejoinDisable`).classList.remove('active'); event.target.classList.add('active') });
        this.addEvent(`button#FreejoinDisable`,`click`, () => { document.querySelector(`button#FreejoinEnable`).classList.remove('active'); event.target.classList.add('active') });
        this.addEvent(`button#XPEnable`,`click`, () => { document.querySelector(`button#XPDisable`).classList.remove('active'); event.target.classList.add('active'); window.mrflags.xp = true; if (window.mrflags.xpIntervalId == null) { window.mrflags.xpIntervalId = setInterval(() => { const element = document.getElementById('gamerenderer'); if(element.style.visibility == 'inherit'){ window.mrflags.bonkWSS.send(`42[38]`);} }, window.mrflags.xpDelay); } });
        this.addEvent(`button#XPDisable`,`click`, () => { document.querySelector(`button#XPEnable`).classList.remove('active'); event.target.classList.add('active'); if (window.mrflags.xpIntervalId !== null) { clearInterval(window.mrflags.xpIntervalId); window.mrflags.xpIntervalId = null; } });

        function XPdelayResolver(event) { clearInterval(window.mrflags.xpIntervalId); window.mrflags.xpIntervalId = null; document.querySelector(`button#XPEnable`).classList.remove('active'); document.querySelector(`button#XPDisable`).classList.add('active'); document.querySelectorAll('button.btnXPDelay').forEach(button => { button.classList.remove('active'); }); event.target.classList.add('active'); }

        this.addEvent(`button#XPDelay10s`,`click`, () => { XPdelayResolver(event); window.mrflags.xpDelay = (10 * 1000); });
        this.addEvent(`button#XPDelay15s`,`click`, () => { XPdelayResolver(event); window.mrflags.xpDelay = (15 * 1000); });
        this.addEvent(`button#XPDelay30s`,`click`, () => { XPdelayResolver(event); window.mrflags.xpDelay = (30 * 1000); });
        this.addEvent(`button#XPDelay60s`,`click`, () => { XPdelayResolver(event); window.mrflags.xpDelay = (60 * 1000); });
    },

    addTab(name, fclick = null)
    {
        API.addHTML(`<button id="` + name.replace(/\s+/g, '') + `" data-tab="` + name.replace(/\s+/g, '') + `">` + name + `</button>`, '.MrMenuUI .sidebar');

        const sidebarSelector = `div.sidebar > button#` + name.replace(/\s+/g, '');
        const sidebar = document.querySelector(sidebarSelector);

        if (sidebar)
        {
            sidebar.addEventListener('click', function(event) {
                const items = document.querySelectorAll('div.MrMenuUI > div.sidebar > button');
                items.forEach(btn => btn.classList.remove('active'))
                event.currentTarget.classList.add('active');

                const dataTab = event.target.getAttribute('data-tab');
                const contents = document.querySelectorAll('div.MrMenuUI > div.content > div');
                contents.forEach(content => {
                    content.style.display = 'none';
                });
                const activeContent = document.querySelector(`div[data-tab="${dataTab}"]`);
                if (activeContent) {
                    activeContent.style.display = 'block';
                }

            });
        }
    },

    addTabElement(name, content)
    {
        let compact = name.replace(/\s+/g, '');
        const area = document.querySelector(`div.MrMenuUI > div.content > div[data-tab="${compact}"]`);
        if(!area)
        {
            API.addHTML(`<div data-tab="${compact}"></div>`, `div.MrMenuUI > div.content`);
        }
        API.addHTML(content, `div.MrMenuUI > div.content > div[data-tab="${compact}"]`);

    },

    addEvent(selector, eventType, callback) {
        const elements = document.querySelectorAll(selector);
        elements.forEach(element => {
            element.addEventListener(eventType, callback);
        });
    },

    toggleMenu()
    {
        const menu = document.querySelector('div.MrMenuUI');
        const visible = window.getComputedStyle(menu).visibility === 'visible';

        menu.style.visibility = visible ? 'hidden' : 'visible';
        menu.style.opacity = visible ? '0' : '1';
        menu.style.zIndex = visible ? '-100' : '100';
    }
};

const Actions = {

    restartRoom()
    {
        setTimeout(function(){
            document.getElementById("newbonklobby_editorbutton").click();
            document.getElementById("mapeditor_close").click();
            document.getElementById("newbonklobby").style["display"] = "none";
            document.getElementById("mapeditor_midbox_testbutton").click();
        },120);
    }
}


function InterceptWSS()
{
    var originalSend = WebSocket.prototype.send;
    WebSocket.prototype.send = function(args)
    {
        window.mrflags.bonkWSS = this;
        var originalReceive = this.onmessage;

        this.onmessage = function(event)
        {

            return originalReceive.call(this, event);
        };
        return originalSend.call(this, args);
    }


}
function Init()
{
    window.mrflags = {
        bonkWSS : null,
        xpIntervalId : null,
        xpDelay : 10000,
    };

    InterceptWSS();

    const mrMenu = new MrMenu();
    mrMenu.addPlugin('MenuUI', MenuUI);
    mrMenu.addPlugin('Actions', Actions);

    mrMenu.init();

}

function ScriptInjector(f)
{
    if (window.location.href == `https://bonk.io/gameframe-release.html`)
    {
        if (document.readyState == 'complete'){ setTimeout(f, 200); }
        else
        { document.addEventListener('readystatechange', function () { setTimeout(f, 1500); }); }
    }
}

ScriptInjector(Init);