t00-multiuser/client/Terminal-00-Multiuser.user.js

1229 lines
56 KiB
JavaScript
Raw Normal View History

2024-04-18 23:18:49 +01:00
// ==UserScript==
// @name MultiProbe
2024-04-18 23:18:49 +01:00
// @namespace https://*.angusnicneven.com/*
2024-10-03 09:07:44 +01:00
// @version 20241003.1
2024-04-18 23:18:49 +01:00
// @description Probe with friends!
// @author tgpholly
// @match https://*.angusnicneven.com/*
2024-05-27 12:56:49 +01:00
// @match https://*.heavenonline.xyz/*
2024-04-18 23:18:49 +01:00
// @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);
}
2024-05-07 21:46:52 +01:00
const windowLocation = window.location.href;
2024-05-06 15:41:26 +01:00
window.multiprobe_debug = false;
2024-10-02 22:25:08 +01:00
window.multiprobe_connectLocal = false;
2024-05-06 15:41:26 +01:00
2024-05-27 12:56:49 +01:00
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"
};
2024-05-07 22:17:30 +01:00
console.log("[MP] MultiProbe init");
2024-04-18 23:18:49 +01:00
(function() {
'use strict';
2024-04-26 10:21:27 +01:00
// Make sure to change the userscript version too!!!!!!!!!!
2024-10-03 09:07:44 +01:00
const USERSCRIPT_VERSION_RAW = "20241003.1";
2024-04-26 10:21:27 +01:00
const USERSCRIPT_VERSION = parseInt(USERSCRIPT_VERSION_RAW.replace(".", ""));
2024-04-26 03:01:06 +01:00
2024-04-18 23:18:49 +01:00
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(value<lowRange||value>highRange){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}writeDouble
const MessageType = {
KeepAlive: 0,
ClientDetails: 1,
CursorPos: 2,
ClientJoined: 3,
Clients: 4,
ClientLeft: 5,
2024-04-25 02:37:37 +01:00
Ping: 6,
2024-05-27 12:56:49 +01:00
GroupData: 7,
2024-10-02 01:08:03 +01:00
HonkShoe: 8,
BadgeUnlock: 9
2024-04-18 23:18:49 +01:00
};
2024-10-02 21:18:03 +01:00
let cssCursor = "";
let cssHoverCursor = "";
let pageLoadCompleted = true;
2024-05-07 22:17:30 +01:00
console.log("[MP] Injecting custom styles...");
2024-04-18 23:18:49 +01:00
const styles = document.createElement("style");
2024-10-02 21:18:03 +01:00
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");
}
2024-10-02 22:25:08 +01:00
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);
}
2024-10-02 21:18:03 +01:00
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 {
2024-10-02 21:18:03 +01:00
${pageLoadCompleted ? `cursor: ${cssCursor};` : ""}
}
2024-04-18 23:18:49 +01:00
#otherCursors {
position: absolute;
top:0px;
left:0px;
width: 100%;
height: 100%;
z-index: 999999999;
pointer-events: none;
overflow:hidden;
2024-05-07 21:46:52 +01:00
text-shadow: none!important;
font-family: Arial,sans-serif;
2024-04-18 23:18:49 +01:00
}
2024-04-26 16:52:58 +01:00
#otherCursors img {
image-rendering: pixelated;
}
2024-10-02 01:08:03 +01:00
2024-04-18 23:18:49 +01:00
@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;
2024-04-20 17:25:16 +01:00
z-index: -1!important;
2024-04-18 23:18:49 +01:00
}
2024-04-24 00:06:42 +01:00
2024-05-27 12:56:49 +01:00
.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);
}
2024-04-24 00:06:42 +01:00
.grouphidden {
right: -12rem!important;
}
.groupui {
position: fixed;
top: calc(2rem + 6px);
2024-04-24 00:06:42 +01:00
right: 0px;
height: 25rem;
width: 12rem;
background-color: black;
color: white;
z-index:9999998;
2024-05-07 21:46:52 +01:00
text-shadow: none!important;
font-family: Arial,sans-serif;
font-size: unset !important;
transition: right .16s ease-in-out;
2024-04-24 00:06:42 +01:00
}
.groupui-popper {
position: absolute;
top: -2px;
left: -1.5rem;
2024-04-24 00:06:42 +01:00
width: 1rem;
height: calc(100% - 6px);
2024-04-24 00:06:42 +01:00
opacity: 0.25;
transition: opacity .16s ease-in-out;
2024-04-24 00:06:42 +01:00
background-color: black;
border: 1px solid white;
color: white;
padding: .125rem;
line-height: 380px;
}
.groupui:not(.grouphidden) .groupui-popper, .groupui-popper:hover {
opacity: 1;
2024-04-24 00:06:42 +01:00
}
.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);
2024-05-07 21:52:46 +01:00
overflow:hidden;
2024-04-24 00:06:42 +01:00
}
.groupui-scrollbox {
position: absolute;
top: 2rem;
left: 0px;
width: 100%;
height: calc(100% - 2rem);
overflow-y: scroll;
2024-05-07 21:46:52 +01:00
font-family: Arial,sans-serif;
font-size: unset !important;
2024-04-24 00:06:42 +01:00
}
.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);
}
2024-10-02 01:08:03 +01:00
.groupui-user mp_text {
2024-04-24 00:06:42 +01:00
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;
}
2024-04-25 10:12:17 +01:00
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;
2024-05-07 21:46:52 +01:00
font-family: Arial,sans-serif;
font-size: unset !important;
2024-04-25 10:12:17 +01:00
}
2024-04-26 03:01:06 +01:00
.mplink, .mplink:visited {
color: #d2738a;
}
.mplink:hover {
color: #c1b492;
}
2024-10-02 01:08:03 +01:00
@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};
}
2024-10-02 01:08:03 +01:00
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;
}
2024-10-02 12:32:04 +01:00
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;
}
2024-04-18 23:18:49 +01:00
`.split("\n").join("").split("\r").join("").split("\t").join("");
2024-10-02 21:18:03 +01:00
}
// 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();
}
2024-04-18 23:18:49 +01:00
document.head.appendChild(styles);
2024-04-26 03:01:06 +01:00
if (!localStorage["mpconnectonload"]) {
localStorage["mpconnectonload"] = true;
}
2024-05-02 16:33:50 +01:00
2024-05-07 21:46:52 +01:00
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", ""));
2024-10-02 01:08:03 +01:00
const otherCursors = document.createElement("mp_cursors");
2024-05-07 21:46:52 +01:00
otherCursors.style.top = `-${((window.scrollY + document.body.getBoundingClientRect().top) - bodyMarginTop)}px`;
2024-04-18 23:18:49 +01:00
otherCursors.id = "otherCursors";
2024-10-02 01:08:03 +01:00
document.documentElement.appendChild(otherCursors);
2024-04-19 12:03:38 +01:00
2024-10-02 01:08:03 +01:00
const groupUIBase = document.createElement("mp_party");
2024-04-24 00:06:42 +01:00
groupUIBase.style = "display:none";
groupUIBase.classList.add("groupui");
groupUIBase.classList.add("grouphidden");
const groupPopper = document.createElement("mp_button");
2024-04-24 00:06:42 +01:00
groupPopper.classList.add("groupui-popper");
groupPopper.onclick = () => {
groupUIBase.classList.toggle("grouphidden");
groupPopper.innerText = groupUIBase.classList.contains("grouphidden") ? "<" : ">";
};
groupPopper.innerText = "<";
groupUIBase.appendChild(groupPopper);
2024-10-02 01:08:03 +01:00
const groupTitle = document.createElement("mp_container");
2024-04-24 00:06:42 +01:00
groupTitle.classList.add("groupui-title");
groupTitle.innerText = "GROUP_NAME";
groupUIBase.appendChild(groupTitle);
2024-10-02 01:08:03 +01:00
const groupUsers = document.createElement("mp_container");
2024-04-24 00:06:42 +01:00
groupUsers.classList.add("groupui-scrollbox");
groupUIBase.appendChild(groupUsers);
2024-10-02 01:08:03 +01:00
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);
2024-04-24 00:06:42 +01:00
2024-10-02 22:25:08 +01:00
const popupSound = new Audio("https://eusv.net/kdHl7VYI1XMS4c");
document.documentElement.appendChild(popupSound);
2024-04-24 00:06:42 +01:00
function createGroupUser(username, location) {
2024-10-02 01:08:03 +01:00
const user = document.createElement("mp_group_user");
2024-04-24 00:06:42 +01:00
user.classList.add("groupui-user");
2024-10-02 01:08:03 +01:00
const usernameBox = document.createElement("mp_text");
2024-04-24 00:06:42 +01:00
usernameBox.innerText = username;
user.appendChild(usernameBox);
2024-10-02 01:08:03 +01:00
const buttonBox = document.createElement("mp_container");
2024-04-24 00:06:42 +01:00
buttonBox.classList.add("buttons");
user.appendChild(buttonBox);
/*const followButton = document.createElement("mp_button");
2024-04-24 00:06:42 +01:00
followButton.innerText = "F";
2024-04-26 03:01:06 +01:00
buttonBox.appendChild(followButton);*/
2024-04-24 00:06:42 +01:00
const gotoButton = document.createElement("mp_button");
2024-04-26 03:01:06 +01:00
gotoButton.innerText = "Go To";
2024-10-02 01:08:03 +01:00
const gotoLoc = location;
gotoButton.onclick = () => {
2024-10-02 01:08:03 +01:00
window.location.href = `https://${gotoLoc}`;
}
2024-04-24 00:06:42 +01:00
buttonBox.appendChild(gotoButton);
groupUsers.appendChild(user);
}
2024-04-25 02:37:37 +01:00
let clientWidth = document.body.getBoundingClientRect().width;
2024-10-02 01:08:03 +01:00
let bodyBoundingRect = document.body.getBoundingClientRect();
2024-04-20 17:20:23 +01:00
2024-04-19 12:03:38 +01:00
setInterval(() => {
2024-10-02 01:08:03 +01:00
bodyBoundingRect = document.body.getBoundingClientRect();
2024-04-20 17:20:23 +01:00
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};`;
2024-04-20 17:20:23 +01:00
} else {
otherCursors.style = `width:${clientWidth = (bodyBoundingRect.width + bodyMarginRight + bodyMarginLeft)}px;height:${window.innerHeight}px;top:-${((window.scrollY + bodyBoundingRect.top) - bodyMarginTop)}px;cursor: ${cssCursor};`;
2024-04-20 17:20:23 +01:00
}
2024-04-19 12:03:38 +01:00
}, 1000);
2024-04-26 03:01:06 +01:00
2024-10-02 22:25:08 +01:00
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;
2024-05-07 22:17:30 +01:00
console.log("[MP] Checking for new versions...");
2024-05-07 21:46:52 +01:00
const versionFetchAddress = windowLocation.replace("127.0.0.1", "localhost").includes("//localhost:") ? "http://localhost:38194/api/version" : "https://multiprobe.eusv.net/api/version";
2024-04-26 10:38:46 +01:00
fetch(versionFetchAddress, { method: "post" }).then(response => {
2024-04-26 10:21:27 +01:00
response.text().then(versionNumberRaw => {
const versionNumber = parseInt(versionNumberRaw);
if (versionNumber > USERSCRIPT_VERSION) {
// We're out of date >:(
needsToUpdate = true;
2024-04-26 10:21:27 +01:00
createUpdateDialog(`${versionNumberRaw.slice(0, versionNumberRaw.length - 1)}.${versionNumberRaw.slice(-1)}`);
2024-05-07 22:17:30 +01:00
console.log("[MP] We're out of date :(");
} else {
console.log("[MP] We're up to date!");
2024-04-26 03:01:06 +01:00
}
});
2024-04-26 10:21:27 +01:00
});
2024-10-02 01:08:03 +01:00
2024-05-27 12:56:49 +01:00
const keepAlivePacket = createWriter(Endian.LE, 1).writeUByte(MessageType.KeepAlive).toBuffer();
2024-04-18 23:18:49 +01:00
let remoteClients = new FunkyArray();
let ws;
let ready = false;
let currentMouseX = 0;
let currentMouseY = 0;
let oldMouseX = 0;
let oldMouseY = 0;
let lastSendTime = 0;
class RemoteClient {
2024-05-27 12:56:49 +01:00
constructor(name, startAfk, isSelfCursor = false) {
2024-04-18 23:18:49 +01:00
this.name = name;
2024-10-02 01:08:03 +01:00
this.element = document.createElement("mp_cursor");
2024-04-18 23:18:49 +01:00
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;
2024-04-20 17:20:23 +01:00
this.probeImage = image;
2024-04-18 23:18:49 +01:00
this.element.appendChild(image);
2024-10-02 01:08:03 +01:00
const clientName = document.createElement("mp_container");
2024-04-20 17:20:23 +01:00
clientName.style = "position:absolute;left:100%;top:100%;background-color:black;padding:4px 8px;color:white;font-size:12px;font-family:Arial,sans-serif;";
2024-04-18 23:18:49 +01:00
clientName.innerText = name;
this.element.appendChild(clientName);
2024-05-27 12:56:49 +01:00
if (!isSelfCursor) {
2024-10-02 01:08:03 +01:00
this.eepy = document.createElement("mp_eepy");
2024-05-27 12:56:49 +01:00
this.eepy.className = "eepy";
this.eepy.style = startAfk ? "" : "display:none";
this.element.appendChild(this.eepy);
}
2024-04-18 23:18:49 +01:00
otherCursors.appendChild(this.element);
this.targetX = 0;
this.targetY = 0;
this.actualX = 0;
this.actualY = 0;
this.oldActualX = 0;
this.oldActualY = 0;
2024-04-20 17:20:23 +01:00
this.hasBeenMoved = false;
this.element.visibility = "hidden";
2024-04-18 23:18:49 +01:00
}
2024-05-27 12:56:49 +01:00
setAfk(afkState) {
this.eepy.style = afkState ? "" : "display:none";
}
2024-04-18 23:18:49 +01:00
rawSetPos(x, y) {
2024-04-20 17:20:23 +01:00
if (!this.hasBeenMoved) {
this.element.visibility = "";
2024-04-20 17:34:32 +01:00
this.hasBeenMoved = true;
2024-04-20 17:20:23 +01:00
}
this.targetX = Math.round(x * clientWidth);
2024-04-18 23:18:49 +01:00
this.targetY = y;
}
rawSetPosInit(x, y) {
2024-04-20 17:20:23 +01:00
if (!this.hasBeenMoved) {
this.element.visibility = "";
2024-04-20 17:34:32 +01:00
this.hasBeenMoved = true;
2024-04-20 17:20:23 +01:00
}
this.actualX = this.targetX = Math.round(x * clientWidth);
this.actualY = this.targetY = y;
}
2024-04-18 23:18:49 +01:00
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;
}
}
}
2024-04-20 17:20:23 +01:00
let selfCursor;
2024-04-18 23:18:49 +01:00
function createPing(x, y) {
2024-10-02 01:08:03 +01:00
const pingDiv = document.createElement("mp_ping");
2024-04-18 23:18:49 +01:00
pingDiv.className = "ping";
pingDiv.style.top = `${y}px`;
pingDiv.style.left = `${x}px`;
otherCursors.appendChild(pingDiv);
setTimeout(() => pingDiv.remove(), 2000);
2024-04-18 23:18:49 +01:00
}
function removeClient(id) {
if (remoteClients.has(id)) {
const client = remoteClients.get(id);
remoteClients.remove(id);
client.element.remove();
}
}
2024-05-27 12:56:49 +01:00
let isAfkLocal = false;
let lastSendAfkState = false
window.onfocus = (e) => {
isAfkLocal = false;
}
window.onblur = (e) => {
isAfkLocal = true;
}
2024-04-18 23:18:49 +01:00
let rawMouseX = 0;
let rawMouseY = 0;
window.onmousemove = (e) => {
2024-05-02 16:33:50 +01:00
currentMouseX = (rawMouseX = e.clientX) + window.scrollX;
currentMouseY = (rawMouseY = e.clientY) + window.scrollY + ((window.scrollY + bodyBoundingRect.top) - bodyMarginTop);
2024-04-20 17:20:23 +01:00
if (selfCursor) {
selfCursor.rawSetPosInit(currentMouseX / clientWidth, currentMouseY);
selfCursor.updateCursor();
}
2024-04-18 23:18:49 +01:00
}
window.onscroll = () => {
2024-10-02 01:08:03 +01:00
bodyBoundingRect = document.body.getBoundingClientRect();
2024-05-02 16:33:50 +01:00
currentMouseX = rawMouseX + window.scrollX;
currentMouseY = rawMouseY + window.scrollY + ((window.scrollY + bodyBoundingRect.top) - bodyMarginTop);
2024-04-20 17:20:23 +01:00
if (selfCursor) {
selfCursor.rawSetPosInit(currentMouseX / clientWidth, currentMouseY);
selfCursor.updateCursor();
}
2024-04-18 23:18:49 +01:00
}
2024-05-27 12:56:49 +01:00
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}`);
}
2024-05-06 15:41:26 +01:00
2024-04-20 17:20:23 +01:00
let allowedPings = 10;
2024-04-18 23:18:49 +01:00
window.onkeypress = (e) => {
if (e.key === "p") {
if (ws && ready) {
2024-04-20 17:20:23 +01:00
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());
2024-04-20 17:20:23 +01:00
}
2024-04-18 23:18:49 +01:00
}
2024-04-20 17:34:32 +01:00
} 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();
}
2024-04-18 23:18:49 +01:00
}
}
2024-05-07 21:46:52 +01:00
window.onkeydown = (e) => {
if (!windowContainer && e.key === "F1") {
localStorage["mpshowfirsttime"] = "true";
createFirstTimeDialog();
}
};
2024-04-18 23:18:49 +01:00
function lerp(value1, value2, amount) {
return value1 + (value2 - value1) * amount;
}
let timeLastFrame = performance.now();
let frameDeltaTime = 0;
2024-04-20 17:20:23 +01:00
let timeSinceLastPingReset = performance.now();
2024-05-08 01:02:18 +01:00
try {
function animate() {
frameDeltaTime = (performance.now() - timeLastFrame) * 0.001;
2024-10-02 01:08:03 +01:00
2024-05-08 01:02:18 +01:00
if (ws && ready) {
if (currentMouseX !== oldMouseX || currentMouseY !== oldMouseY) {
if ((performance.now() - lastSendTime) >= 41) {
lastSendTime = performance.now();
oldMouseX = currentMouseX;
oldMouseY = currentMouseY;
2024-05-27 12:56:49 +01:00
ws.send(createWriter(Endian.LE, 9).writeUByte(MessageType.CursorPos).writeFloat(oldMouseX / clientWidth).writeInt(currentMouseY).toBuffer());
2024-05-08 01:02:18 +01:00
}
2024-04-18 23:18:49 +01:00
}
2024-05-27 12:56:49 +01:00
if (isAfkLocal !== lastSendAfkState) {
lastSendAfkState = isAfkLocal;
ws.send(createWriter(Endian.LE, 2).writeUByte(MessageType.HonkShoe).writeBool(isAfkLocal).toBuffer());
}
2024-04-18 23:18:49 +01:00
}
2024-10-02 01:08:03 +01:00
2024-05-08 01:02:18 +01:00
if ((performance.now() - timeSinceLastPingReset) >= 1000) {
allowedPings = 10;
timeSinceLastPingReset = performance.now();
}
2024-10-02 01:08:03 +01:00
2024-05-08 01:02:18 +01:00
remoteClients.forEach(remoteUser => {
remoteUser.actualX = lerp(remoteUser.actualX, remoteUser.targetX, 20 * frameDeltaTime);
remoteUser.actualY = lerp(remoteUser.actualY, remoteUser.targetY, 20 * frameDeltaTime);
remoteUser.updateCursor();
});
2024-10-02 01:08:03 +01:00
2024-05-08 01:02:18 +01:00
requestAnimationFrame(animate);
timeLastFrame = performance.now();
2024-04-18 23:18:49 +01:00
}
2024-05-08 01:02:18 +01:00
animate();
} catch (e) {
console.error(e);
2024-04-18 23:18:49 +01:00
}
2024-04-25 10:12:17 +01:00
let windowContainer = null;
function doConnect(apiKey) {
const Buffer = getBufferClass();
2024-05-07 22:17:30 +01:00
console.log("[MP] Connecting to realtime server...");
2024-10-02 22:25:08 +01:00
ws = new WebSocket((windowLocation.includes("//localhost:") || window.multiprobe_connectLocal) ? "wss://ws.eusv.net/t00mpdev" : "wss://ws.eusv.net/t00mp");
2024-04-25 10:12:17 +01:00
let keepAliveInterval;
ws.onopen = () => {
2024-05-07 22:17:30 +01:00
console.log("[MP] Connected! Authenticating...");
2024-04-25 10:12:17 +01:00
otherCursors.innerHTML = "";
2024-05-27 12:56:49 +01:00
selfCursor = new RemoteClient(localStorage["t00mp_username"], false, true);
2024-04-25 10:12:17 +01:00
selfCursor.probeImage.style.visibility = "hidden";
selfCursor.element.style.visibility = localStorage["t00mp_cursorStyle"] ?? "hidden";
selfCursor.hasBeenMoved = true;
2024-05-27 12:56:49 +01:00
const currentPage = windowLocation.split("/").slice(2).join("/");
2024-04-25 10:12:17 +01:00
ws.send(createWriter(Endian.LE, 4 + apiKey.length + currentPage.length)
2024-05-27 12:56:49 +01:00
.writeUByte(MessageType.ClientDetails)
2024-04-25 10:12:17 +01:00
.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();
2024-05-27 12:56:49 +01:00
const isAfk = reader.readBool();
remoteClients.set(clientId, new RemoteClient(clientName, isAfk)).rawSetPosInit(clientX, clientY);
2024-04-25 10:12:17 +01:00
}
2024-05-06 15:41:26 +01:00
if (window.multiprobe_debug) {
log("RECV", `Initial client packet, got ${clientCount} clients.`);
}
2024-04-25 10:12:17 +01:00
ready = true;
if (windowContainer) {
windowContainer.remove();
windowContainer = null;
}
if (!needsToUpdate) {
createFirstTimeDialog();
}
2024-05-07 22:17:30 +01:00
console.log("[MP] Authenticated!");
2024-04-25 10:12:17 +01:00
break;
}
case MessageType.ClientJoined:
{
const clientId = reader.readUInt();
const clientName = reader.readShortString();
2024-05-27 12:56:49 +01:00
remoteClients.set(clientId, new RemoteClient(clientName, false));
2024-05-06 15:41:26 +01:00
if (window.multiprobe_debug) {
2024-05-27 12:56:49 +01:00
log("RECV", `New client joined page: ${clientName} ID=${clientId}`);
2024-05-06 15:41:26 +01:00
}
2024-04-25 10:12:17 +01:00
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);
2024-05-06 15:41:26 +01:00
if (window.multiprobe_debug) {
2024-05-27 12:56:49 +01:00
log("RECV", `Cursor position update for ${clientId}, X=${cursorX}, Y=${cursorY}`);
2024-05-06 15:41:26 +01:00
}
2024-04-25 10:12:17 +01:00
}
break;
}
case MessageType.ClientLeft:
2024-04-18 23:18:49 +01:00
{
const clientId = reader.readUInt();
removeClient(clientId);
2024-05-06 15:41:26 +01:00
if (window.multiprobe_debug) {
2024-05-27 12:56:49 +01:00
log("RECV", `Client ${clientId} left or switched pages`);
2024-05-06 15:41:26 +01:00
}
2024-04-25 10:12:17 +01:00
break;
2024-04-18 23:18:49 +01:00
}
case MessageType.Ping:
{
const cursorX = reader.readFloat();
const cursorY = reader.readInt();
2024-04-20 17:20:23 +01:00
createPing(cursorX * clientWidth, cursorY);
2024-05-06 15:41:26 +01:00
if (window.multiprobe_debug) {
2024-05-27 12:56:49 +01:00
log("RECV", `Got a ping, X=${cursorX}, Y=${cursorY}`);
2024-05-06 15:41:26 +01:00
}
2024-04-25 10:12:17 +01:00
break;
}
case MessageType.GroupData:
{
2024-04-26 03:01:06 +01:00
groupUIBase.style = "";
groupUsers.innerHTML = "";
groupTitle.innerText = reader.readShortString();
2024-05-27 12:56:49 +01:00
const groupUserCount = reader.readUShort();
2024-05-06 15:41:26 +01:00
if (window.multiprobe_debug) {
2024-05-27 12:56:49 +01:00
log("RECV", `Server sent group information for "${groupTitle.innerText}" (${groupUserCount} clients)`);
2024-05-06 15:41:26 +01:00
}
2024-04-26 03:01:06 +01:00
for (let i = 0; i < groupUserCount; i++) {
const groupUsername = reader.readShortString();
const groupUserLocation = reader.readString();
2024-05-06 15:41:26 +01:00
if (window.multiprobe_debug) {
2024-05-27 12:56:49 +01:00
log("RECV", `[GROUP USER] USERNAME=${groupUsername}, LOCATION=${groupUserLocation}`);
2024-05-06 15:41:26 +01:00
}
2024-04-26 03:01:06 +01:00
createGroupUser(groupUsername, groupUserLocation);
}
2024-04-25 10:12:17 +01:00
break;
2024-04-18 23:18:49 +01:00
}
2024-05-27 12:56:49 +01:00
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;
}
2024-10-02 01:08:03 +01:00
case MessageType.BadgeUnlock:
{
const badgeTitle = reader.readString16();
const badgeDescription = reader.readString16();
const badgeIconUrl = reader.readString16();
2024-10-02 01:08:03 +01:00
createBadgePopup(badgeTitle, badgeDescription, badgeIconUrl);
}
2024-04-18 23:18:49 +01:00
}
}
ws.onmessage = (e) => {
e.data.arrayBuffer().then(onMessage);
}
function onCloseAndError() {
if (keepAliveInterval) {
clearInterval(keepAliveInterval);
keepAliveInterval = undefined;
}
ws = undefined;
ready = false;
2024-04-25 02:37:37 +01:00
setTimeout(() => doConnect(localStorage["mpapikey"]), 5000);
2024-04-18 23:18:49 +01:00
}
ws.onclose = onCloseAndError;
2024-05-08 01:02:18 +01:00
ws.onerror = (e) => {
console.error(e);
}
2024-04-18 23:18:49 +01:00
}
2024-04-25 10:12:17 +01:00
function createOnlineDialog() {
2024-10-02 01:08:03 +01:00
const bg = document.createElement("mp_container");
2024-04-25 10:12:17 +01:00
windowContainer = bg;
2024-05-07 21:46:52 +01:00
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;";
2024-10-02 01:08:03 +01:00
const dialog = document.createElement("mp_container");
2024-04-25 10:12:17 +01:00
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);
2024-10-02 01:08:03 +01:00
const buttons = document.createElement("mp_container");
2024-04-25 10:12:17 +01:00
buttons.style.marginTop = "1rem";
const disconnectButton = document.createElement("mp_button");
2024-04-26 03:01:06 +01:00
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"]);
2024-04-26 03:01:06 +01:00
}
disconnectButton.innerText = localStorage["mpconnectonload"] === "true" ? "Disconnect" : "Connect";
window.location.reload();
2024-04-26 03:01:06 +01:00
};
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");
2024-04-26 03:01:06 +01:00
manageAccount.style.marginLeft = "1rem";
manageAccount.innerText = "Manage Account";
manageAccount.onclick = () => {
manageAccountLink.click();
}
buttons.appendChild(manageAccount);
const closeButton = document.createElement("mp_button");
2024-04-26 03:01:06 +01:00
closeButton.innerText = "Close";
closeButton.onclick = () => {
bg.remove();
windowContainer = null;
};
closeButton.style.marginLeft = "1rem";
buttons.appendChild(closeButton);
2024-04-25 10:12:17 +01:00
dialog.appendChild(buttons);
2024-10-02 01:08:03 +01:00
document.documentElement.appendChild(bg);
2024-04-25 10:12:17 +01:00
}
2024-04-26 10:21:27 +01:00
function createUpdateDialog(versionNumber) {
2024-10-02 01:08:03 +01:00
const bg = document.createElement("mp_container");
2024-05-07 21:46:52 +01:00
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;";
2024-10-02 01:08:03 +01:00
const dialog = document.createElement("mp_container");
2024-04-26 10:21:27 +01:00
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);
2024-10-02 01:08:03 +01:00
const updateText = document.createElement("mp_text");
2024-04-26 10:21:27 +01:00
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);
2024-10-02 01:08:03 +01:00
const buttons = document.createElement("mp_container");
2024-04-26 10:21:27 +01:00
buttons.style.marginTop = "1rem";
const gotIt = document.createElement("mp_button");
2024-04-26 10:21:27 +01:00
gotIt.onclick = () => {
bg.remove();
}
gotIt.innerText = "Later";
buttons.appendChild(gotIt);
dialog.appendChild(buttons);
2024-10-02 01:08:03 +01:00
document.documentElement.appendChild(bg);
2024-04-26 10:21:27 +01:00
}
2024-04-25 10:12:17 +01:00
function createFirstTimeDialog() {
if (localStorage["mpshowfirsttime"] && localStorage["mpshowfirsttime"] === "false") {
return;
}
2024-10-02 01:08:03 +01:00
const bg = document.createElement("mp_container");
2024-04-25 10:12:17 +01:00
windowContainer = bg;
2024-05-07 21:46:52 +01:00
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;";
2024-10-02 01:08:03 +01:00
const dialog = document.createElement("mp_container");
2024-04-25 10:12:17 +01:00
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 <kbd>P</kbd>";
actionList.appendChild(pingLI);
const nameLI = document.createElement("li");
nameLI.innerHTML = "You can show/hide your own name for screenshots by pressing <kbd>N</kbd>";
actionList.appendChild(nameLI);
const groupLI = document.createElement("li");
groupLI.innerHTML = "You can show/hide the party sidebar if you are in one by pressing <kbd>G</kbd>";
actionList.appendChild(groupLI);
2024-05-07 21:46:52 +01:00
const helpTip = document.createElement("li");
helpTip.innerHTML = "If you press <kbd>F1</kbd> you can open this help again.";
actionList.appendChild(helpTip);
2024-10-02 01:08:03 +01:00
const buttons = document.createElement("mp_container");
2024-04-25 10:12:17 +01:00
buttons.style.marginTop = "1rem";
const gotIt = document.createElement("mp_button");
2024-04-25 10:12:17 +01:00
gotIt.onclick = () => {
localStorage["mpshowfirsttime"] = "false";
bg.remove();
windowContainer = null;
}
gotIt.innerText = "Got It";
buttons.appendChild(gotIt);
dialog.appendChild(buttons);
2024-10-02 01:08:03 +01:00
document.documentElement.appendChild(bg);
}
2024-10-02 22:25:08 +01:00
const badgeQueue = [];
let displaying = false;
2024-10-02 01:08:03 +01:00
function createBadgePopup(title, description, image) {
2024-10-02 22:25:08 +01:00
if (displaying) {
badgeQueue.push([title, description, image]);
return;
}
displaying = true;
2024-10-02 01:08:03 +01:00
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");
2024-10-02 22:25:08 +01:00
setTimeout(() => popupSound.play(), 100);
2024-10-02 01:08:03 +01:00
};
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.innerHTML = description;
2024-10-02 01:08:03 +01:00
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);
2024-10-02 22:25:08 +01:00
displaying = false;
if (badgeQueue.length > 0) {
const badgeData = badgeQueue.splice(0, 1)[0];
setTimeout(() => createBadgePopup(badgeData[0], badgeData[1], badgeData[2]), 0);
}
2024-10-02 01:08:03 +01:00
}, 5350);
2024-04-25 10:12:17 +01:00
}
2024-10-02 22:25:08 +01:00
window.createBadgePopup = createBadgePopup;
2024-04-25 10:12:17 +01:00
2024-04-25 02:37:37 +01:00
function createLoginDialog() {
2024-10-02 01:08:03 +01:00
const bg = document.createElement("mp_container");
2024-04-25 10:12:17 +01:00
windowContainer = bg;
2024-05-07 21:46:52 +01:00
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;";
2024-10-02 01:08:03 +01:00
const dialog = document.createElement("mp_container");
2024-04-25 02:37:37 +01:00
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";
2024-04-18 23:18:49 +01:00
bg.appendChild(dialog);
const title = document.createElement("h4");
2024-04-25 02:37:37 +01:00
title.innerText = "MultiProbe";
2024-04-26 03:01:06 +01:00
title.style.marginBottom = ".5rem";
2024-04-18 23:18:49 +01:00
dialog.appendChild(title);
2024-04-26 03:01:06 +01:00
const manageAccountLink = document.createElement("a");
manageAccountLink.className = "mplink";
manageAccountLink.href = "https://multiprobe.eusv.net/";
manageAccountLink.innerHTML = "Click here to create an account<br><br>";
manageAccountLink.target = "_blank";
manageAccountLink.style.marginLeft = manageAccountLink.style.marginRight = ".5rem";
dialog.appendChild(manageAccountLink);
2024-04-25 02:37:37 +01:00
const loginForm = document.createElement("form");
dialog.appendChild(loginForm);
2024-04-18 23:18:49 +01:00
const username = document.createElement("input");
username.placeholder = "Enter Username";
username.maxLength = 32;
username.style.width = "12rem";
2024-04-25 02:37:37 +01:00
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);
2024-10-02 01:08:03 +01:00
const buttons = document.createElement("mp_container");
2024-04-18 23:18:49 +01:00
buttons.style.marginTop = "1rem";
2024-04-25 02:37:37 +01:00
loginForm.appendChild(buttons);
const submitButton = document.createElement("mp_button");
2024-04-25 02:37:37 +01:00
submitButton.innerText = "Connect";
2024-04-18 23:18:49 +01:00
buttons.appendChild(submitButton);
const doNotButton = document.createElement("mp_button");
2024-04-18 23:18:49 +01:00
doNotButton.innerText = "Close";
doNotButton.onclick = () => bg.remove();
doNotButton.style.marginLeft = "1rem";
buttons.appendChild(doNotButton);
2024-04-25 02:37:37 +01:00
2024-10-03 09:07:44 +01:00
function performLogin() {
2024-04-25 02:37:37 +01:00
username.disabled = true;
password.disabled = true;
submitButton.disabled = true;
doNotButton.disabled = true;
2024-04-25 10:12:17 +01:00
title.innerText = "Authenticating...";
2024-10-02 22:25:08 +01:00
fetch((windowLocation.replace("127.0.0.1", "localhost").includes("//localhost:") || window.multiprobe_connectLocal) ? "http://localhost:38194/api/login" : "https://multiprobe.eusv.net/api/login", {
2024-04-25 02:37:37 +01:00
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 => {
2024-04-25 10:12:17 +01:00
title.innerText = "Connecting to realtime server...";
2024-04-25 02:37:37 +01:00
localStorage["t00mp_username"] = username.value;
localStorage["mpapikey"] = apiKey;
doConnect(apiKey);
});
} else {
2024-04-25 10:12:17 +01:00
title.innerText = "Incorrect Login";
2024-04-25 02:37:37 +01:00
username.disabled = false;
password.disabled = false;
submitButton.disabled = false;
2024-10-02 01:08:03 +01:00
doNotButton.disabled = false;
2024-04-25 02:37:37 +01:00
}
}).catch(err => {
console.error(err);
username.disabled = false;
password.disabled = false;
submitButton.disabled = false;
doNotButton.disabled = false;
});
}
2024-10-03 09:07:44 +01:00
submitButton.onclick = () => performLogin();
loginForm.onsubmit = (e) => {
e.preventDefault();
performLogin();
}
2024-10-02 01:08:03 +01:00
document.documentElement.appendChild(bg);
2024-04-18 23:18:49 +01:00
}
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";
2024-04-25 10:12:17 +01:00
openMenuButton.onclick = () => {
2024-04-26 03:01:06 +01:00
if (ws || localStorage["mpapikey"]) {
2024-04-25 10:12:17 +01:00
createOnlineDialog();
} else {
createLoginDialog();
}
};
2024-10-02 01:08:03 +01:00
document.documentElement.appendChild(openMenuButton);
2024-04-18 23:18:49 +01:00
2024-04-26 03:01:06 +01:00
if (localStorage["mpapikey"] && localStorage["mpapikey"] !== "" && localStorage["mpconnectonload"] === "true") {
2024-04-25 02:37:37 +01:00
doConnect(localStorage["mpapikey"]);
2024-04-18 23:18:49 +01:00
}
2024-05-07 22:17:30 +01:00
console.log("[MP] Init complete.");
2024-04-18 23:18:49 +01:00
})();