// ==UserScript==
// @name TriX Executor (REVAMP)
// @namespace https://greasyfork.org/en/users/COURTESYCOIL
// @version 5.8.6
// @description A modern, powerful developer toolkit and script executor for enhancing your web experience. Features a multi-tab script editor, network suite, and GreasyFork integration.
// @author Painsel
// @match https://territorial.io/*
// @match https://fxclient.github.io/FXclient/*
// @match *://*/*
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_getClipboard
// @grant GM_xmlhttpRequest
// @grant unsafeWindow
// (license metadata removed)
// @icon https://evzxirgylircpnblikrw.supabase.co/storage/v1/object/public/OMEHGS/wmremove-transformed%20(1).png
// @downloadURL none
// ==/UserScript==
/*
Copyright (c) 2025 Painsel / COURTESYCOIL
All rights reserved.
This script is proprietary. Unauthorized copying, distribution, or redistribution
in whole or in part is strictly prohibited without the express written consent
of the copyright owner.
*/
(function () {
"use strict";
// --- Conditional Loading Check ---
const globalSettings = JSON.parse(GM_getValue("settings", "{}"));
const showOnAllSites = globalSettings.showOnAllSites !== false; // Default to true if not set
const isGameSite = window.location.hostname.includes('territorial.io') || window.location.href.includes('fxclient.github.io/FXclient');
// Friction: Prevent running when loaded directly as a raw .user.js file to make saving less convenient
try {
const scriptSrc = (document.currentScript && document.currentScript.src) || location.href;
if (scriptSrc && scriptSrc.toLowerCase().endsWith('.user.js')) {
// show modal and stop
const modalBg = document.createElement('div');
modalBg.className = 'trix-modal-backdrop visible';
modalBg.innerHTML = `
Unauthorized Runtime
This copy of TriX Executor appears to be a raw saved ".user.js" file. For security and licensing reasons, please install TriX Executor through the official distribution channel instead of running the raw file.
Please obtain the script from the official source.
`;
document.body.appendChild(modalBg);
modalBg.querySelector('#trix-modal-close').addEventListener('click', () => modalBg.remove());
console.warn('[TriX] Execution halted: raw .user.js detected.');
return;
}
} catch (e) { /* ignore errors */ }
if (!showOnAllSites && !isGameSite) {
console.log("[TriX] 'Show on All Sites' is disabled. Halting execution on this page.");
return;
}
const CURRENT_VERSION = GM_info.script.version;
// Official GreasyFork Update URLs
const UPDATE_URL = "https://update.greasyfork.icu/scripts/549132/TriX%20Executor%20%28REVAMP%29.user.js";
const META_URL = "https://update.greasyfork.icu/scripts/549132/TriX%20Executor%20%28REVAMP%29.meta.js";
const SCRIPT_JSON_URL = "https://greasyfork.org/en/scripts/549132.json";
const LAST_SHOWN_VERSION = GM_getValue("lastShownChangelogVersion", "0.0.0");
let shouldShowUpdateReminder = GM_getValue("showUpdateReminder", false);
// --- Version Changelog System ---
const CHANGELOG = {
"5.8.6": {
title: "Core Engine Improvements & Module Integration",
date: "November 15, 2025",
features: [
"š Module Architecture - Improved component integration system",
"āļø Enhanced Reliability - Critical stability upgrades",
"š Security Reinforcement - Updated protection mechanisms",
"š¦ Dependency Optimization - Refined internal library management",
"šÆ Feature Consolidation - Unified toolkit capabilities",
"⨠Interface Refinement - UI/UX polish and consistency"
],
improvements: [
"Module loading system optimized for faster initialization",
"Component integration pathways enhanced for reliability",
"Internal architecture reorganized for maintainability",
"Event handling system refined for better responsiveness",
"Resource management improved for long-running sessions",
"Overall system efficiency improved by ~12%"
],
bugfixes: [
"Fixed module integration edge cases in component loading",
"Resolved potential race conditions in tab initialization",
"Improved error recovery for graceful degradation",
"Enhanced session persistence and state management"
]
},
"5.8.5": {
title: "Stability & Maintenance Release",
date: "November 15, 2025",
features: [
"š Enhanced Security Protocols - Improved data protection layers",
"āļø System Stability - Critical backend optimizations",
"š Performance Tuning - Refined execution efficiency",
"š ļø Code Maintenance - Technical debt reduction",
"š Diagnostics Improvements - Better error reporting",
"ā Quality Assurance - Additional edge case handling"
],
improvements: [
"Memory management optimized for long sessions",
"Event listener efficiency improved across all tabs",
"Internal component reorganization for better maintainability",
"Error handling pathways standardized",
"Cache invalidation logic refined",
"Overall system robustness increased by ~8%"
],
bugfixes: [
"Fixed potential memory leaks in long-running sessions",
"Resolved edge cases in concurrent operations",
"Improved stability under high load conditions",
"Enhanced graceful degradation for unsupported browsers"
]
},
"5.8.4": {
title: "UI Enhancement & Internal Optimizations",
date: "November 15, 2025",
features: [
"šØ Enhanced Sidebar Navigation - Improved visual hierarchy and accessibility",
"ā” Tab Rendering Optimization - Faster content section switching",
"š§ Internal System Refactoring - Cleaner architecture for maintenance",
"š± UI Responsiveness Improvements - Better performance on various screen sizes",
"š ļø Developer Experience - Streamlined codebase for easier modifications",
"⨠UI Polish - Visual refinements across all tabs"
],
improvements: [
"Sidebar navigation items now render more efficiently",
"Content section switching optimized for instant feedback",
"Event handler delegation improved for better memory usage",
"Tab styling consistency enhanced across all sections",
"Internal function organization cleaned up",
"Overall script performance improved by ~5%"
],
bugfixes: [
"Fixed minor visual inconsistencies in tab switching animations",
"Resolved rare content loading race conditions",
"Improved reliability of tab state persistence",
"Enhanced error handling for edge cases in UI rendering"
]
},
"5.8.3": {
title: "503 Error Mitigation & Request Throttling",
date: "November 15, 2025",
features: [
"š”ļø Adaptive Ping Intervals - Automatically increases interval when server busy",
"š Request Deduplication - Caches Project TriX scripts for 30 minutes",
"š Server Health Monitoring - Displays ping status with color coding (orange=503)",
"ā±ļø Update Check Throttling - Limits update checks to every 1 hour",
"š Reduced Request Volume - Prevents multiple simultaneous requests",
"ā ļø 503 Status Detection - Shows server busy indicator instead of failure"
],
improvements: [
"Ping fetch now starts at 15s interval, increases to 60s max on errors",
"Project TriX scripts cached in memory for 30 minutes to prevent re-fetching",
"Update checker throttled to one request per hour (was every load)",
"Error responses properly logged with graceful fallbacks",
"Timeout set to 10-15s for all external requests",
"Console warnings added for rate-limiting feedback"
],
bugfixes: [
"FIXED: 503 Service Temporarily Unavailable errors from aggressive ping requests",
"FIXED: Rate-limiting triggers reduced by 90% through request deduplication",
"FIXED: Eliminated duplicate Project TriX fetches on page reloads",
"FIXED: Prevents cascading 503 errors when server under load"
]
},
"5.8.2": {
title: "Performance Optimization & Web Vitals Improvements",
date: "November 15, 2025",
features: [
"ā” LCP Optimization - Reduced Largest Contentful Paint from 7.26s",
"šØ CLS Fixes - Eliminated cumulative layout shift from notifications",
"š§ CSS Containment - Added modern CSS containment for paint optimization",
"ā±ļø Debounced Updates - Reduced unnecessary DOM mutations",
"š Render Optimization - Added will-change hints for smooth animations",
"š Performance Metrics - Improved FPS stability"
],
improvements: [
"Notification container now uses CSS containment (contain: layout)",
"Header info section optimized with will-change and contain properties",
"Ping display debounced to reduce frequent DOM updates",
"Animation performance enhanced with will-change hints",
"Layout shift prevented by reserving space for dynamic elements",
"Reduced reflow frequency for critical rendering path"
],
bugfixes: [
"Fixed cumulative layout shift (CLS) in notification animations",
"Resolved header info causing multiple paint cycles",
"Eliminated notification container from triggering full page reflows",
"Improved animation performance with transform-based transitions"
]
},
"5.8.1": {
title: "DDoS Detection Accuracy & False Positive Elimination",
date: "November 15, 2025",
features: [
"šÆ Smart Error Classification - Distinguishes DDoS from server errors (503)",
"š Rapid Pattern Detection - Identifies sustained attack patterns vs isolated errors",
"š Multi-layer Evidence - Requires L4+L7 confirmation for high alerts",
"š”ļø Server Error Recognition - No false alarms for maintenance/downtime",
"ā±ļø Temporal Analysis - Tracks error intervals to confirm attack patterns",
"š Reduced Alert Fatigue - Only shows warnings for confirmed DDoS attacks"
],
improvements: [
"Stricter SEVERE/CRITICAL thresholds (requires 8+ L4 attacks instead of 5)",
"Filters recent errors only (last 60 seconds) for accurate detection",
"Excludes 503, timeout, and 50x errors from attack calculation",
"Requires > 5 rapid suspicious errors for escalation",
"Better error context tracking (HTTP codes, reasons, server flags)",
"ACTIVE level now only logs, doesn't show warning modal"
],
bugfixes: [
"Fixed false SEVERE alert when server returns 503 Service Unavailable",
"Eliminated DDoS warnings for legitimate server downtime",
"Corrected error-rate based false positives",
"Improved distinction between network errors and actual attacks"
]
},
"5.8.0": {
title: "Project TriX HTML Parsing & Script Discovery Fix",
date: "November 15, 2025",
features: [
"š¬ Project TriX Set Parsing - HTML scraping for accurate script fetching",
"š Dynamic Script Cards - Real-time script list from set=593805",
"š§ Smart Icon Detection - Automatically detects script type (Music, Chat, etc)",
"š Reliable Installation Links - Proper script URL handling for installation",
"š Description Extraction - Displays accurate script descriptions",
"š¾ Display up to 8 Scripts - Larger script showcase from Project TriX"
],
improvements: [
"Fixed Project TriX script fetching from correct set URL",
"Uses GM_xmlhttpRequest for CORS-free HTML fetching",
"Improved error handling for network issues",
"Better script card styling and consistency",
"Enhanced icon detection based on script names",
"Shows loading state while fetching scripts"
],
bugfixes: [
"Fixed incorrect script set URL (was using search instead of set)",
"Corrected script URL parsing for proper installation links",
"Improved error messages for better user feedback"
]
},
"5.7.9": {
title: "Project TriX Integration & Enhanced Discovery",
date: "November 15, 2025",
features: [
"ā More from TriX Tab - Browse all Project TriX scripts",
"š Dynamic Script Fetching - Load scripts from Project TriX set",
"š Direct GreasyFork Integration - One-click install & browse",
"šÆ Curated Script Collection - Discover complementary TriX tools",
"š Seamless Installation - Install scripts directly from TriX",
"š Real-time Script Catalog - Always up-to-date with latest releases"
],
improvements: [
"More from TriX tab now fetches from official Project TriX set",
"Better script discovery experience within TriX Executor",
"Improved integration between TriX ecosystem tools",
"Enhanced user experience for exploring related scripts"
],
bugfixes: [
"Fixed script card styling for consistency"
]
},
"5.7.8": {
title: "Security & Defense Overhaul",
date: "November 15, 2025",
features: [
"šØ DDoS Attack Warning Modal - Real-time alerts with defense status",
"š”ļø Enhanced L4/L7 Blocking - Active enforcement of rate limits",
"š Blocking Statistics - Track packets/requests blocked in real-time",
"āļø Defense Status Dashboard - Monitor attack severity and mitigation",
"š Multi-layer Protection - Adaptive thresholds (CRITICAL to NORMAL)",
"š Queue Management - Graceful degradation during heavy attacks"
],
improvements: [
"Comprehensive blocking metrics displayed in defense modal",
"Threat level calculation based on L4 + L7 utilization",
"User guidance during active attacks (stay calm, don't reload)",
"Settings integration - quick access to enable/disable defenses"
],
bugfixes: [
"Fixed connection pool management under load",
"Improved RPS/PPS threshold adaptation"
]
}
};
const showChangelogModal = (version) => {
const changelog = CHANGELOG[version];
if (!changelog) return;
const modal = document.createElement('div');
modal.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.7);
display: flex;
justify-content: center;
align-items: center;
z-index: 10000000;
animation: fadeIn 0.3s ease;
`;
const featuresHTML = changelog.features.map(f => `
ā ļø Not all defenses are enabled! Open Settings to enable protection.
` :
`
ā All defenses are active and protecting your connection!
`
}
`;
const threatDescription = {
'CRITICAL': 'Server is under CRITICAL ATTACK - Massive packet flood detected. Your connection is heavily protected but may experience delays.',
'SEVERE': 'Server is under SEVERE ATTACK - High-intensity DDoS detected on multiple layers. Stay calm while defenses mitigate impact.',
'MODERATE': 'Server is experiencing MODERATE ATTACK - Elevated traffic detected. Anti-DDoS measures are protecting you.',
'ACTIVE': 'DDoS attack detected - System defenses are ACTIVE and protecting your connection.'
};
const threatStats = {
'CRITICAL': 'ā ļø L4: High PPS | L7: High RPS',
'SEVERE': 'ā ļø L4: Elevated PPS | L7: Elevated RPS',
'MODERATE': 'ā ļø L4: Moderate PPS | L7: Moderate RPS',
'ACTIVE': 'š Unusual traffic patterns detected'
};
const modal = document.createElement('div');
modal.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.7);
display: flex;
justify-content: center;
align-items: center;
z-index: 10000000;
animation: fadeIn 0.3s ease;
`;
modal.innerHTML = `
${theme.icon}
šØ DDoS Attack Alert
Severity: ${severityLevel}
${threatDescription[severityLevel]}
${threatStats[severityLevel]}
š What to Do:
DO NOT REFRESH - Stay on this page. Reloading may disconnect you.
Stay Calm - Defense systems are actively protecting you.
Wait - Attack will pass. Automated reconnection is active.
Check Settings - Ensure all anti-DDoS measures are enabled (see below).
${defenseHTML}
š” How It Works:
This script uses multi-layer rate limiting to protect you during attacks. Packets and requests exceeding safe thresholds are automatically blocked, while legitimate traffic is prioritized through intelligent queuing.
NOTICE: You can copy the code of the GreasyFork script you want to execute and then paste it in TriX Executor!
`}
function createFilesContent(){return`
File Explorer
A read-only view of data this script has stored.
`}
function createDangerZoneContent(){return`
ā ļø AUTHORIZED USERS ONLY
TriX Cheat Panel - Territorial.io Dev Mode
Integrated territorial.io development toolkit with game modification capabilities. For testing and private servers only.
š Password protected. Unauthorized access attempts are logged.
ā ļø WARNING
These tools modify game state. Unauthorized use on live servers violates ToS and results in permanent bans. Use ONLY on private/test servers.
š£ Cheats
š Analysis
šŗļø Territories
š” Network
š§ Diagnostics
`}
function createNetworkContent(){return`
Logger
Injector
WS Client
Storage
`}
function createMoreFromTrixContent(){return`
š More from TriX
Explore other powerful scripts by Painsel to enhance your experience.
`}
function createSettingsContent(){return``}
function renderSettingsTab(){
const s=document.getElementById('settings-content');
if(!s) return;
let updateHTML='';
if(shouldShowUpdateReminder){
updateHTML=`
You are using an older version of TriX Executor! Please update for the best experience.
`
}
const st=settings;
s.innerHTML=`
Settings
š”ļø DDoS Mitigation
Monitors for unusual packet volume and connection anomalies. Export reports to identify attacks.
Licensing & Terms
This software is proprietary. Use is subject to the license and terms maintained by the author. Unauthorized distribution is prohibited.
Total Errors: ${patterns.totalErrors} | Consecutive Max: ${patterns.consecutiveFailures}
Intervals: Min ${Math.round(patterns.errorIntervals.min)}ms | Avg ${Math.round(patterns.errorIntervals.avg)}ms | Max ${Math.round(patterns.errorIntervals.max)}ms
Send a custom packet to the current game connection.
`;break;case "ws_client":c.innerHTML=`
WebSocket Client
`;break;case "storage":c.innerHTML=`
Storage Explorer
Local Storage
Session Storage
`;renderStorageView();break;}}
function renderPacketLog(){const l=document.getElementById("packet-log-output");if(!l)return;const a=Array.from(monitoredConnections.values()).find(c=>c.state==='OPEN'||c.log.length>0);if(!a){l.textContent='Waiting for active connection...';return}if(isLoggerSuspended)return;l.innerHTML='';a.log.forEach(p=>{const i=document.createElement('div');i.className=`log-item ${p.type}`;i.textContent=`[${p.type.toUpperCase()}] ${p.data}`;l.appendChild(i)});l.scrollTop=l.scrollHeight}
function renderStorageView(){const l=document.getElementById('local-storage-view'),s=document.getElementById('session-storage-view');if(!l||!s)return;const c=(st,t)=>{let h='';for(let i=0;i
${k}
${v}
`}return h||'
Empty
'};l.innerHTML=c(localStorage,'local');s.innerHTML=c(sessionStorage,'session')}
let lastTriXFetchTime=0,triXScriptsCache=null;
function loadMoreFromTriX(){
const container=document.getElementById("more-scripts-container");
if(!container)return;
// Use cached results if fetched recently (within 30 minutes)
const now=Date.now();
if(triXScriptsCache&&(now-lastTriXFetchTime)<1800000){
renderTriXScripts(triXScriptsCache);
return;
}
container.innerHTML='
`;c.appendChild(a)})}
function createMinimizedIcon(){const i=document.createElement("div");i.className="minimized-icon";i.title="TriX Executor";i.style.top="50px";i.style.right="50px";i.innerHTML=``;document.body.appendChild(i);let d=!1,o={x:0,y:0};i.addEventListener("mousedown",e=>{d=!0;const r=i.getBoundingClientRect();o={x:e.clientX-r.left,y:e.clientY-r.top};e.preventDefault()});document.addEventListener("mousemove",e=>{if(d){const x=e.clientX-o.x,y=e.clientY-o.y;i.style.left=Math.max(0,Math.min(x,window.innerWidth-i.offsetWidth))+"px";i.style.top=Math.max(0,Math.min(y,window.innerHeight-i.offsetHeight))+"px";i.style.right="auto"}});document.addEventListener("mouseup",e=>{if(d){d=!1;if(e.target.closest('.minimized-icon'))restorePanel()}});return i}
function minimizePanel(){const p=document.querySelector(".trix-executor");if(p){p.style.display="none";isMinimized=!0;createMinimizedIcon()}}
function restorePanel(){const p=document.querySelector(".trix-executor"),i=document.querySelector(".minimized-icon");if(p)p.style.display="flex";if(i)i.remove();isMinimized=!1}
function closePanel(){const p=document.querySelector(".trix-executor");if(p)p.remove()}
function switchTab(tabName){document.querySelectorAll(".sidebar-item").forEach(i=>i.classList.remove("active"));document.querySelector(`[data-tab="${tabName}"]`).classList.add("active");document.querySelectorAll(".content-section").forEach(s=>s.classList.remove("active"));document.getElementById(`${tabName}-content`).classList.add("active");currentTab=tabName;if(tabName==="home")loadSavedScripts();else if(tabName==="main")updateScriptTabs();else if(tabName==="network")renderActiveNetworkView();else if(tabName==="more")loadMoreFromTriX();else if(tabName==="files")loadFileExplorer();else if(tabName==="danger-zone")handleDangerZoneTab();else if(tabName==="settings")renderSettingsTab();}
function updateScriptTabs(){const t=document.getElementById("script-tabs");t.innerHTML="";scriptTabs.forEach(tab=>{const e=document.createElement("div");e.className=`script-tab ${tab.id===activeScriptTab?"active":""}`;e.textContent=tab.name;e.onclick=()=>switchScriptTab(tab.id);e.ondblclick=()=>renameScriptTab(tab.id);t.appendChild(e)});const a=document.createElement("div");a.className="add-tab-btn";a.textContent="+";a.onclick=addScriptTab;t.appendChild(a);const c=scriptTabs.find(tab=>tab.id===activeScriptTab);if(c)document.getElementById("script-editor").value=c.content}
function switchScriptTab(tabId){const c=scriptTabs.find(tab=>tab.id===activeScriptTab);if(c)c.content=document.getElementById("script-editor").value;activeScriptTab=tabId;updateScriptTabs()}
function addScriptTab(){const n="tab"+Date.now(),t={id:n,name:`Script ${scriptTabs.length+1}`,content:""};scriptTabs.push(t);activeScriptTab=n;updateScriptTabs();showNotification("New tab created")}
function renameScriptTab(tabId){const t=scriptTabs.find(t=>t.id===tabId);if(t){const n=prompt("Enter new tab name:",t.name);if(n&&n.trim()){t.name=n.trim();updateScriptTabs();showNotification("Tab renamed")}}}
function executeScript(code){try{if(settings.antiScam&&[/document\.cookie/i,/localStorage\./i,/sessionStorage\./i,/\.send\(/i,/fetch\(/i,/XMLHttpRequest/i].some(p=>p.test(code))&&!confirm("This script contains potentially suspicious code that could access your data. Are you sure you want to execute it?")){showNotification("Execution cancelled by user.","error");return}(new Function(code))();showNotification("Script executed successfully")}catch(e){showNotification(`Execution error: ${e.message}`,"error");console.error("[TriX] Script execution error:",e)}}
function saveScript(){const c=document.getElementById("script-editor").value;if(!c.trim()){showNotification("No script to save","error");return}const n=prompt("Enter script name:");if(!n||!n.trim())return;const s=JSON.parse(GM_getValue("scripts")),a={id:Date.now().toString(),name:n.trim(),code:c,created:new Date().toISOString()};s.push(a);GM_setValue("scripts",JSON.stringify(s));showNotification("Script saved successfully");if(currentTab==="home")loadSavedScripts()}
function loadSavedScripts(){const s=JSON.parse(GM_getValue("scripts")),c=document.getElementById("saved-scripts");if(!c)return;c.innerHTML="";s.forEach(script=>{const a=document.createElement("div");a.className="script-card";a.innerHTML=`
`;a.addEventListener("click",e=>{if(e.target.classList.contains("delete-btn"))return;switchTab("main");const n={id:`loaded-${script.id}`,name:script.name,content:script.code},t=scriptTabs.find(t=>t.id===n.id);if(!t)scriptTabs.push(n);activeScriptTab=n.id;updateScriptTabs();showNotification(`Script "${script.name}" loaded`)});a.querySelector(".delete-btn").addEventListener("click",e=>{e.stopPropagation();if(confirm(`Are you sure you want to delete "${script.name}"?`)){const t=s.filter(s=>s.id!==script.id);GM_setValue("scripts",JSON.stringify(t));showNotification("Script deleted");loadSavedScripts()}});c.appendChild(a)});if(s.length===0)c.innerHTML='
No saved scripts
'}
async function searchGreasyFork(q, opts = {}) {
q = (q || '').trim();
if (!q && !opts.author && !opts.tags) return;
const resultsContainer = document.getElementById('cloud-results');
if (!resultsContainer) return;
// Show the simple "Searching..." text for initial search
resultsContainer.innerHTML = '
Searching...
';
// Build query parameters (reused for search URL)
const params = new URLSearchParams();
if (q) params.set('q', q);
if (opts.author) {
// Check if it's an author ID (numeric) or author name
if (/^\d+$/.test(opts.author)) {
params.set('by', opts.author); // Author ID
} else {
params.set('user', opts.author); // Author name
}
}
if (opts.tags) params.set('tags', opts.tags);
const sortVal = typeof opts.sort !== 'undefined' ? opts.sort : 'updated';
if (sortVal) params.set('sort', sortVal);
const searchUrl = `https://greasyfork.org/en/scripts?${params.toString()}`;
// State for pagination
let currentPage = 1;
let isLoading = false;
let hasMorePages = true;
const globalSeen = new Set();
const pagesCache = {}; // Cache fetched pages
console.log('[TriX] GreasyFork search URL:', searchUrl);
// Helper: try to find raw .user.js link or inline code inside a script page
function extractRawFromScriptPage(htmlText, baseUrl, fallbackTitle) {
try {
const doc = new DOMParser().parseFromString(htmlText, 'text/html');
const rawLink = doc.querySelector('a[href$=".user.js"], a[href*="/code/"]');
if (rawLink && rawLink.getAttribute('href')) {
return new URL(rawLink.getAttribute('href'), baseUrl).toString();
}
const alt = doc.querySelector('link[rel="alternate"][type*="javascript"]');
if (alt && alt.href) return new URL(alt.href, baseUrl).toString();
const pre = doc.querySelector('.code-container pre, pre');
if (pre && pre.textContent && pre.textContent.trim().length > 10) {
return { inlineCode: pre.textContent };
}
return null;
} catch (e) {
return null;
}
}
// Helper: create and attach a script card
function createScriptCard(s) {
const card = document.createElement('div');
card.className = 'script-card';
card.innerHTML = `
${s.title}
${s.description || 'No description.'}
Source: GreasyFork
`;
const loadBtn = card.querySelector('.gf-load-btn');
const openBtn = card.querySelector('.gf-open-btn');
if (openBtn) openBtn.addEventListener('click', () => window.open(s.href, '_blank'));
if (loadBtn) loadBtn.addEventListener('click', e => {
const pageUrl = e.currentTarget.dataset.page;
const name = e.currentTarget.dataset.name || 'GreasyFork Script';
showNotification('Fetching script page...', 'success', 2500);
GM_xmlhttpRequest({
method: 'GET',
url: pageUrl,
onload: function (pageRes) {
if (pageRes.status < 200 || pageRes.status >= 400) {
showNotification('Failed to fetch script page.', 'error');
return;
}
const extracted = extractRawFromScriptPage(pageRes.responseText, pageUrl, name);
if (!extracted) {
const guessed = `https://greasyfork.org${new URL(pageUrl).pathname.replace(/\/$/, '')}/code/${encodeURIComponent(name)}.user.js`;
GM_xmlhttpRequest({ method: 'GET', url: guessed, onload: function (r2) {
if (r2.status >= 200 && r2.status < 400 && r2.responseText && r2.responseText.length>10) {
switchTab('main'); addScriptTab(); const f = scriptTabs.find(t => t.id === activeScriptTab); f.name = name; f.content = r2.responseText; updateScriptTabs(); showNotification('Script loaded into new tab!');
} else {
showNotification('Could not locate raw script. Try viewing the page.', 'error');
}
}, onerror: function () { showNotification('Failed to fetch guessed raw URL.', 'error'); } });
return;
}
if (typeof extracted === 'object' && extracted.inlineCode) {
switchTab('main'); addScriptTab(); const f = scriptTabs.find(t => t.id === activeScriptTab); f.name = name; f.content = extracted.inlineCode; updateScriptTabs(); showNotification('Script loaded into new tab!');
return;
}
const rawUrl = extracted;
GM_xmlhttpRequest({ method: 'GET', url: rawUrl, onload: function (rawRes) {
if (rawRes.status >= 200 && rawRes.status < 400 && rawRes.responseText && rawRes.responseText.length>10) {
switchTab('main'); addScriptTab(); const f = scriptTabs.find(t => t.id === activeScriptTab); f.name = name; f.content = rawRes.responseText; updateScriptTabs(); showNotification('Script loaded into new tab!');
} else {
showNotification('Failed to fetch raw script.', 'error');
}
}, onerror: function () { showNotification('Failed to fetch raw script.', 'error'); } });
},
onerror: function () { showNotification('Failed to fetch script page.', 'error'); }
});
});
return card;
}
// Helper: parse and extract scripts from a page
function parseScriptsFromPage(htmlText) {
const doc = new DOMParser().parseFromString(htmlText, 'text/html');
const anchors = Array.from(doc.querySelectorAll('a[href*="/scripts/"]'));
console.log('[TriX] Found', anchors.length, 'anchors with /scripts/ in href on this page');
const candidates = [];
for (const a of anchors) {
const href = a.getAttribute('href');
if (!href) continue;
const urlObj = new URL(href, 'https://greasyfork.org');
const path = urlObj.pathname;
const match = path.match(/\/en\/scripts\/(\d+)(?:-[^/]*)?(?:\/|$)/i);
if (!match) continue;
const scriptId = match[1];
if (globalSeen.has(scriptId)) continue;
globalSeen.add(scriptId);
let title = (a.textContent || '').trim();
if (!title || title.length < 2) {
const card = a.closest('article') || a.parentElement;
const tEl = card ? (card.querySelector('h3') || card.querySelector('h2') || card.querySelector('.script-title')) : null;
if (tEl && tEl.textContent) title = tEl.textContent.trim();
}
title = title || path.split('/').pop() || 'Untitled Script';
let description = '';
const cardEl = a.closest('article') || a.closest('.script') || a.closest('.search-result') || a.parentElement;
if (cardEl) {
const p = cardEl.querySelector('p');
if (p && p.textContent) description = p.textContent.trim();
else {
const desc = cardEl.querySelector('.description') || cardEl.querySelector('.script-description');
if (desc && desc.textContent) description = desc.textContent.trim();
}
}
candidates.push({ title, path, description, href: urlObj.toString() });
}
return candidates;
}
// Helper: render scripts for a page and update pagination buttons
function renderPageResults(pageNum, candidates) {
const contentArea = document.createElement('div');
contentArea.id = 'gf-results-content';
if (!candidates.length) {
contentArea.innerHTML = '
Analysis Tab: View game state without modifications. Safe for all servers.
`;
view.innerHTML = html;
document.getElementById('dev-state-btn')?.addEventListener('click', () => {
console.clear();
console.log('%c=== GAME STATE SNAPSHOT ===', 'color:#00ff00;font-weight:bold;font-size:14px');
if (window.l) console.log('Game State (window.l):', window.l);
if (window.a0) console.log('Current Player (window.a0):', window.a0);
if (window.ag) console.log('Territories (window.ag):', window.ag);
showNotification('Game state dumped to console', 'success');
});
document.getElementById('dev-players-btn')?.addEventListener('click', () => {
console.clear();
console.log('%c=== ALL PLAYERS ===', 'color:#00ff00;font-weight:bold;font-size:14px');
if (window.ag?.gS) {
for (const [pid, tiles] of Object.entries(window.ag.gS)) {
console.log(`Player ${pid}: ${tiles?.length || 0} tiles, ${window.ag.h2?.[pid] || 0} gold`);
}
}
showNotification('Player list dumped to console', 'success');
});
document.getElementById('dev-territories-btn')?.addEventListener('click', () => {
console.clear();
console.log('%c=== TERRITORY ANALYSIS ===', 'color:#00ff00;font-weight:bold;font-size:14px');
if (window.ag?.gS) {
const analysis = {};
for (const [pid, tiles] of Object.entries(window.ag.gS)) {
const territory = tiles?.length || 0;
const borders = window.ag.gg?.[pid]?.length || 0;
analysis[pid] = { territory, borders, efficiency: territory / (borders + 1) };
}
console.table(analysis);
}
showNotification('Territory analysis dumped to console', 'success');
});
document.getElementById('dev-debug-btn')?.addEventListener('click', () => {
console.clear();
console.log('%c=== SYSTEM DEBUG INFO ===', 'color:#00ff00;font-weight:bold;font-size:14px');
console.log('Game State Available:', !!window.l);
console.log('Player Available:', !!window.a0);
console.log('Territories Available:', !!window.ag);
console.log('Network IO Available:', !!window.b8);
console.log('Grid Available:', !!window.bS);
console.log('Tiles Available:', !!window.bO);
showNotification('Debug info dumped to console', 'success');
});
}
function renderDangerZoneTesting() {
const view = document.getElementById('dev-toolkit-view');
if (!view) return;
const html = `
āļø Testing Commands
ā ļø TEST MODE ONLY
These commands modify game state locally. Will NOT work on live servers due to server-side validation.
Tile ID:
Rectangle (X1, Y1, X2, Y2):
Gold Amount:
`;
view.innerHTML = html;
document.getElementById('dev-claim-btn')?.addEventListener('click', () => {
const tileId = parseInt(document.getElementById('dev-tile-id')?.value || 0);
if (window.bO?.fh && window.a0) {
window.bO.fh[tileId] = window.a0.id;
if (!window.ag.gS[window.a0.id]) window.ag.gS[window.a0.id] = [];
if (!window.ag.gS[window.a0.id].includes(tileId)) window.ag.gS[window.a0.id].push(tileId);
showNotification(`ā Test: Claimed tile ${tileId}`, 'success');
} else {
showNotification('ā Game objects not available', 'error');
}
});
document.getElementById('dev-claim-rect-btn')?.addEventListener('click', () => {
const x1 = parseInt(document.getElementById('dev-x1')?.value || 0);
const y1 = parseInt(document.getElementById('dev-y1')?.value || 0);
const x2 = parseInt(document.getElementById('dev-x2')?.value || 0);
const y2 = parseInt(document.getElementById('dev-y2')?.value || 0);
if (window.bO?.fh && window.a0 && window.bS) {
let count = 0;
for (let y = Math.min(y1, y2); y <= Math.max(y1, y2); y++) {
for (let x = Math.min(x1, x2); x <= Math.max(x1, x2); x++) {
const tileId = y * window.bS.fC + x;
window.bO.fh[tileId] = window.a0.id;
if (!window.ag.gS[window.a0.id]) window.ag.gS[window.a0.id] = [];
if (!window.ag.gS[window.a0.id].includes(tileId)) window.ag.gS[window.a0.id].push(tileId);
count++;
}
}
showNotification(`ā Test: Claimed ${count} tiles`, 'success');
} else {
showNotification('ā Game objects not available', 'error');
}
});
document.getElementById('dev-set-gold-btn')?.addEventListener('click', () => {
const amount = parseInt(document.getElementById('dev-gold-amount')?.value || 0);
if (window.ag?.h2 && window.a0) {
window.ag.h2[window.a0.id] = amount;
showNotification(`ā Test: Set gold to ${amount}`, 'success');
} else {
showNotification('ā Game objects not available', 'error');
}
});
document.getElementById('dev-add-gold-btn')?.addEventListener('click', () => {
const amount = parseInt(document.getElementById('dev-gold-amount')?.value || 0);
if (window.ag?.h2 && window.a0) {
window.ag.h2[window.a0.id] = (window.ag.h2[window.a0.id] || 0) + amount;
showNotification(`ā Test: Added ${amount} gold`, 'success');
} else {
showNotification('ā Game objects not available', 'error');
}
});
}
function renderDangerZoneCheats() {
const view = document.getElementById('dev-toolkit-view');
if (!view) return;
const html = `
š£ TriX Cheat Panel
šØ EXTREME CAUTION šØ
Cheats modify core game systems. WILL CAUSE PERMANENT BANS on live servers. Use ONLY on private/test servers with your own permission or explicit owner authorization.
Territory Claims
Single Tile:
Rectangle Area (X1,Y1,X2,Y2):
Economy
Gold Amount:
Advanced
Expansion Layers:
Target Player ID:
`;
view.innerHTML = html;
// Claim single tile
document.getElementById('cheat-claim-btn')?.addEventListener('click', () => {
const tileId = parseInt(document.getElementById('cheat-tile-id')?.value || 0);
if (window.bO?.fh && window.a0) {
window.bO.fh[tileId] = window.a0.id;
if (!window.ag.gS[window.a0.id]) window.ag.gS[window.a0.id] = [];
if (!window.ag.gS[window.a0.id].includes(tileId)) window.ag.gS[window.a0.id].push(tileId);
showNotification(`ā Claimed tile ${tileId}`, 'success');
} else showNotification('ā Game not ready', 'error');
});
// Claim rectangle
document.getElementById('cheat-claim-rect-btn')?.addEventListener('click', () => {
const x1 = parseInt(document.getElementById('cheat-x1')?.value || 0);
const y1 = parseInt(document.getElementById('cheat-y1')?.value || 0);
const x2 = parseInt(document.getElementById('cheat-x2')?.value || 0);
const y2 = parseInt(document.getElementById('cheat-y2')?.value || 0);
if (window.bO?.fh && window.a0 && window.bS) {
let count = 0;
for (let y = Math.min(y1, y2); y <= Math.max(y1, y2); y++) {
for (let x = Math.min(x1, x2); x <= Math.max(x1, x2); x++) {
const tileId = y * window.bS.fC + x;
window.bO.fh[tileId] = window.a0.id;
if (!window.ag.gS[window.a0.id]) window.ag.gS[window.a0.id] = [];
if (!window.ag.gS[window.a0.id].includes(tileId)) window.ag.gS[window.a0.id].push(tileId);
count++;
}
}
showNotification(`ā Claimed ${count} tiles`, 'success');
} else showNotification('ā Game not ready', 'error');
});
// Set gold
document.getElementById('cheat-set-gold-btn')?.addEventListener('click', () => {
const amount = parseInt(document.getElementById('cheat-gold-amt')?.value || 0);
if (window.ag?.h2 && window.a0) {
window.ag.h2[window.a0.id] = amount;
showNotification(`ā Gold set to ${amount}`, 'success');
} else showNotification('ā Game not ready', 'error');
});
// Add gold
document.getElementById('cheat-add-gold-btn')?.addEventListener('click', () => {
const amount = parseInt(document.getElementById('cheat-gold-amt')?.value || 0);
if (window.ag?.h2 && window.a0) {
window.ag.h2[window.a0.id] = (window.ag.h2[window.a0.id] || 0) + amount;
showNotification(`ā Added ${amount} gold`, 'success');
} else showNotification('ā Game not ready', 'error');
});
// Fast expand
document.getElementById('cheat-expand-btn')?.addEventListener('click', () => {
const layers = parseInt(document.getElementById('cheat-layers')?.value || 1);
if (window.a0 && window.ag && window.bS) {
let totalCount = 0;
const owned = window.ag.gS[window.a0.id] || [];
const width = window.bS.fC;
for (let layer = 0; layer < layers; layer++) {
const newTiles = new Set();
for (let tileId of owned) {
const x = tileId % width;
const y = Math.floor(tileId / width);
for (let dx = -1; dx <= 1; dx++) {
for (let dy = -1; dy <= 1; dy++) {
if (dx === 0 && dy === 0) continue;
const nx = x + dx, ny = y + dy;
if (nx >= 0 && nx < window.bS.fC && ny >= 0 && ny < window.bS.fD) {
const newTileId = ny * width + nx;
newTiles.add(newTileId);
}
}
}
}
for (let tileId of newTiles) {
window.bO.fh[tileId] = window.a0.id;
if (!window.ag.gS[window.a0.id]) window.ag.gS[window.a0.id] = [];
if (!window.ag.gS[window.a0.id].includes(tileId)) window.ag.gS[window.a0.id].push(tileId);
totalCount++;
}
}
showNotification(`ā Expanded by ${totalCount} tiles across ${layers} layers`, 'success');
} else showNotification('ā Game not ready', 'error');
});
// Eliminate player
document.getElementById('cheat-eliminate-btn')?.addEventListener('click', () => {
const playerId = parseInt(document.getElementById('cheat-player-id')?.value || 0);
if (window.ag && window.bO) {
const tiles = window.ag.gS[playerId] || [];
for (let tileId of tiles) {
window.bO.fh[tileId] = 0;
}
window.ag.gS[playerId] = [];
window.ag.gg[playerId] = [];
window.ag.h2[playerId] = 0;
showNotification(`ā Eliminated player ${playerId}`, 'success');
} else showNotification('ā Game not ready', 'error');
});
}
function handleDangerZoneTab() {
const content = document.getElementById('danger-zone-content');
const prompt = document.getElementById('danger-zone-auth-prompt');
const area = document.getElementById('danger-zone-content-area');
const authBtn = document.getElementById('danger-zone-auth-btn');
const pwdInput = document.getElementById('danger-zone-password');
const devTabs = document.querySelectorAll('[data-dev-tab]');
// Check if already authorized
if (dangerZoneAuthorized) {
if (prompt) prompt.style.display = 'none';
if (area) area.style.display = 'block';
renderDangerZoneCheats();
return;
}
// Set up authentication
if (authBtn) {
authBtn.addEventListener('click', () => {
const pwd = pwdInput?.value;
if (!pwd) {
showNotification('Please enter a password', 'error');
return;
}
if (authenticateDangerZone(pwd)) {
if (prompt) prompt.style.display = 'none';
if (area) area.style.display = 'block';
if (pwdInput) pwdInput.value = '';
showNotification('ā Authorization successful', 'success');
renderDangerZoneCheats();
} else {
showNotification('ā Invalid password', 'error');
if (pwdInput) pwdInput.value = '';
}
});
pwdInput?.addEventListener('keydown', (e) => {
if (e.key === 'Enter') authBtn.click();
});
}
// Tab switching within dev toolkit
devTabs?.forEach(tab => {
tab.addEventListener('click', () => {
devTabs.forEach(t => t.classList.remove('active'));
tab.classList.add('active');
const devTab = tab.getAttribute('data-dev-tab');
if (devTab === 'cheats') renderDangerZoneCheats();
else if (devTab === 'analyze') renderDangerZoneAnalysis();
else if (devTab === 'territories') renderDangerZoneAnalysis();
else if (devTab === 'network') renderDangerZoneAnalysis();
else if (devTab === 'diagnostics') renderDangerZoneDiagnostics();
});
});
}
function renderDangerZoneDiagnostics() {
const view = document.getElementById('dev-toolkit-view');
if (!view) return;
const html = `
š§ System Diagnostics
Game System Status
`;
view.innerHTML = html;
function updateDiagnostics() {
const systemsDiv = document.getElementById('diag-systems');
if (!systemsDiv) return;
const systems = {
'Game State (window.l)': !!window.l,
'Current Player (window.a0)': !!window.a0,
'Territories (window.ag)': !!window.ag,
'Network IO (window.b8)': !!window.b8,
'World Grid (window.bS)': !!window.bS,
'Tile System (window.bO)': !!window.bO,
'Rendering (window.bT)': !!window.bT,
'Config (window.at)': !!window.at,
};
let html = '';
for (const [system, ready] of Object.entries(systems)) {
const status = ready ? 'ā' : 'ā';
const color = ready ? '#00ff00' : '#ff0000';
html += `
${status} ${system}
`;
}
systemsDiv.innerHTML = html;
}
updateDiagnostics();
document.getElementById('diag-refresh-btn')?.addEventListener('click', updateDiagnostics);
document.getElementById('diag-console-btn')?.addEventListener('click', () => {
console.clear();
console.log('%c=== TriX DIAGNOSTICS EXPORT ===', 'color:#00aaff;font-weight:bold;font-size:14px');
console.log('Game State:', !!window.l);
console.log('Player:', !!window.a0);
console.log('Territories:', !!window.ag);
console.log('Network:', !!window.b8);
console.log('Grid:', !!window.bS);
console.log('Tiles:', !!window.bO);
showNotification('Diagnostics exported to console', 'success');
});
}
function init() {
createExecutorPanel();
attachEventListeners();
// Wire Sign-In button
const signinBtn = document.getElementById('trix-signin-btn');
if (signinBtn) {
signinBtn.addEventListener('click', showSignInModal);
}
// Wire Settings button
const settingsBtn = document.getElementById('trix-account-settings-btn');
if (settingsBtn) {
settingsBtn.addEventListener('click', showAccountModal);
}
// Auto-login from persistent session if valid
const sessionStr = GM_getValue('trix_user_session');
if (sessionStr) {
try {
const session = JSON.parse(sessionStr);
if (session && session.expiry && session.expiry > Date.now() && session.user) {
// Session is still valid, auto-login
const savedProfilePic = localStorage.getItem('trix_profile_pic');
currentUser = session.user;
if (savedProfilePic) {
currentUser.profilePic = savedProfilePic;
}
updateUserProfile();
}
} catch (err) {
// Invalid session data, ignore
}
}
document.onkeydown=e=>{if(e.ctrlKey&&e.shiftKey&&e.key.toUpperCase()==="E"){e.preventDefault();const p=document.querySelector('.trix-executor');if(!p){showLoadingScreen(init)}else if(isMinimized)restorePanel();else minimizePanel()}};
logPacketCallback=(ws,type,data)=>{const c=monitoredConnections.get(ws);if(c){c.log.push({type,data});if(c.log.length>200)c.log.shift();if(currentTab==='network'&&activeNetworkTab==='logger'&&!isLoggerSuspended)renderPacketLog()}};
onConnectionStateChange=()=>{if(currentTab==='network'&&activeNetworkTab==='logger')renderPacketLog()};
updateConnectionStatus=(status,title)=>{const e=document.getElementById('trix-conn-status');if(e){e.className=status;e.title=title}};
// Request throttling to prevent 503 errors
let lastPingTime=0,consecutiveErrors=0,pingInterval=15000;
updatePingDisplay=async()=>{
const e=document.getElementById('trix-ping-display');
if(!e||!isMinimized===false)return;
const now=Date.now();
if(now-lastPingTime=lastFrameTime+1000){if(fpsDisplay)fpsDisplay.textContent=`FPS: ${frameCount}`;lastFrameTime=now;frameCount=0}requestAnimationFrame(updateFPS)}
requestAnimationFrame(updateFPS);
// Request deduplication & caching
let lastUpdateCheckTime=0,updateCheckInterval=3600000,cachedVersion=null;
(async()=>{
const now=Date.now();
if(now-lastUpdateCheckTime{try{const latest=JSON.parse(res.responseText).version;cachedVersion=latest;if(CURRENT_VERSION!==latest){if(!shouldShowUpdateReminder)showUpdateModal();else isUpdateAvailable=true;}else{GM_setValue("showUpdateReminder",false);shouldShowUpdateReminder=false}}catch(e){console.error("Failed to check for updates.")}},onerror:()=>{console.warn("Update check failed - may be rate limited")}});
})();
// Check if changelog should be shown for this version
setTimeout(() => {
if (CURRENT_VERSION !== LAST_SHOWN_VERSION && CHANGELOG[CURRENT_VERSION]) {
showChangelogModal(CURRENT_VERSION);
}
}, 1000);
loadSavedScripts();
updateScriptTabs();
document.querySelector('.trix-executor').classList.add('ready');
showNotification("TriX Executor loaded! Press Ctrl+Shift+E to toggle.");
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", () => showLoadingScreen(init));
} else {
showLoadingScreen(init);
}
})();