// ==UserScript== // @name MergeCiv 修改器 // @namespace http://tampermonkey.net/ // @version 3.2 // @description 终极杀器:底层时间欺骗,无视一切闭包与框架防御 // @author ZMM // @match https://gityxs.github.io/merge-civ/* // @grant none // @run-at document-start // ==/UserScript== (function () { 'use strict'; /* ========== 配置持久化 ========== */ const CFG_KEY = '__mc_mod_cfg__'; const defaultCfg = { enabled: true, food: '1e170', wood: '1e170', ore: '1e170', metal: '1e170', gold: '1e170', research: '1e170', syncLimits: true, unlockAll: false, culturePoints: '0', magicCrystals: '0', timeCheat: false, timeMultiplier: '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:完美的时间欺骗引擎 ========== */ let timeEngineLastReal = performance.now(); let timeEngineFakeTime = timeEngineLastReal; const OrigPerfNow = performance.now.bind(performance); const OrigDateNow = Date.now; performance.now = function() { const realNow = OrigPerfNow(); const realDelta = realNow - timeEngineLastReal; timeEngineLastReal = realNow; const multiplier = cfg.timeCheat ? (Number(cfg.timeMultiplier) || 2) : 1; timeEngineFakeTime += realDelta * multiplier; return timeEngineFakeTime; }; Date.now = function() { return Math.floor(timeEngineFakeTime); }; /* ========== 核心 2:JSON.parse (一次性覆盖,保留原有功能) ========== */ const origParse = JSON.parse; JSON.parse = function (text, reviver) { try { const result = origParse.call(this, text, reviver); if (result && typeof result === 'object' && result.resources && 'food' in result.resources) { if (cfg.enabled) { const resKeys = ['food', 'wood', 'ore', 'metal', 'gold', 'research']; for (const k of resKeys) { if (k in result.resources && cfg[k]) try { result.resources[k] = Number(cfg[k]); } catch (e) {} } if (cfg.syncLimits && result.limits) { for (const k of resKeys) { if (k in result.limits && cfg[k]) try { result.limits[k] = Number(cfg[k]); } catch (e) {} } } if (cfg.unlockAll && result.upgrades) { for (const k in result.upgrades) { if (typeof result.upgrades[k] === 'boolean') result.upgrades[k] = true; } } if (cfg.culturePoints && Number(cfg.culturePoints) > 0 && result.empire) result.empire.culturePoints = Number(cfg.culturePoints); if (cfg.magicCrystals && Number(cfg.magicCrystals) > 0 && result.empire) { result.empire.magicCrystals = Number(cfg.magicCrystals); result.empire.assignedCrystals = Number(cfg.magicCrystals); } } } return result; } catch(e) { return origParse.call(this, text, reviver); } }; /* ========== 注入 UI ========== */ function injectUI() { try { const css = document.createElement('style'); css.textContent = ` #mc-mod-btn{ position:fixed; z-index:2147483647; width:42px; height:42px; border-radius:50%; border:2px solid #c9a84c; background:linear-gradient(135deg,#3d2e1a 0%,#5a432a 100%); color:#c9a84c; 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; } #mc-mod-btn:hover{ transform:scale(1.12); box-shadow:0 0 18px rgba(201,168,76,.5); } #mc-mod-panel{ position:fixed; z-index:2147483646; right:70px; top:16px; width:320px; max-height:90vh; overflow-y:auto; background:rgba(30,24,18,.96); border:1.5px solid #c9a84c; border-radius:10px; box-shadow:0 4px 30px rgba(0,0,0,.7); font:13px/1.5 'Segoe UI',sans-serif; color:#e0d5c3; transition:opacity .2s,transform .2s; transform-origin:top right; } #mc-mod-panel.mc-hidden{ opacity:0; transform:scale(.92); pointer-events:none; } .mc-hd{ display:flex; align-items:center; justify-content:space-between; padding:10px 14px; background:rgba(201,168,76,.12); border-bottom:1px solid rgba(201,168,76,.25); cursor:move; border-radius:10px 10px 0 0; user-select:none; } .mc-hd span{ color:#c9a84c; font-weight:700; font-size:14px; letter-spacing:.5px; } .mc-close{ background:none; border:none; color:#c9a84c; font-size:20px; cursor:pointer; line-height:1; } .mc-close:hover{ color:#fff; } .mc-body{ padding:12px 14px 16px; } .mc-row{ display:flex; align-items:center; justify-content:space-between; margin-bottom:8px; } .mc-row label{ flex:1; color:#bbb; font-size:12px; } .mc-row input[type=number]{ width:130px; padding:4px 8px; border:1px solid rgba(201,168,76,.35); border-radius:5px; background:rgba(0,0,0,.35); color:#e0d5c3; font:13px monospace; outline:none; text-align:right; } .mc-row input[type=number]:focus{ border-color:#c9a84c; box-shadow:0 0 0 2px rgba(201,168,76,.2); } .mc-toggle{ display:flex; align-items:center; gap:8px; margin-bottom:10px; cursor:pointer; } .mc-toggle input{ display:none; } .mc-sw{ position:relative; width:36px; height:20px; border-radius:10px; background:rgba(255,255,255,.12); transition:background .2s; flex-shrink:0; } .mc-sw::after{ content:''; position:absolute; top:2px; left:2px; width:16px; height:16px; border-radius:50%; background:#888; transition:transform .2s,background .2s; } .mc-toggle input:checked+.mc-sw{ background:rgba(201,168,76,.35); } .mc-toggle input:checked+.mc-sw::after{ transform:translateX(16px); background:#c9a84c; } .mc-toggle span:last-child{ font-size:12px; color:#bbb; } .mc-sep{ height:1px; background:rgba(201,168,76,.18); margin:10px 0; } .mc-apply{ display:block; width:100%; padding:9px 0; margin-top:6px; border:none; border-radius:6px; cursor:pointer; background:linear-gradient(135deg,#c9a84c,#a68a3a); color:#1a1510; font:bold 13px sans-serif; letter-spacing:.5px; transition:filter .15s,transform .1s; } .mc-apply:hover{ filter:brightness(1.15); } .mc-apply:active{ transform:scale(.97); } .mc-hint{ text-align:center; font-size:11px; color:#776; margin-top:6px; } `; document.head.appendChild(css); const btn = document.createElement('div'); btn.id = 'mc-mod-btn'; btn.textContent = 'M'; btn.title = 'MergeCiv Mod'; document.body.appendChild(btn); const panel = document.createElement('div'); panel.id = 'mc-mod-panel'; panel.classList.add('mc-hidden'); const resItems = [['food', '食物'], ['wood', '木材'], ['ore', '矿石'], ['metal', '金属'], ['gold', '黄金'], ['research', '研究']]; const extraItems = [['culturePoints', '文化点'], ['magicCrystals', '魔法水晶']]; function buildRows(items) { return items.map(([key, label]) => `
`).join(''); } function checkedAttr(v) { return v ? ' checked' : ''; } panel.innerHTML = `