add support for badges to the client

This commit is contained in:
Holly Stubbs 2024-10-02 01:08:03 +01:00
parent 2a970a7c5a
commit 60bc7d90cb
Signed by: tgpholly
GPG key ID: B8583C4B7D18119E
2 changed files with 194 additions and 52 deletions

View file

@ -1,7 +1,7 @@
// ==UserScript== // ==UserScript==
// @name MultiProbe // @name MultiProbe
// @namespace https://*.angusnicneven.com/* // @namespace https://*.angusnicneven.com/*
// @version 20240916.0 // @version 20241002.0
// @description Probe with friends! // @description Probe with friends!
// @author tgpholly // @author tgpholly
// @match https://*.angusnicneven.com/* // @match https://*.angusnicneven.com/*
@ -48,7 +48,7 @@ console.log("[MP] MultiProbe init");
'use strict'; 'use strict';
// Make sure to change the userscript version too!!!!!!!!!! // Make sure to change the userscript version too!!!!!!!!!!
const USERSCRIPT_VERSION_RAW = "20240916.0"; const USERSCRIPT_VERSION_RAW = "20241002.0";
const USERSCRIPT_VERSION = parseInt(USERSCRIPT_VERSION_RAW.replace(".", "")); const USERSCRIPT_VERSION = parseInt(USERSCRIPT_VERSION_RAW.replace(".", ""));
if (!continueRunningScript) { if (!continueRunningScript) {
@ -67,7 +67,8 @@ console.log("[MP] MultiProbe init");
ClientLeft: 5, ClientLeft: 5,
Ping: 6, Ping: 6,
GroupData: 7, GroupData: 7,
HonkShoe: 8 HonkShoe: 8,
BadgeUnlock: 9
}; };
let cursorImageI = window.getComputedStyle(document.body).cursor; let cursorImageI = window.getComputedStyle(document.body).cursor;
@ -199,7 +200,7 @@ html {
background-color: rgba(255,255,255,0.15); background-color: rgba(255,255,255,0.15);
} }
.groupui-user p { .groupui-user mp_text {
position: absolute; position: absolute;
line-height: 2rem; line-height: 2rem;
margin: 0; margin: 0;
@ -243,6 +244,98 @@ kbd {
color: #c1b492; color: #c1b492;
} }
@keyframes badgepop {
0% {
top: -4rem;
}
100% {
top: 0rem;
}
}
@keyframes badgepopout {
0% {
top: 0rem;
}
100% {
top: -4rem;
}
}
.badgepopout {
top: -4rem;
animation: badgepopout .35s ease-in-out !important;
}
.badgepopin {
top: 0rem;
animation: badgepop .35s ease-in-out !important;
animation-iteration-count: 1;
}
.badgepopcreate {
top: -4rem;
}
.badgepop {
position: absolute;
margin-top: .5rem;
width: 15rem;
background-color: black;
text-align: start!important;
padding: .5rem;
border: 1px solid white;
}
.badgepop mp_text {
font-size: 8px;
color: white;
padding: 0;
margin: 0;
}
mp_text {
color: white;
display: block;
}
mp_container {
display: block;
}
.badgepop * {
text-align: unset!important;
text-shadow: none!important;
font-family: Arial,sans-serif;
}
mp_container ul {
/* base t00 ul style */
background: #d2738a!important;
margin: 40px 10px 10px 10px!important;
padding: 0px 0px 0px 0px!important;
width: 800px!important;
box-shadow: 0px 5px 10px #000000!important;
line-height: 30px!important;
/* ravarcheon fixes */
position: relative!important;
left: unset!important;
transform: unset!important;
}
mp_container ul li {
background: #000000!important;
margin: 0px 0px 2px 0px!important;
padding: 20px 20px 20px 20px!important;
list-style: none!important;
/* ravarcheon fixes */
text-shadow: unset!important;
}
`.split("\n").join("").split("\r").join("").split("\t").join(""); `.split("\n").join("").split("\r").join("").split("\t").join("");
document.head.appendChild(styles); document.head.appendChild(styles);
@ -256,12 +349,12 @@ kbd {
const bodyMarginLeft = parseInt(marginComputedStyle.marginLeft.replace("px", "")); const bodyMarginLeft = parseInt(marginComputedStyle.marginLeft.replace("px", ""));
const bodyMarginRight = parseInt(marginComputedStyle.marginRight.replace("px", "")); const bodyMarginRight = parseInt(marginComputedStyle.marginRight.replace("px", ""));
const otherCursors = document.createElement("div"); const otherCursors = document.createElement("mp_cursors");
otherCursors.style.top = `-${((window.scrollY + document.body.getBoundingClientRect().top) - bodyMarginTop)}px`; otherCursors.style.top = `-${((window.scrollY + document.body.getBoundingClientRect().top) - bodyMarginTop)}px`;
otherCursors.id = "otherCursors"; otherCursors.id = "otherCursors";
document.body.appendChild(otherCursors); document.documentElement.appendChild(otherCursors);
const groupUIBase = document.createElement("div"); const groupUIBase = document.createElement("mp_party");
groupUIBase.style = "display:none"; groupUIBase.style = "display:none";
groupUIBase.classList.add("groupui"); groupUIBase.classList.add("groupui");
groupUIBase.classList.add("grouphidden"); groupUIBase.classList.add("grouphidden");
@ -273,22 +366,26 @@ kbd {
}; };
groupPopper.innerText = "<"; groupPopper.innerText = "<";
groupUIBase.appendChild(groupPopper); groupUIBase.appendChild(groupPopper);
const groupTitle = document.createElement("div"); const groupTitle = document.createElement("mp_container");
groupTitle.classList.add("groupui-title"); groupTitle.classList.add("groupui-title");
groupTitle.innerText = "GROUP_NAME"; groupTitle.innerText = "GROUP_NAME";
groupUIBase.appendChild(groupTitle); groupUIBase.appendChild(groupTitle);
const groupUsers = document.createElement("div"); const groupUsers = document.createElement("mp_container");
groupUsers.classList.add("groupui-scrollbox"); groupUsers.classList.add("groupui-scrollbox");
groupUIBase.appendChild(groupUsers); groupUIBase.appendChild(groupUsers);
document.body.appendChild(groupUIBase); document.documentElement.appendChild(groupUIBase);
const popupRoot = document.createElement("mp_badge_container");
popupRoot.style = "position:fixed;left:50%;top:0;z-index:9999998";
document.documentElement.appendChild(popupRoot);
function createGroupUser(username, location) { function createGroupUser(username, location) {
const user = document.createElement("div"); const user = document.createElement("mp_group_user");
user.classList.add("groupui-user"); user.classList.add("groupui-user");
const usernameBox = document.createElement("p"); const usernameBox = document.createElement("mp_text");
usernameBox.innerText = username; usernameBox.innerText = username;
user.appendChild(usernameBox); user.appendChild(usernameBox);
const buttonBox = document.createElement("div"); const buttonBox = document.createElement("mp_container");
buttonBox.classList.add("buttons"); buttonBox.classList.add("buttons");
user.appendChild(buttonBox); user.appendChild(buttonBox);
@ -351,7 +448,7 @@ kbd {
class RemoteClient { class RemoteClient {
constructor(name, startAfk, isSelfCursor = false) { constructor(name, startAfk, isSelfCursor = false) {
this.name = name; this.name = name;
this.element = document.createElement("div"); this.element = document.createElement("mp_cursor");
this.element.style.position = "absolute"; this.element.style.position = "absolute";
this.element.style.transform = `translate(-50%, -50%)`; this.element.style.transform = `translate(-50%, -50%)`;
const image = new Image(); const image = new Image();
@ -362,12 +459,12 @@ kbd {
image.src = cursorImage; image.src = cursorImage;
this.probeImage = image; this.probeImage = image;
this.element.appendChild(image); this.element.appendChild(image);
const clientName = document.createElement("div"); const clientName = document.createElement("mp_container");
clientName.style = "position:absolute;left:100%;top:100%;background-color:black;padding:4px 8px;color:white;font-size:12px;font-family:Arial,sans-serif;"; clientName.style = "position:absolute;left:100%;top:100%;background-color:black;padding:4px 8px;color:white;font-size:12px;font-family:Arial,sans-serif;";
clientName.innerText = name; clientName.innerText = name;
this.element.appendChild(clientName); this.element.appendChild(clientName);
if (!isSelfCursor) { if (!isSelfCursor) {
this.eepy = document.createElement("div"); this.eepy = document.createElement("mp_eepy");
this.eepy.className = "eepy"; this.eepy.className = "eepy";
this.eepy.style = startAfk ? "" : "display:none"; this.eepy.style = startAfk ? "" : "display:none";
this.element.appendChild(this.eepy); this.element.appendChild(this.eepy);
@ -424,7 +521,7 @@ kbd {
let selfCursor; let selfCursor;
function createPing(x, y) { function createPing(x, y) {
const pingDiv = document.createElement("div"); const pingDiv = document.createElement("mp_ping");
pingDiv.className = "ping"; pingDiv.className = "ping";
pingDiv.style.top = `${y}px`; pingDiv.style.top = `${y}px`;
pingDiv.style.left = `${x}px`; pingDiv.style.left = `${x}px`;
@ -683,6 +780,14 @@ kbd {
break; break;
} }
case MessageType.BadgeUnlock:
{
const badgeTitle = reader.readShortString();
const badgeDescription = reader.readString();
const badgeIconUrl = reader.readShortString();
createBadgePopup(badgeTitle, badgeDescription, badgeIconUrl);
}
} }
} }
@ -706,10 +811,10 @@ kbd {
} }
function createOnlineDialog() { function createOnlineDialog() {
const bg = document.createElement("div"); const bg = document.createElement("mp_container");
windowContainer = bg; windowContainer = bg;
bg.style = "z-index:1000000000;position:fixed;top:0px;left:0px;width:100%;height:100%;background-color:rgba(0,0,0,0.5);text-shadow: none!important;font-family: Arial,sans-serif;font-size: unset !important;"; bg.style = "z-index:1000000000;position:fixed;top:0px;left:0px;width:100%;height:100%;background-color:rgba(0,0,0,0.5);text-shadow: none!important;font-family: Arial,sans-serif;font-size: unset !important;";
const dialog = document.createElement("div"); const dialog = document.createElement("mp_container");
dialog.style = "position:absolute;top:50%;left:50%;min-width:15rem;background-color:#343434;padding:1rem;transform:translate(-50%,-50%);text-align:center;color:white"; dialog.style = "position:absolute;top:50%;left:50%;min-width:15rem;background-color:#343434;padding:1rem;transform:translate(-50%,-50%);text-align:center;color:white";
bg.appendChild(dialog); bg.appendChild(dialog);
const title = document.createElement("h4"); const title = document.createElement("h4");
@ -721,7 +826,7 @@ kbd {
subtitle.style.marginTop = ".5rem"; subtitle.style.marginTop = ".5rem";
dialog.appendChild(subtitle); dialog.appendChild(subtitle);
const buttons = document.createElement("div"); const buttons = document.createElement("mp_container");
buttons.style.marginTop = "1rem"; buttons.style.marginTop = "1rem";
const disconnectButton = document.createElement("button"); const disconnectButton = document.createElement("button");
@ -764,13 +869,13 @@ kbd {
dialog.appendChild(buttons); dialog.appendChild(buttons);
document.body.appendChild(bg); document.documentElement.appendChild(bg);
} }
function createUpdateDialog(versionNumber) { function createUpdateDialog(versionNumber) {
const bg = document.createElement("div"); const bg = document.createElement("mp_container");
bg.style = "z-index:1000000000;position:fixed;top:0px;left:0px;width:100%;height:100%;background-color:rgba(0,0,0,0.5);text-shadow: none!important;font-family: Arial,sans-serif;font-size: unset !important;"; bg.style = "z-index:1000000000;position:fixed;top:0px;left:0px;width:100%;height:100%;background-color:rgba(0,0,0,0.5);text-shadow: none!important;font-family: Arial,sans-serif;font-size: unset !important;";
const dialog = document.createElement("div"); const dialog = document.createElement("mp_container");
dialog.style = "position:absolute;top:50%;left:50%;min-width:15rem;background-color:#343434;padding:1rem;transform:translate(-50%,-50%);text-align:center;color:white"; dialog.style = "position:absolute;top:50%;left:50%;min-width:15rem;background-color:#343434;padding:1rem;transform:translate(-50%,-50%);text-align:center;color:white";
bg.appendChild(dialog); bg.appendChild(dialog);
const title = document.createElement("h4"); const title = document.createElement("h4");
@ -778,11 +883,11 @@ kbd {
title.style.marginBottom = "0px"; title.style.marginBottom = "0px";
dialog.appendChild(title); dialog.appendChild(title);
const updateText = document.createElement("p"); const updateText = document.createElement("mp_text");
updateText.innerHTML = `<a class="mplink" href="https://git.eusv.net/tgpholly/t00-multiuser/raw/branch/master/client/Terminal-00-Multiuser.user.js?${Date.now()}">Please click here to update to the latest version.</a><br>This takes less than a few seconds to do and ensures you can continue to use MultiProbe.<br><br>Current Version: ${USERSCRIPT_VERSION_RAW}<br>New Version: ${versionNumber}`; updateText.innerHTML = `<a class="mplink" href="https://git.eusv.net/tgpholly/t00-multiuser/raw/branch/master/client/Terminal-00-Multiuser.user.js?${Date.now()}">Please click here to update to the latest version.</a><br>This takes less than a few seconds to do and ensures you can continue to use MultiProbe.<br><br>Current Version: ${USERSCRIPT_VERSION_RAW}<br>New Version: ${versionNumber}`;
dialog.appendChild(updateText); dialog.appendChild(updateText);
const buttons = document.createElement("div"); const buttons = document.createElement("mp_container");
buttons.style.marginTop = "1rem"; buttons.style.marginTop = "1rem";
const gotIt = document.createElement("button"); const gotIt = document.createElement("button");
@ -794,7 +899,7 @@ kbd {
dialog.appendChild(buttons); dialog.appendChild(buttons);
document.body.appendChild(bg); document.documentElement.appendChild(bg);
} }
function createFirstTimeDialog() { function createFirstTimeDialog() {
@ -802,10 +907,10 @@ kbd {
return; return;
} }
const bg = document.createElement("div"); const bg = document.createElement("mp_container");
windowContainer = bg; windowContainer = bg;
bg.style = "z-index:1000000000;position:fixed;top:0px;left:0px;width:100%;height:100%;background-color:rgba(0,0,0,0.5);text-shadow: none!important;font-family: Arial,sans-serif;font-size: unset !important;"; bg.style = "z-index:1000000000;position:fixed;top:0px;left:0px;width:100%;height:100%;background-color:rgba(0,0,0,0.5);text-shadow: none!important;font-family: Arial,sans-serif;font-size: unset !important;";
const dialog = document.createElement("div"); const dialog = document.createElement("mp_container");
dialog.style = "position:absolute;top:50%;left:50%;min-width:15rem;background-color:#343434;padding:1rem;transform:translate(-50%,-50%);text-align:center;color:white"; dialog.style = "position:absolute;top:50%;left:50%;min-width:15rem;background-color:#343434;padding:1rem;transform:translate(-50%,-50%);text-align:center;color:white";
bg.appendChild(dialog); bg.appendChild(dialog);
const title = document.createElement("h4"); const title = document.createElement("h4");
@ -833,7 +938,7 @@ kbd {
helpTip.innerHTML = "If you press <kbd>F1</kbd> you can open this help again."; helpTip.innerHTML = "If you press <kbd>F1</kbd> you can open this help again.";
actionList.appendChild(helpTip); actionList.appendChild(helpTip);
const buttons = document.createElement("div"); const buttons = document.createElement("mp_container");
buttons.style.marginTop = "1rem"; buttons.style.marginTop = "1rem";
const gotIt = document.createElement("button"); const gotIt = document.createElement("button");
@ -847,14 +952,50 @@ kbd {
dialog.appendChild(buttons); dialog.appendChild(buttons);
document.body.appendChild(bg); document.documentElement.appendChild(bg);
}
function createBadgePopup(title, description, image) {
const popup = document.createElement("mp_badge");
popup.classList.add("badgepop");
popup.classList.add("badgepopcreate");
popup.style = "transform:translateX(-50%)";
const badgeImage = new Image(32, 32);
badgeImage.src = image;
badgeImage.style = "image-rendering:pixelated";
badgeImage.onload = () => {
popup.classList.remove("badgepopcreate");
popup.classList.add("badgepopin");
};
popup.appendChild(badgeImage);
const badgeTitle = document.createElement("mp_text");
badgeTitle.innerHTML = `<b>${title}</b>`;
badgeTitle.style = "position:absolute;top:.5rem;left:calc(1rem + 32px)";
popup.appendChild(badgeTitle);
const badgeDescription = document.createElement("mp_text");
badgeDescription.innerText = description;
badgeDescription.style = "position:absolute;top:1.1rem;left:calc(1rem + 32px)";
popup.appendChild(badgeDescription);
popupRoot.appendChild(popup);
setTimeout(() => {
popup.classList.remove("badgepopin");
popup.classList.add("badgepopout");
setTimeout(() => {
popup.remove();
}, 500);
}, 5350);
} }
function createLoginDialog() { function createLoginDialog() {
const bg = document.createElement("div"); const bg = document.createElement("mp_container");
windowContainer = bg; windowContainer = bg;
bg.style = "z-index:1000000000;position:fixed;top:0px;left:0px;width:100%;height:100%;background-color:rgba(0,0,0,0.5);text-shadow: none!important;font-family: Arial,sans-serif;font-size: unset !important;"; bg.style = "z-index:1000000000;position:fixed;top:0px;left:0px;width:100%;height:100%;background-color:rgba(0,0,0,0.5);text-shadow: none!important;font-family: Arial,sans-serif;font-size: unset !important;";
const dialog = document.createElement("div"); const dialog = document.createElement("mp_container");
dialog.style = "position:absolute;top:50%;left:50%;width:15rem;background-color:#343434;padding-bottom:1rem;transform:translate(-50%,-50%);text-align:center;color:white"; dialog.style = "position:absolute;top:50%;left:50%;width:15rem;background-color:#343434;padding-bottom:1rem;transform:translate(-50%,-50%);text-align:center;color:white";
bg.appendChild(dialog); bg.appendChild(dialog);
const title = document.createElement("h4"); const title = document.createElement("h4");
@ -883,7 +1024,7 @@ kbd {
password.style.width = "12rem"; password.style.width = "12rem";
password.name = "password"; password.name = "password";
loginForm.appendChild(password); loginForm.appendChild(password);
const buttons = document.createElement("div"); const buttons = document.createElement("mp_container");
buttons.style.marginTop = "1rem"; buttons.style.marginTop = "1rem";
loginForm.appendChild(buttons); loginForm.appendChild(buttons);
const submitButton = document.createElement("button"); const submitButton = document.createElement("button");
@ -935,7 +1076,7 @@ kbd {
}); });
} }
document.body.appendChild(bg); document.documentElement.appendChild(bg);
} }
const openMenuButton = document.createElement("button"); const openMenuButton = document.createElement("button");
@ -948,7 +1089,7 @@ kbd {
createLoginDialog(); createLoginDialog();
} }
}; };
document.body.appendChild(openMenuButton); document.documentElement.appendChild(openMenuButton);
if (localStorage["mpapikey"] && localStorage["mpapikey"] !== "" && localStorage["mpconnectonload"] === "true") { if (localStorage["mpapikey"] && localStorage["mpapikey"] !== "" && localStorage["mpconnectonload"] === "true") {
doConnect(localStorage["mpapikey"]); doConnect(localStorage["mpapikey"]);

View file

@ -7,5 +7,6 @@ export enum MessageType {
ClientLeft, ClientLeft,
Ping, Ping,
GroupData, GroupData,
HonkShoe HonkShoe,
BadgeUnlock
} }