From de8eec5cd9403bc4fb501bbf337305dd7afbd696 Mon Sep 17 00:00:00 2001 From: Hri7566 Date: Wed, 19 Feb 2025 22:50:21 -0500 Subject: [PATCH 01/25] Add allowBots --- client/index.html | 3 +- client/script.js | 646 +++++++++++++++++++++++----------------------- 2 files changed, 323 insertions(+), 326 deletions(-) diff --git a/client/index.html b/client/index.html index 93f7422..5ba2602 100644 --- a/client/index.html +++ b/client/index.html @@ -178,6 +178,7 @@

+

').appendTo(document.body).hide(); var jqcountdown = $("").appendTo(jqcrown); var countdown_interval; - jqcrown.click(function () { + jqcrown.click(function() { gClient.sendArray([{ m: "chown", id: gClient.participantId }]); }); - gClient.on("ch", function (msg) { + gClient.on("ch", function(msg) { if (msg.ch.crown) { var crown = msg.ch.crown; if (!crown.participantId || !gClient.ppl[crown.participantId]) { @@ -1545,13 +1544,13 @@ $(function () { }, 2000, "linear", - function () { + function() { jqcrown.removeClass("spin"); }, ); } clearInterval(countdown_interval); - countdown_interval = setInterval(function () { + countdown_interval = setInterval(function() { var time = Date.now(); if (time >= land_time) { var ms = avail_time - time; @@ -1570,13 +1569,13 @@ $(function () { jqcrown.hide(); } }); - gClient.on("disconnect", function () { + gClient.on("disconnect", function() { jqcrown.fadeOut(2000); }); })(); // Playing notes - gClient.on("n", function (msg) { + gClient.on("n", function(msg) { var t = msg.t - gClient.serverTimeOffset + TIMING_TARGET - Date.now(); var participant = gClient.findParticipantById(msg.p); if (gPianoMutes.indexOf(participant._id) !== -1) return; @@ -1607,7 +1606,7 @@ $(function () { last_mx = -10, my = 0, last_my = -10; - setInterval(function () { + setInterval(function() { if (Math.abs(mx - last_mx) > 0.1 || Math.abs(my - last_my) > 0.1) { last_mx = mx; last_my = my; @@ -1627,14 +1626,14 @@ $(function () { } } }, 50); - $(document).mousemove(function (event) { + $(document).mousemove(function(event) { mx = ((event.pageX / $(window).width()) * 100).toFixed(2); my = ((event.pageY / $(window).height()) * 100).toFixed(2); }); // Room settings button - (function () { - gClient.on("ch", function (msg) { + (function() { + gClient.on("ch", function(msg) { if (gClient.isOwner() || gClient.permissions.chsetAnywhere) { $("#room-settings-btn").show(); } else { @@ -1650,14 +1649,14 @@ $(function () { $("#getcrown-btn").hide(); } }); - $("#room-settings-btn").click(function (evt) { + $("#room-settings-btn").click(function(evt) { if ( gClient.channel && (gClient.isOwner() || gClient.permissions.chsetAnywhere) ) { var settings = gClient.channel.settings; openModal("#room-settings"); - setTimeout(function () { + setTimeout(function() { $("#room-settings .checkbox[name=visible]").prop( "checked", settings.visible, @@ -1680,11 +1679,15 @@ $(function () { "checked", settings.noindex, ); + $("#room-settings .checkbox[name=allowBots]").prop( + "checked", + settings.allowBots, + ); $("#room-settings input[name=limit]").val(settings.limit); }, 100); } }); - $("#room-settings .submit").click(function () { + $("#room-settings .submit").click(function() { var settings = { visible: $("#room-settings .checkbox[name=visible]").is(":checked"), chat: $("#room-settings .checkbox[name=chat]").is(":checked"), @@ -1693,6 +1696,7 @@ $(function () { ":checked", ), noindex: $("#room-settings .checkbox[name=noindex]").is(":checked"), + allowBots: $("#room-settings .checkbox[name=allowBots]").is(":checked"), color: $("#room-settings input[name=color]").val(), color2: $("#room-settings input[name=color2]").val(), limit: $("#room-settings input[name=limit]").val(), @@ -1700,7 +1704,7 @@ $(function () { gClient.setChannelSettings(settings); closeModal(); }); - $("#room-settings .drop-crown").click(function () { + $("#room-settings .drop-crown").click(function() { closeModal(); if (confirm("This will drop the crown...!")) gClient.sendArray([{ m: "chown" }]); @@ -1708,18 +1712,18 @@ $(function () { })(); // Clear chat button - $("#clearchat-btn").click(function (evt) { + $("#clearchat-btn").click(function(evt) { if (confirm("Are you sure you want to clear chat?")) gClient.sendArray([{ m: "clearchat" }]); }); // Get crown button - $("#getcrown-btn").click(function (evt) { + $("#getcrown-btn").click(function(evt) { gClient.sendArray([{ m: "chown", id: MPP.client.getOwnParticipant().id }]); }); // Vanish or unvanish button - $("#vanish-btn").click(function (evt) { + $("#vanish-btn").click(function(evt) { gClient.sendArray([ { m: "v", vanish: !gClient.getOwnParticipant().vanished }, ]); @@ -1744,12 +1748,12 @@ $(function () { }); // Handle notifications - gClient.on("notification", function (msg) { + gClient.on("notification", function(msg) { new Notification(msg); }); // Don't foget spin - gClient.on("ch", function (msg) { + gClient.on("ch", function(msg) { var chidlo = msg.ch._id.toLowerCase(); if (chidlo === "spin" || chidlo.substr(-5) === "/spin") { $("#piano").addClass("spin"); @@ -1771,7 +1775,7 @@ $(function () { }*/ // Crownsolo notice - gClient.on("ch", function (msg) { + gClient.on("ch", function(msg) { let notice = ""; let has_notice = false; if (msg.ch.settings.crownsolo) { @@ -1790,7 +1794,7 @@ $(function () { if (notice_div.is(":visible")) notice_div.fadeOut(1000); } }); - gClient.on("disconnect", function () { + gClient.on("disconnect", function() { $("#room-notice").fadeOut(1000); }); @@ -1879,7 +1883,7 @@ $(function () { } // Background color - (function () { + (function() { var old_color1 = new Color("#000000"); var old_color2 = new Color("#000000"); function setColor(hex, hex2) { @@ -1912,7 +1916,7 @@ $(function () { difference.b / steps, ); var iv; - iv = setInterval(function () { + iv = setInterval(function() { old_color1.add(inc1.r, inc1.g, inc1.b); old_color2.add(inc2.r, inc2.g, inc2.b); document.body.style.background = @@ -1946,7 +1950,7 @@ $(function () { setColorToDefault(); - gClient.on("ch", function (ch) { + gClient.on("ch", function(ch) { if (gNoBackgroundColor) { setColorToDefault(); return; @@ -1966,19 +1970,19 @@ $(function () { $("#volume-label").text( "Volume: " + Math.floor(gPiano.audio.volume * 100) + "%", ); - volume_slider.addEventListener("input", function (evt) { + volume_slider.addEventListener("input", function(evt) { var v = +volume_slider.value; gPiano.audio.setVolume(v); if (window.localStorage) localStorage.volume = v; $("#volume-label").text("Volume: " + Math.floor(v * 100) + "%"); }); - var Note = function (note, octave) { + var Note = function(note, octave) { this.note = note; this.octave = octave || 0; }; - var n = function (a, b) { + var n = function(a, b) { return { note: new Note(a, b), held: false }; }; @@ -2206,7 +2210,7 @@ $(function () { return false; } - var recapListener = function (evt) { + var recapListener = function(evt) { captureKeyboard(); }; @@ -2236,18 +2240,18 @@ $(function () { captureKeyboard(); - var velocityFromMouseY = function () { + var velocityFromMouseY = function() { return 0.1 + (my / 100) * 0.6; }; // NoteQuota - var gNoteQuota = (function () { + var gNoteQuota = (function() { var last_rat = 0; var nqjq = $("#quota .value"); - setInterval(function () { + setInterval(function() { gNoteQuota.tick(); }, 2000); - return new NoteQuota(function (points) { + return new NoteQuota(function(points) { // update UI var rat = (points / this.max) * 100; if (rat <= last_rat) @@ -2259,10 +2263,10 @@ $(function () { last_rat = rat; }); })(); - gClient.on("nq", function (nq_params) { + gClient.on("nq", function(nq_params) { gNoteQuota.setParams(nq_params); }); - gClient.on("disconnect", function () { + gClient.on("disconnect", function() { gNoteQuota.setParams(NoteQuota.PARAMS_OFFLINE); }); @@ -2289,8 +2293,8 @@ $(function () { }); // click participant names - (function () { - participantTouchhandler = function (e, ele) { + (function() { + participantTouchhandler = function(e, ele) { var target = ele; var target_jq = $(target); if (!target_jq) return; @@ -2299,7 +2303,7 @@ $(function () { var id = target.participantId; if (id == gClient.participantId) { openModal("#rename", "input[name=name]"); - setTimeout(function () { + setTimeout(function() { $("#rename input[name=name]").val( gClient.ppl[gClient.participantId].name, ); @@ -2316,20 +2320,20 @@ $(function () { } } }; - var releasehandler = function (e) { + var releasehandler = function(e) { $("#names .name").removeClass("play"); }; document.body.addEventListener("mouseup", releasehandler); document.body.addEventListener("touchend", releasehandler); - var removeParticipantMenus = function () { + var removeParticipantMenus = function() { $(".participant-menu").remove(); $(".participantSpotlight").hide(); document.removeEventListener("mousedown", removeParticipantMenus); document.removeEventListener("touchstart", removeParticipantMenus); }; - var participantMenu = function (part) { + var participantMenu = function(part) { if (!part) return; removeParticipantMenus(); document.addEventListener("mousedown", removeParticipantMenus); @@ -2347,12 +2351,12 @@ $(function () { left: pos.left + 6, background: part.color || "black", }); - menu.on("mousedown touchstart", function (evt) { + menu.on("mousedown touchstart", function(evt) { evt.stopPropagation(); var target = $(evt.target); if (target.hasClass("menu-item")) { target.addClass("clicked"); - menu.fadeOut(200, function () { + menu.fadeOut(200, function() { removeParticipantMenus(); }); } @@ -2376,7 +2380,7 @@ $(function () { )}`, ) .appendTo(menu) - .on("mousedown touchstart", function (evt) { + .on("mousedown touchstart", function(evt) { gPianoMutes.push(part._id); if (localStorage) localStorage.pianoMutes = gPianoMutes.join(","); $(part.nameDiv).addClass("muted-notes"); @@ -2388,7 +2392,7 @@ $(function () { )}`, ) .appendTo(menu) - .on("mousedown touchstart", function (evt) { + .on("mousedown touchstart", function(evt) { var i; while ((i = gPianoMutes.indexOf(part._id)) != -1) gPianoMutes.splice(i, 1); @@ -2403,7 +2407,7 @@ $(function () { )}`, ) .appendTo(menu) - .on("mousedown touchstart", function (evt) { + .on("mousedown touchstart", function(evt) { gChatMutes.push(part._id); if (localStorage) localStorage.chatMutes = gChatMutes.join(","); $(part.nameDiv).addClass("muted-chat"); @@ -2415,7 +2419,7 @@ $(function () { )}`, ) .appendTo(menu) - .on("mousedown touchstart", function (evt) { + .on("mousedown touchstart", function(evt) { var i; while ((i = gChatMutes.indexOf(part._id)) != -1) gChatMutes.splice(i, 1); @@ -2433,7 +2437,7 @@ $(function () { )}`, ) .appendTo(menu) - .on("mousedown touchstart", function (evt) { + .on("mousedown touchstart", function(evt) { gPianoMutes.push(part._id); if (localStorage) localStorage.pianoMutes = gPianoMutes.join(","); gChatMutes.push(part._id); @@ -2452,7 +2456,7 @@ $(function () { )}`, ) .appendTo(menu) - .on("mousedown touchstart", function (evt) { + .on("mousedown touchstart", function(evt) { var i; while ((i = gPianoMutes.indexOf(part._id)) != -1) gPianoMutes.splice(i, 1); @@ -2471,7 +2475,7 @@ $(function () { )}`, ) .appendTo(menu) - .on("mousedown touchstart", function (evt) { + .on("mousedown touchstart", function(evt) { chat.endDM(); }); } else { @@ -2481,7 +2485,7 @@ $(function () { )}`, ) .appendTo(menu) - .on("mousedown touchstart", function (evt) { + .on("mousedown touchstart", function(evt) { if (!gKnowsHowToDm) { localStorage.knowsHowToDm = true; gKnowsHowToDm = true; @@ -2504,7 +2508,7 @@ $(function () { )}`, ) .appendTo(menu) - .on("mousedown touchstart", function (evt) { + .on("mousedown touchstart", function(evt) { gCursorHides.push(part._id); if (localStorage) localStorage.cursorHides = gCursorHides.join(","); $(part.cursorDiv).hide(); @@ -2516,7 +2520,7 @@ $(function () { )}`, ) .appendTo(menu) - .on("mousedown touchstart", function (evt) { + .on("mousedown touchstart", function(evt) { var i; while ((i = gCursorHides.indexOf(part._id)) != -1) gCursorHides.splice(i, 1); @@ -2531,7 +2535,7 @@ $(function () { )}`, ) .appendTo(menu) - .on("mousedown touchstart", function (evt) { + .on("mousedown touchstart", function(evt) { $("#chat-input")[0].value += "@" + part.id + " "; setTimeout(() => { $("#chat-input").focus(); @@ -2546,7 +2550,7 @@ $(function () { )}`, ) .appendTo(menu) - .on("mousedown touchstart", function (evt) { + .on("mousedown touchstart", function(evt) { if (confirm("Give room ownership to " + part.name + "?")) gClient.sendArray([{ m: "chown", id: part.id }]); }); @@ -2557,7 +2561,7 @@ $(function () { )}`, ) .appendTo(menu) - .on("mousedown touchstart", function (evt) { + .on("mousedown touchstart", function(evt) { var minutes = prompt("How many minutes? (0-300)", "30"); if (minutes === null) return; minutes = parseFloat(minutes) || 0; @@ -2572,9 +2576,9 @@ $(function () { )}`, ) .appendTo(menu) - .on("mousedown touchstart", function (evt) { + .on("mousedown touchstart", function(evt) { openModal("#siteban"); - setTimeout(function () { + setTimeout(function() { $("#siteban input[name=id]").val(part._id); $("#siteban input[name=reasonText]").val( "Discrimination against others", @@ -2607,7 +2611,7 @@ $(function () { )}`, ) .appendTo(menu) - .on("mousedown touchstart", function (evt) { + .on("mousedown touchstart", function(evt) { var color = prompt("What color?", part.color); if (color === null) return; gClient.sendArray([{ m: "setcolor", _id: part._id, color: color }]); @@ -2620,7 +2624,7 @@ $(function () { )}`, ) .appendTo(menu) - .on("mousedown touchstart", function (evt) { + .on("mousedown touchstart", function(evt) { var name = prompt("What name?", part.name); if (name === null) return; gClient.sendArray([{ m: "setname", _id: part._id, name: name }]); @@ -2634,7 +2638,7 @@ $(function () { //////////////////////////////////////////////////////////////// - var Notification = function (par) { + var Notification = function(par) { if (this instanceof Notification === false) throw "yeet"; EventEmitter.call(this); @@ -2655,7 +2659,7 @@ $(function () { } this.domElement = $( '
' + - '
X
', + '
X
', ); this.domElement[0].id = this.id; this.domElement.addClass(this["class"]); @@ -2670,17 +2674,17 @@ $(function () { document.body.appendChild(this.domElement.get(0)); this.position(); - this.onresize = function () { + this.onresize = function() { self.position(); }; window.addEventListener("resize", this.onresize); - this.domElement.find(".x").click(function () { + this.domElement.find(".x").click(function() { self.close(); }); if (this.duration > 0) { - setTimeout(function () { + setTimeout(function() { self.close(); }, this.duration); } @@ -2691,7 +2695,7 @@ $(function () { mixin(Notification.prototype, EventEmitter.prototype); Notification.prototype.constructor = Notification; - Notification.prototype.position = function () { + Notification.prototype.position = function() { var pos = this.target.offset(); var x = pos.left - this.domElement.width() / 2 + this.target.width() / 4; var y = pos.top - this.domElement.height() - 8; @@ -2703,10 +2707,10 @@ $(function () { this.domElement.offset({ left: x, top: y }); }; - Notification.prototype.close = function () { + Notification.prototype.close = function() { var self = this; window.removeEventListener("resize", this.onresize); - this.domElement.fadeOut(500, function () { + this.domElement.fadeOut(500, function() { self.domElement.remove(); self.emit("close"); }); @@ -2721,7 +2725,7 @@ $(function () { if (localStorage && localStorage.knowsYouCanUseKeyboard) gKnowsYouCanUseKeyboard = true; if (!gKnowsYouCanUseKeyboard) { - window.gKnowsYouCanUseKeyboardTimeout = setTimeout(function () { + window.gKnowsYouCanUseKeyboardTimeout = setTimeout(function() { window.gKnowsYouCanUseKeyboardNotification = new Notification({ title: window.i18nextify.i18next.t("Did you know!?!"), text: window.i18nextify.i18next.t( @@ -2739,9 +2743,9 @@ $(function () { gPiano.audio.setVolume(localStorage.volume); $("#volume-label").html( window.i18nextify.i18next.t("Volume") + - ": " + - Math.floor(gPiano.audio.volume * 100) + - "%", + ": " + + Math.floor(gPiano.audio.volume * 100) + + "%", ); } else localStorage.volume = gPiano.audio.volume; @@ -2761,7 +2765,7 @@ $(function () { //////////////////////////////////////////////////////////////// $("#room > .info").text("--"); - gClient.on("ch", function (msg) { + gClient.on("ch", function(msg) { var channel = msg.ch; var info = $("#room > .info"); info.text(channel._id); @@ -2776,14 +2780,14 @@ $(function () { if (!channel.settings.visible) info.addClass("not-visible"); else info.removeClass("not-visible"); }); - gClient.on("ls", function (ls) { + gClient.on("ls", function(ls) { for (var i in ls.u) { if (!ls.u.hasOwnProperty(i)) continue; var room = ls.u[i]; var info = $( '#room .info[roomid="' + - (room.id + "").replace(/[\\"']/g, "\\$&").replace(/\u0000/g, "\\0") + - '"]', + (room.id + "").replace(/[\\"']/g, "\\$&").replace(/\u0000/g, "\\0") + + '"]', ); if (info.length == 0) { @@ -2797,10 +2801,10 @@ $(function () { info.text( room.count + - "/" + - ("limit" in room.settings ? room.settings.limit : 20) + - " " + - room._id, + "/" + + ("limit" in room.settings ? room.settings.limit : 20) + + " " + + room._id, ); if (room.settings.lobby) info.addClass("lobby"); else info.removeClass("lobby"); @@ -2816,7 +2820,7 @@ $(function () { else info.removeClass("banned"); } }); - $("#room").on("click", function (evt) { + $("#room").on("click", function(evt) { evt.stopPropagation(); // clicks on a new room @@ -2836,7 +2840,7 @@ $(function () { openModal("#new-room", "input[name=name]"); } // all other clicks - var doc_click = function (evt) { + var doc_click = function(evt) { if ($(evt.target).is("#room .more")) return; $(document).off("mousedown", doc_click); $("#room .more").fadeOut(250); @@ -2847,16 +2851,16 @@ $(function () { $("#room .more").show(); gClient.sendArray([{ m: "+ls" }]); }); - $("#new-room-btn").on("click", function (evt) { + $("#new-room-btn").on("click", function(evt) { evt.stopPropagation(); openModal("#new-room", "input[name=name]"); }); - $("#play-alone-btn").on("click", function (evt) { + $("#play-alone-btn").on("click", function(evt) { evt.stopPropagation(); var room_name = "Room" + Math.floor(Math.random() * 1000000000000); changeRoom(room_name, "right", { visible: false }); - setTimeout(function () { + setTimeout(function() { new Notification({ id: "share", title: window.i18nextify.i18next.t("Playing alone"), @@ -2875,7 +2879,7 @@ $(function () { }); //Account button - $("#account-btn").on("click", function (evt) { + $("#account-btn").on("click", function(evt) { evt.stopPropagation(); openModal("#account"); if (gClient.accountInfo) { @@ -2884,8 +2888,8 @@ $(function () { $("#account #avatar-image").prop("src", gClient.accountInfo.avatar); $("#account #logged-in-user-text").text( gClient.accountInfo.username + - "#" + - gClient.accountInfo.discriminator, + "#" + + gClient.accountInfo.discriminator, ); } } else { @@ -2910,7 +2914,7 @@ $(function () { $("#modal #modals > *").hide(); $("#modal").fadeIn(250); $(selector).show(); - setTimeout(function () { + setTimeout(function() { $(selector).find(focus).focus(); }, 100); gModal = selector; @@ -2925,12 +2929,12 @@ $(function () { } var modal_bg = $("#modal .bg")[0]; - $(modal_bg).on("click", function (evt) { + $(modal_bg).on("click", function(evt) { if (evt.target != modal_bg) return; closeModal(); }); - (function () { + (function() { function submit() { var name = $("#new-room .text[name=name]").val(); var settings = { @@ -2940,7 +2944,7 @@ $(function () { $("#new-room .text[name=name]").val(""); closeModal(); changeRoom(name, "right", settings); - setTimeout(function () { + setTimeout(function() { new Notification({ id: "share", title: window.i18nextify.i18next.t("Created a Room"), @@ -2957,10 +2961,10 @@ $(function () { }); }, 1000); } - $("#new-room .submit").click(function (evt) { + $("#new-room .submit").click(function(evt) { submit(); }); - $("#new-room .text[name=name]").keypress(function (evt) { + $("#new-room .text[name=name]").keypress(function(evt) { if (evt.keyCode == 13) { submit(); } else if (evt.keyCode == 27) { @@ -3004,7 +3008,7 @@ $(function () { .addClass("ease-out") .addClass("slide-" + opposite); setTimeout( - function () { + function() { $("#piano") .removeClass("ease-out") .removeClass("slide-" + opposite) @@ -3013,7 +3017,7 @@ $(function () { (t += d), ); setTimeout( - function () { + function() { $("#piano") .addClass("ease-in") .removeClass("slide-" + direction); @@ -3021,7 +3025,7 @@ $(function () { (t += d), ); setTimeout( - function () { + function() { $("#piano").removeClass("ease-in"); }, (t += d), @@ -3029,7 +3033,7 @@ $(function () { } var gHistoryDepth = 0; - $(window).on("popstate", function (evt) { + $(window).on("popstate", function(evt) { var depth = evt.state ? evt.state.depth : 0; //if (depth == gHistoryDepth) return; // <-- forgot why I did that though... //yeah brandon idk why you did that either, but it's stopping the back button from changing rooms after 1 click so I commented it out @@ -3045,7 +3049,7 @@ $(function () { //////////////////////////////////////////////////////////////// - (function () { + (function() { function submit() { var set = { name: $("#rename input[name=name]").val(), @@ -3055,10 +3059,10 @@ $(function () { closeModal(); gClient.sendArray([{ m: "userset", set: set }]); } - $("#rename .submit").click(function (evt) { + $("#rename .submit").click(function(evt) { submit(); }); - $("#rename .text[name=name]").keypress(function (evt) { + $("#rename .text[name=name]").keypress(function(evt) { if (evt.keyCode == 13) { submit(); } else if (evt.keyCode == 27) { @@ -3073,7 +3077,7 @@ $(function () { })(); //site-wide bans - (function () { + (function() { function submit() { var msg = { m: "siteban" }; @@ -3151,10 +3155,10 @@ $(function () { closeModal(); gClient.sendArray([msg]); } - $("#siteban .submit").click(function (evt) { + $("#siteban .submit").click(function(evt) { submit(); }); - $("#siteban select[name=reasonSelect]").change(function (evt) { + $("#siteban select[name=reasonSelect]").change(function(evt) { if (this.value === "custom") { $("#siteban .text[name=reasonText]").attr("disabled", false); $("#siteban .text[name=reasonText]").val(""); @@ -3163,7 +3167,7 @@ $(function () { $("#siteban .text[name=reasonText]").val(this.value); } }); - $("#siteban select[name=durationUnit]").change(function (evt) { + $("#siteban select[name=durationUnit]").change(function(evt) { if (this.value === "permanent") { $("#siteban .text[name=durationNumber]").attr("disabled", true); } else { @@ -3189,7 +3193,7 @@ $(function () { //Accounts - (function () { + (function() { function logout() { delete localStorage.token; delete gClient.accountInfo; @@ -3197,10 +3201,10 @@ $(function () { gClient.start(); closeModal(); } - $("#account .logout-btn").click(function (evt) { + $("#account .logout-btn").click(function(evt) { logout(); }); - $("#account .login-discord").click(function (evt) { + $("#account .login-discord").click(function(evt) { location.replace( encodeURI( `https://discord.com/api/oauth2/authorize?client_id=926633278100877393&redirect_uri=${location.origin}/?callback=discord&response_type=code&scope=identify email`, @@ -3213,16 +3217,16 @@ $(function () { //////////////////////////////////////////////////////////////// - var chat = (function () { - gClient.on("ch", function (msg) { + var chat = (function() { + gClient.on("ch", function(msg) { if (msg.ch.settings.chat) { chat.show(); } else { chat.hide(); } }); - gClient.on("disconnect", function (msg) {}); - gClient.on("c", function (msg) { + gClient.on("disconnect", function(msg) { }); + gClient.on("c", function(msg) { chat.clear(); if (msg.c) { for (var i = 0; i < msg.c.length; i++) { @@ -3230,14 +3234,14 @@ $(function () { } } }); - gClient.on("a", function (msg) { + gClient.on("a", function(msg) { chat.receive(msg); }); - gClient.on("dm", function (msg) { + gClient.on("dm", function(msg) { chat.receive(msg); }); - $("#chat input").on("focus", function (evt) { + $("#chat input").on("focus", function(evt) { releaseKeyboard(); $("#chat").addClass("chatting"); chat.scrollToBottom(); @@ -3247,12 +3251,12 @@ $(function () { $("#chat").removeClass("chatting"); chat.scrollToBottom(); });*/ - $(document).mousedown(function (evt) { + $(document).mousedown(function(evt) { if (!$("#chat").has(evt.target).length > 0) { chat.blur(); } }); - document.addEventListener("touchstart", function (event) { + document.addEventListener("touchstart", function(event) { for (var i in event.changedTouches) { var touch = event.changedTouches[i]; if (!$("#chat").has(touch.target).length > 0) { @@ -3260,7 +3264,7 @@ $(function () { } } }); - $(document).on("keydown", function (evt) { + $(document).on("keydown", function(evt) { if ($("#chat").hasClass("chatting")) { if (evt.keyCode == 27) { chat.blur(); @@ -3273,7 +3277,7 @@ $(function () { $("#chat input").focus(); } }); - $("#chat input").on("keydown", function (evt) { + $("#chat input").on("keydown", function(evt) { if (evt.keyCode == 13) { if (MPP.client.isConnected()) { var message = $(this).val(); @@ -3284,13 +3288,13 @@ $(function () { if (gIsReplying) { chat.cancelReply(); } - setTimeout(function () { + setTimeout(function() { chat.blur(); }, 100); } else { chat.send(message); $(this).val(""); - setTimeout(function () { + setTimeout(function() { chat.blur(); }, 100); } @@ -3331,20 +3335,20 @@ $(function () { var messageCache = []; return { - startDM: function (part) { + startDM: function(part) { gIsDming = true; gDmParticipant = part; $("#chat-input")[0].placeholder = "Direct messaging " + part.name + "."; }, - endDM: function () { + endDM: function() { gIsDming = false; $("#chat-input")[0].placeholder = window.i18nextify.i18next.t( "You can chat with this thing.", ); }, - startReply: function (part, id) { + startReply: function(part, id) { $(`#msg-${gMessageId}`).css({ "background-color": "unset", border: "1px solid #00000000", @@ -3355,7 +3359,7 @@ $(function () { $("#chat-input")[0].placeholder = `Replying to ${part.name}`; }, - startDmReply: function (part, id) { + startDmReply: function(part, id) { $(`#msg-${gMessageId}`).css({ "background-color": "unset", border: "1px solid #00000000", @@ -3368,7 +3372,7 @@ $(function () { $("#chat-input")[0].placeholder = `Replying to ${part.name} in a DM.`; }, - cancelReply: function () { + cancelReply: function() { if (gIsDming) gIsDming = false; gIsReplying = false; $(`#msg-${gMessageId}`).css({ @@ -3380,24 +3384,24 @@ $(function () { ); }, - show: function () { + show: function() { $("#chat").fadeIn(); }, - hide: function () { + hide: function() { $("#chat").fadeOut(); }, - clear: function () { + clear: function() { $("#chat li").remove(); }, - scrollToBottom: function () { + scrollToBottom: function() { var ele = $("#chat ul").get(0); ele.scrollTop = ele.scrollHeight - ele.clientHeight; }, - blur: function () { + blur: function() { if ($("#chat").hasClass("chatting")) { $("#chat input").get(0).blur(); $("#chat").removeClass("chatting"); @@ -3406,7 +3410,7 @@ $(function () { } }, - send: function (message) { + send: function(message) { if (gIsReplying) { if (gIsDming) { gClient.sendArray([ @@ -3442,7 +3446,7 @@ $(function () { } }, - receive: function (msg) { + receive: function(msg) { if (msg.m === "dm") { if (gChatMutes.indexOf(msg.sender._id) != -1) return; } else { @@ -3507,18 +3511,16 @@ $(function () { } if (repliedMsg) { li.find(".replyLink").text( - `➥ ${ - repliedMsg.m === "dm" - ? repliedMsg.sender.name - : repliedMsg.p.name + `➥ ${repliedMsg.m === "dm" + ? repliedMsg.sender.name + : repliedMsg.p.name }`, ); li.find(".replyLink").css({ - background: `${ - (repliedMsg?.m === "dm" - ? repliedMsg?.sender?.color - : repliedMsg?.p?.color) ?? "gray" - }`, + background: `${(repliedMsg?.m === "dm" + ? repliedMsg?.sender?.color + : repliedMsg?.p?.color) ?? "gray" + }`, }); li.find(".replyLink").on("click", (evt) => { $("#chat-input").focus(); @@ -3526,16 +3528,14 @@ $(function () { .getElementById(`msg-${repliedMsg?.id}`) .scrollIntoView({ behavior: "smooth" }); $(`#msg-${repliedMsg?.id}`).css({ - border: `1px solid ${ - repliedMsg?.m === "dm" - ? repliedMsg.sender?.color - : repliedMsg.p?.color - }80`, - "background-color": `${ - repliedMsg?.m === "dm" - ? repliedMsg.sender?.color - : repliedMsg.p?.color - }20`, + border: `1px solid ${repliedMsg?.m === "dm" + ? repliedMsg.sender?.color + : repliedMsg.p?.color + }80`, + "background-color": `${repliedMsg?.m === "dm" + ? repliedMsg.sender?.color + : repliedMsg.p?.color + }20`, }); setTimeout(() => { $(`#msg-${repliedMsg?.id}`).css({ @@ -3690,12 +3690,10 @@ $(function () { MPP.chat.startReply(msg.p, msg.id, msg.a); setTimeout(() => { $(`#msg-${msg.id}`).css({ - border: `1px solid ${ - msg?.m === "dm" ? msg.sender?.color : msg.p?.color - }80`, - "background-color": `${ - msg?.m === "dm" ? msg.sender?.color : msg.p?.color - }20`, + border: `1px solid ${msg?.m === "dm" ? msg.sender?.color : msg.p?.color + }80`, + "background-color": `${msg?.m === "dm" ? msg.sender?.color : msg.p?.color + }20`, }); }, 100); setTimeout(() => { @@ -3711,12 +3709,10 @@ $(function () { MPP.chat.startDmReply(replyingTo, msg.id); setTimeout(() => { $(`#msg-${msg.id}`).css({ - border: `1px solid ${ - msg?.m === "dm" ? msg.sender?.color : msg.p?.color - }80`, - "background-color": `${ - msg?.m === "dm" ? msg.sender?.color : msg.p?.color - }20`, + border: `1px solid ${msg?.m === "dm" ? msg.sender?.color : msg.p?.color + }80`, + "background-color": `${msg?.m === "dm" ? msg.sender?.color : msg.p?.color + }20`, }); }, 100); setTimeout(() => { @@ -3801,10 +3797,10 @@ $(function () { 15: 0, }; - (function () { + (function() { if (navigator.requestMIDIAccess) { navigator.requestMIDIAccess().then( - function (midi) { + function(midi) { //console.log(midi); function midimessagehandler(evt) { if (!evt.target.enabled) return; @@ -3821,11 +3817,11 @@ $(function () { // NOTE_OFF release( MIDI_KEY_NAMES[ - note_number - - 9 + - MIDI_TRANSPOSE + - transpose + - pitchBends[channel] + note_number - + 9 + + MIDI_TRANSPOSE + + transpose + + pitchBends[channel] ], ); } else if (cmd == 9) { @@ -3833,11 +3829,11 @@ $(function () { if (evt.target.volume !== undefined) vel *= evt.target.volume; press( MIDI_KEY_NAMES[ - note_number - - 9 + - MIDI_TRANSPOSE + - transpose + - pitchBends[channel] + note_number - + 9 + + MIDI_TRANSPOSE + + transpose + + pitchBends[channel] ], vel / 127, ); @@ -3939,7 +3935,7 @@ $(function () { } //console.log("output", output); } - gMidiOutTest = function ( + gMidiOutTest = function( note_name, vel, delay_ms, @@ -3972,7 +3968,7 @@ $(function () { updateDevices(); } - midi.addEventListener("statechange", function (evt) { + midi.addEventListener("statechange", function(evt) { if (evt instanceof MIDIConnectionEvent) { plug(); } @@ -3999,7 +3995,7 @@ $(function () { li.classList.add("connection"); if (input.enabled) li.classList.add("enabled"); li.textContent = input.name; - li.addEventListener("click", function (evt) { + li.addEventListener("click", function(evt) { var inputs = midi.inputs.values(); for ( var input_it = inputs.next(); @@ -4028,7 +4024,7 @@ $(function () { knob.canvas.style.width = "16px"; knob.canvas.style.height = "16px"; knob.canvas.style.float = "right"; - knob.on("change", function (k) { + knob.on("change", function(k) { input.volume = k.value; }); knob.emit("change", knob); @@ -4052,7 +4048,7 @@ $(function () { li.classList.add("connection"); if (output.enabled) li.classList.add("enabled"); li.textContent = output.name; - li.addEventListener("click", function (evt) { + li.addEventListener("click", function(evt) { var outputs = midi.outputs.values(); for ( var output_it = outputs.next(); @@ -4081,7 +4077,7 @@ $(function () { knob.canvas.style.width = "16px"; knob.canvas.style.height = "16px"; knob.canvas.style.float = "right"; - knob.on("change", function (k) { + knob.on("change", function(k) { output.volume = k.value; }); knob.emit("change", knob); @@ -4115,7 +4111,7 @@ $(function () { document .getElementById("midi-btn") - .addEventListener("click", function (evt) { + .addEventListener("click", function(evt) { if (!document.getElementById("Notification-MIDI-Connections")) showConnections(true); else { @@ -4123,7 +4119,7 @@ $(function () { } }); }, - function (err) { + function(err) { //console.log(err); }, ); @@ -4134,7 +4130,7 @@ $(function () { //////////////////////////////////////////////////////////////// - window.onerror = function (message, url, line) { + window.onerror = function(message, url, line) { /*var url = url || "(no url)"; var line = line || "(no line)"; // errors in socket.io @@ -4258,17 +4254,17 @@ $(function () { ); } - synthVoice.prototype.stop = function (time) { + synthVoice.prototype.stop = function(time) { //this.gain.gain.setValueAtTime(osc1_sustain, time); this.gain.gain.linearRampToValueAtTime(0, time + osc1_release); this.osc.stop(time + osc1_release); }; - (function () { + (function() { var button = document.getElementById("synth-btn"); var notification; - button.addEventListener("click", function () { + button.addEventListener("click", function() { if (notification) { notification.close(); } else { @@ -4280,14 +4276,14 @@ $(function () { var html = document.createElement("div"); // on/off button - (function () { + (function() { var button = document.createElement("input"); mixin(button, { type: "button", value: window.i18nextify.i18next.t("ON/OFF"), className: enableSynth ? "switched-on" : "switched-off", }); - button.addEventListener("click", function (evt) { + button.addEventListener("click", function(evt) { enableSynth = !enableSynth; button.className = enableSynth ? "switched-on" : "switched-off"; if (!enableSynth) { @@ -4316,7 +4312,7 @@ $(function () { knob = new Knob(knob, 0, 100, 0.1, 50, "mix", "%"); knob.canvas.style.width = "32px"; knob.canvas.style.height = "32px"; - knob.on("change", function (k) { + knob.on("change", function(k) { var mix = k.value / 100; audio.pianoGain.gain.value = 1 - mix; audio.synthGain.gain.value = mix; @@ -4324,14 +4320,14 @@ $(function () { knob.emit("change", knob); // osc1 type - (function () { + (function() { osc1_type = osc_types[osc_type_index]; var button = document.createElement("input"); mixin(button, { type: "button", value: window.i18nextify.i18next.t(osc_types[osc_type_index]), }); - button.addEventListener("click", function (evt) { + button.addEventListener("click", function(evt) { if (++osc_type_index >= osc_types.length) osc_type_index = 0; osc1_type = osc_types[osc_type_index]; button.value = window.i18nextify.i18next.t(osc1_type); @@ -4350,7 +4346,7 @@ $(function () { knob = new Knob(knob, 0, 1, 0.001, osc1_attack, "osc1 attack", "s"); knob.canvas.style.width = "32px"; knob.canvas.style.height = "32px"; - knob.on("change", function (k) { + knob.on("change", function(k) { osc1_attack = k.value; }); knob.emit("change", knob); @@ -4366,7 +4362,7 @@ $(function () { knob = new Knob(knob, 0, 2, 0.001, osc1_decay, "osc1 decay", "s"); knob.canvas.style.width = "32px"; knob.canvas.style.height = "32px"; - knob.on("change", function (k) { + knob.on("change", function(k) { osc1_decay = k.value; }); knob.emit("change", knob); @@ -4381,7 +4377,7 @@ $(function () { knob = new Knob(knob, 0, 1, 0.001, osc1_sustain, "osc1 sustain", "x"); knob.canvas.style.width = "32px"; knob.canvas.style.height = "32px"; - knob.on("change", function (k) { + knob.on("change", function(k) { osc1_sustain = k.value; }); knob.emit("change", knob); @@ -4397,7 +4393,7 @@ $(function () { knob = new Knob(knob, 0, 2, 0.001, osc1_release, "osc1 release", "s"); knob.canvas.style.width = "32px"; knob.canvas.style.height = "32px"; - knob.on("change", function (k) { + knob.on("change", function(k) { osc1_release = k.value; }); knob.emit("change", knob); @@ -4414,7 +4410,7 @@ $(function () { duration: -1, target: "#synth-btn", }); - notification.on("close", function () { + notification.on("close", function() { var tip = document.getElementById("tooltip"); if (tip) tip.parentNode.removeChild(tip); notification = null; @@ -4422,12 +4418,12 @@ $(function () { } })(); - (function () { + (function() { if (window.location.hostname === "multiplayerpiano.com") { var button = document.getElementById("client-settings-btn"); var notification; - button.addEventListener("click", function () { + button.addEventListener("click", function() { if (notification) { notification.close(); } else { @@ -4439,14 +4435,14 @@ $(function () { var html = document.createElement("div"); // show ids in chat - (function () { + (function() { var setting = document.createElement("div"); setting.classList = "setting"; setting.innerText = "Show user IDs in chat"; if (gShowIdsInChat) { setting.classList.toggle("enabled"); } - setting.onclick = function () { + setting.onclick = function() { setting.classList.toggle("enabled"); localStorage.showIdsInChat = setting.classList.contains("enabled"); gShowIdsInChat = setting.classList.contains("enabled"); @@ -4455,14 +4451,14 @@ $(function () { })(); // show timestamps in chat - (function () { + (function() { var setting = document.createElement("div"); setting.classList = "setting"; setting.innerText = "Timestamps in chat"; if (gShowTimestampsInChat) { setting.classList.toggle("enabled"); } - setting.onclick = function () { + setting.onclick = function() { setting.classList.toggle("enabled"); localStorage.showTimestampsInChat = setting.classList.contains("enabled"); @@ -4472,14 +4468,14 @@ $(function () { })(); // no chat colors - (function () { + (function() { var setting = document.createElement("div"); setting.classList = "setting"; setting.innerText = "No chat colors"; if (gNoChatColors) { setting.classList.toggle("enabled"); } - setting.onclick = function () { + setting.onclick = function() { setting.classList.toggle("enabled"); localStorage.noChatColors = setting.classList.contains("enabled"); gNoChatColors = setting.classList.contains("enabled"); @@ -4488,14 +4484,14 @@ $(function () { })(); // no background color - (function () { + (function() { var setting = document.createElement("div"); setting.classList = "setting"; setting.innerText = "Force dark background"; if (gNoBackgroundColor) { setting.classList.toggle("enabled"); } - setting.onclick = function () { + setting.onclick = function() { setting.classList.toggle("enabled"); localStorage.noBackgroundColor = setting.classList.contains("enabled"); @@ -4513,14 +4509,14 @@ $(function () { })(); // output own notes - (function () { + (function() { var setting = document.createElement("div"); setting.classList = "setting"; setting.innerText = "Output own notes to MIDI"; if (gOutputOwnNotes) { setting.classList.toggle("enabled"); } - setting.onclick = function () { + setting.onclick = function() { setting.classList.toggle("enabled"); localStorage.outputOwnNotes = setting.classList.contains("enabled"); gOutputOwnNotes = setting.classList.contains("enabled"); @@ -4529,14 +4525,14 @@ $(function () { })(); // virtual piano layout - (function () { + (function() { var setting = document.createElement("div"); setting.classList = "setting"; setting.innerText = "Virtual Piano layout"; if (gVirtualPianoLayout) { setting.classList.toggle("enabled"); } - setting.onclick = function () { + setting.onclick = function() { setting.classList.toggle("enabled"); localStorage.virtualPianoLayout = setting.classList.contains("enabled"); @@ -4548,14 +4544,14 @@ $(function () { // gShowChatTooltips // Show chat tooltips for _ids. - (function () { + (function() { var setting = document.createElement("div"); setting.classList = "setting"; setting.innerText = "Show _id tooltips"; if (gShowChatTooltips) { setting.classList.toggle("enabled"); } - setting.onclick = function () { + setting.onclick = function() { setting.classList.toggle("enabled"); localStorage.showChatTooltips = setting.classList.contains("enabled"); @@ -4564,14 +4560,14 @@ $(function () { html.appendChild(setting); })(); - (function () { + (function() { var setting = document.createElement("div"); setting.classList = "setting"; setting.innerText = "Show Piano Notes"; if (gShowPianoNotes) { setting.classList.toggle("enabled"); } - setting.onclick = function () { + setting.onclick = function() { setting.classList.toggle("enabled"); localStorage.showPianoNotes = setting.classList.contains("enabled"); gShowPianoNotes = setting.classList.contains("enabled"); @@ -4580,14 +4576,14 @@ $(function () { })(); // Enable smooth cursors. - (function () { + (function() { var setting = document.createElement("div"); setting.classList = "setting"; setting.innerText = "Enable smooth cursors"; if (gSmoothCursor) { setting.classList.toggle("enabled"); } - setting.onclick = function () { + setting.onclick = function() { setting.classList.toggle("enabled"); localStorage.smoothCursor = setting.classList.contains("enabled"); gSmoothCursor = setting.classList.contains("enabled"); @@ -4597,7 +4593,7 @@ $(function () { $("#cursors").removeAttr("smooth-cursors"); } if (gSmoothCursor) { - Object.values(gClient.ppl).forEach(function (participant) { + Object.values(gClient.ppl).forEach(function(participant) { if (participant.cursorDiv) { participant.cursorDiv.style.left = ""; participant.cursorDiv.style.top = ""; @@ -4610,7 +4606,7 @@ $(function () { } }); } else { - Object.values(gClient.ppl).forEach(function (participant) { + Object.values(gClient.ppl).forEach(function(participant) { if (participant.cursorDiv) { participant.cursorDiv.style.left = participant.x + "%"; participant.cursorDiv.style.top = participant.y + "%"; @@ -4622,7 +4618,7 @@ $(function () { html.appendChild(setting); })(); - (function () { + (function() { var setting = document.createElement("select"); setting.classList = "setting"; setting.style = "color: inherit; width: calc(100% - 2px);"; @@ -4646,21 +4642,21 @@ $(function () { setting.value = gHighlightScaleNotes; } - setting.onchange = function () { + setting.onchange = function() { localStorage.highlightScaleNotes = setting.value; gHighlightScaleNotes = setting.value; }; html.appendChild(setting); })(); - (function () { + (function() { var setting = document.createElement("div"); setting.classList = "setting"; setting.innerText = "Hide all cursors"; if (gHideAllCursors) { setting.classList.toggle("enabled"); } - setting.onclick = function () { + setting.onclick = function() { setting.classList.toggle("enabled"); localStorage.hideAllCursors = setting.classList.contains("enabled"); gHideAllCursors = setting.classList.contains("enabled"); @@ -4701,7 +4697,7 @@ $(function () { duration: -1, target: "#client-settings-btn", }); - notification.on("close", function () { + notification.on("close", function() { var tip = document.getElementById("tooltip"); if (tip) tip.parentNode.removeChild(tip); notification = null; @@ -4992,7 +4988,7 @@ $(function () { localStorage.smoothCursor = gSmoothCursor; if (gSmoothCursor) { $("#cursors").attr("smooth-cursors", ""); - Object.values(gClient.ppl).forEach(function (participant) { + Object.values(gClient.ppl).forEach(function(participant) { if (participant.cursorDiv) { participant.cursorDiv.style.left = ""; participant.cursorDiv.style.top = ""; @@ -5006,7 +5002,7 @@ $(function () { }); } else { $("#cursors").removeAttr("smooth-cursors"); - Object.values(gClient.ppl).forEach(function (participant) { + Object.values(gClient.ppl).forEach(function(participant) { if (participant.cursorDiv) { participant.cursorDiv.style.left = participant.x + "%"; participant.cursorDiv.style.top = participant.y + "%"; @@ -5087,7 +5083,7 @@ $(function () { var toggleConfetti; //call to start or stop the confetti animation depending on whether it's already running var removeConfetti; //call to stop the confetti animation and remove all confetti immediately - (function () { + (function() { startConfetti = startConfettiInner; stopConfetti = stopConfettiInner; toggleConfetti = toggleConfettiInner; @@ -5125,14 +5121,14 @@ $(function () { function startConfettiInner() { var width = window.innerWidth; var height = window.innerHeight; - window.requestAnimFrame = (function () { + window.requestAnimFrame = (function() { return ( window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || - function (callback) { + function(callback) { return window.setTimeout(callback, 16.6666667); } ); @@ -5150,7 +5146,7 @@ $(function () { canvas.height = height; window.addEventListener( "resize", - function () { + function() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; }, @@ -5246,7 +5242,7 @@ $(function () { (async () => { // prettier-ignore - const translationIdsWithNames = [{"code":"bg","name":"Bulgarian","native":"Български"},{"code":"cs","name":"Czech","native":"Česky"},{"code":"de","name":"German","native":"Deutsch"},{"code":"en","name":"English","native":"English"},{"code":"es","name":"Spanish","native":"Español"},{"code":"fr","name":"French","native":"Français"},{"code":"hu","name":"Hungarian","native":"Magyar"},{"code":"is","name":"Icelandic","native":"Íslenska"},{"code":"ja","name":"Japanese","native":"日本語"},{"code":"ko","name":"Korean","native":"한국어"},{"code":"lv","name":"Latvian","native":"Latviešu"},{"code":"nb","name":"Norwegian Bokmål","native":"Norsk bokmål"},{"code":"nl","name":"Dutch","native":"Nederlands"},{"code":"pl","name":"Polish","native":"Polski"},{"code":"pt","name":"Portuguese","native":"Português"},{"code":"ru","name":"Russian","native":"Русский"},{"code":"sk","name":"Slovak","native":"Slovenčina"},{"code":"sv","name":"Swedish","native":"Svenska"},{"code":"tr","name":"Turkish","native":"Türkçe"},{"code":"zh","name":"Chinese","native":"中文"}] + const translationIdsWithNames = [{ "code": "bg", "name": "Bulgarian", "native": "Български" }, { "code": "cs", "name": "Czech", "native": "Česky" }, { "code": "de", "name": "German", "native": "Deutsch" }, { "code": "en", "name": "English", "native": "English" }, { "code": "es", "name": "Spanish", "native": "Español" }, { "code": "fr", "name": "French", "native": "Français" }, { "code": "hu", "name": "Hungarian", "native": "Magyar" }, { "code": "is", "name": "Icelandic", "native": "Íslenska" }, { "code": "ja", "name": "Japanese", "native": "日本語" }, { "code": "ko", "name": "Korean", "native": "한국어" }, { "code": "lv", "name": "Latvian", "native": "Latviešu" }, { "code": "nb", "name": "Norwegian Bokmål", "native": "Norsk bokmål" }, { "code": "nl", "name": "Dutch", "native": "Nederlands" }, { "code": "pl", "name": "Polish", "native": "Polski" }, { "code": "pt", "name": "Portuguese", "native": "Português" }, { "code": "ru", "name": "Russian", "native": "Русский" }, { "code": "sk", "name": "Slovak", "native": "Slovenčina" }, { "code": "sv", "name": "Swedish", "native": "Svenska" }, { "code": "tr", "name": "Turkish", "native": "Türkçe" }, { "code": "zh", "name": "Chinese", "native": "中文" }] const languages = document.getElementById("languages"); From 8366b3c27038b475d710ec5a3eb6d9d07c95cee3 Mon Sep 17 00:00:00 2001 From: Hri7566 Date: Wed, 19 Feb 2025 23:11:47 -0500 Subject: [PATCH 02/25] Enable allowBots checkbox by default --- client/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/index.html b/client/index.html index 5ba2602..60136bd 100644 --- a/client/index.html +++ b/client/index.html @@ -178,7 +178,7 @@

-

+

- - - diff --git a/client/screen.css b/client/screen.css index 937ecb3..6692fbd 100644 --- a/client/screen.css +++ b/client/screen.css @@ -1434,27 +1434,16 @@ input[type="range"]:hover { padding: 0; } -.mppcommunity-button { - right: 6px; -} - .discord-button { - right: 36px; + right: 6px; } .github-button { - right: 66px; - background-color: white; - filter: invert(100%); - border-color: #c6c6c6; -} - -.github-button:hover { - background-color: #ddd; + right: 36px; } .reddit-button { - right: 96px; + right: 66px; z-index: 500; } From b11307170d08fa97a8ae58a7046e4a8d6a650269 Mon Sep 17 00:00:00 2001 From: ccjt Date: Fri, 9 May 2025 19:23:16 -0300 Subject: [PATCH 04/25] Fix noPreventDefault bug (#54) * Fix noPreventDefault bug --------- Co-authored-by: James --- client/script.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/script.js b/client/script.js index 4b19ed1..bc5dc3f 100644 --- a/client/script.js +++ b/client/script.js @@ -4955,7 +4955,7 @@ $(function() { html, () => { gNoPreventDefault = !gNoPreventDefault; - localStorage.noPreventDefault = noPreventDefault; + localStorage.noPreventDefault = gNoPreventDefault; }, ); From ed4e2dec3fa3ce60ef94de653b6ccf28ec314f56 Mon Sep 17 00:00:00 2001 From: Hri7566 Date: Fri, 9 May 2025 20:33:43 -0400 Subject: [PATCH 05/25] Add mppman --- client/mppman-xmas.png | Bin 0 -> 15161 bytes client/mppman.png | Bin 0 -> 11468 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 client/mppman-xmas.png create mode 100644 client/mppman.png diff --git a/client/mppman-xmas.png b/client/mppman-xmas.png new file mode 100644 index 0000000000000000000000000000000000000000..0353f417c8fa6e8c09accecf8eaa1f5257771443 GIT binary patch literal 15161 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

Q0#3UnpF|}pM6*KvhN}8K4S0nD!?ve< zv10=r0YAztFG3_DF~a!oGd90DP%k`rm&6}?Ttrr5mmW6JD-yVQ=GqgYITnoL`8#n# zmBvE+3Nr#dV;A5U0Yx`^@{d|TejxRS#Qo2+L2S9JJ|(7d-U9R@L%c`@G+o|V{H(q8 z2sCi{2T4Z24sGAeMcrP1fQRu!I29v-p9JKd=|F3xk^3*Urbr)F=b?LmOSnSes4WzeUCU!>4m27Knj+g xLBneF+qHLK8gX}Nvv{)d|LH2+3YH@rSg8*cInm1hZ{0CSTf;!TR@E`?e*nrl!;%01 literal 0 HcmV?d00001 From 3987f38e0e46e8cee79d4a8dd789c899cfb26fe5 Mon Sep 17 00:00:00 2001 From: "Weblate (bot)" Date: Sat, 17 May 2025 07:16:05 +0200 Subject: [PATCH 06/25] Translations update from Hosted Weblate (#47) * Added translation using Weblate (Georgian) * Translated using Weblate (Georgian) Currently translated at 20.7% (21 of 101 strings) Translation: multiplayerpiano/frontend Translate-URL: https://hosted.weblate.org/projects/multiplayerpiano/frontend/ka/ * Translated using Weblate (English) Currently translated at 100.0% (101 of 101 strings) Translation: multiplayerpiano/frontend Translate-URL: https://hosted.weblate.org/projects/multiplayerpiano/frontend/en/ * Translated using Weblate (Swedish) Currently translated at 100.0% (101 of 101 strings) Translation: multiplayerpiano/frontend Translate-URL: https://hosted.weblate.org/projects/multiplayerpiano/frontend/sv/ * Translated using Weblate (Georgian) Currently translated at 20.7% (21 of 101 strings) Translation: multiplayerpiano/frontend Translate-URL: https://hosted.weblate.org/projects/multiplayerpiano/frontend/ka/ * Translated using Weblate (Japanese) Currently translated at 79.2% (80 of 101 strings) Translation: multiplayerpiano/frontend Translate-URL: https://hosted.weblate.org/projects/multiplayerpiano/frontend/ja/ * Translated using Weblate (German) Currently translated at 100.0% (101 of 101 strings) Translation: multiplayerpiano/frontend Translate-URL: https://hosted.weblate.org/projects/multiplayerpiano/frontend/de/ * Translated using Weblate (Dutch) Currently translated at 100.0% (101 of 101 strings) Translation: multiplayerpiano/frontend Translate-URL: https://hosted.weblate.org/projects/multiplayerpiano/frontend/nl/ * Translated using Weblate (Portuguese) Currently translated at 100.0% (101 of 101 strings) Translation: multiplayerpiano/frontend Translate-URL: https://hosted.weblate.org/projects/multiplayerpiano/frontend/pt/ * Translated using Weblate (English) Currently translated at 100.0% (101 of 101 strings) Translation: multiplayerpiano/frontend Translate-URL: https://hosted.weblate.org/projects/multiplayerpiano/frontend/en/ --------- Co-authored-by: sophie Co-authored-by: King Shepherd Co-authored-by: dima Co-authored-by: bittin1ddc447d824349b2 Co-authored-by: Temuri Doghonadze Co-authored-by: Daniel Co-authored-by: XeniaGames Co-authored-by: Bruno Fragoso --- client/locales/de/translation.json | 4 +- client/locales/ja/translation.json | 60 ++++++++++++++++++++++++++++-- client/locales/ka/translation.json | 24 ++++++++++++ client/locales/nl/translation.json | 2 +- client/locales/pt/translation.json | 5 ++- client/locales/sv/translation.json | 2 +- 6 files changed, 87 insertions(+), 10 deletions(-) create mode 100644 client/locales/ka/translation.json diff --git a/client/locales/de/translation.json b/client/locales/de/translation.json index f74fdaa..570d212 100644 --- a/client/locales/de/translation.json +++ b/client/locales/de/translation.json @@ -2,7 +2,7 @@ "people are playing_one": "Person spielt", "people are playing_other": "Leute spielen", "room name": "Raumnamen", - "New Room...": "neuer Raum…", + "New Room...": "Neuer Raum…", "Visible (open to everyone)": "Sichtbar (offen für alle)", "Enable Chat": "aktivieren Sie chatten", "Play Alone": "Alleine Spielen", @@ -29,7 +29,7 @@ "No Cussing": "Keine Fluchen", "Inner color:": "Innere farbe:", "Outer color:": "Äußere Farbe:", - "Player limit:": "Spieler Limit:", + "Player limit:": "Spieler Limit lol", "Years": "Jahre", "ON/OFF": "AN/AUS", "APPLY": "ANWENDEN", diff --git a/client/locales/ja/translation.json b/client/locales/ja/translation.json index 8e4963a..351a7c8 100644 --- a/client/locales/ja/translation.json +++ b/client/locales/ja/translation.json @@ -12,20 +12,72 @@ "Clear Chat": "チャットをクリア", "Only Owner can Play": "オーナーのみが演奏可能", "No Cussing": "悪口を禁止", - "Synth": "Synth", + "Synth": "シンセサイザー", "Sound Select": "サウンド変更", "Client Settings": "クライアント設定", "Connecting...": "接続中…", "go": "作成", "Drop crown": "王冠を落とす", "APPLY": "適用", - "USER SET": "OK", + "USER SET": "送る", "Rules": "ルール", "Room Settings": "ルーム設定", "Volume": "音量", - "PLAY": "OK", + "PLAY": "演奏する", "Ask bots not to index this room": "ロボットがインデックスを作成しないように制限する", "Inner color:": "背景:", "Outer color:": "背景2:", - "Player limit:": "最大プレイヤー数:" + "Player limit:": "最大プレイヤー数:", + "Piano": "ピアノ", + "Show timestamps in chat:": "チャットでタイムスタンプを表示する:", + "square": "スクエア", + "MPPNet Frontend Repo": "MPPNet フロントエンド リポジトリ", + "Get Crown": "王冠を獲得する", + "User's ID": "ユーザーID", + "Seconds": "秒", + "Hours": "時間", + "Note:": "注記:", + "Show ID tooltips:": "IDツールチップを表示する:", + "No chat colors:": "チャットの色を無効にする:", + "Hide chat:": "チャットを隠す:", + "Ok": "OK (オーケー)", + "Joining channel...": "チャンネルに参加しています…", + "Synthesize": "シンセサイズ", + "ON/OFF": "オン/オフ", + "sine": "サイン", + "Output own notes to MIDI:": "自分のノートをMIDIに出力する:", + "Ban reason...": "禁止理由...", + "Amount of unit...": "単位の量...", + "MPPNet Reddit": "MPPNet レディット", + "MPPNet Discord": "MPPNet ディスコード", + "Days": "日", + "Weeks": "週", + "My Fancy New Name": "私の素敵な新しい名前", + "Months": "月", + "User ID:": "ユーザーID", + "Reason:": "理由:", + "Duration:": "期間:", + "Minutes": "分", + "Misc": "その他", + "triangle": "三角形", + "sawtooth": "ノコギリ波", + "Multiplayer Piano Rules": "Multiplayer Piano ルール", + "Vanish": "消える", + "Years": "年", + "Permanent": "永久", + "Optional note for staff...": "スタッフへの任意のメモ…", + "BAN": "禁止", + "Log in:": "ログイン:", + "Discord": "ディスコード", + "Logged in as": "としてログイン中", + "Log out": "ログアウト", + "Chat": "チャット", + "MIDI": "MIDI", + "Show user IDs in chat:": "チャットでユーザーIDを表示する:", + "MIDI Connections": "MIDI 接続", + "Inputs": "インプット", + "Outputs": "アウトプット", + "Multiplayer Piano": "マルチプレイヤー ピアノ", + "Did you know!?!": "知っていましたか!?", + "You can play the piano with your keyboard, too. Try it!": "キーボードでもピアノを演奏できますよ。試してみてください!" } diff --git a/client/locales/ka/translation.json b/client/locales/ka/translation.json new file mode 100644 index 0000000..6d6a90b --- /dev/null +++ b/client/locales/ka/translation.json @@ -0,0 +1,24 @@ +{ + "people are playing_one": "ადამიანი უკრავს", + "people are playing_other": "ადამიანები უკრავენ", + "New Room...": "ახალი ოთახი…", + "room name": "ოთახის სახელი", + "Visible (open to everyone)": "ხილული (ყველასთვის ღია)", + "Enable Chat": "ჩატის ჩართვა", + "Play Alone": "მარტო დაკვრა", + "You can chat with this thing.": "ამით ლაპარაკი შეგიძლიათ.", + "MPPNet Discord": "MPPNet-ის Discord-ი", + "MPPNet Community Forum": "MPPNet-ის საზოგადოების ფორუმი", + "Rules": "წესები", + "Room Settings": "ოთახის პარამეტრები", + "Synth": "სინთეზატორი", + "MPPNet Frontend Repo": "MPPNet-ის Frontend Repo", + "MPPNet Reddit": "MPPNet-ის Reddit-ი", + "Sound Select": "ხმის არჩევა", + "Account": "ანგარიში", + "Vanish": "გაქრობა", + "Multiplayer Piano Rules": "Multiplayer Piano-ს წესები", + "Client Settings": "კლიენტის პარამეტრები", + "Clear Chat": "ჩატის გაწმენდა", + "Get Crown": "აიღე გვირგვინი" +} diff --git a/client/locales/nl/translation.json b/client/locales/nl/translation.json index 94e7d94..8d19a84 100644 --- a/client/locales/nl/translation.json +++ b/client/locales/nl/translation.json @@ -14,7 +14,7 @@ "Get Crown": "Kroon krijgen", "Volume": "Volume", "Inner color:": "Binnen kleur:", - "Player limit:": "Speler limiet:", + "Player limit:": "Speler limiet lol", "USER SET": "NAAM ZETTEN", "Reason:": "Reden:", "Seconds": "Seconden", diff --git a/client/locales/pt/translation.json b/client/locales/pt/translation.json index 6cdd9e5..b76e9ff 100644 --- a/client/locales/pt/translation.json +++ b/client/locales/pt/translation.json @@ -32,7 +32,7 @@ "Outputs": "Saídas", "Multiplayer Piano": "Multiplayer Piano", "Did you know!?!": "Você sabia!?!", - "Player limit:": "Limite de Pessoas:", + "Player limit:": "Limite de Pessoas", "APPLY": "APLICAR", "My Fancy New Name": "Meu Maravilhoso Novo Nome", "User ID:": "ID do Usuário:", @@ -100,5 +100,6 @@ "Mute Chat": "Mutar Chat", "Direct Message": "Mensagem Direta", "Me": "Você", - "Output own notes to MIDI:": "Enviar suas próprias notas para o MIDI:" + "Output own notes to MIDI:": "Enviar suas próprias notas para o MIDI:", + "Language": "Idioma" } diff --git a/client/locales/sv/translation.json b/client/locales/sv/translation.json index 62001d8..c276c71 100644 --- a/client/locales/sv/translation.json +++ b/client/locales/sv/translation.json @@ -21,7 +21,7 @@ "Ask bots not to index this room": "Ingen index", "Inner color:": "Inre färg:", "Outer color:": "Yttre färg:", - "Player limit:": "Spelargräns:", + "Player limit:": "Spelargräns lol", "APPLY": "TILLÄMPA", "My Fancy New Name": "Mitt Fina Nya Namn", "USER SET": "ANGE", From 20673c3b19b8a8e23e3c497197ee1bef17a6222d Mon Sep 17 00:00:00 2001 From: Hri7566 Date: Thu, 27 Mar 2025 01:08:31 -0400 Subject: [PATCH 07/25] Fix GitHub link --- client/github.svg | 1 + client/index.html | 7 +------ client/screen.css | 17 +++-------------- 3 files changed, 5 insertions(+), 20 deletions(-) create mode 100755 client/github.svg diff --git a/client/github.svg b/client/github.svg new file mode 100755 index 0000000..d5e6491 --- /dev/null +++ b/client/github.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/client/index.html b/client/index.html index 60136bd..3df208f 100644 --- a/client/index.html +++ b/client/index.html @@ -73,14 +73,9 @@

-
- - diff --git a/client/screen.css b/client/screen.css index 937ecb3..6692fbd 100644 --- a/client/screen.css +++ b/client/screen.css @@ -1434,27 +1434,16 @@ input[type="range"]:hover { padding: 0; } -.mppcommunity-button { - right: 6px; -} - .discord-button { - right: 36px; + right: 6px; } .github-button { - right: 66px; - background-color: white; - filter: invert(100%); - border-color: #c6c6c6; -} - -.github-button:hover { - background-color: #ddd; + right: 36px; } .reddit-button { - right: 96px; + right: 66px; z-index: 500; } From efccffc6603717bd4e177b3f725b15d55640da54 Mon Sep 17 00:00:00 2001 From: ccjt Date: Fri, 9 May 2025 19:23:16 -0300 Subject: [PATCH 08/25] Fix noPreventDefault bug (#54) * Fix noPreventDefault bug --------- Co-authored-by: James --- client/script.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/script.js b/client/script.js index 4b19ed1..bc5dc3f 100644 --- a/client/script.js +++ b/client/script.js @@ -4955,7 +4955,7 @@ $(function() { html, () => { gNoPreventDefault = !gNoPreventDefault; - localStorage.noPreventDefault = noPreventDefault; + localStorage.noPreventDefault = gNoPreventDefault; }, ); From d3ad46061fb4173d67ef3e87ba669e1e8f595760 Mon Sep 17 00:00:00 2001 From: Hri7566 Date: Fri, 9 May 2025 20:33:43 -0400 Subject: [PATCH 09/25] Add mppman --- client/mppman-xmas.png | Bin 0 -> 15161 bytes client/mppman.png | Bin 0 -> 11468 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 client/mppman-xmas.png create mode 100644 client/mppman.png diff --git a/client/mppman-xmas.png b/client/mppman-xmas.png new file mode 100644 index 0000000000000000000000000000000000000000..0353f417c8fa6e8c09accecf8eaa1f5257771443 GIT binary patch literal 15161 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

Q0#3UnpF|}pM6*KvhN}8K4S0nD!?ve< zv10=r0YAztFG3_DF~a!oGd90DP%k`rm&6}?Ttrr5mmW6JD-yVQ=GqgYITnoL`8#n# zmBvE+3Nr#dV;A5U0Yx`^@{d|TejxRS#Qo2+L2S9JJ|(7d-U9R@L%c`@G+o|V{H(q8 z2sCi{2T4Z24sGAeMcrP1fQRu!I29v-p9JKd=|F3xk^3*Urbr)F=b?LmOSnSes4WzeUCU!>4m27Knj+g xLBneF+qHLK8gX}Nvv{)d|LH2+3YH@rSg8*cInm1hZ{0CSTf;!TR@E`?e*nrl!;%01 literal 0 HcmV?d00001 From 9d3f87c0d6394989f59fc1652a7b3e98085bbba0 Mon Sep 17 00:00:00 2001 From: "Weblate (bot)" Date: Sat, 17 May 2025 07:16:05 +0200 Subject: [PATCH 10/25] Translations update from Hosted Weblate (#47) * Added translation using Weblate (Georgian) * Translated using Weblate (Georgian) Currently translated at 20.7% (21 of 101 strings) Translation: multiplayerpiano/frontend Translate-URL: https://hosted.weblate.org/projects/multiplayerpiano/frontend/ka/ * Translated using Weblate (English) Currently translated at 100.0% (101 of 101 strings) Translation: multiplayerpiano/frontend Translate-URL: https://hosted.weblate.org/projects/multiplayerpiano/frontend/en/ * Translated using Weblate (Swedish) Currently translated at 100.0% (101 of 101 strings) Translation: multiplayerpiano/frontend Translate-URL: https://hosted.weblate.org/projects/multiplayerpiano/frontend/sv/ * Translated using Weblate (Georgian) Currently translated at 20.7% (21 of 101 strings) Translation: multiplayerpiano/frontend Translate-URL: https://hosted.weblate.org/projects/multiplayerpiano/frontend/ka/ * Translated using Weblate (Japanese) Currently translated at 79.2% (80 of 101 strings) Translation: multiplayerpiano/frontend Translate-URL: https://hosted.weblate.org/projects/multiplayerpiano/frontend/ja/ * Translated using Weblate (German) Currently translated at 100.0% (101 of 101 strings) Translation: multiplayerpiano/frontend Translate-URL: https://hosted.weblate.org/projects/multiplayerpiano/frontend/de/ * Translated using Weblate (Dutch) Currently translated at 100.0% (101 of 101 strings) Translation: multiplayerpiano/frontend Translate-URL: https://hosted.weblate.org/projects/multiplayerpiano/frontend/nl/ * Translated using Weblate (Portuguese) Currently translated at 100.0% (101 of 101 strings) Translation: multiplayerpiano/frontend Translate-URL: https://hosted.weblate.org/projects/multiplayerpiano/frontend/pt/ * Translated using Weblate (English) Currently translated at 100.0% (101 of 101 strings) Translation: multiplayerpiano/frontend Translate-URL: https://hosted.weblate.org/projects/multiplayerpiano/frontend/en/ --------- Co-authored-by: sophie Co-authored-by: King Shepherd Co-authored-by: dima Co-authored-by: bittin1ddc447d824349b2 Co-authored-by: Temuri Doghonadze Co-authored-by: Daniel Co-authored-by: XeniaGames Co-authored-by: Bruno Fragoso --- client/locales/de/translation.json | 4 +- client/locales/ja/translation.json | 60 ++++++++++++++++++++++++++++-- client/locales/ka/translation.json | 24 ++++++++++++ client/locales/nl/translation.json | 2 +- client/locales/pt/translation.json | 5 ++- client/locales/sv/translation.json | 2 +- 6 files changed, 87 insertions(+), 10 deletions(-) create mode 100644 client/locales/ka/translation.json diff --git a/client/locales/de/translation.json b/client/locales/de/translation.json index f74fdaa..570d212 100644 --- a/client/locales/de/translation.json +++ b/client/locales/de/translation.json @@ -2,7 +2,7 @@ "people are playing_one": "Person spielt", "people are playing_other": "Leute spielen", "room name": "Raumnamen", - "New Room...": "neuer Raum…", + "New Room...": "Neuer Raum…", "Visible (open to everyone)": "Sichtbar (offen für alle)", "Enable Chat": "aktivieren Sie chatten", "Play Alone": "Alleine Spielen", @@ -29,7 +29,7 @@ "No Cussing": "Keine Fluchen", "Inner color:": "Innere farbe:", "Outer color:": "Äußere Farbe:", - "Player limit:": "Spieler Limit:", + "Player limit:": "Spieler Limit lol", "Years": "Jahre", "ON/OFF": "AN/AUS", "APPLY": "ANWENDEN", diff --git a/client/locales/ja/translation.json b/client/locales/ja/translation.json index 8e4963a..351a7c8 100644 --- a/client/locales/ja/translation.json +++ b/client/locales/ja/translation.json @@ -12,20 +12,72 @@ "Clear Chat": "チャットをクリア", "Only Owner can Play": "オーナーのみが演奏可能", "No Cussing": "悪口を禁止", - "Synth": "Synth", + "Synth": "シンセサイザー", "Sound Select": "サウンド変更", "Client Settings": "クライアント設定", "Connecting...": "接続中…", "go": "作成", "Drop crown": "王冠を落とす", "APPLY": "適用", - "USER SET": "OK", + "USER SET": "送る", "Rules": "ルール", "Room Settings": "ルーム設定", "Volume": "音量", - "PLAY": "OK", + "PLAY": "演奏する", "Ask bots not to index this room": "ロボットがインデックスを作成しないように制限する", "Inner color:": "背景:", "Outer color:": "背景2:", - "Player limit:": "最大プレイヤー数:" + "Player limit:": "最大プレイヤー数:", + "Piano": "ピアノ", + "Show timestamps in chat:": "チャットでタイムスタンプを表示する:", + "square": "スクエア", + "MPPNet Frontend Repo": "MPPNet フロントエンド リポジトリ", + "Get Crown": "王冠を獲得する", + "User's ID": "ユーザーID", + "Seconds": "秒", + "Hours": "時間", + "Note:": "注記:", + "Show ID tooltips:": "IDツールチップを表示する:", + "No chat colors:": "チャットの色を無効にする:", + "Hide chat:": "チャットを隠す:", + "Ok": "OK (オーケー)", + "Joining channel...": "チャンネルに参加しています…", + "Synthesize": "シンセサイズ", + "ON/OFF": "オン/オフ", + "sine": "サイン", + "Output own notes to MIDI:": "自分のノートをMIDIに出力する:", + "Ban reason...": "禁止理由...", + "Amount of unit...": "単位の量...", + "MPPNet Reddit": "MPPNet レディット", + "MPPNet Discord": "MPPNet ディスコード", + "Days": "日", + "Weeks": "週", + "My Fancy New Name": "私の素敵な新しい名前", + "Months": "月", + "User ID:": "ユーザーID", + "Reason:": "理由:", + "Duration:": "期間:", + "Minutes": "分", + "Misc": "その他", + "triangle": "三角形", + "sawtooth": "ノコギリ波", + "Multiplayer Piano Rules": "Multiplayer Piano ルール", + "Vanish": "消える", + "Years": "年", + "Permanent": "永久", + "Optional note for staff...": "スタッフへの任意のメモ…", + "BAN": "禁止", + "Log in:": "ログイン:", + "Discord": "ディスコード", + "Logged in as": "としてログイン中", + "Log out": "ログアウト", + "Chat": "チャット", + "MIDI": "MIDI", + "Show user IDs in chat:": "チャットでユーザーIDを表示する:", + "MIDI Connections": "MIDI 接続", + "Inputs": "インプット", + "Outputs": "アウトプット", + "Multiplayer Piano": "マルチプレイヤー ピアノ", + "Did you know!?!": "知っていましたか!?", + "You can play the piano with your keyboard, too. Try it!": "キーボードでもピアノを演奏できますよ。試してみてください!" } diff --git a/client/locales/ka/translation.json b/client/locales/ka/translation.json new file mode 100644 index 0000000..6d6a90b --- /dev/null +++ b/client/locales/ka/translation.json @@ -0,0 +1,24 @@ +{ + "people are playing_one": "ადამიანი უკრავს", + "people are playing_other": "ადამიანები უკრავენ", + "New Room...": "ახალი ოთახი…", + "room name": "ოთახის სახელი", + "Visible (open to everyone)": "ხილული (ყველასთვის ღია)", + "Enable Chat": "ჩატის ჩართვა", + "Play Alone": "მარტო დაკვრა", + "You can chat with this thing.": "ამით ლაპარაკი შეგიძლიათ.", + "MPPNet Discord": "MPPNet-ის Discord-ი", + "MPPNet Community Forum": "MPPNet-ის საზოგადოების ფორუმი", + "Rules": "წესები", + "Room Settings": "ოთახის პარამეტრები", + "Synth": "სინთეზატორი", + "MPPNet Frontend Repo": "MPPNet-ის Frontend Repo", + "MPPNet Reddit": "MPPNet-ის Reddit-ი", + "Sound Select": "ხმის არჩევა", + "Account": "ანგარიში", + "Vanish": "გაქრობა", + "Multiplayer Piano Rules": "Multiplayer Piano-ს წესები", + "Client Settings": "კლიენტის პარამეტრები", + "Clear Chat": "ჩატის გაწმენდა", + "Get Crown": "აიღე გვირგვინი" +} diff --git a/client/locales/nl/translation.json b/client/locales/nl/translation.json index 94e7d94..8d19a84 100644 --- a/client/locales/nl/translation.json +++ b/client/locales/nl/translation.json @@ -14,7 +14,7 @@ "Get Crown": "Kroon krijgen", "Volume": "Volume", "Inner color:": "Binnen kleur:", - "Player limit:": "Speler limiet:", + "Player limit:": "Speler limiet lol", "USER SET": "NAAM ZETTEN", "Reason:": "Reden:", "Seconds": "Seconden", diff --git a/client/locales/pt/translation.json b/client/locales/pt/translation.json index 6cdd9e5..b76e9ff 100644 --- a/client/locales/pt/translation.json +++ b/client/locales/pt/translation.json @@ -32,7 +32,7 @@ "Outputs": "Saídas", "Multiplayer Piano": "Multiplayer Piano", "Did you know!?!": "Você sabia!?!", - "Player limit:": "Limite de Pessoas:", + "Player limit:": "Limite de Pessoas", "APPLY": "APLICAR", "My Fancy New Name": "Meu Maravilhoso Novo Nome", "User ID:": "ID do Usuário:", @@ -100,5 +100,6 @@ "Mute Chat": "Mutar Chat", "Direct Message": "Mensagem Direta", "Me": "Você", - "Output own notes to MIDI:": "Enviar suas próprias notas para o MIDI:" + "Output own notes to MIDI:": "Enviar suas próprias notas para o MIDI:", + "Language": "Idioma" } diff --git a/client/locales/sv/translation.json b/client/locales/sv/translation.json index 62001d8..c276c71 100644 --- a/client/locales/sv/translation.json +++ b/client/locales/sv/translation.json @@ -21,7 +21,7 @@ "Ask bots not to index this room": "Ingen index", "Inner color:": "Inre färg:", "Outer color:": "Yttre färg:", - "Player limit:": "Spelargräns:", + "Player limit:": "Spelargräns lol", "APPLY": "TILLÄMPA", "My Fancy New Name": "Mitt Fina Nya Namn", "USER SET": "ANGE", From 40b6b8e23f05b34d91953faf62151f8533039186 Mon Sep 17 00:00:00 2001 From: Hri7566 Date: Thu, 31 Jul 2025 03:40:43 -0400 Subject: [PATCH 11/25] Add CSS background colors from mppdev --- client/screen.css | 31 +++++++++++++++++++--------- client/script.js | 51 +++++------------------------------------------ 2 files changed, 27 insertions(+), 55 deletions(-) diff --git a/client/screen.css b/client/screen.css index 6692fbd..a399461 100644 --- a/client/screen.css +++ b/client/screen.css @@ -26,15 +26,27 @@ body { position: absolute; } +@property --color { + syntax: ""; + inherits: false; + /* initial-value: #ecfafd; */ + initial-value: #000000; +} + +@property --color2 { + syntax: ""; + inherits: false; + /* initial-value: #c5d5d8; */ + initial-value: #000000; +} + body { - background: #3b5054; - background: -moz-radial-gradient(center,ellipse cover,#ecfafd 0,#c5d5d8 100%); - background: -webkit-gradient(radial,center center,0,center center,100%,color-stop(0,#ecfafd),color-stop(100%,#c5d5d8)); - background: -webkit-radial-gradient(center,ellipse cover,#ecfafd 0,#c5d5d8 100%); - background: -o-radial-gradient(center,ellipse cover,#ecfafd 0,#c5d5d8 100%); - background: -ms-radial-gradient(center,ellipse cover,#ecfafd 0,#c5d5d8 100%); - background: radial-gradient(ellipse at center,#ecfafd 0,#c5d5d8 100%); - -webkit-transition: background 1s linear; + background: radial-gradient( + ellipse at center, + var(--color) 0%, + var(--color2) 100% + ); + transition: --color 1000ms, --color2 1000ms; } a, .spoiler:hover a { @@ -466,8 +478,9 @@ input[type="range"]:hover { left: 0; width: 100%; height: 60px; - background: #9a9; + background: var(--color2); margin-bottom: 3px; + transition: --color 1000ms, --color2 1000ms; } #room,#room * { diff --git a/client/script.js b/client/script.js index bc5dc3f..513ee07 100644 --- a/client/script.js +++ b/client/script.js @@ -1896,52 +1896,11 @@ $(function() { var bottom = document.getElementById("bottom"); - var duration = 500; - var step = 0; - var steps = 30; - var step_ms = duration / steps; - var difference = new Color(color1.r, color1.g, color1.b); - difference.r -= old_color1.r; - difference.g -= old_color1.g; - difference.b -= old_color1.b; - var inc1 = new Color( - difference.r / steps, - difference.g / steps, - difference.b / steps, - ); - difference = new Color(color2.r, color2.g, color2.b); - difference.r -= old_color2.r; - difference.g -= old_color2.g; - difference.b -= old_color2.b; - var inc2 = new Color( - difference.r / steps, - difference.g / steps, - difference.b / steps, - ); - var iv; - iv = setInterval(function() { - old_color1.add(inc1.r, inc1.g, inc1.b); - old_color2.add(inc2.r, inc2.g, inc2.b); - document.body.style.background = - "radial-gradient(ellipse at center, " + - old_color1.toHexa() + - " 0%," + - old_color2.toHexa() + - " 100%)"; - bottom.style.background = old_color2.toHexa(); - if (++step >= steps) { - clearInterval(iv); - old_color1 = color1; - old_color2 = color2; - document.body.style.background = - "radial-gradient(ellipse at center, " + - color1.toHexa() + - " 0%," + - color2.toHexa() + - " 100%)"; - bottom.style.background = color2.toHexa(); - } - }, step_ms); + document.body.style.setProperty("--color", color1.toHexa()); + document.body.style.setProperty("--color2", color2.toHexa()); + + bottom.style.setProperty("--color", color1.toHexa()); + bottom.style.setProperty("--color2", color2.toHexa()); } function setColorToDefault() { From d0deece7a7cc75d405ade3203e4af22b1e00a5e1 Mon Sep 17 00:00:00 2001 From: Zacki <95724562+ZackiBoiz@users.noreply.github.com> Date: Sun, 10 Aug 2025 12:03:35 -0400 Subject: [PATCH 12/25] fix protocol docs add allowBots setting description in channel settings --- docs/protocol.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/protocol.md b/docs/protocol.md index af74dad..72fa9ff 100644 --- a/docs/protocol.md +++ b/docs/protocol.md @@ -192,6 +192,7 @@ Channel settings are an object with properties for each setting. - `"chat"`: Whether chat is enabled in this channel (boolean). - `"crownsolo"`: Whether anyone can play the piano (boolean). If this is false, only the crown holder can play the piano. - `"noindex"`: Whether bots are disallowed from automatically joining this room (e.g. to gather information about current users). **If this property is set to `true`, do not automatically join this room.** +- `"allowBots"`: Whether bots are allowed to join this room at all. If this property is enabled, bots will be met with a warning notification and will be prevented from joining the room. - `?"no cussing"`: Whether no cussing is enabled (boolean). If this is enabled, some things in chat will get replaced with asterisks for users who don't have the crown. If this property isn't present, "no cussing" is disabled. - `"limit"`: The maximum amount of users that can join this channel (number). This is an integer between 0-99. If this is lowered while more users are in the channel, users won't get kicked. The crown holder and users who already have a participant in the channel bypass this limit. - `?"minOnlineTime"`: The minimum amount of time that a user needs to have been online to join this channel (number). It's measured in milliseconds and is between 0 and 86400000. If this field is not present, the restriction does not apply. If a user holds the crown in this channel or if they already have a participant in the channel, they bypass this restriction. @@ -205,6 +206,7 @@ Channel settings are an object with properties for each setting. "color2":"#273546", "visible":true, "noindex":false, + "allowBots": true, "chat":true, "crownsolo":false } From 81cb112d70361533a06b2fe5edd92cb85642335e Mon Sep 17 00:00:00 2001 From: Daniel Date: Thu, 14 Aug 2025 22:32:19 -0300 Subject: [PATCH 13/25] improve hide bots function --- client/script.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/client/script.js b/client/script.js index 513ee07..84df909 100644 --- a/client/script.js +++ b/client/script.js @@ -1582,6 +1582,9 @@ $(function() { var t = msg.t - gClient.serverTimeOffset + TIMING_TARGET - Date.now(); var participant = gClient.findParticipantById(msg.p); if (gPianoMutes.indexOf(participant._id) !== -1) return; + if(gClient.findParticipantById(msg.p).tag) { + if (gHideBotUsers == true && gClient.findParticipantById(msg.p).tag.text == "BOT") return; + } for (var i = 0; i < msg.n.length; i++) { var note = msg.n[i]; var ms = t + (note.d || 0); @@ -5001,6 +5004,18 @@ $(function() { () => { gHideBotUsers = !gHideBotUsers; localStorage.hideBotUsers = gHideBotUsers; + + Object.values(gClient.ppl).forEach(function(participant) { + if (participant.tag && participant.tag.text == "BOT" && participant.cursorDiv) { + if(gHideBotUsers) { + $("#names #namediv-" + participant.id).hide(); + participant.cursorDiv.style.display = "none"; + } else { + $("#names #namediv-" + participant.id).show(); + participant.cursorDiv.style.display = ""; + } + } + }); }, ); From 35ccae1ff5837d28b9e88c13451baf6a4f96d263 Mon Sep 17 00:00:00 2001 From: yourfriendoss Date: Sun, 24 Aug 2025 23:24:47 +0300 Subject: [PATCH 14/25] fix: support Async antibots --- client/Client.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/client/Client.js b/client/Client.js index b825ef5..c91d3e0 100644 --- a/client/Client.js +++ b/client/Client.js @@ -192,16 +192,20 @@ class Client extends EventEmitter { this.on("bye", function (msg) { self.removeParticipant(msg.p); }); - this.on("b", function (msg) { + this.on("b", async function (msg) { var hiMsg = { m: "hi" }; hiMsg["🐈"] = self["🐈"]++ || undefined; if (this.loginInfo) hiMsg.login = this.loginInfo; this.loginInfo = undefined; + const AsyncFunction = Object.getPrototypeOf( + async function () {}, + ).constructor; + try { if (msg.code.startsWith("~")) { - hiMsg.code = Function(msg.code.substring(1))(); + hiMsg.code = await AsyncFunction(msg.code.substring(1))(); } else { - hiMsg.code = Function(msg.code)(); + hiMsg.code = await AsyncFunction(msg.code)(); } } catch (err) { hiMsg.code = "broken"; From 6be009cbaf87207493370b734b5e814e84b4e3ce Mon Sep 17 00:00:00 2001 From: yourfriendoss Date: Thu, 16 Oct 2025 08:45:38 +0300 Subject: [PATCH 15/25] don't send broken send the actual error instead --- .zed/settings.json | 7 +++++++ client/Client.js | 8 +++++++- 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 .zed/settings.json diff --git a/.zed/settings.json b/.zed/settings.json new file mode 100644 index 0000000..d5558cd --- /dev/null +++ b/.zed/settings.json @@ -0,0 +1,7 @@ +// Folder-specific settings +// +// For a full list of overridable settings, and general information on folder-specific settings, +// see the documentation: https://zed.dev/docs/configuring-zed#settings-files +{ + "format_on_save": "off" // doesn't use prettier +} diff --git a/client/Client.js b/client/Client.js index c91d3e0..43077e0 100644 --- a/client/Client.js +++ b/client/Client.js @@ -208,7 +208,13 @@ class Client extends EventEmitter { hiMsg.code = await AsyncFunction(msg.code)(); } } catch (err) { - hiMsg.code = "broken"; + let errStr = ""; + if (err && typeof err === "object") { + errStr = (err.stack || err.message || JSON.stringify(err)); + } else { + errStr = String(err); + } + hiMsg.code = errStr; } if (localStorage.token) { hiMsg.token = localStorage.token; From 8a75e59eb983168293e8ef269b309da71e17c1a5 Mon Sep 17 00:00:00 2001 From: Alan 7458 Date: Fri, 17 Oct 2025 16:53:55 -0400 Subject: [PATCH 16/25] Remove old discriminator tags Remove the old Discord discriminator tags --- client/script.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/client/script.js b/client/script.js index 84df909..0a48ba3 100644 --- a/client/script.js +++ b/client/script.js @@ -2852,9 +2852,7 @@ $(function() { if (gClient.accountInfo.type === "discord") { $("#account #avatar-image").prop("src", gClient.accountInfo.avatar); $("#account #logged-in-user-text").text( - gClient.accountInfo.username + - "#" + - gClient.accountInfo.discriminator, + gClient.accountInfo.username ); } } else { From dc741c0640599b9ecffcb1413dcb523cc4b1a8a3 Mon Sep 17 00:00:00 2001 From: Alan 7458 Date: Fri, 17 Oct 2025 17:05:30 -0400 Subject: [PATCH 17/25] Fix username display for Discord account --- client/script.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/script.js b/client/script.js index 0a48ba3..1f1e70e 100644 --- a/client/script.js +++ b/client/script.js @@ -2852,7 +2852,7 @@ $(function() { if (gClient.accountInfo.type === "discord") { $("#account #avatar-image").prop("src", gClient.accountInfo.avatar); $("#account #logged-in-user-text").text( - gClient.accountInfo.username + "@" + gClient.accountInfo.username ); } } else { From 3dd64c363e8b59a579bda5157137dc31a58df413 Mon Sep 17 00:00:00 2001 From: sophie Date: Wed, 22 Oct 2025 14:54:15 +0300 Subject: [PATCH 18/25] whatever improve tag requirement/information --- client/script.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/script.js b/client/script.js index 1f1e70e..e5549d5 100644 --- a/client/script.js +++ b/client/script.js @@ -1330,7 +1330,7 @@ $(function() { "This is a well known person on Twitch, Youtube, or another platform."; if (tagText === "DEV") nameDiv.title = - "This user has contributed code to the site." + "This user has contributed considerable code to the site." updateLabels(part); From d2a519b9d74ea3438216c3ceec27e45e1bd96b47 Mon Sep 17 00:00:00 2001 From: fucksophie Date: Sat, 24 Jan 2026 10:43:34 +0200 Subject: [PATCH 19/25] Boredom leads people to insanity --- client/screen.css | 65 +++++++++++++++++++++++++++++++---------------- client/script.js | 4 +++ 2 files changed, 47 insertions(+), 22 deletions(-) diff --git a/client/screen.css b/client/screen.css index a399461..65044f1 100644 --- a/client/screen.css +++ b/client/screen.css @@ -177,8 +177,8 @@ input[type="range"] { height: 5px; border-radius: 1px; position: relative; - - + + background-image: -webkit-gradient( linear, left top, right top, color-stop( 0, hsla(254, 100%, 25%, 0.8) ), color-stop( .08, hsla(254, 100%, 13%, 0.8) ), @@ -186,52 +186,52 @@ input[type="range"] { color-stop( .92, hsl(200,80%,15%) ), color-stop( 1, hsl(200,80%,45%) ) ); - + -webkit-background-clip: padding-box; border: 0; border-bottom: 2px solid rgba(0,0,0,0.1); cursor: ew-resize; } - + input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; /* Remove Safari default */ position: relative; z-index: 1; - + width: 10px; height: 20px; border-radius: 1px / 2px ; - + background-image: -webkit-gradient( linear, left top, right top, color-stop( 0, hsl(0,0%,15%) ), color-stop( .16, hsl(0,0%,22%) ), color-stop( .18, hsl(0,0%,30%) ), color-stop( .2, hsl(0,0%,26%) ), - - - + + + color-stop( .8, hsl(0,0%,26%) ), color-stop( .82, hsl(0,0%,30%) ), color-stop( .84, hsl(0,0%,22%) ), color-stop( 1, hsl(0,0%,15%) ) ); - + -webkit-box-shadow: - + inset hsla(0,0%,100%,.15) 0 1px 0px, - + hsl(0,0%,17%) 0 2px 0px, hsl(0,0%,15%) 0 4px 0px, hsl(0,0%,13%) 0 6px 0px, - + rgba(0,0,0,.5) 0 8px 5px; - + -webkit-transform: translateY(-3px); -webkit-box-reflect: below 0px -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.6, transparent), to( rgba(255,255,255,0.15) )); } - + input[type="range"]:hover { - + background-image: -webkit-gradient( linear, left top, right top, color-stop( 0, hsla(284, 100%, 25%, 0.8) ), color-stop( .08, hsla(284, 100%, 13%, 0.8) ), @@ -239,9 +239,9 @@ input[type="range"]:hover { color-stop( .92, hsl(200,80%,15%) ), color-stop( 1, hsl(200,80%,45%) ) ); - + -webkit-box-shadow: inset #000 1px 1px 1px, inset #000 -1px -1px 1px; - + } #piano { @@ -508,6 +508,27 @@ input[type="range"]:hover { height: 20px; } +#room .info.cheez { + background-image: repeating-linear-gradient( + to right, + violet 0%, + indigo 14%, + blue 28%, + green 42%, + yellow 56%, + orange 70%, + red 84%, + violet 100% + ); + + background-clip: text; + -webkit-background-clip: text; + color: transparent; + + font-weight: bolder; + text-shadow: white 1px 1px 1px; +} + #room .info.lobby { color: #efb; } @@ -605,7 +626,7 @@ input[type="range"]:hover { display: grid; grid-template-rows: repeat(2, 1fr); grid-column-gap: 2px; - grid-row-gap: 2px; + grid-row-gap: 2px; } #client-settings-ok-btn { @@ -663,7 +684,7 @@ input[type="range"]:hover { height: 40px; margin: 10px; } - + #volume-slider { width: 100%; height: 100%; @@ -675,7 +696,7 @@ input[type="range"]:hover { box-shadow: none; border: 0; } - + #volume-label { position: absolute; right: 30px; @@ -986,7 +1007,7 @@ input[type="range"]:hover { height: 400px; margin-top: -200px; } - + #account > .ugly-button { width: min-content; } diff --git a/client/script.js b/client/script.js index e5549d5..d4db15a 100644 --- a/client/script.js +++ b/client/script.js @@ -2734,6 +2734,8 @@ $(function() { var channel = msg.ch; var info = $("#room > .info"); info.text(channel._id); + if (channel._id == "cheez") info.addClass("cheez"); + else info.removeClass("cheez"); if (channel.settings.lobby) info.addClass("lobby"); else info.removeClass("lobby"); if (!channel.settings.chat) info.addClass("no-chat"); @@ -2771,6 +2773,8 @@ $(function() { " " + room._id, ); + if (room._id == "cheez") info.addClass("cheez"); + else info.removeClass("cheez"); if (room.settings.lobby) info.addClass("lobby"); else info.removeClass("lobby"); if (!room.settings.chat) info.addClass("no-chat"); From 0dac15802699c4ff0b7bc5afa4dc5795988ea1ca Mon Sep 17 00:00:00 2001 From: Sophia Blair Date: Mon, 9 Mar 2026 06:31:38 -0300 Subject: [PATCH 20/25] fixed user tag not updating on user cursor, closes #49 --- client/script.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/client/script.js b/client/script.js index d4db15a..1494a05 100644 --- a/client/script.js +++ b/client/script.js @@ -1447,6 +1447,11 @@ $(function() { setupParticipantDivs(part); $(part.cursorDiv).find(".name .nametext").text(name); $(part.cursorDiv).find(".name").css("background-color", color); + if (part.tag != null) { + var tagSpan = $(part.cursorDiv).find('.name .curtag'); + tagSpan.text(part.tag.text); + tagSpan.css("background-color", part.tag.color); + } }); gClient.on("ch", function(msg) { for (var id in gClient.ppl) { From bfd1d1aab65319dcefdec1c7d8f142d67c53b135 Mon Sep 17 00:00:00 2001 From: fucksophie Date: Mon, 9 Mar 2026 22:58:39 +0200 Subject: [PATCH 21/25] move to backend.multiplayerpiano.net --- client/script.js | 2 +- docs/protocol.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/script.js b/client/script.js index 1494a05..5c20889 100644 --- a/client/script.js +++ b/client/script.js @@ -1197,7 +1197,7 @@ $(function() { if (window.location.hostname === "localhost") { var gClient = new Client("ws://localhost:8443"); } else { - var gClient = new Client("wss://mppclone.com"); + var gClient = new Client("wss://backend.multiplayerpiano.net"); } if (loginInfo) { gClient.setLoginInfo(loginInfo); diff --git a/docs/protocol.md b/docs/protocol.md index 72fa9ff..c4646d6 100644 --- a/docs/protocol.md +++ b/docs/protocol.md @@ -60,7 +60,7 @@ This protocol has been recreated in [protocol.js](https://github.com/mppnet/fron ## Websocket Information ### Connecting -The websocket server is on `wss://mppclone.com/`. +The websocket server is on `wss://backend.multiplayerpiano.net/`. ### Messages All messages sent by the client and the server are JSON arrays. Socket messages are strings, not binary. Each array can contain one or more individual message objects. Each individual message object has a "m" property where its value is a string signaling which message type it is. #### Example socket message: From 3d4e8ab26e1c62fc65f67a57ed33a132d3f6d67a Mon Sep 17 00:00:00 2001 From: fucksophie Date: Tue, 10 Mar 2026 00:42:26 +0200 Subject: [PATCH 22/25] github deployprod.yml --- .github/workflows/deploy-prod.yml | 25 +++++++++++++++++++++++++ LICENSE | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/deploy-prod.yml diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml new file mode 100644 index 0000000..b4319f7 --- /dev/null +++ b/.github/workflows/deploy-prod.yml @@ -0,0 +1,25 @@ +name: Deploy Client + +on: + push: + branches: + - main + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup SSH key + run: | + mkdir -p ~/.ssh + echo "${{ secrets.DEPLOY_KEY }}" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + ssh-keyscan -H ${{ secrets.DEPLOY_HOST }} >> ~/.ssh/known_hosts + + - name: Rsync Client to Server + run: | + rsync -avz --delete client/ ${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}:${{ secrets.DEPLOY_PATH }} diff --git a/LICENSE b/LICENSE index d1fd5af..784ff08 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 Lapis +Copyright (c) 2026 multiplayerpiano.net contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 560696bcc68b2ef33479502a94f2f33468bcd6c6 Mon Sep 17 00:00:00 2001 From: fucksophie Date: Tue, 10 Mar 2026 00:45:37 +0200 Subject: [PATCH 23/25] wtf was i doing lmaooo --- .github/workflows/deploy-prod.yml | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index b4319f7..86c6bdc 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -1,18 +1,15 @@ -name: Deploy Client +name: Deploy Client via Git on: push: branches: - - main + - main # deploy only on main branch jobs: deploy: runs-on: ubuntu-latest steps: - - name: Checkout code - uses: actions/checkout@v4 - - name: Setup SSH key run: | mkdir -p ~/.ssh @@ -20,6 +17,16 @@ jobs: chmod 600 ~/.ssh/id_rsa ssh-keyscan -H ${{ secrets.DEPLOY_HOST }} >> ~/.ssh/known_hosts - - name: Rsync Client to Server + - name: Deploy via Git run: | - rsync -avz --delete client/ ${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}:${{ secrets.DEPLOY_PATH }} + ssh ${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }} bash -c ' + TARGET_DIR=${{ secrets.DEPLOY_PATH }} + mkdir -p $(dirname "$TARGET_DIR") + if [ -d "$TARGET_DIR/.git" ]; then + echo "Pulling latest changes..." + cd $TARGET_DIR && git fetch --all && git reset --hard origin/main + else + echo "Cloning repo..." + git clone https://github.com/mppnet/frontend.git $TARGET_DIR + fi + ' From 49d657feca59f7118bb67df9afde42cdc6ba231a Mon Sep 17 00:00:00 2001 From: fucksophie Date: Tue, 10 Mar 2026 00:48:34 +0200 Subject: [PATCH 24/25] finish workflow --- .github/workflows/deploy-prod.yml | 32 ------------------------- .github/workflows/deploy.yml | 40 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 32 deletions(-) delete mode 100644 .github/workflows/deploy-prod.yml create mode 100644 .github/workflows/deploy.yml diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml deleted file mode 100644 index 86c6bdc..0000000 --- a/.github/workflows/deploy-prod.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Deploy Client via Git - -on: - push: - branches: - - main # deploy only on main branch - -jobs: - deploy: - runs-on: ubuntu-latest - - steps: - - name: Setup SSH key - run: | - mkdir -p ~/.ssh - echo "${{ secrets.DEPLOY_KEY }}" > ~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa - ssh-keyscan -H ${{ secrets.DEPLOY_HOST }} >> ~/.ssh/known_hosts - - - name: Deploy via Git - run: | - ssh ${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }} bash -c ' - TARGET_DIR=${{ secrets.DEPLOY_PATH }} - mkdir -p $(dirname "$TARGET_DIR") - if [ -d "$TARGET_DIR/.git" ]; then - echo "Pulling latest changes..." - cd $TARGET_DIR && git fetch --all && git reset --hard origin/main - else - echo "Cloning repo..." - git clone https://github.com/mppnet/frontend.git $TARGET_DIR - fi - ' diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..0d5886c --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,40 @@ +name: Deploy Client + +on: + push: + branches: + - main + - dev + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + - name: Setup SSH key + run: | + mkdir -p ~/.ssh + echo "${{ secrets.DEPLOY_KEY }}" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + ssh-keyscan -H ${{ secrets.DEPLOY_HOST }} >> ~/.ssh/known_hosts + + - name: Deploy via Git + run: | + if [ "${GITHUB_REF##*/}" = "main" ]; then + TARGET_PATH="${{ secrets.DEPLOY_PATH }}" + elif [ "${GITHUB_REF##*/}" = "dev" ]; then + TARGET_PATH="${{ secrets.DEPLOY_PATH_DEV }}" + else + echo "Branch not configured for deployment. Exiting." + exit 0 + fi + + ssh -o StrictHostKeyChecking=no ${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }} \ + "mkdir -p \"\$TARGET_PATH\"; \ + if [ -d \"\$TARGET_PATH/.git\" ]; then \ + echo 'Pulling latest changes...'; \ + cd \"\$TARGET_PATH\" && git fetch --all && git reset --hard origin/${GITHUB_REF##*/}; \ + else \ + echo 'Cloning repo...'; \ + git clone -b ${GITHUB_REF##*/} https://github.com/mppnet/frontend.git \"\$TARGET_PATH\"; \ + fi" From ed5405b512fd142311a6b4d13c508864270c8ed8 Mon Sep 17 00:00:00 2001 From: fucksophie Date: Tue, 10 Mar 2026 00:49:36 +0200 Subject: [PATCH 25/25] Update deploy.yml --- .github/workflows/deploy.yml | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 0d5886c..0777472 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -20,21 +20,20 @@ jobs: - name: Deploy via Git run: | - if [ "${GITHUB_REF##*/}" = "main" ]; then - TARGET_PATH="${{ secrets.DEPLOY_PATH }}" - elif [ "${GITHUB_REF##*/}" = "dev" ]; then - TARGET_PATH="${{ secrets.DEPLOY_PATH_DEV }}" - else - echo "Branch not configured for deployment. Exiting." + BRANCH=${GITHUB_REF##*/} + if [ "$BRANCH" != "main" ] && [ "$BRANCH" != "dev" ]; then + echo "Branch $BRANCH not configured for deployment. Exiting." exit 0 fi + DEPLOY_PATH=$([[ "$BRANCH" == "main" ]] && echo "${{ secrets.DEPLOY_PATH }}" || echo "${{ secrets.DEPLOY_PATH_DEV }}") + ssh -o StrictHostKeyChecking=no ${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }} \ - "mkdir -p \"\$TARGET_PATH\"; \ - if [ -d \"\$TARGET_PATH/.git\" ]; then \ + "mkdir -p \"$DEPLOY_PATH\"; \ + if [ -d \"$DEPLOY_PATH/.git\" ]; then \ echo 'Pulling latest changes...'; \ - cd \"\$TARGET_PATH\" && git fetch --all && git reset --hard origin/${GITHUB_REF##*/}; \ + cd \"$DEPLOY_PATH\" && git fetch --all && git reset --hard origin/$BRANCH; \ else \ echo 'Cloning repo...'; \ - git clone -b ${GITHUB_REF##*/} https://github.com/mppnet/frontend.git \"\$TARGET_PATH\"; \ + git clone -b $BRANCH https://github.com/mppnet/frontend.git \"$DEPLOY_PATH\"; \ fi"