Rie's Mod

Simple mod made by khayrie

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name         Rie's Mod
// @version      5.3
// @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 = " ";
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(); }
})();