From 2ad8b310666761ca4ede899ac8bd6e2e6c780167 Mon Sep 17 00:00:00 2001 From: liooil Date: Sun, 8 Dec 2024 11:25:33 +0800 Subject: [PATCH] add helper --- evolve-helper.js | 216 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 evolve-helper.js diff --git a/evolve-helper.js b/evolve-helper.js new file mode 100644 index 0000000..493ed2f --- /dev/null +++ b/evolve-helper.js @@ -0,0 +1,216 @@ +// ==UserScript== +// @name Evolve Helper +// @namespace http://tampermonkey.net/ +// @version 2024-12-06 +// @description accerlate and automate +// @author liooil +// @match https://pmotschmann.github.io/Evolve/ +// @icon https://www.google.com/s2/favicons?sz=64&domain=github.io +// @grant none +// ==/UserScript== + +let autoIds = getStrSet("autoIds") ?? new Set(); +let vueMethod; + +let scanTimer = setInterval(scan, getInt("scanInterval") ?? 1000); +let autoTimer = setInterval(auto, getInt("autoInterval") ?? 100); + +function scan() { + const versionLogEl = document.getElementById("versionLog"); + if (versionLogEl) { + menuBtn(versionLogEl, "scanInterval", "int", 1000, (val) => { + clearInterval(scanTimer); + scanTimer = setInterval(scan, val); + }); + menuBtn(versionLogEl, "autoInterval", "int", 100, (val) => { + clearInterval(autoTimer); + autoTimer = setInterval(scan, val); + }); + menuBtn(versionLogEl, "customSpeed", "int", 1, () => { + if (!vueMethod._data.s.pause) { + fromScript = true; + vueMethod.pause(); + } + }); + menuBtn(versionLogEl, "autoRun", "bool", true); + vueMethod = document.getElementById("topBar").__vue__; + } + for (const node of document.querySelectorAll("div.action.vb")) { + autoBtn(node, node.firstChild); + } + for (const node of document.querySelectorAll("div.resource.crafted")) { + if (node.style.display === "none") continue; + autoBtn(node, node.firstChild); + } + for (const node of document.getElementById("market")?.querySelectorAll("div.market-item") ?? []) { + if (node.style.display === "none") continue; + for (const type of ['buy', 'sell']) { + const span = node.querySelector('span.' + type); + if (!span) continue; + autoBtn(span, span, node.id + '-' + type); + } + } +} + +function auto() { + if (!getBool("autoRun")) return; + for (const id of autoIds) { + for (const type of ['buy', 'sell']) { + if (id.endsWith('-' + type)) { + const el = document.getElementById(id.slice(0, -type.length - 1)); + if (!el) continue; + const prev = el.querySelector('span.' + type); + if (!prev) continue; + prev.nextElementSibling.click(); + } + } + const el = document.getElementById(id); + if (!el || el.classList.contains("cna")) continue; + /** @type {HTMLElement} */ + const a = el.querySelector("a.button,a:has(span[data-val='A'])"); + if (a) a.click(); + } +} + +/** + * @param {string} key + * @param {number} defaultVal + */ +function useInt(key, defaultVal) { + let text = localStorage.getItem(key); + let val = text ? parseInt(text) : defaultVal; + return [ + () => val, + /** @type {(val: number) => void} */ + (v) => { + val = v; + localStorage.setItem(key, v.toString()); + } + ]; +} + +/** + * @param {string} key + */ +function getInt(key) { + const val = localStorage.getItem(key); + if (val !== null) return parseFloat(val); +} +/** + * @param {string} key + * @param {number} val + */ +function setInt(key, val) { + localStorage.setItem(key, val) +} +/** + * @param {string} key + */ +function getStrSet(key) { + const val = localStorage.getItem(key); + if (val !== null) return new Set(val.split(",")); +} +/** + * @param {string} key + * @param {Set} val + */ +function setStrSet(key, val) { + localStorage.setItem(key, [...val.keys()].join(",")) +} +/** + * @param {string} key + */ +function getBool(key) { + const val = localStorage.getItem(key); + if (val !== null) return val === "true"; +} +/** + * @param {string} key + * @param {boolean} val + */ +function setBool(key, val) { + localStorage.setItem(key, val.toString()); +} + +/** + * @param {HTMLElement} nextElementSibling + * @param {string} id + * @param {"int" | "bool"} type + * @param {number} defaultVal + * @param {(val: number) => void} cb + */ +function menuBtn(nextElementSibling, id, type, defaultVal, cb) { + if (document.getElementById(id)) return; + const el = document.createElement("span"); + el.id = id; + el.classList.add("version"); + el.style.cursor = "pointer"; + el.textContent = `${id}=${getInt(id) ?? defaultVal}`; + el.onclick = () => { + let val; + if (type === "bool") { + val = !(getBool(id) ?? defaultVal); + setBool(id, val); + } else { + let input = prompt(`${id}=`, `${getInt(id) ?? defaultVal}`); + if (input === null) return; + val = parseInt(input) + setInt(id, input); + } + el.textContent = `${id}=${val}`; + cb?.(val); + } + nextElementSibling.before(el); + return el; +} + +/** + * add auto button + * @param {HTMLElement} root + * @param {HTMLElement?} parent + */ +function autoBtn(root, parent = root, id = root.id) { + /** @type {HTMLButtonElement} */ + let auto = root.querySelector(".auto"); + if (!auto) { + auto = parent.appendChild(document.createElement("span")); + auto.classList.add("auto"); + auto.textContent = "A"; + auto.onclick = (e) => { + e.preventDefault(); + e.stopPropagation(); + if (autoIds.has(id)) { + autoIds.delete(id); + auto.style.color = "gray"; + } else { + autoIds.add(id); + auto.style.color = "green"; + } + setStrSet("autoIds", autoIds); + } + } + if (autoIds.has(id)) { + auto.style.color = "green"; + } else { + auto.style.color = "gray"; + } +} + +let fromScript = false; + +const oldPost = Worker.prototype.postMessage; +Worker.prototype.postMessage = async function (...args) { + let that = this + async function hookPost() { + if (args[0].period) { + args[0].period = args[0].period / (getInt("customSpeed") ?? 1) + } + oldPost.apply(that, args) + } + let hookResult = await hookPost() + if (fromScript) { + vueMethod.pause() + fromScript = false + } + return hookResult +}