diff --git a/client/Terminal-00-Multiuser.user.js b/client/Terminal-00-Multiuser.user.js index cc84b66..21382f1 100644 --- a/client/Terminal-00-Multiuser.user.js +++ b/client/Terminal-00-Multiuser.user.js @@ -86,6 +86,7 @@ if (!window.TE_ACTIVE) { background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAAXVJREFUeJztm8ESwyAIRLX//8/2EjKKmhhFUeDN9NbK7kIybaPerSU0vs9PVbGwUGI4hDb/3meypumcsfDtEhsuGCsv8Pw5Us2UiwXnUvEDnaxOTrQmiXaKRRLjk7qVTRVVEKMCA7WglppX4bjusptmLCJc7uF1pIae5HDXl6ePWKqHu+s18DTMKTK7AAHTNJ5gHiDXepJ5gEzzieaBYe0nmwdePfwWijkKCd0HPnuRZB6oerJLACGx+0DRm01AhOTuA5lH9ROgPgBAw/gDiVf1E2ABcAvYAU3XP3B7Vj8BFgC3AG4sAG4B3FgA3AK4sQC4BeyCpm+D9mswxgLgFrATGu4D9qcoRn0AGMmXgT0ZakXiFNjT4a9ImoJuLxJCsD1Co5w8Bar3CqreLap6v/DSHeM7BdG9Xd4OTPQWdfzTwHZkJhGB0qdY87XmVTiu213Tjs2NfBiRBOGcnoOTmKxbdzHhR2dLVDv5xOmHp59ovVMv0/UHCfuPGCq5foYAAAAASUVORK5CYII="); width: 64px; height: 64px; + z-index: 999999998; } `.split("\n").join("").split("\r").join("").split("\t").join(""); document.head.appendChild(styles); @@ -94,8 +95,14 @@ if (!window.TE_ACTIVE) { otherCursors.id = "otherCursors"; document.body.appendChild(otherCursors); + let clientWidth = document.body.getBoundingClientRect().width + setInterval(() => { - otherCursors.style = `width:${window.innerWidth}px;height:${document.body.scrollHeight}px`; + if (document.body.scrollHeight > window.innerHeight) { + otherCursors.style = `width:${clientWidth = document.body.getBoundingClientRect().width}px;height:${document.body.scrollHeight}px`; + } else { + otherCursors.style = `width:${clientWidth = document.body.getBoundingClientRect().width}px;height:${window.innerHeight}px`; + } }, 1000); const keepAlivePacket = createWriter(Endian.LE, 1).writeByte(MessageType.KeepAlive).toBuffer(); @@ -126,9 +133,10 @@ if (!window.TE_ACTIVE) { cursorImage = "https://angusnicneven.com/cursor/rrw.png"; } image.src = cursorImage; + this.probeImage = image; this.element.appendChild(image); const clientName = document.createElement("div"); - clientName.style = "position:absolute;left:100%;top:100%;background-color:black;padding:4px 8px;color:white;font-size:12px"; + 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); otherCursors.appendChild(this.element); @@ -138,15 +146,25 @@ if (!window.TE_ACTIVE) { this.actualY = 0; this.oldActualX = 0; this.oldActualY = 0; + this.hasBeenMoved = false; + this.element.visibility = "hidden"; } rawSetPos(x, y) { - this.targetX = Math.round(x * window.innerWidth); + if (!this.hasBeenMoved) { + this.element.visibility = ""; + } + + this.targetX = Math.round(x * clientWidth); this.targetY = y; } rawSetPosInit(x, y) { - this.actualX = this.targetX = Math.round(x * window.innerWidth); + if (!this.hasBeenMoved) { + this.element.visibility = ""; + } + + this.actualX = this.targetX = Math.round(x * clientWidth); this.actualY = this.targetY = y; } @@ -164,6 +182,8 @@ if (!window.TE_ACTIVE) { } } + let selfCursor; + function createPing(x, y) { const pingDiv = document.createElement("div"); pingDiv.className = "ping"; @@ -187,17 +207,29 @@ if (!window.TE_ACTIVE) { window.onmousemove = (e) => { currentMouseX = (rawMouseX = e.clientX) + document.body.scrollLeft; currentMouseY = (rawMouseY = e.clientY) + document.body.scrollTop; + if (selfCursor) { + selfCursor.rawSetPosInit(currentMouseX / clientWidth, currentMouseY); + selfCursor.updateCursor(); + } } window.onscroll = () => { currentMouseX = rawMouseX + document.body.scrollLeft; currentMouseY = rawMouseY + document.body.scrollTop; + if (selfCursor) { + selfCursor.rawSetPosInit(currentMouseX / clientWidth, currentMouseY); + selfCursor.updateCursor(); + } } + let allowedPings = 10; window.onkeypress = (e) => { if (e.key === "p") { if (ws && ready) { - ws.send(createWriter(Endian.LE, 9).writeByte(MessageType.Ping).writeFloat((rawMouseX + document.body.scrollLeft - 32) / window.innerWidth).writeInt(rawMouseY + document.body.scrollTop - 32).toBuffer()); + if (allowedPings > 0) { + allowedPings--; + ws.send(createWriter(Endian.LE, 9).writeByte(MessageType.Ping).writeFloat((rawMouseX + document.body.scrollLeft - 32) / clientWidth).writeInt(rawMouseY + document.body.scrollTop - 32).toBuffer()); + } } } } @@ -208,6 +240,7 @@ if (!window.TE_ACTIVE) { let timeLastFrame = performance.now(); let frameDeltaTime = 0; + let timeSinceLastPingReset = performance.now(); function animate() { frameDeltaTime = (performance.now() - timeLastFrame) * 0.001; @@ -217,11 +250,16 @@ if (!window.TE_ACTIVE) { lastSendTime = performance.now(); oldMouseX = currentMouseX; oldMouseY = currentMouseY; - ws.send(createWriter(Endian.LE, 9).writeByte(MessageType.CursorPos).writeFloat(oldMouseX / window.innerWidth).writeInt(currentMouseY).toBuffer()); + ws.send(createWriter(Endian.LE, 9).writeByte(MessageType.CursorPos).writeFloat(oldMouseX / clientWidth).writeInt(currentMouseY).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); @@ -236,9 +274,11 @@ if (!window.TE_ACTIVE) { function doConnect() { const Buffer = getBufferClass(); - ws = new WebSocket(window.location.href.includes("localhost") ? "ws://localhost:38195" : "wss://ws.eusv.net/t00mp"); + ws = new WebSocket(window.location.href.includes("//localhost:") ? "ws://localhost:38195" : "wss://ws.eusv.net/t00mp"); let keepAliveInterval; ws.onopen = () => { + selfCursor = new RemoteClient(username); + selfCursor.probeImage.style.visibility = "hidden"; const currentPage = window.location.href.split("/").slice(3).join("/"); ws.send(createWriter(Endian.LE, 4 + username.length + currentPage.length).writeByte(MessageType.ClientDetails).writeShortString(username).writeString(currentPage).toBuffer()); keepAliveInterval = setInterval(() => { @@ -288,7 +328,7 @@ if (!window.TE_ACTIVE) { { const cursorX = reader.readFloat(); const cursorY = reader.readInt(); - createPing(cursorX * window.innerWidth, cursorY); + createPing(cursorX * clientWidth, cursorY); } } } @@ -347,7 +387,7 @@ if (!window.TE_ACTIVE) { buttons.style.marginTop = "1rem"; dialog.appendChild(buttons); const submitButton = document.createElement("button"); - submitButton.innerText = (localStorage["t00mp_username"] && localStorage["t00mp_username"] === "") ? "Connect" : "Change Username"; + submitButton.innerText = (!localStorage["t00mp_username"] || localStorage["t00mp_username"] === "") ? "Connect" : "Change Username"; submitButton.onclick = () => submitFunction(null); buttons.appendChild(submitButton); if (localStorage["t00mp_username"] !== "") {