- // ==UserScript==
- // @name Diep.io Server Selector + Restore Player Count
- // @namespace http://tampermonkey.net/
- // @version 2.7.0
- // @description Select servers from different gamemodes and regions for Diep. Also restores player count for Diep.io.
- // @author Altanis + Bismuth
- // @match *://diep.io/*
- // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
- // @grant unsafeWindow
- // @license MIT
- // ==/UserScript==
-
- (async function() {
- // Special credits to Diep7444 for paving the way to an effective region changer.
-
- const textShadow = 'text-shadow:black 0.18vh 0, black -0.18vh 0, black 0 -0.18vh, black 0 0.18vh, black 0.18vh 0.18vh, black -0.18vh 0.18vh, black 0.18vh -0.18vh, black -0.18vh -0.18vh, black 0.09vh 0.18vh, black -0.09vh 0.18vh, black 0.09vh -0.18vh, black -0.09vh -0.18vh, black 0.18vh 0.09vh, black -0.18vh 0.09vh, black 0.18vh -0.09vh, black -0.18vh -0.09vh'
- const regions = ["lnd-sfo", "lnd-atl", "lnd-fra", "lnd-syd"];
- const modes = ["ffa", "survival", "teams", "4teams", "dom", "tag", "maze", "sandbox"];
- const colors = ["#E8B18A", "#E666EA", "#9566EA", "#6690EA", "#E7D063", "#EA6666", "#92EA66", "#66EAE6"];
-
- let key = 'KeyT'; // Go to https://keycode.info, press desired key, copy event.code, paste into quotes.
- let special = 'alt'; // alt, shift, ctrl, meta (Windows/Command)
-
- let includeUncommon = true;
-
- if (!['alt', 'shift', 'ctrl', 'meta'].includes(special)) special = 'alt'; // Default = Alt.
-
- var PLAYER_COUNT = 0;
- unsafeWindow.API_STATE = { code: 0, message: 'Connecting...'};
-
- const modeHTML = document.createElement("div");
- document.body.appendChild(modeHTML);
- modeHTML.innerHTML = `
- <div class='parent' id='ServerSelector' style='user-select:none; position:fixed; top:25%; right:0.5%; text-align:center; width:15vw; font-family:Ubuntu; color:#FFFFFF; font-style:normal; font-size:0.9vw; ${textShadow}'><div class='child' style='line-height:2vh; opacity:75%'>
- TAB to toggle server selector
- <br>
- <p style="font-size:12px;">Created by Altanis and Bismuth</p>
- <p style="font-size:12px;" id="status">Status: ${unsafeWindow.API_STATE.message}</p>
- <hr>
- </div>
- <p style="font-size:10px">Game Mode</p>
- <button class='child' type='button' id='ffa' value='mode' style='width:3.5vw; height:3vh; border-radius: 0.5vw; font-family:Ubuntu; opacity:60%; background:${colors[7]}; color:#FFFFFF; font-style:normal; font-size:0.9vw; ${textShadow}'>FFA</button>
- <button class='child' type='button' id='survival' value='mode' style='width:3.5vw; height:3vh; border-radius: 0.5vw; font-family:Ubuntu; opacity:60%; background:${colors[6]}; color:#FFFFFF; font-style:normal; font-size:0.9vw; ${textShadow}'>SURV</button>
- <button class='child' type='button' id='teams' value='mode' style='width:3.5vw; height:3vh; border-radius: 0.5vw; font-family:Ubuntu; opacity:60%; background:${colors[5]}; color:#FFFFFF; font-style:normal; font-size:0.9vw; ${textShadow}'>2TDM</button>
- <button class='child' type='button' id='4teams' value='mode' style='width:3.5vw; height:3vh; border-radius: 0.5vw; font-family:Ubuntu; opacity:60%; background:${colors[4]}; color:#FFFFFF; font-style:normal; font-size:0.9vw; ${textShadow}'>4TDM</button>
- <button class='child' type='button' id='dom' value='mode' style='width:3.5vw; height:3vh; border-radius: 0.5vw; font-family:Ubuntu; opacity:60%; background:${colors[3]}; color:#FFFFFF; font-style:normal; font-size:0.9vw; ${textShadow}'>DOM</button>
- <button class='child' type='button' id='tag' value='mode' style='width:3.5vw; height:3vh; border-radius: 0.5vw; font-family:Ubuntu; opacity:60%; background:${colors[2]}; color:#FFFFFF; font-style:normal; font-size:0.9vw; ${textShadow}'>TAG</button>
- <button class='child' type='button' id='maze' value='mode' style='width:3.5vw; height:3vh; border-radius: 0.5vw; font-family:Ubuntu; opacity:60%; background:${colors[1]}; color:#FFFFFF; font-style:normal; font-size:0.9vw;${textShadow}'>MAZE</button>
- <button class='child' type='button' id='sandbox' value='mode' style='width:3.5vw; height:3vh; border-radius: 0.5vw; font-family:Ubuntu; opacity:60%; background:${colors[0]}; color:#FFFFFF; font-style:normal; font-size:0.9vw;${textShadow}'>SBX</button>
- <p style="font-size:10px">Region</p>
- <button class='child' type='button' id=${regions[0]} value='region' style='width:3.5vw; height:3vh; border-radius: 0.5vw; font-family:Ubuntu; opacity:60%; background:${colors[3]}; color:#FFFFFF; font-style:normal; font-size:0.9vw; ${textShadow}'>SFO</button>
- <button class='child' type='button' id=${regions[1]} value='region' style='width:3.5vw; height:3vh; border-radius: 0.5vw; font-family:Ubuntu; opacity:60%; background:${colors[2]}; color:#FFFFFF; font-style:normal; font-size:0.9vw; ${textShadow}'>ATL</button>
- <button class='child' type='button' id=${regions[2]} value='region' style='width:3.5vw; height:3vh; border-radius: 0.5vw; font-family:Ubuntu; opacity:60%; background:${colors[6]}; color:#FFFFFF; font-style:normal; font-size:0.9vw; ${textShadow}'>FRA</button>
- <button class='child' type='button' id=${regions[3]} value='region' style='width:3.5vw; height:3vh; border-radius: 0.5vw; font-family:Ubuntu; opacity:60%; background:${colors[5]}; color:#FFFFFF; font-style:normal; font-size:0.9vw;${textShadow}'>SYD</button>
- <div class='parent' id='choice' style='user-select:none; position:relative; top:65%; left:0.5%; text-align:center; width:15vw; font-family:Ubuntu; color:#FFFFFF; font-style:normal; font-size:0.9vw; ${textShadow}'>
- <br>
- </div>
- </div>
- `
- document.getElementById('ServerSelector').style.display = 'block';
- for (let mode of modes) {
- addButtonListener(mode);
- }
- for (let region of regions) {
- addButtonListener(region);
- }
-
- function refreshStatus() { document.getElementById('status').innerHTML = `Status: ${unsafeWindow.API_STATE.message}`; }
- function refreshHTML() {
- let json = `<div class='parent' id='choice' style='user-select:none; position:relative; top:65%; left:0.5%; text-align:center; width:15vw; font-family:Ubuntu; color:#FFFFFF; font-style:normal; font-size:0.9vw; ${textShadow}'><p style="font-size:12px"> </p><div class='child' style='line-height:2vh; opacity:75%'> Servers for ${choices.mode} ${choices.region}<hr></div>`;
- for (let n = 0; n < serverWithoutCSS[choices.mode][choices.region].lobbies.length; n++) {
- json += `<button class='child' type='button' id='choice${n}'value='${n}'style='width:9vw; height:3vh; border-radius: 0.5vw; font-family:Ubuntu; opacity:60%; background:${colors[n % 8]}; color:#FFFFFF; font-style:normal; font-size:0.9vw; filter: ${currentServer.includes(serverWithoutCSS[choices.mode][choices.region].lobbies[n].slice(0,8))? 'brightness(100%)': 'brightness(50%)'}; ${textShadow}'>${serverWithoutCSS[choices.mode][choices.region].lobbies[n].slice(0,8)} (${serverWithoutCSS[choices.mode][choices.region].info[serverWithoutCSS[choices.mode][choices.region].lobbies[n].slice(0, 36)].total_player_count || '??'}/${serverWithoutCSS[choices.mode][choices.region].info[serverWithoutCSS[choices.mode][choices.region].lobbies[n].slice(0, 36)].max_players_direct || '??'})</button>`;
- }
-
- document.getElementById('choice').innerHTML = `${json}`;
-
- for (let n = 0; n < serverWithoutCSS[choices.mode][choices.region].lobbies.length; n++) {
- addButtonListener('choice' + n);
- }
- }
-
- function buttonAction(id) {
- let button = document.getElementById(id);
- if (button.value === 'mode') {
- choices.mode = id;
- fetchServer(choices.mode, choices.region, 3);
- } else if (button.value === 'region') {
- choices.region = id;
- fetchServer(choices.mode, choices.region, 3);
- } else {
- (connectTo(choices.mode, choices.region, button.value));
- }
- refreshHTML();
- }
-
- function addButtonListener(id) {
- document.getElementById(id).addEventListener("click", function() {
- buttonAction(id)
- });
- document.getElementById(id).addEventListener("mouseenter", function() {
- lightenColor(id)
- });
- document.getElementById(id).addEventListener("mouseleave", function() {
- resetColor(id)
- });
- }
-
- function lightenColor(id) {
- document.getElementById(id).style.opacity = '100%'
- }
-
- function resetColor(id) {
- document.getElementById(id).style.opacity = '60%'
- }
-
- function getServerLink(server) {
- let link = '';
- for (const char of server) {
- const code = char.charCodeAt(0);
- const value = (`00${code.toString(16)}`).slice(-2);
- link += value.split("").reverse().join("");
- }
- return link;
- }
-
- async function calcPlayerCount() {
- const body = JSON.parse(localStorage.lists)?.list;
-
- if (!body.hasOwnProperty('game_modes') && !body.hasOwnProperty('message')) {
- unsafeWindow.API_STATE.code = 2; return;
- };
- if (body.message === 'too many requests') {
- unsafeWindow.API_STATE.code = 3; return;
- };
-
- PLAYER_COUNT = 0;
- body.game_modes.forEach(function(g) {
- if (['dom', 'sandbox', 'survival', 'tag'].includes(g.game_mode_name) && !includeUncommon) return;
- g.regions.forEach(function(r) {
- r.lobbies.forEach(function(l) {
- PLAYER_COUNT += l.total_player_count;
- });
- });
- });
- }
-
- const choices = {
- mode: modes[0],
- region: regions[0],
- }
- const serverWithoutCSS = {};
-
- modes.forEach(function(gamemode) {
- serverWithoutCSS[gamemode] = {};
- regions.forEach(function(region) {
- serverWithoutCSS[gamemode][region] = { lobbies: [], info: {} };
- });
- });
-
- unsafeWindow.API_STATE = new Proxy(unsafeWindow.API_STATE, {
- set: function(t, k, v) {
- t[k] = v;
-
- if ([0, 1, 2, 4].includes(v)) {
- t.message = v === 0 ? 'Connecting...' : (v === 1 ? 'Ready!' : (v === 2 ? 'Endpoint is down.' : 'Lobbies don\'t exist.'))
- } else if (v === 3) {
- const date = new Date(Date.now());
-
- const curMin = date.getMinutes();
- const intervals = [0, 15, 30, 45];
-
- intervals.sort((a, b) => {
- return Math.abs(curMin - a) - Math.abs(curMin - b);
- });
-
- let retry_at = intervals[0] < curMin ? intervals[1] : intervals[0];
- let time = `${retry_at === 0 ? date.getHours() + 1 : date.getHours()}:${retry_at.length === 1 ? `0${retry_at}` : retry_at}`;
- t.message = `Ratelimited! Retry-At: ${time}.`;
-
- const interval = setInterval(function() {
- let [hours, minutes] = time.split(':').map(t => parseInt(t));
- if (new Date(Date.now()).getHours() >= hours && new Date(Date.now()).getMinutes() >= minutes) {
- t.code = 1;
- t.message = 'Ready!';
- refreshStatus();
- clearInterval(interval);
- }
- }, 150);
- }
- refreshStatus();
- return true;
- }
- });
-
- if (!localStorage.lists) {
- var _resp = await fetch(`https://api-game.rivet.gg/v1/matchmaker/lobbies/list`);
- var lists = await _resp.json();
-
- unsafeWindow.API_STATE.code = _resp.status === 200 ? 1 : (_resp.status === 429 ? 3 : 2);
-
- localStorage.lists = JSON.stringify({
- timestamp: Date.now(),
- list: lists,
- });
- }
-
- setInterval(async function() {
- if (!localStorage.lists) {
- var _resp = await fetch(`https://api-game.rivet.gg/v1/matchmaker/lobbies/list`);
- var lists = await _resp.json();
-
- unsafeWindow.API_STATE.code = _resp.status === 200 ? 1 : (_resp.status === 429 ? 3 : 2);
- localStorage.lists = JSON.stringify({
- timestamp: Date.now(),
- list: lists,
- });
- }
-
- if (Date.now() - JSON.parse(localStorage.lists)?.timestamp > 3e5) {
- var _resp = await fetch(`https://api-game.rivet.gg/v1/matchmaker/lobbies/list`);
- var lists = await _resp.json();
-
- unsafeWindow.API_STATE.code = _resp.status === 200 ? 1 : (_resp.status === 429 ? 3 : 2);
-
- localStorage.lists = JSON.stringify({
- timestamp: Date.now(),
- list: lists,
- });
-
- console.log('Refreshed server list.');
- }
- if (unsafeWindow.API_STATE.code === 0) unsafeWindow.API_STATE.code = 1;
- }, 5000);
-
- const GAMEMODES_MAP = [];
- const REGIONS_MAP = [];
-
- try {
- JSON.parse(localStorage.lists).list.game_modes.forEach(function(data) {
- GAMEMODES_MAP.push(data.game_mode_name);
- if (REGIONS_MAP.length === 0) {
- data.regions.forEach(function(data2) {
- REGIONS_MAP.push(data2.region_name);
- });
- }
- });
- } catch (er) {
- alert('API of Rivet is down!');
- unsafeWindow.API_STATE.code = 2;
- }
-
- var do_connect = false;
- var currentServer = '';
- var override = false;
- async function fetchServer(mode, region) {
- const body = JSON.parse(localStorage.lists)?.list;
-
- if (!body.hasOwnProperty('game_modes') && !body.hasOwnProperty('message')) {
- unsafeWindow.API_STATE.code = 2;
- return;
- }
- if (body.message === 'too many requests') {
- unsafeWindow.API_STATE.code = 3;
- return;
- }
-
- calcPlayerCount();
-
- const lobbies = body.game_modes[GAMEMODES_MAP.indexOf(mode)]?.regions[REGIONS_MAP.indexOf(region)]?.lobbies;
-
- if (!lobbies) {
- unsafeWindow.API_STATE.code = 4;
- return;
- };
-
- lobbies.forEach(function({
- lobby_id, total_player_count, max_players_direct
- }) {
- serverWithoutCSS[mode][region].info[lobby_id] = { total_player_count, max_players_direct };
-
- if (!serverWithoutCSS[mode][region].lobbies.some(function(host) {
- return host === `${lobby_id}-80.lobby.${region}.hiss.io:443`
- })) {
- serverWithoutCSS[mode][region].lobbies.push(`${lobby_id}-80.lobby.${region}.hiss.io:443`);
- }
- });
- unsafeWindow.API_STATE.code = 1;
-
- refreshHTML();
- }
-
- function appendServers(mode, region) {
- fetchServer(mode, region);
- }
-
- function connectTo(mode, region, number) {
- if (!serverWithoutCSS[mode][region].lobbies[number]) return;
- currentServer = "wss://" + serverWithoutCSS[mode][region].lobbies[number];
- do_connect = true;
- unsafeWindow.input.execute('lb_reconnect');
- }
- unsafeWindow.servers = serverWithoutCSS;
-
- var _WebSocket = unsafeWindow.WebSocket;
- unsafeWindow.WebSocket = function(wss) {
- let triggered = do_connect;
-
- if (do_connect) wss = currentServer;
- currentServer = wss;
-
- const socket = new _WebSocket(wss);
- socket.addEventListener('error', function(er) {
- if (triggered)
- alert('Connection to lobby failed, redirecting...'); // This is most likely due to the target server closing or reaching player limit.
- });
-
- do_connect = false;
- return socket;
- };
-
- (function(realHTMLInputElement) {
- Object.defineProperty(HTMLTextAreaElement.prototype, 'value', {
- set: function(value) {
- if (!value.startsWith('diep.io/#')) return realHTMLInputElement.set.call(this, value);
-
- let [serverID, party] = value.replace('diep.io/#', '').split('00');
- serverID = getServerLink(currentServer.split("://")[1].split("-80.lobby")[0]).toUpperCase();
- value = `https://diep.io/#${serverID}00${party}`;
-
- return realHTMLInputElement.set.call(this, value);
- },
- });
- }(Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'value')));
-
- document.body.onkeydown = function(e) {
- if (String.fromCharCode(e.keyCode) === '\t') {
- if (document.getElementById('ServerSelector').style.display === "none") {
- document.getElementById('ServerSelector').style.display = "block";
- document.getElementById('choice').style.display = "block";
- } else {
- document.getElementById('ServerSelector').style.display = "none";
- document.getElementById('choice').style.display = "none";
- }
- }
-
- if (e.code === key && e[`${special}Key`]) {
- includeUncommon = !includeUncommon;
- calcPlayerCount();
- }
- }
-
- calcPlayerCount();
- setInterval(calcPlayerCount, 60000);
-
- const crx = CanvasRenderingContext2D.prototype;
-
- crx.fillText = new Proxy(crx.fillText, {
- apply(f, _this, args) {
- if (args[0].includes('ms lnd'))
- args[0] += ` ‖ ${PLAYER_COUNT} players`;
- return f.apply(_this, args);
- }
- });
-
- crx.strokeText = new Proxy(crx.strokeText, {
- apply(f, _this, args) {
- if (args[0].includes('ms lnd'))
- args[0] += ` ‖ ${PLAYER_COUNT} players`;
- return f.apply(_this, args);
- }
- });
-
- crx.measureText = new Proxy(crx.measureText, {
- apply(f, _this, args) {
- if (args[0].includes('ms lnd'))
- args[0] += ` ‖ ${PLAYER_COUNT} players`;
- return f.apply(_this, args);
- }
- });
- })();