Allows you to mute other players!
// ==UserScript==
// @name CarManiac's Mute Feature
// @namespace http://tampermonkey.net/
// @version 1.2
// @description Allows you to mute other players!
// @author CarManiac
// @run-at document-idle
// @license MIT
// @match https://heav.io/game.html
// @match https://hitbox.io/game.html
// @match https://heav.io/game2.html
// @match https://hitbox.io/game2.html
// @match https://hitbox.io/game-beta.html
// @icon https://www.google.com/s2/favicons?sz=64&domain=heav.io
// @icon https://www.google.com/s2/favicons?sz=64&domain=hitbox.io
// @grant none
// ==/UserScript==
(function() {
'use strict';
const targetImage = 'graphics/ui/hitbox.svg';
const newImageSrc = 'https://i.ibb.co/F5RLpmx/hitbox-1.png';
const images = document.querySelectorAll(`img[src="${targetImage}"]`);
images.forEach(img => {
const overlayImage = document.createElement('img');
overlayImage.src = newImageSrc;
overlayImage.style.position = 'absolute';
overlayImage.style.left = img.offsetLeft + 'px';
overlayImage.style.top = img.offsetTop + 'px';
overlayImage.style.width = img.width + 'px';
overlayImage.style.height = img.height + 'px';
overlayImage.style.pointerEvents = 'none';
img.parentNode.appendChild(overlayImage);
});
const mutedPlayers = new Set(loadMutedPlayers());
let players = [];
let WSS;
let myid;
let hostId;
function findPlayer(id) {
for (let t in players) {
let o = players[t];
if (o.id == id || o.name == id) {
o.index = t;
return o;
}
}
}
const originalSend = window.WebSocket.prototype.send;
window.WebSocket.prototype.send = async function(args) {
if (this.url.includes("/socket.io/?EIO=3&transport=websocket&sid=")) {
if (typeof (args) === "string") {
if (!WSS) {
WSS = this;
}
}
}
if (WSS == this && !this.carInjected) {
this.carInjected = true;
const originalClose = this.onclose;
this.onclose = (...args) => {
if (WSS == this) {
WSS = 0;
players = [];
}
originalClose.call(this, ...args);
};
this.onmessageCar = this.onmessage;
this.onmessage = function(event) {
if (event.data.startsWith('42[')) {
let packet = JSON.parse(event.data.slice(2, event.data.length));
if (packet[0] == 7) {
myid = packet[1][0];
hostId = packet[1][1];
for (let i of packet[1][3]) {
players.push({
"team": i[2],
"color": (i[7][0] || i[7][1]),
"name": i[0],
"id": i[4],
"lvl": i[6]
});
}
}
if (packet[0] == 9) {
hostId = packet[2];
}
if (packet[0] == 45) {
hostId = packet[1];
}
if (packet[0] == 29) {
if (mutedPlayers.has(findPlayer(packet[1]).name)) {
return;
}
}
if (packet[0] == 8) {
players.push({
"name": packet[1][0],
"color": (packet[7] ? (packet[7][1] || packet[7][0]) : undefined),
"team": packet[1][2],
"id": packet[1][4],
"lvl": packet[1][6]
});
}
}
this.onmessageCar(event);
};
}
return originalSend.call(this, args);
};
function loadMutedPlayers() {
const storedMutedPlayers = localStorage.getItem('mutedPlayers');
return storedMutedPlayers ? JSON.parse(storedMutedPlayers) : [];
}
function saveMutedPlayers() {
localStorage.setItem('mutedPlayers', JSON.stringify(Array.from(mutedPlayers)));
}
function createMuteItem(playerName) {
const muteItem = document.createElement('div');
muteItem.className = 'item muteButton';
muteItem.textContent = mutedPlayers.has(playerName) ? 'Unmute' : 'Mute';
muteItem.style.paddingLeft = '20px';
muteItem.style.paddingRight = '20px';
muteItem.style.backgroundColor = '#2b2d31';
muteItem.style.height = '28px';
muteItem.style.lineHeight = '28px';
muteItem.style.color = '#ebebeb';
muteItem.style.fontSize = '15px';
muteItem.style.cursor = 'pointer';
muteItem.addEventListener('click', () => {
if (mutedPlayers.has(playerName)) {
mutedPlayers.delete(playerName);
muteItem.textContent = 'Mute';
} else {
mutedPlayers.add(playerName);
muteItem.textContent = 'Unmute';
}
saveMutedPlayers();
});
return muteItem;
}
let lastSelected;
const observer = new MutationObserver((e) => {
for (let i of e) {
if (i.target.classList.contains('sideContainer') || i.target.classList.contains('elementContainer')) {
for (let x of i.target.children) {
if (x.classList.contains('playerElement') && !x.injected) {
x.injected = true;
const y = () => {
lastSelected = x;
console.log('selected');
};
x.addEventListener("mouseup", y);
x.addEventListener("mousedown", y);
x.addEventListener("click", y);
}
}
}
}
const menu = document.querySelector('.rightClickMenu .container');
if (menu) {
const existingMuteItem = Array.from(menu.children).find(item => item.textContent === 'Mute' || item.textContent === 'Unmute');
if (!existingMuteItem) {
let playerName = lastSelected.querySelector("div.name").textContent;
const muteItem = createMuteItem(playerName);
menu.appendChild(muteItem);
}
}
});
observer.observe(document.body, { childList: true, subtree: true });
function extractPlayerNameFromMessage(messageElement) {
const nameSpan = messageElement.querySelector('.name');
return nameSpan ? nameSpan.textContent.trim().slice(0, -1) : null;
}
const style = document.createElement('style');
style.innerHTML = `
.muteButton:hover {
background-color: #323438 !important;
}
`;
document.head.appendChild(style);
})();