// ==UserScript== // @name 通用时间加速器(修复浮窗显示) // @namespace http://tampermonkey.net/ // @version 1.6 // @description 修复浮窗消失问题,确保UI正确显示 // @author ZMM // @match *://*/* // @grant none // @run-at document-start // ==/UserScript== (function () { 'use strict'; /* ========== 配置持久化 ========== */ const CFG_KEY = '__time_cheat_cfg__'; const defaultCfg = { enabled: false, multiplier: 2 // 默认2倍速 }; let cfg = Object.assign({}, defaultCfg); try { cfg = Object.assign(cfg, JSON.parse(localStorage.getItem(CFG_KEY) || '{}')); } catch (e) { localStorage.removeItem(CFG_KEY); } function saveCfg() { localStorage.setItem(CFG_KEY, JSON.stringify(cfg)); } /* ========== 核心:绝对稳定的时间加速引擎 ========== */ // 1. 保存原始函数(关键:Date.now 必须恢复原始行为) const OrigPerfNow = performance.now.bind(performance); const OrigDateNow = Date.now; // 2. 初始化时间引擎变量 let lastRealPerfTime = OrigPerfNow(); let fakePerfTime = lastRealPerfTime; let timeEngineEnabled = false; // 3. 劫持 performance.now(仅用于游戏逻辑加速) function safePerfNow() { const realNow = OrigPerfNow(); const delta = realNow - lastRealPerfTime; lastRealPerfTime = realNow; // 防止时间跳跃过大(如切后台再切回来) if (delta > 0 && delta < 10000) { // 允许10秒内的跳跃,避免异常重置 if (timeEngineEnabled) { const multiplier = Number(cfg.multiplier) || 1; fakePerfTime += delta * multiplier; } else { fakePerfTime += delta; // 即使没开启,也要让 fakePerfTime 跟上真实时间,避免停滞 } } else { // 跳跃过大,直接对齐真实时间,避免负数 fakePerfTime = realNow; } return fakePerfTime; } // 4. 劫持 Date.now(关键修复:恢复原始行为,不再依赖 performance.now) Date.now = OrigDateNow; // 直接使用原始 Date.now,返回系统当前时间 // 5. 启用/禁用时间引擎 function enableTimeEngine() { timeEngineEnabled = true; performance.now = safePerfNow; // 启用加速 } function disableTimeEngine() { timeEngineEnabled = false; performance.now = OrigPerfNow; // 恢复原始 performance.now } /* ========== 注入 UI:可移动浮窗(彻底修复) ========== */ function injectUI() { try { // 1. 注入CSS样式(确保样式正确加载) const css = document.createElement('style'); css.textContent = ` #time-cheat-btn{ position:fixed; z-index:2147483647; width:42px; height:42px; border-radius:50%; border:2px solid #4CAF50; background:linear-gradient(135deg,#2E7D32 0%,#4CAF50 100%); color:#fff; font:bold 18px/42px sans-serif; text-align:center; cursor:pointer; user-select:none; box-shadow:0 2px 12px rgba(0,0,0,.6); transition:transform .15s,box-shadow .15s; right:16px; top:16px; touch-action:none; } #time-cheat-btn:hover{ transform:scale(1.12); box-shadow:0 0 18px rgba(76,175,80,.5); } #time-cheat-panel{ position:fixed; z-index:2147483646; right:70px; top:16px; width:280px; max-height:90vh; overflow-y:auto; background:rgba(30,30,30,.95); border:1.5px solid #4CAF50; border-radius:10px; box-shadow:0 4px 30px rgba(0,0,0,.7); font:13px/1.5 'Segoe UI',sans-serif; color:#e0e0e0; transition:opacity .2s,transform .2s; transform-origin:top right; } #time-cheat-panel.tc-hidden{ opacity:0; transform:scale(.92); pointer-events:none; } .tc-hd{ display:flex; align-items:center; justify-content:space-between; padding:10px 14px; background:rgba(76,175,80,.12); border-bottom:1px solid rgba(76,175,80,.25); cursor:move; border-radius:10px 10px 0 0; user-select:none; } .tc-hd span{ color:#4CAF50; font-weight:700; font-size:14px; letter-spacing:.5px; } .tc-close{ background:none; border:none; color:#4CAF50; font-size:20px; cursor:pointer; line-height:1; } .tc-close:hover{ color:#fff; } .tc-body{ padding:12px 14px 16px; } .tc-row{ display:flex; align-items:center; justify-content:space-between; margin-bottom:8px; } .tc-row label{ flex:1; color:#bbb; font-size:12px; } .tc-row input[type=number]{ width:100px; padding:4px 8px; border:1px solid rgba(76,175,80,.35); border-radius:5px; background:rgba(0,0,0,.35); color:#e0e0e0; font:13px monospace; outline:none; text-align:right; } .tc-row input[type=number]:focus{ border-color:#4CAF50; box-shadow:0 0 0 2px rgba(76,175,80,.2); } .tc-toggle{ display:flex; align-items:center; gap:8px; margin-bottom:10px; cursor:pointer; } .tc-toggle input{ display:none; } .tc-sw{ position:relative; width:36px; height:20px; border-radius:10px; background:rgba(255,255,255,.12); transition:background .2s; flex-shrink:0; } .tc-sw::after{ content:''; position:absolute; top:2px; left:2px; width:16px; height:16px; border-radius:50%; background:#888; transition:transform .2s,background .2s; } .tc-toggle input:checked+.tc-sw{ background:rgba(76,175,80,.35); } .tc-toggle input:checked+.tc-sw::after{ transform:translateX(16px); background:#4CAF50; } .tc-toggle span:last-child{ font-size:12px; color:#bbb; } .tc-sep{ height:1px; background:rgba(76,175,80,.18); margin:10px 0; } .tc-apply{ display:block; width:100%; padding:9px 0; margin-top:6px; border:none; border-radius:6px; cursor:pointer; background:linear-gradient(135deg,#4CAF50,#388E3C); color:#1a1a1a; font:bold 13px sans-serif; letter-spacing:.5px; transition:filter .15s,transform .1s; } .tc-apply:hover{ filter:brightness(1.15); } .tc-apply:active{ transform:scale(.97); } .tc-hint{ text-align:center; font-size:11px; color:#776; margin-top:6px; transition:color .2s; min-height: 16px; } `; document.head.appendChild(css); // 2. 创建浮窗按钮(确保元素正确创建) const btn = document.createElement('div'); btn.id = 'time-cheat-btn'; btn.textContent = '⏩'; btn.title = '时间加速器'; btn.style.cssText = 'position:fixed; z-index:2147483647; width:42px; height:42px; border-radius:50%; border:2px solid #4CAF50; background:linear-gradient(135deg,#2E7D32 0%,#4CAF50 100%); color:#fff; font:bold 18px/42px sans-serif; text-align:center; cursor:pointer; user-select:none; box-shadow:0 2px 12px rgba(0,0,0,.6); transition:transform .15s,box-shadow .15s; right:16px; top:16px; touch-action:none;'; document.body.appendChild(btn); // 3. 创建浮窗面板(确保元素正确创建) const panel = document.createElement('div'); panel.id = 'time-cheat-panel'; panel.classList.add('tc-hidden'); panel.style.cssText = 'position:fixed; z-index:2147483646; right:70px; top:16px; width:280px; max-height:90vh; overflow-y:auto; background:rgba(30,30,30,.95); border:1.5px solid #4CAF50; border-radius:10px; box-shadow:0 4px 30px rgba(0,0,0,.7); font:13px/1.5 \'Segoe UI\',sans-serif; color:#e0e0e0; transition:opacity .2s,transform .2s; transform-origin:top right;'; panel.innerHTML = `
时间加速器
开启后立即生效,关闭后网页完全恢复正常
`; document.body.appendChild(panel); /* --- 浮窗移动逻辑(确保正确绑定)--- */ (function makeBtnDraggable() { const el = btn; let dragging = false, startX = 0, startY = 0, origLeft = 0, origTop = 0; function onPointerDown(e) { if (e.button !== undefined && e.button !== 0) return; dragging = true; const point = e.touches ? e.touches[0] : e; startX = point.clientX; startY = point.clientY; const rect = el.getBoundingClientRect(); origLeft = rect.left; origTop = rect.top; el.style.right = 'auto'; el.style.left = origLeft + 'px'; el.style.top = origTop + 'px'; e.preventDefault(); } function onPointerMove(e) { if (!dragging) return; const point = e.touches ? e.touches[0] : e; const dx = point.clientX - startX; const dy = point.clientY - startY; el.style.left = (origLeft + dx) + 'px'; el.style.top = (origTop + dy) + 'px'; e.preventDefault(); } function onPointerUp(e) { if (!dragging) return; dragging = false; const point = e.changedTouches ? e.changedTouches[0] : e; const dx = point.clientX - startX; const dy = point.clientY - startY; const distance = Math.sqrt(dx * dx + dy * dy); if (distance < 5) { panel.classList.toggle('tc-hidden'); } } el.addEventListener('mousedown', onPointerDown); document.addEventListener('mousemove', onPointerMove); document.addEventListener('mouseup', onPointerUp); el.addEventListener('touchstart', onPointerDown, { passive: false }); document.addEventListener('touchmove', onPointerMove, { passive: false }); el.addEventListener('touchend', onPointerUp); })(); /* --- 提示语逻辑 --- */ const hintEl = panel.querySelector('.tc-hint'); function showHint(msg, isError = false) { hintEl.textContent = msg; hintEl.style.color = isError ? '#ff6b6b' : '#4CAF50'; setTimeout(() => { hintEl.textContent = "开启后立即生效,关闭后网页完全恢复正常"; hintEl.style.color = '#776'; }, 3000); } /* --- 交互逻辑 --- */ panel.querySelector('.tc-close').onclick = () => panel.classList.add('tc-hidden'); // 应用设置(关键:启用/禁用时间引擎) panel.querySelector('.tc-apply').onclick = () => { cfg.enabled = document.getElementById('tc-enabled').checked; cfg.multiplier = document.getElementById('tc-multiplier').value; saveCfg(); if (cfg.enabled) { enableTimeEngine(); // 启用时间引擎 showHint(`✅ 时间加速已开启,倍率:${cfg.multiplier}x`); } else { disableTimeEngine(); // 禁用时间引擎(恢复原始函数) showHint("✅ 时间加速已关闭,网页完全恢复正常"); } }; // 实时更新倍率 document.getElementById('tc-multiplier').addEventListener('input', function() { cfg.multiplier = this.value; saveCfg(); }); document.getElementById('tc-enabled').addEventListener('change', function () { cfg.enabled = this.checked; saveCfg(); }); } catch(err) { console.error("时间加速器 UI Error:", err); // 如果注入失败,尝试延迟注入 setTimeout(injectUI, 1000); } } // 辅助函数:根据布尔值返回 checked 属性 function checkedAttr(v) { return v ? ' checked' : ''; } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', injectUI); } else { injectUI(); } })();