您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
A Comprehensive Script Executor for Territorial.io with multi-tab support, automation, and a user-friendly interface.
当前为
// ==UserScript== // @name TriX Executor // @namespace https://github.com/YourUsername/TriX-Executor // @version 1.0.0 // @description A Comprehensive Script Executor for Territorial.io with multi-tab support, automation, and a user-friendly interface. // @author You // @match *://territorial.io/* // @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-idle // @license MIT // ==/UserScript== /* * _____ ____ _ __ ___________ * |_ _||_ _|| | / / | _ | ___ \ * | | | | | |/ / | |/' | |_/ / * | | | | | \ | /| | __/ * _| |_ _| |_| |\ \ \ |_/ / | * \___/ \___/\_| \_/ \___/\_| * * TriX Executor - v1.0.0 * Logo: https://i.postimg.cc/0NkRZxDm/image.png * * An unparalleled level of control and automation for Territorial.io. */ (function() { 'use strict'; // --- Configuration & Constants --- const SCRIPT_PREFIX = 'trix_script_'; const BROADCAST_CHANNEL = 'trix_broadcast_channel'; const TAB_ID = `tab_${Date.now().toString(36)}_${Math.random().toString(36).substring(2)}`; // --- UI Module --- // Manages the creation, styling, and interaction of the executor's UI panel. const UI = { isDragging: false, dragOffsetX: 0, dragOffsetY: 0, init() { this.injectCSS(); this.injectHTML(); this.attachEventListeners(); this.showTab('executor'); // Default tab ScriptManager.populateScriptSelector(); this.log('TriX Executor v1.0.0 initialized.'); this.log(`Tab ID: ${TAB_ID}`); }, injectCSS() { GM_addStyle(` #trix-container { position: fixed; top: 20px; left: 20px; width: 500px; max-width: 90vw; background-color: #282c34; border: 1px solid #4f5b66; border-radius: 8px; box-shadow: 0 5px 15px rgba(0,0,0,0.5); z-index: 99999; color: #abb2bf; font-family: 'Menlo', 'Monaco', 'Consolas', monospace; font-size: 14px; display: flex; flex-direction: column; resize: both; overflow: hidden; min-width: 350px; min-height: 250px; } #trix-header { background-color: #21252b; padding: 8px 12px; cursor: move; user-select: none; display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid #4f5b66; } #trix-header-title { display: flex; align-items: center; font-weight: bold; } #trix-logo { width: 24px; height: 24px; margin-right: 8px; } #trix-controls button { background: none; border: none; color: #abb2bf; font-size: 18px; cursor: pointer; margin-left: 5px; } #trix-controls button:hover { color: #61afef; } #trix-content { padding: 10px; flex-grow: 1; display: flex; flex-direction: column; } .trix-tab-content { display: none; height: 100%; flex-direction: column; } .trix-tab-content.active { display: flex; } #trix-tabs { display: flex; border-bottom: 1px solid #4f5b66; margin-bottom: 10px; } .trix-tab-button { padding: 8px 15px; cursor: pointer; border: none; background-color: transparent; color: #abb2bf; border-bottom: 2px solid transparent; } .trix-tab-button.active { color: #61afef; border-bottom: 2px solid #61afef; } #trix-editor { width: 100%; flex-grow: 1; background-color: #1e2227; color: #d1d1d1; border: 1px solid #4f5b66; border-radius: 4px; padding: 5px; box-sizing: border-box; resize: none; } .trix-button-bar { margin-top: 10px; display: flex; gap: 10px; flex-wrap: wrap; } .trix-button, input[type="text"].trix-input { background-color: #3a3f4b; border: 1px solid #4f5b66; color: #abb2bf; padding: 8px 12px; border-radius: 4px; cursor: pointer; } .trix-button:hover { background-color: #4b515f; } .trix-button.primary { background-color: #61afef; color: #282c34; font-weight: bold; } .trix-button.primary:hover { background-color: #72baff; } .trix-button.danger { background-color: #e06c75; color: #282c34; } #trix-console { height: 100%; background-color: #1e2227; border: 1px solid #4f5b66; padding: 5px; overflow-y: auto; font-size: 12px; flex-grow: 1; } #trix-console div { padding: 2px 4px; border-bottom: 1px solid #2c313a; } #trix-console .log-error { color: #e06c75; } #trix-console .log-warn { color: #e5c07b; } #trix-console .log-info { color: #61afef; } #trix-console .log-broadcast { color: #98c379; font-style: italic; } #trix-script-manager { display: flex; align-items: center; gap: 10px; } #trix-script-selector { flex-grow: 1; } `); }, injectHTML() { const html = ` <div id="trix-container" style="display: none;"> <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>TriX Executor</span> </div> <div id="trix-controls"> <button id="trix-toggle-btn" title="Toggle Executor Panel">▼</button> </div> </div> <div id="trix-content"> <div id="trix-tabs"> <button class="trix-tab-button" data-tab="executor">Executor</button> <button class="trix-tab-button" data-tab="scripts">Scripts</button> <button class="trix-tab-button" data-tab="console">Console</button> </div> <!-- Executor Tab --> <div id="executor-tab" class="trix-tab-content"> <textarea id="trix-editor" placeholder="Enter your script here..."></textarea> <div class="trix-button-bar"> <button id="trix-execute-btn" class="trix-button primary">Execute</button> <button id="trix-clear-editor-btn" class="trix-button">Clear</button> </div> </div> <!-- Scripts Tab --> <div id="scripts-tab" class="trix-tab-content"> <div id="trix-script-manager"> <select id="trix-script-selector" class="trix-input"></select> <button id="trix-load-script-btn" class="trix-button">Load</button> <button id="trix-delete-script-btn" class="trix-button danger">Delete</button> </div> <input type="text" id="trix-script-name" class="trix-input" placeholder="Enter script name to save..." style="margin-top: 10px;"> <div class="trix-button-bar"> <button id="trix-save-script-btn" class="trix-button primary">Save Current Script</button> </div> <hr style="width:100%; border-color:#4f5b66; margin: 15px 0;"> <input type="text" id="trix-external-url" class="trix-input" placeholder="https://example.com/script.js"> <div class="trix-button-bar"> <button id="trix-fetch-run-btn" class="trix-button">Fetch & Run</button> </div> </div> <!-- Console Tab --> <div id="console-tab" class="trix-tab-content"> <div id="trix-console"></div> <div class="trix-button-bar"> <button id="trix-clear-console-btn" class="trix-button">Clear Console</button> </div> </div> </div> </div> <button id="trix-open-btn" class="trix-button" style="position:fixed; top:20px; right:20px; z-index:99998;">Open TriX</button> `; document.body.insertAdjacentHTML('beforeend', html); }, attachEventListeners() { // Panel Dragging const header = document.getElementById('trix-header'); const container = document.getElementById('trix-container'); header.addEventListener('mousedown', (e) => { if (e.target.tagName === 'BUTTON') return; this.isDragging = true; this.dragOffsetX = e.clientX - container.offsetLeft; this.dragOffsetY = e.clientY - container.offsetTop; }); document.addEventListener('mousemove', (e) => { if (!this.isDragging) return; container.style.left = `${e.clientX - this.dragOffsetX}px`; container.style.top = `${e.clientY - this.dragOffsetY}px`; }); document.addEventListener('mouseup', () => { this.isDragging = false; }); // Panel Visibility document.getElementById('trix-open-btn').addEventListener('click', () => this.togglePanel(true)); document.getElementById('trix-toggle-btn').addEventListener('click', () => this.togglePanel(false)); // Tab Switching document.querySelectorAll('.trix-tab-button').forEach(btn => { btn.addEventListener('click', () => this.showTab(btn.dataset.tab)); }); // Executor Buttons document.getElementById('trix-execute-btn').addEventListener('click', () => { const code = document.getElementById('trix-editor').value; Executor.execute(code); }); document.getElementById('trix-clear-editor-btn').addEventListener('click', () => { document.getElementById('trix-editor').value = ''; }); // Script Manager Buttons document.getElementById('trix-save-script-btn').addEventListener('click', ScriptManager.saveScriptFromEditor); document.getElementById('trix-load-script-btn').addEventListener('click', ScriptManager.loadScriptToEditor); document.getElementById('trix-delete-script-btn').addEventListener('click', ScriptManager.deleteSelectedScript); document.getElementById('trix-fetch-run-btn').addEventListener('click', () => { const url = document.getElementById('trix-external-url').value; if(url) ScriptManager.fetchAndRun(url); else UI.log('External script URL is empty.', 'warn'); }); // Console Buttons document.getElementById('trix-clear-console-btn').addEventListener('click', () => { document.getElementById('trix-console').innerHTML = ''; }); }, togglePanel(forceShow) { const container = document.getElementById('trix-container'); const openBtn = document.getElementById('trix-open-btn'); if (forceShow === true || container.style.display === 'none') { container.style.display = 'flex'; openBtn.style.display = 'none'; } else { container.style.display = 'none'; openBtn.style.display = 'block'; } }, showTab(tabId) { document.querySelectorAll('.trix-tab-content').forEach(tab => tab.classList.remove('active')); document.querySelectorAll('.trix-tab-button').forEach(btn => btn.classList.remove('active')); document.getElementById(`${tabId}-tab`).classList.add('active'); document.querySelector(`.trix-tab-button[data-tab="${tabId}"]`).classList.add('active'); }, log(message, type = 'log') { const consoleEl = document.getElementById('trix-console'); const entry = document.createElement('div'); const timestamp = new Date().toLocaleTimeString(); entry.className = `log-${type}`; entry.textContent = `[${timestamp}] ${message}`; consoleEl.appendChild(entry); consoleEl.scrollTop = consoleEl.scrollHeight; // Auto-scroll } }; // --- Script Manager --- // Handles loading, saving, and deleting user scripts from local storage. const ScriptManager = { async saveScriptFromEditor() { const name = document.getElementById('trix-script-name').value.trim(); const code = document.getElementById('trix-editor').value; if (!name) { UI.log('Cannot save script: Name is required.', 'error'); return; } if (!code) { UI.log('Cannot save script: Editor is empty.', 'warn'); return; } await GM_setValue(SCRIPT_PREFIX + name, code); UI.log(`Script '${name}' saved successfully.`, 'info'); this.populateScriptSelector(); }, async loadScriptToEditor() { const selector = document.getElementById('trix-script-selector'); const name = selector.value; if (!name) { UI.log('No script selected to load.', 'warn'); return; } const code = await GM_getValue(name, ''); document.getElementById('trix-editor').value = code; document.getElementById('trix-script-name').value = name.replace(SCRIPT_PREFIX, ''); UI.log(`Script '${name.replace(SCRIPT_PREFIX, '')}' loaded into editor.`, 'info'); }, async deleteSelectedScript() { const selector = document.getElementById('trix-script-selector'); const name = selector.value; if (!name) { UI.log('No script selected to delete.', 'warn'); return; } if (confirm(`Are you sure you want to delete the script '${name.replace(SCRIPT_PREFIX, '')}'?`)) { await GM_deleteValue(name); UI.log(`Script '${name.replace(SCRIPT_PREFIX, '')}' deleted.`, 'info'); this.populateScriptSelector(); } }, async populateScriptSelector() { const selector = document.getElementById('trix-script-selector'); selector.innerHTML = '<option value="">-- Select a saved script --</option>'; const allKeys = await GM_listValues(); const scriptKeys = allKeys.filter(key => key.startsWith(SCRIPT_PREFIX)); scriptKeys.forEach(key => { const option = document.createElement('option'); option.value = key; option.textContent = key.replace(SCRIPT_PREFIX, ''); selector.appendChild(option); }); }, fetchAndRun(url) { UI.log(`Fetching script from: ${url}`, 'info'); GM.xmlHttpRequest({ method: "GET", url: url, onload: function(response) { if (response.status >= 200 && response.status < 300) { UI.log(`Successfully fetched script from ${url}. Executing...`, 'info'); Executor.execute(response.responseText); } else { UI.log(`Failed to fetch script. Status: ${response.status}`, 'error'); } }, onerror: function(response) { UI.log(`Error fetching script: ${response.statusText}`, 'error'); } }); } }; // --- Executor & API --- // The core that executes scripts and provides a safe API for them. const Executor = { execute(code) { if (!code.trim()) { UI.log('Execution skipped: script is empty.', 'warn'); return; } UI.log('Executing script...', 'info'); try { // The "sandbox": scripts are executed within this function's scope. // They get access to the window, document, and the custom TriX API. const TriX = this.createAPI(); const scriptFunction = new Function('TriX', code); scriptFunction(TriX); } catch (e) { UI.log(`Execution Error: ${e.message}`, 'error'); console.error("TriX Executor Error:", e); } }, createAPI() { return { /** * Logs a message to the TriX console. * @param {any} message The message to log. * @param {'log'|'info'|'warn'|'error'} [type='log'] The type of log. */ log: (message, type = 'log') => { // Ensure message is a string for the UI const msgStr = typeof message === 'object' ? JSON.stringify(message) : String(message); UI.log(msgStr, type); }, /** * Broadcasts a data payload to all other open Territorial.io tabs with TriX Executor. * @param {any} payload The data to send. Must be JSON-serializable. */ broadcast: (payload) => { MultiTab.broadcast(payload); }, /** * A safe way to get game data by querying the DOM. * @param {string} selector The CSS selector for the element. * @param {'text'|'html'|'value'|'element'} [dataType='text'] What to extract. * @returns {string|HTMLElement|null} The extracted data or element. */ query: (selector, dataType = 'text') => { const element = document.querySelector(selector); if (!element) return null; switch(dataType) { case 'html': return element.innerHTML; case 'value': return element.value; case 'element': return element; case 'text': default: return element.textContent; } }, /** * A safe way to get arrays of game data. * @param {string} selector The CSS selector for the elements. * @param {'text'|'html'|'value'|'element'} [dataType='text'] What to extract. * @returns {Array<string|HTMLElement>} An array of the extracted data. */ queryAll: (selector, dataType = 'text') => { const elements = document.querySelectorAll(selector); return Array.from(elements).map(el => { switch(dataType) { case 'html': return el.innerHTML; case 'value': return el.value; case 'element': return el; case 'text': default: return el.textContent; } }); } }; } }; // --- Multi-Tab Communication --- // Manages broadcasting and listening for messages between tabs. const MultiTab = { init() { GM_addValueChangeListener(BROADCAST_CHANNEL, this.listener); }, /** * @param {string} key The key that changed. * @param {any} oldValue The old value. * @param {any} newValue The new value. * @param {boolean} remote Whether the change was from another tab. */ listener(key, oldValue, newValue, remote) { if (remote && newValue.senderId !== TAB_ID) { UI.log(`Received broadcast: ${JSON.stringify(newValue.payload)}`, 'broadcast'); // You can dispatch a custom event here for scripts to listen to // e.g., window.dispatchEvent(new CustomEvent('trix:broadcast', { detail: newValue.payload })); } }, broadcast(payload) { const message = { senderId: TAB_ID, timestamp: Date.now(), payload: payload }; GM_setValue(BROADCAST_CHANNEL, message); UI.log(`Broadcast sent: ${JSON.stringify(payload)}`, 'broadcast'); } }; // --- Main Initialization --- function main() { UI.init(); MultiTab.init(); } // Wait for the page to be fully loaded to avoid conflicts with game scripts. if (document.readyState === 'complete' || document.readyState === 'interactive') { main(); } else { window.addEventListener('load', main); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址