MVPS

MVPS [Multi Visual Piano Script] designed to expand the technical and visual capabilities of the MPP

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

// ==UserScript==
// @name         MVPS
// @namespace    http://tampermonkey.net/
// @version      0.8
// @description  MVPS [Multi Visual Piano Script] designed to expand the technical and visual capabilities of the MPP
// @author       Hustandant#1917
// @match        *://mppclone.com/*
// @include      *://www.multiplayerpiano.com/*
// @include      *://multiplayerpiano.com/*
// @include      *://piano.ourworldofpixels.com/*
// @include      *://mppfork.netlify.app/*
// @match        *.mpp.hri7566.info/*
// @match        *://mpp.autoplayer.xyz/*
// @icon         https://github.com/Hustoroff/mpp/blob/main/icon.png?raw=true
// @resource     https://raw.githubusercontent.com/Hustoroff/mpp/main/MVPS.js
// @grant        none
// @run-at       document-end
// ==/UserScript==
window.addEventListener('load', (event) => {
$("#bottom .relative").append(`<div id="MVPS" class="ugly-button 2_btn">MVPS</div>`);
$("#MVPS").css({position: "absolute", left: "1020px", top: "32px"}).on("click", () => {
    MPP.client.emit("notification", {
        title: "Multi Visual Piano Script (by Hustandant#1917)",
        id:"MVPS_notification",
        duration:-1,
        target:"#MVPS",
        html:`
        <div id="visual_block" style="border-radius: 10px; background-color: #171115; border: 2px solid #333; padding: 4px 12px">
        <h3>Visual:</h3></p>
        <div id="chtClr" class="ugly-button">Clear chat</div>
        <div id="nmsHdn" class="ugly-button">Hide names</div>
        <input type="text" id="inpBack" placeholder="New backround (Image URL)"><button id="back">Background</button></input></br>
        Load background file:<input type="file" id="inpBackimg"></input>
        </div></br>
        <div id="drawBlock" style="border-radius: 10px; background-color: #171115; border: 2px solid #333; padding: 4px 12px">
        <h3>Drawing:</h3></p>
        <div id="clearBtn" class="ugly-button">Clear Drawings</div>
        <div id="drwbrdHdn" class="ugly-button">Drawboard hide</div>
        <div id="rnbwMd" class="ugly-button">Rainbow lines</div>
        <input id="lineTime" type="range" min="1" max="250" title="line lifetime"></input>
        <input id="clrChng" type="color"><button id="clrBtn">Select color</button></input>
        <input id="lineSize"type="range" min="1" max="10" title="brush size"></input></br>
        </div></br>
        <div id="otherBlock" style="border-radius: 10px; background-color: #171115; border: 2px solid #333; padding: 4px 12px">
        <h3>Other settings:</h3>
        <div id="rnbw" class="ugly-button" title="ANIME!?!?!??!?!?!??!?!??!?!">Rainbow room</div>
        <div id="rnbwNt" class="ugly-button">Rainbow notes</div>
        <div id="rnbwNick" class="ugly-button">Rainbow nick</div>
        <div id="pnoSpn" class="ugly-button">Spin piano</div>
        <input type="text" id="inpImg" placeholder="Paste image (Image URL)"><button id="pasteImg">Paste image</button></input></br>
        Load image file:</br><input type="file" id="inpPastImg"></input>
        </div>`
    });
    document.getElementById("chtClr").addEventListener("click", () => { chat_clear() });
    document.getElementById("nmsHdn").addEventListener("click", () => { names_hide = !names_hide; namesHde() });
    document.getElementById("inpBack").addEventListener("input", () => { url_back = document.getElementById("inpBack").value });
    document.getElementById("back").addEventListener("click", () => { backg = !backg; background_del(); });
    document.getElementById("inpBackimg").addEventListener("input", () => { showpreview1(document.getElementById("inpBackimg")) });
    document.getElementById("clearBtn").addEventListener("click", () => { MPP.addons.draw.lines = [[0,0,0,0,0,0,"#0"]] });
    document.getElementById("drwbrdHdn").addEventListener("click", () => { drawboard_hide = !drawboard_hide; drawboard_hde() });
    document.getElementById("rnbwMd").addEventListener("click", () => { rainbowmodename = !rainbowmodename });
    document.getElementById("lineTime").addEventListener("input", () => { MPP.addons.draw.lineLife = document.getElementById("lineTime").value });
    document.getElementById("clrBtn").addEventListener("click", () => { MPP.addons.draw.customColor=document.getElementById("clrChng").value });
    document.getElementById("lineSize").addEventListener("input", () => { MPP.addons.draw.brushSize = document.getElementById("lineSize").value });
    document.getElementById("rnbw").addEventListener("click", () => { rainbowmode = !rainbowmode });
    document.getElementById("rnbwNt").addEventListener("click", () => { rainbowmodenote = !rainbowmodenote });
    document.getElementById("rnbwNick").addEventListener("click", () => { rainbownick = !rainbownick });
    document.getElementById("pnoSpn").addEventListener("click", () => { pianospinbool = !pianospinbool; pianospn() });
    document.getElementById("inpImg").addEventListener("input", () => { url_past_img = document.getElementById("inpImg").value });
    document.getElementById("pasteImg").addEventListener("click", () => { paste_image(url_past_img) });
    document.getElementById("inpPastImg").addEventListener("input", () => { showpreview2(document.getElementById("inpPastImg")) });
    var pianospinbool = false,
        backimg = false,
        rainbowmodename = false,
        rainbowmodenote = false,
        rainbowmode = false,
        backg = false,
        piano = true,
        chat_hide = false,
        names_hide = false,
        drawboard_hide = true,
        rainbownick = false,
        url_past_img = "https://mpp.terrium.net/meow64.png",
        url_back = "https://steamuserimages-a.akamaihd.net/ugc/878625026160084538/0399E81B0D1CF96C853CFCC1288D3E0A3D708049/?imw=1024&imh=819&ima=fit&impolicy=Letterbox&imcolor=%23000000&letterbox=true";
    //MPP draw image script by Ledlamp [https://gist.github.com/ledlamp/ef0d4db05a49fb795ec59cf96bedbf26] (thx a lot :3)
    function paste_image(){
        function getRandomColor() {
            var letters = '0123456789ABCDEF';
            var color = '#';
            for (var i = 0; i < 6; i++) {
                color += letters[Math.floor(Math.random() * 16)];
            }
            return color;
        }

        function drawPixel(x, y, color) {
            MPP.addons.draw.mkline(x-1,y,x,y,10,color)
        }

        function componentToHex(c) {
            var hex = c.toString(16);
            return hex.length == 1 ? "0" + hex : hex;
        }

        function rgbToHex(r, g, b) {
            return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
        }
        var img = document.createElement("img");
        img.crossOrigin = "Anonymous";
        img.addEventListener('load', function(){
            console.log(img);
            var canvas = document.createElement('canvas');
            canvas.width = img.width;
            canvas.height = img.height;
            var c = canvas.getContext('2d');
            c.drawImage(img, 0, 0, img.width, img.height);
            console.log(canvas);
            var pos1 = [128-img.width/2,128-img.height/2], pos2 = [128+img.width/2,128+img.height/2];
            var ii=0;
            for (let x = pos1[0], xo = 0; x < pos2[0]; x++, xo++)
                for (let y = pos1[1], yo = 0; y < pos2[1]; y++, yo++) {
                setTimeout(()=>{
                    var rgb = c.getImageData(xo,yo, 1, 1).data;
                    drawPixel(x,y, rgbToHex(rgb[0], rgb[1], rgb[2]));
                } ,++ii * 10);
                }
        });
    img.src = url_past_img;
    };

    function showpreview1(e) {
        var reader = new FileReader();
        reader.onload = function (e) {
            url_back = e.target.result;
            background_del();
        };
        reader.readAsDataURL(e.files[0]);
    }

    function showpreview2(e) {
        var reader = new FileReader();
        reader.onload = function (e) {
            url_past_img = e.target.result;
        };
        reader.readAsDataURL(e.files[0]);
    }

    // DRAW script by Hri7566 [https://github.com/Hri7566] (thx a lot :3)
    let authenicated = false;
    EXT = window.EXT || {_initfunc: []};

    setInterval(()=>{
        if(Object.entries(MPP.client.ppl).length !== 0 && !authenicated) {
            MPP.client.sendArray([{m:"+custom"}]);

            MPP = MPP || {};
            MPP.addons = EXT;
            for(var x = EXT._initfunc.length; x--;)
                EXT._initfunc[x]();
            EXT.__proto__ = null;
            authenicated = true;
        }
    }, 100);
    /* By ming, v3 */
    EXT._initfunc.push(function(){
        var addon = EXT.draw = {__proto__: null};
        addon.lineLife = 25;
        var p = document.createElement("canvas");
        p.id = "drawboard";
        p.style = "position: absolute; top: 0; left: 0; z-index: 400; pointer-events: none;";
        p.width = window.innerWidth;
        p.height = window.innerHeight;
        document.body.appendChild(p);
        var dbctx = p.getContext("2d");
        var shifted = false;
        var clicking = false;
        $(document).on('mousedown', (e)=>{ if(e.shiftKey){ clicking = true; draw(); e.preventDefault(); }});
        $(document).on('mouseup', (e)=>{ clicking = false; });
        $(document).on('keyup keydown', (e)=>{ shifted = e.shiftKey; });

        addon.enabled = true;
        addon.customColor = null;
        addon.ctx = dbctx;
        addon.onrefresh = [];
        addon.brushSize = 8;
        addon.mutes = [];
        addon.lines = [];
        addon.buf = [{n: "ldraw", v: 0}];
        function resize(){
            p.width = window.innerWidth;
            p.height = window.innerHeight;
        }
        window.addEventListener('resize', resize, false);
        addon.flushloop = setInterval(()=>{
            var t = Date.now();
            if(addon.buf.length != 1){
                if(addon.buf.length>1)
                    MPP.client.sendArray([{m: "custom", data: {m: 'draw', t: t, n: addon.buf}, target: { mode: 'subscribed' } }]);
                addon.buf = [{n: "ldraw", v: 0}];
            }
        }, 1000/60/16);
        addon.onrefresh.push(function(t){
            if(addon.lines.length){
                dbctx.clearRect(0,0,window.innerWidth, window.innerHeight);
                for(var l = 0; l<addon.lines.length;l++){
                    dbctx.globalAlpha = 1;
                    var c=addon.lines[l];
                    dbctx.strokeStyle = c[6];
                    dbctx.lineWidth = c[5];
                    var d = addon.lineLife - (t - c[4]) / 1000;
                    if(d <= 0){
                        addon.lines.splice(l--, 1);
                        continue;
                    }
                    dbctx.globalAlpha = 0.3 * d;
                    dbctx.beginPath();
                    dbctx.moveTo(c[0], c[1]);
                    dbctx.lineTo(c[2], c[3]);
                    dbctx.stroke();
                }
            }
        });
        function redraw(){
            if(addon.enabled){
                var t = Date.now();
                for(var x = 0; x < addon.onrefresh.length; x++){
                    addon.onrefresh[x](t);
                }
            }
            /*window.requestAnimationFrame(redraw);*/
        }
        /*window.requestAnimationFrame(redraw);*/
        setInterval(redraw, 1000/60/16);
        /* https://stackoverflow.com/a/8639991 */
        function stringToBytesFaster(str) {
            var ch, st, re = [], j=0;
            for (var i = 0; i < str.length; i++ ) {
                ch = str.charCodeAt(i);
                if(ch < 127){
                    re[j++] = ch & 0xFF;
                } else {
                    st = [];
                    do {
                        st.push(ch & 0xFF);
                        ch = ch >> 8;
                    } while (ch);
                    st = st.reverse();
                    for(var k=0;k<st.length; ++k)
                        re[j++] = st[k];
                }
            }
            return re;
        }
        function parseLine(str, color, size){
            var vector = [0, 0, 0, 0, Date.now(), 1, color];
            var bytes = stringToBytesFaster(str);
            vector[0] = Math.round(((100 / 255) * bytes[0]/100) * window.innerWidth);
            vector[1] = Math.round(((100 / 255) * bytes[1]/100) * window.innerHeight);
            vector[2] = Math.round(((100 / 255) * bytes[2]/100) * window.innerWidth);
            vector[3] = Math.round(((100 / 255) * bytes[3]/100) * window.innerHeight);
            vector[5] = size;
            addon.lines.push(vector);
        }
        function draw(){
            var u = MPP.client.getOwnParticipant();
            u.y = Math.max(Math.min(100,u.y), 0);
            u.x = Math.max(Math.min(100,u.x), 0);
            var lastpos = [u.x, u.y];
            var b = new ArrayBuffer(4);
            var dv = new DataView(b);
            dv.setUint8(0, Math.round(u.x/100 * 255));
            dv.setUint8(1, Math.round(u.y/100 * 255));
            function poll(){
                if(lastpos[0] != u.x || lastpos[1] != u.y){
                    u.y = Math.max(Math.min(100,u.y), 0);
                    u.x = Math.max(Math.min(100,u.x), 0);
                    dv.setUint8(2, Math.round(u.x/100 * 255));
                    dv.setUint8(3, Math.round(u.y/100 * 255));
                    var s = String.fromCharCode.apply(null, new Uint8Array(b));
                    var clr = addon.customColor || MPP.client.getOwnParticipant().color;
                    addon.buf.push({n: s, v: Math.min(addon.brushSize, 5), d: parseInt(clr.slice(1), 16)});
                    dv.setUint8(0, Math.round(u.x/100 * 255));
                    dv.setUint8(1, Math.round(u.y/100 * 255));
                    lastpos = [u.x, u.y];
                    parseLine(s, clr, Math.min(addon.brushSize, 5));
                }
                if(clicking)
                    setTimeout(poll, 1);
            }
            setTimeout(poll, 1);
        }

        addon.mkline = function(x, y, x2, y2, s, color){
            if(x<0||y<0||x2<0||y2<0||x>255||y>255||x2>255||y2>255)return;
            var b = new ArrayBuffer(4);
            var dv = new DataView(b);
            dv.setUint8(0, x);
            dv.setUint8(1, y);
            dv.setUint8(2, x2);
            dv.setUint8(3, y2);
            var str = String.fromCharCode.apply(null, new Uint8Array(b));
            var clr = color || addon.customColor || MPP.client.getOwnParticipant().color;
            addon.buf.push({n: str, v: Math.min(s||1, 5), d: parseInt(clr.slice(1), 16)});
            parseLine(str, clr, Math.min(s||1, 5));
        }
        addon.tohtml = function(c) {
            c = c.toString(16);
            return '#' + ('000000' + c).substring(c.length);
        };
        MPP.client.on('custom', (msg) => {
            if (msg.data.m !== 'draw') return;
            if(msg.data.n[0].n == "ldraw" && addon.mutes.indexOf(MPP.client.findParticipantById(msg.data.p)._id) === -1){
                msg.data.n.reduce(function(a, b){
                    if(b.n.length == 4){
                        var clr = (b.d !== undefined && addon.tohtml(b.d)) || MPP.client.findParticipantById(msg.data.p).color;
                        parseLine(b.n, clr, Math.min(b.v,5));
                    }
                });
            }
        });
        MPP.client.on('c', ()=>{
            addon.lines = [[0,0,0,0,0,0,"#0"]];
        });
    });
    function background_del(){
        if(backg) {
            var d=document.createElement('div');
            d.style.width = '1280px';
            d.style.height = '913px';
            d.style.position = 'absolute';
            d.style.top= '0px';
            d.style.left= '0px';
            d.id='backgdiv'
            document.body.appendChild(d);
            $("#backgdiv").css({width: window.innerWidth, height: window.innerHeight, "background-position": "25% 25%", "background-size": "cover", "backdrop-effect": "blur(4px)", "background-image": "url("+url_back+")"})
            console.log(url_back)
        } else $("#backgdiv").remove();
    }

    function chat_clear(){ $('ul').empty() }

    function namesHde(){
        if(names_hide) $("#names").css({opacity: "0"});
        else $("#names").css({opacity: "1"});
    }

    function drawboard_hde(){
        if(drawboard_hide) $("#drawboard").css({opacity: "1"});
        else $("#drawboard").css({opacity: "0"});
    }

    function pianospn(){ $("#piano").toggleClass("spin", pianospinbool) }
    //Rainbow room mode script
    var count = 0;
    var size = 100;
    var rainbow = new Array(size);

    for (var i = 0; i < size; i++) {
        var red = sin_to_hex(i, 0 * Math.PI * 2 / 3); // 0   deg
        var blue = sin_to_hex(i, 1 * Math.PI * 2 / 3); // 120 deg
        var green = sin_to_hex(i, 2 * Math.PI * 2 / 3); // 240 deg
        rainbow[i] = "#" + red + green + blue;
    }

    function sin_to_hex(i, phase) {
        var sin = Math.sin(Math.PI / size * 2 * i + phase);
        var int = Math.floor(sin * 127) + 128;
        var hex = int.toString(16);
        return hex.length === 1 ? "0" + hex : hex;
    }

    setInterval(function() {
        if (count > rainbow.length)  count = 0;
        if(rainbowmodename)
            MPP.addons.draw.customColor = rainbow[count]
        if(rainbowmodenote){
            id = MPP.client.getOwnParticipant();
            id.color = rainbow[count];
        }
        if(rainbownick)
            $("#namediv-"+MPP.client.getOwnParticipant().id).css({"background-color": rainbow[count]})
        count++;
    }, 33);

    setInterval(function() {
        if (rainbowmode && MPP.client.isOwner()) {
            if (count > rainbow.length) count = 0;
            MPP.client.sendArray([{ m: "chset", set: { color: rainbow[count] } }]);
        }
        count++;
    }, 500);
});
});