// ==UserScript== // @name MultiProbe // @namespace https://*.angusnicneven.com/* // @version 20241008.0 // @description Probe with friends! // @author tgpholly // @match https://*.angusnicneven.com/* // @match https://*.heavenonline.xyz/* // @icon https://www.google.com/s2/favicons?sz=64&domain=angusnicneven.com // @grant none // ==/UserScript== let continueRunningScript = true; if (!window.TE_ACTIVE) { if (window.location.href.includes("www.")) { window.location.href = window.location.href.replace("www.", ""); continueRunningScript = false; } let didWeNukeIt = false; function nukeCC() { if (didWeNukeIt) { return; } try { const doWeHaveCC = document.getElementById("cursor-container"); if (doWeHaveCC) { doWeHaveCC.remove(); didWeNukeIt = true; } } catch (e) {} } setInterval(nukeCC, 1000); } const windowLocation = window.location.href; window.multiprobe_debug = false; window.multiprobe_connectLocal = false; const SITE_DEFAULT_CURSOR = { "localhost": "https://angusnicneven.com/cursor/rrw.png", "angusnicneven.com": "https://angusnicneven.com/cursor/rrw.png", "heavenonline.xyz": "https://heavenonline.xyz/core/cursor/frame1.png" }; const SITE_DEFAULT_HOVER_CURSOR = { "localhost": "https://angusnicneven.com/cursor/rrw2.png", "angusnicneven.com": "https://angusnicneven.com/cursor/rrw2.png", "heavenonline.xyz": "https://heavenonline.xyz/core/cursor_hover/frame1.png" }; console.log("[MP] MultiProbe init"); (function() { 'use strict'; // Make sure to change the userscript version too!!!!!!!!!! const USERSCRIPT_VERSION_RAW = "20241008.0"; const USERSCRIPT_VERSION = parseInt(USERSCRIPT_VERSION_RAW.replace(".", "")); if (!continueRunningScript) { return; } // This is a minified version of the code at https://git.eusv.net/tgpholly/bufferStuff/releases/tag/1.5.0 + FunkyArray class BrowserBuffer{constructor(dataOrSize){if(typeof dataOrSize==="number"){this.buffer=new Uint8Array(dataOrSize)}else if(typeof dataOrSize==="object"){this.buffer=new Uint8Array(dataOrSize)}else{this.buffer=new Uint8Array(0)}this.dataView=new DataView(this.buffer.buffer)}static allocUnsafe(size){return this.alloc(size)}static allocUnsafeSlow(size){return this.alloc(size)}static alloc(size){return new BrowserBuffer(size)}static concat(buffers,totalLength){let joinedArrays;if(totalLength!==undefined){joinedArrays=new Uint8Array(totalLength)}else{let arraysLength=0;for(const buffer of buffers){arraysLength+=buffer.length}joinedArrays=new Uint8Array(arraysLength)}let offset=0;for(const buffer of buffers){joinedArrays.set(buffer.buffer,offset);offset+=buffer.length}return new BrowserBuffer(joinedArrays)}static from(data){if(typeof data==="string"){throw new Error("BrowserBuffer does not currently support creating buffers from strings.")}return new BrowserBuffer(data)}static of(){}static isBuffer(){}static isEncoding(){}static byteLength(){}static copyBytesFrom(){}static compare(){}get length(){return this.buffer.length}checkRanged(value,valueName,lowRange,highRange){if(valuehighRange){throw new Error(`The value of "${valueName}" is out of range. It must be >= ${lowRange} and <= ${highRange}. Received ${value}`)}}checkValue(value,low,high){this.checkRanged(value,"value",low,high)}checkOffset(offset){if(offset){this.checkRanged(offset,"offset",0,this.buffer.length-1)}}writeInt8(value,offset){this.checkValue(value,-128,127);this.checkOffset(offset);this.dataView.setInt8(offset,value);return this}writeUInt8(value,offset){this.checkValue(value,0,255);this.checkOffset(offset);this.dataView.setUint8(offset,value);return this}writeInt16LE(value,offset){this.checkValue(value,-32768,32767);this.checkOffset(offset);this.dataView.setInt16(offset,value,true);return this}writeUInt16LE(value,offset){this.checkValue(value,0,65535);this.checkOffset(offset);this.dataView.setUint16(offset,value,true);return this}writeInt32LE(value,offset){this.checkValue(value,-2147483648,2147483647);this.checkOffset(offset);this.dataView.setInt32(offset,value,true);return this}writeUInt32LE(value,offset){this.checkValue(value,0,4294967295);this.checkOffset(offset);this.dataView.setUint32(offset,value,true);return this}writeBigInt64LE(value,offset){if(typeof value==="number"){value=BigInt(value)}this.checkValue(value,-9223372036854775808n,9223372036854775808n);this.checkOffset(offset);this.dataView.setBigInt64(offset,value,true);return this}writeBigUint64LE(value,offset){if(typeof value==="number"){value=BigInt(value)}this.checkValue(value,0n,18446744073709551616n);this.checkOffset(offset);this.dataView.setBigUint64(offset,value,true);return this}writeFloatLE(value,offset){this.checkOffset(offset);this.dataView.setFloat32(offset,value,true);return this}writeDoubleLE(value,offset){this.checkOffset(offset);this.dataView.setFloat64(offset,value,true);return this}writeInt16BE(value,offset){this.checkValue(value,-32768,32767);this.checkOffset(offset);this.dataView.setInt16(offset,value,false);return this}writeUInt16BE(value,offset){this.checkValue(value,0,65535);this.checkOffset(offset);this.dataView.setUint16(offset,value,false);return this}writeInt32BE(value,offset){this.checkValue(value,-2147483648,2147483647);this.checkOffset(offset);this.dataView.setInt32(offset,value,false);return this}writeUInt32BE(value,offset){this.checkValue(value,0,4294967295);this.checkOffset(offset);this.dataView.setUint32(offset,value,false);return this}writeBigInt64BE(value,offset){if(typeof value==="number"){value=BigInt(value)}this.checkValue(value,-(2n**63n),2n**63n);this.checkOffset(offset);this.dataView.setBigInt64(offset,value,false);return this}writeBigUint64BE(value,offset){if(typeof value==="number"){value=BigInt(value)}this.checkValue(value,0n,2n**64n);this.checkOffset(offset);this.dataView.setBigUint64(offset,value,false);return this}writeFloatBE(value,offset){this.checkOffset(offset);this.dataView.setFloat32(offset,value,false);return this}writeDoubleBE(value,offset){this.checkOffset(offset);this.dataView.setFloat64(offset,value,false);return this}readInt8(offset){this.checkOffset(offset);return this.dataView.getInt8(offset)}readUInt8(offset){this.checkOffset(offset);return this.dataView.getUint8(offset)}readInt16LE(offset){this.checkOffset(offset);return this.dataView.getInt16(offset,true)}readUInt16LE(offset){this.checkOffset(offset);return this.dataView.getUint16(offset,true)}readInt32LE(offset){this.checkOffset(offset);return this.dataView.getInt32(offset,true)}readUInt32LE(offset){this.checkOffset(offset);return this.dataView.getUint32(offset,true)}readBigInt64LE(offset){this.checkOffset(offset);return this.dataView.getBigInt64(offset,true)}readBigUint64LE(offset){this.checkOffset(offset);return this.dataView.getBigUint64(offset,true)}readFloatLE(offset){this.checkOffset(offset);return this.dataView.getFloat32(offset,true)}readDoubleLE(offset){this.checkOffset(offset);return this.dataView.getFloat64(offset,true)}readInt16BE(offset){this.checkOffset(offset);return this.dataView.getInt16(offset,false)}readUInt16BE(offset){this.checkOffset(offset);return this.dataView.getUint16(offset,false)}readInt32BE(offset){this.checkOffset(offset);return this.dataView.getInt32(offset,false)}readUInt32BE(offset){this.checkOffset(offset);return this.dataView.getUint32(offset,false)}readBigInt64BE(offset){this.checkOffset(offset);return this.dataView.getBigInt64(offset,false)}readBigUint64BE(offset){this.checkOffset(offset);return this.dataView.getBigUint64(offset,false)}readFloatBE(offset){this.checkOffset(offset);return this.dataView.getFloat32(offset,false)}readDoubleBE(offset){this.checkOffset(offset);return this.dataView.getFloat64(offset,false)}}BrowserBuffer.poolSize=8192;function getBufferClass(){if(typeof Buffer==="undefined"){return BrowserBuffer}else{return Buffer}}class ReaderBase{constructor(buffer){this.buffer=buffer;this.offset=0}get readOffset(){return this.offset}get length(){return this.buffer.length}readBuffer(bytes){const value=this.buffer.subarray(this.offset,this.offset+bytes);this.offset+=bytes;return value}readUint8Array(bytes){const croppedBuffer=this.readBuffer(bytes);const newArray=new Uint8Array(croppedBuffer.length);for(let i=0;i{if(this.items.size===0){return resolve(true)}try{const iterator=this.items.values();let result;while(!(result=iterator.next()).done){await callback(result.value)}resolve(true)}catch(e){reject(e)}}))}} const MessageType = { KeepAlive: 0, ClientDetails: 1, CursorPos: 2, ClientJoined: 3, Clients: 4, ClientLeft: 5, Ping: 6, GroupData: 7, HonkShoe: 8, BadgeUnlock: 9, DEBUG_UnlockAllBadges: 10 }; let cssCursor = ""; let cssHoverCursor = ""; let pageLoadCompleted = true; console.log("[MP] Injecting custom styles..."); const styles = document.createElement("style"); function updateStyles() { let cursorImageI = window.getComputedStyle(document.body).cursor; 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"; } let hoverChangeElement = document.querySelector("a"); if (!hoverChangeElement) { hoverChangeElement = document.querySelector(".probedata"); } if (!hoverChangeElement) { hoverChangeElement = document.createElement("a"); hoverChangeElement.innerText = "css test element"; hoverChangeElement.id = "MULTIPROBE_CSS_TEST_ELEMENT"; hoverChangeElement.style = "display:none"; document.body.appendChild(hoverChangeElement); } let cursorHoverImageI = window.getComputedStyle(hoverChangeElement).cursor; cssHoverCursor = `${cursorHoverImageI === "auto" || !cursorHoverImageI.includes("url") ? `url(${SITE_DEFAULT_HOVER_CURSOR[window.location.href.split("//")[1].split("/")[0].split(":")[0]]}) 11 11, auto` : cursorHoverImageI}`; if (cssHoverCursor.includes("undefined")) { cssHoverCursor = "auto"; } styles.innerHTML = ` html { ${pageLoadCompleted ? `cursor: ${cssCursor};` : ""} } #otherCursors { position: absolute; top:0px; left:0px; width: 100%; height: 100%; z-index: 999999999; pointer-events: none; overflow:hidden; text-shadow: none!important; font-family: Arial,sans-serif; } #otherCursors img { image-rendering: pixelated; } @keyframes ping { 0% { scale: 0; opacity: 1; } 100% { scale: 2; opacity: 0; } } .ping { opacity: 0; position: absolute; animation: ping 2s linear; animation-iteration-count: 1; image-rendering: pixelated; background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAAXVJREFUeJztm8ESwyAIRLX//8/2EjKKmhhFUeDN9NbK7kIybaPerSU0vs9PVbGwUGI4hDb/3meypumcsfDtEhsuGCsv8Pw5Us2UiwXnUvEDnaxOTrQmiXaKRRLjk7qVTRVVEKMCA7WglppX4bjusptmLCJc7uF1pIae5HDXl6ePWKqHu+s18DTMKTK7AAHTNJ5gHiDXepJ5gEzzieaBYe0nmwdePfwWijkKCd0HPnuRZB6oerJLACGx+0DRm01AhOTuA5lH9ROgPgBAw/gDiVf1E2ABcAvYAU3XP3B7Vj8BFgC3AG4sAG4B3FgA3AK4sQC4BeyCpm+D9mswxgLgFrATGu4D9qcoRn0AGMmXgT0ZakXiFNjT4a9ImoJuLxJCsD1Co5w8Bar3CqreLap6v/DSHeM7BdG9Xd4OTPQWdfzTwHZkJhGB0qdY87XmVTiu213Tjs2NfBiRBOGcnoOTmKxbdzHhR2dLVDv5xOmHp59ovVMv0/UHCfuPGCq5foYAAAAASUVORK5CYII="); width: 64px; height: 64px; z-index: -1!important; } .eepy { position: absolute; top: 0; right: 0; width: 64px; height: 64px; image-rendering: pixelated; background: url("data:image/webp;base64,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"); z-index: 1; transform: translate(60px, -60px); } .grouphidden { right: -12rem!important; } .groupui { position: fixed; top: calc(2rem + 6px); right: 0px; height: 25rem; width: 12rem; background-color: black; color: white; z-index:9999998; text-shadow: none!important; font-family: Arial,sans-serif; font-size: unset !important; transition: right .16s ease-in-out; } .groupui-popper { position: absolute; top: -2px; left: -1.5rem; width: 1rem; height: calc(100% - 6px); opacity: 0.25; transition: opacity .16s ease-in-out; background-color: black; border: 1px solid white; color: white; padding: .125rem; line-height: 380px; } .groupui:not(.grouphidden) .groupui-popper, .groupui-popper:hover { opacity: 1; } .groupui-title { position: absolute; top: 0px; left: 0px; width: 100%; text-align: center; height: 2rem; line-height: 2rem; background-color: rgba(255,255,255,0.1); overflow:hidden; } .groupui-scrollbox { position: absolute; top: 2rem; left: 0px; width: 100%; height: calc(100% - 2rem); overflow-y: scroll; font-family: Arial,sans-serif; font-size: unset !important; } .groupui-user { position: relative; width: 100%; height: 2rem; background-color: rgba(255,255,255,0.2); } .groupui-user:nth-child(2n) { background-color: rgba(255,255,255,0.15); } .groupui-user mp_text { position: absolute; line-height: 2rem; margin: 0; margin-left: .5rem; } .groupui-user .buttons { position: absolute; height: 100%; top: 0px; right: 0px; margin-right: .5rem; } .groupui-user .buttons button { margin-left: .5rem; margin-top: .2rem; } kbd { background-color: #eee; border-radius: 3px; border: 1px solid #b4b4b4; box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), 0 2px 0 0 rgba(255, 255, 255, 0.7) inset; color: #333; display: inline-block; font-size: 0.85em; font-weight: 700; line-height: 1; padding: 2px 4px; white-space: nowrap; font-family: Arial,sans-serif; font-size: unset !important; } .mplink, .mplink:visited { color: #d2738a; } .mplink:hover { 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 a { cursor: ${cssHoverCursor}; } 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; } mp_group_user { display: block; } mp_button { display: inline-block; background-color: black; color: white; border: 1px solid white; text-shadow: none!important; font-family: Arial,sans-serif; font-size: unset !important; padding: 4px 8px; margin: 2px; text-align: center; cursor: ${cssHoverCursor}; } .out-of-the-way { opacity: 0.25; transition: opacity .16s ease-in-out; } .out-of-the-way:hover { opacity: 1; } `.split("\n").join("").split("\r").join("").split("\t").join(""); } // Cursed way of detecting heavenonline load if (window.location.href.split("://")[1].split("/")[0] === "heavenonline.xyz") { pageLoadCompleted = false; const oldConsoleLog = console.log; console.log = function(...args) { if (args.length >= 1) { if (args[0].trim() === `Page is ready at ${finished}.`) { console.log = oldConsoleLog; console.log("[MP] Reverted console.log override."); pageLoadCompleted = true; updateStyles(); } } oldConsoleLog(...args); } } else { updateStyles(); } document.head.appendChild(styles); if (!localStorage["mpconnectonload"]) { localStorage["mpconnectonload"] = true; } let marginComputedStyle = window.getComputedStyle(document.body); const bodyMarginTop = parseInt(marginComputedStyle.marginTop.replace("px", "")); const bodyMarginLeft = parseInt(marginComputedStyle.marginLeft.replace("px", "")); const bodyMarginRight = parseInt(marginComputedStyle.marginRight.replace("px", "")); const otherCursors = document.createElement("mp_cursors"); otherCursors.style.top = `-${((window.scrollY + document.body.getBoundingClientRect().top) - bodyMarginTop)}px`; otherCursors.id = "otherCursors"; document.documentElement.appendChild(otherCursors); const groupUIBase = document.createElement("mp_party"); groupUIBase.style = "display:none"; groupUIBase.classList.add("groupui"); groupUIBase.classList.add("grouphidden"); const groupPopper = document.createElement("mp_button"); groupPopper.classList.add("groupui-popper"); groupPopper.onclick = () => { groupUIBase.classList.toggle("grouphidden"); groupPopper.innerText = groupUIBase.classList.contains("grouphidden") ? "<" : ">"; }; groupPopper.innerText = "<"; groupUIBase.appendChild(groupPopper); const groupTitle = document.createElement("mp_container"); groupTitle.classList.add("groupui-title"); groupTitle.innerText = "GROUP_NAME"; groupUIBase.appendChild(groupTitle); const groupUsers = document.createElement("mp_container"); groupUsers.classList.add("groupui-scrollbox"); groupUIBase.appendChild(groupUsers); 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); const popupSound = new Audio("https://eusv.net/kdHl7VYI1XMS4c"); document.documentElement.appendChild(popupSound); function createGroupUser(username, location) { const user = document.createElement("mp_group_user"); user.classList.add("groupui-user"); const usernameBox = document.createElement("mp_text"); usernameBox.innerText = username; user.appendChild(usernameBox); const buttonBox = document.createElement("mp_container"); buttonBox.classList.add("buttons"); user.appendChild(buttonBox); /*const followButton = document.createElement("mp_button"); followButton.innerText = "F"; buttonBox.appendChild(followButton);*/ const gotoButton = document.createElement("mp_button"); gotoButton.innerText = "Go To"; const gotoLoc = location; gotoButton.onclick = () => { window.location.href = `https://${gotoLoc}`; } buttonBox.appendChild(gotoButton); groupUsers.appendChild(user); } let clientWidth = document.body.getBoundingClientRect().width; let bodyBoundingRect = document.body.getBoundingClientRect(); setInterval(() => { 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 { otherCursors.style = `width:${clientWidth = (bodyBoundingRect.width + bodyMarginRight + bodyMarginLeft)}px;height:${window.innerHeight}px;top:-${((window.scrollY + bodyBoundingRect.top) - bodyMarginTop)}px;cursor: ${cssCursor};`; } }, 1000); const debugMessageContainer = document.createElement("mp_container"); debugMessageContainer.style = "position:fixed;top:0;left:0;padding:4px;pointer-events:none;text-shadow: 0px 0px 4px black"; document.documentElement.appendChild(debugMessageContainer); if (window.multiprobe_debug) { const debugText = document.createElement("mp_text"); debugText.innerText = "RUNNING IN DEBUG"; debugMessageContainer.appendChild(debugText); } if (window.multiprobe_connectLocal) { const debugConnectLocal = document.createElement("mp_text"); debugConnectLocal.innerText = "CONNECTED TO DEV SERVER"; debugMessageContainer.appendChild(debugConnectLocal); } let needsToUpdate = false; console.log("[MP] Checking for new versions..."); const versionFetchAddress = windowLocation.replace("127.0.0.1", "localhost").includes("//localhost:") ? "http://localhost:38194/api/version" : "https://multiprobe.eusv.net/api/version"; fetch(versionFetchAddress, { method: "post" }).then(response => { response.text().then(versionNumberRaw => { const versionNumber = parseInt(versionNumberRaw); if (versionNumber > USERSCRIPT_VERSION) { // We're out of date >:( needsToUpdate = true; createUpdateDialog(`${versionNumberRaw.slice(0, versionNumberRaw.length - 1)}.${versionNumberRaw.slice(-1)}`); console.log("[MP] We're out of date :("); } else { console.log("[MP] We're up to date!"); } }); }); const keepAlivePacket = createWriter(Endian.LE, 1).writeUByte(MessageType.KeepAlive).toBuffer(); let remoteClients = new FunkyArray(); let ws; let ready = false; let currentMouseX = 0; let currentMouseY = 0; let oldMouseX = 0; let oldMouseY = 0; let lastSendTime = 0; function unlockAllBadges() { if (ws) { ws.send(createWriter(Endian.LE, 1).writeUByte(MessageType.DEBUG_UnlockAllBadges).toBuffer()); } } window.unlockAllBadges = unlockAllBadges; class RemoteClient { constructor(name, startAfk, isSelfCursor = false) { this.name = name; this.element = document.createElement("mp_cursor"); this.element.style.position = "absolute"; this.element.style.transform = `translate(-50%, -50%)`; const image = new Image(); let cursorImage = window.getComputedStyle(document.body).cursor.replace("url(","").split('"').join("").split("'").join("").split(")")[0]; if (cursorImage === "auto") { cursorImage = "https://angusnicneven.com/cursor/rrw.png"; } image.src = cursorImage; this.probeImage = image; this.element.appendChild(image); 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("mp_eepy"); this.eepy.className = "eepy"; this.eepy.style = startAfk ? "" : "display:none"; this.element.appendChild(this.eepy); } otherCursors.appendChild(this.element); this.targetX = 0; this.targetY = 0; this.actualX = 0; this.actualY = 0; this.oldActualX = 0; this.oldActualY = 0; this.hasBeenMoved = false; this.element.visibility = "hidden"; } setAfk(afkState) { this.eepy.style = afkState ? "" : "display:none"; } rawSetPos(x, y) { if (!this.hasBeenMoved) { this.element.visibility = ""; this.hasBeenMoved = true; } this.targetX = Math.round(x * clientWidth); this.targetY = y; } rawSetPosInit(x, y) { if (!this.hasBeenMoved) { this.element.visibility = ""; this.hasBeenMoved = true; } this.actualX = this.targetX = Math.round(x * clientWidth); this.actualY = this.targetY = y; } updateCursor() { const x = Math.round(this.actualX); const y = Math.round(this.actualY); if (y !== this.oldActualY) { this.element.style.top = `${y}px`; this.oldActualY = y; } if (x !== this.oldActualX) { this.element.style.left = `${x}px`; this.oldActualX = x; } } } let selfCursor; function createPing(x, y) { const pingDiv = document.createElement("mp_ping"); pingDiv.className = "ping"; pingDiv.style.top = `${y}px`; pingDiv.style.left = `${x}px`; otherCursors.appendChild(pingDiv); setTimeout(() => pingDiv.remove(), 2000); } function removeClient(id) { if (remoteClients.has(id)) { const client = remoteClients.get(id); remoteClients.remove(id); client.element.remove(); } } let isAfkLocal = false; let lastSendAfkState = false window.onfocus = (e) => { isAfkLocal = false; } window.onblur = (e) => { isAfkLocal = true; } let rawMouseX = 0; let rawMouseY = 0; window.onmousemove = (e) => { currentMouseX = (rawMouseX = e.clientX) + window.scrollX; currentMouseY = (rawMouseY = e.clientY) + window.scrollY + ((window.scrollY + bodyBoundingRect.top) - bodyMarginTop); if (selfCursor) { selfCursor.rawSetPosInit(currentMouseX / clientWidth, currentMouseY); selfCursor.updateCursor(); } } window.onscroll = () => { bodyBoundingRect = document.body.getBoundingClientRect(); currentMouseX = rawMouseX + window.scrollX; currentMouseY = rawMouseY + window.scrollY + ((window.scrollY + bodyBoundingRect.top) - bodyMarginTop); if (selfCursor) { selfCursor.rawSetPosInit(currentMouseX / clientWidth, currentMouseY); selfCursor.updateCursor(); } } function log(type, text) { const d = new Date(); console.log(`[hNET] [${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}:${String(d.getSeconds()).padStart(2, "0")}.${String(d.getMilliseconds()).padStart(4, "0")}] [${type}] ${text}`); } let allowedPings = 10; window.onkeypress = (e) => { if (e.key === "p") { if (ws && ready) { if (allowedPings > 0) { allowedPings--; ws.send(createWriter(Endian.LE, 9).writeUByte(MessageType.Ping).writeFloat((rawMouseX + window.scrollX - 32) / clientWidth).writeInt(rawMouseY + window.scrollY - 32 + ((window.scrollY + bodyBoundingRect.top) - bodyMarginTop)).toBuffer()); } } } else if (e.key === "n") { if (ws && ready && selfCursor) { localStorage["t00mp_cursorStyle"] = selfCursor.element.style.visibility = selfCursor.element.style.visibility === "hidden" ? "" : "hidden"; } } else if (e.key === "g") { if (ws && ready && selfCursor) { groupPopper.click(); } } } window.onkeydown = (e) => { if (!windowContainer && e.key === "F1") { localStorage["mpshowfirsttime"] = "true"; createFirstTimeDialog(); } }; function lerp(value1, value2, amount) { return value1 + (value2 - value1) * amount; } let timeLastFrame = performance.now(); let frameDeltaTime = 0; let timeSinceLastPingReset = performance.now(); try { function animate() { frameDeltaTime = (performance.now() - timeLastFrame) * 0.001; if (ws && ready) { if (currentMouseX !== oldMouseX || currentMouseY !== oldMouseY) { if ((performance.now() - lastSendTime) >= 41) { lastSendTime = performance.now(); oldMouseX = currentMouseX; oldMouseY = currentMouseY; ws.send(createWriter(Endian.LE, 9).writeUByte(MessageType.CursorPos).writeFloat(oldMouseX / clientWidth).writeInt(currentMouseY).toBuffer()); } } if (isAfkLocal !== lastSendAfkState) { lastSendAfkState = isAfkLocal; 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(); } animate(); } catch (e) { console.error(e); } let windowContainer = null; function doConnect(apiKey) { const Buffer = getBufferClass(); console.log("[MP] Connecting to realtime server..."); ws = new WebSocket((windowLocation.includes("//localhost:") || window.multiprobe_connectLocal) ? "wss://ws.eusv.net/t00mpdev" : "wss://ws.eusv.net/t00mp"); let keepAliveInterval; ws.onopen = () => { console.log("[MP] Connected! Authenticating..."); otherCursors.innerHTML = ""; selfCursor = new RemoteClient(localStorage["t00mp_username"], false, true); selfCursor.probeImage.style.visibility = "hidden"; selfCursor.element.style.visibility = localStorage["t00mp_cursorStyle"] ?? "hidden"; selfCursor.hasBeenMoved = true; const currentPage = windowLocation.split("/").slice(2).join("/"); ws.send(createWriter(Endian.LE, 4 + apiKey.length + currentPage.length) .writeUByte(MessageType.ClientDetails) .writeShortString(apiKey) .writeString(currentPage) .toBuffer()); keepAliveInterval = setInterval(() => { ws.send(keepAlivePacket); }, 5000); } function onMessage(buf) { const reader = createReader(Endian.LE, Buffer.from(buf)); switch (reader.readByte()) { case MessageType.Clients: { const clientCount = reader.readUShort(); for (let i = 0; i < clientCount; i++) { const clientId = reader.readUInt(); const clientName = reader.readShortString(); const clientX = reader.readFloat(); const clientY = reader.readInt(); const isAfk = reader.readBool(); remoteClients.set(clientId, new RemoteClient(clientName, isAfk)).rawSetPosInit(clientX, clientY); } if (window.multiprobe_debug) { log("RECV", `Initial client packet, got ${clientCount} clients.`); } ready = true; if (windowContainer) { windowContainer.remove(); windowContainer = null; } if (!needsToUpdate) { createFirstTimeDialog(); } console.log("[MP] Authenticated!"); break; } case MessageType.ClientJoined: { const clientId = reader.readUInt(); const clientName = reader.readShortString(); remoteClients.set(clientId, new RemoteClient(clientName, false)); if (window.multiprobe_debug) { log("RECV", `New client joined page: ${clientName} ID=${clientId}`); } break; } case MessageType.CursorPos: { const clientId = reader.readUInt(); if (remoteClients.has(clientId)) { const cursorX = reader.readFloat(); const cursorY = reader.readInt(); remoteClients.get(clientId).rawSetPos(cursorX, cursorY); if (window.multiprobe_debug) { log("RECV", `Cursor position update for ${clientId}, X=${cursorX}, Y=${cursorY}`); } } break; } case MessageType.ClientLeft: { const clientId = reader.readUInt(); removeClient(clientId); if (window.multiprobe_debug) { log("RECV", `Client ${clientId} left or switched pages`); } break; } case MessageType.Ping: { const cursorX = reader.readFloat(); const cursorY = reader.readInt(); createPing(cursorX * clientWidth, cursorY); if (window.multiprobe_debug) { log("RECV", `Got a ping, X=${cursorX}, Y=${cursorY}`); } break; } case MessageType.GroupData: { groupUIBase.style = ""; groupUsers.innerHTML = ""; groupTitle.innerText = reader.readShortString(); const groupUserCount = reader.readUShort(); if (window.multiprobe_debug) { log("RECV", `Server sent group information for "${groupTitle.innerText}" (${groupUserCount} clients)`); } for (let i = 0; i < groupUserCount; i++) { const groupUsername = reader.readShortString(); const groupUserLocation = reader.readString(); if (window.multiprobe_debug) { log("RECV", `[GROUP USER] USERNAME=${groupUsername}, LOCATION=${groupUserLocation}`); } createGroupUser(groupUsername, groupUserLocation); } break; } case MessageType.HonkShoe: { const clientId = reader.readUInt(); const isAfk = reader.readBool(); if (remoteClients.has(clientId)) { remoteClients.get(clientId).setAfk(isAfk); if (window.multiprobe_debug) { if (isAfk) { log("RECV", `Client ${clientId} went afk`); } else { log("RECV", `Client ${clientId} is no longer afk`); } } } break; } case MessageType.BadgeUnlock: { const badgeTitle = reader.readString16(); const badgeDescription = reader.readString16(); const badgeIconUrl = reader.readString16(); createBadgePopup(badgeTitle, badgeDescription, badgeIconUrl); } } } ws.onmessage = (e) => { e.data.arrayBuffer().then(onMessage); } function onCloseAndError() { if (keepAliveInterval) { clearInterval(keepAliveInterval); keepAliveInterval = undefined; } ws = undefined; ready = false; setTimeout(() => doConnect(localStorage["mpapikey"]), 5000); } ws.onclose = onCloseAndError; ws.onerror = (e) => { console.error(e); } } function createOnlineDialog() { 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("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"); title.innerText = "MultiProbe"; title.style.marginBottom = "0px"; dialog.appendChild(title); const subtitle = document.createElement("h5"); subtitle.innerText = `Logged in as ${localStorage["t00mp_username"]}`; subtitle.style.marginTop = ".5rem"; dialog.appendChild(subtitle); const buttons = document.createElement("mp_container"); buttons.style.marginTop = "1rem"; const disconnectButton = document.createElement("mp_button"); disconnectButton.innerText = localStorage["mpconnectonload"] === "true" ? "Disconnect" : "Connect"; disconnectButton.onclick = () => { if (localStorage["mpconnectonload"] === "true") { localStorage["mpconnectonload"] = false; if (ws) { ws.close(); } } else { localStorage["mpconnectonload"] = true; //doConnect(localStorage["mpapikey"]); } disconnectButton.innerText = localStorage["mpconnectonload"] === "true" ? "Disconnect" : "Connect"; window.location.reload(); }; buttons.appendChild(disconnectButton); const manageAccountLink = document.createElement("a"); manageAccountLink.style.display = "none"; manageAccountLink.href = "https://multiprobe.eusv.net/"; manageAccountLink.target = "_blank"; buttons.appendChild(manageAccountLink); const manageAccount = document.createElement("mp_button"); manageAccount.style.marginLeft = "1rem"; manageAccount.innerText = "Manage Account"; manageAccount.onclick = () => { manageAccountLink.click(); } buttons.appendChild(manageAccount); const closeButton = document.createElement("mp_button"); closeButton.innerText = "Close"; closeButton.onclick = () => { bg.remove(); windowContainer = null; }; closeButton.style.marginLeft = "1rem"; buttons.appendChild(closeButton); dialog.appendChild(buttons); document.documentElement.appendChild(bg); } function createUpdateDialog(versionNumber) { 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("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"); title.innerText = "An update is available!"; title.style.marginBottom = "0px"; dialog.appendChild(title); 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("mp_container"); buttons.style.marginTop = "1rem"; const gotIt = document.createElement("mp_button"); gotIt.onclick = () => { bg.remove(); } gotIt.innerText = "Later"; buttons.appendChild(gotIt); dialog.appendChild(buttons); document.documentElement.appendChild(bg); } function createFirstTimeDialog() { if (localStorage["mpshowfirsttime"] && localStorage["mpshowfirsttime"] === "false") { return; } 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("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"); title.innerText = "Welcome to MultiProbe!"; title.style.marginBottom = "0px"; dialog.appendChild(title); const actionList = document.createElement("ul"); actionList.style.textAlign = "start"; dialog.appendChild(actionList); const pingLI = document.createElement("li"); pingLI.innerHTML = "You can create a \"ping\" at your cursor position by pressing P"; actionList.appendChild(pingLI); const nameLI = document.createElement("li"); nameLI.innerHTML = "You can show/hide your own name for screenshots by pressing N"; actionList.appendChild(nameLI); const groupLI = document.createElement("li"); groupLI.innerHTML = "You can show/hide the party sidebar if you are in one by pressing G"; actionList.appendChild(groupLI); const helpTip = document.createElement("li"); helpTip.innerHTML = "If you press F1 you can open this help again."; actionList.appendChild(helpTip); const buttons = document.createElement("mp_container"); buttons.style.marginTop = "1rem"; const gotIt = document.createElement("mp_button"); gotIt.onclick = () => { localStorage["mpshowfirsttime"] = "false"; bg.remove(); windowContainer = null; } gotIt.innerText = "Got It"; buttons.appendChild(gotIt); dialog.appendChild(buttons); document.documentElement.appendChild(bg); } const badgeQueue = []; let displaying = false; function createBadgePopup(title, description, image) { if (displaying) { badgeQueue.push([title, description, image]); return; } displaying = true; 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"); setTimeout(() => popupSound.play(), 100); }; 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.innerHTML = 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); displaying = false; if (badgeQueue.length > 0) { const badgeData = badgeQueue.splice(0, 1)[0]; setTimeout(() => createBadgePopup(badgeData[0], badgeData[1], badgeData[2]), 0); } }, 5350); } window.createBadgePopup = createBadgePopup; function createLoginDialog() { 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("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"); title.innerText = "MultiProbe"; title.style.marginBottom = ".5rem"; dialog.appendChild(title); const manageAccountLink = document.createElement("a"); manageAccountLink.className = "mplink"; manageAccountLink.href = "https://multiprobe.eusv.net/"; manageAccountLink.innerHTML = "Click here to create an account

"; manageAccountLink.target = "_blank"; manageAccountLink.style.marginLeft = manageAccountLink.style.marginRight = ".5rem"; dialog.appendChild(manageAccountLink); const loginForm = document.createElement("form"); dialog.appendChild(loginForm); const username = document.createElement("input"); username.placeholder = "Enter Username"; username.maxLength = 32; username.style.width = "12rem"; username.name = "username"; loginForm.appendChild(username); const password = document.createElement("input"); password.type = "password"; password.style.marginTop = ".5rem"; password.placeholder = "Enter Password"; password.style.width = "12rem"; password.name = "password"; loginForm.appendChild(password); const buttons = document.createElement("mp_container"); buttons.style.marginTop = "1rem"; loginForm.appendChild(buttons); const submitButton = document.createElement("mp_button"); submitButton.innerText = "Connect"; buttons.appendChild(submitButton); const doNotButton = document.createElement("mp_button"); doNotButton.innerText = "Close"; doNotButton.onclick = () => bg.remove(); doNotButton.style.marginLeft = "1rem"; buttons.appendChild(doNotButton); function performLogin() { username.disabled = true; password.disabled = true; submitButton.disabled = true; doNotButton.disabled = true; title.innerText = "Authenticating..."; fetch((windowLocation.replace("127.0.0.1", "localhost").includes("//localhost:") || window.multiprobe_connectLocal) ? "http://localhost:38194/api/login" : "https://multiprobe.eusv.net/api/login", { method: "POST", body: `username=${encodeURIComponent(username.value)}&password=${encodeURIComponent(password.value)}`, headers: { "Content-Type": "application/x-www-form-urlencoded" } }).then(res => { if (res.status === 200) { res.text().then(apiKey => { title.innerText = "Connecting to realtime server..."; localStorage["t00mp_username"] = username.value; localStorage["mpapikey"] = apiKey; doConnect(apiKey); }); } else { title.innerText = "Incorrect Login"; username.disabled = false; password.disabled = false; submitButton.disabled = false; doNotButton.disabled = false; } }).catch(err => { console.error(err); username.disabled = false; password.disabled = false; submitButton.disabled = false; doNotButton.disabled = false; }); } submitButton.onclick = () => performLogin(); loginForm.onsubmit = (e) => { e.preventDefault(); performLogin(); } document.documentElement.appendChild(bg); } const openMenuButton = document.createElement("mp_button"); openMenuButton.style = "position:fixed;top:0px;right:0px;z-index:9999999;margin:4px"; openMenuButton.classList.add("out-of-the-way"); openMenuButton.innerText = "MultiProbe"; openMenuButton.onclick = () => { if (ws || localStorage["mpapikey"]) { createOnlineDialog(); } else { createLoginDialog(); } }; document.documentElement.appendChild(openMenuButton); if (localStorage["mpapikey"] && localStorage["mpapikey"] !== "" && localStorage["mpconnectonload"] === "true") { doConnect(localStorage["mpapikey"]); } console.log("[MP] Init complete."); })();