Slither.io Server Picker

Pings available servers and lets you pick the one you want. This is a good plugin for playing with friends.

目前为 2017-01-12 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Slither.io Server Picker
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1.11
  5. // @description Pings available servers and lets you pick the one you want. This is a good plugin for playing with friends.
  6. // @author SystemDisc
  7. // @match http://slither.io/
  8. // @grant none
  9. // @run-at document-start
  10. // @require https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. let serverData = $.ajax({
  17. type: 'GET',
  18. url: 'http://slither.io/i33628.txt',
  19. async: false
  20. }).responseText;
  21.  
  22. let currentZoom = 0.9;
  23.  
  24. $(function() {
  25. let css = `
  26. iframe[src="/social-box/"] {
  27. display: none !important;
  28. }
  29. #HUD, #sidebar {
  30. position: fixed;
  31. top: 0;
  32. left: 0;
  33. z-index: 20;
  34. padding: 15px;
  35. background-color: rgba(0,0,0,0.5);
  36. color: #fff;
  37. }
  38. #sidebar {
  39. height: 100vh;
  40. overflow: auto;
  41. }
  42. #connectForm {
  43. margin-bottom: 15px;
  44. }
  45. #serverList > .server-listing {
  46. margin-bottom: 5px;
  47. cursor: pointer;
  48. }
  49. #serverList > .server-listing > .server-name, #serverList > .server-listing > .server-ping {
  50. display: inline-block;
  51. }
  52. #serverList > .server-listing > .server-ping {
  53. margin-left: 10px;
  54. color: green;
  55. }
  56. #serverList > .server-listing > .server-ping.bad {
  57. color: red;
  58. }
  59. `;
  60. let styleSheet = $('<style type="text/css">');
  61. styleSheet.html(css);
  62.  
  63. let HUD = $('<div id="HUD">');
  64. let server = $('<div class="server">');
  65. let coordinates = $('<div class="coordinates">');
  66. let section = $('<div class="section">');
  67. HUD.append(server);
  68. HUD.append(coordinates);
  69. HUD.append(section);
  70.  
  71. let sidebar = $('<div id="sidebar">');
  72.  
  73. let connectForm = $('<div id="connectForm">');
  74. let serverInput = $('<input class="server-input" type="test" name="serverHostname" placeholder="ip:port">');
  75. let serverConnect = $('<button class="connect-button" type="button">Connect</button>');
  76. connectForm.append(serverInput);
  77. connectForm.append(serverConnect);
  78.  
  79. let serverList = $('<div id="serverList">');
  80.  
  81. sidebar.append(connectForm);
  82. sidebar.append(serverList);
  83. $('body').append(HUD);
  84. $('body').append(sidebar);
  85. $('head').append(styleSheet);
  86.  
  87. $('#HUD').hide();
  88.  
  89. $(document).on('click', '#connectForm > .connect-button', function(e) {
  90. selectServer($('.server-input').val());
  91. });
  92.  
  93. $(document).on('click', '#serverList > .server-listing', function(e) {
  94. selectServer($(e.currentTarget).find('.server-name').text());
  95. });
  96.  
  97. let start = true;
  98. setInterval(function() {
  99. if (!window.playing) {
  100. $('#sidebar').show();
  101. $('#HUD').hide();
  102. if (!$('#nick').hasClass('loaded')) {
  103. $('#nick').val(localStorage.getItem('savedNick'));
  104. $('#nick').addClass('loaded');
  105. }
  106. if (start) {
  107. loadServers();
  108. start = false;
  109. }
  110. }
  111. else {
  112. $('#sidebar').hide();
  113. $('#HUD').show();
  114. start = true;
  115. }
  116. window.want_quality = 1;
  117. window.render_mode = 1;
  118. window.high_quality = true;
  119. window.gla = false;
  120. window.ggbg = false;
  121. if (window.gbgi) {
  122. window.gbgi.src = '';
  123. window.gbgi.onload = null;
  124. window.gbgi = null;
  125. if (window.gbgmc) {
  126. window.gbgmc = null;
  127. }
  128. }
  129.  
  130. window.gsc = currentZoom;
  131.  
  132. if (window.snake) {
  133. $('#HUD').find('.server').text('Server: ' + window.bso.ip + ':' + window.bso.po);
  134. $('#HUD').find('.coordinates').text('Coordinates: ' + Math.round(window.snake.xx / 100) + ', ' + Math.round(window.snake.yy / 100));
  135. $('#HUD').find('.section').text('Section: ' + Math.round((window.snake.xx - 22000) / 1000) + ', ' + Math.round((window.snake.yy - 22000)/1000));
  136. localStorage.setItem('savedNick', snake.nk);
  137. }
  138.  
  139. if (window.bso && window.bso.ip) {
  140. document.title = 'slither.io - ' + window.bso.ip + ':' + window.bso.po;
  141. }
  142. else {
  143. document.title = 'slither.io - disconnected'
  144. }
  145. }, 15);
  146.  
  147. $(document).bind('DOMMouseScroll mousewheel', zoom);
  148.  
  149. $(window).keydown(function(e) {
  150. console.log('keydown: ' + e.keyCode);
  151.  
  152. if (e.keyCode === 27) {
  153. quit();
  154. }
  155.  
  156. if (e.keyCode === 90) {
  157. currentZoom = 0.9;
  158. }
  159. });
  160. });
  161.  
  162. function loadServers() {
  163. let serverList = $('#serverList');
  164. serverList.children().remove();
  165. let servers = loadSos(serverData);
  166. let savedServers = window.localStorage.getItem('servers');
  167. if (!savedServers) {
  168. savedServers = {};
  169. }
  170. else {
  171. savedServers = JSON.parse(savedServers);
  172. }
  173. for (let servername in savedServers) {
  174. let ip;
  175. let port;
  176. [ip, port] = servername.split(':');
  177. servers.push({ip: ip, po: port});
  178. }
  179. let promises = [];
  180. servers.forEach(function(server) {
  181. let serverElem = $('[id="' + server.ip + '"]');
  182. let serverNameElem;
  183. let serverPingElem;
  184. if (serverElem.length === 0) {
  185. serverElem = $('<div id="' + server.ip + '" class="server-listing">');
  186. serverNameElem = $('<div class="server-name">');
  187. serverPingElem = $('<div class="server-ping">');
  188. serverNameElem.text(server.ip + ':' + server.po);
  189. serverElem.append(serverNameElem);
  190. serverElem.append(serverPingElem);
  191. serverList.append(serverElem);
  192. }
  193. else {
  194. serverNameElem = serverElem.find('.server-name');
  195. serverPingElem = serverElem.find('.server-ping');
  196. }
  197. let promise = pingServer(server.ip).then(function(ping) {
  198. if (savedServers[server.ip + ':' + server.po]) {
  199. ping = Math.round((savedServers[server.ip + ':' + server.po] + ping) / 2);
  200. }
  201. let pingElem = $('[id="' + server.ip + '"]').find('.server-ping');
  202. pingElem.text(ping);
  203. if (ping > 75) {
  204. pingElem.addClass('bad');
  205. }
  206. else {
  207. savedServers[server.ip + ':' + server.po] = ping;
  208. pingElem.removeClass('bad');
  209. }
  210. let serverList = $('#serverList');
  211. let serverElems = serverList.children();
  212. serverElems.sort(function(a, b) {
  213. let an = +$(a).find('.server-ping').text();
  214. let bn = +$(b).find('.server-ping').text();
  215. if (an === 0) {
  216. an = 1000;
  217. }
  218. if (bn === 0) {
  219. bn = 1000;
  220. }
  221. return an > bn? 1:(an < bn? -1:0);
  222. });
  223. serverElems.detach().appendTo(serverList);
  224. if (!window.bso || !window.bso.ip) {
  225. $('.server-input').val(serverElems.first().find('.server-name').text());
  226. }
  227. }).catch(function(err) {
  228. $('[id="' + server.ip + '"]').remove();
  229. delete savedServers[server.ip + ':' + server.po];
  230. return false;
  231. });
  232. promises.push(promise);
  233. });
  234.  
  235. Promise.all(promises).then(function() {
  236. localStorage.setItem('servers', JSON.stringify(savedServers));
  237. selectServer($('.server-input').val());
  238. });
  239. }
  240.  
  241. function quit() {
  242. if (window.playing && window.resetGame) {
  243. window.want_close_socket = true;
  244. window.dead_mtm = 0;
  245. if (window.play_btn) {
  246. window.play_btn.setEnabled(true);
  247. }
  248. window.resetGame();
  249. }
  250. }
  251.  
  252. function zoom(e) {
  253. console.log(window.gsc);
  254. if (!window.gsc) {
  255. return;
  256. }
  257. currentZoom *= Math.pow(0.9, e.originalEvent.wheelDelta / -120 || e.originalEvent.detail / 2 || 0);
  258. }
  259.  
  260. function selectServer(servername) {
  261. let ip;
  262. let port;
  263. [ip, port] = servername.split(':');
  264. console.log(ip, +port);
  265. window.forceServer(ip, +port);
  266. let serverElem = $('[id="' + ip + '"]');
  267. serverElem.addClass('selected');
  268. serverElem.siblings().removeClass('selected');
  269. $('.server-input').val(servername);
  270. }
  271.  
  272.  
  273. function loadSos(chars) {
  274. /** @type {Array} */
  275. sos = [];
  276. /** @type {Array} */
  277. clus = [];
  278. chars.charAt(0);
  279. /** @type {number} */
  280. var i = 1;
  281. var d = {};
  282. /** @type {number} */
  283. var index = 0;
  284. /** @type {number} */
  285. d = index = 0;
  286. var c;
  287. /** @type {number} */
  288. var data = 0;
  289. /** @type {number} */
  290. var handle = 0;
  291. /** @type {Array} */
  292. var split = [];
  293. /** @type {Array} */
  294. var m = [];
  295. /** @type {Array} */
  296. var messages = [];
  297. /** @type {Array} */
  298. var received = [];
  299. for (;i < chars.length;) {
  300. if (c = (chars.charCodeAt(i++) - 97 - handle) % 26, 0 > c && (c += 26), data *= 16, data += c, handle += 7, 1 == d) {
  301. if (0 == index) {
  302. split.push(data);
  303. if (4 == split.length) {
  304. index++;
  305. }
  306. } else {
  307. if (1 == index) {
  308. m.push(data);
  309. if (3 == m.length) {
  310. index++;
  311. }
  312. } else {
  313. if (2 == index) {
  314. messages.push(data);
  315. if (3 == messages.length) {
  316. index++;
  317. }
  318. } else {
  319. if (3 == index && (received.push(data), 1 == received.length)) {
  320. d = {};
  321. /** @type {number} */
  322. index = c = 0;
  323. for (;index < m.length;index++) {
  324. c *= 256;
  325. c += m[index];
  326. }
  327. /** @type {number} */
  328. index = m = 0;
  329. for (;index < messages.length;index++) {
  330. m *= 256;
  331. m += messages[index];
  332. }
  333. /** @type {string} */
  334. d.ip = split.join(".");
  335. d.po = c;
  336. d.ac = m;
  337. d.wg = m + 5;
  338. d.clu = received[0];
  339. /** @type {Array} */
  340. sos.push(d);
  341. /** @type {Array} */
  342. split = [];
  343. /** @type {Array} */
  344. m = [];
  345. /** @type {Array} */
  346. messages = [];
  347. /** @type {Array} */
  348. received = [];
  349. /** @type {number} */
  350. index = 0;
  351. }
  352. }
  353. }
  354. }
  355. /** @type {number} */
  356. d = data = 0;
  357. } else {
  358. d++;
  359. }
  360. }
  361. return sos;
  362. }
  363.  
  364. function pingServer(ip) {
  365. return new Promise(function(resolve, reject) {
  366. let handle = null;
  367. let ping = Date.now();
  368. try {
  369. handle = new WebSocket('ws://' + ip + ':80/ptc');
  370. }
  371. catch (e) {
  372. handle = null;
  373. reject(e);
  374. }
  375. if (handle) {
  376. handle.binaryType = "arraybuffer";
  377. handle.onerror = function(err) {
  378. reject(err);
  379. };
  380. handle.onmessage = function(data) {
  381. let pong = Date.now();
  382. if (testing) {
  383. console.log(ip, ping, pong, pong - ping, data);
  384. }
  385. resolve(pong - ping);
  386. };
  387. handle.onopen = function(body) {
  388. console.log(body);
  389. ping = Date.now();
  390. let data = new Uint8Array(1);
  391. data[0] = 112;
  392. this.send(data);
  393. };
  394. }
  395. });
  396. }
  397. })();