TriX Executor for Territorial.io

TriX is a powerful, command-driven script executor designed to enhance your territorial.io experience. It features a modular interface with a command prompt for quick automation, a 'Featured Scripts' section for loading complex modules like the F-key controlled Auto-Join & Play script, and a dedicated JavaScript Executor for running your own custom code. ⚠️ The JS Executor is a powerful tool; never run code from untrusted sources. Take control of your game with TriX.

当前为 2025-07-02 提交的版本,查看 最新版本

// ==UserScript==
// @name         TriX Executor for Territorial.io
// @namespace    Violentmonkey Scripts
// @version      30.0.2
// @description  TriX is a powerful, command-driven script executor designed to enhance your territorial.io experience. It features a modular interface with a command prompt for quick automation, a 'Featured Scripts' section for loading complex modules like the F-key controlled Auto-Join & Play script, and a dedicated JavaScript Executor for running your own custom code. ⚠️ The JS Executor is a powerful tool; never run code from untrusted sources. Take control of your game with TriX.
// @author       Painsel & Assistant
// @match        https://territorial.io/*
// @match        https://*.croxyproxy.com/*territorial.io*
// @match        https://*/*?__cpo=*
// @match        about:blank
// @grant        window.open
// @run-at       document-end
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // --- Configuration & State ---
    const isController = window.location.hash === '#trix-controller';
    const isGame = !isController && isTerritorialPage();
    const tabId = sessionStorage.getItem('trixTabId') || Date.now() + Math.random();
    sessionStorage.setItem('trixTabId', tabId);

    const baseNames = ['Strategist','Ironclad','Vanguard','Tactician','Swiftstrike','Commander','Sentinel','Echo','Shadow','Apex','Overwatch','Pioneer','Horizon','Maverick','Pathfinder','Siege','Rampart','Nexus','Warden','Beacon','Vengeance','Fury','Razor','Annihilator','Slayer','Berserker','Havoc','Destroyer','Venom','Overlord','Executioner','Dominator','Reaper','Conqueror','Thunder','Juggernaut','Warlord','Avalanche','Brutal','Phantom','Specter','Cipher','Rogue','Enigma','Obscure','Whisper','Nomad','Drifter','Wanderer','Cryptic','Illusionist','Abyss','Void','Stalker','Wraith','Shade','Mirage','Eclipse','Pixel','Ninja','Quasar','Goblin','Sparky','Unicorn','GummyBear','Captain','Phoenix','Fuzzy','Whiz','Zoom','Giggle','Panda','Retro','Waffle','Disco','Cosmic','Jellyfish','BubbleGum','Player','Gamer','Pro','Warrior','Legend','Elite','Ace','Ruler','Master','Chief','Hunter','Zealot','Crusader','Guardian','Knight','Baron','Duke','King','Queen','Aegis','Alpha','Amazon','Ambush','Android','Apollo','Arcane','Archer','Arctic','Argon','Argus','Ares','Armada','Arrow','Artillery','Asgard','Ash','Assassin','Asteroid','Astra','Atlas','Atom','Aurora','Avatar','Avenger','Axiom','Azrael','Azure','Ballista','Bandit','Banshee','Barbarian','Barrage','Basilisk','Bastion','Battalion','Bear','Behemoth','Biscuit','Blackout','Blade','Blaster','Blaze','Blitz','Blizzard','Blockade','Bolt','Bomber','Boop','Borealis','Breaker','Brigade','Bullet','Button','Cabal','Cadet','Caliber','Canyon','Cascade','Cataclysm','Catalyst','Catapult','Cavalry','Centurion','Cerberus','Chaos','Charger','Chimera','Cinder','Citadel','Cleric','Cliff','Cobra'];
    let trixAutomationRunning = false, trixSpammingActive = false, trixSpaceSpamIntervalId = null;
    let autoJoinScriptExecuted = false;

    if (!isGame && !isController) return;


    // --- UI CREATION AND MANAGEMENT ---

    function createExecutorUI() {
        if (document.getElementById('trix-frame')) return;
        const frame=document.createElement("div");frame.id="trix-frame",Object.assign(frame.style,{position:"fixed",top:"50%",left:"50%",transform:"translate(-50%, -50%)",background:"#111",border:"1px solid #444",borderRadius:"6px",zIndex:"100000",boxShadow:"0 0 15px rgba(0,0,0,0.5)",padding:"8px",cursor:"move",animation:"trix-fade-in 0.3s ease-out"});
        const executor=document.createElement("div");executor.id="trix-executor",Object.assign(executor.style,{width:"600px",height:"420px",backgroundColor:"#1e1e1e",display:"flex",flexDirection:"column",fontFamily:'Consolas, "Courier New", monospace',cursor:"default"});
        const header=document.createElement("div");header.id="trix-header",Object.assign(header.style,{backgroundColor:"#111",color:"white",padding:"8px",borderTopLeftRadius:"5px",borderTopRightRadius:"5px",display:"flex",justifyContent:"space-between",alignItems:"center"}),header.innerHTML=`<div><img src="https://i.postimg.cc/pVhYV8kL/image.png" style="height: 20px; margin-right: 10px; vertical-align: middle;"> TriX <span style="font-size: 0.7em; color: #888;">by Painsel</span></div>`;const headerControls=document.createElement("div");Object.assign(headerControls.style,{display:"flex",alignItems:"center",gap:"8px"});
        const popOutButton=document.createElement("button");popOutButton.title="Pop out Controller",popOutButton.innerHTML='<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line></svg>',Object.assign(popOutButton.style,{background:"#555",border:"none",color:"white",borderRadius:"4px",cursor:"pointer",width:"22px",height:"22px",display:"flex",alignItems:"center",justifyContent:"center"});const toggleButton=document.createElement("button");toggleButton.innerHTML="−",Object.assign(toggleButton.style,{background:"#555",border:"none",color:"white",borderRadius:"4px",cursor:"pointer",width:"22px",height:"22px",fontSize:"16px",lineHeight:"1",padding:"0"});const injectButton=document.createElement("button");injectButton.id="trix-inject-btn",injectButton.textContent="Inject",Object.assign(injectButton.style,{background:"#c62828",color:"white",border:"1px solid #d32f2f",padding:"4px 10px",borderRadius:"4px",cursor:"pointer",fontFamily:"inherit",transition:"background-color 0.3s"});
        const tabCounter=document.createElement("span");tabCounter.id="trix-tab-counter",tabCounter.title="Active territorial.io tabs",Object.assign(tabCounter.style,{color:"#ccc",fontSize:"12px",marginRight:"8px",background:"#252526",padding:"3px 6px",borderRadius:"4px"}),tabCounter.textContent="Tabs: 0";
        headerControls.appendChild(tabCounter),headerControls.appendChild(popOutButton),headerControls.appendChild(toggleButton),headerControls.appendChild(injectButton),header.appendChild(headerControls);
        const body=document.createElement("div");body.id="trix-body",Object.assign(body.style,{display:"flex",flexGrow:"1",overflow:"hidden",height:"100%"});
        const sidebar=document.createElement("div");Object.assign(sidebar.style,{width:"160px",backgroundColor:"#252526",padding:"10px 0",borderRight:"1px solid #444"}),sidebar.innerHTML=`<button class="trix-nav-button active" data-page="cmd">Command Prompt</button><button class="trix-nav-button" data-page="scripts">Featured Scripts</button><button class="trix-nav-button" id="trix-executor-nav-btn" data-page="executor" disabled>Script Executor</button><button class="trix-nav-button" id="trix-server-log-nav-btn" data-page="serverlog" disabled>Server Logs</button><button class="trix-nav-button" data-page="changelog">Changelog</button>`;
        const content=document.createElement("div");Object.assign(content.style,{flexGrow:"1",display:"flex",flexDirection:"column"});
        const cmdPage=document.createElement("div");cmdPage.id="trix-page-cmd",cmdPage.className="trix-page",Object.assign(cmdPage.style,{display:"flex",flexDirection:"column",height:"100%"}),cmdPage.innerHTML=`<div id="trix-history" style="flex-grow: 1; padding: 10px; overflow-y: auto; font-size: 13px;"></div><div style="display: flex; border-top: 1px solid #444; align-items: center; padding-left: 10px;"><label for="trix-target-input" style="color: #ccc; font-size: 12px; margin-right: 5px;">Targets:</label><input type="number" id="trix-target-input" min="1" placeholder="All" style="width: 50px; background: #333; border: 1px solid #555; color: white; padding: 4px; border-radius: 3px;"><input type="text" id="trix-cmd-input" placeholder="Type a command..." style="flex-grow: 1; background: #333; border: none; color: white; padding: 8px; outline: none;"><button id="trix-send-btn" style="background: #0e639c; color: white; border: none; padding: 0 15px; cursor: pointer; align-self: stretch;">Send</button></div>`;
        const scriptsPage=document.createElement("div");scriptsPage.id="trix-page-scripts",scriptsPage.className="trix-page",Object.assign(scriptsPage.style,{display:"none",padding:"15px",overflowY:"auto"});
        const executorPage=document.createElement("div");executorPage.id="trix-page-executor",executorPage.className="trix-page",Object.assign(executorPage.style,{display:"none",flexDirection:"column",height:"100%",padding:"10px"}),executorPage.innerHTML=`<div style="margin-bottom: 5px; color: #ffeb3b;">⚠️ JS Executor. End with 'return { ... }' to manage it in the F12 console.</div><textarea id="trix-script-input" placeholder="let myVar = 10;\\nfunction myFunc(){...}\\n\\nreturn { myVar, myFunc };" style="flex-grow: 1; background: #111; color: #e0e0e0; border: 1px solid #444; resize: none; width: 100%; box-sizing: border-box; font-family: inherit;"></textarea><div style="display: flex; gap: 10px; margin-top: 10px;"><button id="trix-execute-script-btn" style="background: #c62828; color: white; border: none; padding: 10px; cursor: pointer; flex-grow: 1;">Execute</button><button id="trix-save-script-btn" style="background: #0277bd; color: white; border: none; padding: 10px; cursor: pointer;">Save</button><button id="trix-clear-script-btn" style="background: #555; color: white; border: none; padding: 10px; cursor: pointer;">Clear</button></div>`;
        const changelogPage=document.createElement("div");changelogPage.id="trix-page-changelog",changelogPage.className="trix-page",Object.assign(changelogPage.style,{display:"none",padding:"15px",overflowY:"auto",color:"#ccc",fontSize:"13px"});
        const serverLogPage=document.createElement("div");serverLogPage.id="trix-page-serverlog",serverLogPage.className="trix-page",Object.assign(serverLogPage.style,{display:"none",padding:"15px",overflowY:"auto",color:"#ccc",fontSize:"13px"}),serverLogPage.innerHTML=`<h3 style="color: white; margin-top: 0;">Simulated Server Logs</h3><div id="trix-server-log-content"></div>`;
        content.appendChild(cmdPage),content.appendChild(scriptsPage),content.appendChild(executorPage),content.appendChild(changelogPage),content.appendChild(serverLogPage),body.appendChild(sidebar),body.appendChild(content),executor.appendChild(header),executor.appendChild(body),frame.appendChild(executor),document.body.appendChild(frame),addGlobalStyles(),makeDraggable(frame),setupCommandPrompt(),setupSidebarNavigation(),populateFeaturedScripts(),populateChangelog(changelogPage),setupExecutorInjection(injectButton),logToHistory("Welcome to TriX Executor. Type /help for commands."),toggleButton.onclick=()=>{const isMinimized=body.style.display==="none";body.style.display=isMinimized?"flex":"none",toggleButton.innerHTML=isMinimized?"−":"+"},popOutButton.onclick=()=>{window.open("about:blank#trix-controller","_blank","width=650,height=480,resizable=yes,scrollbars=no"),document.getElementById("trix-frame").style.display="none"},isController&&(popOutButton.style.display="none",document.title="TriX Controller")}

    // --- CROSS-TAB COMMUNICATION & TAB COUNTING ---
    function sendCommandToGame(command, args = [], targetCount = 999) {
        const payload = { cmd: command, args: args, targetCount: targetCount, commandId: Date.now() };
        localStorage.setItem('trix-command', JSON.stringify(payload));
    }
    function setupStorageListener() {
        if (isGame) {
            window.addEventListener('storage', e => {
                if (e.key === 'trix-command' && e.newValue) {
                    const payload = JSON.parse(e.newValue);
                    shouldIExecute(payload).then(doExecute => {
                        if (!doExecute) return;
                        logToHistory(`Executing command: ${payload.cmd}`);
                        switch(payload.cmd) {
                            case 'auto-join': if (!trixAutomationRunning) { trixAutomationRunning = true; startTrixAutomation(); } break;
                            case 'spam': startTrixSpaceSpam(payload.args[0]); break;
                            case 'stop': stopTrixSpaceSpam(); break;
                            case 'detach': if (window.trixHandle) { delete window.trixHandle; logToHistory("Handle detached."); } break;
                            case 'execute-legacy': if (!autoJoinScriptExecuted) { executeAutoJoinAndPlayScript(); } break;
                            case 'execute-custom': executeCustomScript(payload.args[0]); break;
                        }
                    });
                }
            });
        }
        if (isController) {
             window.addEventListener('storage', e => {
                if (e.key === 'trix-status' && e.newValue) {
                    const { id, text } = JSON.parse(e.newValue);
                    updateStatus(id, text);
                }
            });
        }
    }
    function setupTabCounter() {
        if (isGame) {
            setInterval(() => {
                const heartbeats = JSON.parse(localStorage.getItem('trix-heartbeats') || '{}');
                heartbeats[tabId] = Date.now();
                localStorage.setItem('trix-heartbeats', JSON.stringify(heartbeats));
            }, 3000);
            window.addEventListener('beforeunload', () => {
                const heartbeats = JSON.parse(localStorage.getItem('trix-heartbeats') || '{}');
                delete heartbeats[tabId];
                localStorage.setItem('trix-heartbeats', JSON.stringify(heartbeats));
            });
        }
        if (isController) {
            setInterval(() => {
                const heartbeats = JSON.parse(localStorage.getItem('trix-heartbeats') || '{}');
                const now = Date.now();
                let activeCount = 0;
                for (const id in heartbeats) {
                    if (now - heartbeats[id] < 5000) { activeCount++; }
                    else { delete heartbeats[id]; }
                }
                localStorage.setItem('trix-heartbeats', JSON.stringify(heartbeats));
                const counterEl = document.getElementById('trix-tab-counter');
                if(counterEl) counterEl.textContent = `Tabs: ${activeCount}`;
            }, 1000);
        }
    }
    function shouldIExecute(payload) {
        return new Promise(resolve => {
            let attempts = 0;
            const tryLock = setInterval(() => {
                if (attempts++ > 100) { clearInterval(tryLock); return resolve(false); }
                if (localStorage.getItem('trix-exec-lock')) return;
                localStorage.setItem('trix-exec-lock', 'true');
                const counterKey = `trix-exec-count-${payload.commandId}`;
                let count = parseInt(localStorage.getItem(counterKey) || '0', 10);
                if (count < payload.targetCount) {
                    count++;
                    localStorage.setItem(counterKey, count);
                    localStorage.removeItem('trix-exec-lock');
                    clearInterval(tryLock);
                    resolve(true);
                } else {
                    localStorage.removeItem('trix-exec-lock');
                    clearInterval(tryLock);
                    resolve(false);
                }
            }, 50);
        });
    }

    // --- COMMAND PROMPT & UI LOGIC ---
    function handleCommand(command) {
        logToHistory(`> ${command}`);
        const [cmd, ...args] = command.trim().toLowerCase().split(" ");
        const targetCount = parseInt(document.getElementById("trix-target-input").value, 10) || 999;
        if (isController) {
            sendCommandToGame(cmd.substring(1), args, targetCount);
            return;
        }
        if (cmd === "/auto-join") {
            if (trixAutomationRunning) return logToHistory("Sequence already running.", "error");
            trixAutomationRunning = true;
            startTrixAutomation();
        } else if (cmd === "/spam") {
            if (trixSpammingActive) return logToHistory("Spam is already active.", "error");
            const interval = parseTimeInterval(args[0]);
            interval ? (logToHistory(`Starting spam every ${args[0]}.`, "success"), startTrixSpaceSpam(interval)) : logToHistory("Invalid time interval.", "error");
        } else if (cmd === "/stop") {
            trixSpammingActive ? (stopTrixSpaceSpam(), logToHistory("Spam stopped.", "success")) : logToHistory("Nothing to stop.", "error");
        } else if (cmd === "/detach") {
            window.trixHandle ? (delete window.trixHandle, logToHistory("Handle detached.", "success")) : logToHistory("No handle attached.", "error");
        } else if (cmd === "/help") {
            logToHistory("Available Commands: /auto-join, /spam [e.g. 5s], /stop, /detach");
        } else {
            logToHistory(`Unknown command: ${cmd}`, "error");
        }
    }

    // --- SCRIPT EXECUTOR MODULE ---
    function setupExecutorInjection(button) {
        button.addEventListener('click', () => {
            button.textContent = 'Injecting...'; button.style.backgroundColor = '#fbc02d'; button.disabled = true;
            logToHistory("Injecting JavaScript Runtime...");
            setTimeout(() => {
                logToHistory("Injection successful. Script Executor is now online.", "success");
                document.getElementById('trix-executor-nav-btn').disabled = false;
                document.getElementById('trix-server-log-nav-btn').disabled = false;
                button.textContent = 'Injected ✔'; button.style.backgroundColor = '#2e7d32';
                document.getElementById('trix-execute-script-btn').addEventListener('click', () => executeCustomScript());
                document.getElementById('trix-clear-script-btn').addEventListener('click', () => { document.getElementById('trix-script-input').value = ''; });
                document.getElementById('trix-save-script-btn').addEventListener('click', saveScriptToFile);
            }, 1500);
        });
    }
    function executeCustomScript(scriptText = null) {
        scriptText = scriptText ?? document.getElementById('trix-script-input').value;
        const targetCount = parseInt(document.getElementById("trix-target-input").value, 10) || 999;
        if (isController) {
            sendCommandToGame('execute-custom', [scriptText], targetCount);
            return;
        }
        if (scriptText.trim() === '') return logToHistory("Script input is empty.", "error");
        logToHistory("Executing custom script...");
        try {
            window.trixHandle = new Function(scriptText)();
            logToHistory("Script attached. Use 'trixHandle' in F12 console to manage.", "success");
            logToServerPanel(`[200 OK] Script attached to window.trixHandle.`, 'success');
        } catch (e) {
            logToServerPanel(`[500 ERROR] ${e.message}`, 'error');
            console.error("Custom Script Error:", e);
        }
    }
    function saveScriptToFile() {
        const scriptText = document.getElementById("trix-script-input").value;
        if (scriptText.trim() === '') return logToHistory("Cannot save an empty script.", "error");
        const blob = new Blob([scriptText], { type: 'text/plain;charset=utf-8' });
        const now = new Date();
        const pad = num => num.toString().padStart(2, '0');
        const timestamp = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}_${pad(now.getHours())}-${pad(now.getMinutes())}-${pad(now.getSeconds())}`;
        const filename = `trix_script_${timestamp}.txt`;
        const link = document.createElement('a');
        link.href = URL.createObjectURL(blob);
        link.download = filename;
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
        URL.revokeObjectURL(link.href);
        logToHistory(`Script saved as ${filename}`, 'success');
    }

    // --- ALL OTHER FUNCTIONS (UNCHANGED, READABLE FORMAT) ---
    function logToServerPanel(message, type = 'log') {
        const logContent = document.getElementById('trix-server-log-content');
        if (!logContent) return;
        const entry = document.createElement('div');
        entry.className = `trix-${type}`;
        const timestamp = new Date().toLocaleTimeString();
        entry.innerHTML = `<span style="color: #888;">[${timestamp}]</span> ${message}`;
        logContent.appendChild(entry);
        logContent.scrollTop = logContent.scrollHeight;
    }
    function populateChangelog(container) {
        container.innerHTML = `
            <h3 style="color:white;margin-top:0">Changelog</h3>
            <h4>v30.0.1 - Tab Counter Fix</h4><ul><li>Fixed a critical bug where the tab counter was not being initialized.</li></ul>
            <h4>v30.0.0 - Multi-Tab Control</h4><ul><li>Added popup controller window.</li><li>Implemented live tab counter and targeted command execution.</li></ul>
            <h4>v29.0.1 - Embed UI Fix</h4><ul><li>Fixed a critical bug where the UI would not load in the new 'controller' tab.</li></ul>
            <h4>v28.0.1 - Draggable Border</h4><ul><li>Wrapped the UI in a frame to create a larger draggable border.</li></ul>`;
    }
    function addGlobalStyles() {
        const style = document.createElement('style');
        style.textContent = `@keyframes trix-fade-in{from{opacity:0;transform:translate(-50%,-50%) scale(.95)}to{opacity:1;transform:translate(-50%,-50%) scale(1)}}#trix-executor-nav-btn:disabled,#trix-server-log-nav-btn:disabled{color:#666;cursor:not-allowed}.trix-nav-button{background:0 0;border:none;color:#ccc;display:block;width:100%;text-align:left;padding:10px 15px;cursor:pointer;font-family:inherit;font-size:14px}.trix-nav-button:hover:not(:disabled){background:#333}.trix-nav-button.active{background:#0e639c;color:#fff}#trix-history .trix-log,#trix-server-log-content .trix-log{margin-bottom:5px}#trix-history .trix-error,#trix-server-log-content .trix-error{color:#f44336}#trix-history .trix-success,#trix-server-log-content .trix-success{color:#4caf50}.featured-script-card{background-color:#2a2d2e;border:1px solid #444;border-radius:4px;padding:15px;display:flex;align-items:center;gap:15px}.featured-script-card img{width:64px;height:64px;border-radius:4px}.featured-script-card .info p{margin:5px 0 10px;font-size:13px;color:#ccc}.featured-script-card button{background:#4caf50;color:#fff;border:none;padding:8px 12px;border-radius:4px;cursor:pointer}.featured-script-card button:disabled{background:#555;cursor:not-allowed}`;
        document.head.appendChild(style);
    }
    function populateFeaturedScripts() {
        const container = document.getElementById("trix-page-scripts");
        const scriptCard = document.createElement("div");
        scriptCard.className = "featured-script-card";
        scriptCard.innerHTML = `<img src="https://i.postimg.cc/P5w5PX9Z/image.png" alt="Script Logo"><div class="info"><h3>Auto-Join & Play</h3><p>Loads a script with F-key controls, multi-tab "arming", and its own status dashboard.</p><button id="execute-auto-join">Execute</button></div>`;
        container.appendChild(scriptCard);
        document.getElementById("execute-auto-join").addEventListener("click", () => {
            if (autoJoinScriptExecuted) return logToHistory("Auto-Join & Play script already running.", "error");
            const targetCount = parseInt(document.getElementById("trix-target-input").value, 10) || 999;
            isController ? sendCommandToGame("execute-legacy", [], targetCount) : executeAutoJoinAndPlayScript();
            document.getElementById("execute-auto-join").textContent = "Executed ✔";
            document.getElementById("execute-auto-join").disabled = true;
        });
    }
    function createStatusDashboard(id, title) {
        if (document.getElementById(id)) return;
        const dashboard = document.createElement("div");
        dashboard.id = id;
        Object.assign(dashboard.style, { position: "fixed", top: "20px", left: "20px", zIndex: "99999", display: "none", backgroundColor: "rgba(0, 0, 0, 0.75)", color: "white", border: "1px solid #888", borderRadius: "8px", fontFamily: "sans-serif", fontSize: "14px", minWidth: "280px", userSelect: "none" });
        dashboard.innerHTML = `<div id="${id}-header" style="padding: 8px 12px; background-color: #333; cursor: move; border-radius: 8px 8px 0 0;"><strong>${title}</strong></div><div style="padding: 12px;"><strong>Status:</strong> <span id="${id}-text">Idle</span></div>`;
        document.body.appendChild(dashboard);
        makeDraggable(dashboard);
    }
    function setupCommandPrompt() {
        const input = document.getElementById("trix-cmd-input");
        const sendBtn = document.getElementById("trix-send-btn");
        const handler = () => { if (input.value.trim()) { handleCommand(input.value); input.value = ''; } };
        input.addEventListener("keydown", e => { if (e.key === 'Enter') handler(); });
        sendBtn.addEventListener("click", handler);
    }
    function setupSidebarNavigation() {
        document.querySelectorAll(".trix-nav-button").forEach(button => {
            button.addEventListener("click", () => {
                if (button.disabled) return;
                document.querySelectorAll(".trix-nav-button").forEach(btn => btn.classList.remove("active"));
                button.classList.add("active");
                const pageId = `trix-page-${button.dataset.page}`;
                document.querySelectorAll(".trix-page").forEach(page => {
                    page.style.display = page.id === pageId ? (page.id.includes("cmd") || page.id.includes("executor") ? "flex" : "block") : "none";
                });
            });
        });
    }
    function startTrixAutomation() {
        updateStatusInStorage("trix-status-dashboard", "Running sequence...");
        autoFillUsername().then(() => waitForElementAndClick(findMultiplayerButton, "'Multiplayer' button")).then(() => waitForElementAndClick(findReadyButton, "'Ready' button")).then(() => {
            trixAutomationRunning = false;
            updateStatusInStorage("trix-status-dashboard", "Sequence Complete.");
        }).catch(error => {
            trixAutomationRunning = false;
            updateStatusInStorage("trix-status-dashboard", "Error!");
            logToHistory(error.message, "error");
        });
    }
    function startTrixSpaceSpam(intervalMs) {
        if (trixSpammingActive) return;
        trixSpammingActive = true;
        updateStatusInStorage("trix-status-dashboard", `Spamming...`);
        trixSpaceSpamIntervalId = setInterval(() => { document.dispatchEvent(new KeyboardEvent("keydown", { key: " ", code: "Space", keyCode: 32, bubbles: true })); }, intervalMs);
    }
    function stopTrixSpaceSpam() {
        if (!trixSpammingActive) return;
        clearInterval(trixSpaceSpamIntervalId);
        trixSpammingActive = false;
        updateStatusInStorage("trix-status-dashboard", "Spam Stopped.");
    }
    function executeAutoJoinAndPlayScript() {
        autoJoinScriptExecuted = true;
        logToHistory("Executing Auto-Join & Play script...", "success");
        const legacyBaseNames = ["Abyss", "Ace", "Aegis", "Agent", "Algorithm", "Alpha", "Alpine", "Amazon", "Ambush", "Android", "Annihilator", "Apex", "Apollo", "Arcane", "Archer", "Arctic", "Argon", "Argus", "Ares", "Armada", "Arrow", "Artillery", "Asgard", "Ash", "Assassin", "Asteroid", "Astra", "Atlas", "Atom", "Aurora", "Avalanche", "Avatar", "Avenger", "Axiom", "Azrael", "Azure", "Ballista", "Bandit", "Banshee", "Barbarian", "Baron", "Barrage", "Basilisk", "Bastion", "Battalion", "Beacon", "Bear", "Behemoth", "Berserker", "Biscuit", "Blackout", "Blade", "Blaster", "Blaze", "Blitz", "Blizzard", "Blockade", "Bolt", "Bomber", "Boop", "Borealis", "Breaker", "Brigade", "Brutal", "BubbleGum", "Bullet", "Button", "Cabal", "Cadet", "Caliber", "Canyon", "Captain", "Cascade", "Cataclysm", "Catalyst", "Catapult", "Cavalry", "Centurion", "Cerberus", "Chaos", "Charger", "Chief", "Chimera", "Cinder", "Cipher", "Citadel", "Cleric", "Cliff", "Cobra", "Colonel", "Colossus", "Comet", "Commander", "Commando", "Conqueror", "Constellation", "Cosmic", "Cougar", "Coyote", "Crash", "Crater", "Creek", "Crescent", "Crossbow", "Crown", "Crucible", "Crusader", "Cryptic", "Crystal", "Curse", "Cyber", "Cyclone", "Cyclops", "Daemon", "Dagger", "Deadeye", "Deathwish", "Decoy", "Delta", "Demon", "Desert", "Desolator", "Destroyer", "Diablo", "Diamond", "Digger", "Disco", "Doodle", "Doomsday", "Dozer", "Draco", "Dragon", "Drifter", "Droid", "Druid", "Duke", "Dune", "Dust", "Dynamite", "Dynamo", "Dynasty", "Eagle", "Earthquake", "Echo", "Eclipse", "Edict", "Einherjar", "Elder", "Element", "Elite", "Elysium", "Ember", "Emperor", "Empire", "Enforcer", "Enigma", "Entity", "Envoy", "Eon", "Epoch", "Era", "Eruption", "Eternal", "Everest", "Executioner", "Exile", "Exodus", "Factor", "Falcon", "Famine", "Fang", "Faze", "Fenrir", "Firewall", "Fissure", "Flame", "Flash", "Flux", "Forerunner", "Forest", "Forge", "Fortress", "Fox", "Fragment", "Frenzy", "Frost", "Fury", "Fuse", "Fusion", "Fuzzy", "Gadget", "Gale", "Gamma", "Gamer", "Gargoyle", "Garrison", "Gauntlet", "Geist", "General", "Genesis", "Ghost", "Giant", "Giggle", "Glacier", "Gladiator", "Glitch", "Gloom", "Gnasher", "Goblin", "Golem", "Goliath", "Gorgon", "Granite", "Gravity", "Gremlin", "Griffin", "Grim", "Grizzly", "Groove", "Guardian", "Guerilla", "Gully", "GummyBear", "Gunner", "Hades", "Hailstorm", "Hammer", "Harbinger", "Harpy", "Havoc", "Hawk", "Hazard", "Haze", "Headhunter", "Hellfire", "Hellion", "Herald", "Hermes", "Hero", "Hex", "Hive", "Horizon", "Hornet", "Hunter", "Hurricane", "Husk", "Hydra", "Hyperion", "Ice", "Icarus", "Icon", "Ifrit", "Illusionist", "Impact", "Impulse", "Incendiary", "Inferno", "Infinity", "Infantry", "Inquisitor", "Ion", "Iron", "Ironclad", "Jaguar", "Javelin", "Jawbreaker", "Jellyfish", "Jester", "Jet", "Jinx", "Jotun", "Juggernaut", "Jungle", "Juno", "Jupiter", "Kaiser", "Kami", "Karma", "Kestrel", "King", "Kismet", "Knight", "Kodiak", "Kraken", "Kyrie", "Labyrinth", "Lagoon", "Lancer", "Landslide", "Laser", "Lava", "Legacy", "Legend", "Legion", "Leopard", "Leviathan", "Lightning", "Lion", "Lizard", "Locus", "Lotus", "Lumberjack", "Luna", "Lynx"];
        let isLegacyAutomationRunning = false, isLegacySpammingActive = false, legacySpaceSpamIntervalId = null;
        let isLegacyArmed = sessionStorage.getItem("territorialAutoStartArmed") === 'true';
        createLegacyDashboard();
        updateLegacyDashboardStatus(`Auto-start ${isLegacyArmed ? "ARMED" : "DISARMED"}.`);
        document.addEventListener("keydown", event => { if (event.key === 'F6') { event.preventDefault(); toggleLegacyManualSequence(); } if (event.key === 'F7') { event.preventDefault(); toggleLegacyArmedState(); } });
        document.addEventListener("visibilitychange", () => { if (document.visibilityState === 'visible' && isLegacyArmed && !isLegacyAutomationRunning && !isLegacySpammingActive) { isLegacyAutomationRunning = true; startLegacyAutomation(); } });
        function toggleLegacyManualSequence() { if (isLegacySpammingActive) { stopLegacySpaceSpam(); } else if (!isLegacyAutomationRunning) { isLegacyAutomationRunning = true; startLegacyAutomation(); } }
        function toggleLegacyArmedState() { isLegacyArmed = !isLegacyArmed; sessionStorage.setItem("territorialAutoStartArmed", isLegacyArmed); updateLegacyDashboardStatus(`Auto-start ${isLegacyArmed ? "ARMED" : "DISARMED"}.`); }
        function startLegacyAutomation() { updateLegacyDashboardStatus("Running sequence..."); autoFillUsername(legacyBaseNames).then(() => waitForElementAndClick(findMultiplayerButton, "'Multiplayer' button")).then(() => waitForElementAndClick(findReadyButton, "'Ready' button")).then(() => { isLegacyAutomationRunning = false; startLegacySpaceSpam(); }).catch(error => { isLegacyAutomationRunning = false; updateLegacyDashboardStatus("Error!"); logToHistory(error.message, "error"); }); }
        function startLegacySpaceSpam() { if (isLegacySpammingActive) return; isLegacySpammingActive = true; updateLegacyDashboardStatus("Spamming Space key every 5s..."); legacySpaceSpamIntervalId = setInterval(() => { document.dispatchEvent(new KeyboardEvent("keydown", { key: " ", code: "Space", keyCode: 32, bubbles: true })); }, 5000); }
        function stopLegacySpaceSpam() { if (!isLegacySpammingActive) return; clearInterval(legacySpaceSpamIntervalId); isLegacySpammingActive = false; updateLegacyDashboardStatus("Idle."); }
        function createLegacyDashboard() { const dashboard = document.createElement("div"); Object.assign(dashboard.style, { position: "fixed", top: "150px", left: "20px", zIndex: "99998", backgroundColor: "rgba(0, 0, 0, 0.75)", color: "white", border: "1px solid #888", borderRadius: "8px", fontFamily: "sans-serif", fontSize: "14px", minWidth: "280px", userSelect: "none" }); const header = document.createElement("div"); Object.assign(header.style, { padding: "8px 12px", backgroundColor: "#333", cursor: "move", borderRadius: "8px 8px 0 0", display: "flex", justifyContent: "space-between" }); header.innerHTML = "<strong>Legacy Auto-Play</strong>"; const content = document.createElement("div"); content.innerHTML = '<ul style="margin: 12px 0 12px 20px; padding: 0; list-style-type: \'» \';"><li><code>F7</code> to arm/disarm auto-start.</li><li><code>F6</code> to start/stop script.</li><li><strong>Status:</strong> <span id="legacy-dashboard-status">Idle</span></li></ul>'; dashboard.appendChild(header); dashboard.appendChild(content); document.body.appendChild(dashboard); makeDraggable(dashboard); }
        function updateLegacyDashboardStatus(text) { const el = document.getElementById("legacy-dashboard-status"); if (el) el.textContent = text; updateStatusInStorage("legacy-dashboard", text); }
    }
    function autoFillUsername(nameList = baseNames) {
        return new Promise((resolve, reject) => {
            waitForElement(findUsernameInput, "Username Input Field").then(nameInput => {
                const username = nameList[Math.floor(Math.random() * nameList.length)];
                updateStatusInStorage("trix-status-dashboard", `Setting name: ${username}`);
                nameInput.value = username;
                nameInput.dispatchEvent(new Event("input", { bubbles: true, cancelable: true }));
                nameInput.focus();
                nameInput.blur();
                setTimeout(resolve, 200);
            }).catch(reject);
        });
    }
    function logToHistory(message, type = "log") {
        const history = document.getElementById("trix-history");
        if (!history) return;
        const entry = document.createElement("div");
        entry.className = `trix-${type}`;
        entry.textContent = message;
        history.appendChild(entry);
        history.scrollTop = history.scrollHeight;
    }
    function updateStatus(dashboardId, text) {
        const textEl = document.getElementById(`${dashboardId}-text`);
        if (textEl) textEl.innerText = text;
    }
    function updateStatusInStorage(dashboardId, text) {
        if (isController) return;
        localStorage.setItem("trix-status", JSON.stringify({ id: dashboardId, text: text, ts: Date.now() }));
    }
    function parseTimeInterval(timeString) {
        if (!timeString) return null;
        const match = timeString.match(/^(\d+)(s|min)$/);
        if (!match) return null;
        let seconds = parseInt(match[1], 10);
        if (match[2] === 'min') { seconds *= 60; }
        return (seconds > 599 || seconds <= 0) ? null : seconds * 1000;
    }
    function makeDraggable(element) {
        let isDragging = false, offsetX, offsetY;
        const handle = element;
        handle.onmousedown = e => {
            if (e.target !== handle && !e.target.closest("#trix-header")) return;
            e.preventDefault();
            isDragging = true;
            offsetX = e.clientX - element.offsetLeft;
            offsetY = e.clientY - element.offsetTop;
            document.onmousemove = e => { if (isDragging) { element.style.left = `${e.clientX - offsetX}px`; element.style.top = `${e.clientY - offsetY}px`; } };
            document.onmouseup = () => { isDragging = false; document.onmousemove = document.onmouseup = null; };
        };
    }
    function isTerritorialPage() {
        const href = window.location.href;
        if (href.includes("territorial.io")) return true;
        if (href.includes("?__cpo=")) { try { return atob(new URLSearchParams(window.location.search).get("__cpo")).includes("territorial.io"); } catch (e) { return false; } }
        return false;
    }
    function waitForElement(findFunction, description) {
        return new Promise((resolve, reject) => {
            let attempts = 0, maxAttempts = 75;
            const interval = setInterval(() => {
                if (attempts++ >= maxAttempts) { clearInterval(interval); reject(new Error(`Timed out: ${description}`)); return; }
                const element = findFunction();
                if (element) { clearInterval(interval); resolve(element); }
            }, 200);
        });
    }
    function waitForElementAndClick(findFunction, description) {
        return waitForElement(findFunction, description).then(element => element.click());
    }
    const findUsernameInput = () => document.getElementById("input0");
    const findMultiplayerButton = () => Array.from(document.querySelectorAll("button")).find(btn => btn.innerText.includes("Multiplayer"));
    const findReadyButton = () => Array.from(document.querySelectorAll("button")).find(btn => btn.innerText.trim().startsWith("Ready"));
    function initialize() {
        if (isController) {
            document.body.style.backgroundColor = "#1e1e1e";
            createExecutorUI();
            createStatusDashboard("trix-status-dashboard", "TriX Automation Status");
            createStatusDashboard("legacy-dashboard", "Legacy Auto-Play");
            setupStorageListener();
            setupTabCounter();
        } else if (isGame) {
            waitForElement(findUsernameInput, "Game UI to load").then(() => {
                console.log("[TriX] Agent Loaded.");
                createExecutorUI();
                setupStorageListener();
                setupTabCounter();
            }).catch(error => {
                console.error("[TriX] Could not initialize, game UI did not load in time.", error);
            });
        }
    }
    initialize();
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址