// ==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);