Slither.io - 607ch00 remix

slither.io MOD - 2021 Update! - Zoom, High score, Custom backgrounds, Clock, and more!

  1. // ==UserScript==
  2. // @name Slither.io - 607ch00 remix
  3. // @namespace slitherio.remix.607ch00
  4. // @version 0.6.9.19
  5. // @description slither.io MOD - 2021 Update! - Zoom, High score, Custom backgrounds, Clock, and more!
  6. // @author 607ch00
  7. // @match http://slither.io/
  8. // @noframes
  9. // @run-at document-idle
  10. // @grant none
  11. // ==/UserScript==
  12. /*jshint multistr: true */
  13.  
  14. /**
  15. * newSnake()
  16. * newFood()
  17. * newPrey()
  18. * ws.onmessage()
  19. */
  20.  
  21. var modVersion = 'v0.6.9.19', //used in menu box
  22. graphicsMode = '4', //4 - customized high quality 3 - high quality, 2 - simple optimized, 1 - simple (mobile)
  23. graphicsModeChanged = true, //flag to indicate graphics mode has changed
  24. statsContainer = null, //reference to stats container
  25. fpsContainer = null, //reference to fps div
  26. xferContainer = null, //refernce to current transfer rate div
  27. zoomContainer = null, //reference to zoom div
  28. positionContainer = null, //reference to coordinates div
  29. ipContainer = null, //reference to current/last connected server div
  30. highscoreContainer = null, //reference to high score display
  31. clockContainer = null, //reference to clock container
  32. backgroundImage = -1, //store the user selected background image
  33. randomizeBackground = false, //indicate whether or not to randomize background
  34. originalBackground = null, //store the game's default background image
  35. originalBackgroundCanvas = null, //store the game's default background canvas object
  36. backgroundImageChanged = true, //indicate if background image needs to be set
  37. clearedGlow = false, //store whether glow was attempted to be cleared
  38. highScore = 0, //store the user's current high score
  39. currentIP = null, //store the current connected server ip
  40. selectedServer = -1, //store the user selected server ip
  41. selectedSkinOption = -1, //Store skin option
  42. selectedSkin = null, //Store skin number
  43. manualServer = false, //store user manual server entry
  44. connectButtonOverride = false, //store whether the connect button click listener was overridden
  45. connectButton = null, //reference to the connect button
  46. retry = 0 //hold the current number of connection retries
  47. customZoom = false,
  48. currentZoom = unsafeWindow.gsc; //hold the zoom level we should be at based on mousewheel
  49.  
  50. // allow context menu
  51. unsafeWindow.oncontextmenu = function() {
  52. return true;
  53. }
  54.  
  55. /**
  56. * Init script
  57. */
  58. var init = function() {
  59. removeIframes();
  60. createCSS();
  61. stopLogoAnimation();
  62. createHTML();
  63. createListeners();
  64. setupMenu();
  65. customConnectButton();
  66. setupGraphics();
  67. updateLoop();
  68. showFPS();
  69. fixedZoom();
  70. }
  71.  
  72. var removeIframes = function() {
  73. var iframes = document.querySelectorAll('iframe');
  74. for (var i = 0; i < iframes.length; i++) {
  75. iframes[i].parentNode.removeChild(iframes[i]);
  76. }
  77. }
  78.  
  79. /**
  80. * Create stylesheet in head
  81. */
  82. var createCSS = function() {
  83. var styleElement = document.createElement('style');
  84. document.getElementsByTagName('head')[0].appendChild(styleElement);
  85. styleElement.type = 'text/css';
  86.  
  87. var cssString = ' \
  88. body { \
  89. background-color: #000!important; \
  90. overflow-x:hidden; \
  91. } \
  92. #nbg { \
  93. display:none; \
  94. visibility:hidden; \
  95. } \
  96. #clq { \
  97. bottom:0!important; \
  98. height:auto!important; \
  99. } \
  100. #grqh { \
  101. top: auto!important; \
  102. right: auto!important; \
  103. bottom: 20px; \
  104. left: 150px; \
  105. } \
  106. #login { \
  107. /* margin-top:0!important; */ \
  108. position:relative!important; \
  109. width:auto!important; \
  110. height:auto!important; \
  111. } \
  112. #logo { \
  113. /* margin-top:30px!important; */ \
  114. } \
  115. #stats-container { \
  116. position:fixed; \
  117. right: 30px; \
  118. bottom: 120px; \
  119. opacity: 0.35; \
  120. z-index: 7; \
  121. color: #FFF; \
  122. font: 14px Arial, Helvetica Neue, Helvetica, sans-serif; \
  123. text-align: right; \
  124. } \
  125. #custom-menu-container { \
  126. width:260px; \
  127. color:#8058D0; \
  128. background-color:#1E262E; \
  129. border-radius:29px; \
  130. font: 14px Lucida Sans Unicode, Lucida Grande, sans-serif; \
  131. text-align:center; \
  132. margin: 20px auto 0; \
  133. padding:10px 14px; \
  134. } \
  135. .custom-select-container { \
  136. background-color:#A5A5A5; \
  137. border-radius:10px; \
  138. margin:5px auto; \
  139. padding:5px 0; \
  140. } \
  141. .custom-select-container select { \
  142. width:100%; \
  143. background:none; \
  144. border:none; \
  145. outline:none; \
  146. } \
  147. #server-manual-input { \
  148. width: 100%; \
  149. display:none; \
  150. margin: 3px auto; \
  151. width: 98%; \
  152. background-color: #4C447C; \
  153. border: 1px solid #1E262E; \
  154. color: #e0e0ff; \
  155. border-radius: 3px; \
  156. padding: 3px 3px; \
  157. } \
  158. #hotkey-help { \
  159. margin:0; \
  160. padding:0; \
  161. display:flex; \
  162. flex-wrap:wrap; \
  163. } \
  164. #hotkey-help li { \
  165. display:inline; \
  166. white-space:nowrap; \
  167. flex-grow:1; \
  168. } \
  169. #clock-container { \
  170. font-weight:900; \
  171. font: 14px Courier New, Courier, monospace; \
  172. } \
  173. #ingame-score { \
  174. left: 50%!important; \
  175. bottom: auto!important; \
  176. top: 0px!important; \
  177. transform: translate(-50%, 0)!important;\
  178. text-align: center!important; \
  179. font-size: 18px!important; \
  180. height: 50px!important; \
  181. line-height: 120%!important; \
  182. width:100%!important; \
  183. } \
  184. #ingame-score span:first-child { \
  185. font-size: 24px!important; \
  186. } \
  187. .nsi { \
  188. transition:none!important; \
  189. } \
  190. ';
  191.  
  192. if (styleElement.styleSheet) {
  193. styleElement.styleSheet.cssText = cssString;
  194. } else {
  195. styleElement.appendChild(document.createTextNode(cssString));
  196. }
  197. }
  198.  
  199. /**
  200. * Prevent laggy logo animation
  201. */
  202. var stopLogoAnimation = function() {
  203. if (typeof unsafeWindow.showlogo_iv !== 'undefined') {
  204. // if (unsafeWindow.hasOwnProperty('showlogo_iv')) {
  205. unsafeWindow.ncka = unsafeWindow.lgss = unsafeWindow.lga = 1;
  206. clearInterval(unsafeWindow.showlogo_iv);
  207. unsafeWindow.showLogo(true);
  208. } else {
  209. setTimeout(stopLogoAnimation, 25);
  210. }
  211. }
  212.  
  213. var createHTML = function() {
  214. // unsafeWindow.smh.innerHTML = '';
  215.  
  216. statsContainer = document.createElement('div');
  217. statsContainer.id = 'stats-container';
  218. statsContainer.innerHTML = ' \
  219. <div id="fps-container"></div> \
  220. <div id="xfer-container"></div> \
  221. <div id="zoom-container"></div> \
  222. <div id="position-container"></div> \
  223. <div id="ip-container"></div> \
  224. <div id="highscore-container"></div> \
  225. <div id="clock-container"></div> \
  226. ';
  227. document.body.appendChild(statsContainer);
  228.  
  229. fpsContainer = document.getElementById('fps-container');
  230. xferContainer = document.getElementById('xfer-container');
  231. zoomContainer = document.getElementById('zoom-container');
  232. positionContainer = document.getElementById('position-container');
  233. ipContainer = document.getElementById('ip-container');
  234. highscoreContainer = document.getElementById('highscore-container');
  235. clockContainer = document.getElementById('clock-container');
  236. }
  237.  
  238. var createListeners = function() {
  239. // Add zoom
  240. if (/firefox/i.test(navigator.userAgent)) {
  241. document.addEventListener('DOMMouseScroll', zoom, false);
  242. } else {
  243. document.body.onmousewheel = zoom;
  244. }
  245.  
  246. //Setup keyboard shortcuts
  247. document.addEventListener('keydown', function(e) {
  248. switch (e.keyCode) {
  249. //Toggle stats (tab)
  250. case 9:
  251. e.preventDefault();
  252. toggleStats();
  253. break;
  254. //Respawn (escape)
  255. case 27:
  256. disconnect(false);
  257. customConnect();
  258. break;
  259. //Disconnect (q)
  260. case 81:
  261. disconnect(true);
  262. break;
  263. //Reset zoom (~ tilde)
  264. case 192:
  265. resetZoom();
  266. break;
  267. }
  268. }, false);
  269. }
  270.  
  271. /**
  272. * Toggle display of stats window
  273. */
  274. var toggleStats = function() {
  275. if (statsContainer.style.display == 'none') {
  276. statsContainer.style.display = 'block';
  277. } else {
  278. statsContainer.style.display = 'none';
  279. }
  280. }
  281.  
  282. /**
  283. * Calculate zoom from mousewheel
  284. */
  285. var zoom = function(e) {
  286. if (!unsafeWindow.gsc || !unsafeWindow.playing) {
  287. return;
  288. }
  289.  
  290. customZoom = true;
  291. currentZoom *= Math.pow(0.9, e.wheelDelta / -120 || e.detail / 2 || 0);
  292. unsafeWindow.gsc = currentZoom;
  293. zoomContainer.textContent = 'Zoom: ' + unsafeWindow.gsc.toFixed(2);
  294.  
  295. // q.gcv = Math.floor(b.ic * gsc * (.25 + .75 * q.sz / 16.5));
  296. // console.log(unsafeWindow.foods);
  297. // for (var food in unsafeWindow.foods) {
  298. // console.log(unsafeWindow.foods[food]);
  299. // unsafeWindow.foods[food].cv2 = Math.floor(unsafeWindow.foods[food].id.ic * unsafeWindow.gsc * unsafeWindow.foods[food].sz / 16.5);
  300. // unsafeWindow.foods[food].gcv = Math.floor(unsafeWindow.foods[food].id.ic * unsafeWindow.gsc * (.25 + .75 * unsafeWindow.foods[food].sz / 16.5));
  301. // unsafeWindow.foods[food].g2cv = Math.floor(unsafeWindow.foods[food].id.ic * unsafeWindow.gsc * (.25 + .75 * unsafeWindow.foods[food].sz / 16.5));
  302.  
  303. // unsafeWindow.foods[food].cv2 = Math.floor(unsafeWindow.foods[food].id.ic * unsafeWindow.foods[food].sz / 16.5);
  304. // unsafeWindow.foods[food].gcv = Math.floor(unsafeWindow.foods[food].id.ic * (.25 + .75 * unsafeWindow.foods[food].sz / 16.5));
  305. // unsafeWindow.foods[food].g2cv = Math.floor(unsafeWindow.foods[food].id.ic * (.25 + .75 * unsafeWindow.foods[food].sz / 16.5));
  306. // unsafeWindow.foods[food].gfi =
  307. // unsafeWindow.foods[food].cv = 1;
  308. // unsafeWindow.foods[food].fh = 25;
  309. // unsafeWindow.foods[food].cv = unsafeWindow.foods[food].sz;
  310. // unsafeWindow.foods[food].cv2 = unsafeWindow.foods[food].sz;
  311. // unsafeWindow.foods[food].fh = unsafeWindow.foods[food].sz;
  312. // unsafeWindow.foods[food].gcv = unsafeWindow.foods[food].sz;
  313. // unsafeWindow.foods[food].g2cv = unsafeWindow.foods[food].sz;
  314. // unsafeWindow.foods[food].gcv = 25;
  315. // unsafeWindow.foods[food].g2cv = 25;
  316. // unsafeWindow.foods[food].gfi = 25;
  317. // unsafeWindow.foods[food].fi = null;
  318. // unsafeWindow.foods[food].g2fi = null;
  319. // unsafeWindow.foods[food].ofi = null;
  320. // console.log(unsafeWindow.foods[food]);
  321. // }
  322. // console.log(unsafeWindow.foods);
  323.  
  324. // unsafeWindow.resize();
  325. }
  326.  
  327. /**
  328. * Reset zoom to default level
  329. */
  330. function resetZoom() {
  331. customZoom = true;
  332. currentZoom = 0.5;
  333. unsafeWindow.gsc = currentZoom;
  334.  
  335. zoomContainer.textContent = 'Zoom: ' + unsafeWindow.gsc.toFixed(2);
  336. }
  337.  
  338. /**
  339. * Load settings from browser local storage
  340. */
  341. function loadSettings() {
  342. //Enable skins
  343. unsafeWindow.localStorage.setItem('edttsg', 1);
  344.  
  345. if (unsafeWindow.localStorage.getItem('nick') !== null) {
  346. var nick = unsafeWindow.localStorage.getItem('nick');
  347. document.getElementById('nick').value = nick;
  348. }
  349.  
  350. if (unsafeWindow.localStorage.getItem('high-score') !== null) {
  351. highScore = parseInt(unsafeWindow.localStorage.getItem('high-score'));
  352. highscoreContainer.textContent = 'Hi Score: ' + highScore;
  353. }
  354.  
  355. if (unsafeWindow.localStorage.getItem('graphics-mode') !== null) {
  356. var mode = unsafeWindow.localStorage.getItem('graphics-mode');
  357. if (mode >= 1 && mode <= 4) {
  358. graphicsMode = mode;
  359. }
  360. } else {
  361. unsafeWindow.localStorage.setItem('graphics-mode', '4');
  362. }
  363.  
  364. if (unsafeWindow.localStorage.getItem('background-image') !== null) {
  365. backgroundImage = unsafeWindow.localStorage.getItem('background-image');
  366. randomizeBackground = (backgroundImage == '-2' && graphicsMode == '4') ? true : false;
  367. } else {
  368. unsafeWindow.localStorage.setItem('background-image', '-2');
  369. }
  370.  
  371. if (unsafeWindow.localStorage.getItem('server-selected') !== null) {
  372. selectedServer = unsafeWindow.localStorage.getItem('server-selected');
  373. } else {
  374. unsafeWindow.localStorage.setItem('server-selected', selectedServer);
  375. }
  376.  
  377. if (unsafeWindow.localStorage.getItem('server-manual') !== null) {
  378. manualServer = unsafeWindow.localStorage.getItem('server-manual');
  379. } else {
  380. unsafeWindow.localStorage.setItem('server-manual', false);
  381. }
  382.  
  383. if (unsafeWindow.localStorage.getItem('skin-select') !== null) {
  384. selectedSkinOption = unsafeWindow.localStorage.getItem('skin-select');
  385. } else {
  386. unsafeWindow.localStorage.setItem('skin-select', selectedSkinOption);
  387. }
  388.  
  389. if (unsafeWindow.localStorage.getItem('snakercv') !== null) {
  390. selectedSkin = unsafeWindow.localStorage.getItem('snakercv');
  391. }
  392. }
  393.  
  394. /**
  395. * Setup main menu
  396. */
  397. var setupMenu = function() {
  398. var login = document.getElementById('login');
  399. var playButtonContainer = document.getElementById('playh');
  400. if (playButtonContainer) {
  401. // Load settings
  402. loadSettings();
  403.  
  404. //Create container
  405. var menuContainer = document.createElement('div');
  406. menuContainer.id = 'custom-menu-container';
  407. menuContainer.innerHTML = '\
  408. <!-- <div class="custom-select-container"> \
  409. <select id="server-select"> \
  410. <option value="-1">Server: Default Closest</option> \
  411. <option value="-2">Server: Random</option> \
  412. <option value="-3">Server: Manual Input</option> \
  413. </select> \
  414. <input type"text" id="server-manual-input"> \
  415. </div> --> \
  416. <div class="custom-select-container"> \
  417. <select id="graphics-select"> \
  418. <option value="4">Graphics: customized</option> \
  419. <option value="3">Graphics: normal</option> \
  420. <option value="2">Graphics: no background</option> \
  421. <option value="1">Graphics: low</option> \
  422. </select> \
  423. </div> \
  424. <div class="custom-select-container" id="background-select-container"> \
  425. <select id="background-select"> \
  426. <option value="-2">Background Image: Random</option> \
  427. <option value="-1">Background Image: Default</option> \
  428. <option value="http://i.imgur.com/YioXLYV.jpg">Grid</option> \
  429. <option value="http://i.imgur.com/Iffij8a.jpg">Cats</option> \
  430. <option value="http://i.imgur.com/jYFIA9J.jpg">Dirt</option> \
  431. <option value="http://i.imgur.com/wQIghye.jpg">Grass</option> \
  432. <option value="http://i.imgur.com/HVnFfK9.jpg">Magma Storm</option> \
  433. <option value="http://i.imgur.com/HaxzRtX.jpg">Wood</option> \
  434. <option value="http://i.imgur.com/kQvgICX.jpg">Stonewall</option> \
  435. <option value="http://i.imgur.com/bwfU0Qr.jpg">Hungry Like Wolf</option> \
  436. <option value="http://i.imgur.com/TyKD6Ie.png">Shaq-fu</option> \
  437. </select> \
  438. </div> \
  439. <div class="custom-select-container" id="skin-select-container"> \
  440. <select id="skin-select"> \
  441. <option value="-1">Skins: Default Single Skin</option> \
  442. <option value="1">Skins: Random</option> \
  443. <option value="2">Skins: Rotate All</option> \
  444. </select> \
  445. </div> \
  446. <ul id="hotkey-help"> \
  447. <li>[Mousewheel] Zoom</li> \
  448. <li>[~] Reset Zoom</li> \
  449. <li>[ESC] Respawn</li> \
  450. <li>[Q]uit Game</li> \
  451. <li>[TAB] Toggle Stats</li> \
  452. </ul> \
  453. <strong>607ch00 remix</strong> | <strong>' + modVersion + '</strong> \
  454. ';
  455.  
  456. login.insertBefore(menuContainer, playButtonContainer);
  457.  
  458. //Capture and store nickname
  459. var nick = document.getElementById('nick');
  460. nick.addEventListener("input", getNick, false);
  461.  
  462. //Set graphics mode
  463. var selectGraphics = document.getElementById('graphics-select');
  464. selectGraphics.value = graphicsMode;
  465. toggleBackgroundSelect();
  466.  
  467. selectGraphics.onchange = function() {
  468. var mode = selectGraphics.value;
  469. if (mode) {
  470. graphicsMode = mode;
  471. unsafeWindow.localStorage.setItem('graphics-mode', graphicsMode);
  472. toggleBackgroundSelect();
  473. graphicsModeChanged = true;
  474. backgroundImageChanged = true;
  475. if (graphicsMode != '4') {
  476. randomizeBackground = false;
  477. } else if (unsafeWindow.localStorage.getItem('background-image') == '-2') {
  478. randomizeBackground = true;
  479. }
  480. }
  481. };
  482.  
  483. //Set background options
  484. var selectBackground = document.getElementById('background-select');
  485. if (selectBackground) {
  486. selectBackground.value = backgroundImage;
  487. }
  488. selectBackground.onchange = function() {
  489. backgroundImage = selectBackground.value;
  490. unsafeWindow.localStorage.setItem('background-image', backgroundImage);
  491. graphicsModeChanged = true;
  492. backgroundImageChanged = true;
  493. randomizeBackground = (backgroundImage == '-2') ? true : false;
  494. };
  495.  
  496. //Set server options
  497. // getServersList();
  498.  
  499. // var selectServer = document.getElementById('server-select');
  500. // var inputServerManual = document.getElementById('server-manual-input');
  501.  
  502. // if (selectedServer) {
  503. // selectServer.value = selectedServer;
  504. // inputServerManual.style.display = (selectedServer === '-3') ? 'block' : 'none';
  505. // }
  506.  
  507. // if (manualServer && manualServer !== 'false') {
  508. // inputServerManual.value = manualServer;
  509. // }
  510.  
  511. // selectServer.onchange = function() {
  512. // selectedServer = selectServer.value;
  513.  
  514. // if (selectedServer === '-3') {
  515. // inputServerManual.style.display = 'block';
  516. // inputServerManual.focus();
  517. // } else {
  518. // inputServerManual.style.display = 'none';
  519. // }
  520.  
  521. // unsafeWindow.localStorage.setItem('server-selected', selectedServer);
  522. // };
  523.  
  524. // inputServerManual.onchange = function() {
  525. // manualServer = inputServerManual.value;
  526. // unsafeWindow.localStorage.setItem('server-manual', manualServer);
  527. // };
  528.  
  529. //Set skin options
  530. var selectSkin = document.getElementById('skin-select');
  531. if (selectedSkinOption) {
  532. selectSkin.value = selectedSkinOption;
  533. }
  534. selectSkin.onchange = function() {
  535. selectedSkinOption = selectSkin.value;
  536. unsafeWindow.localStorage.setItem('skin-select', selectedSkinOption);
  537. }
  538.  
  539. //Move this out of the way
  540. document.body.appendChild(document.getElementById('nbg'));
  541.  
  542. resizeView();
  543. } else {
  544. setTimeout(setupMenu, 100);
  545. }
  546. }
  547.  
  548. /**
  549. * Validate IP address format
  550. */
  551. var validIP = function(ip) {
  552. return /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(ip);
  553. }
  554.  
  555. /**
  556. * Toggle availablility of background image selection based on graphics mode
  557. */
  558. var toggleBackgroundSelect = function() {
  559. if (graphicsMode == '4') {
  560. document.getElementById('background-select-container').style.display = 'block';
  561. } else {
  562. document.getElementById('background-select-container').style.display = 'none';
  563. }
  564. }
  565.  
  566. /**
  567. * Select a random background when the game loads
  568. */
  569. var randomBackground = function() {
  570. var selectBackground = document.getElementById('background-select');
  571. var backgroundOptions = selectBackground.getElementsByTagName('option');
  572. var randomSelection = Math.floor(Math.random() * (backgroundOptions.length-1))+1;
  573. backgroundImage = backgroundOptions[randomSelection].value;
  574. backgroundImageChanged = true;
  575. }
  576.  
  577. /**
  578. * Get and store user's nickname
  579. */
  580. var getNick = function() {
  581. var nick = document.getElementById('nick').value;
  582. unsafeWindow.localStorage.setItem('nick', nick);
  583. }
  584.  
  585. /**
  586. * Generate select list of game servers available
  587. */
  588. var getServersList = function() {
  589. if (unsafeWindow.sos && unsafeWindow.sos.length > 0) {
  590. var selectSrv = document.getElementById('server-select');
  591. console.log(unsafeWindow.sos);
  592. for (var i = 0; i < unsafeWindow.sos.length; i++) {
  593. var srv = unsafeWindow.sos[i];
  594. var option = document.createElement('option');
  595. var serverLoopString = option.value = srv.ip + ':' + srv.po;
  596. option.text = (i + 1) + '. ' + option.value;
  597. selectSrv.appendChild(option);
  598. }
  599. } else {
  600. setTimeout(getServersList, 100);
  601. }
  602. }
  603.  
  604. /**
  605. * Override default connect button behavior to use custom server lists
  606. */
  607. var customConnectButton = function() {
  608. connectBtn = document.getElementById('playh').getElementsByClassName('btnt')[0];
  609. if (connectBtn && !connectButtonOverride) {
  610. // Force connect
  611. connectBtn.onclick = customConnect;
  612. } else {
  613. setTimeout(customConnectButton, 50);
  614. }
  615. }
  616.  
  617. /**
  618. * Custom connection function to allow for selection of server ip, random or default behavior
  619. */
  620. var customConnect = function() {
  621. if (!unsafeWindow.connect) {
  622. return;
  623. }
  624.  
  625. if (!connectBtn.disabled) {
  626. connectBtn.disabled = true;
  627. } else {
  628. return false;
  629. }
  630.  
  631. backgroundImageChanged = true;
  632. if (randomizeBackground) {
  633. randomBackground();
  634. }
  635.  
  636. //Handle skin change options
  637. skinChange();
  638.  
  639. //Reset zoom on new game
  640. resetZoom();
  641.  
  642. //Need to reset this before trying to reconnect
  643. unsafeWindow.dead_mtm = -1;
  644.  
  645. if (selectedServer != '-1') {
  646. unsafeWindow.forcing = true;
  647. if (!unsafeWindow.bso) {
  648. unsafeWindow.bso = {};
  649. }
  650. }
  651.  
  652. if (selectedServer == '-3') {
  653. //double check custom server entry
  654. manualServer = document.getElementById('server-manual-input').value;
  655. unsafeWindow.localStorage.setItem('server-manual', manualServer);
  656.  
  657. var srv = manualServer.trim().split(':');
  658.  
  659. if (validIP(srv[0])) {
  660. unsafeWindow.bso.ip = srv[0];
  661. unsafeWindow.bso.po = srv[1];
  662. } else {
  663. alert('The custom server you entered does not have a valid IP address format');
  664. document.getElementById('server-manual-input').focus();
  665. return false;
  666. }
  667. } else if (selectedServer == '-2') {
  668. var connectToServer = unsafeWindow.sos[Math.floor(Math.random()*unsafeWindow.sos.length)];
  669. unsafeWindow.bso.ip = connectToServer.ip;
  670. unsafeWindow.bso.po = connectToServer.po;
  671. selectedServer = connectToServer.ip + ':' + connectToServer.po;
  672. var selectSrv = document.getElementById('server-select').value = selectedServer;
  673. } else if (selectedServer != '-1') {
  674. var srv = selectedServer.trim().split(':');
  675. unsafeWindow.bso.ip = srv[0];
  676. unsafeWindow.bso.po = srv[1];
  677. }
  678.  
  679. unsafeWindow.connect();
  680. setTimeout(connectionStatus, 1000);
  681. }
  682.  
  683. /**
  684. * Loop to force retry of connection
  685. */
  686. var connectionStatus = function() {
  687. if (!unsafeWindow.connecting || retry == 10) {
  688. unsafeWindow.forcing = false;
  689. retry = 0;
  690. connectBtn.disabled = false;
  691. return;
  692. }
  693. retry++;
  694. setTimeout(connectionStatus, 1000);
  695. }
  696.  
  697. /**
  698. * Force disconnect from game and return to menu
  699. */
  700. var disconnect = function(resetGame) {
  701. if (unsafeWindow.playing) {
  702. unsafeWindow.want_close_socket = true;
  703. unsafeWindow.dead_mtm = Date.now();
  704.  
  705. if (resetGame) {
  706. unsafeWindow.resetGame();
  707. }
  708. }
  709. }
  710.  
  711. /**
  712. * Handle random or rotating to next skin
  713. */
  714. var skinChange = function() {
  715. //Default
  716. if (selectedSkinOption == -1) {
  717. return true;
  718. }
  719.  
  720. //Check local storage again in case user switch skin via default interface
  721. selectedSkin = unsafeWindow.localStorage.getItem('snakercv');
  722.  
  723. //Random
  724. if (selectedSkinOption == 1) {
  725. selectedSkin = Math.floor(Math.random() * (unsafeWindow.max_skin_cv+1));
  726. //Rotate
  727. } else if (selectedSkinOption == 2) {
  728. selectedSkin = (selectedSkin > unsafeWindow.max_skin_cv) ? 0 : parseInt(selectedSkin)+1;
  729. }
  730.  
  731. unsafeWindow.localStorage.setItem('snakercv', selectedSkin);
  732. }
  733.  
  734. /**
  735. * Set up graphics mode
  736. */
  737. var setupGraphics = function() {
  738. //Store original background image
  739. if ((!originalBackground || !originalBackgroundCanvas) && unsafeWindow.bgp2 && unsafeWindow.ii) {
  740. originalBackground = unsafeWindow.ii.src;
  741. originalBackgroundCanvas = unsafeWindow.bgp2;
  742. }
  743.  
  744. unsafeWindow.lbf.setAttribute("id", "ingame-score");
  745.  
  746. //Handle game graphics quality if needed
  747. if (graphicsModeChanged) {
  748. if (graphicsMode == '3') {
  749. unsafeWindow.grqi.style.display = 'block';
  750. unsafeWindow.grqi.src = '/s/highquality.png';
  751.  
  752. unsafeWindow.want_quality = 1;
  753. unsafeWindow.localStorage.setItem('qual', '1');
  754.  
  755. if (typeof unsafeWindow.high_quality !== 'undefined') {
  756. unsafeWindow.high_quality = true;
  757. }
  758.  
  759. //Global alpha
  760. if (unsafeWindow.gla) {
  761. unsafeWindow.gla = 1;
  762. }
  763.  
  764. if (typeof unsafeWindow.render_mode !== 'undefined') {
  765. unsafeWindow.render_mode = 2;
  766. }
  767. } else {
  768. if (graphicsMode == '4') {
  769. unsafeWindow.grqi.style.display = 'none';
  770. } else {
  771. unsafeWindow.grqi.style.display = 'block';
  772. unsafeWindow.grqi.src = '/s/lowquality.png';
  773. }
  774.  
  775. unsafeWindow.want_quality = 0;
  776. unsafeWindow.localStorage.setItem('qual', '0');
  777. unsafeWindow.qsm = 0;
  778.  
  779. if (typeof unsafeWindow.high_quality !== 'undefined') {
  780. unsafeWindow.high_quality = false;
  781. window.high_quality = false;
  782. }
  783.  
  784. //Global alpha
  785. if (unsafeWindow.gla) {
  786. unsafeWindow.gla = 0;
  787. }
  788.  
  789. //Snake rendering
  790. if (typeof unsafeWindow.render_mode !== 'undefined') {
  791. if (graphicsMode == '4') {
  792. unsafeWindow.render_mode = 2;
  793. } else {
  794. unsafeWindow.render_mode = parseInt(graphicsMode);
  795. }
  796. }
  797. }
  798.  
  799. graphicsModeChanged = false;
  800. }
  801.  
  802. //Handle game background change if needed
  803. if (backgroundImageChanged && typeof unsafeWindow.bgp2 !== 'undefined' && typeof unsafeWindow.ii !== 'undefined') {
  804. //Customized high quality
  805. if (graphicsMode == '4') {
  806. clearGlow();
  807.  
  808. if (unsafeWindow.bgp2) {
  809. unsafeWindow.bgp2 = originalBackgroundCanvas;
  810. }
  811.  
  812. if (unsafeWindow.ii) {
  813. if (backgroundImage != '-1') {
  814. unsafeWindow.ii.src = backgroundImage;
  815. var bgcanvas = unsafeWindow.bgi2.getContext("2d");
  816. bgcanvas.drawImage(unsafeWindow.ii, 0, 0);
  817. unsafeWindow.bgp2 = bgcanvas.createPattern(unsafeWindow.bgi2, "repeat");
  818. } else {
  819. unsafeWindow.ii.src = originalBackground;
  820. }
  821. }
  822. //Default high quality
  823. } else if (graphicsMode == '3') {
  824. if (unsafeWindow.ggbg && unsafeWindow.gbgmc) {
  825. unsafeWindow.ggbg = true;
  826. }
  827. if (unsafeWindow.bgp2) {
  828. unsafeWindow.bgp2 = originalBackgroundCanvas;
  829. }
  830. if (unsafeWindow.ii) {
  831. unsafeWindow.ii.src = originalBackground;
  832. }
  833. //Low quality / no background
  834. } else {
  835. clearGlow();
  836. //Background picture
  837. if (unsafeWindow.bgp2) {
  838. unsafeWindow.bgp2 = null;
  839. }
  840. }
  841.  
  842. backgroundImageChanged = false;
  843. }
  844. }
  845.  
  846. /**
  847. * Clear glow from game
  848. */
  849. var clearGlow = function() {
  850. if (unsafeWindow.ggbg) {
  851. unsafeWindow.ggbg = false;
  852. }
  853. if (clearedGlow) {
  854. return;
  855. } else if (unsafeWindow.gbgi && !clearedGlow) {
  856. unsafeWindow.gbgi.src = '';
  857. unsafeWindow.gbgi.onload = null;
  858. unsafeWindow.gbgi = null;
  859. if (unsafeWindow.gbgmc) {
  860. unsafeWindow.gbgmc = null;
  861. }
  862. clearedGlow = true;
  863. } else {
  864. setTimeout(clearGlow, 50);
  865. }
  866. }
  867.  
  868. /**
  869. * Resize the view to the current browser window
  870. */
  871. var resizeView = function() {
  872. if (unsafeWindow.resize) {
  873. unsafeWindow.lww = 0; // Reset width (force resize)
  874. unsafeWindow.wsu = 0; // Clear ad space
  875. unsafeWindow.resize();
  876. var wh = Math.ceil(unsafeWindow.innerHeight);
  877. if (wh < 800) {
  878. var login = document.getElementById('login');
  879. unsafeWindow.lgbsc = wh / 800;
  880. login.style.top = - (Math.round(wh * (1 - unsafeWindow.lgbsc) * 1E5) / 1E5) + 'px';
  881. if (unsafeWindow.trf) {
  882. unsafeWindow.trf(login, 'scale(' + unsafeWindow.lgbsc + ',' + unsafeWindow.lgbsc + ')');
  883. }
  884. }
  885. } else {
  886. setTimeout(resizeView, 100);
  887. }
  888. }
  889.  
  890. /**
  891. * Show FPS
  892. */
  893. var showFPS = function() {
  894. if (unsafeWindow.playing && unsafeWindow.fps && unsafeWindow.lrd_mtm) {
  895. if (Date.now() - unsafeWindow.lrd_mtm > 970) {
  896. fpsContainer.textContent = 'FPS: ' + unsafeWindow.fps;
  897. }
  898. }
  899. setTimeout(showFPS, 250);
  900. }
  901.  
  902. /**
  903. * Game recalcs zoom every redraw, setup a loop to keep it at our last zoom level
  904. */
  905. var fixedZoom = function() {
  906. if (customZoom) {
  907. unsafeWindow.gsc = currentZoom;
  908. }
  909. setTimeout(fixedZoom, 20);
  910. }
  911.  
  912. /**
  913. * Update loop for real-time data
  914. */
  915. var updateLoop = function() {
  916. setupGraphics();
  917.  
  918. //testing this
  919. //unsafeWindow.testing = true;
  920.  
  921. if (unsafeWindow.playing) {
  922. positionContainer.textContent = 'X: ' + (~~unsafeWindow.view_xx || 0) + ' Y: ' + (~~unsafeWindow.view_yy || 0);
  923.  
  924. if (unsafeWindow.bso && currentIP != unsafeWindow.bso.ip + ':' + unsafeWindow.bso.po) {
  925. currentIP = unsafeWindow.bso.ip + ":" + unsafeWindow.bso.po;
  926. ipContainer.textContent = 'IP: ' + currentIP;
  927. }
  928.  
  929. zoomContainer.textContent = 'Zoom: ' + unsafeWindow.gsc.toFixed(2);
  930. xferContainer.textContent = 'BPS: ' + unsafeWindow.rdps;
  931.  
  932. var currentScore = Math.floor(150 * (unsafeWindow.fpsls[unsafeWindow.snake.sct] + unsafeWindow.snake.fam / unsafeWindow.fmlts[unsafeWindow.snake.sct] - 1) - 50) / 10;
  933. if (currentScore > highScore) {
  934. highScore = currentScore;
  935. localStorage.setItem('high-score', highScore);
  936. highscoreContainer.textContent = 'Hi Score: ' + highScore;
  937. }
  938. } else {
  939. xferContainer.textContent = '';
  940. fpsContainer.textContent = '';
  941. zoomContainer.textContent = '';
  942. positionContainer.textContent = '';
  943. }
  944.  
  945. //Add/update clock
  946. var now = new Date();
  947. var hours = now.getHours();
  948. var minutes = now.getMinutes();
  949. var seconds = now.getSeconds();
  950. var timeValue = "" + ((hours > 12) ? hours - 12 : hours);
  951. timeValue += ((minutes < 10) ? ':0' : ':') + minutes;
  952. timeValue += ((seconds < 10) ? ':0' : ':') + seconds;
  953. timeValue += (hours >= 12) ? ' PM' : ' AM';
  954. clockContainer.textContent = timeValue;
  955.  
  956. //Fix this
  957. if (typeof window.oncontextmenu === 'function') {
  958. window.oncontextmenu=null;
  959. }
  960.  
  961. setTimeout(updateLoop, 20);
  962. }
  963.  
  964. // Init
  965. init();