Rie's Mod

Simple mod made by khayrie

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Rie's Mod
// @version      5.2
// @description  Simple mod made by khayrie
// @author       khayrie
// @match        https://bonk.io/*
// @match        https://bonkisback.io/*
// @match        https://multiplayer.gg/physics/*
// @grant        unsafeWindow
// @run-at       document-idle
// @namespace https://github.com/khayrie
// ==/UserScript==
(function() {
'use strict';
let CUSTOM_NAME = "khayrie's little slave";
let isNameActive = true;
let gameReady = false;
let mutationObserver = null;
const nicknames = {};
const customLevels = {};
const remoteCustomizations = {};
const uw = unsafeWindow;
const NAME_SELECTORS = [
'#pretty_top_name', '.newbonklobby_playerentry_name', '.ingamescoreboard_playername',
'.ingamechatname', '.newbonklobby_chat_msg_name', '#ingamewinner_top', '.replay_playername'
];
const LEVEL_SELECTORS = [
'#pretty_top_level', '.newbonklobby_playerentry_level', '.ingamescoreboard_playerlevel'
];
const UPDATE_INTERVAL = 200;
const PRESETS = {
rainbow: { colors: ['#FF0000', '#FFA500', '#FFFF00', '#00FF00', '#0000FF', '#4B0082', '#8B00FF'], speed: 100 },
fire: { colors: ['#FF4500', '#FF8C00', '#FFD700'], speed: 150 },
ocean: { colors: ['#1E90FF', '#87CEEB', '#00BFFF'], speed: 200 },
sunset: { colors: ['#FF4500', '#FFA500', '#FFD700', '#FF69B4'], speed: 120 },
neon: { colors: ['#00FF00', '#00FFFF', '#FF00FF', '#FF0000'], speed: 80 },
lavender: { colors: ['#9370DB', '#BA55D3', '#DA70D6', '#EE82EE'], speed: 180 }
};
let lastUpdate = 0;

function escapeRegExp(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

function parseQuotedArgs(input) {
const tokens = [];
let current = '';
let inQuote = false;
let escapeNext = false;
for (let i = 0; i < input.length; i++) {
const char = input[i];
if (escapeNext) { current += char; escapeNext = false; continue; }
if (char === '\\') { escapeNext = true; continue; }
if (char === '"' && (i === 0 || input[i-1] !== '\\')) { inQuote = !inQuote; continue; }
if (char === ' ' && !inQuote) { if (current !== '') { tokens.push(current); current = ''; } continue; }
current += char;
}
if (current !== '') tokens.push(current);
return tokens;
}

function waitForGame(callback, retries = 0) {
if (retries > 50) return;
const frame = document.getElementById('maingameframe');
if (!frame || !frame.contentWindow) { setTimeout(() => waitForGame(callback, retries + 1), 200); return; }
const gameWin = frame.contentWindow;
const gameDoc = frame.contentDocument;
if (!gameWin.PIXI || typeof uw.playerids === 'undefined' || typeof uw.myid === 'undefined' || !gameDoc.body) {
setTimeout(() => waitForGame(callback, retries + 1), 200);
return;
}
gameReady = true;
callback(gameWin, gameDoc);
}

function hookPIXIText(gameWin) {
if (!gameWin?.PIXI?.Text?.prototype) return;
const originalUpdate = gameWin.PIXI.Text.prototype.updateText;
gameWin.PIXI.Text.prototype.updateText = function() {
try {
if (typeof this.text !== 'string') return originalUpdate.call(this);
const playerIds = uw.playerids || {};
const myId = uw.myid;
for (const id in playerIds) {
const player = playerIds[id];
if (!player || !player.userName) continue;
let displayName = player.userName;
if (nicknames[id]) { displayName = nicknames[id]; }
else if (id == myId && isNameActive) { displayName = CUSTOM_NAME; }
else if (remoteCustomizations[id]?.name && id != myId) { displayName = remoteCustomizations[id].name; }
if (displayName === player.userName) continue;
const safeName = escapeRegExp(player.userName);
if (new RegExp(safeName, 'i').test(this.text)) {
this.text = this.text.replace(new RegExp(safeName, 'ig'), displayName);
}
}
} catch (e) {}
return originalUpdate.call(this);
};
}

function forceInstantUpdate(doc) {
if (!doc) doc = uw.Gdocument;
if (!doc || !gameReady) return;
try {
const targets = NAME_SELECTORS.concat(LEVEL_SELECTORS);
for (let i = 0; i < targets.length; i++) {
const selector = targets[i];
const elements = doc.querySelectorAll(selector);
for (let j = 0; j < elements.length; j++) {
const el = elements[j];
if (el.style) {
el.style.transform = '';
el.style.animation = '';
el.style.textShadow = '';
el.style.textAlign = '';
el.style.position = '';
el.style.top = '';
el.style.backgroundImage = '';
el.style.backgroundClip = '';
el.style.webkitBackgroundClip = '';
el.style.color = '';
}
}
}
updateAllDOM(doc);
} catch (e) {}
}

function getDisplayName(playerId) {
if (playerId == uw.myid && isNameActive) return CUSTOM_NAME;
if (nicknames[playerId]) return nicknames[playerId];
if (remoteCustomizations[playerId]?.name && playerId != uw.myid) return remoteCustomizations[playerId].name;
return uw.playerids?.[playerId]?.userName || "Guest";
}

function updateAllDOM(doc) {
if (!doc || !gameReady || !uw.playerids) return;
const now = Date.now();
if (now - lastUpdate < UPDATE_INTERVAL) return;
lastUpdate = now;
try {
const playerIds = uw.playerids;
const myId = uw.myid;
const nameElements = [];
const levelElements = [];
for (let i = 0; i < NAME_SELECTORS.length; i++) {
const els = doc.querySelectorAll(NAME_SELECTORS[i]);
for (let j = 0; j < els.length; j++) {
nameElements.push(els[j]);
}
}
for (let i = 0; i < LEVEL_SELECTORS.length; i++) {
const els = doc.querySelectorAll(LEVEL_SELECTORS[i]);
for (let j = 0; j < els.length; j++) {
levelElements.push(els[j]);
}
}
for (let i = 0; i < nameElements.length; i++) {
const el = nameElements[i];
for (const id in playerIds) {
const player = playerIds[id];
if (!player || !player.userName) continue;
const safeName = escapeRegExp(player.userName);
let displayValue = player.userName;
if (nicknames[id]) { displayValue = nicknames[id]; }
else if (id == myId && isNameActive) { displayValue = CUSTOM_NAME; }
else if (remoteCustomizations[id]?.name && id != myId) { displayValue = remoteCustomizations[id].name; }
if (el.textContent && new RegExp(safeName, 'i').test(el.textContent)) {
el.textContent = el.textContent.replace(new RegExp(safeName, 'ig'), displayValue);
}
}
}
for (let i = 0; i < levelElements.length; i++) {
const el = levelElements[i];
const playerId = getPlayerIdFromLevelElement(el, doc);
if (playerId && customLevels[playerId]) { el.textContent = customLevels[playerId]; }
else if (playerId == myId && customLevels[myId]) { el.textContent = customLevels[myId]; }
else if (playerId && remoteCustomizations[playerId]?.level && playerId != myId) { el.textContent = remoteCustomizations[playerId].level; }
}
} catch (e) {}
}

function getPlayerIdFromLevelElement(el, doc) {
if (!el || !uw.playerids) return null;
let parent = el.parentElement;
let nameElement = null;
while (parent && !nameElement) {
try {
nameElement = parent.querySelector('.newbonklobby_playerentry_name, .ingamescoreboard_playername, .ingamechatname');
} catch (e) {}
if (nameElement) break;
parent = parent.parentElement;
}
if (!nameElement || !nameElement.textContent) return null;
const nameText = nameElement.textContent.trim();
const playerIds = uw.playerids;
for (const id in playerIds) {
const player = playerIds[id];
if (!player || !player.userName) continue;
let displayName = player.userName;
if (nicknames[id]) { displayName = nicknames[id]; }
else if (id == uw.myid && isNameActive) { displayName = CUSTOM_NAME; }
else if (remoteCustomizations[id]?.name && id != uw.myid) { displayName = remoteCustomizations[id].name; }
if (displayName === nameText) { return id; }
}
return null;
}

function broadcastCustomization() {
if (!uw.sendToServer || !gameReady) return;
try {
uw.sendToServer(JSON.stringify({
type: "bonk_customizer",
senderId: uw.myid,
name: CUSTOM_NAME,
level: customLevels[uw.myid] || "Level 1"
}));
} catch (e) {}
}

function broadcastNickname(playerId, nickname) {
if (!uw.sendToServer || !playerId || !gameReady) return;
try {
uw.sendToServer(JSON.stringify({
type: "bonk_nick",
senderId: uw.myid,
targetId: playerId,
nickname: nickname
}));
} catch (e) {}
}

function broadcastLevel(playerId, levelStr) {
if (!uw.sendToServer || !playerId || !gameReady) return;
try {
uw.sendToServer(JSON.stringify({
type: "bonk_level",
senderId: uw.myid,
targetId: playerId,
level: levelStr
}));
} catch (e) {}
}

function sendPrivateMessage(targetId, message) {
if (!uw.sendToServer || !gameReady) return;
try {
uw.sendToServer(JSON.stringify({
type: "bonk_pm",
senderId: uw.myid,
targetId: targetId,
senderName: getDisplayName(uw.myid),
content: message
}));
} catch (e) {}
}

function handleCustomMessage(data) {
try {
const msg = JSON.parse(data);
if (!msg.senderId) return;
switch(msg.type) {
case "bonk_customizer":
remoteCustomizations[msg.senderId] = {
name: msg.name,
level: msg.level
};
forceInstantUpdate(uw.Gdocument);
break;
case "bonk_nick":
if (msg.targetId) {
if (msg.nickname === "" || msg.nickname === null) { delete nicknames[msg.targetId]; }
else { nicknames[msg.targetId] = msg.nickname; }
forceInstantUpdate(uw.Gdocument);
}
break;
case "bonk_level":
if (msg.targetId && msg.level) {
customLevels[msg.targetId] = msg.level;
forceInstantUpdate(uw.Gdocument);
}
break;
case "bonk_pm":
if (msg.targetId === uw.myid && msg.senderName && msg.content) {
const displayMsg = `[PM from ${msg.senderName}] ${msg.content}`;
if (uw.displayInChat) uw.displayInChat(displayMsg, "#00FF00", "#00AA00");
}
break;
case "bonk_clearnicks":
Object.keys(nicknames).forEach(id => { broadcastNickname(id, ""); });
Object.keys(nicknames).forEach(id => delete nicknames[id]);
forceInstantUpdate(uw.Gdocument);
break;
case "bonk_clearlevel":
if (msg.targetId) {
delete customLevels[msg.targetId];
forceInstantUpdate(uw.Gdocument);
}
break;
}
} catch (e) {}
}

function findPlayerIdByName(namePart) {
if (!namePart || !uw.playerids) return null;
const cleanPart = namePart.toLowerCase().replace(/^"|"$/g, '').trim();
const playerIds = uw.playerids;
for (const id in playerIds) {
const player = playerIds[id];
if (player && player.userName && player.userName.toLowerCase().includes(cleanPart)) { return id; }
}
return null;
}

function showHelp() {
const helpLines = [
"╔════════════════════════════════════════════════╗",
"║   Rie's Mod v5.0 - Command List                ║",
"╠════════════════════════════════════════════════╣",
"║ /name <text>          Change your name         ║",
"║                       (supports ASCII art!)    ║",
"║ /nick <player> <name> Nickname a player        ║",
"║                       (supports ASCII art!)    ║",
"║ /level <player> <num> Set player's level       ║",
"║ /whois <player>       Show real username       ║",
"║ /m <player> <msg>     Private message          ║",
"║ /clearnick            Clear all nicknames      ║",
"║ /info                 Show this help           ║",
"╚════════════════════════════════════════════════╝"
];
const display = uw.displayInChat;
if (!display) return;
for (let i = 0; i < helpLines.length; i++) {
display(helpLines[i], "#FFD700", "#FFA500");
}
}

function cleanupRoom() {
if (mutationObserver) {
try { mutationObserver.disconnect(); } catch (e) {}
mutationObserver = null;
}
gameReady = false;
lastUpdate = 0;
Object.keys(remoteCustomizations).forEach(id => delete remoteCustomizations[id]);
}

function addCommands() {
if (typeof uw.commandhandle !== 'function') { setTimeout(addCommands, 500); return; }
const originalCommandHandle = uw.commandhandle;
uw.commandhandle = function(chat_val) {
if (!gameReady) return originalCommandHandle(chat_val);
const display = uw.displayInChat;
if (chat_val.startsWith('/whois ')) {
const playerName = chat_val.substring(7).trim();
const playerId = findPlayerIdByName(playerName);
if (!playerId) { if (display) display(`Player "${playerName}" not found.`, "#FF0000", "#FF0000"); return ""; }
const realName = uw.playerids?.[playerId]?.userName || "Unknown";
const nick = nicknames[playerId] || "None";
if (display) display(`🔍 ${playerName}: Real = "${realName}", Nick = "${nick}"`, "#00FF00", "#00AA00"); return "";
}
if (chat_val.startsWith('/level ')) {
const rest = chat_val.substring(7).trim();
const args = parseQuotedArgs(rest);
if (args.length < 2) { if (display) display("Usage: /level <player> <number>", "#FF0000", "#FF0000"); return ""; }
const playerName = args[0];
const levelNum = parseInt(args[1]);
const playerId = findPlayerIdByName(playerName);
if (!playerId) { if (display) display(`Player "${playerName}" not found.`, "#FF0000", "#FF0000"); return ""; }
if (isNaN(levelNum) || levelNum < 0 || levelNum > 9999) { if (display) display("Level must be 0-9999.", "#FF0000", "#FF0000"); return ""; }
const levelStr = `Level ${levelNum}`;
customLevels[playerId] = levelStr; broadcastLevel(playerId, levelStr); forceInstantUpdate(uw.Gdocument);
const targetName = uw.playerids?.[playerId]?.userName || "Player";
if (display) display(`📊 Set ${targetName}'s level to: ${levelStr}`, "#00FF00", "#00AA00"); return "";
}
if (chat_val === '/clearnick') {
Object.keys(nicknames).forEach(id => { broadcastNickname(id, ""); });
Object.keys(nicknames).forEach(id => delete nicknames[id]);
if (uw.sendToServer) { try { uw.sendToServer(JSON.stringify({ type: "bonk_clearnicks", senderId: uw.myid })); } catch (e) {} }
forceInstantUpdate(uw.Gdocument);
if (display) display("🏷️ All nicknames cleared", "#FFD700", "#FFA500"); return "";
}
if (chat_val.startsWith('/nick ')) {
const rest = chat_val.substring(6).trim();
const args = parseQuotedArgs(rest);
if (args.length < 2) { if (display) display('Usage: /nick <player> <nickname>', "#FF0000", "#FF0000"); return ""; }
const playerName = args[0];
const nickname = args.slice(1).join(" ");
const playerId = findPlayerIdByName(playerName);
if (!playerId) { if (display) display(`Player "${playerName}" not found.`, "#FF0000", "#FF0000"); return ""; }
if (nickname.trim().length === 0) { if (display) display("Nickname cannot be empty.", "#FF0000", "#FF0000"); return ""; }
nicknames[playerId] = nickname; broadcastNickname(playerId, nickname); forceInstantUpdate(uw.Gdocument);
if (display) display(`🏷️ Nickname applied`, "#00FF00", "#00AA00"); return "";
}
if (chat_val.startsWith('/m ')) {
const rest = chat_val.substring(3).trim();
const args = parseQuotedArgs(rest);
if (args.length < 2) { if (display) display('Usage: /m <player> <message>', "#FF0000", "#FF0000"); return ""; }
const playerName = args[0];
const message = args.slice(1).join(" ");
const playerId = findPlayerIdByName(playerName);
if (!playerId) { if (display) display(`Player "${playerName}" not found.`, "#FF0000", "#FF0000"); return ""; }
sendPrivateMessage(playerId, message);
if (display) display(`💬 [PM to ${getDisplayName(playerId)}] ${message}`, "#00FF00", "#00AA00"); return "";
}
if (chat_val.startsWith('/name ')) {
const newName = chat_val.substring(6);
if (newName.trim().length > 0) {
CUSTOM_NAME = newName; isNameActive = true; broadcastCustomization(); forceInstantUpdate(uw.Gdocument);
if (display) display(`🏷️ Name applied`, "#00FF00", "#00AA00");
} else { if (display) display("Name cannot be empty.", "#FF0000", "#FF0000"); }
return "";
} else if (chat_val === '/name') {
isNameActive = !isNameActive; broadcastCustomization(); forceInstantUpdate(uw.Gdocument);
if (display) display(isNameActive ? "✅ Custom name enabled" : "✅ Custom name disabled", "#FFD700", "#FFA500"); return "";
}
if (chat_val === '/info') { showHelp(); return ""; }
return originalCommandHandle(chat_val);
};
}

function init() {
cleanupRoom();
waitForGame((gameWin, gameDoc) => {
if (!gameDoc.body) return;
if (typeof uw.handleCustomMessageOriginal === 'undefined') {
uw.handleCustomMessageOriginal = uw.handleCustomMessage || (() => {});
uw.handleCustomMessage = function(data) {
handleCustomMessage(data);
uw.handleCustomMessageOriginal(data);
};
}
hookPIXIText(gameWin);
addCommands();
broadcastCustomization();
setInterval(() => { if (gameReady) updateAllDOM(gameDoc); }, UPDATE_INTERVAL);
mutationObserver = new MutationObserver(() => { if (gameReady) updateAllDOM(gameDoc); });
try { mutationObserver.observe(gameDoc.body, { childList: true, subtree: true, characterData: true }); } catch (e) {}
let lastRoomId = uw.roomid;
setInterval(() => {
if (uw.roomid && uw.roomid !== lastRoomId) {
lastRoomId = uw.roomid;
cleanupRoom();
setTimeout(() => init(), 1000);
}
}, 1000);
});
}

const originalCreateOrJoinRoom = uw.createOrJoinRoom;
uw.createOrJoinRoom = function(...args) {
cleanupRoom();
return originalCreateOrJoinRoom.apply(this, args);
};

if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); }
else { init(); }
})();