- // ==UserScript==
- // @name diep.io Spade Script - Public
- // @namespace spade-squad.com
- // @author DiE ♠ BiTCH // ♠-squad
- // @version 1.0.0
- // @description Press TAB to show Server Selector.
- // @homepage http://spade-squad.com
- // @icon http://spade-squad.com/pub/userscript/icon64.png
- // @match *://*.diep.io/*
- // @run-at document-start
- // @grant GM_addStyle
- // @grant GM_getResourceText
- // @grant GM_setClipboard
- // @grant GM_notification
- // @grant unsafeWindow
- // @require http://code.jquery.com/jquery-3.2.1.slim.min.js
- // @resource spadeCSS http://spade-squad.com/pub/userscript/spadeuserscript.css
- // ==/UserScript==
-
- //TODO: handle keypress fix partycache
-
- /* eslint-disable */
- let spadeCSS = GM_getResourceText("spadeCSS");
- GM_addStyle(spadeCSS);
- /* eslint-enable */
-
- (function () {
- "use strict";
-
- let defaultConfig = {
- "hotkey": {
- "connectUI": "\t" // TAB
- },
- "gameModeName": {
- "ffa": "FFA",
- "survival": "Survival",
- "teams": "2TDM",
- "4teams": "4TDM",
- "dom": "Domination",
- "maze": "Maze",
- "tag": "Tag",
- "sandbox": "Sandbox"
- },
- "team": {
- "blue": [[0, 178, 225, 255], [76, 201, 234, 255]],
- "red": [[241, 78, 84, 255], [245, 131, 135, 255]],
- "green": [[0, 225, 110, 255], [76, 234, 153, 255]],
- "purple": [[191, 127, 245, 255], [210, 165, 248, 255]]
- },
- "settings": {
- "firstRunDisable": false
- },
- "script": {
- "currentServer": {},
- "debugging": false
- }
- };
-
- const isObject = (obj) => {
- return obj instanceof Object && obj.constructor === Object;
- };
-
- const dataStorage = {
- set (key, value) {
- localStorage.setItem(key, JSON.stringify(value));
- },
- get (key) {
- const value = localStorage.getItem(key);
- return value && JSON.parse(value);
- }
- };
-
- (function () {
- let privateConfig;
- unsafeWindow.Config = {};
- const proxify = (obj) => {
- for (const subkey in obj) {
- if (Object.prototype.hasOwnProperty.call(obj, subkey)) {
- unsafeWindow.Config[subkey] = new Proxy(obj[subkey], {
- get (target, propKey, receiver) {
- if (propKey in target) {
- return Reflect.get(target, propKey, receiver);
- }
- throw new ReferenceError("Unknown property: " + propKey);
- },
- set (target, propKey, value, receiver) {
- target[propKey] = value;
- dataStorage.set("spadepublic", obj);
- return Reflect.set(target, propKey, value, receiver);
- }
- });
- }
- }
- };
-
- if (dataStorage.get("spadepublic")) {
- privateConfig = dataStorage.get("spadepublic");
- } else {
- dataStorage.set("spadepublic", defaultConfig);
- privateConfig = defaultConfig;
- }
-
- proxify(privateConfig);
-
- unsafeWindow.resetConfig = () => {
- dataStorage.set("spadepublic", defaultConfig);
- unsafeWindow.Config = {};
- privateConfig = defaultConfig;
- proxify(privateConfig);
- };
- })();
-
- let playing = () => {
- return false;
- };
-
- $(window).on("load", () => {
- (function setBack () {
- try {
- if (unsafeWindow.input.should_prevent_unload) {
- playing = () => {
- return !!unsafeWindow.input.should_prevent_unload();
- };
- }
- } catch (error) {
- setTimeout(() => {
- setBack();
- }, 100);
- }
- })();
- });
-
- let canvas, ctx;
- $(() => {
- canvas = $("#canvas").get(0);
- ctx = canvas.getContext("2d");
- });
-
- HTMLElement.prototype.focus = () => {};
- HTMLElement.prototype.blur = () => {};
-
- const capitalizeFirstLetter = (string) => {
- return string && string[0].toUpperCase() + string.slice(1);
- };
-
- const createEl = (elObj, parent) => {
- let element;
- if (typeof elObj === "string") {
- element = $(document.createTextNode(elObj));
- } else {
- element = $(`<${elObj.node}>`);
- if (elObj.att) {
- let attributes = elObj.att;
- for (let key in attributes) {
- if (attributes.hasOwnProperty(key)) {
- if (key.charAt(0) === "@") {
- element.attr(key.substring(1), attributes[key]);
- } else {
- element.text(attributes[key]);
- }
- }
- }
- }
- if (elObj.evl) {
- element.on(elObj.evl.type, elObj.evl.f);
- }
- if (elObj.child) {
- elObj.child.forEach((node) => {
- createEl(node, element.get(0));
- });
- }
- }
- if (parent) {
- parent.append(element.get(0));
- }
- return element;
- };
-
- const scriptBody = $("<body>").get(0);
- createEl({
- node: "div", att: {"@id": "main", "@class": "base"},
- child: [ {
- node: "div", att: {"@class": "top"},
- child: [ {
- node: "h2", att: {"@class": "title"},
- child: [ {
- node: "span", att: {"@class": "spadesymbol", textContent: "♠"}
- }, " Select diep.io Server ", {
- node: "span", att: {"@class": "spadesymbol", textContent: "♠"}
- }, {
- } ]
- }, {
- node: "span", att: {"@class": "menu"},
- child: [ {
- node: "a", att: {"@class": "menuButton close", textContent: "X"},
- evl: {
- type: "click",
- f: () => {
- $(".appear").removeClass("appear");
- }}
- } ]
- }]
- }, {
- node: "lable", att: {textContent: "Gamemode"},
- child: [ {
- node: "select", att: {"@id": "gamemode"}
- } ]
- }, {
- node: "lable", att: {textContent: "Server"},
- child: [ {
- node: "select", att: {"@id": "server"}
- } ]
- }, {
- node: "span", att: {"@id": "more", textContent: "+"}
- }, {
- node: "div",
- child: [ {
- node: "button", att: {"@type": "button", "@id": "connect", "@class": "commandButton", textContent: "Connect"},
- evl: {
- type: "click",
- f: () => {
- connectServer();
- setTimeout(() => {
- $(".appear").removeClass( "appear" );
- }, 800);
- }}
- }, {
- node: "button", att: {"@type": "button", "@id": "disconnect", "@class": "commandButton", textContent: "Disconnect"},
- evl: {
- type: "click",
- f: () => {
- unsafeWindow.m28nOverride = false;
- unsafeWindow.input.execute("lb_reconnect");
- }}
- } ]
- }, {
- node: "p", att: {"@class": "ctag", textContent: "// © "},
- child: [ {
- node: "a", att: {"@class": "spadeweb", "@href": "http://spade-squad.com", "@target": "_blank", textContent: "spade-squad.com"}
- } ]
- } ]
- }, scriptBody);
-
- $(() => {
- // View script info only on firstRun
- if (!unsafeWindow.Config.settings.firstRunDisable) {
- createEl({
- node: "div", att: {"@id": "firstrun", "@class": "base appear"},
- child: [ {
- node: "div", att: {"@class": "top"},
- child: [ {
- node: "h2", att: {"@class": "title"},
- child: [ {
- node: "span", att: {"@class": "spadesymbol", textContent: "♠"}
- }, " Spade Script - First Run ", {
- node: "span", att: {"@class": "spadesymbol", textContent: "♠"}
- } ]
- }, {
- node: "span", att: {"@class": "menu"},
- child: [ {
- node: "a", att: {"@class": "menuButton close", textContent: "X"},
- evl: {
- type: "click",
- f: () => {
- $("#firstrun").removeClass("appear");
- unsafeWindow.Config.settings.firstRunDisable = true;
- }}
- } ]
- } ]
- }, {
- node: "ul", att: {"@class": "settingslist"},
- child: [ {
- node: "h3", att: {"@class": "intro", textContent: "Spade Script was successfully installed and started"}
- }, {
- node: "li",
- child: ["- Press TAB to toggle the Server Selector."]
- }, {
- node: "li",
- child: ["- In the top right corner of a window is a X-Button to close it and O-Button so accesss aditional options."]
- }, {
- node: "li",
- child: ["- You are using the PUBLIC version with reduced features. Check out our Website/Discord for updates and please report any bugs."]
- }, {
- node: "li",
- child: ["- This info is only shown on the first start. Just close it and it won't appear again."]
- }
- ]
- } ]
- }, scriptBody);
- }
- });
-
- $("body").after(scriptBody);
-
- /* jshint ignore:start */
- const fetchServer = async (mode, times, ids = []) => {
- const url = "https://api.n.m28.io";
- const $serverSelect = $("#server");
- const $moreButton = $("#more");
- $moreButton.addClass("spin");
-
- for (let i = 0; i < times; i++) {
- try {
- const response = await fetch(`${url}/endpoint/diepio-${mode}/findEach/`);
- const body = await response.json();
- if (body.hasOwnProperty("servers")) {
- Object.entries(body.servers).forEach(([key, val]) => {
- if (!ids.some((id) => {
- return id === val.id;
- })) {
- ids.push(val.id);
- const txt = key.replace(/(linode-|vultr-)/, "") + ` - ${val.id.toUpperCase()}`;
- $serverSelect.append($("<option>", {
- "value": JSON.stringify(val),
- "text": capitalizeFirstLetter(txt)
- }));
- }
- });
- }
- } catch (err) {
- console.error(err);
- }
- }
- $("#server option").detach().sort((a, b) => {
- a = $(a);
- b = $(b);
- return ((a.text() > b.text()) ?
- 1 :
- (a.text() < b.text()) ?
- -1 :
- 0);
- }).appendTo($serverSelect).filter(":first").attr("selected", true);
- $moreButton.on("click", () => {
- fetchServer(mode, 4, ids);
- }).removeClass("spin");
- };
- /* jshint ignore:end */
-
- $(() => {
- const $gamemode = $("#gamemode");
- Object.entries(unsafeWindow.Config.gameModeName).forEach(([key, val]) => {
- $gamemode.append($("<option>", {
- "value": key,
- "text": val
- }));
- });
- $gamemode.change((event) => {
- $("#server").empty();
- fetchServer($(event.currentTarget).val(), 8, []);
- }).trigger("change");
- });
-
- $(() => {
- unsafeWindow.m28n.findServerPreference = (endpoint, options, cb) => {
- if (unsafeWindow.m28nOverride)
- options(null, [JSON.parse($( "#server option:selected" ).val())]);
- if (typeof options == "function") {
- cb = options;
- options = {};
- }
- unsafeWindow.m28n.findServers(endpoint, (err, r) => {
- if (err)
- return cb(err);
- var availableRegions = [];
- for (var region in r.servers) {
- availableRegions.push(region);
- }
- if (availableRegions.length === 0) {
- cb("Couldn't find any servers in any region");
- return;
- }
- if (availableRegions.length === 1) {
- for (var region in r.servers) {
- cb(null, [r.servers[region]]);
- return;
- }
- }
- unsafeWindow.m28n.findRegionPreference(availableRegions, options, (err, regionList) => {
- if (err)
- return cb(err);
- var serverList = regionList.map((region) => {
- return r.servers[region];
- });
- cb(null, serverList);
- });
- });
- };
- });
-
- const connectServer = () => {
- if ($("#server option:selected").length === 1) {
- const $autojoin = $("#autojoin");
- const $connect = $("#connect");
-
- let Observer = new MutationObserver(mutation => {
- mutation.forEach(mutation => {
- if (mutation.target.style.display === "block") {
- if ($autojoin.prop("checked")) {
- const sequence = ["keydown", "keyup"];
- sequence.forEach(event => {
- $(canvas).trigger($.Event(event, {
- "keyCode": "\r".charCodeAt(0)
- }));
- });
- $(".appear").removeClass("appear");
- }
- $connect.removeClass("connecting");
- } else if (mutation.target.style.display === "none") {
- if (playing()) {
- Observer.disconnect();
- }
- unsafeWindow.m28nOverride = false;
- }
- });
- });
- $connect.addClass("connecting");
- unsafeWindow.m28nOverride = true;
- unsafeWindow.input.execute("lb_reconnect");
- Observer.observe($("#textInputContainer").get(0), {
- "attributes": true,
- "attributeFilter": ["style"]
- });
- }
- };
-
- const WebSocketProxy = new Proxy(unsafeWindow.WebSocket, {
- construct (Target, args) {
- const instance = new Target(...args);
-
- const messageHandler = (event) => {
- const buffer = new DataView(event.data);
- const opcode = buffer.getUint8(0);
- switch (opcode) {
- case 4:
- if (typeof unsafeWindow.Config.script.currentServer === "object") {
- const decoded = new TextDecoder("utf-8").decode(event.data);
- unsafeWindow.Config.script.currentServer = (/\W*(\w+).?((linode|vultr)-(\w+))/).exec(decoded);
- unsafeWindow.Config.script.currentServer[4] = capitalizeFirstLetter(unsafeWindow.Config.script.currentServer[4]);
- }
- break;
- default:
- break;
- }
- };
-
- instance.addEventListener("message", messageHandler);
- return instance;
- }
- });
-
- unsafeWindow.WebSocket = WebSocketProxy;
-
- const drawServer = () => {
- const x = window.innerWidth * window.devicePixelRatio / 2;
- const y = window.innerHeight * window.devicePixelRatio * 0.575;
- if (unsafeWindow.Config.script.currentServer.length === 5) {
- ctx.textAlign = "center";
- ctx.font = "25px Ubuntu";
- ctx.lineWidth = 5;
- ctx.strokeStyle = "rgba(0, 0, 0, 1)";
- ctx.strokeText("Server:", x, y);
- ctx.fillStyle = "rgba(255, 255, 255, 1)";
- ctx.fillText("Server:", x, y);
-
- ctx.font = "35px Ubuntu";
- ctx.lineWidth = 5;
- ctx.strokeStyle = "rgba(0, 0, 0, 1)";
- ctx.strokeText(unsafeWindow.Config.script.currentServer[2], x, y + 45);
- ctx.fillStyle = "rgba(255, 255, 255, 1)";
- ctx.fillText(unsafeWindow.Config.script.currentServer[2], x, y + 45);
- }
- };
-
- unsafeWindow.requestAnimFrame = (function () {
- return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame ||
- window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback, element) {
- window.setTimeout(callback, 1000 / 60);
- };
- })();
-
- $(window).on("load", function animate () {
- if ($("#textInputContainer").css("display") === "block" && !playing()) {
- drawServer();
- }
- unsafeWindow.requestAnimFrame(animate);
- });
-
- const handleKeypress = (event) => {
- const key = String.fromCharCode(event.keyCode);
- switch (key) {
- case unsafeWindow.Config.hotkey.connectUI:
- event.preventDefault();
- event.stopPropagation();
- $("#main").toggleClass("appear");
- break;
- }
- };
-
- $(document).keydown((event) => {
- handleKeypress(event);
- });
-
- })();