您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Helpful script dedicated to Minecraft players.
// ==UserScript== // @name Minecraft Helper Rev // @namespace http://tampermonkey.net/ // @version 0.1.0 // @description Helpful script dedicated to Minecraft players. // @author PRO // @license gpl-3.0 // @match https://www.minecraft.net/* // @match https://www.curseforge.com/* // @match https://modrinth.com/* // @icon https://www.minecraft.net/etc.clientlibs/minecraftnet/clientlibs/clientlib-site/resources/favicon.ico // @grant unsafeWindow // @grant GM_setValue // @grant GM_getValue // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @grant GM_addValueChangeListener // @require https://github.com/PRO-2684/GM_config/releases/download/v1.2.2/config.min.js#md5=c45f9b0d19ba69bb2d44918746c4d7ae // ==/UserScript== (function () { "use strict"; const { name, version } = GM_info.script; const debug = console.debug.bind(console, `[${name}@${version}]`); const warn = console.warn.bind(console, `[${name}@${version}]`); GM_config.extend("list", { value: [], processor: (_prop, input, _desc) => input.split(",").map((s) => s.trim()), formatter: (_prop, value, desc) => `${desc.name}: ${value.join(", ")}`, }); const configDesc = { "$default": { autoClose: false }, general: { name: "⚙️ General", title: "General settings", type: "folder", items: { timeout: { name: "Timeout", title: "General timeout value in milliseconds", type: "int", value: 500, min: 1, }, }, }, minecraft: { name: "🪓 Minecraft.net", title: "Settings for Minecraft.net", type: "folder", items: { autoStay: { name: "Auto Stay", title: "Automatically click the 'Stay on Minecraft.net' button", type: "bool", value: true, }, }, }, curseforge: { name: "📦 CurseForge", title: "Settings for CurseForge", type: "folder", items: { autoMod: { name: "Auto Navigate to MC Mods", title: "Automatically navigate to MC Mods on the homepage", type: "bool", value: true, }, highlightFiles: { name: "Highlight Files Tab", title: "Highlight the Files tab on mod pages", type: "bool", value: true, }, highlightBorder: { name: "Highlight Border Style", title: "CSS border style for highlighting the Files tab", value: "rgb(241, 100, 54) 0.2em solid", }, shortcut: { name: "Keyboard Shortcuts", title: "Enable keyboard shortcuts", type: "bool", value: true, }, }, }, modrinth: { name: "🔧 Modrinth", title: "Settings for Modrinth", type: "folder", items: { autoMod: { name: "Auto Navigate to Mods", title: "Automatically navigate to the Mods page on the homepage", type: "bool", value: true, }, shortcut: { name: "Keyboard Shortcuts", title: "Enable keyboard shortcuts", type: "bool", value: true, }, filter: { name: "Filter", title: "Default filters applied when searching for mods", type: "folder", items: { loader: { name: "Loader", title: "Default loader(s) for mod searches", type: "list", value: ["fabric"], }, version: { name: "Version", title: "Default Minecraft version(s) for mod searches", type: "list", value: [], }, channel: { name: "Channel", title: "Default channel(s) for mod searches", type: "list", value: [], }, }, }, }, }, }; const config = new GM_config(configDesc); /** * Try to click an element. * @param {string} selector The query selector. */ function tryClick(selector) { const ele = document.querySelector(selector); if (ele) { ele.click(); return true; } return false; } /** * Setup shortcuts. * @param {string[]} selectors The selectors. [left, right, pre-search, search] * @param {Function} filter The filter function. * @param {number} timeout Timeout in milliseconds. */ function setupShortcuts(selectors, filter, timeout) { const nodeNames = ["INPUT", "TEXTAREA"]; document.addEventListener("keydown", (e) => { if (!nodeNames.includes(document.activeElement.nodeName) && !e.altKey && !e.ctrlKey && !e.metaKey && !e.shiftKey) { switch (e.key) { case "ArrowLeft": tryClick(selectors[0]); break; case "ArrowRight": tryClick(selectors[1]); break; case "f": filter(); break; case "s": if (selectors[2].length) { tryClick(selectors[2]); window.setTimeout(() => { const search = document.querySelector(selectors[3]); if (search) search.focus(); }, timeout); } else { const search = document.querySelector(selectors[3]); if (search) search.focus(); } e.preventDefault(); break; default: break; } } else if (document.activeElement.value == "") { switch (e.key) { case "Escape": document.activeElement.blur(); break; case "ArrowLeft": tryClick(selectors[0]); break; case "ArrowRight": tryClick(selectors[1]); break; default: break; } } }) debug("⚙️ Shortcuts installed!"); } switch (window.location.host) { case 'www.minecraft.net': { config.down("minecraft"); if (config.get("minecraft.autoStay")) { let attempts = 16; const timer = window.setInterval(() => { const success = tryClick("button[data-aem-contentname='close-icon']") || tryClick("button.btn.btn-link#popup-btn"); if (success) { debug("✋ Auto stayed!"); window.clearInterval(timer); } else if (--attempts <= 0) { warn("❌ Auto stay failed!"); window.clearInterval(timer); } }, config.get("general.timeout")); } break; } case 'www.curseforge.com': { config.down("curseforge"); if (config.get("curseforge.autoMod") && window.location.pathname == '/') { debug("🛣️ Navigating to mc mods..."); window.location.pathname = "/minecraft/mc-mods"; } const tabs = document.getElementsByClassName("tabs"); let fileTab = undefined; if (tabs.length) { for (const tab of tabs[0].children) { if (tab.textContent == "Files") { fileTab = tab; break; } } } if (config.get("curseforge.highlightFiles") && window.location.pathname != "/") { fileTab.style.border = config.get("curseforge.highlightBorder"); } if (config.get("curseforge.shortcut")) { setupShortcuts([".btn-prev", ".btn-next", "", "input.search-input-field"], () => { fileTab?.firstElementChild?.click(); }); } break; } case "modrinth.com": { config.down("modrinth"); if (window.location.pathname == "/" && config.get("modrinth.autoMod")) { debug("🛣️ Navigating to mod search page..."); tryClick("a[href='/mods']"); } function filter() { const router = document.getElementById("__nuxt").__vue_app__.$nuxt.$router; if (router.currentRoute.value.name === "type-id") { const path = router.currentRoute.value.path; router.push({ path: path + "/versions", query: { "l": config.get("modrinth.filter.loader"), "g": config.get("modrinth.filter.version"), "c": config.get("modrinth.filter.channel"), } }); } } if (config.get("modrinth.shortcut")) { setupShortcuts([".btn-wrapper > a[aria-label='Previous Page']", ".btn-wrapper > a[aria-label='Next Page']", "a[href='/mods']", "input[placeholder='Search mods...']"], filter); } break; } } })();