您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Display speed of streamers on rtirl.com
// ==UserScript== // @name RTIRL Speed Display // @author intsven // @namespace intsven // @description Display speed of streamers on rtirl.com // @version 0.1 // @match https://rtirl.com/* // @run-at document-start // @license MIT // @grant none // ==/UserScript== const sockets = []; const nativeWebSocket = window.WebSocket; const version = '14'; var lastECEF = null; var lastTime = null; var ecefTimes = []; var speedsKmH = []; window.WebSocket = function(...args){ const socket = new nativeWebSocket(...args); sockets.push(socket); console.log('WSHook args:', args); const url = args[0]; console.log('WSHook version:', version); // append function to the socket onmessage event //socket.onmessage. return socket; }; setTimeout(() => { // or create a button which, when clicked, does something with the sockets console.log(sockets); for (const socket of sockets) { const oldOnMessage = socket.onmessage; socket.onmessage = function(event) { //console.log('WSHook onmessage:', event); try { WSHookMessage(event); } catch (error) { console.info('WSHook error:', error); } if (oldOnMessage) { oldOnMessage.bind(this)(event); } } } }, 5000); // Create display for speed in bottom left corner const speedDisplay = document.createElement('div'); speedDisplay.style.position = 'fixed'; speedDisplay.style.bottom = '30px'; speedDisplay.style.left = '0'; //speedDisplay.style.backgroundColor = 'rgba(0, 0, 0, 0.5)'; speedDisplay.style.color = 'white'; speedDisplay.style.padding = '5px'; speedDisplay.style.borderRadius = '5px'; speedDisplay.innerHTML = 'Speed: 0 km/h'; // text shadow speedDisplay.style.textShadow = '2px 2px 2px #000'; // Font with monospace speedDisplay.style.fontFamily = 'monospace'; // Font size speedDisplay.style.fontSize = '20px'; document.body.appendChild(speedDisplay); function WSHookMessage(event) { const eventUrl = event.target.url; //console.log('WSHook eventUrl:', eventUrl); if (eventUrl.includes('.firebaseio.com/.ws?') && eventUrl.includes('-locations-rtdb')) { //console.log('WSHook Received message:', eventUrl, event.data); const data = JSON.parse(event.data); //console.log(data); // Check if location data is present if (!data.d || !data.d.b || !data.d.b.d) { return; } const pos = data.d.b.d; //console.log(pos); const lat = pos['0']; const lon = pos['1']; const ecef = fromDegreeToECEF(lat, lon, 0); if (lastECEF) { // Get the distance between the last position and the current position const dist = distance(lastECEF, ecef); //console.log('Distance:', dist); const deltaTime = Date.now() - lastTime; const speed = dist / deltaTime * 1000; const speedKmH = speed * 3.6; ecefTimes.push([ecef, Date.now()]); speedsKmH.push(speedKmH); const avgSpeed = average(speedsKmH, 10); console.log('Speed [km/h]:', speedKmH, 'Distance [m]:', dist, 'Time [ms]:', deltaTime); // three padding zeros speedDisplay.innerHTML = 'Speed[km/h]: ' + speedKmH.toFixed(2).padStart(6, '0') + '<br>'; speedDisplay.innerHTML += 'Avg Last 10: ' + avgSpeed.toFixed(2).padStart(6, '0'); //console.log('WSHook Received message:', event.data); } lastECEF = ecef; lastTime = Date.now(); } }; function distance(ecef1, ecef2) { const x = ecef1[0] - ecef2[0]; const y = ecef1[1] - ecef2[1]; const z = ecef1[2] - ecef2[2]; return Math.sqrt(x * x + y * y + z * z); } function average(arr, lastN=0) { if (lastN > 0) { arr = arr.slice(-lastN); } return arr.reduce((a, b) => a + b, 0) / arr.length; } function fromDegreeToECEF(latitude,longitude,alt){ const lat = latitude * Math.PI / 180; const lon = longitude * Math.PI / 180; return toECEF(lat, lon, alt); } function toECEF(lat, lon, alt) { const a = 6378137.0; const f = 1.0 / 298.257223563; const e2 = f * (2 - f); const N = a / Math.sqrt(1 - e2 * Math.sin(lat) * Math.sin(lat)); const x = (N + alt) * Math.cos(lat) * Math.cos(lon); const y = (N + alt) * Math.cos(lat) * Math.sin(lon); const z = (N * (1 - e2) + alt) * Math.sin(lat); return [x, y, z]; } // wss://s-usc1b-nss-2133.firebaseio.com/.ws?v=5&p=1:684852107701:web:22f87dcafccc98249a61fc&ns=rtirl-a1d7f-locations-rtdb