您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
A Comprehensive Script Executor for Territorial.io with proxy support, a modern UI, and tab management.
当前为
// ==UserScript== // @name TriX Executor // @namespace https://github.com/YourUsername/TriX-Executor // @version 1.3.2 // @description A Comprehensive Script Executor for Territorial.io with proxy support, a modern UI, and tab management. // @author You // @match *://territorial.io/* // @match *://www.territorial.io/* // @match *://*.*.*.*/* // @icon https://i.postimg.cc/0NkRZxDm/image.png // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @grant GM_listValues // @grant GM_deleteValue // @grant GM_addValueChangeListener // @grant GM.xmlHttpRequest // @run-at document-start // @license MIT // ==/UserScript== /* * _____ ____ _ __ ___________ * |_ _||_ _|| | / / | _ | ___ \ * | | | | | |/ / | |/' | |_/ / * | | | | | \ | /| | __/ * _| |_ _| |_| |\ \ \ |_/ / | * \___/ \___/\_| \_/ \___/\_| * * TriX Executor - v1.3.2 (Proxy Support Edition) * Logo: https://i.postimg.cc/0NkRZxDm/image.png * * Changelog: * - Added support for CroxyProxy by matching IP-based URLs and verifying * the `__cpo` URL parameter. */ (function() { 'use strict'; // --- Page Verification --- // This function runs first to ensure the script only executes on the correct pages. function isTerritorialPage() { // 1. Direct match for the official site if (window.location.hostname.includes('territorial.io')) { return true; } // 2. Proxy check for sites like CroxyProxy try { const urlParams = new URLSearchParams(window.location.search); const cpoParam = urlParams.get('__cpo'); if (cpoParam) { // The parameter value is Base64 encoded. Decode it. // aHR0cHM6Ly90ZXJyaXRvcmlhbC5pbw -> https://territorial.io const decodedUrl = atob(cpoParam); if (decodedUrl.includes('territorial.io')) { // This is a proxy for our target site. return true; } } } catch (e) { // Ignore errors (e.g., invalid base64 from another site's param) return false; } // If none of the above, it's an unrelated IP page we should not run on. return false; } // --- SCRIPT EXECUTION GUARD --- // Only proceed if the page is confirmed to be territorial.io or a valid proxy. if (!isTerritorialPage()) { // console.log('[TriX Executor] Page is not territorial.io or a recognized proxy. Halting execution.'); return; } console.log('[TriX Executor] Script injected. Waiting for game UI to load...'); // --- Configuration & Constants --- const SCRIPT_PREFIX = 'trix_script_'; const BROADCAST_CHANNEL = 'trix_broadcast_channel'; const TAB_LIST_KEY = 'trix_active_tabs'; const HEARTBEAT_INTERVAL = 5000; const STALE_TAB_TIMEOUT = 15000; const TAB_ID = `tab_${Date.now().toString(36)}_${Math.random().toString(36).substring(2)}`; const LOAD_TIME = Date.now(); const GAME_READY_SELECTOR = '#input0'; // --- TabManager, UI, ScriptManager, Executor, MultiTab Modules (minified for brevity, no changes) --- const TabManager={tabs:[],myTabInfo:{},uiInitialized:!1,isMaster:!1,init(e){this.myTabInfo={id:TAB_ID,username:e,loadTime:LOAD_TIME,lastSeen:Date.now()},GM_addValueChangeListener(TAB_LIST_KEY,(e,t,s,o)=>{o&&this.pruneAndRefresh(s)}),this.register(),setInterval(()=>this.register(),HEARTBEAT_INTERVAL),window.addEventListener("beforeunload",()=>this.unregister())},async register(){let e=await GM_getValue(TAB_LIST_KEY,[]);const t=Date.now();e=e.filter(e=>t-e.lastSeen<STALE_TAB_TIMEOUT),this.myTabInfo.lastSeen=t;const s=e.findIndex(e=>e.id===TAB_ID);-1<s?e[s]=this.myTabInfo:e.push(this.myTabInfo),await GM_setValue(TAB_LIST_KEY,e),this.pruneAndRefresh(e)},async unregister(){let e=await GM_getValue(TAB_LIST_KEY,[]);e=e.filter(e=>e.id!==TAB_ID),await GM_setValue(TAB_LIST_KEY,e)},pruneAndRefresh(e){this.tabs=e,this.updateTabCountUI(),this.checkMasterStatus()},updateTabCountUI(){const e=this.tabs.length,t=document.getElementById("trix-open-btn-badge"),s=document.getElementById("trix-header-tab-counter");t&&(t.textContent=e),s&&(s.textContent=e)},checkMasterStatus(){this.isMaster=this.amIMaster(),this.isMaster&&!this.uiInitialized&&this.initUI()},amIMaster(){if(!this.myTabInfo.username||this.myTabInfo.username.startsWith("Guest_"))return!0;const e=this.tabs.filter(e=>e.username===this.myTabInfo.username);return 0===e.length||this.myTabInfo.loadTime===Math.min(...e.map(e=>e.loadTime))},initUI(){this.uiInitialized||(console.log("[TriX Executor] This tab is the master. Initializing UI."),this.uiInitialized=!0,UI.init(),MultiTab.init())}}; const UI={isMinimized:!1,currentScriptName:"",init(){this.injectCSS(),this.injectHTML(),this.attachEventListeners(),ScriptManager.populateScriptList(),TabManager.updateTabCountUI(),this.log("TriX Executor v1.3.2 initialized.")},injectCSS(){GM_addStyle(`:root{--trix-bg-primary:#1e1e1e;--trix-bg-secondary:#2d2d2d;--trix-bg-tertiary:#3c3c3c;--trix-accent-color:#00aeff;--trix-text-primary:#d4d4d4;--trix-text-secondary:#8c8c8c;--trix-border-color:#4a4a4a}#trix-container,#trix-open-btn{font-family:'Segoe UI','Roboto',sans-serif!important}#trix-container{position:fixed!important;top:50px!important;left:50px!important;width:600px;height:400px;background-color:var(--trix-bg-primary);border:1px solid var(--trix-border-color);box-shadow:0 0 20px rgba(0,0,0,.5);z-index:1000000!important;display:flex!important;flex-direction:column;resize:both;overflow:hidden;min-width:450px;min-height:300px}#trix-container.hidden{display:none!important}#trix-container.minimized{height:auto!important;min-height:0!important;resize:none!important}#trix-container.minimized #trix-body,#trix-container.minimized #trix-footer,#trix-container.minimized #trix-console{display:none!important}#trix-open-btn{position:fixed!important;top:20px!important;right:20px!important;z-index:999999!important;display:flex!important;align-items:center;background-color:var(--trix-accent-color)!important;color:#fff!important;border:none!important;border-radius:5px;padding:10px 15px!important;cursor:pointer!important;box-shadow:0 0 10px rgba(0,174,255,.7);font-weight:700!important;font-size:14px!important}.trix-tab-badge{display:inline-block;background-color:var(--trix-bg-secondary);color:var(--trix-text-primary);padding:2px 8px;margin-left:8px;border-radius:10px;font-size:12px;font-weight:700;line-height:1.2;vertical-align:middle;min-width:10px;text-align:center}#trix-header{background-color:var(--trix-bg-secondary);padding:5px 10px;cursor:move;user-select:none;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid var(--trix-border-color)}#trix-header-title{display:flex;align-items:center;font-weight:700;color:var(--trix-text-primary)}#trix-logo{width:24px;height:24px;margin-right:8px}#trix-window-controls button{background:0 0;border:none;color:var(--trix-text-secondary);font-size:18px;cursor:pointer;margin-left:8px;padding:0 4px;line-height:1}#trix-window-controls button:hover{color:var(--trix-accent-color)}#trix-close-btn:hover{color:#ff5555}#trix-body{flex-grow:1;display:flex;overflow:hidden}#trix-left-panel{width:150px;background-color:var(--trix-bg-secondary);padding:10px 0;display:flex;flex-direction:column;border-right:1px solid var(--trix-border-color)}#trix-script-list-title{padding:0 10px 10px;font-weight:700;color:var(--trix-text-primary);border-bottom:1px solid var(--trix-border-color)}#trix-script-list{flex-grow:1;overflow-y:auto;margin-top:10px}.trix-script-item{padding:8px 10px;cursor:pointer;color:var(--trix-text-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.trix-script-item:hover{background-color:var(--trix-bg-tertiary);color:var(--trix-text-primary)}.trix-script-item.active{background-color:var(--trix-accent-color);color:var(--trix-bg-primary)!important;font-weight:700}#trix-right-panel{flex-grow:1;display:flex;flex-direction:column}#trix-editor{flex-grow:1;background-color:var(--trix-bg-primary);color:var(--trix-text-primary);border:none;padding:10px;box-sizing:border-box;resize:none;font-family:'Consolas','Monaco',monospace;font-size:14px}#trix-console{height:120px;background-color:var(--trix-bg-secondary);border-top:1px solid var(--trix-border-color);padding:5px;overflow-y:auto;font-size:12px;font-family:'Consolas','Monaco',monospace}#trix-console div{padding:2px 4px;border-bottom:1px solid #333;word-break:break-all}#trix-console .log-error{color:#ff5555}#trix-console .log-warn{color:#e5c07b}#trix-console .log-info{color:#00aeff}#trix-console .log-broadcast{color:#98c379;font-style:italic}#trix-footer{display:flex;gap:10px;padding:10px;background-color:var(--trix-bg-secondary);border-top:1px solid var(--trix-border-color);align-items:center}.trix-button{background-color:var(--trix-bg-tertiary);border:1px solid var(--trix-border-color);color:var(--trix-text-primary);padding:8px 15px;cursor:pointer;transition:background-color .2s}.trix-button:hover{background-color:#555}.trix-button.primary{background-color:var(--trix-accent-color);color:var(--trix-bg-primary);font-weight:700}.trix-button.primary:hover{background-color:#00bfff}.trix-button.danger{background-color:#c0392b}.trix-button.danger:hover{background-color:#e74c3c}`)},injectHTML(){const e=`<div id="trix-container" class="hidden"><div id="trix-header"><div id="trix-header-title"><img id="trix-logo" src="https://i.postimg.cc/0NkRZxDm/image.png" alt="TriX Logo"> <span id="trix-header-title-text">TriX Executor</span><span id="trix-header-tab-counter" class="trix-tab-badge">1</span></div><div id="trix-window-controls"><button id="trix-minimize-btn" title="Minimize">-</button> <button id="trix-close-btn" title="Close">✕</button></div></div><div id="trix-body"><div id="trix-left-panel"><div id="trix-script-list-title">Script List</div><div id="trix-script-list"></div></div><div id="trix-right-panel"><textarea id="trix-editor" placeholder="-- Paste or load a script here..."></textarea><div id="trix-console"></div></div></div><div id="trix-footer"><button id="trix-execute-btn" class="trix-button primary">▶ Execute</button> <button id="trix-clear-btn" class="trix-button">Clear</button> <input type="text" id="trix-save-name" placeholder="Script Name..." class="trix-button" style="flex-grow:1; cursor:text;"> <button id="trix-save-btn" class="trix-button">Save</button> <button id="trix-delete-btn" class="trix-button danger">Delete</button></div></div><button id="trix-open-btn"><span>Open TriX</span><span id="trix-open-btn-badge" class="trix-tab-badge">1</span></button>`;document.body.insertAdjacentHTML("beforeend",e)},attachEventListeners(){const e=document.getElementById("trix-container"),t=document.getElementById("trix-header");t.addEventListener("mousedown",t=>{if(t.target.closest("#trix-window-controls"))return;let s=!0;const o=t.clientX-e.offsetLeft,n=t.clientY-e.offsetTop,i=i=>{s&&(i.preventDefault(),e.style.left=`${i.clientX-o}px`,e.style.top=`${i.clientY-n}px`)},d=()=>{s=!1,document.removeEventListener("mousemove",i),document.removeEventListener("mouseup",d)};document.addEventListener("mousemove",i),document.addEventListener("mouseup",d)}),document.getElementById("trix-open-btn").addEventListener("click",()=>this.togglePanel(!0)),document.getElementById("trix-close-btn").addEventListener("click",()=>this.togglePanel(!1)),document.getElementById("trix-minimize-btn").addEventListener("click",()=>{this.isMinimized=!this.isMinimized,e.classList.toggle("minimized",this.isMinimized)}),document.getElementById("trix-script-list").addEventListener("click",e=>{if(e.target.matches(".trix-script-item")){const t=e.target.dataset.scriptKey;ScriptManager.loadScriptToEditor(t)}}),document.getElementById("trix-execute-btn").addEventListener("click",()=>Executor.execute(document.getElementById("trix-editor").value)),document.getElementById("trix-clear-btn").addEventListener("click",()=>{document.getElementById("trix-editor").value="",document.getElementById("trix-save-name").value="",this.setActiveScriptItem(null),this.currentScriptName=""}),document.getElementById("trix-save-btn").addEventListener("click",ScriptManager.saveScriptFromEditor),document.getElementById("trix-delete-btn").addEventListener("click",ScriptManager.deleteCurrentScript)},togglePanel(e){const t=document.getElementById("trix-container"),s=document.getElementById("trix-open-btn"),o=t.classList.contains("hidden");!0===e||o?(t.classList.remove("hidden"),s.style.display="none"):(t.classList.add("hidden"),s.style.display="flex")},log(e,t="log"){const s=document.getElementById("trix-console");if(!s)return;const o=document.createElement("div");o.className=`log-${t}`,o.textContent=`> ${String(e)}`,s.prepend(o)},setActiveScriptItem(e){document.querySelectorAll(".trix-script-item").forEach(t=>{t.classList.toggle("active",t.dataset.scriptKey===e)})}}; const ScriptManager={async saveScriptFromEditor(){const e=document.getElementById("trix-save-name").value.trim(),t=document.getElementById("trix-editor").value;e?t?(await GM_setValue(SCRIPT_PREFIX+e,t),UI.log(`Script '${e}' saved.`,"info"),this.populateScriptList(SCRIPT_PREFIX+e)):UI.log("Cannot save: Editor is empty.","warn"):UI.log("Cannot save: Name is required.","error")},async loadScriptToEditor(e){if(!e)return UI.log("Invalid script key.","error");const t=await GM_getValue(e,""),s=e.replace(SCRIPT_PREFIX,"");document.getElementById("trix-editor").value=t,document.getElementById("trix-save-name").value=s,UI.log(`Loaded script: ${s}`,"info"),UI.currentScriptName=s,UI.setActiveScriptItem(e)},async deleteCurrentScript(){const e=UI.currentScriptName;e&&confirm(`Are you sure you want to delete '${e}'?`)&&(await GM_deleteValue(SCRIPT_PREFIX+e),UI.log(`Script '${e}' deleted.`,"info"),document.getElementById("trix-editor").value="",document.getElementById("trix-save-name").value="",UI.currentScriptName="",this.populateScriptList())},async populateScriptList(e=null){const t=document.getElementById("trix-script-list");t.innerHTML="";const s=(await GM_listValues()).filter(e=>e.startsWith(SCRIPT_PREFIX));s.sort().forEach(e=>{const s=document.createElement("div");s.className="trix-script-item",s.textContent=e.replace(SCRIPT_PREFIX,""),s.dataset.scriptKey=e,t.appendChild(s)}),UI.setActiveScriptItem(e||UI.currentScriptName?SCRIPT_PREFIX+UI.currentScriptName:null)}}; const Executor={execute(e){if(!e.trim())return void UI.log("Execution skipped: script is empty.","warn");UI.log("Executing script...","info");try{const t=this.createAPI(),s=new Function("TriX",e);s(t)}catch(e){UI.log(`Execution Error: ${e.message}`,"error"),console.error("TriX Executor Error:",e)}},createAPI:()=>({log:(e,t="log")=>{const s="object"==typeof e?JSON.stringify(e):String(e);UI.log(s,t)},broadcast:e=>{MultiTab.broadcast(e)},query:(e,t="text")=>{const s=document.querySelector(e);return s?"html"===t?s.innerHTML:"value"===t?s.value:"element"===t?s:s.textContent:null},queryAll:(e,t="text")=>{const s=document.querySelectorAll(e);return Array.from(s).map(e=>"html"===t?e.innerHTML:"value"===t?e.value:"element"===t?e:e.textContent)}})}; const MultiTab={init(){GM_addValueChangeListener(BROADCAST_CHANNEL,this.listener)},listener(e,t,s,o){o&&s.senderId!==TAB_ID&&UI.log(`Received broadcast: ${JSON.stringify(s.payload)}`,"broadcast")},broadcast(e){const t={senderId:TAB_ID,timestamp:Date.now(),payload:e};GM_setValue(BROADCAST_CHANNEL,t),UI.log(`Broadcast sent: ${JSON.stringify(e)}`,"broadcast")}}; function waitForElement(e,t){if(document.querySelector(e))return void t();const s=new MutationObserver((o,n)=>{document.querySelector(e)&&(n.disconnect(),t())});s.observe(document.documentElement,{childList:!0,subtree:!0})} function main(){const e=document.querySelector("#input0").value.trim()||`Guest_${TAB_ID}`;TabManager.init(e)} waitForElement("#input0",main); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址