您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
(WORKING AS OF 9/5/24) The only working stream sniper script without using exploits.
当前为
// ==UserScript== // @name RoSniper // @namespace http://tampermonkey.net/ // @version 3.1.2 // @description (WORKING AS OF 9/5/24) The only working stream sniper script without using exploits. // @author ryi3r // @match https://www.roblox.com/* // @grant none // @license MIT // ==/UserScript== // Psst... if you encounter any issues, talk to me on Discord: `ryi3r`! (function () { "use strict"; const getJSON = (url, args = {}) => { args.headers = args.headers || {}; return fetch(url, args) .then((r) => r.json()) .catch((e) => console.log(e)); }; const delay = ms => new Promise(res => setTimeout(res, ms)); const search = async (placeId, name, setStatus, cb, setThumb) => { setStatus("Loading..."); let userID = 0; try { userID = await getUserId(name); } catch (e) { console.log("error:", e); setStatus("Requested user doesn't exist."); return; } const thumbUrl = await getThumb(userID); //console.log(thumbUrl); setThumb(thumbUrl.replace("/noFilter", "/isCircular")); let cursor = null; let found = false; let serversSearched = 0; let playersTotal = 0; let serversStatus = ""; const nextThumbChunk = async (chunk, place) => { if (found || chunk.length === 0) return; //console.log("pre-mapping:", chunk); //console.log("place:", place); let data; while (true) { try { data = await fetchThumbs(chunk); break; } catch (e) { console.log("error:", e); await delay(1000); } } //console.log("thumbs:", data); let serverThumbs = data.data; if (!serverThumbs) setStatus("error: " + serverThumbs); else { //console.log(serverThumbs); for (let k = 0; k < serverThumbs.length; k++) { const thumb = serverThumbs[k]; //console.log(thumb); if (thumb && thumb.imageUrl === thumbUrl) { found = true; //const thumbToken = thumb.requestId.split(":")[1]; cb({ found: true, place: place, serversStatus, }); //console.log("found at index", k, "and got place", place); return; } } } }; while (true) { const servers = await getServer(placeId, cursor); if (servers !== undefined && servers.data !== undefined) { //console.log(servers); for (let i = 0; i < servers.data.length; i++) { const place = servers.data[i]; if (!found) { serversSearched++; playersTotal += place.playerTokens.length; serversStatus = `Servers searched: ${serversSearched} (through ${playersTotal} players.)`; setStatus(serversStatus); await nextThumbChunk(place.playerTokens, place); } else {} } cursor = servers.nextPageCursor; if (!cursor || found) break; } else { let amount = 10; while (amount > 0) { let secDef = "seconds"; if (amount === 1) { secDef = "second"; } setStatus(`Waiting ${amount} ${secDef}...\n${serversStatus}`); amount -= 1; await delay(1000); } setStatus(`Waiting 0 seconds...\n${serversStatus}`); } } if (!found) { cb({ found: false, serversStatus }); } }; const getUserId = (name) => fetch("https://www.roblox.com/users/profile?username=" + name).then((r) => { if (!r.ok) throw "User not found."; return r.url.match(/\d+/)[0]; }); const getThumb = (id) => getJSON( `https://thumbnails.roblox.com/v1/users/avatar-headshot?userIds=${id}&format=Png&size=150x150` ).then((d) => { //console.log(d); return d.data[0].imageUrl; }); const getServer = (placeId, cursor) => { let url = `https://games.roblox.com/v1/games/${placeId}/servers/0?limit=100`; if (cursor) url += "&cursor=" + cursor; return getJSON(url).catch(() => null); }; const fetchThumbs = async (tokens) => { let body = []; tokens.forEach((token) => { body.push({ requestId: `0:${token}:AvatarHeadshot:150x150:png:regular`, type: "AvatarHeadShot", targetId: 0, token, format: "png", size: "150x150", }); }); return getJSON("https://thumbnails.roblox.com/v1/batch", { method: "POST", headers: { "Content-Type": "application/json", Accept: "application/json", }, body: JSON.stringify(body), }); }; const instancesContainer = document.getElementById( "running-game-instances-container" ); if (instancesContainer) { const containerHeader = document.createElement("div"); containerHeader.classList = "section"; const headerText = document.createElement("h2"); headerText.innerText = "RoSniper 3.1"; containerHeader.appendChild(headerText); const form = document.createElement("form"); const thumbImage = document.createElement("img"); thumbImage.height = "40"; thumbImage.display = "none"; containerHeader.appendChild(thumbImage); form.appendChild(document.createElement("br")); const usernameInput = document.createElement("input"); usernameInput.classList = "input-field"; usernameInput.placeholder = "Username"; form.appendChild(usernameInput); const submitButton = document.createElement("button"); submitButton.classList = "btn-primary-md"; submitButton.innerText = "Search"; submitButton.disabled = true; form.appendChild(submitButton); usernameInput.addEventListener("input", (e) => { submitButton.disabled = e.target.value.length === 0; }); const statusText = document.createElement("p"); form.appendChild(statusText); const joinBtn = document.createElement("button"); joinBtn.style.display = "none"; joinBtn.innerText = "Join"; joinBtn.classList = "btn-control-xs rbx-game-server-join game-server-join-btn btn-primary-md btn-min-width"; const copyBtn = document.createElement("button"); copyBtn.style.display = "none"; copyBtn.innerText = "Copy Join Link"; copyBtn.classList = "btn-control-xs rg-btn btn-primary-md btn-min-width"; containerHeader.appendChild(form); containerHeader.appendChild(joinBtn); containerHeader.appendChild(copyBtn); instancesContainer.insertBefore( containerHeader, instancesContainer.firstChild ); const placeId = location.href.match(/\d+/)[0]; form.addEventListener("submit", (evt) => { evt.preventDefault(); joinBtn.style.display = "none"; copyBtn.style.display = "none"; search( placeId, usernameInput.value, (txt) => { statusText.innerText = txt; }, (place) => { console.log(place); if (!place.found) { statusText.innerText = "User not found in the servers.\n" + place.serversStatus; return; } statusText.innerText = `User found.\n${place.serversStatus}\n${place.place.playing} of ${place.place.maxPlayers} people max`; joinBtn.style.display = ""; joinBtn.onclick = () => { window.Roblox.GameLauncher.joinGameInstance( placeId, place.place.id ); }; copyBtn.style.display = ""; copyBtn.onclick = () => { copyBtn.innerText = "Copied!"; navigator.clipboard.writeText(`https://www.roblox.com/games/start?placeId=${placeId}&gameId=${place.place.id}`).finally(() => { delay(1000).then(() => { copyBtn.innerText = "Copy Join Link"; }); }); }; }, (src) => { thumbImage.src = src; thumbImage.display = ""; } ); }); } })();