您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
BEST TERRITORIAL.IO EXECUTOR. A powerful in-game developer toolkit with a multi-tab script injector and syntax highlighting. | Recent Changes (v0.1.1): Initial BETA release of TriX Executor. Added multi-tab script editor, syntax highlighting, and persistent script saving.
当前为
// ==UserScript== // @name TriX Executor (BETA) // @namespace http://tampermonkey.net/ // @version 0.1.1 // @description BEST TERRITORIAL.IO EXECUTOR. A powerful in-game developer toolkit with a multi-tab script injector and syntax highlighting. | Recent Changes (v0.1.1): Initial BETA release of TriX Executor. Added multi-tab script editor, syntax highlighting, and persistent script saving. // @author Your Name // @match *://territorial.io/* // @icon https://i.imgur.com/O2s5H3I.png // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // @grant GM_getResourceText // @require https://openuserjs.org/src/libs/sizzle/GM_config.js // @require https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js // @resource PRISM_CSS https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css // ==/UserScript== (function() { 'use strict'; // ----------------------------------------------------------------------------- // 1. SETTINGS MODULE (GM_config) // ----------------------------------------------------------------------------- const SettingsModule = { init: function() { GM_config.init({ 'id': 'TriX_Executor_Config', 'title': "TriX Executor Settings", 'fields': { 'uiTheme': { 'label': 'UI Theme', 'type': 'select', 'options': ['Dark Knight', 'Arctic Light', 'Crimson'], 'default': 'Dark Knight', 'section': ['Appearance'], }, 'showFPS': { 'label': 'Enable FPS Counter', 'type': 'checkbox', 'default': true, } }, 'css': ` #TriX_Executor_Config { background-color: #2a2a30; color: #fff; border: 1px solid #555; } #TriX_Executor_Config .section_header { background-color: #3a3a42; border-bottom: 1px solid #555; } #TriX_Executor_Config .config_header { background-color: #1e1e22; } #TriX_Executor_Config button { background-color: #007bff; color: white; border: none; padding: 8px 12px; cursor: pointer; transition: background-color 0.2s; border-radius: 4px; } #TriX_Executor_Config button:hover { background-color: #0069d9; } #TriX_Executor_Config .reset { background-color: #f44336; } #TriX_Executor_Config .reset:hover { background-color: #da190b; } `, 'events': { 'save': () => this.applyTheme(), 'open': (doc) => { doc.getElementById('TriX_Executor_Config').style.animation = 'trix-fade-in 0.3s ease-out'; } } }); GM_registerMenuCommand("TriX Settings", () => GM_config.open()); }, applyTheme: function() { const theme = GM_config.get('uiTheme'); const container = document.getElementById('trix-container'); if (container) { container.setAttribute('data-theme', theme.replace(' ', '-').toLowerCase()); } }, get: (key) => GM_config.get(key) }; // ----------------------------------------------------------------------------- // 2. STYLE MODULE // ----------------------------------------------------------------------------- const StyleModule = { inject: function() { // Inject Prism.js theme CSS from @resource const prismCSS = GM_getResourceText('PRISM_CSS'); GM_addStyle(prismCSS); GM_addStyle(` /* --- Animations --- */ @keyframes trix-fade-in { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } } @keyframes trix-slide-in { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } /* --- Main UI & Toggle --- */ #trix-toggle-btn { position: fixed; top: 15px; right: 15px; z-index: 99999; width: 50px; height: 50px; background-color: rgba(30, 30, 34, 0.8); color: #00aaff; border: 2px solid #00aaff; border-radius: 50%; cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 24px; transition: all 0.3s ease; backdrop-filter: blur(5px); font-family: monospace; } #trix-toggle-btn:hover { transform: scale(1.1) rotate(15deg); box-shadow: 0 0 15px #00aaff; } #trix-container { position: fixed; top: 80px; right: 15px; width: 450px; min-height: 400px; z-index: 99998; color: #fff; border-radius: 10px; overflow: hidden; box-shadow: 0 5px 25px rgba(0,0,0,0.5); display: flex; flex-direction: column; backdrop-filter: blur(10px); animation: trix-slide-in 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards; resize: both; } #trix-container.hidden { display: none; } /* --- Theming --- */ #trix-container[data-theme='dark-knight'] { background-color: rgba(30, 30, 34, 0.9); border: 1px solid #444; } #trix-container[data-theme='arctic-light'] { background-color: rgba(240, 240, 255, 0.9); border: 1px solid #ccc; color: #111; } #trix-container[data-theme='crimson'] { background-color: rgba(43, 8, 8, 0.9); border: 1px solid #8B0000; color: #f1f1f1; } /* --- Header --- */ #trix-header { padding: 10px 15px; cursor: move; user-select: none; font-weight: bold; font-size: 16px; display: flex; justify-content: space-between; align-items: center; } #trix-container[data-theme='dark-knight'] #trix-header { background-color: rgba(0,0,0,0.3); } #trix-container[data-theme='arctic-light'] #trix-header { background-color: rgba(0,0,0,0.1); } #trix-container[data-theme='crimson'] #trix-header { background-color: rgba(139, 0, 0, 0.5); } #trix-close-btn { cursor: pointer; font-size: 20px; font-weight: bold; padding: 0 5px; } #trix-close-btn:hover { color: #ff5555; } /* --- Content Area --- */ #trix-content { padding: 0 15px 15px 15px; flex-grow: 1; display: flex; flex-direction: column; } /* --- Script Injector Specific Styles --- */ #trix-injector-container { display: flex; flex-direction: column; flex-grow: 1; margin-top: 10px; } .trix-tabs { display: flex; flex-wrap: wrap; border-bottom: 1px solid #555; } .trix-tab { background: #2a2a30; padding: 8px 12px; cursor: pointer; border-radius: 5px 5px 0 0; margin-right: 4px; position: relative; transition: background 0.2s; } .trix-tab:hover { background: #3a3a42; } .trix-tab.active { background: #1e1e22; font-weight: bold; color: #00aaff; } .trix-tab-name { padding-right: 15px; } .trix-tab-close { position: absolute; top: 50%; right: 5px; transform: translateY(-50%); font-size: 14px; opacity: 0.6; } .trix-tab-close:hover { opacity: 1; color: #ff5555; } #trix-new-tab-btn { background: none; border: none; color: #00aaff; font-size: 20px; cursor: pointer; padding: 5px 10px; } .trix-editor-area { position: relative; flex-grow: 1; margin-top: -1px; background: #2d2d2d; border: 1px solid #555; border-radius: 0 0 5px 5px; } .trix-editor-area textarea, .trix-editor-area pre { margin: 0; padding: 10px; font-family: 'Fira Code', 'Consolas', monospace; font-size: 14px; line-height: 1.5; white-space: pre; word-wrap: normal; width: 100%; height: 100%; box-sizing: border-box; position: absolute; top: 0; left: 0; overflow: auto; } .trix-editor-area textarea { z-index: 1; background: transparent; color: inherit; resize: none; border: none; outline: none; -webkit-text-fill-color: transparent; /* Makes textarea text invisible */ } .trix-editor-area pre { z-index: 0; pointer-events: none; } .trix-action-bar { display: flex; gap: 10px; margin-top: 10px; } .trix-button { background-color: #007bff; color: white; border: none; padding: 8px 12px; cursor: pointer; border-radius: 5px; transition: background-color 0.2s; flex-grow: 1; } .trix-button:hover { background-color: #0069d9; } #trix-execute-btn { background-color: #28a745; } #trix-execute-btn:hover { background-color: #218838; } .trix-status-bar { margin-top: 10px; padding: 5px; background: rgba(0,0,0,0.2); font-size: 12px; border-radius: 3px; min-height: 1em; } .trix-status-success { color: #28a745; } .trix-status-error { color: #dc3545; } `); } }; // ----------------------------------------------------------------------------- // 3. UI MODULE // ----------------------------------------------------------------------------- const UIModule = { init: function() { this.createToggleButton(); this.createMainPanel(); this.addEventListeners(); }, createToggleButton: () => document.body.insertAdjacentHTML('beforeend', `<div id="trix-toggle-btn" title="Toggle TriX Executor">X</div>`), createMainPanel: function() { const mainPanelHTML = ` <div id="trix-container" class="hidden"> <div id="trix-header"> <span>TriX Executor</span> <span id="trix-close-btn" title="Close">✖</span> </div> <div id="trix-content"> <!-- Script Injector will be rendered here by its module --> </div> <div id="trix-footer" style="padding:10px; text-align:center; background:rgba(0,0,0,0.2);"> <button id="trix-settings-btn" class="trix-button">Open Settings</button> </div> </div> `; document.body.insertAdjacentHTML('beforeend', mainPanelHTML); }, addEventListeners: function() { const container = document.getElementById('trix-container'); const header = document.getElementById('trix-header'); const toggleBtn = document.getElementById('trix-toggle-btn'); const closeBtn = document.getElementById('trix-close-btn'); const settingsBtn = document.getElementById('trix-settings-btn'); toggleBtn.addEventListener('click', () => container.classList.toggle('hidden')); closeBtn.addEventListener('click', () => container.classList.add('hidden')); settingsBtn.addEventListener('click', () => GM_config.open()); // Drag functionality let isDragging = false, offset = { x: 0, y: 0 }; header.addEventListener('mousedown', (e) => { isDragging = true; offset = { x: e.clientX - container.offsetLeft, y: e.clientY - container.offsetTop }; header.style.cursor = 'grabbing'; }); document.addEventListener('mouseup', () => { isDragging = false; header.style.cursor = 'move'; }); document.addEventListener('mousemove', (e) => { if (!isDragging) return; container.style.left = `${e.clientX - offset.x}px`; container.style.top = `${e.clientY - offset.y}px`; container.style.right = 'auto'; container.style.bottom = 'auto'; }); } }; // ----------------------------------------------------------------------------- // 4. SCRIPT INJECTOR MODULE // ----------------------------------------------------------------------------- const ScriptInjectorModule = { state: { scripts: [], activeTabId: null, }, elements: {}, init: function() { this.loadState(); this.render(); this.attachEventListeners(); }, loadState: function() { const savedState = GM_getValue('TriX_Scripts', null); if (savedState) { this.state = JSON.parse(savedState); } if (this.state.scripts.length === 0) { // Create a default script if none exist const newScript = { id: Date.now(), name: 'Script 1', code: '// Welcome to TriX Executor!\n' }; this.state.scripts.push(newScript); this.state.activeTabId = newScript.id; } }, saveState: function() { GM_setValue('TriX_Scripts', JSON.stringify(this.state)); }, render: function() { const container = document.getElementById('trix-content'); container.innerHTML = ` <div id="trix-injector-container"> <div class="trix-tabs"> ${this.state.scripts.map(script => ` <div class="trix-tab ${script.id === this.state.activeTabId ? 'active' : ''}" data-id="${script.id}"> <span class="trix-tab-name">${script.name}</span> <span class="trix-tab-close">×</span> </div> `).join('')} <button id="trix-new-tab-btn" title="New Script">+</button> </div> <div class="trix-editor-area"> <textarea id="trix-editor-input" spellcheck="false"></textarea> <pre id="trix-editor-highlight" class="language-js"><code class="language-js"></code></pre> </div> <div class="trix-action-bar"> <button id="trix-execute-btn" class="trix-button">Execute (Ctrl+Enter)</button> </div> <div id="trix-status-bar" class="trix-status-bar">Ready.</div> </div> `; this.elements = { tabsContainer: container.querySelector('.trix-tabs'), input: container.querySelector('#trix-editor-input'), highlight: container.querySelector('#trix-editor-highlight code'), statusBar: container.querySelector('#trix-status-bar'), executeBtn: container.querySelector('#trix-execute-btn'), }; this.updateEditorContent(); }, updateEditorContent: function() { const activeScript = this.state.scripts.find(s => s.id === this.state.activeTabId); if (activeScript) { this.elements.input.value = activeScript.code; this.elements.highlight.textContent = activeScript.code; Prism.highlightElement(this.elements.highlight); } }, attachEventListeners: function() { const container = document.getElementById('trix-content'); // Tab management container.addEventListener('click', (e) => { const target = e.target; if (target.id === 'trix-new-tab-btn') this.handleNewTab(); else if (target.classList.contains('trix-tab-close')) this.handleCloseTab(target.parentElement.dataset.id); else if (target.closest('.trix-tab')) this.handleTabClick(target.closest('.trix-tab').dataset.id); }); // Tab renaming container.addEventListener('dblclick', (e) => { const tabNameSpan = e.target.closest('.trix-tab-name'); if (tabNameSpan) this.handleRenameTab(tabNameSpan); }); // Editor input and sync this.elements.input.addEventListener('input', this.handleCodeInput.bind(this)); this.elements.input.addEventListener('scroll', () => { this.elements.highlight.parentElement.scrollTop = this.elements.input.scrollTop; this.elements.highlight.parentElement.scrollLeft = this.elements.input.scrollLeft; }); // Execute button this.elements.executeBtn.addEventListener('click', this.handleExecute.bind(this)); this.elements.input.addEventListener('keydown', (e) => { if (e.ctrlKey && e.key === 'Enter') { e.preventDefault(); this.handleExecute(); } }); }, handleCodeInput: function() { const code = this.elements.input.value; const activeScript = this.state.scripts.find(s => s.id === this.state.activeTabId); if (activeScript) { activeScript.code = code; this.elements.highlight.textContent = code; Prism.highlightElement(this.elements.highlight); this.saveState(); } }, handleNewTab: function() { const newId = Date.now(); const newScript = { id: newId, name: `Script ${this.state.scripts.length + 1}`, code: '' }; this.state.scripts.push(newScript); this.state.activeTabId = newId; this.saveState(); this.render(); this.attachEventListeners(); // Re-attach listeners after re-render }, handleCloseTab: function(tabId) { tabId = Number(tabId); const tabIndex = this.state.scripts.findIndex(s => s.id === tabId); this.state.scripts.splice(tabIndex, 1); if (this.state.activeTabId === tabId) { this.state.activeTabId = this.state.scripts[tabIndex]?.id || this.state.scripts[tabIndex - 1]?.id || null; } if (this.state.scripts.length === 0) { this.handleNewTab(); // Don't allow zero tabs return; } this.saveState(); this.render(); this.attachEventListeners(); }, handleTabClick: function(tabId) { this.state.activeTabId = Number(tabId); this.saveState(); // No full re-render needed, just update classes and content document.querySelectorAll('.trix-tab').forEach(t => t.classList.remove('active')); document.querySelector(`.trix-tab[data-id="${tabId}"]`).classList.add('active'); this.updateEditorContent(); }, handleRenameTab: function(span) { const tabId = Number(span.closest('.trix-tab').dataset.id); const script = this.state.scripts.find(s => s.id === tabId); const input = document.createElement('input'); input.type = 'text'; input.value = span.textContent; span.replaceWith(input); input.focus(); input.select(); const saveName = () => { script.name = input.value || 'Untitled'; input.replaceWith(span); span.textContent = script.name; this.saveState(); }; input.addEventListener('blur', saveName); input.addEventListener('keydown', e => e.key === 'Enter' && saveName()); }, handleExecute: function() { const code = this.elements.input.value; try { // Using new Function() is safer than eval() as it doesn't pollute the local scope const result = (new Function(code))(); this.elements.statusBar.textContent = `Executed successfully at ${new Date().toLocaleTimeString()}.`; this.elements.statusBar.className = 'trix-status-bar trix-status-success'; console.log('TriX Execution Result:', result); } catch (error) { this.elements.statusBar.textContent = `Error: ${error.message}`; this.elements.statusBar.className = 'trix-status-bar trix-status-error'; console.error('TriX Execution Error:', error); } } }; // ----------------------------------------------------------------------------- // 5. MAIN INITIALIZATION // ----------------------------------------------------------------------------- function main() { console.log("TriX Executor: Initializing..."); SettingsModule.init(); StyleModule.inject(); UIModule.init(); ScriptInjectorModule.init(); // Initialize our new feature SettingsModule.applyTheme(); console.log("TriX Executor: Ready!"); } const checkInterval = setInterval(() => { if (document.getElementById('canvasA')) { clearInterval(checkInterval); main(); } }, 200); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址