您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Shared library for TankTrouble userscript development
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greatest.deepsurf.us/scripts/482092/1301930/TankTrouble%20Development%20Library.js
// ==UserScript== // @name TankTrouble Development Library // @author commander // @namespace https://github.com/asger-finding // @version 0.0.5 // @license GPL-3.0 // @description Shared library for TankTrouble userscript development // @match *://*.tanktrouble.com/* // @grant none // @run-at document-start // @noframes // ==/UserScript== /* eslint-disable no-unused-vars */ class Loader { /** * Pass a function to a hook with the correct context * @param context Function context (e.g `window`) * @param funcName Function identifier in the context * @param hook Hook to call before the original */ static hookFunction(context, funcName, hook) { const original = Reflect.get(context, funcName); if (typeof original !== 'function') throw new Error('Item passed is not typeof function'); Reflect.defineProperty(context, funcName, { /** * Call the hook with the original function bound to its context * and supply with the arguments list * @param args Arguments passed from outside * @returns Original function return value */ value: (...args) => hook(original.bind(context), ...args) }); } /** * Fires when the `main()` function is done on TankTrouble. * @returns Promise that resolves when Content.init() finishes */ static whenContentInitialized() { if (GM.info.script.runAt !== 'document-start') return Loader.#hookContentInit(); return whenContentLoaded().then(() => Loader.#hookContentInit()); } /** * Fires when the document is readyState `interactive` or `complete` * @returns Promise that resolves upon content loaded */ static whenContentLoaded() { return new Promise(resolve => { if (document.readyState === 'interactive' || document.readyState === 'complete') resolve(); else document.addEventListener('DOMContentLoaded', () => resolve()); }); } /** * Apply a hook to the Content.init function which resolves when the promise ends * @returns Promise when Content.init has finished * @private */ static #hookContentInit() { return new Promise(resolve => { const { init } = Content; Reflect.defineProperty(Content, 'init', { /** * Resolve after Content.init call finishes * @param args Arguments to pass * @returns Function call return value */ value: (...args) => { const result = init(...args); resolve(); return result; } }); }); } }