TriX Executor for Territorial.io

A command-based executor UI with auto-join, custom space-spam, and a modular interface.

目前為 2025-07-01 提交的版本,檢視 最新版本

// ==UserScript==
// @name         TriX Executor for Territorial.io
// @namespace    Violentmonkey Scripts
// @version      18.0
// @description  A command-based executor UI with auto-join, custom space-spam, and a modular interface.
// @author       Assistant
// @match        https://territorial.io/*
// @match        https://*.croxyproxy.com/*territorial.io*
// @match        https://*/*?__cpo=*
// @grant        none
// @run-at       document-end
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // --- Configuration: Random Username Parts ---
    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', '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'
    ];
    // Tags are now empty as requested
    const tags = [];

    // --- State Variables ---
    let isAutomationRunning = false;
    let isSpammingActive = false;
    let spaceSpamIntervalId = null;

    // Stop immediately if this isn't a territorial.io page.
    if (!isTerritorialPage()) return;


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

    function createExecutorUI() {
        const executor = document.createElement('div');
        executor.id = 'trix-executor';
        Object.assign(executor.style, {
            position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%, -50%)',
            width: '500px', height: '350px', backgroundColor: '#1e1e1e', border: '1px solid #444',
            borderRadius: '5px', zIndex: '100000', display: 'flex', flexDirection: 'column',
            boxShadow: '0 0 15px rgba(0,0,0,0.5)', fontFamily: 'Consolas, "Courier New", monospace'
        });

        // Header
        const header = document.createElement('div');
        header.id = 'trix-header';
        header.innerHTML = `<img src="https://i.postimg.cc/pVhYV8kL/image.png" style="height: 20px; margin-right: 10px; vertical-align: middle;"> TriX`;
        Object.assign(header.style, {
            backgroundColor: '#111', color: 'white', padding: '8px',
            cursor: 'move', borderTopLeftRadius: '5px', borderTopRightRadius: '5px'
        });

        // Main Body (Sidebar + Content)
        const body = document.createElement('div');
        Object.assign(body.style, { display: 'flex', flexGrow: '1', overflow: 'hidden' });

        // Sidebar
        const sidebar = document.createElement('div');
        Object.assign(sidebar.style, {
            width: '150px', 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>
        `;

        // Content Area
        const content = document.createElement('div');
        Object.assign(content.style, { flexGrow: '1', display: 'flex', flexDirection: 'column' });

        // Command Prompt Page
        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;">
                <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;">Send</button>
            </div>
        `;

        // Featured Scripts Page
        const scriptsPage = document.createElement('div');
        scriptsPage.id = 'trix-page-scripts';
        scriptsPage.className = 'trix-page';
        Object.assign(scriptsPage.style, { display: 'none', padding: '15px' });
        scriptsPage.innerHTML = `<h3>Featured Scripts</h3><p>Coming soon...</p>`;

        content.appendChild(cmdPage);
        content.appendChild(scriptsPage);
        body.appendChild(sidebar);
        body.appendChild(content);
        executor.appendChild(header);
        executor.appendChild(body);
        document.body.appendChild(executor);

        // Add CSS styles for buttons
        const style = document.createElement('style');
        style.textContent = `
            .trix-nav-button { background: none; 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 { background: #333; }
            .trix-nav-button.active { background: #0e639c; color: white; }
            #trix-history .trix-log { margin-bottom: 5px; }
            #trix-history .trix-error { color: #f44336; }
            #trix-history .trix-success { color: #4CAF50; }
        `;
        document.head.appendChild(style);

        // --- UI Functionality ---
        makeDraggable(executor, header);
        setupCommandPrompt();
        setupSidebarNavigation();
        logToHistory("Welcome to TriX Executor. Type /help for commands.");
    }

    function createStatusDashboard() {
        if (document.getElementById('trix-status-dashboard')) return; // Don't create if it exists
        const dashboard = document.createElement('div');
        dashboard.id = 'trix-status-dashboard';
        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="trix-status-header" style="padding: 8px 12px; background-color: #333; cursor: move; border-top-left-radius: 8px; border-top-right-radius: 8px;">
                <strong>Automation Status</strong>
            </div>
            <div style="padding: 12px;"><strong>Status:</strong> <span id="trix-status-text">Idle</span></div>
        `;
        document.body.appendChild(dashboard);
        makeDraggable(dashboard, dashboard.querySelector('#trix-status-header'));
    }

    function updateDashboardStatus(statusText) {
        const statusEl = document.getElementById('trix-status-text');
        if (statusEl) statusEl.innerText = statusText;
    }

    // --- COMMAND HANDLING ---

    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 handleCommand(command) {
        logToHistory(`> ${command}`);
        const [cmd, ...args] = command.trim().toLowerCase().split(' ');

        if (cmd === '/auto-join') {
            if (isAutomationRunning) {
                logToHistory("Auto-Join sequence is already running.", 'error');
                return;
            }
            const dashboard = document.getElementById('trix-status-dashboard');
            if(dashboard) dashboard.style.display = 'block';
            isAutomationRunning = true;
            startAutomation();
        } else if (cmd === '/spam') {
            if (isSpammingActive) {
                logToHistory("Spam is already active. Stop it first if you want to change the interval.", 'error');
                return;
            }
            const interval = parseTimeInterval(args[0]);
            if (interval !== null) {
                logToHistory(`Starting space spam every ${args[0]}.`, 'success');
                startSpaceSpam(interval);
            } else {
                logToHistory("Invalid time interval. Use format like '5s' or '2min'. Max is 9min, 59s.", 'error');
            }
        } else if (cmd === '/stop') {
             if(isSpammingActive) {
                 stopSpaceSpam();
                 logToHistory("Spam stopped.", 'success');
             } else {
                 logToHistory("Nothing to stop.", 'error');
             }
        } else if (cmd === '/help') {
            logToHistory("Available Commands:");
            logToHistory("/auto-join - Starts the full join sequence.");
            logToHistory("/spam [interval] - Starts space spam (e.g., /spam 5s).");
            logToHistory("/stop - Stops the space spam.");
        }
        else {
            logToHistory(`Unknown command: ${cmd}`, 'error');
        }
    }

    function logToHistory(message, type = 'log') {
        const history = document.getElementById('trix-history');
        const entry = document.createElement('div');
        entry.className = `trix-${type}`;
        entry.textContent = message;
        history.appendChild(entry);
        history.scrollTop = history.scrollHeight;
    }

    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;
        }

        const maxSeconds = 9 * 60 + 59;
        if (seconds > maxSeconds || seconds <= 0) return null;

        return seconds * 1000;
    }

    // --- CORE AUTOMATION LOGIC ---

    function startAutomation() {
        logToHistory("Starting automation sequence...", 'success');
        updateDashboardStatus('Running sequence...');
        autoFillUsername()
            .then(() => waitForElementAndClick(findMultiplayerButton, "'Multiplayer' button"))
            .then(() => waitForElementAndClick(findReadyButton, "'Ready' button"))
            .then(() => {
                isAutomationRunning = false;
                updateDashboardStatus('Sequence Complete. Ready to play.');
                logToHistory("Auto-Join sequence complete!", 'success');
            })
            .catch(error => {
                console.error(error);
                isAutomationRunning = false;
                updateDashboardStatus('Error!');
                logToHistory(error.message, 'error');
            });
    }

    function autoFillUsername() {
        return new Promise((resolve, reject) => {
            waitForElement(findUsernameInput, 'Username Input Field').then(nameInput => {
                const username = generateRandomUsername();
                logToHistory(`Setting name: ${username}`);
                updateDashboardStatus(`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 generateRandomUsername() {
        const randomBase = baseNames[Math.floor(Math.random() * baseNames.length)];
        // Tags array is empty, so no tag will be added.
        if (tags.length > 0) {
            const randomTag = tags[Math.floor(Math.random() * tags.length)];
            return Math.random() < 0.5 ? randomTag + randomBase : randomBase + randomTag;
        }
        return randomBase;
    }

    function startSpaceSpam(intervalMs) {
        if (isSpammingActive) return;
        isSpammingActive = true;
        updateDashboardStatus(`Spamming Space key every ${intervalMs / 1000}s...`);
        spaceSpamIntervalId = setInterval(() => {
            document.dispatchEvent(new KeyboardEvent('keydown', { 'key': ' ', 'code': 'Space', 'keyCode': 32, 'bubbles': true }));
        }, intervalMs);
    }

    function stopSpaceSpam() {
        if (!isSpammingActive) return;
        clearInterval(spaceSpamIntervalId);
        isSpammingActive = false;
        updateDashboardStatus('Spam Stopped. Idle.');
    }


    // --- HELPER & UTILITY FUNCTIONS ---

    function setupSidebarNavigation() {
        const buttons = document.querySelectorAll('.trix-nav-button');
        buttons.forEach(button => {
            button.addEventListener('click', () => {
                buttons.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 ? 'flex' : 'none';
                });
            });
        });
    }

    function makeDraggable(element, handle) {
        let isDragging = false, offsetX, offsetY;
        handle.onmousedown = (e) => {
            isDragging = true;
            offsetX = e.clientX - element.offsetLeft;
            offsetY = e.clientY - element.offsetTop;
            document.onmousemove = (e) => {
                if (!isDragging) return;
                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'));

    // --- INITIALIZER ---
    function initialize() {
        waitForElement(findUsernameInput, "Game UI to load")
            .then(() => {
                console.log("[TriX] Executor Loaded.");
                createExecutorUI();
                createStatusDashboard();
            })
            .catch(error => {
                console.error("[TriX] Could not initialize, game UI did not load in time.", error);
            });
    }

    initialize();
})();

QingJ © 2025

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