diff --git a/client/Terminal-00-Multiuser.user.js b/client/Terminal-00-Multiuser.user.js
index 4147ca2..aa95523 100644
--- a/client/Terminal-00-Multiuser.user.js
+++ b/client/Terminal-00-Multiuser.user.js
@@ -1,7 +1,7 @@
// ==UserScript==
// @name MultiProbe
// @namespace https://*.angusnicneven.com/*
-// @version 20240916.0
+// @version 20241002.0
// @description Probe with friends!
// @author tgpholly
// @match https://*.angusnicneven.com/*
@@ -48,7 +48,7 @@ console.log("[MP] MultiProbe init");
'use strict';
// 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(".", ""));
if (!continueRunningScript) {
@@ -67,14 +67,15 @@ console.log("[MP] MultiProbe init");
ClientLeft: 5,
Ping: 6,
GroupData: 7,
- HonkShoe: 8
+ HonkShoe: 8,
+ BadgeUnlock: 9
};
let cursorImageI = window.getComputedStyle(document.body).cursor;
let cssCursor = `${cursorImageI === "auto" || !cursorImageI.includes("url") ? `url(${SITE_DEFAULT_CURSOR[window.location.href.split("//")[1].split("/")[0].split(":")[0]]}) 11 11, auto` : cursorImageI}`;
- if (cssCursor.includes("undefined")) {
- cssCursor = "auto";
- }
+ if (cssCursor.includes("undefined")) {
+ cssCursor = "auto";
+ }
console.log("[MP] Injecting custom styles...");
const styles = document.createElement("style");
styles.innerHTML = `
@@ -98,7 +99,7 @@ html {
#otherCursors img {
image-rendering: pixelated;
}
-
+
@keyframes ping {
0% {
scale: 0;
@@ -199,7 +200,7 @@ html {
background-color: rgba(255,255,255,0.15);
}
-.groupui-user p {
+.groupui-user mp_text {
position: absolute;
line-height: 2rem;
margin: 0;
@@ -243,6 +244,98 @@ kbd {
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("");
document.head.appendChild(styles);
@@ -256,12 +349,12 @@ kbd {
const bodyMarginLeft = parseInt(marginComputedStyle.marginLeft.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.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.classList.add("groupui");
groupUIBase.classList.add("grouphidden");
@@ -273,22 +366,26 @@ kbd {
};
groupPopper.innerText = "<";
groupUIBase.appendChild(groupPopper);
- const groupTitle = document.createElement("div");
+ const groupTitle = document.createElement("mp_container");
groupTitle.classList.add("groupui-title");
groupTitle.innerText = "GROUP_NAME";
groupUIBase.appendChild(groupTitle);
- const groupUsers = document.createElement("div");
+ const groupUsers = document.createElement("mp_container");
groupUsers.classList.add("groupui-scrollbox");
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) {
- const user = document.createElement("div");
+ const user = document.createElement("mp_group_user");
user.classList.add("groupui-user");
- const usernameBox = document.createElement("p");
+ const usernameBox = document.createElement("mp_text");
usernameBox.innerText = username;
user.appendChild(usernameBox);
- const buttonBox = document.createElement("div");
+ const buttonBox = document.createElement("mp_container");
buttonBox.classList.add("buttons");
user.appendChild(buttonBox);
@@ -298,20 +395,20 @@ kbd {
const gotoButton = document.createElement("button");
gotoButton.innerText = "Go To";
- const gotoLoc = location;
+ const gotoLoc = location;
gotoButton.onclick = () => {
- window.location.href = `https://${gotoLoc}`;
- }
+ window.location.href = `https://${gotoLoc}`;
+ }
buttonBox.appendChild(gotoButton);
groupUsers.appendChild(user);
}
let clientWidth = document.body.getBoundingClientRect().width;
- let bodyBoundingRect = document.body.getBoundingClientRect();
+ let bodyBoundingRect = document.body.getBoundingClientRect();
setInterval(() => {
- bodyBoundingRect = document.body.getBoundingClientRect();
+ bodyBoundingRect = document.body.getBoundingClientRect();
if (document.body.scrollHeight > window.innerHeight) {
otherCursors.style = `width:${clientWidth = (bodyBoundingRect.width + bodyMarginRight + bodyMarginLeft)}px;height:${document.body.scrollHeight}px;top:-${((window.scrollY + bodyBoundingRect.top) - bodyMarginTop)}px;cursor: ${cssCursor};`;
} else {
@@ -335,7 +432,7 @@ kbd {
}
});
});
-
+
const keepAlivePacket = createWriter(Endian.LE, 1).writeUByte(MessageType.KeepAlive).toBuffer();
let remoteClients = new FunkyArray();
@@ -351,7 +448,7 @@ kbd {
class RemoteClient {
constructor(name, startAfk, isSelfCursor = false) {
this.name = name;
- this.element = document.createElement("div");
+ this.element = document.createElement("mp_cursor");
this.element.style.position = "absolute";
this.element.style.transform = `translate(-50%, -50%)`;
const image = new Image();
@@ -362,12 +459,12 @@ kbd {
image.src = cursorImage;
this.probeImage = 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.innerText = name;
this.element.appendChild(clientName);
if (!isSelfCursor) {
- this.eepy = document.createElement("div");
+ this.eepy = document.createElement("mp_eepy");
this.eepy.className = "eepy";
this.eepy.style = startAfk ? "" : "display:none";
this.element.appendChild(this.eepy);
@@ -424,7 +521,7 @@ kbd {
let selfCursor;
function createPing(x, y) {
- const pingDiv = document.createElement("div");
+ const pingDiv = document.createElement("mp_ping");
pingDiv.className = "ping";
pingDiv.style.top = `${y}px`;
pingDiv.style.left = `${x}px`;
@@ -464,7 +561,7 @@ kbd {
}
window.onscroll = () => {
- bodyBoundingRect = document.body.getBoundingClientRect();
+ bodyBoundingRect = document.body.getBoundingClientRect();
currentMouseX = rawMouseX + window.scrollX;
currentMouseY = rawMouseY + window.scrollY + ((window.scrollY + bodyBoundingRect.top) - bodyMarginTop);
if (selfCursor) {
@@ -515,7 +612,7 @@ kbd {
try {
function animate() {
frameDeltaTime = (performance.now() - timeLastFrame) * 0.001;
-
+
if (ws && ready) {
if (currentMouseX !== oldMouseX || currentMouseY !== oldMouseY) {
if ((performance.now() - lastSendTime) >= 41) {
@@ -530,18 +627,18 @@ kbd {
ws.send(createWriter(Endian.LE, 2).writeUByte(MessageType.HonkShoe).writeBool(isAfkLocal).toBuffer());
}
}
-
+
if ((performance.now() - timeSinceLastPingReset) >= 1000) {
allowedPings = 10;
timeSinceLastPingReset = performance.now();
}
-
+
remoteClients.forEach(remoteUser => {
remoteUser.actualX = lerp(remoteUser.actualX, remoteUser.targetX, 20 * frameDeltaTime);
remoteUser.actualY = lerp(remoteUser.actualY, remoteUser.targetY, 20 * frameDeltaTime);
remoteUser.updateCursor();
});
-
+
requestAnimationFrame(animate);
timeLastFrame = performance.now();
}
@@ -683,6 +780,14 @@ kbd {
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() {
- const bg = document.createElement("div");
+ const bg = document.createElement("mp_container");
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;";
- 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";
bg.appendChild(dialog);
const title = document.createElement("h4");
@@ -721,7 +826,7 @@ kbd {
subtitle.style.marginTop = ".5rem";
dialog.appendChild(subtitle);
- const buttons = document.createElement("div");
+ const buttons = document.createElement("mp_container");
buttons.style.marginTop = "1rem";
const disconnectButton = document.createElement("button");
@@ -764,13 +869,13 @@ kbd {
dialog.appendChild(buttons);
- document.body.appendChild(bg);
+ document.documentElement.appendChild(bg);
}
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;";
- 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";
bg.appendChild(dialog);
const title = document.createElement("h4");
@@ -778,11 +883,11 @@ kbd {
title.style.marginBottom = "0px";
dialog.appendChild(title);
- const updateText = document.createElement("p");
+ const updateText = document.createElement("mp_text");
updateText.innerHTML = `Please click here to update to the latest version.
This takes less than a few seconds to do and ensures you can continue to use MultiProbe.
Current Version: ${USERSCRIPT_VERSION_RAW}
New Version: ${versionNumber}`;
dialog.appendChild(updateText);
- const buttons = document.createElement("div");
+ const buttons = document.createElement("mp_container");
buttons.style.marginTop = "1rem";
const gotIt = document.createElement("button");
@@ -794,7 +899,7 @@ kbd {
dialog.appendChild(buttons);
- document.body.appendChild(bg);
+ document.documentElement.appendChild(bg);
}
function createFirstTimeDialog() {
@@ -802,10 +907,10 @@ kbd {
return;
}
- const bg = document.createElement("div");
+ const bg = document.createElement("mp_container");
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;";
- 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";
bg.appendChild(dialog);
const title = document.createElement("h4");
@@ -833,7 +938,7 @@ kbd {
helpTip.innerHTML = "If you press F1 you can open this help again.";
actionList.appendChild(helpTip);
- const buttons = document.createElement("div");
+ const buttons = document.createElement("mp_container");
buttons.style.marginTop = "1rem";
const gotIt = document.createElement("button");
@@ -847,14 +952,50 @@ kbd {
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 = `${title}`;
+ 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() {
- const bg = document.createElement("div");
+ const bg = document.createElement("mp_container");
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;";
- 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";
bg.appendChild(dialog);
const title = document.createElement("h4");
@@ -883,7 +1024,7 @@ kbd {
password.style.width = "12rem";
password.name = "password";
loginForm.appendChild(password);
- const buttons = document.createElement("div");
+ const buttons = document.createElement("mp_container");
buttons.style.marginTop = "1rem";
loginForm.appendChild(buttons);
const submitButton = document.createElement("button");
@@ -924,7 +1065,7 @@ kbd {
username.disabled = false;
password.disabled = false;
submitButton.disabled = false;
- doNotButton.disabled = false;
+ doNotButton.disabled = false;
}
}).catch(err => {
console.error(err);
@@ -935,7 +1076,7 @@ kbd {
});
}
- document.body.appendChild(bg);
+ document.documentElement.appendChild(bg);
}
const openMenuButton = document.createElement("button");
@@ -948,7 +1089,7 @@ kbd {
createLoginDialog();
}
};
- document.body.appendChild(openMenuButton);
+ document.documentElement.appendChild(openMenuButton);
if (localStorage["mpapikey"] && localStorage["mpapikey"] !== "" && localStorage["mpconnectonload"] === "true") {
doConnect(localStorage["mpapikey"]);
diff --git a/server/enums/MessageType.ts b/server/enums/MessageType.ts
index 7e20a88..68117a1 100644
--- a/server/enums/MessageType.ts
+++ b/server/enums/MessageType.ts
@@ -7,5 +7,6 @@ export enum MessageType {
ClientLeft,
Ping,
GroupData,
- HonkShoe
+ HonkShoe,
+ BadgeUnlock
}
\ No newline at end of file