Compare commits

...

2 commits

3 changed files with 74 additions and 16 deletions

View file

@ -86,6 +86,7 @@ if (!window.TE_ACTIVE) {
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAAXVJREFUeJztm8ESwyAIRLX//8/2EjKKmhhFUeDN9NbK7kIybaPerSU0vs9PVbGwUGI4hDb/3meypumcsfDtEhsuGCsv8Pw5Us2UiwXnUvEDnaxOTrQmiXaKRRLjk7qVTRVVEKMCA7WglppX4bjusptmLCJc7uF1pIae5HDXl6ePWKqHu+s18DTMKTK7AAHTNJ5gHiDXepJ5gEzzieaBYe0nmwdePfwWijkKCd0HPnuRZB6oerJLACGx+0DRm01AhOTuA5lH9ROgPgBAw/gDiVf1E2ABcAvYAU3XP3B7Vj8BFgC3AG4sAG4B3FgA3AK4sQC4BeyCpm+D9mswxgLgFrATGu4D9qcoRn0AGMmXgT0ZakXiFNjT4a9ImoJuLxJCsD1Co5w8Bar3CqreLap6v/DSHeM7BdG9Xd4OTPQWdfzTwHZkJhGB0qdY87XmVTiu213Tjs2NfBiRBOGcnoOTmKxbdzHhR2dLVDv5xOmHp59ovVMv0/UHCfuPGCq5foYAAAAASUVORK5CYII="); background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAAXVJREFUeJztm8ESwyAIRLX//8/2EjKKmhhFUeDN9NbK7kIybaPerSU0vs9PVbGwUGI4hDb/3meypumcsfDtEhsuGCsv8Pw5Us2UiwXnUvEDnaxOTrQmiXaKRRLjk7qVTRVVEKMCA7WglppX4bjusptmLCJc7uF1pIae5HDXl6ePWKqHu+s18DTMKTK7AAHTNJ5gHiDXepJ5gEzzieaBYe0nmwdePfwWijkKCd0HPnuRZB6oerJLACGx+0DRm01AhOTuA5lH9ROgPgBAw/gDiVf1E2ABcAvYAU3XP3B7Vj8BFgC3AG4sAG4B3FgA3AK4sQC4BeyCpm+D9mswxgLgFrATGu4D9qcoRn0AGMmXgT0ZakXiFNjT4a9ImoJuLxJCsD1Co5w8Bar3CqreLap6v/DSHeM7BdG9Xd4OTPQWdfzTwHZkJhGB0qdY87XmVTiu213Tjs2NfBiRBOGcnoOTmKxbdzHhR2dLVDv5xOmHp59ovVMv0/UHCfuPGCq5foYAAAAASUVORK5CYII=");
width: 64px; width: 64px;
height: 64px; height: 64px;
z-index: 999999998;
} }
`.split("\n").join("").split("\r").join("").split("\t").join(""); `.split("\n").join("").split("\r").join("").split("\t").join("");
document.head.appendChild(styles); document.head.appendChild(styles);
@ -94,8 +95,14 @@ if (!window.TE_ACTIVE) {
otherCursors.id = "otherCursors"; otherCursors.id = "otherCursors";
document.body.appendChild(otherCursors); document.body.appendChild(otherCursors);
let clientWidth = document.body.getBoundingClientRect().width
setInterval(() => { 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); }, 1000);
const keepAlivePacket = createWriter(Endian.LE, 1).writeByte(MessageType.KeepAlive).toBuffer(); 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"; cursorImage = "https://angusnicneven.com/cursor/rrw.png";
} }
image.src = cursorImage; image.src = cursorImage;
this.probeImage = image;
this.element.appendChild(image); this.element.appendChild(image);
const clientName = document.createElement("div"); 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; clientName.innerText = name;
this.element.appendChild(clientName); this.element.appendChild(clientName);
otherCursors.appendChild(this.element); otherCursors.appendChild(this.element);
@ -138,15 +146,25 @@ if (!window.TE_ACTIVE) {
this.actualY = 0; this.actualY = 0;
this.oldActualX = 0; this.oldActualX = 0;
this.oldActualY = 0; this.oldActualY = 0;
this.hasBeenMoved = false;
this.element.visibility = "hidden";
} }
rawSetPos(x, y) { 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; this.targetY = y;
} }
rawSetPosInit(x, 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; this.actualY = this.targetY = y;
} }
@ -164,6 +182,8 @@ if (!window.TE_ACTIVE) {
} }
} }
let selfCursor;
function createPing(x, y) { function createPing(x, y) {
const pingDiv = document.createElement("div"); const pingDiv = document.createElement("div");
pingDiv.className = "ping"; pingDiv.className = "ping";
@ -187,17 +207,29 @@ if (!window.TE_ACTIVE) {
window.onmousemove = (e) => { window.onmousemove = (e) => {
currentMouseX = (rawMouseX = e.clientX) + document.body.scrollLeft; currentMouseX = (rawMouseX = e.clientX) + document.body.scrollLeft;
currentMouseY = (rawMouseY = e.clientY) + document.body.scrollTop; currentMouseY = (rawMouseY = e.clientY) + document.body.scrollTop;
if (selfCursor) {
selfCursor.rawSetPosInit(currentMouseX / clientWidth, currentMouseY);
selfCursor.updateCursor();
}
} }
window.onscroll = () => { window.onscroll = () => {
currentMouseX = rawMouseX + document.body.scrollLeft; currentMouseX = rawMouseX + document.body.scrollLeft;
currentMouseY = rawMouseY + document.body.scrollTop; currentMouseY = rawMouseY + document.body.scrollTop;
if (selfCursor) {
selfCursor.rawSetPosInit(currentMouseX / clientWidth, currentMouseY);
selfCursor.updateCursor();
}
} }
let allowedPings = 10;
window.onkeypress = (e) => { window.onkeypress = (e) => {
if (e.key === "p") { if (e.key === "p") {
if (ws && ready) { 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 timeLastFrame = performance.now();
let frameDeltaTime = 0; let frameDeltaTime = 0;
let timeSinceLastPingReset = performance.now();
function animate() { function animate() {
frameDeltaTime = (performance.now() - timeLastFrame) * 0.001; frameDeltaTime = (performance.now() - timeLastFrame) * 0.001;
@ -217,11 +250,16 @@ if (!window.TE_ACTIVE) {
lastSendTime = performance.now(); lastSendTime = performance.now();
oldMouseX = currentMouseX; oldMouseX = currentMouseX;
oldMouseY = currentMouseY; 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 => { remoteClients.forEach(remoteUser => {
remoteUser.actualX = lerp(remoteUser.actualX, remoteUser.targetX, 20 * frameDeltaTime); remoteUser.actualX = lerp(remoteUser.actualX, remoteUser.targetX, 20 * frameDeltaTime);
remoteUser.actualY = lerp(remoteUser.actualY, remoteUser.targetY, 20 * frameDeltaTime); remoteUser.actualY = lerp(remoteUser.actualY, remoteUser.targetY, 20 * frameDeltaTime);
@ -236,9 +274,11 @@ if (!window.TE_ACTIVE) {
function doConnect() { function doConnect() {
const Buffer = getBufferClass(); 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; let keepAliveInterval;
ws.onopen = () => { ws.onopen = () => {
selfCursor = new RemoteClient(username);
selfCursor.probeImage.style.visibility = "hidden";
const currentPage = window.location.href.split("/").slice(3).join("/"); 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()); ws.send(createWriter(Endian.LE, 4 + username.length + currentPage.length).writeByte(MessageType.ClientDetails).writeShortString(username).writeString(currentPage).toBuffer());
keepAliveInterval = setInterval(() => { keepAliveInterval = setInterval(() => {
@ -288,7 +328,7 @@ if (!window.TE_ACTIVE) {
{ {
const cursorX = reader.readFloat(); const cursorX = reader.readFloat();
const cursorY = reader.readInt(); 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"; buttons.style.marginTop = "1rem";
dialog.appendChild(buttons); dialog.appendChild(buttons);
const submitButton = document.createElement("button"); 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); submitButton.onclick = () => submitFunction(null);
buttons.appendChild(submitButton); buttons.appendChild(submitButton);
if (localStorage["t00mp_username"] !== "") { if (localStorage["t00mp_username"] !== "") {

View file

@ -54,7 +54,8 @@ server.on("connection", (socket) => {
return; return;
} }
const username = reader.readShortString(); const username = reader.readShortString();
let page = reader.readString().toLowerCase().replace(".htm", "").replace(".html", ""); const rawURL = reader.readString();
let page = rawURL.toLowerCase().replace(".htm", "").replace(".html", "");
if (page === "index") { if (page === "index") {
page = ""; page = "";
} }
@ -70,7 +71,7 @@ server.on("connection", (socket) => {
for (const otherUser of usersOnPage) { for (const otherUser of usersOnPage) {
usersToSend.writeUInt(otherUser.id).writeShortString(otherUser.username).writeFloat(otherUser.cursorX).writeInt(otherUser.cursorY); usersToSend.writeUInt(otherUser.id).writeShortString(otherUser.username).writeFloat(otherUser.cursorX).writeInt(otherUser.cursorY);
} }
user = users.set(myUUID, new User(socket, username, page)); user = users.set(myUUID, new User(socket, username, page, rawURL));
sendToAllButSelf(user, createWriter(Endian.LE, 6 + username.length).writeByte(MessageType.ClientJoined).writeUInt(user.id).writeShortString(username).toBuffer()); sendToAllButSelf(user, createWriter(Endian.LE, 6 + username.length).writeByte(MessageType.ClientJoined).writeUInt(user.id).writeShortString(username).toBuffer());
user.send(usersToSend.toBuffer()); user.send(usersToSend.toBuffer());
break; break;
@ -86,10 +87,21 @@ server.on("connection", (socket) => {
} }
case MessageType.Ping: case MessageType.Ping:
{ {
if (user === undefined) {
return;
}
if ((Date.now() - user.lastPingReset) >= 1000) {
user.allowedPings = 10;
}
if (user.allowedPings > 0) {
user.allowedPings--;
const cursorX = reader.readFloat(); const cursorX = reader.readFloat();
const cursorY = reader.readInt(); const cursorY = reader.readInt();
const packet = createWriter(Endian.LE, 9).writeByte(MessageType.Ping).writeFloat(cursorX).writeInt(cursorY).toBuffer(); const packet = createWriter(Endian.LE, 9).writeByte(MessageType.Ping).writeFloat(cursorX).writeInt(cursorY).toBuffer();
sendToAll(user, packet); sendToAll(user, packet);
}
break; break;
} }
} }

View file

@ -7,14 +7,20 @@ export default class User {
public readonly id:number; public readonly id:number;
public readonly username:string; public readonly username:string;
public readonly currentURL:string; public readonly currentURL:string;
public readonly rawURL:string = "";
public cursorX:number = 0; public cursorX:number = 0;
public cursorY:number = 0; public cursorY:number = 0;
public allowedPings:number;
public lastPingReset:number;
constructor(socket:WebSocket, username:string, currentURL:string) { constructor(socket:WebSocket, username:string, currentURL:string, rawURL:string) {
this.socket = socket; this.socket = socket;
this.id = User.USER_IDS++; this.id = User.USER_IDS++;
this.username = username; this.username = username;
this.currentURL = currentURL; this.currentURL = currentURL;
this.rawURL = rawURL;
this.allowedPings = 10;
this.lastPingReset = Date.now();
} }
send(data:Buffer) { send(data:Buffer) {