您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Ability to have a second color in MPP
// ==UserScript== // @name MPP Second Color // @namespace http://tampermonkey.net/ // @version 1.9 // @description Ability to have a second color in MPP // @author meleestars // @license MIT // @match https://multiplayerpiano.com/* // @match https://multiplayerpiano.net/* // @match https://multiplayerpiano.org/* // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACDSURBVDhPY2TABooL/kNZBAGKAXxFOURrhAG4AXKF6SRrBgGwAXqFyWRpBgGwAXYFceQb4JcfRbZmEGCMyw+jzIC8vEDKDKjL86XMgP5cD8oMmJ/jQpkBIGJ9jj3ZhoAN2J9tTZkBIHA+y5wsQ+AGgMD9LCOSDUExAAbeZ+oRaRADAwAarSM3FaaFtwAAAABJRU5ErkJggg== // @grant none // ==/UserScript== function _sc_init() { const _sc_version = "1.9"; window._sc_users = {}; let currentSecondColor = window.localStorage.getItem("secondColor") || '#777777'; let currentAtTop = (window.localStorage.getItem("atTop") === 'true') || false; function _sc_isColorInvalid(sc) { return typeof sc !== "string" || !CSS.supports("color", sc) || sc.length !== 7; } function _sc_sendColor(sc, atTop, global, user, req) { if (_sc_isColorInvalid(sc)) sc = MPP.client.getOwnParticipant().color; window.localStorage.setItem("secondColor", sc); currentSecondColor = sc; const top = String(atTop) === 'true'; window.localStorage.setItem("atTop", top); currentAtTop = top; if (global) MPP.client.sendArray([{m: "custom", data: {sc, atTop: top, requestSc: req}, target: {mode: "subscribed"}}]); else MPP.client.sendArray([{m: "custom", data: {sc, atTop: top, requestSc: req}, target: {mode: "id", id: user}}]); } function _sc_getOwnColor() { let secondColor = currentSecondColor; if (secondColor === null) { window.localStorage.setItem("secondColor", MPP.client.getOwnParticipant().color); secondColor = window.localStorage.getItem("secondColor"); } if (_sc_isColorInvalid(secondColor)) secondColor = MPP.client.getOwnParticipant().color; return secondColor; } function _sc_logUsers() { const users = []; for (const user of Object.entries(window._sc_users)) users.push("`" + user[1][0] + "`"); MPP.chat.receive({ m: "a", p: { _id: "Second", name: "Color" }, a: `Users that use Second Color: ${users.join(", ")}`, t: Date.now() }); } function _sc_patchReply(msg) { const replyId = msg.r; console.log(msg); if (replyId == null) return; const replyLink = $(`#chat ul li#msg-${msg.id} .replyLink`)[0]; const repliedUser = $(`#chat ul li#msg-${replyId}`)[0].title; if (replyLink && window._sc_users[repliedUser]) { const participant = MPP.client.findParticipantById(repliedUser); const replied = window._sc_users[repliedUser]; const atTop = window._sc_users[repliedUser][2]; if (atTop) replyLink.style.background = `linear-gradient(${replied[1]}, ${participant.color})`; else replyLink.style.background = `linear-gradient(${participant.color}, ${replied[1]})`; } } MPP.client.on('hi', () => MPP.client.sendArray([{m: "+custom"}])); MPP.client.on('ch', () => { let secondColor = _sc_getOwnColor(); const participant = MPP.client.getOwnParticipant(); window._sc_users[participant.id] = [participant.name, secondColor, currentAtTop]; const background = currentAtTop ? `linear-gradient(${ secondColor }, ${ participant.color })` : `linear-gradient(${ participant.color }, ${ secondColor })`; if (participant.nameDiv) participant.nameDiv.style.background = background; if (participant.cursorDiv) participant.cursorDiv.getElementsByClassName("name")[0].style.background = background; _sc_sendColor(secondColor, currentAtTop, true, "", true); }); MPP.client.on('participant added', msg => { _sc_sendColor(_sc_getOwnColor(), currentAtTop, false, msg.id, true); }); MPP.client.on('bye', msg => { delete window._sc_users[msg.p]; }); MPP.client.on('c', msg => { for (let a of msg.c) _sc_patchReply(a); }); MPP.client.on('a', msg => { _sc_patchReply(msg); }); MPP.client.on('custom', msg => { if (msg.data.sc !== undefined) { let secondColor = msg.data.sc; let participant = MPP.client.findParticipantById(msg.p); if (_sc_isColorInvalid(secondColor)) secondColor = participant.color; const background = msg.data.atTop ? `linear-gradient(${ secondColor }, ${ participant.color })` : `linear-gradient(${ participant.color }, ${ secondColor })`; if (participant.nameDiv) participant.nameDiv.style.background = background; if (participant.cursorDiv) participant.cursorDiv.getElementsByClassName("name")[0].style.background = background; if (participant.tag === undefined) participant.nameDiv.title = "This user is using Second Color."; else switch (participant.tag.text) { default: case '': case undefined: participant.nameDiv.title = "This user is using Second Color."; break; case 'ROOMKEEPER': case 'BOT': participant.nameDiv.title = "This is an authorized bot which is using Second Color."; break; case 'MOD': participant.nameDiv.title = "This user is an official moderator of the site who is using Second Color."; break; case 'ADMIN': participant.nameDiv.title = "This user is an official administrator of the site who is using Second Color."; break; case 'OWNER': participant.nameDiv.title = "This user is the owner of the site who is using Second Color."; break; case 'MEDIA': participant.nameDiv.title = "This is a well known person on Twitch, Youtube, or another platform who is using Second Color."; break; } window._sc_users[participant.id] = [participant.name, secondColor, msg.data.atTop]; if (_sc_isColorInvalid(window.localStorage.getItem("secondColor"))) window.localStorage.setItem("secondColor", MPP.client.getOwnParticipant().color); if (msg.data.requestSc && msg.p !== MPP.client.getOwnParticipant().id) _sc_sendColor(window.localStorage.getItem("secondColor"), currentAtTop, false, msg.p); } }); $("#rename .submit").click(() => { const participant = MPP.client.getOwnParticipant(); const name = $("#rename input[name=name]").val(); const firstColor = $("#rename input[name=color]").val(); const secondColor = $("#rename input[name=secondcolor]").val(); const top = document.querySelector('#rename input[id="second-color-at-top"]').checked; MPP.client.sendArray([{m: "userset", set: {name, color: firstColor}}]); window._sc_users[participant.id][1] = secondColor; if (secondColor !== window.localStorage.getItem("secondColor") || top !== (window.localStorage.getItem("atTop") === 'true')) _sc_sendColor(secondColor, top, true); if (participant.nameDiv) participant.nameDiv.style.background = top ? `linear-gradient(${secondColor}, ${firstColor})` : `linear-gradient(${firstColor}, ${secondColor})`; if (participant.cursorDiv) participant.cursorDiv.style.background = top ? `linear-gradient(${secondColor}, ${firstColor})` : `linear-gradient(${firstColor}, ${secondColor})`; }); function _sc_createButtons() { $("#rename p .text")[0].style.marginBottom = "5px"; const br = document.createElement("br"); $("#rename p .text")[0].after(br); const button = document.createElement("input"); const secondColor = (window.localStorage.getItem("secondColor") === null || _sc_isColorInvalid(window.localStorage.getItem("secondColor"))) ? MPP.client.getOwnParticipant().color : window.localStorage.getItem("secondColor"); button.setAttribute("type", "color"); button.setAttribute("class", "color"); button.setAttribute("placeholder", ""); button.setAttribute("value", secondColor); button.setAttribute("maxlength", 7); button.setAttribute("name", "secondcolor"); const _button = document.createElement("button"); _button.innerText = "Invert"; _button.setAttribute("class", "ugly-button"); _button.setAttribute("id", "invert"); _button.style = "margin-left: 10px; width: 50px; height: 27px; user-select: none; color: white"; _button.onclick = () => { let firstColor = $("#rename p .color")[0].value; $("#rename p .color")[0].value = button.value; button.value = firstColor; } const label = document.createElement("label"); label.innerText = ' Second color at top: '; label.style.fontSize = '16px'; label.setAttribute("id", "scattop"); const checkbox = document.createElement("input"); checkbox.type = 'checkbox'; checkbox.id = 'second-color-at-top'; checkbox.checked = currentAtTop; label.appendChild(checkbox); $("#rename p").append(button).append(_button).append(label); const _br = document.createElement("br"); $("#rename p #scattop")[0].before(_br); const bottomButton = document.createElement("div"); bottomButton.setAttribute("class", "ugly-button sclist-btn"); bottomButton.setAttribute("id", "sclist-btn"); bottomButton.innerText = "SC Users"; bottomButton.onclick = _sc_logUsers; $("#bottom .relative .buttons")[0].appendChild(bottomButton); } _sc_createButtons(); setTimeout(() => { fetch(new Request("https://aod.undo.it/misc/scv")).then(response => response.text().then(text => { const _sc_actualVersion = text.trim(); if (_sc_version.indexOf(_sc_actualVersion) < 0) { new MPP.Notification({ title: "Your Second Color version is outdated!", text: `You have ${_sc_version} while the latest is ${_sc_actualVersion}! Please get the new version from: https://greasyfork.org/en/users/1085754-mpp-firefox`, target: "#piano", duration: 10000 }); } })); }, 3000); console.log(`MPP Second Color ${_sc_version} loaded!`); new MPP.Notification({ title: "Second Color", text: `MPP Second Color ${_sc_version} loaded!`, target: "#piano", duration: 3000 }); }; function _sc_mppExists() { if (window.MPP === undefined) requestAnimationFrame(_sc_mppExists); else _sc_init(); } requestAnimationFrame(_sc_mppExists);