您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Press TAB to show Server Selector.
当前为
// ==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); }); })();