您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Does some shenanigans to recreate a class tree. SHIFT + M to open the mockup browser.
// ==UserScript== // @name Woomy Mockup Browser // @namespace http://tampermonkey.net/ // @version 1.0 // @description Does some shenanigans to recreate a class tree. SHIFT + M to open the mockup browser. // @author PowfuArras // Discord: @xskt // @match *://*.woomy.app/* // @icon https://www.google.com/s2/favicons?sz=64&domain=woomy.app // @grant none // @run-at document-start // @license FLORRIM DEVELOPER GROUP LICENSE (https://github.com/Florrim/license/blob/main/LICENSE.md) // ==/UserScript== (function() { "use strict"; let socket = null; const postMessageToUser = (function () { let intervalID = null; function post(message) { socket.dispatchEvent(new MessageEvent("message", { data: protocol.encode(["displayText", message.length !== 0, message, "#FFFFFF"]) })); } return function text(message) { clearInterval(intervalID); post(message); intervalID = setTimeout(function () { post(""); }, 2500); }; })(); const mockups = { count: 0, entries: new Map(), getByName(name) { const values = [...this.entries.values()]; return values[values.findIndex(m => m.name === name)]; } }; const natives = { log: console.log, send: WebSocket.prototype.send }; WebSocket.prototype.send = function (data) { natives.send.call(this, data); WebSocket.prototype.send = natives.send; socket = this; } console.log = (...text) => void 0; const packets = { incoming: new Map(), outgoing: new Map() }; function addEntryToEntryMap(map, key, value) { if (!map.has(key)) map.set(key, [value]); else map.get(key).push(value); } const protocol = { encode: function (message, callback) { addEntryToEntryMap(packets.outgoing, message[0], message); return callback(message); }, decode: function (data, callback) { const message = callback(data); addEntryToEntryMap(packets.incoming, message[0], message); switch (message[0]) { case "da": mockups.count = message[3]; break; case "mu": mockups.entries.set(message[1], JSON.parse(message[2])); break; } return message; } }; for (const key in protocol) { const callback = protocol[key]; Object.defineProperty(Object.prototype, key, { get() { return function (data) { return callback(data, protocol[key]); }; }, set(value) { protocol[key] = value; } }); } Object.defineProperty(Object.prototype, "statsdata", { get() { return this._statsdata; }, set(value) { this._statsdata = value; natives.log(this); return value; } }); async function fetchMockups(doFetch) { if (doFetch) { postMessageToUser("Preparing for mockups."); mockups.entries.clear(); mockups.count = 0; postMessageToUser("Fetching mockup count."); socket.talk("da"); await new Promise((function () { let intervalID = null; return function (resolve) { intervalID = setInterval(function () { if (mockups.count !== 0) { clearInterval(intervalID); resolve(); } }, 10); } })()); let requested = 0; const digits = (Math.log10((mockups.count ^ (mockups.countx >> 31)) - (mockups.count >> 31)) | 0) + 1; postMessageToUser(`Mockups to fetch: ${mockups.count}.`); let intervalID = setInterval(function () { postMessageToUser(`Fetching Mockups. Requested: (${`${requested}`.padStart(digits, "0")}/${mockups.count}) Received: (${`${mockups.entries.size}`.padStart(digits, "0")}/${mockups.count})`); }, 20); for (let i = 0, length = mockups.count; i < length; i++) { setTimeout(function() { socket.talk("mu", i); requested++; }, i); } await new Promise((function () { let intervalID = null; return function (resolve) { intervalID = setInterval(function () { if (mockups.entries.size >= mockups.count) { clearInterval(intervalID); resolve(); } }, 10); } })()); clearInterval(intervalID); postMessageToUser(`Mockups fetched, opening mockup browser! Total: ${mockups.count}.`); } else { postMessageToUser(`Loading mockup browser without fetching new data.`); } const holder = document.createElement("div"); holder.style.position = "absolute"; holder.style.width = "100vw"; holder.style.height = "100vh"; holder.style.backgroundColor = "#00000088"; holder.style.top = "0"; holder.style.display = "flex"; holder.style.alignItems = "center"; holder.style.justifyContent = "center"; holder.style.zIndex = "101"; const body = document.createElement("div"); body.style.padding = "2vmin"; body.style.width = "70vmin"; body.style.height = "70vmin"; body.style.backgroundColor = "#CCCCCC"; body.style.borderRadius = "2vmin"; body.style.boxShadow = "0 0 1vmin #00000066, 0 0 2vmin #00000066"; body.style.overflowY = "scroll"; body.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 512px; width: 512px;"><g class="" transform="translate(0,0)" style=""><path d="M217 28.098v455.804l142-42.597V70.697zm159.938 26.88l.062 2.327V87h16V55zM119 55v117.27h18V73h62V55zm258 50v16h16v-16zm0 34v236h16V139zm-240 58.727V233H41v46h96v35.273L195.273 256zM244 232c6.627 0 12 10.745 12 24s-5.373 24-12 24-12-10.745-12-24 5.373-24 12-24zM137 339.73h-18V448h18zM377 393v14h16v-14zm0 32v23h16v-23zM32 471v18h167v-18zm290.652 0l-60 18H480v-18z" fill="#ff0000" fill-opacity="1"/></g></svg>`; const exitButton = body.childNodes[0]; exitButton.style.width = "8vmin"; exitButton.style.height = "8vmin"; exitButton.style.float = "right"; exitButton.style.filter = "drop-shadow(0 0 0.5vmin #00000066)"; exitButton.style.cursor = "pointer"; exitButton.onclick = function () { holder.remove(); postMessageToUser("Mockup browser closed"); }; holder.appendChild(body); function buildTree(mockup, parentElement, suffix, isRoot) { const liElement = document.createElement("li"); const spanElement = document.createElement("span"); liElement.style.fontSize = spanElement.style.fontSize = "2vmin"; spanElement.textContent = `${mockup.name} - ${mockup.index}${suffix}`; liElement.appendChild(spanElement); liElement.style.listStyle = "none"; liElement.style.margin = "0"; liElement.style.padding = "0"; if (!isRoot) liElement.style.marginLeft = "2vmin"; if (mockup.upgrades !== undefined) { let isHidden = true; spanElement.style.cursor = "pointer"; spanElement.textContent = `◇ ${spanElement.textContent}`; spanElement.onclick = function () { if (isHidden) { spanElement.textContent = `◈ ${spanElement.textContent.slice(2)}`; const ulElement = document.createElement("ul"); ulElement.style.margin = "0"; ulElement.style.padding = "0"; ulElement.style.marginLeft = "2vmin"; mockup.upgrades.forEach(function (upgrade) { buildTree(mockups.entries.get(upgrade.index), ulElement, ` - tier ${upgrade.tier}`, false); }); liElement.appendChild(ulElement); } else { spanElement.textContent = `◇ ${spanElement.textContent.slice(2)}`; liElement.children[1].remove(); } isHidden = !isHidden; }; } parentElement.appendChild(liElement); } const ulElement = document.createElement("ul"); ulElement.style.margin = "0"; ulElement.style.padding = "0"; buildTree(mockups.getByName("Basic"), ulElement, "", true); body.appendChild(ulElement); holder.appendChild(body); document.body.appendChild(holder); body.focus(); }; function doPrompt(text, options = []) { let choice = -1; const holder = document.createElement("div"); holder.style.position = "absolute"; holder.style.width = "100vw"; holder.style.height = "100vh"; holder.style.backgroundColor = "#00000088"; holder.style.top = "0"; holder.style.display = "flex"; holder.style.alignItems = "center"; holder.style.justifyContent = "center"; holder.style.zIndex = "102"; const body = document.createElement("div"); body.style.padding = "2vmin"; body.style.width = "60vmin"; body.style.height = "25vmin"; body.style.backgroundColor = "#CCCCCC"; body.style.borderRadius = "2vmin"; body.style.boxShadow = "0 0 1vmin #00000066, 0 0 2vmin #00000066"; body.style.overflowY = "scroll"; body.style.display = "flex"; body.style.flexDirection = "column"; const span = document.createElement("span"); span.textContent = text; span.style.fontSize = "2vmin"; body.appendChild(span); const buttonHolder = document.createElement("div"); buttonHolder.style.marginTop = "auto"; buttonHolder.style.display = "flex"; for (let i = 0; i < options.length; i++) { const option = options[i]; const iiiiiiii = i; switch (option.type) { case "button": { const button = document.createElement("div"); button.style.marginRight = "1vmin"; button.style.padding = "1vmin"; button.style.backgroundColor = option.color; button.style.display = "flex"; button.style.alignItems = "center"; button.style.justifyContent = "center"; button.style.width = "fit-content"; button.style.height = "3vmin"; button.style.borderRadius = "1vmin"; button.style.cursor = "pointer"; button.style.float = "bottom"; const text = document.createElement("p"); text.textContent = option.text; text.style.color = "#FFFFFF"; text.style.fontSize = "2vmin"; button.appendChild(text); buttonHolder.appendChild(button); button.addEventListener("click", function () { choice = iiiiiiii; holder.remove(); }); }; break; } } body.appendChild(buttonHolder); holder.appendChild(body); document.body.appendChild(holder); body.focus(); let intervalID = null; return new Promise(resolve => { intervalID = setInterval(function () { if (choice !== -1) { resolve(choice); clearInterval(intervalID); } }, 10); }); } window.addEventListener("load", function () { let nextTime = 0; let hasData = false; document.getElementById("gameCanvas").addEventListener("keydown", async function (event) { if (event.shiftKey && event.keyCode === 77) { const now = performance.now(); if (nextTime > now) { postMessageToUser(`Please wait 20 seconds between fetching mockups! Time: (${(Math.ceil((nextTime - now) * 0.01) * 0.1) | 0}/20)`); return; } nextTime = performance.now() + 20_000; if (hasData) { const option = await doPrompt("Do you want to refetch or use cache?", [{ type: "button", color: "#00AA00", text: "Yes, refetch" }, { type: "button", color: "#AA0000", text: "No, use cache" }]); fetchMockups(option === 0); } else { fetchMockups(true); hasData = true; } } }); }); window.packeteer = { protocol: protocol, packets: packets, natives: natives, mockups: mockups, doPrompt: doPrompt, get socket() { return socket; } }; })();