Uses a Web Worker to ensure high-precision timing for setInterval and setTimeout.
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyfork.org/scripts/552983/1679680/HackTimer%20V1.js
// ==UserScript==
// @license MIT
// @name HackTimer V1
// @namespace HackTimer
// @version 1.0.0
// @description Uses a Web Worker to ensure high-precision timing for setInterval and setTimeout.
// @grant none
// ==/UserScript==
(function (workerScript) {
'use strict';
let worker,
fakeIdToCallback = {},
lastFakeId = 0,
maxFakeId = 0x7FFFFFFF, // 2^31 - 1
logPrefix = 'HackTimer.js: ';
// --- Worker Script Definition (Inlined for Greasemonkey/Userscript) ---
const workerCode = `
var fakeIdToId = {};
onmessage = function (event) {
var data = event.data,
name = data.name,
fakeId = data.fakeId,
time = data.time;
switch (name) {
case 'setInterval':
fakeIdToId[fakeId] = setInterval(function () {
postMessage({fakeId: fakeId});
}, time);
break;
case 'clearInterval':
if (fakeIdToId.hasOwnProperty(fakeId)) {
clearInterval(fakeIdToId[fakeId]);
delete fakeIdToId[fakeId];
}
break;
case 'setTimeout':
fakeIdToId[fakeId] = setTimeout(function () {
postMessage({fakeId: fakeId});
if (fakeIdToId.hasOwnProperty(fakeId)) {
delete fakeIdToId[fakeId];
}
}, time);
break;
case 'clearTimeout':
if (fakeIdToId.hasOwnProperty(fakeId)) {
clearTimeout(fakeIdToId[fakeId]);
delete fakeIdToId[fakeId];
}
break;
}
};
`;
// ----------------------------------------------------------------------
// Attempt to create a Worker Blob URL
if (typeof Worker !== 'undefined') {
try {
const blob = new Blob([workerCode], { type: 'application/javascript' });
workerScript = window.URL.createObjectURL(blob);
} catch (error) {
console.error(logPrefix + 'Blob Worker creation failed:', error);
// Fallback to external script if Blob is not supported (unlikely in modern browsers)
}
}
function getFakeId() {
do {
lastFakeId = (lastFakeId >= maxFakeId) ? 1 : lastFakeId + 1;
} while (fakeIdToCallback.hasOwnProperty(lastFakeId));
return lastFakeId;
}
if (typeof Worker !== 'undefined') {
try {
worker = new Worker(workerScript);
// --- Override setInterval ---
window.setInterval = function (callback, time /* , parameters */) {
const fakeId = getFakeId();
fakeIdToCallback[fakeId] = {
callback: callback,
parameters: Array.prototype.slice.call(arguments, 2)
};
worker.postMessage({
name: 'setInterval',
fakeId: fakeId,
time: time
});
return fakeId;
};
// --- Override clearInterval ---
window.clearInterval = function (fakeId) {
if (fakeIdToCallback.hasOwnProperty(fakeId)) {
delete fakeIdToCallback[fakeId];
worker.postMessage({
name: 'clearInterval',
fakeId: fakeId
});
}
};
// --- Override setTimeout ---
window.setTimeout = function (callback, time /* , parameters */) {
const fakeId = getFakeId();
fakeIdToCallback[fakeId] = {
callback: callback,
parameters: Array.prototype.slice.call(arguments, 2),
isTimeout: true
};
worker.postMessage({
name: 'setTimeout',
fakeId: fakeId,
time: time
});
return fakeId;
};
// --- Override clearTimeout ---
window.clearTimeout = function (fakeId) {
if (fakeIdToCallback.hasOwnProperty(fakeId)) {
delete fakeIdToCallback[fakeId];
worker.postMessage({
name: 'clearTimeout',
fakeId: fakeId
});
}
};
// --- Worker Message Handler ---
worker.onmessage = function (event) {
const data = event.data;
const fakeId = data.fakeId;
if (fakeIdToCallback.hasOwnProperty(fakeId)) {
const request = fakeIdToCallback[fakeId];
let callback = request.callback;
const parameters = request.parameters;
if (request.isTimeout) {
delete fakeIdToCallback[fakeId];
}
if (typeof callback === 'string') {
try {
// Dangerous but necessary if string callbacks are passed
callback = new Function(callback);
} catch (error) {
console.error(logPrefix + 'Error parsing callback code string:', error);
return;
}
}
if (typeof callback === 'function') {
callback.apply(window, parameters);
}
}
};
worker.onerror = function (event) {
console.error(logPrefix + 'Worker error:', event);
};
} catch (error) {
console.error(logPrefix + 'Initialisation failed (Worker runtime error):', error);
}
} else {
console.warn(logPrefix + 'Initialisation failed - HTML5 Web Worker is not supported. Using standard timers.');
}
})('HackTimerWorker.js'); // Keeping original script name for potential external loading fallback