ServerSearch

Find roblox servers at the click of a button.

  1. // ==UserScript==
  2. // @name ServerSearch
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.0
  5. // @description Find roblox servers at the click of a button.
  6. // @author Doctor Who
  7. // @match https://www.roblox.com/discover/*
  8. // @icon https://www.google.com/s2/favicons?domain=roblox.com
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. let Cookie = document.cookie.match(/rosearch=(?<json>{.*?});/);
  16. let Options = Cookie?.groups.json ? JSON.parse(Cookie?.groups.json) : {};
  17. let GameID = document.URL.match(/games\/(\d+)\//)[1];
  18. let GameOptions = Options[GameID] || {};
  19.  
  20. function GetServers(Index) {
  21. return new Promise((resolve, reject) => {
  22. fetch(`https://www.roblox.com/games/getgameinstancesjson?placeId=${GameID}&startIndex=${Index}&_=1`, {
  23. method: "GET",
  24. })
  25. .then(res => res.text())
  26. .then(json => resolve(JSON.parse(json)))
  27. .catch(er => reject(er));
  28. });
  29. }
  30.  
  31. function SaveOptions() {
  32. let Status = document.getElementById("server-status");
  33. let MaxPing = document.getElementById("ping-box").value;
  34. let MaxPlayers = document.getElementById("player-box").value;
  35. let CookieData = {};
  36. if (MaxPing.length) CookieData.MaxPing = MaxPing;
  37. if (MaxPlayers.length) CookieData.MaxPlayers = MaxPlayers;
  38.  
  39. let StatusBackup = Status.innerHTML;
  40. Options[GameID] = CookieData;
  41. Status.innerHTML = "Saved options!";
  42. document.cookie = `rosearch=${JSON.stringify(Options)}; path=/games; expires=Fri, 31 Dec 9999 23:59:59 GMT;`;
  43.  
  44. setTimeout(() => Status.innerHTML = StatusBackup, 2000);
  45. }
  46.  
  47. let GameInstances = document.getElementById("game-instances");
  48. let ParentDiv = document.createElement("div");
  49. let ContainerHead = document.createElement("div");
  50.  
  51. ParentDiv.className = "stack";
  52. GameInstances.prepend(ParentDiv);
  53.  
  54. // container header
  55.  
  56. let Title = document.createElement("h3");
  57. Title.innerHTML = "ServerSearch";
  58.  
  59. ContainerHead.className = "container-header";
  60. ContainerHead.prepend(Title);
  61.  
  62. // container children
  63.  
  64. let pingbox = document.createElement("textarea");
  65. pingbox.className = "dialog-input ng-valid ng-isolate-scope ng-touched ng-not-empty ng-dirty ng-valid-parse";
  66. pingbox.rows = 1;
  67. pingbox.style = "overflow: hidden; overflow-wrap: break-word; resize: none; height: 30px; margin-bottom: 5px; display: inherit; border-radius: 3px; width: 330px;";
  68. pingbox.placeholder = "Max Ping (Leave Blank For Default)";
  69. pingbox.innerHTML = GameOptions.MaxPing || "";
  70. pingbox.id = "ping-box";
  71.  
  72. let maxPlayer = document.createElement("textarea");
  73. maxPlayer.className = "dialog-input ng-valid ng-isolate-scope ng-touched ng-not-empty ng-dirty ng-valid-parse";
  74. maxPlayer.rows = 1;
  75. maxPlayer.style = "overflow: hidden; overflow-wrap: break-word; resize: none; height: 30px; margin-bottom: 5px; display: inherit; border-radius: 3px; width: 330px;";
  76. maxPlayer.placeholder = "Max Players (Leave Blank For Default)";
  77. maxPlayer.innerHTML = GameOptions.MaxPlayers || "";
  78. maxPlayer.id = "player-box";
  79. let status = document.createElement("span");
  80. status.className = "section-content-off";
  81. status.id = "server-status";
  82. status.style = "display: inherit;";
  83.  
  84. async function main() {
  85. if (!confirm("Are you sure you want to find the server?")) return;
  86.  
  87. let Stats = document.getElementsByClassName("game-stat game-stat-width");
  88. let MaxPing = pingbox.value.length ? parseInt(pingbox.value) : 300;
  89. let MaxPlayers = maxPlayer.value.length ? parseInt(maxPlayer.value) : 4;
  90. let MaxServerP = parseInt(Stats[5].children[1].innerText);
  91. let ActiveP = parseInt(Stats[0].children[1].innerText.replace(",", ""));
  92. let Iterator = Math.floor(ActiveP / (MaxServerP * 9));
  93. let TimeNow = Date.now();
  94.  
  95. status.innerHTML = "Looking for servers...";
  96.  
  97. while (true) {
  98. let Servers = await GetServers(Iterator);
  99. if (!Servers.Collection.length) {
  100. status.innerHTML = "Couldn't find any servers meeting your options, try editing your options!";
  101. break;
  102. }
  103.  
  104. let LowerMatch = Servers.Collection.filter((server) => server.CurrentPlayers.length <= MaxPlayers && server.Ping <= MaxPing).shift();
  105. let ExactMatch = Servers.Collection.filter((server) => server.CurrentPlayers.length == MaxPlayers && server.Ping <= MaxPing).shift();
  106.  
  107. if (ExactMatch) {
  108. status.innerHTML = `Found server! Players: ${ExactMatch.CurrentPlayers.length} Ping: ${ExactMatch.Ping} Index: ${Iterator} Took: ${(Date.now() - TimeNow) / 1000}s`;
  109. eval(ExactMatch.JoinScript);
  110. break;
  111. }
  112.  
  113. if (LowerMatch) {
  114. status.innerHTML = `We couldn't find an exact match however we found a lower one! Players: ${LowerMatch.CurrentPlayers.length} Ping: ${LowerMatch.Ping} Index: ${Iterator} Took: ${(Date.now() - TimeNow) / 1000}s`;
  115. eval(LowerMatch.JoinScript);
  116. break;
  117. }
  118.  
  119. status.innerHTML = `Index: ${Iterator}.`;
  120. Iterator += Math.floor(ActiveP / (MaxServerP * Servers.Collection.length));
  121. }
  122. }
  123.  
  124. let fakeButton = document.createElement("span");
  125. fakeButton.className = "btn-secondary-md btn-more";
  126. fakeButton.innerHTML = "Find Server";
  127. fakeButton.onclick = main;
  128. fakeButton.style = "display: inherit; width: min-content; margin-bottom: 20px;";
  129.  
  130. let fakeButton2 = document.createElement("span");
  131. fakeButton2.className = "btn-secondary-md btn-more";
  132. fakeButton2.innerHTML = "Save Options";
  133. fakeButton2.onclick = SaveOptions;
  134. fakeButton2.style = "display: inherit; width: min-content; margin-bottom: 5px;";
  135.  
  136. ParentDiv.prepend(ContainerHead, maxPlayer, pingbox, fakeButton2, fakeButton, status);
  137. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址