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