ServerSelector

Select servers from different gamemodes and regions.

目前為 2022-01-11 提交的版本,檢視 最新版本

// ==UserScript==
// @name         ServerSelector
// @namespace    http://tampermonkey.net/
// @version      1.2.1
// @description  Select servers from different gamemodes and regions.
// @author       Altanis + Bismuth
// @match        *://diep.io/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant        unsafeWindow
// @grant        GM_setClipboard
// @license      MIT
// ==/UserScript==

// 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 = ["do-sfo","do-nyc","do-fra","do-sgp"];
const modes = ["ffa", "survival","teams", "4teams", "dom","tag","maze","sandbox"];
const colors = ["#E8B18A", "#E666EA", "#9566EA", "#6690EA", "#E7D063", "#EA6666", "#92EA66", "#66EAE6"];
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 show server selector
        <br>
        <p style="font-size:12px">Created by Altanis and Bismuth</p>
        <p style="font-size:12px">Credits to Diep7444</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='do-sfo' 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='do-nyc' 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}'>NYC</button>
    <button class='child' type='button' id='do-fra' 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='do-sgp' 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}'>SGP</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 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].length; n++) {
        json += `<button class='child' type='button' id='choice${n}'value='${n}'style='width:6vw; height:3vh; border-radius: 0.5vw; font-family:Ubuntu; opacity:60%; background:${colors[n % 8]}; color:#FFFFFF; font-style:normal; font-size:0.9vw; ${textShadow}'> ${currentServer.includes(serverWithoutCSS[choices.mode][choices.region][n].slice(0,8))? '>': ''}${serverWithoutCSS[choices.mode][choices.region][n].slice(0,8)}</button>`;
    }
    document.getElementById('choice').innerHTML = `${json}`;
    for (let n = 0; n < serverWithoutCSS[choices.mode][choices.region].length; n++) {
        addButtonListener('choice'+n);
    }
    addButtonListener('copylink');
}
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 if (button.value === 'copy') {
        GM_setClipboard("diep.io/#" + getServerLink(currentServer.split("://")[1].split("-80.lobby")[0]).toUpperCase());
    }
    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%'
}
const choices = {
    mode: 'ffa',
    region: 'do-sfo'
}
const serverWithoutCSS = {
    "ffa": {
        "do-sfo": [],
        "do-nyc": [],
        "do-fra": [],
        "do-sgp": []
    },
    "survival": {
        "do-sfo": [],
        "do-nyc": [],
        "do-fra": [],
        "do-sgp": []
    },
    "teams": {
        "do-sfo": [],
        "do-nyc": [],
        "do-fra": [],
        "do-sgp": []
    },
    "4teams": {
        "do-sfo": [],
        "do-nyc": [],
        "do-fra": [],
        "do-sgp": []
    },
    "dom": {
        "do-sfo": [],
        "do-nyc": [],
        "do-fra": [],
        "do-sgp": []
    },
    "tag": {
        "do-sfo": [],
        "do-nyc": [],
        "do-fra": [],
        "do-sgp": []
    },
    "maze": {
        "do-sfo": [],
        "do-nyc": [],
        "do-fra": [],
        "do-sgp": []
    },
    "sandbox": {
        "do-sfo": [],
        "do-nyc": [],
        "do-fra": [],
        "do-sgp": []
    },
};
var do_connect = false;
var currentServer = '';
var override = false;
async function fetchServer(mode, region, times = 3) {
    if (mode === 'sandbox') times = 1;
    const url = "https://api-game.rivet.gg";
    for (let i = 0; i < times; i++) {
        try {
            const response = await fetch(`${url}/v1/matchmaker/lobbies/find`, {method: 'post', body: `{"game_modes": ["${mode}"], "regions": ["${region}"]}`});
            const body = await response.json();
            if (body.hasOwnProperty("lobby")) {
                Object.entries(body.lobby.ports).forEach(([key, val]) => {
                    if (!serverWithoutCSS[mode][region].some((host) => {
                        return host === val.host;
                    })) {
                        serverWithoutCSS[mode][region].push(val.host);
                    }
                });
            }
            refreshHTML();
        } catch (err) {
            console.error(err);
        }
    }
}
function appendServers(mode, region) {
    fetchServer(mode, region, 3);
}
function connectTo(mode, region, number) {
    if (!serverWithoutCSS[mode][region][number]) return;
    currentServer = "wss://" + serverWithoutCSS[mode][region][number];
    do_connect = true;
    unsafeWindow.input.execute('lb_reconnect');
}
unsafeWindow.servers = serverWithoutCSS;
unsafeWindow.WebSocket = new Proxy(WebSocket,{
    construct(t, args) {
    if (do_connect) args[0] = currentServer;
    currentServer = args[0];
    unsafeWindow.serverURL = args[0];
    do_connect = false;
    override = true;
    return Reflect.construct(t, args)}
});
var _fetch = unsafeWindow.fetch;
unsafeWindow.fetch = function(endpoint, opts) {
    return _fetch(endpoint, opts)
    .then(function(response) {
        return new Promise(function(res) {
            response.clone().json()
            .then(function(body) {
                if (!override) return res(response);

                body.lobby.lobby_id = currentServer.split('wss://')[1].split('-80.lobby')[0];
                body.lobby.region.region_id = choices.region;
                const blob = new Blob([JSON.stringify(body)], { type: 'application/json' });
                console.log(res(new Response(blob)));
                return res(new Response(blob));
                override = false;
            })
            .catch(function(er) {
                return res(response);
            });
        });
    });
}
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";
        }
    }
}
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;
}

QingJ © 2025

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