diep.io Spade Script - Public

Press TAB to show Server Selector.

Author
Diep.ro.PianoYT youtube
Daily installs
1
Total installs
5,753
Ratings
0 0 1
Version
1.0.0
Created
2020-01-09
Updated
2020-01-09
License
N/A
Applies to

// ==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 = $("").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($("

", {
"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($("

", {
"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);
});

})();